|
@@ -79,12 +79,14 @@ enum {
|
|
|
* @base: base address
|
|
|
* @size: size in bytes
|
|
|
* @offset: difference between base and rm.size
|
|
|
+ * @destroy: flag if region should be destroyed upon shutdown
|
|
|
*/
|
|
|
|
|
|
struct mem_region {
|
|
|
u64 base;
|
|
|
u64 size;
|
|
|
unsigned long offset;
|
|
|
+ int destroy;
|
|
|
};
|
|
|
|
|
|
/**
|
|
@@ -262,6 +264,7 @@ static int ps3_mm_region_create(struct mem_region *r, unsigned long size)
|
|
|
goto zero_region;
|
|
|
}
|
|
|
|
|
|
+ r->destroy = 1;
|
|
|
r->offset = r->base - map.rm.size;
|
|
|
return result;
|
|
|
|
|
@@ -279,7 +282,14 @@ static void ps3_mm_region_destroy(struct mem_region *r)
|
|
|
{
|
|
|
int result;
|
|
|
|
|
|
+ if (!r->destroy) {
|
|
|
+ pr_info("%s:%d: Not destroying high region: %llxh %llxh\n",
|
|
|
+ __func__, __LINE__, r->base, r->size);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
DBG("%s:%d: r->base = %llxh\n", __func__, __LINE__, r->base);
|
|
|
+
|
|
|
if (r->base) {
|
|
|
result = lv1_release_memory(r->base);
|
|
|
BUG_ON(result);
|
|
@@ -288,6 +298,36 @@ static void ps3_mm_region_destroy(struct mem_region *r)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static int ps3_mm_get_repository_highmem(struct mem_region *r)
|
|
|
+{
|
|
|
+ int result;
|
|
|
+
|
|
|
+ /* Assume a single highmem region. */
|
|
|
+
|
|
|
+ result = ps3_repository_read_highmem_info(0, &r->base, &r->size);
|
|
|
+
|
|
|
+ if (result)
|
|
|
+ goto zero_region;
|
|
|
+
|
|
|
+ if (!r->base || !r->size) {
|
|
|
+ result = -1;
|
|
|
+ goto zero_region;
|
|
|
+ }
|
|
|
+
|
|
|
+ r->offset = r->base - map.rm.size;
|
|
|
+
|
|
|
+ DBG("%s:%d: Found high region in repository: %llxh %llxh\n",
|
|
|
+ __func__, __LINE__, r->base, r->size);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+zero_region:
|
|
|
+ DBG("%s:%d: No high region in repository.\n", __func__, __LINE__);
|
|
|
+
|
|
|
+ r->size = r->base = r->offset = 0;
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* ps3_mm_add_memory - hot add memory
|
|
|
*/
|
|
@@ -304,6 +344,12 @@ static int __init ps3_mm_add_memory(void)
|
|
|
|
|
|
BUG_ON(!mem_init_done);
|
|
|
|
|
|
+ if (!map.r1.size) {
|
|
|
+ DBG("%s:%d: No region 1, not adding memory\n",
|
|
|
+ __func__, __LINE__);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
start_addr = map.rm.size;
|
|
|
start_pfn = start_addr >> PAGE_SHIFT;
|
|
|
nr_pages = (map.r1.size + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
|
@@ -1217,9 +1263,10 @@ void __init ps3_mm_init(void)
|
|
|
BUG_ON(map.rm.base);
|
|
|
BUG_ON(!map.rm.size);
|
|
|
|
|
|
+ /* Check if we got the highmem region from an earlier boot step */
|
|
|
|
|
|
- /* arrange to do this in ps3_mm_add_memory */
|
|
|
- ps3_mm_region_create(&map.r1, map.total - map.rm.size);
|
|
|
+ if (ps3_mm_get_repository_highmem(&map.r1))
|
|
|
+ ps3_mm_region_create(&map.r1, map.total - map.rm.size);
|
|
|
|
|
|
/* correct map.total for the real total amount of memory we use */
|
|
|
map.total = map.rm.size + map.r1.size;
|