diff options
-rw-r--r-- | arch/powerpc/kernel/prom.c | 40 | ||||
-rw-r--r-- | arch/powerpc/mm/numa.c | 77 |
2 files changed, 95 insertions, 22 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 87d83c56b31e..09455e1c27c5 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -888,9 +888,10 @@ static u64 __init dt_mem_next_cell(int s, cell_t **cellp) | |||
888 | */ | 888 | */ |
889 | static int __init early_init_dt_scan_drconf_memory(unsigned long node) | 889 | static int __init early_init_dt_scan_drconf_memory(unsigned long node) |
890 | { | 890 | { |
891 | cell_t *dm, *ls; | 891 | cell_t *dm, *ls, *usm; |
892 | unsigned long l, n, flags; | 892 | unsigned long l, n, flags; |
893 | u64 base, size, lmb_size; | 893 | u64 base, size, lmb_size; |
894 | unsigned int is_kexec_kdump = 0, rngs; | ||
894 | 895 | ||
895 | ls = (cell_t *)of_get_flat_dt_prop(node, "ibm,lmb-size", &l); | 896 | ls = (cell_t *)of_get_flat_dt_prop(node, "ibm,lmb-size", &l); |
896 | if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t)) | 897 | if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t)) |
@@ -905,6 +906,12 @@ static int __init early_init_dt_scan_drconf_memory(unsigned long node) | |||
905 | if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(cell_t)) | 906 | if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(cell_t)) |
906 | return 0; | 907 | return 0; |
907 | 908 | ||
909 | /* check if this is a kexec/kdump kernel. */ | ||
910 | usm = (cell_t *)of_get_flat_dt_prop(node, "linux,drconf-usable-memory", | ||
911 | &l); | ||
912 | if (usm != NULL) | ||
913 | is_kexec_kdump = 1; | ||
914 | |||
908 | for (; n != 0; --n) { | 915 | for (; n != 0; --n) { |
909 | base = dt_mem_next_cell(dt_root_addr_cells, &dm); | 916 | base = dt_mem_next_cell(dt_root_addr_cells, &dm); |
910 | flags = dm[3]; | 917 | flags = dm[3]; |
@@ -915,13 +922,34 @@ static int __init early_init_dt_scan_drconf_memory(unsigned long node) | |||
915 | if ((flags & 0x80) || !(flags & 0x8)) | 922 | if ((flags & 0x80) || !(flags & 0x8)) |
916 | continue; | 923 | continue; |
917 | size = lmb_size; | 924 | size = lmb_size; |
918 | if (iommu_is_off) { | 925 | rngs = 1; |
919 | if (base >= 0x80000000ul) | 926 | if (is_kexec_kdump) { |
927 | /* | ||
928 | * For each lmb in ibm,dynamic-memory, a corresponding | ||
929 | * entry in linux,drconf-usable-memory property contains | ||
930 | * a counter 'p' followed by 'p' (base, size) duple. | ||
931 | * Now read the counter from | ||
932 | * linux,drconf-usable-memory property | ||
933 | */ | ||
934 | rngs = dt_mem_next_cell(dt_root_size_cells, &usm); | ||
935 | if (!rngs) /* there are no (base, size) duple */ | ||
920 | continue; | 936 | continue; |
921 | if ((base + size) > 0x80000000ul) | ||
922 | size = 0x80000000ul - base; | ||
923 | } | 937 | } |
924 | lmb_add(base, size); | 938 | do { |
939 | if (is_kexec_kdump) { | ||
940 | base = dt_mem_next_cell(dt_root_addr_cells, | ||
941 | &usm); | ||
942 | size = dt_mem_next_cell(dt_root_size_cells, | ||
943 | &usm); | ||
944 | } | ||
945 | if (iommu_is_off) { | ||
946 | if (base >= 0x80000000ul) | ||
947 | continue; | ||
948 | if ((base + size) > 0x80000000ul) | ||
949 | size = 0x80000000ul - base; | ||
950 | } | ||
951 | lmb_add(base, size); | ||
952 | } while (--rngs); | ||
925 | } | 953 | } |
926 | lmb_dump_all(); | 954 | lmb_dump_all(); |
927 | return 0; | 955 | return 0; |
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index d9a181351332..be05457631d4 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
@@ -150,6 +150,21 @@ static const int *of_get_associativity(struct device_node *dev) | |||
150 | return of_get_property(dev, "ibm,associativity", NULL); | 150 | return of_get_property(dev, "ibm,associativity", NULL); |
151 | } | 151 | } |
152 | 152 | ||
153 | /* | ||
154 | * Returns the property linux,drconf-usable-memory if | ||
155 | * it exists (the property exists only in kexec/kdump kernels, | ||
156 | * added by kexec-tools) | ||
157 | */ | ||
158 | static const u32 *of_get_usable_memory(struct device_node *memory) | ||
159 | { | ||
160 | const u32 *prop; | ||
161 | u32 len; | ||
162 | prop = of_get_property(memory, "linux,drconf-usable-memory", &len); | ||
163 | if (!prop || len < sizeof(unsigned int)) | ||
164 | return 0; | ||
165 | return prop; | ||
166 | } | ||
167 | |||
153 | /* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa | 168 | /* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa |
154 | * info is found. | 169 | * info is found. |
155 | */ | 170 | */ |
@@ -487,14 +502,29 @@ static unsigned long __init numa_enforce_memory_limit(unsigned long start, | |||
487 | } | 502 | } |
488 | 503 | ||
489 | /* | 504 | /* |
505 | * Reads the counter for a given entry in | ||
506 | * linux,drconf-usable-memory property | ||
507 | */ | ||
508 | static inline int __init read_usm_ranges(const u32 **usm) | ||
509 | { | ||
510 | /* | ||
511 | * For each lmb in ibm,dynamic-memory a corresponding | ||
512 | * entry in linux,drconf-usable-memory property contains | ||
513 | * a counter followed by that many (base, size) duple. | ||
514 | * read the counter from linux,drconf-usable-memory | ||
515 | */ | ||
516 | return read_n_cells(n_mem_size_cells, usm); | ||
517 | } | ||
518 | |||
519 | /* | ||
490 | * Extract NUMA information from the ibm,dynamic-reconfiguration-memory | 520 | * Extract NUMA information from the ibm,dynamic-reconfiguration-memory |
491 | * node. This assumes n_mem_{addr,size}_cells have been set. | 521 | * node. This assumes n_mem_{addr,size}_cells have been set. |
492 | */ | 522 | */ |
493 | static void __init parse_drconf_memory(struct device_node *memory) | 523 | static void __init parse_drconf_memory(struct device_node *memory) |
494 | { | 524 | { |
495 | const u32 *dm; | 525 | const u32 *dm, *usm; |
496 | unsigned int n, rc; | 526 | unsigned int n, rc, ranges, is_kexec_kdump = 0; |
497 | unsigned long lmb_size, size; | 527 | unsigned long lmb_size, base, size, sz; |
498 | int nid; | 528 | int nid; |
499 | struct assoc_arrays aa; | 529 | struct assoc_arrays aa; |
500 | 530 | ||
@@ -510,6 +540,11 @@ static void __init parse_drconf_memory(struct device_node *memory) | |||
510 | if (rc) | 540 | if (rc) |
511 | return; | 541 | return; |
512 | 542 | ||
543 | /* check if this is a kexec/kdump kernel */ | ||
544 | usm = of_get_usable_memory(memory); | ||
545 | if (usm != NULL) | ||
546 | is_kexec_kdump = 1; | ||
547 | |||
513 | for (; n != 0; --n) { | 548 | for (; n != 0; --n) { |
514 | struct of_drconf_cell drmem; | 549 | struct of_drconf_cell drmem; |
515 | 550 | ||
@@ -521,21 +556,31 @@ static void __init parse_drconf_memory(struct device_node *memory) | |||
521 | || !(drmem.flags & DRCONF_MEM_ASSIGNED)) | 556 | || !(drmem.flags & DRCONF_MEM_ASSIGNED)) |
522 | continue; | 557 | continue; |
523 | 558 | ||
524 | nid = of_drconf_to_nid_single(&drmem, &aa); | 559 | base = drmem.base_addr; |
560 | size = lmb_size; | ||
561 | ranges = 1; | ||
525 | 562 | ||
526 | fake_numa_create_new_node( | 563 | if (is_kexec_kdump) { |
527 | ((drmem.base_addr + lmb_size) >> PAGE_SHIFT), | 564 | ranges = read_usm_ranges(&usm); |
565 | if (!ranges) /* there are no (base, size) duple */ | ||
566 | continue; | ||
567 | } | ||
568 | do { | ||
569 | if (is_kexec_kdump) { | ||
570 | base = read_n_cells(n_mem_addr_cells, &usm); | ||
571 | size = read_n_cells(n_mem_size_cells, &usm); | ||
572 | } | ||
573 | nid = of_drconf_to_nid_single(&drmem, &aa); | ||
574 | fake_numa_create_new_node( | ||
575 | ((base + size) >> PAGE_SHIFT), | ||
528 | &nid); | 576 | &nid); |
529 | 577 | node_set_online(nid); | |
530 | node_set_online(nid); | 578 | sz = numa_enforce_memory_limit(base, size); |
531 | 579 | if (sz) | |
532 | size = numa_enforce_memory_limit(drmem.base_addr, lmb_size); | 580 | add_active_range(nid, base >> PAGE_SHIFT, |
533 | if (!size) | 581 | (base >> PAGE_SHIFT) |
534 | continue; | 582 | + (sz >> PAGE_SHIFT)); |
535 | 583 | } while (--ranges); | |
536 | add_active_range(nid, drmem.base_addr >> PAGE_SHIFT, | ||
537 | (drmem.base_addr >> PAGE_SHIFT) | ||
538 | + (size >> PAGE_SHIFT)); | ||
539 | } | 584 | } |
540 | } | 585 | } |
541 | 586 | ||