Commit e114d758 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: Fixes for OF device tree update code, from Nathan Lynch

From: anton@samba.org

Fixes for OF device tree update code, from Nathan Lynch
parent 494a55d8
...@@ -268,12 +268,10 @@ static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t coun ...@@ -268,12 +268,10 @@ static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t coun
static int do_remove_node(char *buf) static int do_remove_node(char *buf)
{ {
struct device_node *node; struct device_node *node;
int rv = 0; int rv = -ENODEV;
if ((node = of_find_node_by_path(buf))) if ((node = of_find_node_by_path(buf)))
of_remove_node(node); rv = of_remove_node(node);
else
rv = -ENODEV;
of_node_put(node); of_node_put(node);
return rv; return rv;
......
...@@ -2507,29 +2507,48 @@ int of_add_node(const char *path, struct property *proplist) ...@@ -2507,29 +2507,48 @@ int of_add_node(const char *path, struct property *proplist)
/* /*
* Remove an OF device node from the system. * Remove an OF device node from the system.
* Caller should have already "gotten" np.
*/ */
int of_remove_node(struct device_node *np) int of_remove_node(struct device_node *np)
{ {
struct device_node *parent, *child; struct device_node *parent, *child;
parent = of_get_parent(np); parent = of_get_parent(np);
child = of_get_next_child(np, NULL);
if (child && !child->child && !child->sibling) { if (!parent)
/* For now, we will allow removal of a
* node with one and only one child, so
* that we can support removing a slot with
* an IOA in it. More general support for
* subtree removal to be implemented later, if
* necessary.
*/
of_remove_node(child);
}
else if (child) {
of_node_put(child);
of_node_put(parent);
return -EINVAL; return -EINVAL;
/* Make sure we are not recursively removing
* more than one level of nodes. We need to
* allow this so we can remove a slot containing
* an IOA.
*/
for (child = of_get_next_child(np, NULL);
child != NULL;
child = of_get_next_child(np, child)) {
struct device_node *grandchild;
if ((grandchild = of_get_next_child(child, NULL))) {
/* Too deep */
of_node_put(grandchild);
of_node_put(child);
return -EBUSY;
}
}
/* Now that we're reasonably sure that we won't
* overflow our stack, remove any children of np.
*/
for (child = of_get_next_child(np, NULL);
child != NULL;
child = of_get_next_child(np, child)) {
int rc;
if ((rc = of_remove_node(child))) {
of_node_put(child);
return rc;
}
} }
of_node_put(child);
write_lock(&devtree_lock); write_lock(&devtree_lock);
OF_MARK_STALE(np); OF_MARK_STALE(np);
...@@ -2545,8 +2564,8 @@ int of_remove_node(struct device_node *np) ...@@ -2545,8 +2564,8 @@ int of_remove_node(struct device_node *np)
prev->allnext = np->allnext; prev->allnext = np->allnext;
} }
if (np->parent->child == np) if (parent->child == np)
np->parent->child = np->sibling; parent->child = np->sibling;
else { else {
struct device_node *prevsib; struct device_node *prevsib;
for (prevsib = np->parent->child; for (prevsib = np->parent->child;
......
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