diff options
Diffstat (limited to 'arch/powerpc/platforms/ps3/mm.c')
| -rw-r--r-- | arch/powerpc/platforms/ps3/mm.c | 81 | 
1 files changed, 41 insertions, 40 deletions
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c index c2045880e67..0c9f643d9e2 100644 --- a/arch/powerpc/platforms/ps3/mm.c +++ b/arch/powerpc/platforms/ps3/mm.c @@ -19,8 +19,7 @@   */  #include <linux/kernel.h> -#include <linux/module.h> -#include <linux/memory_hotplug.h> +#include <linux/export.h>  #include <linux/memblock.h>  #include <linux/slab.h> @@ -29,6 +28,7 @@  #include <asm/prom.h>  #include <asm/udbg.h>  #include <asm/lv1call.h> +#include <asm/setup.h>  #include "platform.h" @@ -78,12 +78,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;  };  /** @@ -95,7 +97,7 @@ struct mem_region {   * The HV virtual address space (vas) allows for hotplug memory regions.   * Memory regions can be created and destroyed in the vas at runtime.   * @rm: real mode (bootmem) region - * @r1: hotplug memory region(s) + * @r1: highmem region(s)   *   * ps3 addresses   * virt_addr: a cpu 'translated' effective address @@ -221,10 +223,6 @@ void ps3_mm_vas_destroy(void)  	}  } -/*============================================================================*/ -/* memory hotplug routines                                                    */ -/*============================================================================*/ -  /**   * ps3_mm_region_create - create a memory region in the vas   * @r: pointer to a struct mem_region to accept initialized values @@ -261,6 +259,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; @@ -278,7 +277,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); @@ -287,51 +293,36 @@ static void ps3_mm_region_destroy(struct mem_region *r)  	}  } -/** - * ps3_mm_add_memory - hot add memory - */ - -static int __init ps3_mm_add_memory(void) +static int ps3_mm_get_repository_highmem(struct mem_region *r)  {  	int result; -	unsigned long start_addr; -	unsigned long start_pfn; -	unsigned long nr_pages; - -	if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) -		return -ENODEV; -	BUG_ON(!mem_init_done); +	/* Assume a single highmem region. */ -	start_addr = map.rm.size; -	start_pfn = start_addr >> PAGE_SHIFT; -	nr_pages = (map.r1.size + PAGE_SIZE - 1) >> PAGE_SHIFT; +	result = ps3_repository_read_highmem_info(0, &r->base, &r->size); -	DBG("%s:%d: start_addr %lxh, start_pfn %lxh, nr_pages %lxh\n", -		__func__, __LINE__, start_addr, start_pfn, nr_pages); - -	result = add_memory(0, start_addr, map.r1.size); +	if (result) +		goto zero_region; -	if (result) { -		pr_err("%s:%d: add_memory failed: (%d)\n", -			__func__, __LINE__, result); -		return result; +	if (!r->base || !r->size) { +		result = -1; +		goto zero_region;  	} -	memblock_add(start_addr, map.r1.size); -	memblock_analyze(); +	r->offset = r->base - map.rm.size; -	result = online_pages(start_pfn, nr_pages); +	DBG("%s:%d: Found high region in repository: %llxh %llxh\n", +	    __func__, __LINE__, r->base, r->size); -	if (result) -		pr_err("%s:%d: online_pages failed: (%d)\n", -			__func__, __LINE__, result); +	return 0; +zero_region: +	DBG("%s:%d: No high region in repository.\n", __func__, __LINE__); + +	r->size = r->base = r->offset = 0;  	return result;  } -device_initcall(ps3_mm_add_memory); -  /*============================================================================*/  /* dma routines                                                               */  /*============================================================================*/ @@ -1217,13 +1208,23 @@ 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; +	if (!map.r1.size) { +		DBG("%s:%d: No highmem region found\n", __func__, __LINE__); +	} else { +		DBG("%s:%d: Adding highmem region: %llxh %llxh\n", +			__func__, __LINE__, map.rm.size, +			map.total - map.rm.size); +		memblock_add(map.rm.size, map.total - map.rm.size); +	} +  	DBG(" <- %s:%d\n", __func__, __LINE__);  }  | 
