diff options
author | Chandru <chandru@in.ibm.com> | 2008-08-29 10:28:16 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-09-15 14:07:58 -0400 |
commit | cf00085d8045cddd80a8aabad97de96fa8131793 (patch) | |
tree | 22bc2935d93709ed6ae229b5737c5412cfaf5991 /arch/powerpc/kernel/prom.c | |
parent | 525c411d400603665f8416f7e84bb14a43830027 (diff) |
powerpc: Add support for dynamic reconfiguration memory in kexec/kdump kernels
Kdump kernel needs to use only those memory regions that it is allowed
to use (crashkernel, rtas, tce, etc.). Each of these regions have
their own sizes and are currently added under 'linux,usable-memory'
property under each memory@xxx node of the device tree.
The ibm,dynamic-memory property of ibm,dynamic-reconfiguration-memory
node (on POWER6) now stores in it the representation for most of the
logical memory blocks with the size of each memory block being a
constant (lmb_size). If one or more or part of the above mentioned
regions lie under one of the lmb from ibm,dynamic-memory property,
there is a need to identify those regions within the given lmb.
This makes the kernel recognize a new 'linux,drconf-usable-memory'
property added by kexec-tools. Each entry in this property is of the
form of a count followed by that many (base, size) pairs for the above
mentioned regions. The number of cells in the count value is given by
the #size-cells property of the root node.
Signed-off-by: Chandru Siddalingappa <chandru@in.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/prom.c')
-rw-r--r-- | arch/powerpc/kernel/prom.c | 40 |
1 files changed, 34 insertions, 6 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; |