Commit de1bb03a authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt

Merge branch 'dt' into next

parents 11ee7e99 f459d63e
...@@ -211,7 +211,7 @@ static void __init update_fec_mac_prop(enum mac_oui oui) ...@@ -211,7 +211,7 @@ static void __init update_fec_mac_prop(enum mac_oui oui)
macaddr[4] = (val >> 8) & 0xff; macaddr[4] = (val >> 8) & 0xff;
macaddr[5] = (val >> 0) & 0xff; macaddr[5] = (val >> 0) & 0xff;
prom_update_property(np, newmac); of_update_property(np, newmac);
} }
} }
......
#ifndef _PPC64_PSERIES_RECONFIG_H
#define _PPC64_PSERIES_RECONFIG_H
#ifdef __KERNEL__
#include <linux/notifier.h>
/*
* Use this API if your code needs to know about OF device nodes being
* added or removed on pSeries systems.
*/
#define PSERIES_RECONFIG_ADD 0x0001
#define PSERIES_RECONFIG_REMOVE 0x0002
#define PSERIES_DRCONF_MEM_ADD 0x0003
#define PSERIES_DRCONF_MEM_REMOVE 0x0004
#define PSERIES_UPDATE_PROPERTY 0x0005
/**
* pSeries_reconfig_notify - Notifier value structure for OFDT property updates
*
* @node: Device tree node which owns the property being updated
* @property: Updated property
*/
struct pSeries_reconfig_prop_update {
struct device_node *node;
struct property *property;
};
#ifdef CONFIG_PPC_PSERIES
extern int pSeries_reconfig_notifier_register(struct notifier_block *);
extern void pSeries_reconfig_notifier_unregister(struct notifier_block *);
extern int pSeries_reconfig_notify(unsigned long action, void *p);
/* Not the best place to put this, will be fixed when we move some
* of the rtas suspend-me stuff to pseries */
extern void pSeries_coalesce_init(void);
#else /* !CONFIG_PPC_PSERIES */
static inline int pSeries_reconfig_notifier_register(struct notifier_block *nb)
{
return 0;
}
static inline void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) { }
static inline void pSeries_coalesce_init(void) { }
#endif /* CONFIG_PPC_PSERIES */
#endif /* __KERNEL__ */
#endif /* _PPC64_PSERIES_RECONFIG_H */
...@@ -58,6 +58,22 @@ static inline int of_node_to_nid(struct device_node *device) { return 0; } ...@@ -58,6 +58,22 @@ static inline int of_node_to_nid(struct device_node *device) { return 0; }
extern void of_instantiate_rtc(void); extern void of_instantiate_rtc(void);
/* The of_drconf_cell struct defines the layout of the LMB array
* specified in the device tree property
* ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory
*/
struct of_drconf_cell {
u64 base_addr;
u32 drc_index;
u32 reserved;
u32 aa_index;
u32 flags;
};
#define DRCONF_MEM_ASSIGNED 0x00000008
#define DRCONF_MEM_AI_INVALID 0x00000040
#define DRCONF_MEM_RESERVED 0x00000080
/* These includes are put at the bottom because they may contain things /* These includes are put at the bottom because they may contain things
* that are overridden by this file. Ideally they shouldn't be included * that are overridden by this file. Ideally they shouldn't be included
* by this file, but there are a bunch of .c files that currently depend * by this file, but there are a bunch of .c files that currently depend
......
...@@ -353,8 +353,13 @@ static inline int page_is_rtas_user_buf(unsigned long pfn) ...@@ -353,8 +353,13 @@ static inline int page_is_rtas_user_buf(unsigned long pfn)
return 1; return 1;
return 0; return 0;
} }
/* Not the best place to put pSeries_coalesce_init, will be fixed when we
* move some of the rtas suspend-me stuff to pseries */
extern void pSeries_coalesce_init(void);
#else #else
static inline int page_is_rtas_user_buf(unsigned long pfn) { return 0;} static inline int page_is_rtas_user_buf(unsigned long pfn) { return 0;}
static inline void pSeries_coalesce_init(void) { }
#endif #endif
extern int call_rtas(const char *, int, int, unsigned long *, ...); extern int call_rtas(const char *, int, int, unsigned long *, ...);
......
...@@ -218,23 +218,23 @@ static void __init export_crashk_values(struct device_node *node) ...@@ -218,23 +218,23 @@ static void __init export_crashk_values(struct device_node *node)
* be sure what's in them, so remove them. */ * be sure what's in them, so remove them. */
prop = of_find_property(node, "linux,crashkernel-base", NULL); prop = of_find_property(node, "linux,crashkernel-base", NULL);
if (prop) if (prop)
prom_remove_property(node, prop); of_remove_property(node, prop);
prop = of_find_property(node, "linux,crashkernel-size", NULL); prop = of_find_property(node, "linux,crashkernel-size", NULL);
if (prop) if (prop)
prom_remove_property(node, prop); of_remove_property(node, prop);
if (crashk_res.start != 0) { if (crashk_res.start != 0) {
prom_add_property(node, &crashk_base_prop); of_add_property(node, &crashk_base_prop);
crashk_size = resource_size(&crashk_res); crashk_size = resource_size(&crashk_res);
prom_add_property(node, &crashk_size_prop); of_add_property(node, &crashk_size_prop);
} }
/* /*
* memory_limit is required by the kexec-tools to limit the * memory_limit is required by the kexec-tools to limit the
* crash regions to the actual memory used. * crash regions to the actual memory used.
*/ */
prom_update_property(node, &memory_limit_prop); of_update_property(node, &memory_limit_prop);
} }
static int __init kexec_setup(void) static int __init kexec_setup(void)
...@@ -249,11 +249,11 @@ static int __init kexec_setup(void) ...@@ -249,11 +249,11 @@ static int __init kexec_setup(void)
/* remove any stale properties so ours can be found */ /* remove any stale properties so ours can be found */
prop = of_find_property(node, kernel_end_prop.name, NULL); prop = of_find_property(node, kernel_end_prop.name, NULL);
if (prop) if (prop)
prom_remove_property(node, prop); of_remove_property(node, prop);
/* information needed by userspace when using default_machine_kexec */ /* information needed by userspace when using default_machine_kexec */
kernel_end = __pa(_end); kernel_end = __pa(_end);
prom_add_property(node, &kernel_end_prop); of_add_property(node, &kernel_end_prop);
export_crashk_values(node); export_crashk_values(node);
......
...@@ -389,14 +389,14 @@ static int __init export_htab_values(void) ...@@ -389,14 +389,14 @@ static int __init export_htab_values(void)
/* remove any stale propertys so ours can be found */ /* remove any stale propertys so ours can be found */
prop = of_find_property(node, htab_base_prop.name, NULL); prop = of_find_property(node, htab_base_prop.name, NULL);
if (prop) if (prop)
prom_remove_property(node, prop); of_remove_property(node, prop);
prop = of_find_property(node, htab_size_prop.name, NULL); prop = of_find_property(node, htab_size_prop.name, NULL);
if (prop) if (prop)
prom_remove_property(node, prop); of_remove_property(node, prop);
htab_base = __pa(htab_address); htab_base = __pa(htab_address);
prom_add_property(node, &htab_base_prop); of_add_property(node, &htab_base_prop);
prom_add_property(node, &htab_size_prop); of_add_property(node, &htab_size_prop);
of_node_put(node); of_node_put(node);
return 0; return 0;
......
...@@ -208,7 +208,7 @@ pci_create_OF_bus_map(void) ...@@ -208,7 +208,7 @@ pci_create_OF_bus_map(void)
of_prop->name = "pci-OF-bus-map"; of_prop->name = "pci-OF-bus-map";
of_prop->length = 256; of_prop->length = 256;
of_prop->value = &of_prop[1]; of_prop->value = &of_prop[1];
prom_add_property(dn, of_prop); of_add_property(dn, of_prop);
of_node_put(dn); of_node_put(dn);
} }
} }
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/memblock.h> #include <linux/memblock.h>
#include <linux/of.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/rtas.h> #include <asm/rtas.h>
...@@ -49,7 +50,6 @@ ...@@ -49,7 +50,6 @@
#include <asm/btext.h> #include <asm/btext.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/pSeries_reconfig.h>
#include <asm/pci-bridge.h> #include <asm/pci-bridge.h>
#include <asm/kexec.h> #include <asm/kexec.h>
#include <asm/opal.h> #include <asm/opal.h>
...@@ -803,7 +803,7 @@ static int prom_reconfig_notifier(struct notifier_block *nb, ...@@ -803,7 +803,7 @@ static int prom_reconfig_notifier(struct notifier_block *nb,
int err; int err;
switch (action) { switch (action) {
case PSERIES_RECONFIG_ADD: case OF_RECONFIG_ATTACH_NODE:
err = of_finish_dynamic_node(node); err = of_finish_dynamic_node(node);
if (err < 0) if (err < 0)
printk(KERN_ERR "finish_node returned %d\n", err); printk(KERN_ERR "finish_node returned %d\n", err);
...@@ -822,7 +822,7 @@ static struct notifier_block prom_reconfig_nb = { ...@@ -822,7 +822,7 @@ static struct notifier_block prom_reconfig_nb = {
static int __init prom_reconfig_setup(void) static int __init prom_reconfig_setup(void)
{ {
return pSeries_reconfig_notifier_register(&prom_reconfig_nb); return of_reconfig_notifier_register(&prom_reconfig_nb);
} }
__initcall(prom_reconfig_setup); __initcall(prom_reconfig_setup);
#endif #endif
......
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
#include <asm/time.h> #include <asm/time.h>
#include <asm/mmu.h> #include <asm/mmu.h>
#include <asm/topology.h> #include <asm/topology.h>
#include <asm/pSeries_reconfig.h>
struct rtas_t rtas = { struct rtas_t rtas = {
.lock = __ARCH_SPIN_LOCK_UNLOCKED .lock = __ARCH_SPIN_LOCK_UNLOCKED
......
...@@ -399,18 +399,6 @@ static unsigned long read_n_cells(int n, const unsigned int **buf) ...@@ -399,18 +399,6 @@ static unsigned long read_n_cells(int n, const unsigned int **buf)
return result; return result;
} }
struct of_drconf_cell {
u64 base_addr;
u32 drc_index;
u32 reserved;
u32 aa_index;
u32 flags;
};
#define DRCONF_MEM_ASSIGNED 0x00000008
#define DRCONF_MEM_AI_INVALID 0x00000040
#define DRCONF_MEM_RESERVED 0x00000080
/* /*
* Read the next memblock list entry from the ibm,dynamic-memory property * Read the next memblock list entry from the ibm,dynamic-memory property
* and return the information in the provided of_drconf_cell structure. * and return the information in the provided of_drconf_cell structure.
......
...@@ -539,7 +539,7 @@ static void __init p1022_ds_setup_arch(void) ...@@ -539,7 +539,7 @@ static void __init p1022_ds_setup_arch(void)
}; };
/* /*
* prom_update_property() is called before * of_update_property() is called before
* kmalloc() is available, so the 'new' object * kmalloc() is available, so the 'new' object
* should be allocated in the global area. * should be allocated in the global area.
* The easiest way is to do that is to * The easiest way is to do that is to
...@@ -548,7 +548,7 @@ static void __init p1022_ds_setup_arch(void) ...@@ -548,7 +548,7 @@ static void __init p1022_ds_setup_arch(void)
*/ */
pr_info("p1022ds: disabling %s node", pr_info("p1022ds: disabling %s node",
np2->full_name); np2->full_name);
prom_update_property(np2, &nor_status); of_update_property(np2, &nor_status);
of_node_put(np2); of_node_put(np2);
} }
...@@ -564,7 +564,7 @@ static void __init p1022_ds_setup_arch(void) ...@@ -564,7 +564,7 @@ static void __init p1022_ds_setup_arch(void)
pr_info("p1022ds: disabling %s node", pr_info("p1022ds: disabling %s node",
np2->full_name); np2->full_name);
prom_update_property(np2, &nand_status); of_update_property(np2, &nand_status);
of_node_put(np2); of_node_put(np2);
} }
......
...@@ -280,13 +280,13 @@ static void os_area_set_property(struct device_node *node, ...@@ -280,13 +280,13 @@ static void os_area_set_property(struct device_node *node,
if (tmp) { if (tmp) {
pr_debug("%s:%d found %s\n", __func__, __LINE__, prop->name); pr_debug("%s:%d found %s\n", __func__, __LINE__, prop->name);
prom_remove_property(node, tmp); of_remove_property(node, tmp);
} }
result = prom_add_property(node, prop); result = of_add_property(node, prop);
if (result) if (result)
pr_debug("%s:%d prom_set_property failed\n", __func__, pr_debug("%s:%d of_set_property failed\n", __func__,
__LINE__); __LINE__);
} }
......
...@@ -13,17 +13,16 @@ ...@@ -13,17 +13,16 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/of.h>
#include "offline_states.h" #include "offline_states.h"
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/rtas.h> #include <asm/rtas.h>
#include <asm/pSeries_reconfig.h>
struct cc_workarea { struct cc_workarea {
u32 drc_index; u32 drc_index;
...@@ -255,9 +254,6 @@ static struct device_node *derive_parent(const char *path) ...@@ -255,9 +254,6 @@ static struct device_node *derive_parent(const char *path)
int dlpar_attach_node(struct device_node *dn) int dlpar_attach_node(struct device_node *dn)
{ {
#ifdef CONFIG_PROC_DEVICETREE
struct proc_dir_entry *ent;
#endif
int rc; int rc;
of_node_set_flag(dn, OF_DYNAMIC); of_node_set_flag(dn, OF_DYNAMIC);
...@@ -266,44 +262,26 @@ int dlpar_attach_node(struct device_node *dn) ...@@ -266,44 +262,26 @@ int dlpar_attach_node(struct device_node *dn)
if (!dn->parent) if (!dn->parent)
return -ENOMEM; return -ENOMEM;
rc = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, dn); rc = of_attach_node(dn);
if (rc) { if (rc) {
printk(KERN_ERR "Failed to add device node %s\n", printk(KERN_ERR "Failed to add device node %s\n",
dn->full_name); dn->full_name);
return rc; return rc;
} }
of_attach_node(dn);
#ifdef CONFIG_PROC_DEVICETREE
ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde);
if (ent)
proc_device_tree_add_node(dn, ent);
#endif
of_node_put(dn->parent); of_node_put(dn->parent);
return 0; return 0;
} }
int dlpar_detach_node(struct device_node *dn) int dlpar_detach_node(struct device_node *dn)
{ {
#ifdef CONFIG_PROC_DEVICETREE int rc;
struct device_node *parent = dn->parent;
struct property *prop = dn->properties;
while (prop) {
remove_proc_entry(prop->name, dn->pde);
prop = prop->next;
}
if (dn->pde) rc = of_detach_node(dn);
remove_proc_entry(dn->pde->name, parent->pde); if (rc)
#endif return rc;
pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, dn);
of_detach_node(dn);
of_node_put(dn); /* Must decrement the refcount */ of_node_put(dn); /* Must decrement the refcount */
return 0; return 0;
} }
......
...@@ -23,12 +23,12 @@ ...@@ -23,12 +23,12 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/sched.h> /* for idle_task_exit */ #include <linux/sched.h> /* for idle_task_exit */
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/of.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/rtas.h> #include <asm/rtas.h>
#include <asm/firmware.h> #include <asm/firmware.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/vdso_datapage.h> #include <asm/vdso_datapage.h>
#include <asm/pSeries_reconfig.h>
#include <asm/xics.h> #include <asm/xics.h>
#include "plpar_wrappers.h" #include "plpar_wrappers.h"
#include "offline_states.h" #include "offline_states.h"
...@@ -333,10 +333,10 @@ static int pseries_smp_notifier(struct notifier_block *nb, ...@@ -333,10 +333,10 @@ static int pseries_smp_notifier(struct notifier_block *nb,
int err = 0; int err = 0;
switch (action) { switch (action) {
case PSERIES_RECONFIG_ADD: case OF_RECONFIG_ATTACH_NODE:
err = pseries_add_processor(node); err = pseries_add_processor(node);
break; break;
case PSERIES_RECONFIG_REMOVE: case OF_RECONFIG_DETACH_NODE:
pseries_remove_processor(node); pseries_remove_processor(node);
break; break;
} }
...@@ -399,7 +399,7 @@ static int __init pseries_cpu_hotplug_init(void) ...@@ -399,7 +399,7 @@ static int __init pseries_cpu_hotplug_init(void)
/* Processors can be added/removed only on LPAR */ /* Processors can be added/removed only on LPAR */
if (firmware_has_feature(FW_FEATURE_LPAR)) { if (firmware_has_feature(FW_FEATURE_LPAR)) {
pSeries_reconfig_notifier_register(&pseries_smp_nb); of_reconfig_notifier_register(&pseries_smp_nb);
cpu_maps_update_begin(); cpu_maps_update_begin();
if (cede_offline_enabled && parse_cede_parameters() == 0) { if (cede_offline_enabled && parse_cede_parameters() == 0) {
default_offline_state = CPU_STATE_INACTIVE; default_offline_state = CPU_STATE_INACTIVE;
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <asm/firmware.h> #include <asm/firmware.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/pSeries_reconfig.h>
#include <asm/sparsemem.h> #include <asm/sparsemem.h>
static unsigned long get_memblock_size(void) static unsigned long get_memblock_size(void)
...@@ -187,42 +186,69 @@ static int pseries_add_memory(struct device_node *np) ...@@ -187,42 +186,69 @@ static int pseries_add_memory(struct device_node *np)
return (ret < 0) ? -EINVAL : 0; return (ret < 0) ? -EINVAL : 0;
} }
static int pseries_drconf_memory(unsigned long *base, unsigned int action) static int pseries_update_drconf_memory(struct of_prop_reconfig *pr)
{ {
struct of_drconf_cell *new_drmem, *old_drmem;
unsigned long memblock_size; unsigned long memblock_size;
int rc; u32 entries;
u32 *p;
int i, rc = -EINVAL;
memblock_size = get_memblock_size(); memblock_size = get_memblock_size();
if (!memblock_size) if (!memblock_size)
return -EINVAL; return -EINVAL;
if (action == PSERIES_DRCONF_MEM_ADD) { p = (u32 *)of_get_property(pr->dn, "ibm,dynamic-memory", NULL);
rc = memblock_add(*base, memblock_size); if (!p)
rc = (rc < 0) ? -EINVAL : 0; return -EINVAL;
} else if (action == PSERIES_DRCONF_MEM_REMOVE) {
rc = pseries_remove_memblock(*base, memblock_size); /* The first int of the property is the number of lmb's described
} else { * by the property. This is followed by an array of of_drconf_cell
rc = -EINVAL; * entries. Get the niumber of entries and skip to the array of
* of_drconf_cell's.
*/
entries = *p++;
old_drmem = (struct of_drconf_cell *)p;
p = (u32 *)pr->prop->value;
p++;
new_drmem = (struct of_drconf_cell *)p;
for (i = 0; i < entries; i++) {
if ((old_drmem[i].flags & DRCONF_MEM_ASSIGNED) &&
(!(new_drmem[i].flags & DRCONF_MEM_ASSIGNED))) {
rc = pseries_remove_memblock(old_drmem[i].base_addr,
memblock_size);
break;
} else if ((!(old_drmem[i].flags & DRCONF_MEM_ASSIGNED)) &&
(new_drmem[i].flags & DRCONF_MEM_ASSIGNED)) {
rc = memblock_add(old_drmem[i].base_addr,
memblock_size);
rc = (rc < 0) ? -EINVAL : 0;
break;
}
} }
return rc; return rc;
} }
static int pseries_memory_notifier(struct notifier_block *nb, static int pseries_memory_notifier(struct notifier_block *nb,
unsigned long action, void *node) unsigned long action, void *node)
{ {
struct of_prop_reconfig *pr;
int err = 0; int err = 0;
switch (action) { switch (action) {
case PSERIES_RECONFIG_ADD: case OF_RECONFIG_ATTACH_NODE:
err = pseries_add_memory(node); err = pseries_add_memory(node);
break; break;
case PSERIES_RECONFIG_REMOVE: case OF_RECONFIG_DETACH_NODE:
err = pseries_remove_memory(node); err = pseries_remove_memory(node);
break; break;
case PSERIES_DRCONF_MEM_ADD: case OF_RECONFIG_UPDATE_PROPERTY:
case PSERIES_DRCONF_MEM_REMOVE: pr = (struct of_prop_reconfig *)node;
err = pseries_drconf_memory(node, action); if (!strcmp(pr->prop->name, "ibm,dynamic-memory"))
err = pseries_update_drconf_memory(pr);
break; break;
} }
return notifier_from_errno(err); return notifier_from_errno(err);
...@@ -235,7 +261,7 @@ static struct notifier_block pseries_mem_nb = { ...@@ -235,7 +261,7 @@ static struct notifier_block pseries_mem_nb = {
static int __init pseries_memory_hotplug_init(void) static int __init pseries_memory_hotplug_init(void)
{ {
if (firmware_has_feature(FW_FEATURE_LPAR)) if (firmware_has_feature(FW_FEATURE_LPAR))
pSeries_reconfig_notifier_register(&pseries_mem_nb); of_reconfig_notifier_register(&pseries_mem_nb);
return 0; return 0;
} }
......
...@@ -36,13 +36,13 @@ ...@@ -36,13 +36,13 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/crash_dump.h> #include <linux/crash_dump.h>
#include <linux/memory.h> #include <linux/memory.h>
#include <linux/of.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/rtas.h> #include <asm/rtas.h>
#include <asm/iommu.h> #include <asm/iommu.h>
#include <asm/pci-bridge.h> #include <asm/pci-bridge.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/pSeries_reconfig.h>
#include <asm/firmware.h> #include <asm/firmware.h>
#include <asm/tce.h> #include <asm/tce.h>
#include <asm/ppc-pci.h> #include <asm/ppc-pci.h>
...@@ -760,7 +760,7 @@ static void remove_ddw(struct device_node *np) ...@@ -760,7 +760,7 @@ static void remove_ddw(struct device_node *np)
__remove_ddw(np, ddw_avail, liobn); __remove_ddw(np, ddw_avail, liobn);
delprop: delprop:
ret = prom_remove_property(np, win64); ret = of_remove_property(np, win64);
if (ret) if (ret)
pr_warning("%s: failed to remove direct window property: %d\n", pr_warning("%s: failed to remove direct window property: %d\n",
np->full_name, ret); np->full_name, ret);
...@@ -1070,7 +1070,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) ...@@ -1070,7 +1070,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
goto out_free_window; goto out_free_window;
} }
ret = prom_add_property(pdn, win64); ret = of_add_property(pdn, win64);
if (ret) { if (ret) {
dev_err(&dev->dev, "unable to add dma window property for %s: %d", dev_err(&dev->dev, "unable to add dma window property for %s: %d",
pdn->full_name, ret); pdn->full_name, ret);
...@@ -1294,7 +1294,7 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti ...@@ -1294,7 +1294,7 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti
struct direct_window *window; struct direct_window *window;
switch (action) { switch (action) {
case PSERIES_RECONFIG_REMOVE: case OF_RECONFIG_DETACH_NODE:
if (pci && pci->iommu_table) if (pci && pci->iommu_table)
iommu_free_table(pci->iommu_table, np->full_name); iommu_free_table(pci->iommu_table, np->full_name);
...@@ -1357,7 +1357,7 @@ void iommu_init_early_pSeries(void) ...@@ -1357,7 +1357,7 @@ void iommu_init_early_pSeries(void)
} }
pSeries_reconfig_notifier_register(&iommu_reconfig_nb); of_reconfig_notifier_register(&iommu_reconfig_nb);
register_memory_notifier(&iommu_mem_nb); register_memory_notifier(&iommu_mem_nb);
set_pci_dma_ops(&dma_iommu_ops); set_pci_dma_ops(&dma_iommu_ops);
......
...@@ -116,7 +116,7 @@ static int update_dt_property(struct device_node *dn, struct property **prop, ...@@ -116,7 +116,7 @@ static int update_dt_property(struct device_node *dn, struct property **prop,
} }
if (!more) { if (!more) {
prom_update_property(dn, new_prop); of_update_property(dn, new_prop);
new_prop = NULL; new_prop = NULL;
} }
...@@ -172,7 +172,7 @@ static int update_dt_node(u32 phandle) ...@@ -172,7 +172,7 @@ static int update_dt_node(u32 phandle)
case 0x80000000: case 0x80000000:
prop = of_find_property(dn, prop_name, NULL); prop = of_find_property(dn, prop_name, NULL);
prom_remove_property(dn, prop); of_remove_property(dn, prop);
prop = NULL; prop = NULL;
break; break;
......
...@@ -16,55 +16,13 @@ ...@@ -16,55 +16,13 @@
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/of.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pSeries_reconfig.h>
#include <asm/mmu.h> #include <asm/mmu.h>
/*
* Routines for "runtime" addition and removal of device tree nodes.
*/
#ifdef CONFIG_PROC_DEVICETREE
/*
* Add a node to /proc/device-tree.
*/
static void add_node_proc_entries(struct device_node *np)
{
struct proc_dir_entry *ent;
ent = proc_mkdir(strrchr(np->full_name, '/') + 1, np->parent->pde);
if (ent)
proc_device_tree_add_node(np, ent);
}
static void remove_node_proc_entries(struct device_node *np)
{
struct property *pp = np->properties;
struct device_node *parent = np->parent;
while (pp) {
remove_proc_entry(pp->name, np->pde);
pp = pp->next;
}
if (np->pde)
remove_proc_entry(np->pde->name, parent->pde);
}
#else /* !CONFIG_PROC_DEVICETREE */
static void add_node_proc_entries(struct device_node *np)
{
return;
}
static void remove_node_proc_entries(struct device_node *np)
{
return;
}
#endif /* CONFIG_PROC_DEVICETREE */
/** /**
* derive_parent - basically like dirname(1) * derive_parent - basically like dirname(1)
* @path: the full_name of a node to be added to the tree * @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,28 +55,6 @@ static struct device_node *derive_parent(const char *path)
return parent; return parent;
} }
static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain);
int pSeries_reconfig_notifier_register(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb);
}
EXPORT_SYMBOL_GPL(pSeries_reconfig_notifier_register);
void pSeries_reconfig_notifier_unregister(struct notifier_block *nb)
{
blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb);
}
EXPORT_SYMBOL_GPL(pSeries_reconfig_notifier_unregister);
int pSeries_reconfig_notify(unsigned long action, void *p)
{
int err = blocking_notifier_call_chain(&pSeries_reconfig_chain,
action, p);
return notifier_to_errno(err);
}
static int pSeries_reconfig_add_node(const char *path, struct property *proplist) static int pSeries_reconfig_add_node(const char *path, struct property *proplist)
{ {
struct device_node *np; struct device_node *np;
...@@ -142,16 +78,12 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist ...@@ -142,16 +78,12 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
goto out_err; goto out_err;
} }
err = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, np); err = of_attach_node(np);
if (err) { if (err) {
printk(KERN_ERR "Failed to add device node %s\n", path); printk(KERN_ERR "Failed to add device node %s\n", path);
goto out_err; goto out_err;
} }
of_attach_node(np);
add_node_proc_entries(np);
of_node_put(np->parent); of_node_put(np->parent);
return 0; return 0;
...@@ -179,11 +111,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np) ...@@ -179,11 +111,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np)
return -EBUSY; return -EBUSY;
} }
remove_node_proc_entries(np);
pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, np);
of_detach_node(np); of_detach_node(np);
of_node_put(parent); of_node_put(parent);
of_node_put(np); /* Must decrement the refcount */ of_node_put(np); /* Must decrement the refcount */
return 0; return 0;
...@@ -398,7 +326,7 @@ static int do_add_property(char *buf, size_t bufsize) ...@@ -398,7 +326,7 @@ static int do_add_property(char *buf, size_t bufsize)
if (!prop) if (!prop)
return -ENOMEM; return -ENOMEM;
prom_add_property(np, prop); of_add_property(np, prop);
return 0; return 0;
} }
...@@ -422,16 +350,15 @@ static int do_remove_property(char *buf, size_t bufsize) ...@@ -422,16 +350,15 @@ static int do_remove_property(char *buf, size_t bufsize)
prop = of_find_property(np, buf, NULL); prop = of_find_property(np, buf, NULL);
return prom_remove_property(np, prop); return of_remove_property(np, prop);
} }
static int do_update_property(char *buf, size_t bufsize) static int do_update_property(char *buf, size_t bufsize)
{ {
struct device_node *np; struct device_node *np;
struct pSeries_reconfig_prop_update upd_value;
unsigned char *value; unsigned char *value;
char *name, *end, *next_prop; char *name, *end, *next_prop;
int rc, length; int length;
struct property *newprop; struct property *newprop;
buf = parse_node(buf, bufsize, &np); buf = parse_node(buf, bufsize, &np);
end = buf + bufsize; end = buf + bufsize;
...@@ -453,41 +380,7 @@ static int do_update_property(char *buf, size_t bufsize) ...@@ -453,41 +380,7 @@ static int do_update_property(char *buf, size_t bufsize)
if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size")) if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size"))
slb_set_size(*(int *)value); slb_set_size(*(int *)value);
upd_value.node = np; return of_update_property(np, newprop);
upd_value.property = newprop;
pSeries_reconfig_notify(PSERIES_UPDATE_PROPERTY, &upd_value);
rc = prom_update_property(np, newprop);
if (rc)
return rc;
/* For memory under the ibm,dynamic-reconfiguration-memory node
* of the device tree, adding and removing memory is just an update
* to the ibm,dynamic-memory property instead of adding/removing a
* memory node in the device tree. For these cases we still need to
* involve the notifier chain.
*/
if (!strcmp(name, "ibm,dynamic-memory")) {
int action;
next_prop = parse_next_property(next_prop, end, &name,
&length, &value);
if (!next_prop)
return -EINVAL;
if (!strcmp(name, "add"))
action = PSERIES_DRCONF_MEM_ADD;
else
action = PSERIES_DRCONF_MEM_REMOVE;
rc = pSeries_reconfig_notify(action, value);
if (rc) {
prom_update_property(np, newprop);
return rc;
}
}
return 0;
} }
/** /**
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/root_dev.h> #include <linux/root_dev.h>
#include <linux/cpuidle.h> #include <linux/cpuidle.h>
#include <linux/of.h>
#include <asm/mmu.h> #include <asm/mmu.h>
#include <asm/processor.h> #include <asm/processor.h>
...@@ -63,7 +64,6 @@ ...@@ -63,7 +64,6 @@
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/firmware.h> #include <asm/firmware.h>
#include <asm/eeh.h> #include <asm/eeh.h>
#include <asm/pSeries_reconfig.h>
#include "plpar_wrappers.h" #include "plpar_wrappers.h"
#include "pseries.h" #include "pseries.h"
...@@ -258,7 +258,7 @@ static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long act ...@@ -258,7 +258,7 @@ static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long act
int err = NOTIFY_OK; int err = NOTIFY_OK;
switch (action) { switch (action) {
case PSERIES_RECONFIG_ADD: case OF_RECONFIG_ATTACH_NODE:
pci = np->parent->data; pci = np->parent->data;
if (pci) { if (pci) {
update_dn_pci_info(np, pci->phb); update_dn_pci_info(np, pci->phb);
...@@ -389,7 +389,7 @@ static void __init pSeries_setup_arch(void) ...@@ -389,7 +389,7 @@ static void __init pSeries_setup_arch(void)
/* Find and initialize PCI host bridges */ /* Find and initialize PCI host bridges */
init_pci_config_tokens(); init_pci_config_tokens();
find_and_init_phbs(); find_and_init_phbs();
pSeries_reconfig_notifier_register(&pci_dn_reconfig_nb); of_reconfig_notifier_register(&pci_dn_reconfig_nb);
pSeries_nvram_init(); pSeries_nvram_init();
......
...@@ -38,7 +38,6 @@ ...@@ -38,7 +38,6 @@
#include <asm/cputable.h> #include <asm/cputable.h>
#include <asm/firmware.h> #include <asm/firmware.h>
#include <asm/rtas.h> #include <asm/rtas.h>
#include <asm/pSeries_reconfig.h>
#include <asm/mpic.h> #include <asm/mpic.h>
#include <asm/vdso_datapage.h> #include <asm/vdso_datapage.h>
#include <asm/cputhreads.h> #include <asm/cputhreads.h>
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/pSeries_reconfig.h>
#include <asm/vio.h> #include <asm/vio.h>
#include "nx_csbcpb.h" /* struct nx_csbcpb */ #include "nx_csbcpb.h" /* struct nx_csbcpb */
...@@ -1014,26 +1013,23 @@ static int nx842_OF_upd(struct property *new_prop) ...@@ -1014,26 +1013,23 @@ static int nx842_OF_upd(struct property *new_prop)
* NOTIFY_BAD encoded with error number on failure, use * NOTIFY_BAD encoded with error number on failure, use
* notifier_to_errno() to decode this value * notifier_to_errno() to decode this value
*/ */
static int nx842_OF_notifier(struct notifier_block *np, static int nx842_OF_notifier(struct notifier_block *np, unsigned long action,
unsigned long action, void *update)
void *update)
{ {
struct pSeries_reconfig_prop_update *upd; struct of_prop_reconfig *upd = update;
struct nx842_devdata *local_devdata; struct nx842_devdata *local_devdata;
struct device_node *node = NULL; struct device_node *node = NULL;
upd = (struct pSeries_reconfig_prop_update *)update;
rcu_read_lock(); rcu_read_lock();
local_devdata = rcu_dereference(devdata); local_devdata = rcu_dereference(devdata);
if (local_devdata) if (local_devdata)
node = local_devdata->dev->of_node; node = local_devdata->dev->of_node;
if (local_devdata && if (local_devdata &&
action == PSERIES_UPDATE_PROPERTY && action == OF_RECONFIG_UPDATE_PROPERTY &&
!strcmp(upd->node->name, node->name)) { !strcmp(upd->dn->name, node->name)) {
rcu_read_unlock(); rcu_read_unlock();
nx842_OF_upd(upd->property); nx842_OF_upd(upd->prop);
} else } else
rcu_read_unlock(); rcu_read_unlock();
...@@ -1182,7 +1178,7 @@ static int __init nx842_probe(struct vio_dev *viodev, ...@@ -1182,7 +1178,7 @@ static int __init nx842_probe(struct vio_dev *viodev,
synchronize_rcu(); synchronize_rcu();
kfree(old_devdata); kfree(old_devdata);
pSeries_reconfig_notifier_register(&nx842_of_nb); of_reconfig_notifier_register(&nx842_of_nb);
ret = nx842_OF_upd(NULL); ret = nx842_OF_upd(NULL);
if (ret && ret != -ENODEV) { if (ret && ret != -ENODEV) {
...@@ -1228,7 +1224,7 @@ static int __exit nx842_remove(struct vio_dev *viodev) ...@@ -1228,7 +1224,7 @@ static int __exit nx842_remove(struct vio_dev *viodev)
spin_lock_irqsave(&devdata_mutex, flags); spin_lock_irqsave(&devdata_mutex, flags);
old_devdata = rcu_dereference_check(devdata, old_devdata = rcu_dereference_check(devdata,
lockdep_is_held(&devdata_mutex)); lockdep_is_held(&devdata_mutex));
pSeries_reconfig_notifier_unregister(&nx842_of_nb); of_reconfig_notifier_unregister(&nx842_of_nb);
rcu_assign_pointer(devdata, NULL); rcu_assign_pointer(devdata, NULL);
spin_unlock_irqrestore(&devdata_mutex, flags); spin_unlock_irqrestore(&devdata_mutex, flags);
synchronize_rcu(); synchronize_rcu();
......
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/of.h> #include <linux/of.h>
#include <asm/pSeries_reconfig.h>
#include <asm/hvcall.h> #include <asm/hvcall.h>
#include <asm/vio.h> #include <asm/vio.h>
......
...@@ -997,7 +997,7 @@ static struct smu_sdbp_header *smu_create_sdb_partition(int id) ...@@ -997,7 +997,7 @@ static struct smu_sdbp_header *smu_create_sdb_partition(int id)
"%02x !\n", id, hdr->id); "%02x !\n", id, hdr->id);
goto failure; goto failure;
} }
if (prom_add_property(smu->of_node, prop)) { if (of_add_property(smu->of_node, prop)) {
printk(KERN_DEBUG "SMU: Failed creating sdb-partition-%02x " printk(KERN_DEBUG "SMU: Failed creating sdb-partition-%02x "
"property !\n", id); "property !\n", id);
goto failure; goto failure;
......
...@@ -1028,13 +1028,36 @@ int of_parse_phandle_with_args(struct device_node *np, const char *list_name, ...@@ -1028,13 +1028,36 @@ int of_parse_phandle_with_args(struct device_node *np, const char *list_name,
} }
EXPORT_SYMBOL(of_parse_phandle_with_args); EXPORT_SYMBOL(of_parse_phandle_with_args);
#if defined(CONFIG_OF_DYNAMIC)
static int of_property_notify(int action, struct device_node *np,
struct property *prop)
{
struct of_prop_reconfig pr;
pr.dn = np;
pr.prop = prop;
return of_reconfig_notify(action, &pr);
}
#else
static int of_property_notify(int action, struct device_node *np,
struct property *prop)
{
return 0;
}
#endif
/** /**
* prom_add_property - Add a property to a node * of_add_property - Add a property to a node
*/ */
int prom_add_property(struct device_node *np, struct property *prop) int of_add_property(struct device_node *np, struct property *prop)
{ {
struct property **next; struct property **next;
unsigned long flags; unsigned long flags;
int rc;
rc = of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop);
if (rc)
return rc;
prop->next = NULL; prop->next = NULL;
write_lock_irqsave(&devtree_lock, flags); write_lock_irqsave(&devtree_lock, flags);
...@@ -1060,18 +1083,23 @@ int prom_add_property(struct device_node *np, struct property *prop) ...@@ -1060,18 +1083,23 @@ int prom_add_property(struct device_node *np, struct property *prop)
} }
/** /**
* prom_remove_property - Remove a property from a node. * of_remove_property - Remove a property from a node.
* *
* Note that we don't actually remove it, since we have given out * Note that we don't actually remove it, since we have given out
* who-knows-how-many pointers to the data using get-property. * who-knows-how-many pointers to the data using get-property.
* Instead we just move the property to the "dead properties" * Instead we just move the property to the "dead properties"
* list, so it won't be found any more. * list, so it won't be found any more.
*/ */
int prom_remove_property(struct device_node *np, struct property *prop) int of_remove_property(struct device_node *np, struct property *prop)
{ {
struct property **next; struct property **next;
unsigned long flags; unsigned long flags;
int found = 0; int found = 0;
int rc;
rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop);
if (rc)
return rc;
write_lock_irqsave(&devtree_lock, flags); write_lock_irqsave(&devtree_lock, flags);
next = &np->properties; next = &np->properties;
...@@ -1101,7 +1129,7 @@ int prom_remove_property(struct device_node *np, struct property *prop) ...@@ -1101,7 +1129,7 @@ int prom_remove_property(struct device_node *np, struct property *prop)
} }
/* /*
* prom_update_property - Update a property in a node, if the property does * of_update_property - Update a property in a node, if the property does
* not exist, add it. * not exist, add it.
* *
* Note that we don't actually remove it, since we have given out * 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,19 +1137,22 @@ int prom_remove_property(struct device_node *np, struct property *prop)
* Instead we just move the property to the "dead properties" list, * Instead we just move the property to the "dead properties" list,
* and add the new property to the property list * and add the new property to the property list
*/ */
int prom_update_property(struct device_node *np, int of_update_property(struct device_node *np, struct property *newprop)
struct property *newprop)
{ {
struct property **next, *oldprop; struct property **next, *oldprop;
unsigned long flags; unsigned long flags;
int found = 0; int rc, found = 0;
rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop);
if (rc)
return rc;
if (!newprop->name) if (!newprop->name)
return -EINVAL; return -EINVAL;
oldprop = of_find_property(np, newprop->name, NULL); oldprop = of_find_property(np, newprop->name, NULL);
if (!oldprop) if (!oldprop)
return prom_add_property(np, newprop); return of_add_property(np, newprop);
write_lock_irqsave(&devtree_lock, flags); write_lock_irqsave(&devtree_lock, flags);
next = &np->properties; next = &np->properties;
...@@ -1160,12 +1191,53 @@ int prom_update_property(struct device_node *np, ...@@ -1160,12 +1191,53 @@ int prom_update_property(struct device_node *np,
* device tree nodes. * device tree nodes.
*/ */
static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);
int of_reconfig_notifier_register(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&of_reconfig_chain, nb);
}
int of_reconfig_notifier_unregister(struct notifier_block *nb)
{
return blocking_notifier_chain_unregister(&of_reconfig_chain, nb);
}
int of_reconfig_notify(unsigned long action, void *p)
{
int rc;
rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p);
return notifier_to_errno(rc);
}
#ifdef CONFIG_PROC_DEVICETREE
static void of_add_proc_dt_entry(struct device_node *dn)
{
struct proc_dir_entry *ent;
ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde);
if (ent)
proc_device_tree_add_node(dn, ent);
}
#else
static void of_add_proc_dt_entry(struct device_node *dn)
{
return;
}
#endif
/** /**
* of_attach_node - Plug a device node into the tree and global list. * of_attach_node - Plug a device node into the tree and global list.
*/ */
void of_attach_node(struct device_node *np) int of_attach_node(struct device_node *np)
{ {
unsigned long flags; unsigned long flags;
int rc;
rc = of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np);
if (rc)
return rc;
write_lock_irqsave(&devtree_lock, flags); write_lock_irqsave(&devtree_lock, flags);
np->sibling = np->parent->child; np->sibling = np->parent->child;
...@@ -1173,24 +1245,61 @@ void of_attach_node(struct device_node *np) ...@@ -1173,24 +1245,61 @@ void of_attach_node(struct device_node *np)
np->parent->child = np; np->parent->child = np;
allnodes = np; allnodes = np;
write_unlock_irqrestore(&devtree_lock, flags); write_unlock_irqrestore(&devtree_lock, flags);
of_add_proc_dt_entry(np);
return 0;
} }
#ifdef CONFIG_PROC_DEVICETREE
static void of_remove_proc_dt_entry(struct device_node *dn)
{
struct device_node *parent = dn->parent;
struct property *prop = dn->properties;
while (prop) {
remove_proc_entry(prop->name, dn->pde);
prop = prop->next;
}
if (dn->pde)
remove_proc_entry(dn->pde->name, parent->pde);
}
#else
static void of_remove_proc_dt_entry(struct device_node *dn)
{
return;
}
#endif
/** /**
* of_detach_node - "Unplug" a node from the device tree. * of_detach_node - "Unplug" a node from the device tree.
* *
* The caller must hold a reference to the node. The memory associated with * The caller must hold a reference to the node. The memory associated with
* the node is not freed until its refcount goes to zero. * the node is not freed until its refcount goes to zero.
*/ */
void of_detach_node(struct device_node *np) int of_detach_node(struct device_node *np)
{ {
struct device_node *parent; struct device_node *parent;
unsigned long flags; unsigned long flags;
int rc = 0;
rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
if (rc)
return rc;
write_lock_irqsave(&devtree_lock, flags); write_lock_irqsave(&devtree_lock, flags);
if (of_node_check_flag(np, OF_DETACHED)) {
/* someone already detached it */
write_unlock_irqrestore(&devtree_lock, flags);
return rc;
}
parent = np->parent; parent = np->parent;
if (!parent) if (!parent) {
goto out_unlock; write_unlock_irqrestore(&devtree_lock, flags);
return rc;
}
if (allnodes == np) if (allnodes == np)
allnodes = np->allnext; allnodes = np->allnext;
...@@ -1215,9 +1324,10 @@ void of_detach_node(struct device_node *np) ...@@ -1215,9 +1324,10 @@ void of_detach_node(struct device_node *np)
} }
of_node_set_flag(np, OF_DETACHED); of_node_set_flag(np, OF_DETACHED);
out_unlock:
write_unlock_irqrestore(&devtree_lock, flags); write_unlock_irqrestore(&devtree_lock, flags);
of_remove_proc_dt_entry(np);
return rc;
} }
#endif /* defined(CONFIG_OF_DYNAMIC) */ #endif /* defined(CONFIG_OF_DYNAMIC) */
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/topology.h> #include <linux/topology.h>
#include <linux/notifier.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/errno.h> #include <asm/errno.h>
...@@ -267,16 +268,28 @@ extern int of_alias_get_id(struct device_node *np, const char *stem); ...@@ -267,16 +268,28 @@ extern int of_alias_get_id(struct device_node *np, const char *stem);
extern int of_machine_is_compatible(const char *compat); extern int of_machine_is_compatible(const char *compat);
extern int prom_add_property(struct device_node* np, struct property* prop); extern int of_add_property(struct device_node *np, struct property *prop);
extern int prom_remove_property(struct device_node *np, struct property *prop); extern int of_remove_property(struct device_node *np, struct property *prop);
extern int prom_update_property(struct device_node *np, extern int of_update_property(struct device_node *np, struct property *newprop);
struct property *newprop);
#if defined(CONFIG_OF_DYNAMIC)
/* For updating the device tree at runtime */ /* For updating the device tree at runtime */
extern void of_attach_node(struct device_node *); #define OF_RECONFIG_ATTACH_NODE 0x0001
extern void of_detach_node(struct device_node *); #define OF_RECONFIG_DETACH_NODE 0x0002
#endif #define OF_RECONFIG_ADD_PROPERTY 0x0003
#define OF_RECONFIG_REMOVE_PROPERTY 0x0004
#define OF_RECONFIG_UPDATE_PROPERTY 0x0005
struct of_prop_reconfig {
struct device_node *dn;
struct property *prop;
};
extern int of_reconfig_notifier_register(struct notifier_block *);
extern int of_reconfig_notifier_unregister(struct notifier_block *);
extern int of_reconfig_notify(unsigned long, void *);
extern int of_attach_node(struct device_node *);
extern int of_detach_node(struct device_node *);
#define of_match_ptr(_ptr) (_ptr) #define of_match_ptr(_ptr) (_ptr)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment