diff options
Diffstat (limited to 'arch/powerpc/mm/numa.c')
| -rw-r--r-- | arch/powerpc/mm/numa.c | 159 |
1 files changed, 16 insertions, 143 deletions
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 6c0f1c7d83e5..43c272075e1a 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
| @@ -39,96 +39,6 @@ static bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES]; | |||
| 39 | static int min_common_depth; | 39 | static int min_common_depth; |
| 40 | static int n_mem_addr_cells, n_mem_size_cells; | 40 | static int n_mem_addr_cells, n_mem_size_cells; |
| 41 | 41 | ||
| 42 | /* | ||
| 43 | * We need somewhere to store start/end/node for each region until we have | ||
| 44 | * allocated the real node_data structures. | ||
| 45 | */ | ||
| 46 | #define MAX_REGIONS (MAX_LMB_REGIONS*2) | ||
| 47 | static struct { | ||
| 48 | unsigned long start_pfn; | ||
| 49 | unsigned long end_pfn; | ||
| 50 | int nid; | ||
| 51 | } init_node_data[MAX_REGIONS] __initdata; | ||
| 52 | |||
| 53 | int __init early_pfn_to_nid(unsigned long pfn) | ||
| 54 | { | ||
| 55 | unsigned int i; | ||
| 56 | |||
| 57 | for (i = 0; init_node_data[i].end_pfn; i++) { | ||
| 58 | unsigned long start_pfn = init_node_data[i].start_pfn; | ||
| 59 | unsigned long end_pfn = init_node_data[i].end_pfn; | ||
| 60 | |||
| 61 | if ((start_pfn <= pfn) && (pfn < end_pfn)) | ||
| 62 | return init_node_data[i].nid; | ||
| 63 | } | ||
| 64 | |||
| 65 | return -1; | ||
| 66 | } | ||
| 67 | |||
| 68 | void __init add_region(unsigned int nid, unsigned long start_pfn, | ||
| 69 | unsigned long pages) | ||
| 70 | { | ||
| 71 | unsigned int i; | ||
| 72 | |||
| 73 | dbg("add_region nid %d start_pfn 0x%lx pages 0x%lx\n", | ||
| 74 | nid, start_pfn, pages); | ||
| 75 | |||
| 76 | for (i = 0; init_node_data[i].end_pfn; i++) { | ||
| 77 | if (init_node_data[i].nid != nid) | ||
| 78 | continue; | ||
| 79 | if (init_node_data[i].end_pfn == start_pfn) { | ||
| 80 | init_node_data[i].end_pfn += pages; | ||
| 81 | return; | ||
| 82 | } | ||
| 83 | if (init_node_data[i].start_pfn == (start_pfn + pages)) { | ||
| 84 | init_node_data[i].start_pfn -= pages; | ||
| 85 | return; | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | /* | ||
| 90 | * Leave last entry NULL so we dont iterate off the end (we use | ||
| 91 | * entry.end_pfn to terminate the walk). | ||
| 92 | */ | ||
| 93 | if (i >= (MAX_REGIONS - 1)) { | ||
| 94 | printk(KERN_ERR "WARNING: too many memory regions in " | ||
| 95 | "numa code, truncating\n"); | ||
| 96 | return; | ||
| 97 | } | ||
| 98 | |||
| 99 | init_node_data[i].start_pfn = start_pfn; | ||
| 100 | init_node_data[i].end_pfn = start_pfn + pages; | ||
| 101 | init_node_data[i].nid = nid; | ||
| 102 | } | ||
| 103 | |||
| 104 | /* We assume init_node_data has no overlapping regions */ | ||
| 105 | void __init get_region(unsigned int nid, unsigned long *start_pfn, | ||
| 106 | unsigned long *end_pfn, unsigned long *pages_present) | ||
| 107 | { | ||
| 108 | unsigned int i; | ||
| 109 | |||
| 110 | *start_pfn = -1UL; | ||
| 111 | *end_pfn = *pages_present = 0; | ||
| 112 | |||
| 113 | for (i = 0; init_node_data[i].end_pfn; i++) { | ||
| 114 | if (init_node_data[i].nid != nid) | ||
| 115 | continue; | ||
| 116 | |||
| 117 | *pages_present += init_node_data[i].end_pfn - | ||
| 118 | init_node_data[i].start_pfn; | ||
| 119 | |||
| 120 | if (init_node_data[i].start_pfn < *start_pfn) | ||
| 121 | *start_pfn = init_node_data[i].start_pfn; | ||
| 122 | |||
| 123 | if (init_node_data[i].end_pfn > *end_pfn) | ||
| 124 | *end_pfn = init_node_data[i].end_pfn; | ||
| 125 | } | ||
| 126 | |||
| 127 | /* We didnt find a matching region, return start/end as 0 */ | ||
| 128 | if (*start_pfn == -1UL) | ||
| 129 | *start_pfn = 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | static void __cpuinit map_cpu_to_node(int cpu, int node) | 42 | static void __cpuinit map_cpu_to_node(int cpu, int node) |
| 133 | { | 43 | { |
| 134 | numa_cpu_lookup_table[cpu] = node; | 44 | numa_cpu_lookup_table[cpu] = node; |
| @@ -468,8 +378,8 @@ new_range: | |||
| 468 | continue; | 378 | continue; |
| 469 | } | 379 | } |
| 470 | 380 | ||
| 471 | add_region(nid, start >> PAGE_SHIFT, | 381 | add_active_range(nid, start >> PAGE_SHIFT, |
| 472 | size >> PAGE_SHIFT); | 382 | (start >> PAGE_SHIFT) + (size >> PAGE_SHIFT)); |
| 473 | 383 | ||
| 474 | if (--ranges) | 384 | if (--ranges) |
| 475 | goto new_range; | 385 | goto new_range; |
| @@ -482,6 +392,7 @@ static void __init setup_nonnuma(void) | |||
| 482 | { | 392 | { |
| 483 | unsigned long top_of_ram = lmb_end_of_DRAM(); | 393 | unsigned long top_of_ram = lmb_end_of_DRAM(); |
| 484 | unsigned long total_ram = lmb_phys_mem_size(); | 394 | unsigned long total_ram = lmb_phys_mem_size(); |
| 395 | unsigned long start_pfn, end_pfn; | ||
| 485 | unsigned int i; | 396 | unsigned int i; |
| 486 | 397 | ||
| 487 | printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", | 398 | printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", |
| @@ -489,9 +400,11 @@ static void __init setup_nonnuma(void) | |||
| 489 | printk(KERN_DEBUG "Memory hole size: %ldMB\n", | 400 | printk(KERN_DEBUG "Memory hole size: %ldMB\n", |
| 490 | (top_of_ram - total_ram) >> 20); | 401 | (top_of_ram - total_ram) >> 20); |
| 491 | 402 | ||
| 492 | for (i = 0; i < lmb.memory.cnt; ++i) | 403 | for (i = 0; i < lmb.memory.cnt; ++i) { |
| 493 | add_region(0, lmb.memory.region[i].base >> PAGE_SHIFT, | 404 | start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT; |
| 494 | lmb_size_pages(&lmb.memory, i)); | 405 | end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i); |
| 406 | add_active_range(0, start_pfn, end_pfn); | ||
| 407 | } | ||
| 495 | node_set_online(0); | 408 | node_set_online(0); |
| 496 | } | 409 | } |
| 497 | 410 | ||
| @@ -630,11 +543,11 @@ void __init do_init_bootmem(void) | |||
| 630 | (void *)(unsigned long)boot_cpuid); | 543 | (void *)(unsigned long)boot_cpuid); |
| 631 | 544 | ||
| 632 | for_each_online_node(nid) { | 545 | for_each_online_node(nid) { |
| 633 | unsigned long start_pfn, end_pfn, pages_present; | 546 | unsigned long start_pfn, end_pfn; |
| 634 | unsigned long bootmem_paddr; | 547 | unsigned long bootmem_paddr; |
| 635 | unsigned long bootmap_pages; | 548 | unsigned long bootmap_pages; |
| 636 | 549 | ||
| 637 | get_region(nid, &start_pfn, &end_pfn, &pages_present); | 550 | get_pfn_range_for_nid(nid, &start_pfn, &end_pfn); |
| 638 | 551 | ||
| 639 | /* Allocate the node structure node local if possible */ | 552 | /* Allocate the node structure node local if possible */ |
| 640 | NODE_DATA(nid) = careful_allocation(nid, | 553 | NODE_DATA(nid) = careful_allocation(nid, |
| @@ -667,19 +580,7 @@ void __init do_init_bootmem(void) | |||
| 667 | init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT, | 580 | init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT, |
| 668 | start_pfn, end_pfn); | 581 | start_pfn, end_pfn); |
| 669 | 582 | ||
| 670 | /* Add free regions on this node */ | 583 | free_bootmem_with_active_regions(nid, end_pfn); |
| 671 | for (i = 0; init_node_data[i].end_pfn; i++) { | ||
| 672 | unsigned long start, end; | ||
| 673 | |||
| 674 | if (init_node_data[i].nid != nid) | ||
| 675 | continue; | ||
| 676 | |||
| 677 | start = init_node_data[i].start_pfn << PAGE_SHIFT; | ||
| 678 | end = init_node_data[i].end_pfn << PAGE_SHIFT; | ||
| 679 | |||
| 680 | dbg("free_bootmem %lx %lx\n", start, end - start); | ||
| 681 | free_bootmem_node(NODE_DATA(nid), start, end - start); | ||
| 682 | } | ||
| 683 | 584 | ||
| 684 | /* Mark reserved regions on this node */ | 585 | /* Mark reserved regions on this node */ |
| 685 | for (i = 0; i < lmb.reserved.cnt; i++) { | 586 | for (i = 0; i < lmb.reserved.cnt; i++) { |
| @@ -710,44 +611,16 @@ void __init do_init_bootmem(void) | |||
| 710 | } | 611 | } |
| 711 | } | 612 | } |
| 712 | 613 | ||
| 713 | /* Add regions into sparsemem */ | 614 | sparse_memory_present_with_active_regions(nid); |
| 714 | for (i = 0; init_node_data[i].end_pfn; i++) { | ||
| 715 | unsigned long start, end; | ||
| 716 | |||
| 717 | if (init_node_data[i].nid != nid) | ||
| 718 | continue; | ||
| 719 | |||
| 720 | start = init_node_data[i].start_pfn; | ||
| 721 | end = init_node_data[i].end_pfn; | ||
| 722 | |||
| 723 | memory_present(nid, start, end); | ||
| 724 | } | ||
| 725 | } | 615 | } |
| 726 | } | 616 | } |
| 727 | 617 | ||
| 728 | void __init paging_init(void) | 618 | void __init paging_init(void) |
| 729 | { | 619 | { |
| 730 | unsigned long zones_size[MAX_NR_ZONES]; | 620 | unsigned long max_zone_pfns[MAX_NR_ZONES] = { |
| 731 | unsigned long zholes_size[MAX_NR_ZONES]; | 621 | lmb_end_of_DRAM() >> PAGE_SHIFT |
| 732 | int nid; | 622 | }; |
| 733 | 623 | free_area_init_nodes(max_zone_pfns); | |
| 734 | memset(zones_size, 0, sizeof(zones_size)); | ||
| 735 | memset(zholes_size, 0, sizeof(zholes_size)); | ||
| 736 | |||
| 737 | for_each_online_node(nid) { | ||
| 738 | unsigned long start_pfn, end_pfn, pages_present; | ||
| 739 | |||
| 740 | get_region(nid, &start_pfn, &end_pfn, &pages_present); | ||
| 741 | |||
| 742 | zones_size[ZONE_DMA] = end_pfn - start_pfn; | ||
| 743 | zholes_size[ZONE_DMA] = zones_size[ZONE_DMA] - pages_present; | ||
| 744 | |||
| 745 | dbg("free_area_init node %d %lx %lx (hole: %lx)\n", nid, | ||
| 746 | zones_size[ZONE_DMA], start_pfn, zholes_size[ZONE_DMA]); | ||
| 747 | |||
| 748 | free_area_init_node(nid, NODE_DATA(nid), zones_size, start_pfn, | ||
| 749 | zholes_size); | ||
| 750 | } | ||
| 751 | } | 624 | } |
| 752 | 625 | ||
| 753 | static int __init early_numa(char *p) | 626 | static int __init early_numa(char *p) |
