]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.arch/ppc-dynamic-reconfiguration.diff
Add a patch to fix Intel E100 wake-on-lan problems.
[ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.arch / ppc-dynamic-reconfiguration.diff
CommitLineData
6a930a95
BS
1From: Chandru <chandru@in.ibm.com>
2Date: Sat, 30 Aug 2008 00:28:16 +1000
3Subject: [PATCH] powerpc: Add support for dynamic reconfiguration memory in kexec/kdump kernels
4References: bnc#431492
5X-Git-Commit: cf00085d8045cddd80a8aabad97de96fa8131793 Mon Sep 17 00:00:00 2001
6
7Kdump kernel needs to use only those memory regions that it is allowed
8to use (crashkernel, rtas, tce, etc.). Each of these regions have
9their own sizes and are currently added under 'linux,usable-memory'
10property under each memory@xxx node of the device tree.
11
12The ibm,dynamic-memory property of ibm,dynamic-reconfiguration-memory
13node (on POWER6) now stores in it the representation for most of the
14logical memory blocks with the size of each memory block being a
15constant (lmb_size). If one or more or part of the above mentioned
16regions lie under one of the lmb from ibm,dynamic-memory property,
17there is a need to identify those regions within the given lmb.
18
19This makes the kernel recognize a new 'linux,drconf-usable-memory'
20property added by kexec-tools. Each entry in this property is of the
21form of a count followed by that many (base, size) pairs for the above
22mentioned regions. The number of cells in the count value is given by
23the #size-cells property of the root node.
24
25Signed-off-by: Chandru Siddalingappa <chandru@in.ibm.com>
26Signed-off-by: Paul Mackerras <paulus@samba.org>
27Acked-by: Bernhard Walle <bwalle@suse.de>
28
29---
30 arch/powerpc/kernel/prom.c | 40 +++++++++++++++++++---
31 arch/powerpc/mm/numa.c | 79 +++++++++++++++++++++++++++++++++++----------
32 2 files changed, 96 insertions(+), 23 deletions(-)
33
34--- a/arch/powerpc/kernel/prom.c
35+++ b/arch/powerpc/kernel/prom.c
36@@ -888,9 +888,10 @@ static u64 __init dt_mem_next_cell(int s
37 */
38 static int __init early_init_dt_scan_drconf_memory(unsigned long node)
39 {
40- cell_t *dm, *ls;
41+ cell_t *dm, *ls, *usm;
42 unsigned long l, n, flags;
43 u64 base, size, lmb_size;
44+ unsigned int is_kexec_kdump = 0, rngs;
45
46 ls = (cell_t *)of_get_flat_dt_prop(node, "ibm,lmb-size", &l);
47 if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t))
48@@ -905,6 +906,12 @@ static int __init early_init_dt_scan_drc
49 if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(cell_t))
50 return 0;
51
52+ /* check if this is a kexec/kdump kernel. */
53+ usm = (cell_t *)of_get_flat_dt_prop(node, "linux,drconf-usable-memory",
54+ &l);
55+ if (usm != NULL)
56+ is_kexec_kdump = 1;
57+
58 for (; n != 0; --n) {
59 base = dt_mem_next_cell(dt_root_addr_cells, &dm);
60 flags = dm[3];
61@@ -915,13 +922,34 @@ static int __init early_init_dt_scan_drc
62 if ((flags & 0x80) || !(flags & 0x8))
63 continue;
64 size = lmb_size;
65- if (iommu_is_off) {
66- if (base >= 0x80000000ul)
67+ rngs = 1;
68+ if (is_kexec_kdump) {
69+ /*
70+ * For each lmb in ibm,dynamic-memory, a corresponding
71+ * entry in linux,drconf-usable-memory property contains
72+ * a counter 'p' followed by 'p' (base, size) duple.
73+ * Now read the counter from
74+ * linux,drconf-usable-memory property
75+ */
76+ rngs = dt_mem_next_cell(dt_root_size_cells, &usm);
77+ if (!rngs) /* there are no (base, size) duple */
78 continue;
79- if ((base + size) > 0x80000000ul)
80- size = 0x80000000ul - base;
81 }
82- lmb_add(base, size);
83+ do {
84+ if (is_kexec_kdump) {
85+ base = dt_mem_next_cell(dt_root_addr_cells,
86+ &usm);
87+ size = dt_mem_next_cell(dt_root_size_cells,
88+ &usm);
89+ }
90+ if (iommu_is_off) {
91+ if (base >= 0x80000000ul)
92+ continue;
93+ if ((base + size) > 0x80000000ul)
94+ size = 0x80000000ul - base;
95+ }
96+ lmb_add(base, size);
97+ } while (--rngs);
98 }
99 lmb_dump_all();
100 return 0;
101--- a/arch/powerpc/mm/numa.c
102+++ b/arch/powerpc/mm/numa.c
103@@ -192,6 +192,21 @@ static const int *of_get_associativity(s
104 return of_get_property(dev, "ibm,associativity", NULL);
105 }
106
107+/*
108+ * Returns the property linux,drconf-usable-memory if
109+ * it exists (the property exists only in kexec/kdump kernels,
110+ * added by kexec-tools)
111+ */
112+static const u32 *of_get_usable_memory(struct device_node *memory)
113+{
114+ const u32 *prop;
115+ u32 len;
116+ prop = of_get_property(memory, "linux,drconf-usable-memory", &len);
117+ if (!prop || len < sizeof(unsigned int))
118+ return 0;
119+ return prop;
120+}
121+
122 /* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa
123 * info is found.
124 */
125@@ -529,14 +544,29 @@ static unsigned long __init numa_enforce
126 }
127
128 /*
129+ * Reads the counter for a given entry in
130+ * linux,drconf-usable-memory property
131+ */
132+static inline int __init read_usm_ranges(const u32 **usm)
133+{
134+ /*
135+ * For each lmb in ibm,dynamic-memory a corresponding
136+ * entry in linux,drconf-usable-memory property contains
137+ * a counter followed by that many (base, size) duple.
138+ * read the counter from linux,drconf-usable-memory
139+ */
140+ return read_n_cells(n_mem_size_cells, usm);
141+}
142+
143+/*
144 * Extract NUMA information from the ibm,dynamic-reconfiguration-memory
145 * node. This assumes n_mem_{addr,size}_cells have been set.
146 */
147 static void __init parse_drconf_memory(struct device_node *memory)
148 {
149- const u32 *dm;
150- unsigned int n, rc;
151- unsigned long lmb_size, size;
152+ const u32 *dm, *usm;
153+ unsigned int n, rc, ranges, is_kexec_kdump = 0;
154+ unsigned long lmb_size, base, size, sz;
155 int nid;
156 struct assoc_arrays aa;
157
158@@ -552,6 +582,11 @@ static void __init parse_drconf_memory(s
159 if (rc)
160 return;
161
162+ /* check if this is a kexec/kdump kernel */
163+ usm = of_get_usable_memory(memory);
164+ if (usm != NULL)
165+ is_kexec_kdump = 1;
166+
167 for (; n != 0; --n) {
168 struct of_drconf_cell drmem;
169
170@@ -563,21 +598,31 @@ static void __init parse_drconf_memory(s
171 || !(drmem.flags & DRCONF_MEM_ASSIGNED))
172 continue;
173
174- nid = of_drconf_to_nid_single(&drmem, &aa);
175-
176- fake_numa_create_new_node(
177- ((drmem.base_addr + lmb_size) >> PAGE_SHIFT),
178+ base = drmem.base_addr;
179+ size = lmb_size;
180+ ranges = 1;
181+
182+ if (is_kexec_kdump) {
183+ ranges = read_usm_ranges(&usm);
184+ if (!ranges) /* there are no (base, size) duple */
185+ continue;
186+ }
187+ do {
188+ if (is_kexec_kdump) {
189+ base = read_n_cells(n_mem_addr_cells, &usm);
190+ size = read_n_cells(n_mem_size_cells, &usm);
191+ }
192+ nid = of_drconf_to_nid_single(&drmem, &aa);
193+ fake_numa_create_new_node(
194+ ((base + size) >> PAGE_SHIFT),
195 &nid);
196-
197- node_set_online(nid);
198-
199- size = numa_enforce_memory_limit(drmem.base_addr, lmb_size);
200- if (!size)
201- continue;
202-
203- add_active_range(nid, drmem.base_addr >> PAGE_SHIFT,
204- (drmem.base_addr >> PAGE_SHIFT)
205- + (size >> PAGE_SHIFT));
206+ node_set_online(nid);
207+ sz = numa_enforce_memory_limit(base, size);
208+ if (sz)
209+ add_active_range(nid, base >> PAGE_SHIFT,
210+ (base >> PAGE_SHIFT)
211+ + (sz >> PAGE_SHIFT));
212+ } while (--ranges);
213 }
214 }
215