aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/prom.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/prom.c')
-rw-r--r--arch/powerpc/kernel/prom.c43
1 files changed, 37 insertions, 6 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 87d83c56b31e..3a2dc7e6586a 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 */
889static int __init early_init_dt_scan_drconf_memory(unsigned long node) 889static 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;
@@ -1164,6 +1192,9 @@ void __init early_init_devtree(void *params)
1164 1192
1165 /* Reserve LMB regions used by kernel, initrd, dt, etc... */ 1193 /* Reserve LMB regions used by kernel, initrd, dt, etc... */
1166 lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START); 1194 lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
1195 /* If relocatable, reserve first 32k for interrupt vectors etc. */
1196 if (PHYSICAL_START > MEMORY_START)
1197 lmb_reserve(MEMORY_START, 0x8000);
1167 reserve_kdump_trampoline(); 1198 reserve_kdump_trampoline();
1168 reserve_crashkernel(); 1199 reserve_crashkernel();
1169 early_reserve_mem(); 1200 early_reserve_mem();