diff options
| author | Dmitry Torokhov <[email protected]> | 2023-05-01 15:20:08 -0700 | 
|---|---|---|
| committer | Dmitry Torokhov <[email protected]> | 2023-05-01 15:20:08 -0700 | 
| commit | 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e (patch) | |
| tree | d57f3a63479a07b4e0cece029886e76e04feb984 /drivers/of/dynamic.c | |
| parent | 5dc63e56a9cf8df0b59c234a505a1653f1bdf885 (diff) | |
| parent | 53bea86b5712c7491bb3dae12e271666df0a308c (diff) | |
Merge branch 'next' into for-linus
Prepare input updates for 6.4 merge window.
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)  |