diff options
Diffstat (limited to 'arch/powerpc/mm/numa.c')
-rw-r--r-- | arch/powerpc/mm/numa.c | 122 |
1 files changed, 75 insertions, 47 deletions
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index eb505ad34a85..a8397bbad3d4 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
@@ -865,6 +865,67 @@ static struct notifier_block __cpuinitdata ppc64_numa_nb = { | |||
865 | .priority = 1 /* Must run before sched domains notifier. */ | 865 | .priority = 1 /* Must run before sched domains notifier. */ |
866 | }; | 866 | }; |
867 | 867 | ||
868 | static void mark_reserved_regions_for_nid(int nid) | ||
869 | { | ||
870 | struct pglist_data *node = NODE_DATA(nid); | ||
871 | int i; | ||
872 | |||
873 | for (i = 0; i < lmb.reserved.cnt; i++) { | ||
874 | unsigned long physbase = lmb.reserved.region[i].base; | ||
875 | unsigned long size = lmb.reserved.region[i].size; | ||
876 | unsigned long start_pfn = physbase >> PAGE_SHIFT; | ||
877 | unsigned long end_pfn = ((physbase + size) >> PAGE_SHIFT); | ||
878 | struct node_active_region node_ar; | ||
879 | unsigned long node_end_pfn = node->node_start_pfn + | ||
880 | node->node_spanned_pages; | ||
881 | |||
882 | /* | ||
883 | * Check to make sure that this lmb.reserved area is | ||
884 | * within the bounds of the node that we care about. | ||
885 | * Checking the nid of the start and end points is not | ||
886 | * sufficient because the reserved area could span the | ||
887 | * entire node. | ||
888 | */ | ||
889 | if (end_pfn <= node->node_start_pfn || | ||
890 | start_pfn >= node_end_pfn) | ||
891 | continue; | ||
892 | |||
893 | get_node_active_region(start_pfn, &node_ar); | ||
894 | while (start_pfn < end_pfn && | ||
895 | node_ar.start_pfn < node_ar.end_pfn) { | ||
896 | unsigned long reserve_size = size; | ||
897 | /* | ||
898 | * if reserved region extends past active region | ||
899 | * then trim size to active region | ||
900 | */ | ||
901 | if (end_pfn > node_ar.end_pfn) | ||
902 | reserve_size = (node_ar.end_pfn << PAGE_SHIFT) | ||
903 | - (start_pfn << PAGE_SHIFT); | ||
904 | dbg("reserve_bootmem %lx %lx nid=%d\n", physbase, | ||
905 | reserve_size, node_ar.nid); | ||
906 | reserve_bootmem_node(NODE_DATA(node_ar.nid), physbase, | ||
907 | reserve_size, BOOTMEM_DEFAULT); | ||
908 | /* | ||
909 | * if reserved region is contained in the active region | ||
910 | * then done. | ||
911 | */ | ||
912 | if (end_pfn <= node_ar.end_pfn) | ||
913 | break; | ||
914 | |||
915 | /* | ||
916 | * reserved region extends past the active region | ||
917 | * get next active region that contains this | ||
918 | * reserved region | ||
919 | */ | ||
920 | start_pfn = node_ar.end_pfn; | ||
921 | physbase = start_pfn << PAGE_SHIFT; | ||
922 | size = size - reserve_size; | ||
923 | get_node_active_region(start_pfn, &node_ar); | ||
924 | } | ||
925 | } | ||
926 | } | ||
927 | |||
928 | |||
868 | void __init do_init_bootmem(void) | 929 | void __init do_init_bootmem(void) |
869 | { | 930 | { |
870 | int nid; | 931 | int nid; |
@@ -890,7 +951,13 @@ void __init do_init_bootmem(void) | |||
890 | 951 | ||
891 | get_pfn_range_for_nid(nid, &start_pfn, &end_pfn); | 952 | get_pfn_range_for_nid(nid, &start_pfn, &end_pfn); |
892 | 953 | ||
893 | /* Allocate the node structure node local if possible */ | 954 | /* |
955 | * Allocate the node structure node local if possible | ||
956 | * | ||
957 | * Be careful moving this around, as it relies on all | ||
958 | * previous nodes' bootmem to be initialized and have | ||
959 | * all reserved areas marked. | ||
960 | */ | ||
894 | NODE_DATA(nid) = careful_allocation(nid, | 961 | NODE_DATA(nid) = careful_allocation(nid, |
895 | sizeof(struct pglist_data), | 962 | sizeof(struct pglist_data), |
896 | SMP_CACHE_BYTES, end_pfn); | 963 | SMP_CACHE_BYTES, end_pfn); |
@@ -922,53 +989,14 @@ void __init do_init_bootmem(void) | |||
922 | start_pfn, end_pfn); | 989 | start_pfn, end_pfn); |
923 | 990 | ||
924 | free_bootmem_with_active_regions(nid, end_pfn); | 991 | free_bootmem_with_active_regions(nid, end_pfn); |
925 | } | 992 | /* |
926 | 993 | * Be very careful about moving this around. Future | |
927 | /* Mark reserved regions */ | 994 | * calls to careful_allocation() depend on this getting |
928 | for (i = 0; i < lmb.reserved.cnt; i++) { | 995 | * done correctly. |
929 | unsigned long physbase = lmb.reserved.region[i].base; | 996 | */ |
930 | unsigned long size = lmb.reserved.region[i].size; | 997 | mark_reserved_regions_for_nid(nid); |
931 | unsigned long start_pfn = physbase >> PAGE_SHIFT; | ||
932 | unsigned long end_pfn = ((physbase + size) >> PAGE_SHIFT); | ||
933 | struct node_active_region node_ar; | ||
934 | |||
935 | get_node_active_region(start_pfn, &node_ar); | ||
936 | while (start_pfn < end_pfn && | ||
937 | node_ar.start_pfn < node_ar.end_pfn) { | ||
938 | unsigned long reserve_size = size; | ||
939 | /* | ||
940 | * if reserved region extends past active region | ||
941 | * then trim size to active region | ||
942 | */ | ||
943 | if (end_pfn > node_ar.end_pfn) | ||
944 | reserve_size = (node_ar.end_pfn << PAGE_SHIFT) | ||
945 | - (start_pfn << PAGE_SHIFT); | ||
946 | dbg("reserve_bootmem %lx %lx nid=%d\n", physbase, | ||
947 | reserve_size, node_ar.nid); | ||
948 | reserve_bootmem_node(NODE_DATA(node_ar.nid), physbase, | ||
949 | reserve_size, BOOTMEM_DEFAULT); | ||
950 | /* | ||
951 | * if reserved region is contained in the active region | ||
952 | * then done. | ||
953 | */ | ||
954 | if (end_pfn <= node_ar.end_pfn) | ||
955 | break; | ||
956 | |||
957 | /* | ||
958 | * reserved region extends past the active region | ||
959 | * get next active region that contains this | ||
960 | * reserved region | ||
961 | */ | ||
962 | start_pfn = node_ar.end_pfn; | ||
963 | physbase = start_pfn << PAGE_SHIFT; | ||
964 | size = size - reserve_size; | ||
965 | get_node_active_region(start_pfn, &node_ar); | ||
966 | } | ||
967 | |||
968 | } | ||
969 | |||
970 | for_each_online_node(nid) | ||
971 | sparse_memory_present_with_active_regions(nid); | 998 | sparse_memory_present_with_active_regions(nid); |
999 | } | ||
972 | } | 1000 | } |
973 | 1001 | ||
974 | void __init paging_init(void) | 1002 | void __init paging_init(void) |