Skip to content

Commit

Permalink
powerpc/ps3: Use highmem region from repository
Browse files Browse the repository at this point in the history
Use any preallocated highmem region setup by the bootloader.
This implementation only checks for the existance of a single
region at region_index=0.

This feature allows the bootloader to preallocate highmem
regions and pass the region locations to the kernel through
the repository.  Preallocated regions can be used to hold the
initrd or other large data.  If no region info exists, the
kernel retains the old behavior and attempts to allocate the
highmem region itself.

Based on Hector Martin's patch "Get lv1 high memory region from
devtree".

CC: Hector Martin <hector@marcansoft.com>
Signed-off-by: Andre Heider <a.heider@gmail.com>
CC: Nathan Whitehorn <nwhitehorn@freebsd.org>
Signed-off-by: Geoff Levand <geoff@infradead.org>
  • Loading branch information
Andre Heider authored and Geoff Levand committed Apr 24, 2012
1 parent 6750edb commit 1e755c0
Showing 1 changed file with 49 additions and 2 deletions.
51 changes: 49 additions & 2 deletions arch/powerpc/platforms/ps3/mm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

/**
Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand All @@ -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
*/
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 1e755c0

Please sign in to comment.