summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/phyp_dump.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/pseries/phyp_dump.c')
-rw-r--r--arch/powerpc/platforms/pseries/phyp_dump.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/pseries/phyp_dump.c b/arch/powerpc/platforms/pseries/phyp_dump.c
index df4870ec90d..034fe1b54dd 100644
--- a/arch/powerpc/platforms/pseries/phyp_dump.c
+++ b/arch/powerpc/platforms/pseries/phyp_dump.c
@@ -261,6 +261,39 @@ static void release_memory_range(unsigned long start_pfn,
}
}
+/**
+ * track_freed_range -- Counts the range being freed.
+ * Once the counter goes to zero, it re-registers dump for
+ * future use.
+ */
+static void
+track_freed_range(unsigned long addr, unsigned long length)
+{
+ static unsigned long scratch_area_size, reserved_area_size;
+
+ if (addr < phyp_dump_info->init_reserve_start)
+ return;
+
+ if ((addr >= phyp_dump_info->init_reserve_start) &&
+ (addr <= phyp_dump_info->init_reserve_start +
+ phyp_dump_info->init_reserve_size))
+ reserved_area_size += length;
+
+ if ((addr >= phyp_dump_info->reserved_scratch_addr) &&
+ (addr <= phyp_dump_info->reserved_scratch_addr +
+ phyp_dump_info->reserved_scratch_size))
+ scratch_area_size += length;
+
+ if ((reserved_area_size == phyp_dump_info->init_reserve_size) &&
+ (scratch_area_size == phyp_dump_info->reserved_scratch_size)) {
+
+ invalidate_last_dump(&phdr,
+ phyp_dump_info->reserved_scratch_addr);
+ register_dump_area(&phdr,
+ phyp_dump_info->reserved_scratch_addr);
+ }
+}
+
/* ------------------------------------------------- */
/**
* sysfs_release_region -- sysfs interface to release memory range.
@@ -285,6 +318,8 @@ static ssize_t store_release_region(struct kobject *kobj,
if (ret != 2)
return -EINVAL;
+ track_freed_range(start_addr, length);
+
/* Range-check - don't free any reserved memory that
* wasn't reserved for phyp-dump */
if (start_addr < phyp_dump_info->init_reserve_start)