powerpc+of: Add of node/property notification chain for adds and removes
This patch moves the notification chain for updates to the device tree from the powerpc/pseries code to the base OF code. This makes this functionality available to all architectures. Additionally the notification chain is updated to allow notifications for property add/remove/update. To make this work a pointer to a new struct (of_prop_reconfig) is passed to the routines in the notification chain. The of_prop_reconfig property contains a pointer to the node containing the property and a pointer to the property itself. In the case of property updates, the property pointer refers to the new property. Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com> Acked-by: Rob Herring <rob.herring@calxeda.com> Acked-by: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:

committad av
Benjamin Herrenschmidt

förälder
f594972083
incheckning
1cf3d8b3d2
@@ -16,11 +16,11 @@
|
||||
#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>
|
||||
|
||||
/**
|
||||
@@ -55,28 +55,6 @@ static struct device_node *derive_parent(const char *path)
|
||||
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)
|
||||
{
|
||||
struct device_node *np;
|
||||
@@ -100,13 +78,12 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
err = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, np);
|
||||
err = of_attach_node(np);
|
||||
if (err) {
|
||||
printk(KERN_ERR "Failed to add device node %s\n", path);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
of_attach_node(np);
|
||||
of_node_put(np->parent);
|
||||
|
||||
return 0;
|
||||
@@ -134,9 +111,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, np);
|
||||
of_detach_node(np);
|
||||
|
||||
of_node_put(parent);
|
||||
of_node_put(np); /* Must decrement the refcount */
|
||||
return 0;
|
||||
@@ -381,10 +356,9 @@ static int do_remove_property(char *buf, size_t bufsize)
|
||||
static int do_update_property(char *buf, size_t bufsize)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct pSeries_reconfig_prop_update upd_value;
|
||||
unsigned char *value;
|
||||
char *name, *end, *next_prop;
|
||||
int rc, length;
|
||||
int length;
|
||||
struct property *newprop;
|
||||
buf = parse_node(buf, bufsize, &np);
|
||||
end = buf + bufsize;
|
||||
@@ -406,41 +380,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);
|
||||
|
||||
upd_value.node = np;
|
||||
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;
|
||||
return prom_update_property(np, newprop);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Referens i nytt ärende
Block a user