diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries/reconfig.c')
| -rw-r--r-- | arch/powerpc/platforms/pseries/reconfig.c | 130 |
1 files changed, 14 insertions, 116 deletions
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 1de2cbb9230..1c0a60d9886 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -12,59 +12,16 @@ */ #include <linux/kernel.h> -#include <linux/kref.h> #include <linux/notifier.h> #include <linux/proc_fs.h> #include <linux/slab.h> +#include <linux/of.h> #include <asm/prom.h> #include <asm/machdep.h> #include <asm/uaccess.h> -#include <asm/pSeries_reconfig.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) * @path: the full_name of a node to be added to the tree @@ -97,18 +54,6 @@ static struct device_node *derive_parent(const char *path) return parent; } -BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain); - -int pSeries_reconfig_notifier_register(struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb); -} - -void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) -{ - blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb); -} - static int pSeries_reconfig_add_node(const char *path, struct property *proplist) { struct device_node *np; @@ -124,7 +69,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist np->properties = proplist; of_node_set_flag(np, OF_DYNAMIC); - kref_init(&np->kref); + of_node_init(np); np->parent = derive_parent(path); if (IS_ERR(np->parent)) { @@ -132,18 +77,12 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist goto out_err; } - err = blocking_notifier_call_chain(&pSeries_reconfig_chain, - PSERIES_RECONFIG_ADD, np); - if (err == NOTIFY_BAD) { + err = of_attach_node(np); + if (err) { printk(KERN_ERR "Failed to add device node %s\n", path); - err = -ENOMEM; /* For now, safe to assume kmalloc failure */ goto out_err; } - of_attach_node(np); - - add_node_proc_entries(np); - of_node_put(np->parent); return 0; @@ -171,12 +110,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np) return -EBUSY; } - remove_node_proc_entries(np); - - blocking_notifier_call_chain(&pSeries_reconfig_chain, - PSERIES_RECONFIG_REMOVE, np); of_detach_node(np); - of_node_put(parent); of_node_put(np); /* Must decrement the refcount */ return 0; @@ -274,12 +208,11 @@ static struct property *new_property(const char *name, const int length, if (!new) return NULL; - if (!(new->name = kmalloc(strlen(name) + 1, GFP_KERNEL))) + if (!(new->name = kstrdup(name, GFP_KERNEL))) goto cleanup; if (!(new->value = kmalloc(length + 1, GFP_KERNEL))) goto cleanup; - strcpy(new->name, name); memcpy(new->value, value, length); *(((char *)new->value) + length) = 0; new->length = length; @@ -391,7 +324,7 @@ static int do_add_property(char *buf, size_t bufsize) if (!prop) return -ENOMEM; - prom_add_property(np, prop); + of_add_property(np, prop); return 0; } @@ -415,7 +348,7 @@ static int do_remove_property(char *buf, size_t bufsize) 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) @@ -423,8 +356,8 @@ static int do_update_property(char *buf, size_t bufsize) struct device_node *np; unsigned char *value; char *name, *end, *next_prop; - int rc, length; - struct property *newprop, *oldprop; + int length; + struct property *newprop; buf = parse_node(buf, bufsize, &np); end = buf + bufsize; @@ -435,6 +368,9 @@ static int do_update_property(char *buf, size_t bufsize) if (!next_prop) return -EINVAL; + if (!strlen(name)) + return -ENODEV; + newprop = new_property(name, length, value, NULL); if (!newprop) return -ENOMEM; @@ -442,45 +378,7 @@ static int do_update_property(char *buf, size_t bufsize) if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size")) slb_set_size(*(int *)value); - oldprop = of_find_property(np, name,NULL); - if (!oldprop) { - if (strlen(name)) - return prom_add_property(np, newprop); - return -ENODEV; - } - - rc = prom_update_property(np, newprop, oldprop); - 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 = blocking_notifier_call_chain(&pSeries_reconfig_chain, - action, value); - if (rc == NOTIFY_BAD) { - rc = prom_update_property(np, oldprop, newprop); - return -ENOMEM; - } - } - - return 0; + return of_update_property(np, newprop); } /** @@ -553,7 +451,7 @@ static int proc_ppc64_create_ofdt(void) ent = proc_create("powerpc/ofdt", S_IWUSR, NULL, &ofdt_fops); if (ent) - ent->size = 0; + proc_set_size(ent, 0); return 0; } |
