aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/hotplug-memory.c
diff options
context:
space:
mode:
authorNathan Fontenot <nfont@linux.vnet.ibm.com>2012-10-02 12:57:57 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-11-14 20:56:41 -0500
commit1cf3d8b3d24cd383ddfd5442c83ec5c355ffc2f7 (patch)
tree0f4790e95f917c6b76d95c88b7b3d67445261893 /arch/powerpc/platforms/pseries/hotplug-memory.c
parentf59497208363f3dd9d62b79b7f7eafc95432de79 (diff)
powerpc+of: Add of node/property notification chain for adds and removes
This patch moves the notification chain for updates to the device tree from the powerpc/pseries code to the base OF code. This makes this functionality available to all architectures. Additionally the notification chain is updated to allow notifications for property add/remove/update. To make this work a pointer to a new struct (of_prop_reconfig) is passed to the routines in the notification chain. The of_prop_reconfig property contains a pointer to the node containing the property and a pointer to the property itself. In the case of property updates, the property pointer refers to the new property. Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com> Acked-by: Rob Herring <rob.herring@calxeda.com> Acked-by: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms/pseries/hotplug-memory.c')
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-memory.c60
1 files changed, 43 insertions, 17 deletions
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index ecdb0a6b3171..2372c609fa2b 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -16,7 +16,6 @@
16 16
17#include <asm/firmware.h> 17#include <asm/firmware.h>
18#include <asm/machdep.h> 18#include <asm/machdep.h>
19#include <asm/pSeries_reconfig.h>
20#include <asm/sparsemem.h> 19#include <asm/sparsemem.h>
21 20
22static unsigned long get_memblock_size(void) 21static unsigned long get_memblock_size(void)
@@ -187,42 +186,69 @@ static int pseries_add_memory(struct device_node *np)
187 return (ret < 0) ? -EINVAL : 0; 186 return (ret < 0) ? -EINVAL : 0;
188} 187}
189 188
190static int pseries_drconf_memory(unsigned long *base, unsigned int action) 189static int pseries_update_drconf_memory(struct of_prop_reconfig *pr)
191{ 190{
191 struct of_drconf_cell *new_drmem, *old_drmem;
192 unsigned long memblock_size; 192 unsigned long memblock_size;
193 int rc; 193 u32 entries;
194 u32 *p;
195 int i, rc = -EINVAL;
194 196
195 memblock_size = get_memblock_size(); 197 memblock_size = get_memblock_size();
196 if (!memblock_size) 198 if (!memblock_size)
197 return -EINVAL; 199 return -EINVAL;
198 200
199 if (action == PSERIES_DRCONF_MEM_ADD) { 201 p = (u32 *)of_get_property(pr->dn, "ibm,dynamic-memory", NULL);
200 rc = memblock_add(*base, memblock_size); 202 if (!p)
201 rc = (rc < 0) ? -EINVAL : 0; 203 return -EINVAL;
202 } else if (action == PSERIES_DRCONF_MEM_REMOVE) { 204
203 rc = pseries_remove_memblock(*base, memblock_size); 205 /* The first int of the property is the number of lmb's described
204 } else { 206 * by the property. This is followed by an array of of_drconf_cell
205 rc = -EINVAL; 207 * entries. Get the niumber of entries and skip to the array of
208 * of_drconf_cell's.
209 */
210 entries = *p++;
211 old_drmem = (struct of_drconf_cell *)p;
212
213 p = (u32 *)pr->prop->value;
214 p++;
215 new_drmem = (struct of_drconf_cell *)p;
216
217 for (i = 0; i < entries; i++) {
218 if ((old_drmem[i].flags & DRCONF_MEM_ASSIGNED) &&
219 (!(new_drmem[i].flags & DRCONF_MEM_ASSIGNED))) {
220 rc = pseries_remove_memblock(old_drmem[i].base_addr,
221 memblock_size);
222 break;
223 } else if ((!(old_drmem[i].flags & DRCONF_MEM_ASSIGNED)) &&
224 (new_drmem[i].flags & DRCONF_MEM_ASSIGNED)) {
225 rc = memblock_add(old_drmem[i].base_addr,
226 memblock_size);
227 rc = (rc < 0) ? -EINVAL : 0;
228 break;
229 }
206 } 230 }
207 231
208 return rc; 232 return rc;
209} 233}
210 234
211static int pseries_memory_notifier(struct notifier_block *nb, 235static int pseries_memory_notifier(struct notifier_block *nb,
212 unsigned long action, void *node) 236 unsigned long action, void *node)
213{ 237{
238 struct of_prop_reconfig *pr;
214 int err = 0; 239 int err = 0;
215 240
216 switch (action) { 241 switch (action) {
217 case PSERIES_RECONFIG_ADD: 242 case OF_RECONFIG_ATTACH_NODE:
218 err = pseries_add_memory(node); 243 err = pseries_add_memory(node);
219 break; 244 break;
220 case PSERIES_RECONFIG_REMOVE: 245 case OF_RECONFIG_DETACH_NODE:
221 err = pseries_remove_memory(node); 246 err = pseries_remove_memory(node);
222 break; 247 break;
223 case PSERIES_DRCONF_MEM_ADD: 248 case OF_RECONFIG_UPDATE_PROPERTY:
224 case PSERIES_DRCONF_MEM_REMOVE: 249 pr = (struct of_prop_reconfig *)node;
225 err = pseries_drconf_memory(node, action); 250 if (!strcmp(pr->prop->name, "ibm,dynamic-memory"))
251 err = pseries_update_drconf_memory(pr);
226 break; 252 break;
227 } 253 }
228 return notifier_from_errno(err); 254 return notifier_from_errno(err);
@@ -235,7 +261,7 @@ static struct notifier_block pseries_mem_nb = {
235static int __init pseries_memory_hotplug_init(void) 261static int __init pseries_memory_hotplug_init(void)
236{ 262{
237 if (firmware_has_feature(FW_FEATURE_LPAR)) 263 if (firmware_has_feature(FW_FEATURE_LPAR))
238 pSeries_reconfig_notifier_register(&pseries_mem_nb); 264 of_reconfig_notifier_register(&pseries_mem_nb);
239 265
240 return 0; 266 return 0;
241} 267}