diff options
Diffstat (limited to 'drivers/of/dynamic.c')
-rw-r--r-- | drivers/of/dynamic.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c index cd3821a6444f..07d93753b12f 100644 --- a/drivers/of/dynamic.c +++ b/drivers/of/dynamic.c @@ -329,10 +329,30 @@ void of_node_release(struct kobject *kobj) { struct device_node *node = kobj_to_device_node(kobj); + /* + * can not use '"%pOF", node' in pr_err() calls from this function + * because an of_node_get(node) when refcount is already zero + * will result in an error and a stack dump + */ + /* We should never be releasing nodes that haven't been detached. */ if (!of_node_check_flag(node, OF_DETACHED)) { - pr_err("ERROR: Bad of_node_put() on %pOF\n", node); - dump_stack(); + + pr_err("ERROR: %s() detected bad of_node_put() on %pOF/%s\n", + __func__, node->parent, node->full_name); + + /* + * of unittests will test this path. Do not print the stack + * trace when the error is caused by unittest so that we do + * not display what a normal developer might reasonably + * consider a real bug. + */ + if (!IS_ENABLED(CONFIG_OF_UNITTEST) || + strcmp(node->parent->full_name, "testcase-data")) { + dump_stack(); + pr_err("ERROR: next of_node_put() on this node will result in a kobject warning 'refcount_t: underflow; use-after-free.'\n"); + } + return; } if (!of_node_check_flag(node, OF_DYNAMIC)) @@ -357,6 +377,10 @@ void of_node_release(struct kobject *kobj) __func__, node); } + if (node->child) + pr_err("ERROR: %s() unexpected children for %pOF/%s\n", + __func__, node->parent, node->full_name); + property_list_free(node->properties); property_list_free(node->deadprops); fwnode_links_purge(of_fwnode_handle(node)); @@ -419,7 +443,8 @@ struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags) * another node. The node data are dynamically allocated and all the node * flags have the OF_DYNAMIC & OF_DETACHED bits set. * - * Return: The newly allocated node or NULL on out of memory error. + * Return: The newly allocated node or NULL on out of memory error. Use + * of_node_put() on it when done to free the memory allocated for it. */ struct device_node *__of_node_dup(const struct device_node *np, const char *full_name) |