Commit de1bb03af7f4dde8e0e823629909d179fed4beff
Exists in
master
and in
20 other branches
Merge branch 'dt' into next
Showing 25 changed files Side-by-side Diff
- arch/arm/mach-mxs/mach-mxs.c
- arch/powerpc/include/asm/pSeries_reconfig.h
- arch/powerpc/include/asm/prom.h
- arch/powerpc/include/asm/rtas.h
- arch/powerpc/kernel/machine_kexec.c
- arch/powerpc/kernel/machine_kexec_64.c
- arch/powerpc/kernel/pci_32.c
- arch/powerpc/kernel/prom.c
- arch/powerpc/kernel/rtas.c
- arch/powerpc/mm/numa.c
- arch/powerpc/platforms/85xx/p1022_ds.c
- arch/powerpc/platforms/ps3/os-area.c
- arch/powerpc/platforms/pseries/dlpar.c
- arch/powerpc/platforms/pseries/hotplug-cpu.c
- arch/powerpc/platforms/pseries/hotplug-memory.c
- arch/powerpc/platforms/pseries/iommu.c
- arch/powerpc/platforms/pseries/mobility.c
- arch/powerpc/platforms/pseries/reconfig.c
- arch/powerpc/platforms/pseries/setup.c
- arch/powerpc/platforms/pseries/smp.c
- drivers/crypto/nx/nx-842.c
- drivers/crypto/nx/nx.c
- drivers/macintosh/smu.c
- drivers/of/base.c
- include/linux/of.h
arch/arm/mach-mxs/mach-mxs.c
arch/powerpc/include/asm/pSeries_reconfig.h
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 | - */ | |
24 | -struct pSeries_reconfig_prop_update { | |
25 | - struct device_node *node; | |
26 | - struct property *property; | |
27 | -}; | |
28 | - | |
29 | -#ifdef CONFIG_PPC_PSERIES | |
30 | -extern int pSeries_reconfig_notifier_register(struct notifier_block *); | |
31 | -extern void pSeries_reconfig_notifier_unregister(struct notifier_block *); | |
32 | -extern 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 */ | |
35 | -extern void pSeries_coalesce_init(void); | |
36 | -#else /* !CONFIG_PPC_PSERIES */ | |
37 | -static inline int pSeries_reconfig_notifier_register(struct notifier_block *nb) | |
38 | -{ | |
39 | - return 0; | |
40 | -} | |
41 | -static inline void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) { } | |
42 | -static inline void pSeries_coalesce_init(void) { } | |
43 | -#endif /* CONFIG_PPC_PSERIES */ | |
44 | - | |
45 | - | |
46 | -#endif /* __KERNEL__ */ | |
47 | -#endif /* _PPC64_PSERIES_RECONFIG_H */ |
arch/powerpc/include/asm/prom.h
... | ... | @@ -58,6 +58,22 @@ |
58 | 58 | |
59 | 59 | extern 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 | + */ | |
65 | +struct 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 | 77 | /* These includes are put at the bottom because they may contain things |
62 | 78 | * that are overridden by this file. Ideally they shouldn't be included |
63 | 79 | * by this file, but there are a bunch of .c files that currently depend |
arch/powerpc/include/asm/rtas.h
... | ... | @@ -353,8 +353,13 @@ |
353 | 353 | return 1; |
354 | 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 */ | |
359 | +extern void pSeries_coalesce_init(void); | |
356 | 360 | #else |
357 | 361 | static inline int page_is_rtas_user_buf(unsigned long pfn) { return 0;} |
362 | +static inline void pSeries_coalesce_init(void) { } | |
358 | 363 | #endif |
359 | 364 | |
360 | 365 | extern int call_rtas(const char *, int, int, unsigned long *, ...); |
arch/powerpc/kernel/machine_kexec.c
... | ... | @@ -218,23 +218,23 @@ |
218 | 218 | * be sure what's in them, so remove them. */ |
219 | 219 | prop = of_find_property(node, "linux,crashkernel-base", NULL); |
220 | 220 | if (prop) |
221 | - prom_remove_property(node, prop); | |
221 | + of_remove_property(node, prop); | |
222 | 222 | |
223 | 223 | prop = of_find_property(node, "linux,crashkernel-size", NULL); |
224 | 224 | if (prop) |
225 | - prom_remove_property(node, prop); | |
225 | + of_remove_property(node, prop); | |
226 | 226 | |
227 | 227 | if (crashk_res.start != 0) { |
228 | - prom_add_property(node, &crashk_base_prop); | |
228 | + of_add_property(node, &crashk_base_prop); | |
229 | 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 | 234 | * memory_limit is required by the kexec-tools to limit the |
235 | 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 | |
240 | 240 | static int __init kexec_setup(void) |
241 | 241 | |
... | ... | @@ -249,11 +249,11 @@ |
249 | 249 | /* remove any stale properties so ours can be found */ |
250 | 250 | prop = of_find_property(node, kernel_end_prop.name, NULL); |
251 | 251 | if (prop) |
252 | - prom_remove_property(node, prop); | |
252 | + of_remove_property(node, prop); | |
253 | 253 | |
254 | 254 | /* information needed by userspace when using default_machine_kexec */ |
255 | 255 | kernel_end = __pa(_end); |
256 | - prom_add_property(node, &kernel_end_prop); | |
256 | + of_add_property(node, &kernel_end_prop); | |
257 | 257 | |
258 | 258 | export_crashk_values(node); |
259 | 259 |
arch/powerpc/kernel/machine_kexec_64.c
... | ... | @@ -389,14 +389,14 @@ |
389 | 389 | /* remove any stale propertys so ours can be found */ |
390 | 390 | prop = of_find_property(node, htab_base_prop.name, NULL); |
391 | 391 | if (prop) |
392 | - prom_remove_property(node, prop); | |
392 | + of_remove_property(node, prop); | |
393 | 393 | prop = of_find_property(node, htab_size_prop.name, NULL); |
394 | 394 | if (prop) |
395 | - prom_remove_property(node, prop); | |
395 | + of_remove_property(node, prop); | |
396 | 396 | |
397 | 397 | htab_base = __pa(htab_address); |
398 | - prom_add_property(node, &htab_base_prop); | |
399 | - prom_add_property(node, &htab_size_prop); | |
398 | + of_add_property(node, &htab_base_prop); | |
399 | + of_add_property(node, &htab_size_prop); | |
400 | 400 | |
401 | 401 | of_node_put(node); |
402 | 402 | return 0; |
arch/powerpc/kernel/pci_32.c
arch/powerpc/kernel/prom.c
... | ... | @@ -32,6 +32,7 @@ |
32 | 32 | #include <linux/debugfs.h> |
33 | 33 | #include <linux/irq.h> |
34 | 34 | #include <linux/memblock.h> |
35 | +#include <linux/of.h> | |
35 | 36 | |
36 | 37 | #include <asm/prom.h> |
37 | 38 | #include <asm/rtas.h> |
... | ... | @@ -49,7 +50,6 @@ |
49 | 50 | #include <asm/btext.h> |
50 | 51 | #include <asm/sections.h> |
51 | 52 | #include <asm/machdep.h> |
52 | -#include <asm/pSeries_reconfig.h> | |
53 | 53 | #include <asm/pci-bridge.h> |
54 | 54 | #include <asm/kexec.h> |
55 | 55 | #include <asm/opal.h> |
... | ... | @@ -803,7 +803,7 @@ |
803 | 803 | int err; |
804 | 804 | |
805 | 805 | switch (action) { |
806 | - case PSERIES_RECONFIG_ADD: | |
806 | + case OF_RECONFIG_ATTACH_NODE: | |
807 | 807 | err = of_finish_dynamic_node(node); |
808 | 808 | if (err < 0) |
809 | 809 | printk(KERN_ERR "finish_node returned %d\n", err); |
... | ... | @@ -822,7 +822,7 @@ |
822 | 822 | |
823 | 823 | static 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 | 827 | __initcall(prom_reconfig_setup); |
828 | 828 | #endif |
arch/powerpc/kernel/rtas.c
arch/powerpc/mm/numa.c
... | ... | @@ -399,18 +399,6 @@ |
399 | 399 | return result; |
400 | 400 | } |
401 | 401 | |
402 | -struct 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 | 403 | * Read the next memblock list entry from the ibm,dynamic-memory property |
416 | 404 | * and return the information in the provided of_drconf_cell structure. |
arch/powerpc/platforms/85xx/p1022_ds.c
... | ... | @@ -539,7 +539,7 @@ |
539 | 539 | }; |
540 | 540 | |
541 | 541 | /* |
542 | - * prom_update_property() is called before | |
542 | + * of_update_property() is called before | |
543 | 543 | * kmalloc() is available, so the 'new' object |
544 | 544 | * should be allocated in the global area. |
545 | 545 | * The easiest way is to do that is to |
... | ... | @@ -548,7 +548,7 @@ |
548 | 548 | */ |
549 | 549 | pr_info("p1022ds: disabling %s node", |
550 | 550 | np2->full_name); |
551 | - prom_update_property(np2, &nor_status); | |
551 | + of_update_property(np2, &nor_status); | |
552 | 552 | of_node_put(np2); |
553 | 553 | } |
554 | 554 | |
... | ... | @@ -564,7 +564,7 @@ |
564 | 564 | |
565 | 565 | pr_info("p1022ds: disabling %s node", |
566 | 566 | np2->full_name); |
567 | - prom_update_property(np2, &nand_status); | |
567 | + of_update_property(np2, &nand_status); | |
568 | 568 | of_node_put(np2); |
569 | 569 | } |
570 | 570 |
arch/powerpc/platforms/ps3/os-area.c
... | ... | @@ -280,13 +280,13 @@ |
280 | 280 | |
281 | 281 | if (tmp) { |
282 | 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 | 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 | 290 | __LINE__); |
291 | 291 | } |
292 | 292 |
arch/powerpc/platforms/pseries/dlpar.c
... | ... | @@ -13,17 +13,16 @@ |
13 | 13 | #include <linux/kernel.h> |
14 | 14 | #include <linux/kref.h> |
15 | 15 | #include <linux/notifier.h> |
16 | -#include <linux/proc_fs.h> | |
17 | 16 | #include <linux/spinlock.h> |
18 | 17 | #include <linux/cpu.h> |
19 | 18 | #include <linux/slab.h> |
19 | +#include <linux/of.h> | |
20 | 20 | #include "offline_states.h" |
21 | 21 | |
22 | 22 | #include <asm/prom.h> |
23 | 23 | #include <asm/machdep.h> |
24 | 24 | #include <asm/uaccess.h> |
25 | 25 | #include <asm/rtas.h> |
26 | -#include <asm/pSeries_reconfig.h> | |
27 | 26 | |
28 | 27 | struct cc_workarea { |
29 | 28 | u32 drc_index; |
... | ... | @@ -255,9 +254,6 @@ |
255 | 254 | |
256 | 255 | int dlpar_attach_node(struct device_node *dn) |
257 | 256 | { |
258 | -#ifdef CONFIG_PROC_DEVICETREE | |
259 | - struct proc_dir_entry *ent; | |
260 | -#endif | |
261 | 257 | int rc; |
262 | 258 | |
263 | 259 | of_node_set_flag(dn, OF_DYNAMIC); |
264 | 260 | |
265 | 261 | |
266 | 262 | |
267 | 263 | |
268 | 264 | |
... | ... | @@ -266,44 +262,26 @@ |
266 | 262 | if (!dn->parent) |
267 | 263 | return -ENOMEM; |
268 | 264 | |
269 | - rc = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, dn); | |
265 | + rc = of_attach_node(dn); | |
270 | 266 | if (rc) { |
271 | 267 | printk(KERN_ERR "Failed to add device node %s\n", |
272 | 268 | dn->full_name); |
273 | 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 | 272 | of_node_put(dn->parent); |
285 | 273 | return 0; |
286 | 274 | } |
287 | 275 | |
288 | 276 | int dlpar_detach_node(struct device_node *dn) |
289 | 277 | { |
290 | -#ifdef CONFIG_PROC_DEVICETREE | |
291 | - struct device_node *parent = dn->parent; | |
292 | - struct property *prop = dn->properties; | |
278 | + int rc; | |
293 | 279 | |
294 | - while (prop) { | |
295 | - remove_proc_entry(prop->name, dn->pde); | |
296 | - prop = prop->next; | |
297 | - } | |
280 | + rc = of_detach_node(dn); | |
281 | + if (rc) | |
282 | + return rc; | |
298 | 283 | |
299 | - if (dn->pde) | |
300 | - remove_proc_entry(dn->pde->name, parent->pde); | |
301 | -#endif | |
302 | - | |
303 | - pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, dn); | |
304 | - of_detach_node(dn); | |
305 | 284 | of_node_put(dn); /* Must decrement the refcount */ |
306 | - | |
307 | 285 | return 0; |
308 | 286 | } |
309 | 287 |
arch/powerpc/platforms/pseries/hotplug-cpu.c
... | ... | @@ -23,12 +23,12 @@ |
23 | 23 | #include <linux/delay.h> |
24 | 24 | #include <linux/sched.h> /* for idle_task_exit */ |
25 | 25 | #include <linux/cpu.h> |
26 | +#include <linux/of.h> | |
26 | 27 | #include <asm/prom.h> |
27 | 28 | #include <asm/rtas.h> |
28 | 29 | #include <asm/firmware.h> |
29 | 30 | #include <asm/machdep.h> |
30 | 31 | #include <asm/vdso_datapage.h> |
31 | -#include <asm/pSeries_reconfig.h> | |
32 | 32 | #include <asm/xics.h> |
33 | 33 | #include "plpar_wrappers.h" |
34 | 34 | #include "offline_states.h" |
35 | 35 | |
... | ... | @@ -333,10 +333,10 @@ |
333 | 333 | int err = 0; |
334 | 334 | |
335 | 335 | switch (action) { |
336 | - case PSERIES_RECONFIG_ADD: | |
336 | + case OF_RECONFIG_ATTACH_NODE: | |
337 | 337 | err = pseries_add_processor(node); |
338 | 338 | break; |
339 | - case PSERIES_RECONFIG_REMOVE: | |
339 | + case OF_RECONFIG_DETACH_NODE: | |
340 | 340 | pseries_remove_processor(node); |
341 | 341 | break; |
342 | 342 | } |
... | ... | @@ -399,7 +399,7 @@ |
399 | 399 | |
400 | 400 | /* Processors can be added/removed only on LPAR */ |
401 | 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 | 403 | cpu_maps_update_begin(); |
404 | 404 | if (cede_offline_enabled && parse_cede_parameters() == 0) { |
405 | 405 | default_offline_state = CPU_STATE_INACTIVE; |
arch/powerpc/platforms/pseries/hotplug-memory.c
... | ... | @@ -16,7 +16,6 @@ |
16 | 16 | |
17 | 17 | #include <asm/firmware.h> |
18 | 18 | #include <asm/machdep.h> |
19 | -#include <asm/pSeries_reconfig.h> | |
20 | 19 | #include <asm/sparsemem.h> |
21 | 20 | |
22 | 21 | static unsigned long get_memblock_size(void) |
23 | 22 | |
24 | 23 | |
25 | 24 | |
26 | 25 | |
27 | 26 | |
28 | 27 | |
29 | 28 | |
30 | 29 | |
... | ... | @@ -187,42 +186,69 @@ |
187 | 186 | return (ret < 0) ? -EINVAL : 0; |
188 | 187 | } |
189 | 188 | |
190 | -static int pseries_drconf_memory(unsigned long *base, unsigned int action) | |
189 | +static int pseries_update_drconf_memory(struct of_prop_reconfig *pr) | |
191 | 190 | { |
191 | + struct of_drconf_cell *new_drmem, *old_drmem; | |
192 | 192 | unsigned long memblock_size; |
193 | - int rc; | |
193 | + u32 entries; | |
194 | + u32 *p; | |
195 | + int i, rc = -EINVAL; | |
194 | 196 | |
195 | 197 | memblock_size = get_memblock_size(); |
196 | 198 | if (!memblock_size) |
197 | 199 | return -EINVAL; |
198 | 200 | |
199 | - if (action == PSERIES_DRCONF_MEM_ADD) { | |
200 | - rc = memblock_add(*base, memblock_size); | |
201 | - rc = (rc < 0) ? -EINVAL : 0; | |
202 | - } else if (action == PSERIES_DRCONF_MEM_REMOVE) { | |
203 | - rc = pseries_remove_memblock(*base, memblock_size); | |
204 | - } else { | |
205 | - rc = -EINVAL; | |
201 | + p = (u32 *)of_get_property(pr->dn, "ibm,dynamic-memory", NULL); | |
202 | + if (!p) | |
203 | + return -EINVAL; | |
204 | + | |
205 | + /* The first int of the property is the number of lmb's described | |
206 | + * by the property. This is followed by an array of of_drconf_cell | |
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 | 232 | return rc; |
209 | 233 | } |
210 | 234 | |
211 | 235 | static 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 | 239 | int err = 0; |
215 | 240 | |
216 | 241 | switch (action) { |
217 | - case PSERIES_RECONFIG_ADD: | |
242 | + case OF_RECONFIG_ATTACH_NODE: | |
218 | 243 | err = pseries_add_memory(node); |
219 | 244 | break; |
220 | - case PSERIES_RECONFIG_REMOVE: | |
245 | + case OF_RECONFIG_DETACH_NODE: | |
221 | 246 | err = pseries_remove_memory(node); |
222 | 247 | break; |
223 | - case PSERIES_DRCONF_MEM_ADD: | |
224 | - case PSERIES_DRCONF_MEM_REMOVE: | |
225 | - err = pseries_drconf_memory(node, action); | |
248 | + case OF_RECONFIG_UPDATE_PROPERTY: | |
249 | + pr = (struct of_prop_reconfig *)node; | |
250 | + if (!strcmp(pr->prop->name, "ibm,dynamic-memory")) | |
251 | + err = pseries_update_drconf_memory(pr); | |
226 | 252 | break; |
227 | 253 | } |
228 | 254 | return notifier_from_errno(err); |
... | ... | @@ -235,7 +261,7 @@ |
235 | 261 | static int __init pseries_memory_hotplug_init(void) |
236 | 262 | { |
237 | 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 | 266 | return 0; |
241 | 267 | } |
arch/powerpc/platforms/pseries/iommu.c
... | ... | @@ -36,13 +36,13 @@ |
36 | 36 | #include <linux/dma-mapping.h> |
37 | 37 | #include <linux/crash_dump.h> |
38 | 38 | #include <linux/memory.h> |
39 | +#include <linux/of.h> | |
39 | 40 | #include <asm/io.h> |
40 | 41 | #include <asm/prom.h> |
41 | 42 | #include <asm/rtas.h> |
42 | 43 | #include <asm/iommu.h> |
43 | 44 | #include <asm/pci-bridge.h> |
44 | 45 | #include <asm/machdep.h> |
45 | -#include <asm/pSeries_reconfig.h> | |
46 | 46 | #include <asm/firmware.h> |
47 | 47 | #include <asm/tce.h> |
48 | 48 | #include <asm/ppc-pci.h> |
... | ... | @@ -760,7 +760,7 @@ |
760 | 760 | __remove_ddw(np, ddw_avail, liobn); |
761 | 761 | |
762 | 762 | delprop: |
763 | - ret = prom_remove_property(np, win64); | |
763 | + ret = of_remove_property(np, win64); | |
764 | 764 | if (ret) |
765 | 765 | pr_warning("%s: failed to remove direct window property: %d\n", |
766 | 766 | np->full_name, ret); |
... | ... | @@ -1070,7 +1070,7 @@ |
1070 | 1070 | goto out_free_window; |
1071 | 1071 | } |
1072 | 1072 | |
1073 | - ret = prom_add_property(pdn, win64); | |
1073 | + ret = of_add_property(pdn, win64); | |
1074 | 1074 | if (ret) { |
1075 | 1075 | dev_err(&dev->dev, "unable to add dma window property for %s: %d", |
1076 | 1076 | pdn->full_name, ret); |
... | ... | @@ -1294,7 +1294,7 @@ |
1294 | 1294 | struct direct_window *window; |
1295 | 1295 | |
1296 | 1296 | switch (action) { |
1297 | - case PSERIES_RECONFIG_REMOVE: | |
1297 | + case OF_RECONFIG_DETACH_NODE: | |
1298 | 1298 | if (pci && pci->iommu_table) |
1299 | 1299 | iommu_free_table(pci->iommu_table, np->full_name); |
1300 | 1300 | |
... | ... | @@ -1357,7 +1357,7 @@ |
1357 | 1357 | } |
1358 | 1358 | |
1359 | 1359 | |
1360 | - pSeries_reconfig_notifier_register(&iommu_reconfig_nb); | |
1360 | + of_reconfig_notifier_register(&iommu_reconfig_nb); | |
1361 | 1361 | register_memory_notifier(&iommu_mem_nb); |
1362 | 1362 | |
1363 | 1363 | set_pci_dma_ops(&dma_iommu_ops); |
arch/powerpc/platforms/pseries/mobility.c
... | ... | @@ -116,7 +116,7 @@ |
116 | 116 | } |
117 | 117 | |
118 | 118 | if (!more) { |
119 | - prom_update_property(dn, new_prop); | |
119 | + of_update_property(dn, new_prop); | |
120 | 120 | new_prop = NULL; |
121 | 121 | } |
122 | 122 | |
... | ... | @@ -172,7 +172,7 @@ |
172 | 172 | |
173 | 173 | case 0x80000000: |
174 | 174 | prop = of_find_property(dn, prop_name, NULL); |
175 | - prom_remove_property(dn, prop); | |
175 | + of_remove_property(dn, prop); | |
176 | 176 | prop = NULL; |
177 | 177 | break; |
178 | 178 |
arch/powerpc/platforms/pseries/reconfig.c
... | ... | @@ -16,55 +16,13 @@ |
16 | 16 | #include <linux/notifier.h> |
17 | 17 | #include <linux/proc_fs.h> |
18 | 18 | #include <linux/slab.h> |
19 | +#include <linux/of.h> | |
19 | 20 | |
20 | 21 | #include <asm/prom.h> |
21 | 22 | #include <asm/machdep.h> |
22 | 23 | #include <asm/uaccess.h> |
23 | -#include <asm/pSeries_reconfig.h> | |
24 | 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 | - */ | |
35 | -static 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 | - | |
44 | -static 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 */ | |
57 | -static void add_node_proc_entries(struct device_node *np) | |
58 | -{ | |
59 | - return; | |
60 | -} | |
61 | - | |
62 | -static void remove_node_proc_entries(struct device_node *np) | |
63 | -{ | |
64 | - return; | |
65 | -} | |
66 | -#endif /* CONFIG_PROC_DEVICETREE */ | |
67 | - | |
68 | 26 | /** |
69 | 27 | * derive_parent - basically like dirname(1) |
70 | 28 | * @path: the full_name of a node to be added to the tree |
... | ... | @@ -97,28 +55,6 @@ |
97 | 55 | return parent; |
98 | 56 | } |
99 | 57 | |
100 | -static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain); | |
101 | - | |
102 | -int pSeries_reconfig_notifier_register(struct notifier_block *nb) | |
103 | -{ | |
104 | - return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb); | |
105 | -} | |
106 | -EXPORT_SYMBOL_GPL(pSeries_reconfig_notifier_register); | |
107 | - | |
108 | -void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) | |
109 | -{ | |
110 | - blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb); | |
111 | -} | |
112 | -EXPORT_SYMBOL_GPL(pSeries_reconfig_notifier_unregister); | |
113 | - | |
114 | -int 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 | - | |
122 | 58 | static int pSeries_reconfig_add_node(const char *path, struct property *proplist) |
123 | 59 | { |
124 | 60 | struct device_node *np; |
125 | 61 | |
... | ... | @@ -142,16 +78,12 @@ |
142 | 78 | goto out_err; |
143 | 79 | } |
144 | 80 | |
145 | - err = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, np); | |
81 | + err = of_attach_node(np); | |
146 | 82 | if (err) { |
147 | 83 | printk(KERN_ERR "Failed to add device node %s\n", path); |
148 | 84 | goto out_err; |
149 | 85 | } |
150 | 86 | |
151 | - of_attach_node(np); | |
152 | - | |
153 | - add_node_proc_entries(np); | |
154 | - | |
155 | 87 | of_node_put(np->parent); |
156 | 88 | |
157 | 89 | return 0; |
158 | 90 | |
... | ... | @@ -179,11 +111,7 @@ |
179 | 111 | return -EBUSY; |
180 | 112 | } |
181 | 113 | |
182 | - remove_node_proc_entries(np); | |
183 | - | |
184 | - pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, np); | |
185 | 114 | of_detach_node(np); |
186 | - | |
187 | 115 | of_node_put(parent); |
188 | 116 | of_node_put(np); /* Must decrement the refcount */ |
189 | 117 | return 0; |
... | ... | @@ -398,7 +326,7 @@ |
398 | 326 | if (!prop) |
399 | 327 | return -ENOMEM; |
400 | 328 | |
401 | - prom_add_property(np, prop); | |
329 | + of_add_property(np, prop); | |
402 | 330 | |
403 | 331 | return 0; |
404 | 332 | } |
405 | 333 | |
406 | 334 | |
... | ... | @@ -422,16 +350,15 @@ |
422 | 350 | |
423 | 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 | |
428 | 356 | static int do_update_property(char *buf, size_t bufsize) |
429 | 357 | { |
430 | 358 | struct device_node *np; |
431 | - struct pSeries_reconfig_prop_update upd_value; | |
432 | 359 | unsigned char *value; |
433 | 360 | char *name, *end, *next_prop; |
434 | - int rc, length; | |
361 | + int length; | |
435 | 362 | struct property *newprop; |
436 | 363 | buf = parse_node(buf, bufsize, &np); |
437 | 364 | end = buf + bufsize; |
... | ... | @@ -453,41 +380,7 @@ |
453 | 380 | if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size")) |
454 | 381 | slb_set_size(*(int *)value); |
455 | 382 | |
456 | - upd_value.node = np; | |
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; | |
383 | + return of_update_property(np, newprop); | |
491 | 384 | } |
492 | 385 | |
493 | 386 | /** |
arch/powerpc/platforms/pseries/setup.c
... | ... | @@ -40,6 +40,7 @@ |
40 | 40 | #include <linux/seq_file.h> |
41 | 41 | #include <linux/root_dev.h> |
42 | 42 | #include <linux/cpuidle.h> |
43 | +#include <linux/of.h> | |
43 | 44 | |
44 | 45 | #include <asm/mmu.h> |
45 | 46 | #include <asm/processor.h> |
... | ... | @@ -63,7 +64,6 @@ |
63 | 64 | #include <asm/smp.h> |
64 | 65 | #include <asm/firmware.h> |
65 | 66 | #include <asm/eeh.h> |
66 | -#include <asm/pSeries_reconfig.h> | |
67 | 67 | |
68 | 68 | #include "plpar_wrappers.h" |
69 | 69 | #include "pseries.h" |
... | ... | @@ -258,7 +258,7 @@ |
258 | 258 | int err = NOTIFY_OK; |
259 | 259 | |
260 | 260 | switch (action) { |
261 | - case PSERIES_RECONFIG_ADD: | |
261 | + case OF_RECONFIG_ATTACH_NODE: | |
262 | 262 | pci = np->parent->data; |
263 | 263 | if (pci) { |
264 | 264 | update_dn_pci_info(np, pci->phb); |
... | ... | @@ -389,7 +389,7 @@ |
389 | 389 | /* Find and initialize PCI host bridges */ |
390 | 390 | init_pci_config_tokens(); |
391 | 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 | 394 | pSeries_nvram_init(); |
395 | 395 |
arch/powerpc/platforms/pseries/smp.c
drivers/crypto/nx/nx-842.c
... | ... | @@ -28,7 +28,6 @@ |
28 | 28 | #include <linux/slab.h> |
29 | 29 | |
30 | 30 | #include <asm/page.h> |
31 | -#include <asm/pSeries_reconfig.h> | |
32 | 31 | #include <asm/vio.h> |
33 | 32 | |
34 | 33 | #include "nx_csbcpb.h" /* struct nx_csbcpb */ |
35 | 34 | |
36 | 35 | |
37 | 36 | |
38 | 37 | |
... | ... | @@ -1014,26 +1013,23 @@ |
1014 | 1013 | * NOTIFY_BAD encoded with error number on failure, use |
1015 | 1014 | * notifier_to_errno() to decode this value |
1016 | 1015 | */ |
1017 | -static int nx842_OF_notifier(struct notifier_block *np, | |
1018 | - unsigned long action, | |
1019 | - void *update) | |
1016 | +static int nx842_OF_notifier(struct notifier_block *np, unsigned long action, | |
1017 | + void *update) | |
1020 | 1018 | { |
1021 | - struct pSeries_reconfig_prop_update *upd; | |
1019 | + struct of_prop_reconfig *upd = update; | |
1022 | 1020 | struct nx842_devdata *local_devdata; |
1023 | 1021 | struct device_node *node = NULL; |
1024 | 1022 | |
1025 | - upd = (struct pSeries_reconfig_prop_update *)update; | |
1026 | - | |
1027 | 1023 | rcu_read_lock(); |
1028 | 1024 | local_devdata = rcu_dereference(devdata); |
1029 | 1025 | if (local_devdata) |
1030 | 1026 | node = local_devdata->dev->of_node; |
1031 | 1027 | |
1032 | 1028 | if (local_devdata && |
1033 | - action == PSERIES_UPDATE_PROPERTY && | |
1034 | - !strcmp(upd->node->name, node->name)) { | |
1029 | + action == OF_RECONFIG_UPDATE_PROPERTY && | |
1030 | + !strcmp(upd->dn->name, node->name)) { | |
1035 | 1031 | rcu_read_unlock(); |
1036 | - nx842_OF_upd(upd->property); | |
1032 | + nx842_OF_upd(upd->prop); | |
1037 | 1033 | } else |
1038 | 1034 | rcu_read_unlock(); |
1039 | 1035 | |
... | ... | @@ -1182,7 +1178,7 @@ |
1182 | 1178 | synchronize_rcu(); |
1183 | 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 | 1183 | ret = nx842_OF_upd(NULL); |
1188 | 1184 | if (ret && ret != -ENODEV) { |
... | ... | @@ -1228,7 +1224,7 @@ |
1228 | 1224 | spin_lock_irqsave(&devdata_mutex, flags); |
1229 | 1225 | old_devdata = rcu_dereference_check(devdata, |
1230 | 1226 | lockdep_is_held(&devdata_mutex)); |
1231 | - pSeries_reconfig_notifier_unregister(&nx842_of_nb); | |
1227 | + of_reconfig_notifier_unregister(&nx842_of_nb); | |
1232 | 1228 | rcu_assign_pointer(devdata, NULL); |
1233 | 1229 | spin_unlock_irqrestore(&devdata_mutex, flags); |
1234 | 1230 | synchronize_rcu(); |
drivers/crypto/nx/nx.c
drivers/macintosh/smu.c
... | ... | @@ -997,7 +997,7 @@ |
997 | 997 | "%02x !\n", id, hdr->id); |
998 | 998 | goto failure; |
999 | 999 | } |
1000 | - if (prom_add_property(smu->of_node, prop)) { | |
1000 | + if (of_add_property(smu->of_node, prop)) { | |
1001 | 1001 | printk(KERN_DEBUG "SMU: Failed creating sdb-partition-%02x " |
1002 | 1002 | "property !\n", id); |
1003 | 1003 | goto failure; |
drivers/of/base.c
... | ... | @@ -1028,14 +1028,37 @@ |
1028 | 1028 | } |
1029 | 1029 | EXPORT_SYMBOL(of_parse_phandle_with_args); |
1030 | 1030 | |
1031 | +#if defined(CONFIG_OF_DYNAMIC) | |
1032 | +static 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 | |
1042 | +static 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 | */ |
1034 | -int prom_add_property(struct device_node *np, struct property *prop) | |
1052 | +int of_add_property(struct device_node *np, struct property *prop) | |
1035 | 1053 | { |
1036 | 1054 | struct property **next; |
1037 | 1055 | unsigned long flags; |
1056 | + int rc; | |
1038 | 1057 | |
1058 | + rc = of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop); | |
1059 | + if (rc) | |
1060 | + return rc; | |
1061 | + | |
1039 | 1062 | prop->next = NULL; |
1040 | 1063 | write_lock_irqsave(&devtree_lock, flags); |
1041 | 1064 | next = &np->properties; |
1042 | 1065 | |
1043 | 1066 | |
1044 | 1067 | |
... | ... | @@ -1060,19 +1083,24 @@ |
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 | 1088 | * Note that we don't actually remove it, since we have given out |
1066 | 1089 | * who-knows-how-many pointers to the data using get-property. |
1067 | 1090 | * Instead we just move the property to the "dead properties" |
1068 | 1091 | * list, so it won't be found any more. |
1069 | 1092 | */ |
1070 | -int prom_remove_property(struct device_node *np, struct property *prop) | |
1093 | +int of_remove_property(struct device_node *np, struct property *prop) | |
1071 | 1094 | { |
1072 | 1095 | struct property **next; |
1073 | 1096 | unsigned long flags; |
1074 | 1097 | int found = 0; |
1098 | + int rc; | |
1075 | 1099 | |
1100 | + rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop); | |
1101 | + if (rc) | |
1102 | + return rc; | |
1103 | + | |
1076 | 1104 | write_lock_irqsave(&devtree_lock, flags); |
1077 | 1105 | next = &np->properties; |
1078 | 1106 | while (*next) { |
... | ... | @@ -1101,7 +1129,7 @@ |
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 | 1133 | * not exist, add it. |
1106 | 1134 | * |
1107 | 1135 | * Note that we don't actually remove it, since we have given out |
1108 | 1136 | |
1109 | 1137 | |
1110 | 1138 | |
... | ... | @@ -1109,19 +1137,22 @@ |
1109 | 1137 | * Instead we just move the property to the "dead properties" list, |
1110 | 1138 | * and add the new property to the property list |
1111 | 1139 | */ |
1112 | -int prom_update_property(struct device_node *np, | |
1113 | - struct property *newprop) | |
1140 | +int of_update_property(struct device_node *np, struct property *newprop) | |
1114 | 1141 | { |
1115 | 1142 | struct property **next, *oldprop; |
1116 | 1143 | unsigned long flags; |
1117 | - int found = 0; | |
1144 | + int rc, found = 0; | |
1118 | 1145 | |
1146 | + rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop); | |
1147 | + if (rc) | |
1148 | + return rc; | |
1149 | + | |
1119 | 1150 | if (!newprop->name) |
1120 | 1151 | return -EINVAL; |
1121 | 1152 | |
1122 | 1153 | oldprop = of_find_property(np, newprop->name, NULL); |
1123 | 1154 | if (!oldprop) |
1124 | - return prom_add_property(np, newprop); | |
1155 | + return of_add_property(np, newprop); | |
1125 | 1156 | |
1126 | 1157 | write_lock_irqsave(&devtree_lock, flags); |
1127 | 1158 | next = &np->properties; |
1128 | 1159 | |
1129 | 1160 | |
1130 | 1161 | |
1131 | 1162 | |
1132 | 1163 | |
1133 | 1164 | |
1134 | 1165 | |
1135 | 1166 | |
1136 | 1167 | |
1137 | 1168 | |
... | ... | @@ -1160,37 +1191,115 @@ |
1160 | 1191 | * device tree nodes. |
1161 | 1192 | */ |
1162 | 1193 | |
1194 | +static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain); | |
1195 | + | |
1196 | +int of_reconfig_notifier_register(struct notifier_block *nb) | |
1197 | +{ | |
1198 | + return blocking_notifier_chain_register(&of_reconfig_chain, nb); | |
1199 | +} | |
1200 | + | |
1201 | +int of_reconfig_notifier_unregister(struct notifier_block *nb) | |
1202 | +{ | |
1203 | + return blocking_notifier_chain_unregister(&of_reconfig_chain, nb); | |
1204 | +} | |
1205 | + | |
1206 | +int 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 | |
1215 | +static 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 | |
1224 | +static void of_add_proc_dt_entry(struct device_node *dn) | |
1225 | +{ | |
1226 | + return; | |
1227 | +} | |
1228 | +#endif | |
1229 | + | |
1163 | 1230 | /** |
1164 | 1231 | * of_attach_node - Plug a device node into the tree and global list. |
1165 | 1232 | */ |
1166 | -void of_attach_node(struct device_node *np) | |
1233 | +int of_attach_node(struct device_node *np) | |
1167 | 1234 | { |
1168 | 1235 | unsigned long flags; |
1236 | + int rc; | |
1169 | 1237 | |
1238 | + rc = of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np); | |
1239 | + if (rc) | |
1240 | + return rc; | |
1241 | + | |
1170 | 1242 | write_lock_irqsave(&devtree_lock, flags); |
1171 | 1243 | np->sibling = np->parent->child; |
1172 | 1244 | np->allnext = allnodes; |
1173 | 1245 | np->parent->child = np; |
1174 | 1246 | allnodes = np; |
1175 | 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 | |
1254 | +static 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 | |
1268 | +static void of_remove_proc_dt_entry(struct device_node *dn) | |
1269 | +{ | |
1270 | + return; | |
1271 | +} | |
1272 | +#endif | |
1273 | + | |
1178 | 1274 | /** |
1179 | 1275 | * of_detach_node - "Unplug" a node from the device tree. |
1180 | 1276 | * |
1181 | 1277 | * The caller must hold a reference to the node. The memory associated with |
1182 | 1278 | * the node is not freed until its refcount goes to zero. |
1183 | 1279 | */ |
1184 | -void of_detach_node(struct device_node *np) | |
1280 | +int of_detach_node(struct device_node *np) | |
1185 | 1281 | { |
1186 | 1282 | struct device_node *parent; |
1187 | 1283 | unsigned long flags; |
1284 | + int rc = 0; | |
1188 | 1285 | |
1286 | + rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np); | |
1287 | + if (rc) | |
1288 | + return rc; | |
1289 | + | |
1189 | 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 | 1298 | parent = np->parent; |
1192 | - if (!parent) | |
1193 | - goto out_unlock; | |
1299 | + if (!parent) { | |
1300 | + write_unlock_irqrestore(&devtree_lock, flags); | |
1301 | + return rc; | |
1302 | + } | |
1194 | 1303 | |
1195 | 1304 | if (allnodes == np) |
1196 | 1305 | allnodes = np->allnext; |
1197 | 1306 | |
... | ... | @@ -1215,9 +1324,10 @@ |
1215 | 1324 | } |
1216 | 1325 | |
1217 | 1326 | of_node_set_flag(np, OF_DETACHED); |
1218 | - | |
1219 | -out_unlock: | |
1220 | 1327 | write_unlock_irqrestore(&devtree_lock, flags); |
1328 | + | |
1329 | + of_remove_proc_dt_entry(np); | |
1330 | + return rc; | |
1221 | 1331 | } |
1222 | 1332 | #endif /* defined(CONFIG_OF_DYNAMIC) */ |
1223 | 1333 |
include/linux/of.h
... | ... | @@ -22,6 +22,7 @@ |
22 | 22 | #include <linux/mod_devicetable.h> |
23 | 23 | #include <linux/spinlock.h> |
24 | 24 | #include <linux/topology.h> |
25 | +#include <linux/notifier.h> | |
25 | 26 | |
26 | 27 | #include <asm/byteorder.h> |
27 | 28 | #include <asm/errno.h> |
28 | 29 | |
29 | 30 | |
... | ... | @@ -267,16 +268,28 @@ |
267 | 268 | |
268 | 269 | extern int of_machine_is_compatible(const char *compat); |
269 | 270 | |
270 | -extern int prom_add_property(struct device_node* np, struct property* prop); | |
271 | -extern int prom_remove_property(struct device_node *np, struct property *prop); | |
272 | -extern int prom_update_property(struct device_node *np, | |
273 | - struct property *newprop); | |
271 | +extern int of_add_property(struct device_node *np, struct property *prop); | |
272 | +extern int of_remove_property(struct device_node *np, struct property *prop); | |
273 | +extern int of_update_property(struct device_node *np, struct property *newprop); | |
274 | 274 | |
275 | -#if defined(CONFIG_OF_DYNAMIC) | |
276 | 275 | /* For updating the device tree at runtime */ |
277 | -extern void of_attach_node(struct device_node *); | |
278 | -extern void of_detach_node(struct device_node *); | |
279 | -#endif | |
276 | +#define OF_RECONFIG_ATTACH_NODE 0x0001 | |
277 | +#define OF_RECONFIG_DETACH_NODE 0x0002 | |
278 | +#define OF_RECONFIG_ADD_PROPERTY 0x0003 | |
279 | +#define OF_RECONFIG_REMOVE_PROPERTY 0x0004 | |
280 | +#define OF_RECONFIG_UPDATE_PROPERTY 0x0005 | |
281 | + | |
282 | +struct of_prop_reconfig { | |
283 | + struct device_node *dn; | |
284 | + struct property *prop; | |
285 | +}; | |
286 | + | |
287 | +extern int of_reconfig_notifier_register(struct notifier_block *); | |
288 | +extern int of_reconfig_notifier_unregister(struct notifier_block *); | |
289 | +extern int of_reconfig_notify(unsigned long, void *); | |
290 | + | |
291 | +extern int of_attach_node(struct device_node *); | |
292 | +extern int of_detach_node(struct device_node *); | |
280 | 293 | |
281 | 294 | #define of_match_ptr(_ptr) (_ptr) |
282 | 295 |