aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-11-14 23:02:44 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-11-14 23:02:44 -0500
commitde1bb03af7f4dde8e0e823629909d179fed4beff (patch)
tree4ea86f8e160b8ea5c9689883c7f7da1536f5294b
parent11ee7e99f35ecb15f59b21da6a82d96d2cd3fcc8 (diff)
parentf459d63e1689b16a2f5a965557e19b25bad5dbdc (diff)
Merge branch 'dt' into next
-rw-r--r--arch/arm/mach-mxs/mach-mxs.c2
-rw-r--r--arch/powerpc/include/asm/pSeries_reconfig.h47
-rw-r--r--arch/powerpc/include/asm/prom.h16
-rw-r--r--arch/powerpc/include/asm/rtas.h5
-rw-r--r--arch/powerpc/kernel/machine_kexec.c14
-rw-r--r--arch/powerpc/kernel/machine_kexec_64.c8
-rw-r--r--arch/powerpc/kernel/pci_32.c2
-rw-r--r--arch/powerpc/kernel/prom.c6
-rw-r--r--arch/powerpc/kernel/rtas.c1
-rw-r--r--arch/powerpc/mm/numa.c12
-rw-r--r--arch/powerpc/platforms/85xx/p1022_ds.c6
-rw-r--r--arch/powerpc/platforms/ps3/os-area.c6
-rw-r--r--arch/powerpc/platforms/pseries/dlpar.c34
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-cpu.c8
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-memory.c60
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c10
-rw-r--r--arch/powerpc/platforms/pseries/mobility.c4
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c119
-rw-r--r--arch/powerpc/platforms/pseries/setup.c6
-rw-r--r--arch/powerpc/platforms/pseries/smp.c1
-rw-r--r--drivers/crypto/nx/nx-842.c20
-rw-r--r--drivers/crypto/nx/nx.c1
-rw-r--r--drivers/macintosh/smu.c2
-rw-r--r--drivers/of/base.c140
-rw-r--r--include/linux/of.h29
25 files changed, 267 insertions, 292 deletions
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
index 4748ec551a68..d61b915ce52c 100644
--- a/arch/arm/mach-mxs/mach-mxs.c
+++ b/arch/arm/mach-mxs/mach-mxs.c
@@ -211,7 +211,7 @@ static void __init update_fec_mac_prop(enum mac_oui oui)
211 macaddr[4] = (val >> 8) & 0xff; 211 macaddr[4] = (val >> 8) & 0xff;
212 macaddr[5] = (val >> 0) & 0xff; 212 macaddr[5] = (val >> 0) & 0xff;
213 213
214 prom_update_property(np, newmac); 214 of_update_property(np, newmac);
215 } 215 }
216} 216}
217 217
diff --git a/arch/powerpc/include/asm/pSeries_reconfig.h b/arch/powerpc/include/asm/pSeries_reconfig.h
deleted file mode 100644
index c07edfe98b98..000000000000
--- a/arch/powerpc/include/asm/pSeries_reconfig.h
+++ /dev/null
@@ -1,47 +0,0 @@
1#ifndef _PPC64_PSERIES_RECONFIG_H
2#define _PPC64_PSERIES_RECONFIG_H
3#ifdef __KERNEL__
4
5#include <linux/notifier.h>
6
7/*
8 * Use this API if your code needs to know about OF device nodes being
9 * added or removed on pSeries systems.
10 */
11
12#define PSERIES_RECONFIG_ADD 0x0001
13#define PSERIES_RECONFIG_REMOVE 0x0002
14#define PSERIES_DRCONF_MEM_ADD 0x0003
15#define PSERIES_DRCONF_MEM_REMOVE 0x0004
16#define PSERIES_UPDATE_PROPERTY 0x0005
17
18/**
19 * pSeries_reconfig_notify - Notifier value structure for OFDT property updates
20 *
21 * @node: Device tree node which owns the property being updated
22 * @property: Updated property
23 */
24struct pSeries_reconfig_prop_update {
25 struct device_node *node;
26 struct property *property;
27};
28
29#ifdef CONFIG_PPC_PSERIES
30extern int pSeries_reconfig_notifier_register(struct notifier_block *);
31extern void pSeries_reconfig_notifier_unregister(struct notifier_block *);
32extern int pSeries_reconfig_notify(unsigned long action, void *p);
33/* Not the best place to put this, will be fixed when we move some
34 * of the rtas suspend-me stuff to pseries */
35extern void pSeries_coalesce_init(void);
36#else /* !CONFIG_PPC_PSERIES */
37static inline int pSeries_reconfig_notifier_register(struct notifier_block *nb)
38{
39 return 0;
40}
41static inline void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) { }
42static inline void pSeries_coalesce_init(void) { }
43#endif /* CONFIG_PPC_PSERIES */
44
45
46#endif /* __KERNEL__ */
47#endif /* _PPC64_PSERIES_RECONFIG_H */
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index b5c91901e384..99c92d5363e4 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -58,6 +58,22 @@ static inline int of_node_to_nid(struct device_node *device) { return 0; }
58 58
59extern void of_instantiate_rtc(void); 59extern void of_instantiate_rtc(void);
60 60
61/* The of_drconf_cell struct defines the layout of the LMB array
62 * specified in the device tree property
63 * ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory
64 */
65struct of_drconf_cell {
66 u64 base_addr;
67 u32 drc_index;
68 u32 reserved;
69 u32 aa_index;
70 u32 flags;
71};
72
73#define DRCONF_MEM_ASSIGNED 0x00000008
74#define DRCONF_MEM_AI_INVALID 0x00000040
75#define DRCONF_MEM_RESERVED 0x00000080
76
61/* These includes are put at the bottom because they may contain things 77/* These includes are put at the bottom because they may contain things
62 * that are overridden by this file. Ideally they shouldn't be included 78 * that are overridden by this file. Ideally they shouldn't be included
63 * by this file, but there are a bunch of .c files that currently depend 79 * by this file, but there are a bunch of .c files that currently depend
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index 557cff845dee..aef00c675905 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -353,8 +353,13 @@ static inline int page_is_rtas_user_buf(unsigned long pfn)
353 return 1; 353 return 1;
354 return 0; 354 return 0;
355} 355}
356
357/* Not the best place to put pSeries_coalesce_init, will be fixed when we
358 * move some of the rtas suspend-me stuff to pseries */
359extern void pSeries_coalesce_init(void);
356#else 360#else
357static inline int page_is_rtas_user_buf(unsigned long pfn) { return 0;} 361static inline int page_is_rtas_user_buf(unsigned long pfn) { return 0;}
362static inline void pSeries_coalesce_init(void) { }
358#endif 363#endif
359 364
360extern int call_rtas(const char *, int, int, unsigned long *, ...); 365extern int call_rtas(const char *, int, int, unsigned long *, ...);
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
index fa9f6c72f557..e1ec57e87b3b 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -218,23 +218,23 @@ static void __init export_crashk_values(struct device_node *node)
218 * be sure what's in them, so remove them. */ 218 * be sure what's in them, so remove them. */
219 prop = of_find_property(node, "linux,crashkernel-base", NULL); 219 prop = of_find_property(node, "linux,crashkernel-base", NULL);
220 if (prop) 220 if (prop)
221 prom_remove_property(node, prop); 221 of_remove_property(node, prop);
222 222
223 prop = of_find_property(node, "linux,crashkernel-size", NULL); 223 prop = of_find_property(node, "linux,crashkernel-size", NULL);
224 if (prop) 224 if (prop)
225 prom_remove_property(node, prop); 225 of_remove_property(node, prop);
226 226
227 if (crashk_res.start != 0) { 227 if (crashk_res.start != 0) {
228 prom_add_property(node, &crashk_base_prop); 228 of_add_property(node, &crashk_base_prop);
229 crashk_size = resource_size(&crashk_res); 229 crashk_size = resource_size(&crashk_res);
230 prom_add_property(node, &crashk_size_prop); 230 of_add_property(node, &crashk_size_prop);
231 } 231 }
232 232
233 /* 233 /*
234 * memory_limit is required by the kexec-tools to limit the 234 * memory_limit is required by the kexec-tools to limit the
235 * crash regions to the actual memory used. 235 * crash regions to the actual memory used.
236 */ 236 */
237 prom_update_property(node, &memory_limit_prop); 237 of_update_property(node, &memory_limit_prop);
238} 238}
239 239
240static int __init kexec_setup(void) 240static int __init kexec_setup(void)
@@ -249,11 +249,11 @@ static int __init kexec_setup(void)
249 /* remove any stale properties so ours can be found */ 249 /* remove any stale properties so ours can be found */
250 prop = of_find_property(node, kernel_end_prop.name, NULL); 250 prop = of_find_property(node, kernel_end_prop.name, NULL);
251 if (prop) 251 if (prop)
252 prom_remove_property(node, prop); 252 of_remove_property(node, prop);
253 253
254 /* information needed by userspace when using default_machine_kexec */ 254 /* information needed by userspace when using default_machine_kexec */
255 kernel_end = __pa(_end); 255 kernel_end = __pa(_end);
256 prom_add_property(node, &kernel_end_prop); 256 of_add_property(node, &kernel_end_prop);
257 257
258 export_crashk_values(node); 258 export_crashk_values(node);
259 259
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c
index d7f609086a99..7206701b1ff1 100644
--- a/arch/powerpc/kernel/machine_kexec_64.c
+++ b/arch/powerpc/kernel/machine_kexec_64.c
@@ -389,14 +389,14 @@ static int __init export_htab_values(void)
389 /* remove any stale propertys so ours can be found */ 389 /* remove any stale propertys so ours can be found */
390 prop = of_find_property(node, htab_base_prop.name, NULL); 390 prop = of_find_property(node, htab_base_prop.name, NULL);
391 if (prop) 391 if (prop)
392 prom_remove_property(node, prop); 392 of_remove_property(node, prop);
393 prop = of_find_property(node, htab_size_prop.name, NULL); 393 prop = of_find_property(node, htab_size_prop.name, NULL);
394 if (prop) 394 if (prop)
395 prom_remove_property(node, prop); 395 of_remove_property(node, prop);
396 396
397 htab_base = __pa(htab_address); 397 htab_base = __pa(htab_address);
398 prom_add_property(node, &htab_base_prop); 398 of_add_property(node, &htab_base_prop);
399 prom_add_property(node, &htab_size_prop); 399 of_add_property(node, &htab_size_prop);
400 400
401 of_node_put(node); 401 of_node_put(node);
402 return 0; 402 return 0;
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 4b06ec5a502e..64f526a321f5 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -208,7 +208,7 @@ pci_create_OF_bus_map(void)
208 of_prop->name = "pci-OF-bus-map"; 208 of_prop->name = "pci-OF-bus-map";
209 of_prop->length = 256; 209 of_prop->length = 256;
210 of_prop->value = &of_prop[1]; 210 of_prop->value = &of_prop[1];
211 prom_add_property(dn, of_prop); 211 of_add_property(dn, of_prop);
212 of_node_put(dn); 212 of_node_put(dn);
213 } 213 }
214} 214}
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index f5ca76a79c88..8b6f7a99cce2 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -32,6 +32,7 @@
32#include <linux/debugfs.h> 32#include <linux/debugfs.h>
33#include <linux/irq.h> 33#include <linux/irq.h>
34#include <linux/memblock.h> 34#include <linux/memblock.h>
35#include <linux/of.h>
35 36
36#include <asm/prom.h> 37#include <asm/prom.h>
37#include <asm/rtas.h> 38#include <asm/rtas.h>
@@ -49,7 +50,6 @@
49#include <asm/btext.h> 50#include <asm/btext.h>
50#include <asm/sections.h> 51#include <asm/sections.h>
51#include <asm/machdep.h> 52#include <asm/machdep.h>
52#include <asm/pSeries_reconfig.h>
53#include <asm/pci-bridge.h> 53#include <asm/pci-bridge.h>
54#include <asm/kexec.h> 54#include <asm/kexec.h>
55#include <asm/opal.h> 55#include <asm/opal.h>
@@ -803,7 +803,7 @@ static int prom_reconfig_notifier(struct notifier_block *nb,
803 int err; 803 int err;
804 804
805 switch (action) { 805 switch (action) {
806 case PSERIES_RECONFIG_ADD: 806 case OF_RECONFIG_ATTACH_NODE:
807 err = of_finish_dynamic_node(node); 807 err = of_finish_dynamic_node(node);
808 if (err < 0) 808 if (err < 0)
809 printk(KERN_ERR "finish_node returned %d\n", err); 809 printk(KERN_ERR "finish_node returned %d\n", err);
@@ -822,7 +822,7 @@ static struct notifier_block prom_reconfig_nb = {
822 822
823static int __init prom_reconfig_setup(void) 823static int __init prom_reconfig_setup(void)
824{ 824{
825 return pSeries_reconfig_notifier_register(&prom_reconfig_nb); 825 return of_reconfig_notifier_register(&prom_reconfig_nb);
826} 826}
827__initcall(prom_reconfig_setup); 827__initcall(prom_reconfig_setup);
828#endif 828#endif
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index fcec38241f79..1fd6e7b2f390 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -42,7 +42,6 @@
42#include <asm/time.h> 42#include <asm/time.h>
43#include <asm/mmu.h> 43#include <asm/mmu.h>
44#include <asm/topology.h> 44#include <asm/topology.h>
45#include <asm/pSeries_reconfig.h>
46 45
47struct rtas_t rtas = { 46struct rtas_t rtas = {
48 .lock = __ARCH_SPIN_LOCK_UNLOCKED 47 .lock = __ARCH_SPIN_LOCK_UNLOCKED
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 59213cfaeca9..bba87ca2b4d7 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -399,18 +399,6 @@ static unsigned long read_n_cells(int n, const unsigned int **buf)
399 return result; 399 return result;
400} 400}
401 401
402struct of_drconf_cell {
403 u64 base_addr;
404 u32 drc_index;
405 u32 reserved;
406 u32 aa_index;
407 u32 flags;
408};
409
410#define DRCONF_MEM_ASSIGNED 0x00000008
411#define DRCONF_MEM_AI_INVALID 0x00000040
412#define DRCONF_MEM_RESERVED 0x00000080
413
414/* 402/*
415 * Read the next memblock list entry from the ibm,dynamic-memory property 403 * Read the next memblock list entry from the ibm,dynamic-memory property
416 * and return the information in the provided of_drconf_cell structure. 404 * and return the information in the provided of_drconf_cell structure.
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 848a3e98e1c1..8fb12570b2f5 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -539,7 +539,7 @@ static void __init p1022_ds_setup_arch(void)
539 }; 539 };
540 540
541 /* 541 /*
542 * prom_update_property() is called before 542 * of_update_property() is called before
543 * kmalloc() is available, so the 'new' object 543 * kmalloc() is available, so the 'new' object
544 * should be allocated in the global area. 544 * should be allocated in the global area.
545 * The easiest way is to do that is to 545 * The easiest way is to do that is to
@@ -548,7 +548,7 @@ static void __init p1022_ds_setup_arch(void)
548 */ 548 */
549 pr_info("p1022ds: disabling %s node", 549 pr_info("p1022ds: disabling %s node",
550 np2->full_name); 550 np2->full_name);
551 prom_update_property(np2, &nor_status); 551 of_update_property(np2, &nor_status);
552 of_node_put(np2); 552 of_node_put(np2);
553 } 553 }
554 554
@@ -564,7 +564,7 @@ static void __init p1022_ds_setup_arch(void)
564 564
565 pr_info("p1022ds: disabling %s node", 565 pr_info("p1022ds: disabling %s node",
566 np2->full_name); 566 np2->full_name);
567 prom_update_property(np2, &nand_status); 567 of_update_property(np2, &nand_status);
568 of_node_put(np2); 568 of_node_put(np2);
569 } 569 }
570 570
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c
index 56d26bc4fd41..09787139834d 100644
--- a/arch/powerpc/platforms/ps3/os-area.c
+++ b/arch/powerpc/platforms/ps3/os-area.c
@@ -280,13 +280,13 @@ static void os_area_set_property(struct device_node *node,
280 280
281 if (tmp) { 281 if (tmp) {
282 pr_debug("%s:%d found %s\n", __func__, __LINE__, prop->name); 282 pr_debug("%s:%d found %s\n", __func__, __LINE__, prop->name);
283 prom_remove_property(node, tmp); 283 of_remove_property(node, tmp);
284 } 284 }
285 285
286 result = prom_add_property(node, prop); 286 result = of_add_property(node, prop);
287 287
288 if (result) 288 if (result)
289 pr_debug("%s:%d prom_set_property failed\n", __func__, 289 pr_debug("%s:%d of_set_property failed\n", __func__,
290 __LINE__); 290 __LINE__);
291} 291}
292 292
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index 0f1b706506ed..a1a7b9a67ffd 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -13,17 +13,16 @@
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/kref.h> 14#include <linux/kref.h>
15#include <linux/notifier.h> 15#include <linux/notifier.h>
16#include <linux/proc_fs.h>
17#include <linux/spinlock.h> 16#include <linux/spinlock.h>
18#include <linux/cpu.h> 17#include <linux/cpu.h>
19#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/of.h>
20#include "offline_states.h" 20#include "offline_states.h"
21 21
22#include <asm/prom.h> 22#include <asm/prom.h>
23#include <asm/machdep.h> 23#include <asm/machdep.h>
24#include <asm/uaccess.h> 24#include <asm/uaccess.h>
25#include <asm/rtas.h> 25#include <asm/rtas.h>
26#include <asm/pSeries_reconfig.h>
27 26
28struct cc_workarea { 27struct cc_workarea {
29 u32 drc_index; 28 u32 drc_index;
@@ -255,9 +254,6 @@ static struct device_node *derive_parent(const char *path)
255 254
256int dlpar_attach_node(struct device_node *dn) 255int dlpar_attach_node(struct device_node *dn)
257{ 256{
258#ifdef CONFIG_PROC_DEVICETREE
259 struct proc_dir_entry *ent;
260#endif
261 int rc; 257 int rc;
262 258
263 of_node_set_flag(dn, OF_DYNAMIC); 259 of_node_set_flag(dn, OF_DYNAMIC);
@@ -266,44 +262,26 @@ int dlpar_attach_node(struct device_node *dn)
266 if (!dn->parent) 262 if (!dn->parent)
267 return -ENOMEM; 263 return -ENOMEM;
268 264
269 rc = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, dn); 265 rc = of_attach_node(dn);
270 if (rc) { 266 if (rc) {
271 printk(KERN_ERR "Failed to add device node %s\n", 267 printk(KERN_ERR "Failed to add device node %s\n",
272 dn->full_name); 268 dn->full_name);
273 return rc; 269 return rc;
274 } 270 }
275 271
276 of_attach_node(dn);
277
278#ifdef CONFIG_PROC_DEVICETREE
279 ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde);
280 if (ent)
281 proc_device_tree_add_node(dn, ent);
282#endif
283
284 of_node_put(dn->parent); 272 of_node_put(dn->parent);
285 return 0; 273 return 0;
286} 274}
287 275
288int dlpar_detach_node(struct device_node *dn) 276int dlpar_detach_node(struct device_node *dn)
289{ 277{
290#ifdef CONFIG_PROC_DEVICETREE 278 int rc;
291 struct device_node *parent = dn->parent;
292 struct property *prop = dn->properties;
293
294 while (prop) {
295 remove_proc_entry(prop->name, dn->pde);
296 prop = prop->next;
297 }
298 279
299 if (dn->pde) 280 rc = of_detach_node(dn);
300 remove_proc_entry(dn->pde->name, parent->pde); 281 if (rc)
301#endif 282 return rc;
302 283
303 pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, dn);
304 of_detach_node(dn);
305 of_node_put(dn); /* Must decrement the refcount */ 284 of_node_put(dn); /* Must decrement the refcount */
306
307 return 0; 285 return 0;
308} 286}
309 287
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index 64c97d8ac0c5..a38956269fbf 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -23,12 +23,12 @@
23#include <linux/delay.h> 23#include <linux/delay.h>
24#include <linux/sched.h> /* for idle_task_exit */ 24#include <linux/sched.h> /* for idle_task_exit */
25#include <linux/cpu.h> 25#include <linux/cpu.h>
26#include <linux/of.h>
26#include <asm/prom.h> 27#include <asm/prom.h>
27#include <asm/rtas.h> 28#include <asm/rtas.h>
28#include <asm/firmware.h> 29#include <asm/firmware.h>
29#include <asm/machdep.h> 30#include <asm/machdep.h>
30#include <asm/vdso_datapage.h> 31#include <asm/vdso_datapage.h>
31#include <asm/pSeries_reconfig.h>
32#include <asm/xics.h> 32#include <asm/xics.h>
33#include "plpar_wrappers.h" 33#include "plpar_wrappers.h"
34#include "offline_states.h" 34#include "offline_states.h"
@@ -333,10 +333,10 @@ static int pseries_smp_notifier(struct notifier_block *nb,
333 int err = 0; 333 int err = 0;
334 334
335 switch (action) { 335 switch (action) {
336 case PSERIES_RECONFIG_ADD: 336 case OF_RECONFIG_ATTACH_NODE:
337 err = pseries_add_processor(node); 337 err = pseries_add_processor(node);
338 break; 338 break;
339 case PSERIES_RECONFIG_REMOVE: 339 case OF_RECONFIG_DETACH_NODE:
340 pseries_remove_processor(node); 340 pseries_remove_processor(node);
341 break; 341 break;
342 } 342 }
@@ -399,7 +399,7 @@ static int __init pseries_cpu_hotplug_init(void)
399 399
400 /* Processors can be added/removed only on LPAR */ 400 /* Processors can be added/removed only on LPAR */
401 if (firmware_has_feature(FW_FEATURE_LPAR)) { 401 if (firmware_has_feature(FW_FEATURE_LPAR)) {
402 pSeries_reconfig_notifier_register(&pseries_smp_nb); 402 of_reconfig_notifier_register(&pseries_smp_nb);
403 cpu_maps_update_begin(); 403 cpu_maps_update_begin();
404 if (cede_offline_enabled && parse_cede_parameters() == 0) { 404 if (cede_offline_enabled && parse_cede_parameters() == 0) {
405 default_offline_state = CPU_STATE_INACTIVE; 405 default_offline_state = CPU_STATE_INACTIVE;
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}
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 6153eea27ce7..e2685badb5db 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -36,13 +36,13 @@
36#include <linux/dma-mapping.h> 36#include <linux/dma-mapping.h>
37#include <linux/crash_dump.h> 37#include <linux/crash_dump.h>
38#include <linux/memory.h> 38#include <linux/memory.h>
39#include <linux/of.h>
39#include <asm/io.h> 40#include <asm/io.h>
40#include <asm/prom.h> 41#include <asm/prom.h>
41#include <asm/rtas.h> 42#include <asm/rtas.h>
42#include <asm/iommu.h> 43#include <asm/iommu.h>
43#include <asm/pci-bridge.h> 44#include <asm/pci-bridge.h>
44#include <asm/machdep.h> 45#include <asm/machdep.h>
45#include <asm/pSeries_reconfig.h>
46#include <asm/firmware.h> 46#include <asm/firmware.h>
47#include <asm/tce.h> 47#include <asm/tce.h>
48#include <asm/ppc-pci.h> 48#include <asm/ppc-pci.h>
@@ -760,7 +760,7 @@ static void remove_ddw(struct device_node *np)
760 __remove_ddw(np, ddw_avail, liobn); 760 __remove_ddw(np, ddw_avail, liobn);
761 761
762delprop: 762delprop:
763 ret = prom_remove_property(np, win64); 763 ret = of_remove_property(np, win64);
764 if (ret) 764 if (ret)
765 pr_warning("%s: failed to remove direct window property: %d\n", 765 pr_warning("%s: failed to remove direct window property: %d\n",
766 np->full_name, ret); 766 np->full_name, ret);
@@ -1070,7 +1070,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
1070 goto out_free_window; 1070 goto out_free_window;
1071 } 1071 }
1072 1072
1073 ret = prom_add_property(pdn, win64); 1073 ret = of_add_property(pdn, win64);
1074 if (ret) { 1074 if (ret) {
1075 dev_err(&dev->dev, "unable to add dma window property for %s: %d", 1075 dev_err(&dev->dev, "unable to add dma window property for %s: %d",
1076 pdn->full_name, ret); 1076 pdn->full_name, ret);
@@ -1294,7 +1294,7 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti
1294 struct direct_window *window; 1294 struct direct_window *window;
1295 1295
1296 switch (action) { 1296 switch (action) {
1297 case PSERIES_RECONFIG_REMOVE: 1297 case OF_RECONFIG_DETACH_NODE:
1298 if (pci && pci->iommu_table) 1298 if (pci && pci->iommu_table)
1299 iommu_free_table(pci->iommu_table, np->full_name); 1299 iommu_free_table(pci->iommu_table, np->full_name);
1300 1300
@@ -1357,7 +1357,7 @@ void iommu_init_early_pSeries(void)
1357 } 1357 }
1358 1358
1359 1359
1360 pSeries_reconfig_notifier_register(&iommu_reconfig_nb); 1360 of_reconfig_notifier_register(&iommu_reconfig_nb);
1361 register_memory_notifier(&iommu_mem_nb); 1361 register_memory_notifier(&iommu_mem_nb);
1362 1362
1363 set_pci_dma_ops(&dma_iommu_ops); 1363 set_pci_dma_ops(&dma_iommu_ops);
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
index dd30b12edfe4..6573808cc5f3 100644
--- a/arch/powerpc/platforms/pseries/mobility.c
+++ b/arch/powerpc/platforms/pseries/mobility.c
@@ -116,7 +116,7 @@ static int update_dt_property(struct device_node *dn, struct property **prop,
116 } 116 }
117 117
118 if (!more) { 118 if (!more) {
119 prom_update_property(dn, new_prop); 119 of_update_property(dn, new_prop);
120 new_prop = NULL; 120 new_prop = NULL;
121 } 121 }
122 122
@@ -172,7 +172,7 @@ static int update_dt_node(u32 phandle)
172 172
173 case 0x80000000: 173 case 0x80000000:
174 prop = of_find_property(dn, prop_name, NULL); 174 prop = of_find_property(dn, prop_name, NULL);
175 prom_remove_property(dn, prop); 175 of_remove_property(dn, prop);
176 prop = NULL; 176 prop = NULL;
177 break; 177 break;
178 178
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 39f71fba9b38..30b358dc2beb 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -16,55 +16,13 @@
16#include <linux/notifier.h> 16#include <linux/notifier.h>
17#include <linux/proc_fs.h> 17#include <linux/proc_fs.h>
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/of.h>
19 20
20#include <asm/prom.h> 21#include <asm/prom.h>
21#include <asm/machdep.h> 22#include <asm/machdep.h>
22#include <asm/uaccess.h> 23#include <asm/uaccess.h>
23#include <asm/pSeries_reconfig.h>
24#include <asm/mmu.h> 24#include <asm/mmu.h>
25 25
26
27
28/*
29 * Routines for "runtime" addition and removal of device tree nodes.
30 */
31#ifdef CONFIG_PROC_DEVICETREE
32/*
33 * Add a node to /proc/device-tree.
34 */
35static void add_node_proc_entries(struct device_node *np)
36{
37 struct proc_dir_entry *ent;
38
39 ent = proc_mkdir(strrchr(np->full_name, '/') + 1, np->parent->pde);
40 if (ent)
41 proc_device_tree_add_node(np, ent);
42}
43
44static void remove_node_proc_entries(struct device_node *np)
45{
46 struct property *pp = np->properties;
47 struct device_node *parent = np->parent;
48
49 while (pp) {
50 remove_proc_entry(pp->name, np->pde);
51 pp = pp->next;
52 }
53 if (np->pde)
54 remove_proc_entry(np->pde->name, parent->pde);
55}
56#else /* !CONFIG_PROC_DEVICETREE */
57static void add_node_proc_entries(struct device_node *np)
58{
59 return;
60}
61
62static void remove_node_proc_entries(struct device_node *np)
63{
64 return;
65}
66#endif /* CONFIG_PROC_DEVICETREE */
67
68/** 26/**
69 * derive_parent - basically like dirname(1) 27 * derive_parent - basically like dirname(1)
70 * @path: the full_name of a node to be added to the tree 28 * @path: the full_name of a node to be added to the tree
@@ -97,28 +55,6 @@ static struct device_node *derive_parent(const char *path)
97 return parent; 55 return parent;
98} 56}
99 57
100static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain);
101
102int pSeries_reconfig_notifier_register(struct notifier_block *nb)
103{
104 return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb);
105}
106EXPORT_SYMBOL_GPL(pSeries_reconfig_notifier_register);
107
108void pSeries_reconfig_notifier_unregister(struct notifier_block *nb)
109{
110 blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb);
111}
112EXPORT_SYMBOL_GPL(pSeries_reconfig_notifier_unregister);
113
114int pSeries_reconfig_notify(unsigned long action, void *p)
115{
116 int err = blocking_notifier_call_chain(&pSeries_reconfig_chain,
117 action, p);
118
119 return notifier_to_errno(err);
120}
121
122static int pSeries_reconfig_add_node(const char *path, struct property *proplist) 58static int pSeries_reconfig_add_node(const char *path, struct property *proplist)
123{ 59{
124 struct device_node *np; 60 struct device_node *np;
@@ -142,16 +78,12 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
142 goto out_err; 78 goto out_err;
143 } 79 }
144 80
145 err = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, np); 81 err = of_attach_node(np);
146 if (err) { 82 if (err) {
147 printk(KERN_ERR "Failed to add device node %s\n", path); 83 printk(KERN_ERR "Failed to add device node %s\n", path);
148 goto out_err; 84 goto out_err;
149 } 85 }
150 86
151 of_attach_node(np);
152
153 add_node_proc_entries(np);
154
155 of_node_put(np->parent); 87 of_node_put(np->parent);
156 88
157 return 0; 89 return 0;
@@ -179,11 +111,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np)
179 return -EBUSY; 111 return -EBUSY;
180 } 112 }
181 113
182 remove_node_proc_entries(np);
183
184 pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, np);
185 of_detach_node(np); 114 of_detach_node(np);
186
187 of_node_put(parent); 115 of_node_put(parent);
188 of_node_put(np); /* Must decrement the refcount */ 116 of_node_put(np); /* Must decrement the refcount */
189 return 0; 117 return 0;
@@ -398,7 +326,7 @@ static int do_add_property(char *buf, size_t bufsize)
398 if (!prop) 326 if (!prop)
399 return -ENOMEM; 327 return -ENOMEM;
400 328
401 prom_add_property(np, prop); 329 of_add_property(np, prop);
402 330
403 return 0; 331 return 0;
404} 332}
@@ -422,16 +350,15 @@ static int do_remove_property(char *buf, size_t bufsize)
422 350
423 prop = of_find_property(np, buf, NULL); 351 prop = of_find_property(np, buf, NULL);
424 352
425 return prom_remove_property(np, prop); 353 return of_remove_property(np, prop);
426} 354}
427 355
428static int do_update_property(char *buf, size_t bufsize) 356static int do_update_property(char *buf, size_t bufsize)
429{ 357{
430 struct device_node *np; 358 struct device_node *np;
431 struct pSeries_reconfig_prop_update upd_value;
432 unsigned char *value; 359 unsigned char *value;
433 char *name, *end, *next_prop; 360 char *name, *end, *next_prop;
434 int rc, length; 361 int length;
435 struct property *newprop; 362 struct property *newprop;
436 buf = parse_node(buf, bufsize, &np); 363 buf = parse_node(buf, bufsize, &np);
437 end = buf + bufsize; 364 end = buf + bufsize;
@@ -453,41 +380,7 @@ static int do_update_property(char *buf, size_t bufsize)
453 if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size")) 380 if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size"))
454 slb_set_size(*(int *)value); 381 slb_set_size(*(int *)value);
455 382
456 upd_value.node = np; 383 return of_update_property(np, newprop);
457 upd_value.property = newprop;
458 pSeries_reconfig_notify(PSERIES_UPDATE_PROPERTY, &upd_value);
459
460 rc = prom_update_property(np, newprop);
461 if (rc)
462 return rc;
463
464 /* For memory under the ibm,dynamic-reconfiguration-memory node
465 * of the device tree, adding and removing memory is just an update
466 * to the ibm,dynamic-memory property instead of adding/removing a
467 * memory node in the device tree. For these cases we still need to
468 * involve the notifier chain.
469 */
470 if (!strcmp(name, "ibm,dynamic-memory")) {
471 int action;
472
473 next_prop = parse_next_property(next_prop, end, &name,
474 &length, &value);
475 if (!next_prop)
476 return -EINVAL;
477
478 if (!strcmp(name, "add"))
479 action = PSERIES_DRCONF_MEM_ADD;
480 else
481 action = PSERIES_DRCONF_MEM_REMOVE;
482
483 rc = pSeries_reconfig_notify(action, value);
484 if (rc) {
485 prom_update_property(np, newprop);
486 return rc;
487 }
488 }
489
490 return 0;
491} 384}
492 385
493/** 386/**
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index e3cb7ae61658..e1a5b8a32d25 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -40,6 +40,7 @@
40#include <linux/seq_file.h> 40#include <linux/seq_file.h>
41#include <linux/root_dev.h> 41#include <linux/root_dev.h>
42#include <linux/cpuidle.h> 42#include <linux/cpuidle.h>
43#include <linux/of.h>
43 44
44#include <asm/mmu.h> 45#include <asm/mmu.h>
45#include <asm/processor.h> 46#include <asm/processor.h>
@@ -63,7 +64,6 @@
63#include <asm/smp.h> 64#include <asm/smp.h>
64#include <asm/firmware.h> 65#include <asm/firmware.h>
65#include <asm/eeh.h> 66#include <asm/eeh.h>
66#include <asm/pSeries_reconfig.h>
67 67
68#include "plpar_wrappers.h" 68#include "plpar_wrappers.h"
69#include "pseries.h" 69#include "pseries.h"
@@ -258,7 +258,7 @@ static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long act
258 int err = NOTIFY_OK; 258 int err = NOTIFY_OK;
259 259
260 switch (action) { 260 switch (action) {
261 case PSERIES_RECONFIG_ADD: 261 case OF_RECONFIG_ATTACH_NODE:
262 pci = np->parent->data; 262 pci = np->parent->data;
263 if (pci) { 263 if (pci) {
264 update_dn_pci_info(np, pci->phb); 264 update_dn_pci_info(np, pci->phb);
@@ -389,7 +389,7 @@ static void __init pSeries_setup_arch(void)
389 /* Find and initialize PCI host bridges */ 389 /* Find and initialize PCI host bridges */
390 init_pci_config_tokens(); 390 init_pci_config_tokens();
391 find_and_init_phbs(); 391 find_and_init_phbs();
392 pSeries_reconfig_notifier_register(&pci_dn_reconfig_nb); 392 of_reconfig_notifier_register(&pci_dn_reconfig_nb);
393 393
394 pSeries_nvram_init(); 394 pSeries_nvram_init();
395 395
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 71706bc34a0d..9fc0a4941908 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -38,7 +38,6 @@
38#include <asm/cputable.h> 38#include <asm/cputable.h>
39#include <asm/firmware.h> 39#include <asm/firmware.h>
40#include <asm/rtas.h> 40#include <asm/rtas.h>
41#include <asm/pSeries_reconfig.h>
42#include <asm/mpic.h> 41#include <asm/mpic.h>
43#include <asm/vdso_datapage.h> 42#include <asm/vdso_datapage.h>
44#include <asm/cputhreads.h> 43#include <asm/cputhreads.h>
diff --git a/drivers/crypto/nx/nx-842.c b/drivers/crypto/nx/nx-842.c
index 0ce625738677..6c4c000671c5 100644
--- a/drivers/crypto/nx/nx-842.c
+++ b/drivers/crypto/nx/nx-842.c
@@ -28,7 +28,6 @@
28#include <linux/slab.h> 28#include <linux/slab.h>
29 29
30#include <asm/page.h> 30#include <asm/page.h>
31#include <asm/pSeries_reconfig.h>
32#include <asm/vio.h> 31#include <asm/vio.h>
33 32
34#include "nx_csbcpb.h" /* struct nx_csbcpb */ 33#include "nx_csbcpb.h" /* struct nx_csbcpb */
@@ -1014,26 +1013,23 @@ error_out:
1014 * NOTIFY_BAD encoded with error number on failure, use 1013 * NOTIFY_BAD encoded with error number on failure, use
1015 * notifier_to_errno() to decode this value 1014 * notifier_to_errno() to decode this value
1016 */ 1015 */
1017static int nx842_OF_notifier(struct notifier_block *np, 1016static int nx842_OF_notifier(struct notifier_block *np, unsigned long action,
1018 unsigned long action, 1017 void *update)
1019 void *update)
1020{ 1018{
1021 struct pSeries_reconfig_prop_update *upd; 1019 struct of_prop_reconfig *upd = update;
1022 struct nx842_devdata *local_devdata; 1020 struct nx842_devdata *local_devdata;
1023 struct device_node *node = NULL; 1021 struct device_node *node = NULL;
1024 1022
1025 upd = (struct pSeries_reconfig_prop_update *)update;
1026
1027 rcu_read_lock(); 1023 rcu_read_lock();
1028 local_devdata = rcu_dereference(devdata); 1024 local_devdata = rcu_dereference(devdata);
1029 if (local_devdata) 1025 if (local_devdata)
1030 node = local_devdata->dev->of_node; 1026 node = local_devdata->dev->of_node;
1031 1027
1032 if (local_devdata && 1028 if (local_devdata &&
1033 action == PSERIES_UPDATE_PROPERTY && 1029 action == OF_RECONFIG_UPDATE_PROPERTY &&
1034 !strcmp(upd->node->name, node->name)) { 1030 !strcmp(upd->dn->name, node->name)) {
1035 rcu_read_unlock(); 1031 rcu_read_unlock();
1036 nx842_OF_upd(upd->property); 1032 nx842_OF_upd(upd->prop);
1037 } else 1033 } else
1038 rcu_read_unlock(); 1034 rcu_read_unlock();
1039 1035
@@ -1182,7 +1178,7 @@ static int __init nx842_probe(struct vio_dev *viodev,
1182 synchronize_rcu(); 1178 synchronize_rcu();
1183 kfree(old_devdata); 1179 kfree(old_devdata);
1184 1180
1185 pSeries_reconfig_notifier_register(&nx842_of_nb); 1181 of_reconfig_notifier_register(&nx842_of_nb);
1186 1182
1187 ret = nx842_OF_upd(NULL); 1183 ret = nx842_OF_upd(NULL);
1188 if (ret && ret != -ENODEV) { 1184 if (ret && ret != -ENODEV) {
@@ -1228,7 +1224,7 @@ static int __exit nx842_remove(struct vio_dev *viodev)
1228 spin_lock_irqsave(&devdata_mutex, flags); 1224 spin_lock_irqsave(&devdata_mutex, flags);
1229 old_devdata = rcu_dereference_check(devdata, 1225 old_devdata = rcu_dereference_check(devdata,
1230 lockdep_is_held(&devdata_mutex)); 1226 lockdep_is_held(&devdata_mutex));
1231 pSeries_reconfig_notifier_unregister(&nx842_of_nb); 1227 of_reconfig_notifier_unregister(&nx842_of_nb);
1232 rcu_assign_pointer(devdata, NULL); 1228 rcu_assign_pointer(devdata, NULL);
1233 spin_unlock_irqrestore(&devdata_mutex, flags); 1229 spin_unlock_irqrestore(&devdata_mutex, flags);
1234 synchronize_rcu(); 1230 synchronize_rcu();
diff --git a/drivers/crypto/nx/nx.c b/drivers/crypto/nx/nx.c
index 638110efae9b..f7a8a16aa7d3 100644
--- a/drivers/crypto/nx/nx.c
+++ b/drivers/crypto/nx/nx.c
@@ -33,7 +33,6 @@
33#include <linux/scatterlist.h> 33#include <linux/scatterlist.h>
34#include <linux/device.h> 34#include <linux/device.h>
35#include <linux/of.h> 35#include <linux/of.h>
36#include <asm/pSeries_reconfig.h>
37#include <asm/hvcall.h> 36#include <asm/hvcall.h>
38#include <asm/vio.h> 37#include <asm/vio.h>
39 38
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index 7d5a6b40b31c..5b939509db3b 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -997,7 +997,7 @@ static struct smu_sdbp_header *smu_create_sdb_partition(int id)
997 "%02x !\n", id, hdr->id); 997 "%02x !\n", id, hdr->id);
998 goto failure; 998 goto failure;
999 } 999 }
1000 if (prom_add_property(smu->of_node, prop)) { 1000 if (of_add_property(smu->of_node, prop)) {
1001 printk(KERN_DEBUG "SMU: Failed creating sdb-partition-%02x " 1001 printk(KERN_DEBUG "SMU: Failed creating sdb-partition-%02x "
1002 "property !\n", id); 1002 "property !\n", id);
1003 goto failure; 1003 goto failure;
diff --git a/drivers/of/base.c b/drivers/of/base.c
index af3b22ac7627..02d94c4ea83c 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1028,13 +1028,36 @@ int of_parse_phandle_with_args(struct device_node *np, const char *list_name,
1028} 1028}
1029EXPORT_SYMBOL(of_parse_phandle_with_args); 1029EXPORT_SYMBOL(of_parse_phandle_with_args);
1030 1030
1031#if defined(CONFIG_OF_DYNAMIC)
1032static int of_property_notify(int action, struct device_node *np,
1033 struct property *prop)
1034{
1035 struct of_prop_reconfig pr;
1036
1037 pr.dn = np;
1038 pr.prop = prop;
1039 return of_reconfig_notify(action, &pr);
1040}
1041#else
1042static int of_property_notify(int action, struct device_node *np,
1043 struct property *prop)
1044{
1045 return 0;
1046}
1047#endif
1048
1031/** 1049/**
1032 * prom_add_property - Add a property to a node 1050 * of_add_property - Add a property to a node
1033 */ 1051 */
1034int prom_add_property(struct device_node *np, struct property *prop) 1052int of_add_property(struct device_node *np, struct property *prop)
1035{ 1053{
1036 struct property **next; 1054 struct property **next;
1037 unsigned long flags; 1055 unsigned long flags;
1056 int rc;
1057
1058 rc = of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop);
1059 if (rc)
1060 return rc;
1038 1061
1039 prop->next = NULL; 1062 prop->next = NULL;
1040 write_lock_irqsave(&devtree_lock, flags); 1063 write_lock_irqsave(&devtree_lock, flags);
@@ -1060,18 +1083,23 @@ int prom_add_property(struct device_node *np, struct property *prop)
1060} 1083}
1061 1084
1062/** 1085/**
1063 * prom_remove_property - Remove a property from a node. 1086 * of_remove_property - Remove a property from a node.
1064 * 1087 *
1065 * Note that we don't actually remove it, since we have given out 1088 * Note that we don't actually remove it, since we have given out
1066 * who-knows-how-many pointers to the data using get-property. 1089 * who-knows-how-many pointers to the data using get-property.
1067 * Instead we just move the property to the "dead properties" 1090 * Instead we just move the property to the "dead properties"
1068 * list, so it won't be found any more. 1091 * list, so it won't be found any more.
1069 */ 1092 */
1070int prom_remove_property(struct device_node *np, struct property *prop) 1093int of_remove_property(struct device_node *np, struct property *prop)
1071{ 1094{
1072 struct property **next; 1095 struct property **next;
1073 unsigned long flags; 1096 unsigned long flags;
1074 int found = 0; 1097 int found = 0;
1098 int rc;
1099
1100 rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop);
1101 if (rc)
1102 return rc;
1075 1103
1076 write_lock_irqsave(&devtree_lock, flags); 1104 write_lock_irqsave(&devtree_lock, flags);
1077 next = &np->properties; 1105 next = &np->properties;
@@ -1101,7 +1129,7 @@ int prom_remove_property(struct device_node *np, struct property *prop)
1101} 1129}
1102 1130
1103/* 1131/*
1104 * prom_update_property - Update a property in a node, if the property does 1132 * of_update_property - Update a property in a node, if the property does
1105 * not exist, add it. 1133 * not exist, add it.
1106 * 1134 *
1107 * Note that we don't actually remove it, since we have given out 1135 * Note that we don't actually remove it, since we have given out
@@ -1109,19 +1137,22 @@ int prom_remove_property(struct device_node *np, struct property *prop)
1109 * Instead we just move the property to the "dead properties" list, 1137 * Instead we just move the property to the "dead properties" list,
1110 * and add the new property to the property list 1138 * and add the new property to the property list
1111 */ 1139 */
1112int prom_update_property(struct device_node *np, 1140int of_update_property(struct device_node *np, struct property *newprop)
1113 struct property *newprop)
1114{ 1141{
1115 struct property **next, *oldprop; 1142 struct property **next, *oldprop;
1116 unsigned long flags; 1143 unsigned long flags;
1117 int found = 0; 1144 int rc, found = 0;
1145
1146 rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop);
1147 if (rc)
1148 return rc;
1118 1149
1119 if (!newprop->name) 1150 if (!newprop->name)
1120 return -EINVAL; 1151 return -EINVAL;
1121 1152
1122 oldprop = of_find_property(np, newprop->name, NULL); 1153 oldprop = of_find_property(np, newprop->name, NULL);
1123 if (!oldprop) 1154 if (!oldprop)
1124 return prom_add_property(np, newprop); 1155 return of_add_property(np, newprop);
1125 1156
1126 write_lock_irqsave(&devtree_lock, flags); 1157 write_lock_irqsave(&devtree_lock, flags);
1127 next = &np->properties; 1158 next = &np->properties;
@@ -1160,12 +1191,53 @@ int prom_update_property(struct device_node *np,
1160 * device tree nodes. 1191 * device tree nodes.
1161 */ 1192 */
1162 1193
1194static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);
1195
1196int of_reconfig_notifier_register(struct notifier_block *nb)
1197{
1198 return blocking_notifier_chain_register(&of_reconfig_chain, nb);
1199}
1200
1201int of_reconfig_notifier_unregister(struct notifier_block *nb)
1202{
1203 return blocking_notifier_chain_unregister(&of_reconfig_chain, nb);
1204}
1205
1206int of_reconfig_notify(unsigned long action, void *p)
1207{
1208 int rc;
1209
1210 rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p);
1211 return notifier_to_errno(rc);
1212}
1213
1214#ifdef CONFIG_PROC_DEVICETREE
1215static void of_add_proc_dt_entry(struct device_node *dn)
1216{
1217 struct proc_dir_entry *ent;
1218
1219 ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde);
1220 if (ent)
1221 proc_device_tree_add_node(dn, ent);
1222}
1223#else
1224static void of_add_proc_dt_entry(struct device_node *dn)
1225{
1226 return;
1227}
1228#endif
1229
1163/** 1230/**
1164 * of_attach_node - Plug a device node into the tree and global list. 1231 * of_attach_node - Plug a device node into the tree and global list.
1165 */ 1232 */
1166void of_attach_node(struct device_node *np) 1233int of_attach_node(struct device_node *np)
1167{ 1234{
1168 unsigned long flags; 1235 unsigned long flags;
1236 int rc;
1237
1238 rc = of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np);
1239 if (rc)
1240 return rc;
1169 1241
1170 write_lock_irqsave(&devtree_lock, flags); 1242 write_lock_irqsave(&devtree_lock, flags);
1171 np->sibling = np->parent->child; 1243 np->sibling = np->parent->child;
@@ -1173,24 +1245,61 @@ void of_attach_node(struct device_node *np)
1173 np->parent->child = np; 1245 np->parent->child = np;
1174 allnodes = np; 1246 allnodes = np;
1175 write_unlock_irqrestore(&devtree_lock, flags); 1247 write_unlock_irqrestore(&devtree_lock, flags);
1248
1249 of_add_proc_dt_entry(np);
1250 return 0;
1176} 1251}
1177 1252
1253#ifdef CONFIG_PROC_DEVICETREE
1254static void of_remove_proc_dt_entry(struct device_node *dn)
1255{
1256 struct device_node *parent = dn->parent;
1257 struct property *prop = dn->properties;
1258
1259 while (prop) {
1260 remove_proc_entry(prop->name, dn->pde);
1261 prop = prop->next;
1262 }
1263
1264 if (dn->pde)
1265 remove_proc_entry(dn->pde->name, parent->pde);
1266}
1267#else
1268static void of_remove_proc_dt_entry(struct device_node *dn)
1269{
1270 return;
1271}
1272#endif
1273
1178/** 1274/**
1179 * of_detach_node - "Unplug" a node from the device tree. 1275 * of_detach_node - "Unplug" a node from the device tree.
1180 * 1276 *
1181 * The caller must hold a reference to the node. The memory associated with 1277 * The caller must hold a reference to the node. The memory associated with
1182 * the node is not freed until its refcount goes to zero. 1278 * the node is not freed until its refcount goes to zero.
1183 */ 1279 */
1184void of_detach_node(struct device_node *np) 1280int of_detach_node(struct device_node *np)
1185{ 1281{
1186 struct device_node *parent; 1282 struct device_node *parent;
1187 unsigned long flags; 1283 unsigned long flags;
1284 int rc = 0;
1285
1286 rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
1287 if (rc)
1288 return rc;
1188 1289
1189 write_lock_irqsave(&devtree_lock, flags); 1290 write_lock_irqsave(&devtree_lock, flags);
1190 1291
1292 if (of_node_check_flag(np, OF_DETACHED)) {
1293 /* someone already detached it */
1294 write_unlock_irqrestore(&devtree_lock, flags);
1295 return rc;
1296 }
1297
1191 parent = np->parent; 1298 parent = np->parent;
1192 if (!parent) 1299 if (!parent) {
1193 goto out_unlock; 1300 write_unlock_irqrestore(&devtree_lock, flags);
1301 return rc;
1302 }
1194 1303
1195 if (allnodes == np) 1304 if (allnodes == np)
1196 allnodes = np->allnext; 1305 allnodes = np->allnext;
@@ -1215,9 +1324,10 @@ void of_detach_node(struct device_node *np)
1215 } 1324 }
1216 1325
1217 of_node_set_flag(np, OF_DETACHED); 1326 of_node_set_flag(np, OF_DETACHED);
1218
1219out_unlock:
1220 write_unlock_irqrestore(&devtree_lock, flags); 1327 write_unlock_irqrestore(&devtree_lock, flags);
1328
1329 of_remove_proc_dt_entry(np);
1330 return rc;
1221} 1331}
1222#endif /* defined(CONFIG_OF_DYNAMIC) */ 1332#endif /* defined(CONFIG_OF_DYNAMIC) */
1223 1333
diff --git a/include/linux/of.h b/include/linux/of.h
index 72843b72a2b2..a093b2fe5dfb 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -22,6 +22,7 @@
22#include <linux/mod_devicetable.h> 22#include <linux/mod_devicetable.h>
23#include <linux/spinlock.h> 23#include <linux/spinlock.h>
24#include <linux/topology.h> 24#include <linux/topology.h>
25#include <linux/notifier.h>
25 26
26#include <asm/byteorder.h> 27#include <asm/byteorder.h>
27#include <asm/errno.h> 28#include <asm/errno.h>
@@ -267,16 +268,28 @@ extern int of_alias_get_id(struct device_node *np, const char *stem);
267 268
268extern int of_machine_is_compatible(const char *compat); 269extern int of_machine_is_compatible(const char *compat);
269 270
270extern int prom_add_property(struct device_node* np, struct property* prop); 271extern int of_add_property(struct device_node *np, struct property *prop);
271extern int prom_remove_property(struct device_node *np, struct property *prop); 272extern int of_remove_property(struct device_node *np, struct property *prop);
272extern int prom_update_property(struct device_node *np, 273extern int of_update_property(struct device_node *np, struct property *newprop);
273 struct property *newprop);
274 274
275#if defined(CONFIG_OF_DYNAMIC)
276/* For updating the device tree at runtime */ 275/* For updating the device tree at runtime */
277extern void of_attach_node(struct device_node *); 276#define OF_RECONFIG_ATTACH_NODE 0x0001
278extern void of_detach_node(struct device_node *); 277#define OF_RECONFIG_DETACH_NODE 0x0002
279#endif 278#define OF_RECONFIG_ADD_PROPERTY 0x0003
279#define OF_RECONFIG_REMOVE_PROPERTY 0x0004
280#define OF_RECONFIG_UPDATE_PROPERTY 0x0005
281
282struct of_prop_reconfig {
283 struct device_node *dn;
284 struct property *prop;
285};
286
287extern int of_reconfig_notifier_register(struct notifier_block *);
288extern int of_reconfig_notifier_unregister(struct notifier_block *);
289extern int of_reconfig_notify(unsigned long, void *);
290
291extern int of_attach_node(struct device_node *);
292extern int of_detach_node(struct device_node *);
280 293
281#define of_match_ptr(_ptr) (_ptr) 294#define of_match_ptr(_ptr) (_ptr)
282 295