aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm/mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/mm/mem.c')
-rw-r--r--arch/powerpc/mm/mem.c71
1 files changed, 64 insertions, 7 deletions
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 2c8e90f5789e..8ebaac75c940 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -128,7 +128,8 @@ int arch_add_memory(int nid, u64 start, u64 size)
128 return -EINVAL; 128 return -EINVAL;
129 129
130 /* this should work for most non-highmem platforms */ 130 /* this should work for most non-highmem platforms */
131 zone = pgdata->node_zones; 131 zone = pgdata->node_zones +
132 zone_for_memory(nid, start, size, 0);
132 133
133 return __add_pages(nid, zone, start_pfn, nr_pages); 134 return __add_pages(nid, zone, start_pfn, nr_pages);
134} 135}
@@ -259,6 +260,60 @@ static int __init mark_nonram_nosave(void)
259 } 260 }
260 return 0; 261 return 0;
261} 262}
263#else /* CONFIG_NEED_MULTIPLE_NODES */
264static int __init mark_nonram_nosave(void)
265{
266 return 0;
267}
268#endif
269
270static bool zone_limits_final;
271
272static unsigned long max_zone_pfns[MAX_NR_ZONES] = {
273 [0 ... MAX_NR_ZONES - 1] = ~0UL
274};
275
276/*
277 * Restrict the specified zone and all more restrictive zones
278 * to be below the specified pfn. May not be called after
279 * paging_init().
280 */
281void __init limit_zone_pfn(enum zone_type zone, unsigned long pfn_limit)
282{
283 int i;
284
285 if (WARN_ON(zone_limits_final))
286 return;
287
288 for (i = zone; i >= 0; i--) {
289 if (max_zone_pfns[i] > pfn_limit)
290 max_zone_pfns[i] = pfn_limit;
291 }
292}
293
294/*
295 * Find the least restrictive zone that is entirely below the
296 * specified pfn limit. Returns < 0 if no suitable zone is found.
297 *
298 * pfn_limit must be u64 because it can exceed 32 bits even on 32-bit
299 * systems -- the DMA limit can be higher than any possible real pfn.
300 */
301int dma_pfn_limit_to_zone(u64 pfn_limit)
302{
303 enum zone_type top_zone = ZONE_NORMAL;
304 int i;
305
306#ifdef CONFIG_HIGHMEM
307 top_zone = ZONE_HIGHMEM;
308#endif
309
310 for (i = top_zone; i >= 0; i--) {
311 if (max_zone_pfns[i] <= pfn_limit)
312 return i;
313 }
314
315 return -EPERM;
316}
262 317
263/* 318/*
264 * paging_init() sets up the page tables - in fact we've already done this. 319 * paging_init() sets up the page tables - in fact we've already done this.
@@ -267,7 +322,7 @@ void __init paging_init(void)
267{ 322{
268 unsigned long long total_ram = memblock_phys_mem_size(); 323 unsigned long long total_ram = memblock_phys_mem_size();
269 phys_addr_t top_of_ram = memblock_end_of_DRAM(); 324 phys_addr_t top_of_ram = memblock_end_of_DRAM();
270 unsigned long max_zone_pfns[MAX_NR_ZONES]; 325 enum zone_type top_zone;
271 326
272#ifdef CONFIG_PPC32 327#ifdef CONFIG_PPC32
273 unsigned long v = __fix_to_virt(__end_of_fixed_addresses - 1); 328 unsigned long v = __fix_to_virt(__end_of_fixed_addresses - 1);
@@ -289,18 +344,20 @@ void __init paging_init(void)
289 (unsigned long long)top_of_ram, total_ram); 344 (unsigned long long)top_of_ram, total_ram);
290 printk(KERN_DEBUG "Memory hole size: %ldMB\n", 345 printk(KERN_DEBUG "Memory hole size: %ldMB\n",
291 (long int)((top_of_ram - total_ram) >> 20)); 346 (long int)((top_of_ram - total_ram) >> 20));
292 memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); 347
293#ifdef CONFIG_HIGHMEM 348#ifdef CONFIG_HIGHMEM
294 max_zone_pfns[ZONE_DMA] = lowmem_end_addr >> PAGE_SHIFT; 349 top_zone = ZONE_HIGHMEM;
295 max_zone_pfns[ZONE_HIGHMEM] = top_of_ram >> PAGE_SHIFT; 350 limit_zone_pfn(ZONE_NORMAL, lowmem_end_addr >> PAGE_SHIFT);
296#else 351#else
297 max_zone_pfns[ZONE_DMA] = top_of_ram >> PAGE_SHIFT; 352 top_zone = ZONE_NORMAL;
298#endif 353#endif
354
355 limit_zone_pfn(top_zone, top_of_ram >> PAGE_SHIFT);
356 zone_limits_final = true;
299 free_area_init_nodes(max_zone_pfns); 357 free_area_init_nodes(max_zone_pfns);
300 358
301 mark_nonram_nosave(); 359 mark_nonram_nosave();
302} 360}
303#endif /* ! CONFIG_NEED_MULTIPLE_NODES */
304 361
305static void __init register_page_bootmem_info(void) 362static void __init register_page_bootmem_info(void)
306{ 363{