aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2007-06-19 02:08:00 -0400
committerPaul Mackerras <paulus@samba.org>2007-07-10 07:53:47 -0400
commit6a281856c02d2291df2f7d9df5bfdee2e7bdd747 (patch)
treef9dee0818d797edef6fdb59ddeb069883a7b191c /arch
parentd3b814bb1e8b0c63449a3430196c20cbe24a3e67 (diff)
[POWERPC] Add a warning to help trackdown device_node refcounting bugs
When the refcount for a device node goes to 0, we call the destructor - of_node_release(). This should only happen if we've already detached the node from the device tree. So add a flag OF_DETACHED which tracks detached-ness, and if we find ourselves in of_node_release() without it set, issue a warning and don't free the device_node. To avoid warning continuously reinitialise the kref to a sane value. Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/kernel/prom.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index bcd1c5ed44a3..6d5e601097a0 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -1375,8 +1375,17 @@ static void of_node_release(struct kref *kref)
1375 struct device_node *node = kref_to_device_node(kref); 1375 struct device_node *node = kref_to_device_node(kref);
1376 struct property *prop = node->properties; 1376 struct property *prop = node->properties;
1377 1377
1378 /* We should never be releasing nodes that haven't been detached. */
1379 if (!of_node_check_flag(node, OF_DETACHED)) {
1380 printk("WARNING: Bad of_node_put() on %s\n", node->full_name);
1381 dump_stack();
1382 kref_init(&node->kref);
1383 return;
1384 }
1385
1378 if (!of_node_check_flag(node, OF_DYNAMIC)) 1386 if (!of_node_check_flag(node, OF_DYNAMIC))
1379 return; 1387 return;
1388
1380 while (prop) { 1389 while (prop) {
1381 struct property *next = prop->next; 1390 struct property *next = prop->next;
1382 kfree(prop->name); 1391 kfree(prop->name);
@@ -1457,6 +1466,8 @@ void of_detach_node(const struct device_node *np)
1457 prevsib->sibling = np->sibling; 1466 prevsib->sibling = np->sibling;
1458 } 1467 }
1459 1468
1469 of_node_set_flag(np, OF_DETACHED);
1470
1460out_unlock: 1471out_unlock:
1461 write_unlock(&devtree_lock); 1472 write_unlock(&devtree_lock);
1462} 1473}