|
@@ -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)
|