xref: /linux/drivers/of/dynamic.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1af6074fcSRob Herring // SPDX-License-Identifier: GPL-2.0
26afc0dc3SGrant Likely /*
36afc0dc3SGrant Likely  * Support for dynamic device trees.
46afc0dc3SGrant Likely  *
56afc0dc3SGrant Likely  * On some platforms, the device tree can be manipulated at runtime.
66afc0dc3SGrant Likely  * The routines in this section support adding, removing and changing
76afc0dc3SGrant Likely  * device tree nodes.
86afc0dc3SGrant Likely  */
96afc0dc3SGrant Likely 
10606ad42aSRob Herring #define pr_fmt(fmt)	"OF: " fmt
11606ad42aSRob Herring 
1240b0f174SRob Herring #include <linux/cleanup.h>
138917e738SHerve Codina #include <linux/device.h>
146afc0dc3SGrant Likely #include <linux/of.h>
156afc0dc3SGrant Likely #include <linux/spinlock.h>
166afc0dc3SGrant Likely #include <linux/slab.h>
176afc0dc3SGrant Likely #include <linux/string.h>
186afc0dc3SGrant Likely #include <linux/proc_fs.h>
196afc0dc3SGrant Likely 
206afc0dc3SGrant Likely #include "of_private.h"
216afc0dc3SGrant Likely 
kobj_to_device_node(struct kobject * kobj)224c2bb574SRob Herring static struct device_node *kobj_to_device_node(struct kobject *kobj)
234c2bb574SRob Herring {
244c2bb574SRob Herring 	return container_of(kobj, struct device_node, kobj);
254c2bb574SRob Herring }
264c2bb574SRob Herring 
276afc0dc3SGrant Likely /**
286afc0dc3SGrant Likely  * of_node_get() - Increment refcount of a node
296afc0dc3SGrant Likely  * @node:	Node to inc refcount, NULL is supported to simplify writing of
306afc0dc3SGrant Likely  *		callers
316afc0dc3SGrant Likely  *
328c8239c2SRob Herring  * Return: The node with refcount incremented.
336afc0dc3SGrant Likely  */
of_node_get(struct device_node * node)346afc0dc3SGrant Likely struct device_node *of_node_get(struct device_node *node)
356afc0dc3SGrant Likely {
366afc0dc3SGrant Likely 	if (node)
376afc0dc3SGrant Likely 		kobject_get(&node->kobj);
386afc0dc3SGrant Likely 	return node;
396afc0dc3SGrant Likely }
406afc0dc3SGrant Likely EXPORT_SYMBOL(of_node_get);
416afc0dc3SGrant Likely 
426afc0dc3SGrant Likely /**
436afc0dc3SGrant Likely  * of_node_put() - Decrement refcount of a node
446afc0dc3SGrant Likely  * @node:	Node to dec refcount, NULL is supported to simplify writing of
456afc0dc3SGrant Likely  *		callers
466afc0dc3SGrant Likely  */
of_node_put(struct device_node * node)476afc0dc3SGrant Likely void of_node_put(struct device_node *node)
486afc0dc3SGrant Likely {
496afc0dc3SGrant Likely 	if (node)
506afc0dc3SGrant Likely 		kobject_put(&node->kobj);
516afc0dc3SGrant Likely }
526afc0dc3SGrant Likely EXPORT_SYMBOL(of_node_put);
536afc0dc3SGrant Likely 
546afc0dc3SGrant Likely static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);
556afc0dc3SGrant Likely 
of_reconfig_notifier_register(struct notifier_block * nb)566afc0dc3SGrant Likely int of_reconfig_notifier_register(struct notifier_block *nb)
576afc0dc3SGrant Likely {
586afc0dc3SGrant Likely 	return blocking_notifier_chain_register(&of_reconfig_chain, nb);
596afc0dc3SGrant Likely }
606afc0dc3SGrant Likely EXPORT_SYMBOL_GPL(of_reconfig_notifier_register);
616afc0dc3SGrant Likely 
of_reconfig_notifier_unregister(struct notifier_block * nb)626afc0dc3SGrant Likely int of_reconfig_notifier_unregister(struct notifier_block *nb)
636afc0dc3SGrant Likely {
646afc0dc3SGrant Likely 	return blocking_notifier_chain_unregister(&of_reconfig_chain, nb);
656afc0dc3SGrant Likely }
666afc0dc3SGrant Likely EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister);
676afc0dc3SGrant Likely 
68914d9d83SRob Herring static const char *action_names[] = {
69914d9d83SRob Herring 	[0] = "INVALID",
7000aa3720SGrant Likely 	[OF_RECONFIG_ATTACH_NODE] = "ATTACH_NODE",
7100aa3720SGrant Likely 	[OF_RECONFIG_DETACH_NODE] = "DETACH_NODE",
7200aa3720SGrant Likely 	[OF_RECONFIG_ADD_PROPERTY] = "ADD_PROPERTY",
7300aa3720SGrant Likely 	[OF_RECONFIG_REMOVE_PROPERTY] = "REMOVE_PROPERTY",
7400aa3720SGrant Likely 	[OF_RECONFIG_UPDATE_PROPERTY] = "UPDATE_PROPERTY",
7500aa3720SGrant Likely };
7600aa3720SGrant Likely 
7727a02f26SRob Herring #define _do_print(func, prefix, action, node, prop, ...) ({	\
7827a02f26SRob Herring 	func("changeset: " prefix "%-15s %pOF%s%s\n",		\
7927a02f26SRob Herring 	     ##__VA_ARGS__, action_names[action], node,		\
8027a02f26SRob Herring 	     prop ? ":" : "", prop ? prop->name : "");		\
8127a02f26SRob Herring })
8227a02f26SRob Herring #define of_changeset_action_err(...) _do_print(pr_err, __VA_ARGS__)
8327a02f26SRob Herring #define of_changeset_action_debug(...) _do_print(pr_debug, __VA_ARGS__)
8427a02f26SRob Herring 
of_reconfig_notify(unsigned long action,struct of_reconfig_data * p)85f5242e5aSGrant Likely int of_reconfig_notify(unsigned long action, struct of_reconfig_data *p)
866afc0dc3SGrant Likely {
876afc0dc3SGrant Likely 	int rc;
88f5242e5aSGrant Likely 	struct of_reconfig_data *pr = p;
896afc0dc3SGrant Likely 
9027a02f26SRob Herring 	of_changeset_action_debug("notify: ", action, pr->dn, pr->prop);
9100aa3720SGrant Likely 
926afc0dc3SGrant Likely 	rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p);
936afc0dc3SGrant Likely 	return notifier_to_errno(rc);
946afc0dc3SGrant Likely }
956afc0dc3SGrant Likely 
96b53a2340SPantelis Antoniou /*
97b53a2340SPantelis Antoniou  * of_reconfig_get_state_change()	- Returns new state of device
98b53a2340SPantelis Antoniou  * @action	- action of the of notifier
99b53a2340SPantelis Antoniou  * @arg		- argument of the of notifier
100b53a2340SPantelis Antoniou  *
101b53a2340SPantelis Antoniou  * Returns the new state of a device based on the notifier used.
1028c8239c2SRob Herring  *
103d7997278SLuca Ceresoli  * Return: OF_RECONFIG_CHANGE_REMOVE on device going from enabled to
104d7997278SLuca Ceresoli  * disabled, OF_RECONFIG_CHANGE_ADD on device going from disabled to
105d7997278SLuca Ceresoli  * enabled and OF_RECONFIG_NO_CHANGE on no change.
106b53a2340SPantelis Antoniou  */
of_reconfig_get_state_change(unsigned long action,struct of_reconfig_data * pr)107f5242e5aSGrant Likely int of_reconfig_get_state_change(unsigned long action, struct of_reconfig_data *pr)
108b53a2340SPantelis Antoniou {
109f5242e5aSGrant Likely 	struct property *prop, *old_prop = NULL;
110b53a2340SPantelis Antoniou 	int is_status, status_state, old_status_state, prev_state, new_state;
111b53a2340SPantelis Antoniou 
112b53a2340SPantelis Antoniou 	/* figure out if a device should be created or destroyed */
113b53a2340SPantelis Antoniou 	switch (action) {
114b53a2340SPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
115b53a2340SPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
116f5242e5aSGrant Likely 		prop = of_find_property(pr->dn, "status", NULL);
117b53a2340SPantelis Antoniou 		break;
118b53a2340SPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
119b53a2340SPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
120b53a2340SPantelis Antoniou 		prop = pr->prop;
121b53a2340SPantelis Antoniou 		break;
122b53a2340SPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
123b53a2340SPantelis Antoniou 		prop = pr->prop;
124b53a2340SPantelis Antoniou 		old_prop = pr->old_prop;
125b53a2340SPantelis Antoniou 		break;
126b53a2340SPantelis Antoniou 	default:
127b53a2340SPantelis Antoniou 		return OF_RECONFIG_NO_CHANGE;
128b53a2340SPantelis Antoniou 	}
129b53a2340SPantelis Antoniou 
130b53a2340SPantelis Antoniou 	is_status = 0;
131b53a2340SPantelis Antoniou 	status_state = -1;
132b53a2340SPantelis Antoniou 	old_status_state = -1;
133b53a2340SPantelis Antoniou 	prev_state = -1;
134b53a2340SPantelis Antoniou 	new_state = -1;
135b53a2340SPantelis Antoniou 
136b53a2340SPantelis Antoniou 	if (prop && !strcmp(prop->name, "status")) {
137b53a2340SPantelis Antoniou 		is_status = 1;
138b53a2340SPantelis Antoniou 		status_state = !strcmp(prop->value, "okay") ||
139b53a2340SPantelis Antoniou 			       !strcmp(prop->value, "ok");
140b53a2340SPantelis Antoniou 		if (old_prop)
141b53a2340SPantelis Antoniou 			old_status_state = !strcmp(old_prop->value, "okay") ||
142b53a2340SPantelis Antoniou 					   !strcmp(old_prop->value, "ok");
143b53a2340SPantelis Antoniou 	}
144b53a2340SPantelis Antoniou 
145b53a2340SPantelis Antoniou 	switch (action) {
146b53a2340SPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
147b53a2340SPantelis Antoniou 		prev_state = 0;
148b53a2340SPantelis Antoniou 		/* -1 & 0 status either missing or okay */
149b53a2340SPantelis Antoniou 		new_state = status_state != 0;
150b53a2340SPantelis Antoniou 		break;
151b53a2340SPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
152b53a2340SPantelis Antoniou 		/* -1 & 0 status either missing or okay */
153b53a2340SPantelis Antoniou 		prev_state = status_state != 0;
154b53a2340SPantelis Antoniou 		new_state = 0;
155b53a2340SPantelis Antoniou 		break;
156b53a2340SPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
157b53a2340SPantelis Antoniou 		if (is_status) {
158b53a2340SPantelis Antoniou 			/* no status property -> enabled (legacy) */
159b53a2340SPantelis Antoniou 			prev_state = 1;
160b53a2340SPantelis Antoniou 			new_state = status_state;
161b53a2340SPantelis Antoniou 		}
162b53a2340SPantelis Antoniou 		break;
163b53a2340SPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
164b53a2340SPantelis Antoniou 		if (is_status) {
165b53a2340SPantelis Antoniou 			prev_state = status_state;
166b53a2340SPantelis Antoniou 			/* no status property -> enabled (legacy) */
167b53a2340SPantelis Antoniou 			new_state = 1;
168b53a2340SPantelis Antoniou 		}
169b53a2340SPantelis Antoniou 		break;
170b53a2340SPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
171b53a2340SPantelis Antoniou 		if (is_status) {
172b53a2340SPantelis Antoniou 			prev_state = old_status_state != 0;
173b53a2340SPantelis Antoniou 			new_state = status_state != 0;
174b53a2340SPantelis Antoniou 		}
175b53a2340SPantelis Antoniou 		break;
176b53a2340SPantelis Antoniou 	}
177b53a2340SPantelis Antoniou 
178b53a2340SPantelis Antoniou 	if (prev_state == new_state)
179b53a2340SPantelis Antoniou 		return OF_RECONFIG_NO_CHANGE;
180b53a2340SPantelis Antoniou 
181b53a2340SPantelis Antoniou 	return new_state ? OF_RECONFIG_CHANGE_ADD : OF_RECONFIG_CHANGE_REMOVE;
182b53a2340SPantelis Antoniou }
183b53a2340SPantelis Antoniou EXPORT_SYMBOL_GPL(of_reconfig_get_state_change);
184b53a2340SPantelis Antoniou 
of_property_notify(int action,struct device_node * np,struct property * prop,struct property * oldprop)1856afc0dc3SGrant Likely int of_property_notify(int action, struct device_node *np,
186259092a3SGrant Likely 		       struct property *prop, struct property *oldprop)
1876afc0dc3SGrant Likely {
188f5242e5aSGrant Likely 	struct of_reconfig_data pr;
1896afc0dc3SGrant Likely 
1906afc0dc3SGrant Likely 	/* only call notifiers if the node is attached */
1916afc0dc3SGrant Likely 	if (!of_node_is_attached(np))
1926afc0dc3SGrant Likely 		return 0;
1936afc0dc3SGrant Likely 
1946afc0dc3SGrant Likely 	pr.dn = np;
1956afc0dc3SGrant Likely 	pr.prop = prop;
196259092a3SGrant Likely 	pr.old_prop = oldprop;
1976afc0dc3SGrant Likely 	return of_reconfig_notify(action, &pr);
1986afc0dc3SGrant Likely }
1996afc0dc3SGrant Likely 
__of_attach_node(struct device_node * np)20024996951SFrank Rowand static void __of_attach_node(struct device_node *np)
201d8c50088SPantelis Antoniou {
202a25095d4SGrant Likely 	const __be32 *phandle;
203a25095d4SGrant Likely 	int sz;
204fab610beSRob Herring 	unsigned long flags;
205fab610beSRob Herring 
206fab610beSRob Herring 	raw_spin_lock_irqsave(&devtree_lock, flags);
207a25095d4SGrant Likely 
208f9627881SFrank Rowand 	if (!of_node_check_flag(np, OF_OVERLAY)) {
209f9627881SFrank Rowand 		np->name = __of_get_property(np, "name", NULL);
210f9627881SFrank Rowand 		if (!np->name)
211f9627881SFrank Rowand 			np->name = "<NULL>";
212a25095d4SGrant Likely 
213a25095d4SGrant Likely 		phandle = __of_get_property(np, "phandle", &sz);
214a25095d4SGrant Likely 		if (!phandle)
215a25095d4SGrant Likely 			phandle = __of_get_property(np, "linux,phandle", &sz);
216f76502aaSGeert Uytterhoeven 		if (IS_ENABLED(CONFIG_PPC_PSERIES) && !phandle)
217a25095d4SGrant Likely 			phandle = __of_get_property(np, "ibm,phandle", &sz);
218f9627881SFrank Rowand 		if (phandle && (sz >= 4))
219f9627881SFrank Rowand 			np->phandle = be32_to_cpup(phandle);
220f9627881SFrank Rowand 		else
221f9627881SFrank Rowand 			np->phandle = 0;
222f9627881SFrank Rowand 	}
223a25095d4SGrant Likely 
2246162dbe4SGrant Likely 	np->child = NULL;
225d8c50088SPantelis Antoniou 	np->sibling = np->parent->child;
226d8c50088SPantelis Antoniou 	np->parent->child = np;
227d8c50088SPantelis Antoniou 	of_node_clear_flag(np, OF_DETACHED);
2281a50d940SGeert Uytterhoeven 	np->fwnode.flags |= FWNODE_FLAG_NOT_DEVICE;
229fab610beSRob Herring 
230fab610beSRob Herring 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
231fab610beSRob Herring 
232fab610beSRob Herring 	__of_attach_node_sysfs(np);
233d8c50088SPantelis Antoniou }
234d8c50088SPantelis Antoniou 
2356afc0dc3SGrant Likely /**
2366afc0dc3SGrant Likely  * of_attach_node() - Plug a device node into the tree and global list.
2373cb025d9SLee Jones  * @np:		Pointer to the caller's Device Node
2386afc0dc3SGrant Likely  */
of_attach_node(struct device_node * np)2396afc0dc3SGrant Likely int of_attach_node(struct device_node *np)
2406afc0dc3SGrant Likely {
241f5242e5aSGrant Likely 	struct of_reconfig_data rd;
2426afc0dc3SGrant Likely 
243f5242e5aSGrant Likely 	memset(&rd, 0, sizeof(rd));
244f5242e5aSGrant Likely 	rd.dn = np;
245f5242e5aSGrant Likely 
2468a2b22a2SGrant Likely 	mutex_lock(&of_mutex);
247d8c50088SPantelis Antoniou 	__of_attach_node(np);
2488a2b22a2SGrant Likely 	mutex_unlock(&of_mutex);
249259092a3SGrant Likely 
250f5242e5aSGrant Likely 	of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, &rd);
251259092a3SGrant Likely 
2526afc0dc3SGrant Likely 	return 0;
2536afc0dc3SGrant Likely }
2546afc0dc3SGrant Likely 
__of_detach_node(struct device_node * np)255d8c50088SPantelis Antoniou void __of_detach_node(struct device_node *np)
2566afc0dc3SGrant Likely {
2576afc0dc3SGrant Likely 	struct device_node *parent;
258fab610beSRob Herring 	unsigned long flags;
2596afc0dc3SGrant Likely 
260fab610beSRob Herring 	raw_spin_lock_irqsave(&devtree_lock, flags);
2616afc0dc3SGrant Likely 
2626afc0dc3SGrant Likely 	parent = np->parent;
263fab610beSRob Herring 	if (WARN_ON(of_node_check_flag(np, OF_DETACHED) || !parent)) {
264fab610beSRob Herring 		raw_spin_unlock_irqrestore(&devtree_lock, flags);
265d8c50088SPantelis Antoniou 		return;
266fab610beSRob Herring 	}
2676afc0dc3SGrant Likely 
2686afc0dc3SGrant Likely 	if (parent->child == np)
2696afc0dc3SGrant Likely 		parent->child = np->sibling;
2706afc0dc3SGrant Likely 	else {
2716afc0dc3SGrant Likely 		struct device_node *prevsib;
2726afc0dc3SGrant Likely 		for (prevsib = np->parent->child;
2736afc0dc3SGrant Likely 		     prevsib->sibling != np;
2746afc0dc3SGrant Likely 		     prevsib = prevsib->sibling)
2756afc0dc3SGrant Likely 			;
2766afc0dc3SGrant Likely 		prevsib->sibling = np->sibling;
2776afc0dc3SGrant Likely 	}
2786afc0dc3SGrant Likely 
2796afc0dc3SGrant Likely 	of_node_set_flag(np, OF_DETACHED);
2805801169aSFrank Rowand 
2815801169aSFrank Rowand 	/* race with of_find_node_by_phandle() prevented by devtree_lock */
28290dc0d1cSRob Herring 	__of_phandle_cache_inv_entry(np->phandle);
283fab610beSRob Herring 
284fab610beSRob Herring 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
285fab610beSRob Herring 
286fab610beSRob Herring 	__of_detach_node_sysfs(np);
287d8c50088SPantelis Antoniou }
288d8c50088SPantelis Antoniou 
289d8c50088SPantelis Antoniou /**
290d8c50088SPantelis Antoniou  * of_detach_node() - "Unplug" a node from the device tree.
2913cb025d9SLee Jones  * @np:		Pointer to the caller's Device Node
292d8c50088SPantelis Antoniou  */
of_detach_node(struct device_node * np)293d8c50088SPantelis Antoniou int of_detach_node(struct device_node *np)
294d8c50088SPantelis Antoniou {
295f5242e5aSGrant Likely 	struct of_reconfig_data rd;
296d8c50088SPantelis Antoniou 
297f5242e5aSGrant Likely 	memset(&rd, 0, sizeof(rd));
298f5242e5aSGrant Likely 	rd.dn = np;
299f5242e5aSGrant Likely 
3008a2b22a2SGrant Likely 	mutex_lock(&of_mutex);
301d8c50088SPantelis Antoniou 	__of_detach_node(np);
3028a2b22a2SGrant Likely 	mutex_unlock(&of_mutex);
303259092a3SGrant Likely 
304f5242e5aSGrant Likely 	of_reconfig_notify(OF_RECONFIG_DETACH_NODE, &rd);
305259092a3SGrant Likely 
30658fb82ccSDing Xiang 	return 0;
3076afc0dc3SGrant Likely }
308bb91f923SGavin Shan EXPORT_SYMBOL_GPL(of_detach_node);
3096afc0dc3SGrant Likely 
__of_prop_free(struct property * prop)3101c5e3d9bSRob Herring void __of_prop_free(struct property *prop)
3111c5e3d9bSRob Herring {
3121c5e3d9bSRob Herring 	kfree(prop->name);
3131c5e3d9bSRob Herring 	kfree(prop->value);
3141c5e3d9bSRob Herring 	kfree(prop);
3151c5e3d9bSRob Herring }
3161c5e3d9bSRob Herring 
property_list_free(struct property * prop_list)317070ea018SLixin Wang static void property_list_free(struct property *prop_list)
318070ea018SLixin Wang {
319070ea018SLixin Wang 	struct property *prop, *next;
320070ea018SLixin Wang 
321070ea018SLixin Wang 	for (prop = prop_list; prop != NULL; prop = next) {
322070ea018SLixin Wang 		next = prop->next;
3231c5e3d9bSRob Herring 		__of_prop_free(prop);
324070ea018SLixin Wang 	}
325070ea018SLixin Wang }
326070ea018SLixin Wang 
3276afc0dc3SGrant Likely /**
3286afc0dc3SGrant Likely  * of_node_release() - release a dynamically allocated node
3293cb025d9SLee Jones  * @kobj: kernel object of the node to be released
3306afc0dc3SGrant Likely  *
3316afc0dc3SGrant Likely  * In of_node_put() this function is passed to kref_put() as the destructor.
3326afc0dc3SGrant Likely  */
of_node_release(struct kobject * kobj)3336afc0dc3SGrant Likely void of_node_release(struct kobject *kobj)
3346afc0dc3SGrant Likely {
3356afc0dc3SGrant Likely 	struct device_node *node = kobj_to_device_node(kobj);
3366afc0dc3SGrant Likely 
33723522dd7SFrank Rowand 	/*
33823522dd7SFrank Rowand 	 * can not use '"%pOF", node' in pr_err() calls from this function
33923522dd7SFrank Rowand 	 * because an of_node_get(node) when refcount is already zero
34023522dd7SFrank Rowand 	 * will result in an error and a stack dump
34123522dd7SFrank Rowand 	 */
34223522dd7SFrank Rowand 
3436afc0dc3SGrant Likely 	/* We should never be releasing nodes that haven't been detached. */
3446afc0dc3SGrant Likely 	if (!of_node_check_flag(node, OF_DETACHED)) {
34523522dd7SFrank Rowand 
34623522dd7SFrank Rowand 		pr_err("ERROR: %s() detected bad of_node_put() on %pOF/%s\n",
34723522dd7SFrank Rowand 			__func__, node->parent, node->full_name);
34874df14cdSFrank Rowand 
34974df14cdSFrank Rowand 		/*
35074df14cdSFrank Rowand 		 * of unittests will test this path.  Do not print the stack
35174df14cdSFrank Rowand 		 * trace when the error is caused by unittest so that we do
35274df14cdSFrank Rowand 		 * not display what a normal developer might reasonably
35374df14cdSFrank Rowand 		 * consider a real bug.
35474df14cdSFrank Rowand 		 */
35574df14cdSFrank Rowand 		if (!IS_ENABLED(CONFIG_OF_UNITTEST) ||
35674df14cdSFrank Rowand 		    strcmp(node->parent->full_name, "testcase-data")) {
3576afc0dc3SGrant Likely 			dump_stack();
358b4858dc6SColin Ian King 			pr_err("ERROR: next of_node_put() on this node will result in a kobject warning 'refcount_t: underflow; use-after-free.'\n");
35974df14cdSFrank Rowand 		}
36074df14cdSFrank Rowand 
3616afc0dc3SGrant Likely 		return;
3626afc0dc3SGrant Likely 	}
3636afc0dc3SGrant Likely 	if (!of_node_check_flag(node, OF_DYNAMIC))
3646afc0dc3SGrant Likely 		return;
3656afc0dc3SGrant Likely 
366144552c7SFrank Rowand 	if (of_node_check_flag(node, OF_OVERLAY)) {
367144552c7SFrank Rowand 
368144552c7SFrank Rowand 		if (!of_node_check_flag(node, OF_OVERLAY_FREE_CSET)) {
369144552c7SFrank Rowand 			/* premature refcount of zero, do not free memory */
370144552c7SFrank Rowand 			pr_err("ERROR: memory leak before free overlay changeset,  %pOF\n",
371144552c7SFrank Rowand 			       node);
372144552c7SFrank Rowand 			return;
373144552c7SFrank Rowand 		}
374144552c7SFrank Rowand 
375144552c7SFrank Rowand 		/*
376144552c7SFrank Rowand 		 * If node->properties non-empty then properties were added
377144552c7SFrank Rowand 		 * to this node either by different overlay that has not
378144552c7SFrank Rowand 		 * yet been removed, or by a non-overlay mechanism.
379144552c7SFrank Rowand 		 */
380144552c7SFrank Rowand 		if (node->properties)
381144552c7SFrank Rowand 			pr_err("ERROR: %s(), unexpected properties in %pOF\n",
382144552c7SFrank Rowand 			       __func__, node);
383144552c7SFrank Rowand 	}
384144552c7SFrank Rowand 
385ec0b7e24SFrank Rowand 	if (node->child)
386ec0b7e24SFrank Rowand 		pr_err("ERROR: %s() unexpected children for %pOF/%s\n",
387ec0b7e24SFrank Rowand 			__func__, node->parent, node->full_name);
388ec0b7e24SFrank Rowand 
389070ea018SLixin Wang 	property_list_free(node->properties);
390070ea018SLixin Wang 	property_list_free(node->deadprops);
3917b337cb3SSaravana Kannan 	fwnode_links_purge(of_fwnode_handle(node));
3926afc0dc3SGrant Likely 
3936afc0dc3SGrant Likely 	kfree(node->full_name);
3946afc0dc3SGrant Likely 	kfree(node->data);
3956afc0dc3SGrant Likely 	kfree(node);
3966afc0dc3SGrant Likely }
39769843396SPantelis Antoniou 
39869843396SPantelis Antoniou /**
39969843396SPantelis Antoniou  * __of_prop_dup - Copy a property dynamically.
40069843396SPantelis Antoniou  * @prop:	Property to copy
40169843396SPantelis Antoniou  * @allocflags:	Allocation flags (typically pass GFP_KERNEL)
40269843396SPantelis Antoniou  *
40369843396SPantelis Antoniou  * Copy a property by dynamically allocating the memory of both the
40427b3383aSGeert Uytterhoeven  * property structure and the property name & contents. The property's
40569843396SPantelis Antoniou  * flags have the OF_DYNAMIC bit set so that we can differentiate between
40669843396SPantelis Antoniou  * dynamically allocated properties and not.
4078c8239c2SRob Herring  *
4088c8239c2SRob Herring  * Return: The newly allocated property or NULL on out of memory error.
40969843396SPantelis Antoniou  */
__of_prop_dup(const struct property * prop,gfp_t allocflags)41069843396SPantelis Antoniou struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags)
41169843396SPantelis Antoniou {
41269843396SPantelis Antoniou 	struct property *new;
41369843396SPantelis Antoniou 
41469843396SPantelis Antoniou 	new = kzalloc(sizeof(*new), allocflags);
41569843396SPantelis Antoniou 	if (!new)
41669843396SPantelis Antoniou 		return NULL;
41769843396SPantelis Antoniou 
41869843396SPantelis Antoniou 	/*
41969843396SPantelis Antoniou 	 * NOTE: There is no check for zero length value.
420b6ae5dc5SGrant Likely 	 * In case of a boolean property, this will allocate a value
42169843396SPantelis Antoniou 	 * of zero bytes. We do this to work around the use
42269843396SPantelis Antoniou 	 * of of_get_property() calls on boolean values.
42369843396SPantelis Antoniou 	 */
42469843396SPantelis Antoniou 	new->name = kstrdup(prop->name, allocflags);
42569843396SPantelis Antoniou 	new->value = kmemdup(prop->value, prop->length, allocflags);
42669843396SPantelis Antoniou 	new->length = prop->length;
42769843396SPantelis Antoniou 	if (!new->name || !new->value)
42869843396SPantelis Antoniou 		goto err_free;
42969843396SPantelis Antoniou 
43069843396SPantelis Antoniou 	/* mark the property as dynamic */
43169843396SPantelis Antoniou 	of_property_set_flag(new, OF_DYNAMIC);
43269843396SPantelis Antoniou 
43369843396SPantelis Antoniou 	return new;
43469843396SPantelis Antoniou 
43569843396SPantelis Antoniou  err_free:
4361c5e3d9bSRob Herring 	__of_prop_free(new);
43769843396SPantelis Antoniou 	return NULL;
43869843396SPantelis Antoniou }
43969843396SPantelis Antoniou 
44069843396SPantelis Antoniou /**
441e5179581SGrant Likely  * __of_node_dup() - Duplicate or create an empty device node dynamically.
442b89dae18SFrank Rowand  * @np:		if not NULL, contains properties to be duplicated in new node
443b89dae18SFrank Rowand  * @full_name:	string value to be duplicated into new node's full_name field
44469843396SPantelis Antoniou  *
445b89dae18SFrank Rowand  * Create a device tree node, optionally duplicating the properties of
446b89dae18SFrank Rowand  * another node.  The node data are dynamically allocated and all the node
447b89dae18SFrank Rowand  * flags have the OF_DYNAMIC & OF_DETACHED bits set.
448b89dae18SFrank Rowand  *
449d9194e00SFrank Rowand  * Return: The newly allocated node or NULL on out of memory error.  Use
450d9194e00SFrank Rowand  * of_node_put() on it when done to free the memory allocated for it.
45169843396SPantelis Antoniou  */
__of_node_dup(const struct device_node * np,const char * full_name)452b89dae18SFrank Rowand struct device_node *__of_node_dup(const struct device_node *np,
453b89dae18SFrank Rowand 				  const char *full_name)
45469843396SPantelis Antoniou {
45569843396SPantelis Antoniou 	struct device_node *node;
45669843396SPantelis Antoniou 
457ef8bbd73SGrant Likely 	node = kzalloc(sizeof(*node), GFP_KERNEL);
45869843396SPantelis Antoniou 	if (!node)
45969843396SPantelis Antoniou 		return NULL;
460b89dae18SFrank Rowand 	node->full_name = kstrdup(full_name, GFP_KERNEL);
461e5179581SGrant Likely 	if (!node->full_name) {
462e5179581SGrant Likely 		kfree(node);
463e5179581SGrant Likely 		return NULL;
464e5179581SGrant Likely 	}
46569843396SPantelis Antoniou 
466ef8bbd73SGrant Likely 	of_node_set_flag(node, OF_DYNAMIC);
467ef8bbd73SGrant Likely 	of_node_set_flag(node, OF_DETACHED);
46869843396SPantelis Antoniou 	of_node_init(node);
46969843396SPantelis Antoniou 
470e5179581SGrant Likely 	/* Iterate over and duplicate all properties */
471e5179581SGrant Likely 	if (np) {
472e5179581SGrant Likely 		struct property *pp, *new_pp;
473e5179581SGrant Likely 		for_each_property_of_node(np, pp) {
474e5179581SGrant Likely 			new_pp = __of_prop_dup(pp, GFP_KERNEL);
475e5179581SGrant Likely 			if (!new_pp)
476e5179581SGrant Likely 				goto err_prop;
477e5179581SGrant Likely 			if (__of_add_property(node, new_pp)) {
4781c5e3d9bSRob Herring 				__of_prop_free(new_pp);
479e5179581SGrant Likely 				goto err_prop;
480e5179581SGrant Likely 			}
481e5179581SGrant Likely 		}
482e5179581SGrant Likely 	}
48369843396SPantelis Antoniou 	return node;
48469843396SPantelis Antoniou 
485e5179581SGrant Likely  err_prop:
486e5179581SGrant Likely 	of_node_put(node); /* Frees the node and properties */
48769843396SPantelis Antoniou 	return NULL;
48869843396SPantelis Antoniou }
489201c910bSPantelis Antoniou 
490b544fc2bSLizhi Hou /**
491b544fc2bSLizhi Hou  * of_changeset_create_node - Dynamically create a device node and attach to
492b544fc2bSLizhi Hou  * a given changeset.
493b544fc2bSLizhi Hou  *
494b544fc2bSLizhi Hou  * @ocs: Pointer to changeset
495b544fc2bSLizhi Hou  * @parent: Pointer to parent device node
496b544fc2bSLizhi Hou  * @full_name: Node full name
497b544fc2bSLizhi Hou  *
498b544fc2bSLizhi Hou  * Return: Pointer to the created device node or NULL in case of an error.
499b544fc2bSLizhi Hou  */
of_changeset_create_node(struct of_changeset * ocs,struct device_node * parent,const char * full_name)500b544fc2bSLizhi Hou struct device_node *of_changeset_create_node(struct of_changeset *ocs,
501b544fc2bSLizhi Hou 					     struct device_node *parent,
502b544fc2bSLizhi Hou 					     const char *full_name)
503b544fc2bSLizhi Hou {
504b544fc2bSLizhi Hou 	struct device_node *np;
505b544fc2bSLizhi Hou 	int ret;
506b544fc2bSLizhi Hou 
507b544fc2bSLizhi Hou 	np = __of_node_dup(NULL, full_name);
508b544fc2bSLizhi Hou 	if (!np)
509b544fc2bSLizhi Hou 		return NULL;
510b544fc2bSLizhi Hou 	np->parent = parent;
511b544fc2bSLizhi Hou 
512b544fc2bSLizhi Hou 	ret = of_changeset_attach_node(ocs, np);
513b544fc2bSLizhi Hou 	if (ret) {
514b544fc2bSLizhi Hou 		of_node_put(np);
515b544fc2bSLizhi Hou 		return NULL;
516b544fc2bSLizhi Hou 	}
517b544fc2bSLizhi Hou 
518b544fc2bSLizhi Hou 	return np;
519b544fc2bSLizhi Hou }
520b544fc2bSLizhi Hou EXPORT_SYMBOL(of_changeset_create_node);
521b544fc2bSLizhi Hou 
__of_changeset_entry_destroy(struct of_changeset_entry * ce)522201c910bSPantelis Antoniou static void __of_changeset_entry_destroy(struct of_changeset_entry *ce)
523201c910bSPantelis Antoniou {
524144552c7SFrank Rowand 	if (ce->action == OF_RECONFIG_ATTACH_NODE &&
525144552c7SFrank Rowand 	    of_node_check_flag(ce->np, OF_OVERLAY)) {
526144552c7SFrank Rowand 		if (kref_read(&ce->np->kobj.kref) > 1) {
527144552c7SFrank Rowand 			pr_err("ERROR: memory leak, expected refcount 1 instead of %d, of_node_get()/of_node_put() unbalanced - destroy cset entry: attach overlay node %pOF\n",
528144552c7SFrank Rowand 			       kref_read(&ce->np->kobj.kref), ce->np);
529144552c7SFrank Rowand 		} else {
530144552c7SFrank Rowand 			of_node_set_flag(ce->np, OF_OVERLAY_FREE_CSET);
531144552c7SFrank Rowand 		}
532144552c7SFrank Rowand 	}
533144552c7SFrank Rowand 
534201c910bSPantelis Antoniou 	of_node_put(ce->np);
535201c910bSPantelis Antoniou 	list_del(&ce->node);
536201c910bSPantelis Antoniou 	kfree(ce);
537201c910bSPantelis Antoniou }
538201c910bSPantelis Antoniou 
__of_changeset_entry_invert(struct of_changeset_entry * ce,struct of_changeset_entry * rce)539201c910bSPantelis Antoniou static void __of_changeset_entry_invert(struct of_changeset_entry *ce,
540201c910bSPantelis Antoniou 					  struct of_changeset_entry *rce)
541201c910bSPantelis Antoniou {
542201c910bSPantelis Antoniou 	memcpy(rce, ce, sizeof(*rce));
543201c910bSPantelis Antoniou 
544201c910bSPantelis Antoniou 	switch (ce->action) {
545201c910bSPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
546201c910bSPantelis Antoniou 		rce->action = OF_RECONFIG_DETACH_NODE;
547201c910bSPantelis Antoniou 		break;
548201c910bSPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
549201c910bSPantelis Antoniou 		rce->action = OF_RECONFIG_ATTACH_NODE;
550201c910bSPantelis Antoniou 		break;
551201c910bSPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
552201c910bSPantelis Antoniou 		rce->action = OF_RECONFIG_REMOVE_PROPERTY;
553201c910bSPantelis Antoniou 		break;
554201c910bSPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
555201c910bSPantelis Antoniou 		rce->action = OF_RECONFIG_ADD_PROPERTY;
556201c910bSPantelis Antoniou 		break;
557201c910bSPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
558201c910bSPantelis Antoniou 		rce->old_prop = ce->prop;
559201c910bSPantelis Antoniou 		rce->prop = ce->old_prop;
560b9c43856SPantelis Antoniou 		/* update was used but original property did not exist */
561b9c43856SPantelis Antoniou 		if (!rce->prop) {
562b9c43856SPantelis Antoniou 			rce->action = OF_RECONFIG_REMOVE_PROPERTY;
563b9c43856SPantelis Antoniou 			rce->prop = ce->prop;
564b9c43856SPantelis Antoniou 		}
565201c910bSPantelis Antoniou 		break;
566201c910bSPantelis Antoniou 	}
567201c910bSPantelis Antoniou }
568201c910bSPantelis Antoniou 
__of_changeset_entry_notify(struct of_changeset_entry * ce,bool revert)56924789c5cSFrank Rowand static int __of_changeset_entry_notify(struct of_changeset_entry *ce,
57024789c5cSFrank Rowand 		bool revert)
571201c910bSPantelis Antoniou {
572f5242e5aSGrant Likely 	struct of_reconfig_data rd;
573201c910bSPantelis Antoniou 	struct of_changeset_entry ce_inverted;
57424789c5cSFrank Rowand 	int ret = 0;
575201c910bSPantelis Antoniou 
576201c910bSPantelis Antoniou 	if (revert) {
577201c910bSPantelis Antoniou 		__of_changeset_entry_invert(ce, &ce_inverted);
578201c910bSPantelis Antoniou 		ce = &ce_inverted;
579201c910bSPantelis Antoniou 	}
580201c910bSPantelis Antoniou 
581201c910bSPantelis Antoniou 	switch (ce->action) {
582201c910bSPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
583201c910bSPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
584f5242e5aSGrant Likely 		memset(&rd, 0, sizeof(rd));
585f5242e5aSGrant Likely 		rd.dn = ce->np;
586f5242e5aSGrant Likely 		ret = of_reconfig_notify(ce->action, &rd);
587201c910bSPantelis Antoniou 		break;
588201c910bSPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
589201c910bSPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
590201c910bSPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
591201c910bSPantelis Antoniou 		ret = of_property_notify(ce->action, ce->np, ce->prop, ce->old_prop);
592201c910bSPantelis Antoniou 		break;
593201c910bSPantelis Antoniou 	default:
594606ad42aSRob Herring 		pr_err("invalid devicetree changeset action: %i\n",
595201c910bSPantelis Antoniou 			(int)ce->action);
59624789c5cSFrank Rowand 		ret = -EINVAL;
597201c910bSPantelis Antoniou 	}
598201c910bSPantelis Antoniou 
599201c910bSPantelis Antoniou 	if (ret)
6000d638a07SRob Herring 		pr_err("changeset notifier error @%pOF\n", ce->np);
60124789c5cSFrank Rowand 	return ret;
602201c910bSPantelis Antoniou }
603201c910bSPantelis Antoniou 
__of_changeset_entry_apply(struct of_changeset_entry * ce)604201c910bSPantelis Antoniou static int __of_changeset_entry_apply(struct of_changeset_entry *ce)
605201c910bSPantelis Antoniou {
606201c910bSPantelis Antoniou 	int ret = 0;
607201c910bSPantelis Antoniou 
60827a02f26SRob Herring 	of_changeset_action_debug("apply: ", ce->action, ce->np, ce->prop);
609201c910bSPantelis Antoniou 
610201c910bSPantelis Antoniou 	switch (ce->action) {
611201c910bSPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
612201c910bSPantelis Antoniou 		__of_attach_node(ce->np);
613201c910bSPantelis Antoniou 		break;
614201c910bSPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
615201c910bSPantelis Antoniou 		__of_detach_node(ce->np);
616201c910bSPantelis Antoniou 		break;
617201c910bSPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
618201c910bSPantelis Antoniou 		ret = __of_add_property(ce->np, ce->prop);
619201c910bSPantelis Antoniou 		break;
620201c910bSPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
621201c910bSPantelis Antoniou 		ret = __of_remove_property(ce->np, ce->prop);
622201c910bSPantelis Antoniou 		break;
623201c910bSPantelis Antoniou 
624201c910bSPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
625420f0de9SRob Herring 		ret = __of_update_property(ce->np, ce->prop, &ce->old_prop);
626201c910bSPantelis Antoniou 		break;
627201c910bSPantelis Antoniou 	default:
628201c910bSPantelis Antoniou 		ret = -EINVAL;
629201c910bSPantelis Antoniou 	}
630201c910bSPantelis Antoniou 
631914d9d83SRob Herring 	if (ret) {
63227a02f26SRob Herring 		of_changeset_action_err("apply failed: ", ce->action, ce->np, ce->prop);
633201c910bSPantelis Antoniou 		return ret;
634914d9d83SRob Herring 	}
635201c910bSPantelis Antoniou 
636201c910bSPantelis Antoniou 	return 0;
637201c910bSPantelis Antoniou }
638201c910bSPantelis Antoniou 
__of_changeset_entry_revert(struct of_changeset_entry * ce)639201c910bSPantelis Antoniou static inline int __of_changeset_entry_revert(struct of_changeset_entry *ce)
640201c910bSPantelis Antoniou {
641201c910bSPantelis Antoniou 	struct of_changeset_entry ce_inverted;
642201c910bSPantelis Antoniou 
643201c910bSPantelis Antoniou 	__of_changeset_entry_invert(ce, &ce_inverted);
644201c910bSPantelis Antoniou 	return __of_changeset_entry_apply(&ce_inverted);
645201c910bSPantelis Antoniou }
646201c910bSPantelis Antoniou 
647201c910bSPantelis Antoniou /**
648201c910bSPantelis Antoniou  * of_changeset_init - Initialize a changeset for use
649201c910bSPantelis Antoniou  *
650201c910bSPantelis Antoniou  * @ocs:	changeset pointer
651201c910bSPantelis Antoniou  *
652201c910bSPantelis Antoniou  * Initialize a changeset structure
653201c910bSPantelis Antoniou  */
of_changeset_init(struct of_changeset * ocs)654201c910bSPantelis Antoniou void of_changeset_init(struct of_changeset *ocs)
655201c910bSPantelis Antoniou {
656201c910bSPantelis Antoniou 	memset(ocs, 0, sizeof(*ocs));
657201c910bSPantelis Antoniou 	INIT_LIST_HEAD(&ocs->entries);
658201c910bSPantelis Antoniou }
65918322377SGavin Shan EXPORT_SYMBOL_GPL(of_changeset_init);
660201c910bSPantelis Antoniou 
661201c910bSPantelis Antoniou /**
662201c910bSPantelis Antoniou  * of_changeset_destroy - Destroy a changeset
663201c910bSPantelis Antoniou  *
664201c910bSPantelis Antoniou  * @ocs:	changeset pointer
665201c910bSPantelis Antoniou  *
666201c910bSPantelis Antoniou  * Destroys a changeset. Note that if a changeset is applied,
667201c910bSPantelis Antoniou  * its changes to the tree cannot be reverted.
668201c910bSPantelis Antoniou  */
of_changeset_destroy(struct of_changeset * ocs)669201c910bSPantelis Antoniou void of_changeset_destroy(struct of_changeset *ocs)
670201c910bSPantelis Antoniou {
671201c910bSPantelis Antoniou 	struct of_changeset_entry *ce, *cen;
672201c910bSPantelis Antoniou 
6738917e738SHerve Codina 	/*
6748917e738SHerve Codina 	 * When a device is deleted, the device links to/from it are also queued
6758917e738SHerve Codina 	 * for deletion. Until these device links are freed, the devices
6768917e738SHerve Codina 	 * themselves aren't freed. If the device being deleted is due to an
6778917e738SHerve Codina 	 * overlay change, this device might be holding a reference to a device
6788917e738SHerve Codina 	 * node that will be freed. So, wait until all already pending device
6798917e738SHerve Codina 	 * links are deleted before freeing a device node. This ensures we don't
6808917e738SHerve Codina 	 * free any device node that has a non-zero reference count.
6818917e738SHerve Codina 	 */
6828917e738SHerve Codina 	device_link_wait_removal();
6838917e738SHerve Codina 
684201c910bSPantelis Antoniou 	list_for_each_entry_safe_reverse(ce, cen, &ocs->entries, node)
685201c910bSPantelis Antoniou 		__of_changeset_entry_destroy(ce);
686201c910bSPantelis Antoniou }
68718322377SGavin Shan EXPORT_SYMBOL_GPL(of_changeset_destroy);
688201c910bSPantelis Antoniou 
68924789c5cSFrank Rowand /*
69024789c5cSFrank Rowand  * Apply the changeset entries in @ocs.
69124789c5cSFrank Rowand  * If apply fails, an attempt is made to revert the entries that were
69224789c5cSFrank Rowand  * successfully applied.
69324789c5cSFrank Rowand  *
69424789c5cSFrank Rowand  * If multiple revert errors occur then only the final revert error is reported.
69524789c5cSFrank Rowand  *
69624789c5cSFrank Rowand  * Returns 0 on success, a negative error value in case of an error.
69724789c5cSFrank Rowand  * If a revert error occurs, it is returned in *ret_revert.
69824789c5cSFrank Rowand  */
__of_changeset_apply_entries(struct of_changeset * ocs,int * ret_revert)69924789c5cSFrank Rowand int __of_changeset_apply_entries(struct of_changeset *ocs, int *ret_revert)
700201c910bSPantelis Antoniou {
701201c910bSPantelis Antoniou 	struct of_changeset_entry *ce;
70224789c5cSFrank Rowand 	int ret, ret_tmp;
703201c910bSPantelis Antoniou 
704606ad42aSRob Herring 	pr_debug("changeset: applying...\n");
705201c910bSPantelis Antoniou 	list_for_each_entry(ce, &ocs->entries, node) {
706201c910bSPantelis Antoniou 		ret = __of_changeset_entry_apply(ce);
707201c910bSPantelis Antoniou 		if (ret) {
708606ad42aSRob Herring 			pr_err("Error applying changeset (%d)\n", ret);
70924789c5cSFrank Rowand 			list_for_each_entry_continue_reverse(ce, &ocs->entries,
71024789c5cSFrank Rowand 							     node) {
71124789c5cSFrank Rowand 				ret_tmp = __of_changeset_entry_revert(ce);
71224789c5cSFrank Rowand 				if (ret_tmp)
71324789c5cSFrank Rowand 					*ret_revert = ret_tmp;
71424789c5cSFrank Rowand 			}
715201c910bSPantelis Antoniou 			return ret;
716201c910bSPantelis Antoniou 		}
717201c910bSPantelis Antoniou 	}
71824789c5cSFrank Rowand 
71924789c5cSFrank Rowand 	return 0;
72024789c5cSFrank Rowand }
72124789c5cSFrank Rowand 
72224789c5cSFrank Rowand /*
72324789c5cSFrank Rowand  * Returns 0 on success, a negative error value in case of an error.
72424789c5cSFrank Rowand  *
725e9d92e40SGeert Uytterhoeven  * If multiple changeset entry notification errors occur then only the
72624789c5cSFrank Rowand  * final notification error is reported.
72724789c5cSFrank Rowand  */
__of_changeset_apply_notify(struct of_changeset * ocs)72824789c5cSFrank Rowand int __of_changeset_apply_notify(struct of_changeset *ocs)
72924789c5cSFrank Rowand {
73024789c5cSFrank Rowand 	struct of_changeset_entry *ce;
73124789c5cSFrank Rowand 	int ret = 0, ret_tmp;
73224789c5cSFrank Rowand 
73324789c5cSFrank Rowand 	pr_debug("changeset: emitting notifiers.\n");
734201c910bSPantelis Antoniou 
735201c910bSPantelis Antoniou 	/* drop the global lock while emitting notifiers */
736201c910bSPantelis Antoniou 	mutex_unlock(&of_mutex);
73724789c5cSFrank Rowand 	list_for_each_entry(ce, &ocs->entries, node) {
73824789c5cSFrank Rowand 		ret_tmp = __of_changeset_entry_notify(ce, 0);
73924789c5cSFrank Rowand 		if (ret_tmp)
74024789c5cSFrank Rowand 			ret = ret_tmp;
74124789c5cSFrank Rowand 	}
742201c910bSPantelis Antoniou 	mutex_lock(&of_mutex);
743606ad42aSRob Herring 	pr_debug("changeset: notifiers sent.\n");
744201c910bSPantelis Antoniou 
74524789c5cSFrank Rowand 	return ret;
74624789c5cSFrank Rowand }
74724789c5cSFrank Rowand 
74824789c5cSFrank Rowand /*
74924789c5cSFrank Rowand  * Returns 0 on success, a negative error value in case of an error.
75024789c5cSFrank Rowand  *
75124789c5cSFrank Rowand  * If a changeset entry apply fails, an attempt is made to revert any
75224789c5cSFrank Rowand  * previous entries in the changeset.  If any of the reverts fails,
75324789c5cSFrank Rowand  * that failure is not reported.  Thus the state of the device tree
75424789c5cSFrank Rowand  * is unknown if an apply error occurs.
75524789c5cSFrank Rowand  */
__of_changeset_apply(struct of_changeset * ocs)75624789c5cSFrank Rowand static int __of_changeset_apply(struct of_changeset *ocs)
75724789c5cSFrank Rowand {
75824789c5cSFrank Rowand 	int ret, ret_revert = 0;
75924789c5cSFrank Rowand 
76024789c5cSFrank Rowand 	ret = __of_changeset_apply_entries(ocs, &ret_revert);
76124789c5cSFrank Rowand 	if (!ret)
76224789c5cSFrank Rowand 		ret = __of_changeset_apply_notify(ocs);
76324789c5cSFrank Rowand 
76424789c5cSFrank Rowand 	return ret;
765201c910bSPantelis Antoniou }
766201c910bSPantelis Antoniou 
767201c910bSPantelis Antoniou /**
76818322377SGavin Shan  * of_changeset_apply - Applies a changeset
769201c910bSPantelis Antoniou  *
770201c910bSPantelis Antoniou  * @ocs:	changeset pointer
771201c910bSPantelis Antoniou  *
77218322377SGavin Shan  * Applies a changeset to the live tree.
77318322377SGavin Shan  * Any side-effects of live tree state changes are applied here on
77418322377SGavin Shan  * success, like creation/destruction of devices and side-effects
77518322377SGavin Shan  * like creation of sysfs properties and directories.
7768c8239c2SRob Herring  *
7778c8239c2SRob Herring  * Return: 0 on success, a negative error value in case of an error.
77818322377SGavin Shan  * On error the partially applied effects are reverted.
779201c910bSPantelis Antoniou  */
of_changeset_apply(struct of_changeset * ocs)78018322377SGavin Shan int of_changeset_apply(struct of_changeset *ocs)
78118322377SGavin Shan {
78218322377SGavin Shan 	int ret;
78318322377SGavin Shan 
78418322377SGavin Shan 	mutex_lock(&of_mutex);
78518322377SGavin Shan 	ret = __of_changeset_apply(ocs);
78618322377SGavin Shan 	mutex_unlock(&of_mutex);
78718322377SGavin Shan 
78818322377SGavin Shan 	return ret;
78918322377SGavin Shan }
79018322377SGavin Shan EXPORT_SYMBOL_GPL(of_changeset_apply);
79118322377SGavin Shan 
79224789c5cSFrank Rowand /*
79324789c5cSFrank Rowand  * Revert the changeset entries in @ocs.
79424789c5cSFrank Rowand  * If revert fails, an attempt is made to re-apply the entries that were
79524789c5cSFrank Rowand  * successfully removed.
79624789c5cSFrank Rowand  *
79724789c5cSFrank Rowand  * If multiple re-apply errors occur then only the final apply error is
79824789c5cSFrank Rowand  * reported.
79924789c5cSFrank Rowand  *
80024789c5cSFrank Rowand  * Returns 0 on success, a negative error value in case of an error.
80124789c5cSFrank Rowand  * If an apply error occurs, it is returned in *ret_apply.
80224789c5cSFrank Rowand  */
__of_changeset_revert_entries(struct of_changeset * ocs,int * ret_apply)80324789c5cSFrank Rowand int __of_changeset_revert_entries(struct of_changeset *ocs, int *ret_apply)
804201c910bSPantelis Antoniou {
805201c910bSPantelis Antoniou 	struct of_changeset_entry *ce;
80624789c5cSFrank Rowand 	int ret, ret_tmp;
807201c910bSPantelis Antoniou 
808606ad42aSRob Herring 	pr_debug("changeset: reverting...\n");
809201c910bSPantelis Antoniou 	list_for_each_entry_reverse(ce, &ocs->entries, node) {
810201c910bSPantelis Antoniou 		ret = __of_changeset_entry_revert(ce);
811201c910bSPantelis Antoniou 		if (ret) {
812606ad42aSRob Herring 			pr_err("Error reverting changeset (%d)\n", ret);
81324789c5cSFrank Rowand 			list_for_each_entry_continue(ce, &ocs->entries, node) {
81424789c5cSFrank Rowand 				ret_tmp = __of_changeset_entry_apply(ce);
81524789c5cSFrank Rowand 				if (ret_tmp)
81624789c5cSFrank Rowand 					*ret_apply = ret_tmp;
81724789c5cSFrank Rowand 			}
818201c910bSPantelis Antoniou 			return ret;
819201c910bSPantelis Antoniou 		}
820201c910bSPantelis Antoniou 	}
82124789c5cSFrank Rowand 
82224789c5cSFrank Rowand 	return 0;
82324789c5cSFrank Rowand }
82424789c5cSFrank Rowand 
82524789c5cSFrank Rowand /*
826e9d92e40SGeert Uytterhoeven  * If multiple changeset entry notification errors occur then only the
82724789c5cSFrank Rowand  * final notification error is reported.
82824789c5cSFrank Rowand  */
__of_changeset_revert_notify(struct of_changeset * ocs)82924789c5cSFrank Rowand int __of_changeset_revert_notify(struct of_changeset *ocs)
83024789c5cSFrank Rowand {
83124789c5cSFrank Rowand 	struct of_changeset_entry *ce;
83224789c5cSFrank Rowand 	int ret = 0, ret_tmp;
83324789c5cSFrank Rowand 
83424789c5cSFrank Rowand 	pr_debug("changeset: emitting notifiers.\n");
835201c910bSPantelis Antoniou 
836201c910bSPantelis Antoniou 	/* drop the global lock while emitting notifiers */
837201c910bSPantelis Antoniou 	mutex_unlock(&of_mutex);
83824789c5cSFrank Rowand 	list_for_each_entry_reverse(ce, &ocs->entries, node) {
83924789c5cSFrank Rowand 		ret_tmp = __of_changeset_entry_notify(ce, 1);
84024789c5cSFrank Rowand 		if (ret_tmp)
84124789c5cSFrank Rowand 			ret = ret_tmp;
84224789c5cSFrank Rowand 	}
843201c910bSPantelis Antoniou 	mutex_lock(&of_mutex);
844606ad42aSRob Herring 	pr_debug("changeset: notifiers sent.\n");
845201c910bSPantelis Antoniou 
84624789c5cSFrank Rowand 	return ret;
84724789c5cSFrank Rowand }
84824789c5cSFrank Rowand 
__of_changeset_revert(struct of_changeset * ocs)84924789c5cSFrank Rowand static int __of_changeset_revert(struct of_changeset *ocs)
85024789c5cSFrank Rowand {
85124789c5cSFrank Rowand 	int ret, ret_reply;
85224789c5cSFrank Rowand 
85324789c5cSFrank Rowand 	ret_reply = 0;
85424789c5cSFrank Rowand 	ret = __of_changeset_revert_entries(ocs, &ret_reply);
85524789c5cSFrank Rowand 
85624789c5cSFrank Rowand 	if (!ret)
85724789c5cSFrank Rowand 		ret = __of_changeset_revert_notify(ocs);
85824789c5cSFrank Rowand 
85924789c5cSFrank Rowand 	return ret;
860201c910bSPantelis Antoniou }
861201c910bSPantelis Antoniou 
862201c910bSPantelis Antoniou /**
86318322377SGavin Shan  * of_changeset_revert - Reverts an applied changeset
86418322377SGavin Shan  *
86518322377SGavin Shan  * @ocs:	changeset pointer
86618322377SGavin Shan  *
86718322377SGavin Shan  * Reverts a changeset returning the state of the tree to what it
86818322377SGavin Shan  * was before the application.
86918322377SGavin Shan  * Any side-effects like creation/destruction of devices and
87018322377SGavin Shan  * removal of sysfs properties and directories are applied.
8718c8239c2SRob Herring  *
8728c8239c2SRob Herring  * Return: 0 on success, a negative error value in case of an error.
87318322377SGavin Shan  */
of_changeset_revert(struct of_changeset * ocs)87418322377SGavin Shan int of_changeset_revert(struct of_changeset *ocs)
87518322377SGavin Shan {
87618322377SGavin Shan 	int ret;
87718322377SGavin Shan 
87818322377SGavin Shan 	mutex_lock(&of_mutex);
87918322377SGavin Shan 	ret = __of_changeset_revert(ocs);
88018322377SGavin Shan 	mutex_unlock(&of_mutex);
88118322377SGavin Shan 
88218322377SGavin Shan 	return ret;
88318322377SGavin Shan }
88418322377SGavin Shan EXPORT_SYMBOL_GPL(of_changeset_revert);
88518322377SGavin Shan 
88618322377SGavin Shan /**
8870290c4caSFrank Rowand  * of_changeset_action - Add an action to the tail of the changeset list
888201c910bSPantelis Antoniou  *
889201c910bSPantelis Antoniou  * @ocs:	changeset pointer
890201c910bSPantelis Antoniou  * @action:	action to perform
891201c910bSPantelis Antoniou  * @np:		Pointer to device node
892201c910bSPantelis Antoniou  * @prop:	Pointer to property
893201c910bSPantelis Antoniou  *
894201c910bSPantelis Antoniou  * On action being one of:
895201c910bSPantelis Antoniou  * + OF_RECONFIG_ATTACH_NODE
896201c910bSPantelis Antoniou  * + OF_RECONFIG_DETACH_NODE,
897201c910bSPantelis Antoniou  * + OF_RECONFIG_ADD_PROPERTY
898201c910bSPantelis Antoniou  * + OF_RECONFIG_REMOVE_PROPERTY,
899201c910bSPantelis Antoniou  * + OF_RECONFIG_UPDATE_PROPERTY
9008c8239c2SRob Herring  *
9018c8239c2SRob Herring  * Return: 0 on success, a negative error value in case of an error.
902201c910bSPantelis Antoniou  */
of_changeset_action(struct of_changeset * ocs,unsigned long action,struct device_node * np,struct property * prop)903201c910bSPantelis Antoniou int of_changeset_action(struct of_changeset *ocs, unsigned long action,
904201c910bSPantelis Antoniou 		struct device_node *np, struct property *prop)
905201c910bSPantelis Antoniou {
906201c910bSPantelis Antoniou 	struct of_changeset_entry *ce;
907201c910bSPantelis Antoniou 
90855e95bfcSDan Carpenter 	if (WARN_ON(action >= ARRAY_SIZE(action_names)))
90955e95bfcSDan Carpenter 		return -EINVAL;
91055e95bfcSDan Carpenter 
911201c910bSPantelis Antoniou 	ce = kzalloc(sizeof(*ce), GFP_KERNEL);
912606ad42aSRob Herring 	if (!ce)
913201c910bSPantelis Antoniou 		return -ENOMEM;
914606ad42aSRob Herring 
915201c910bSPantelis Antoniou 	/* get a reference to the node */
916201c910bSPantelis Antoniou 	ce->action = action;
917201c910bSPantelis Antoniou 	ce->np = of_node_get(np);
918201c910bSPantelis Antoniou 	ce->prop = prop;
919201c910bSPantelis Antoniou 
920201c910bSPantelis Antoniou 	/* add it to the list */
921201c910bSPantelis Antoniou 	list_add_tail(&ce->node, &ocs->entries);
922201c910bSPantelis Antoniou 	return 0;
923201c910bSPantelis Antoniou }
92418322377SGavin Shan EXPORT_SYMBOL_GPL(of_changeset_action);
925b544fc2bSLizhi Hou 
of_changeset_add_prop_helper(struct of_changeset * ocs,struct device_node * np,const struct property * pp)926b544fc2bSLizhi Hou static int of_changeset_add_prop_helper(struct of_changeset *ocs,
927b544fc2bSLizhi Hou 					struct device_node *np,
928b544fc2bSLizhi Hou 					const struct property *pp)
929b544fc2bSLizhi Hou {
930b544fc2bSLizhi Hou 	struct property *new_pp;
931b544fc2bSLizhi Hou 	int ret;
932b544fc2bSLizhi Hou 
933b544fc2bSLizhi Hou 	new_pp = __of_prop_dup(pp, GFP_KERNEL);
934b544fc2bSLizhi Hou 	if (!new_pp)
935b544fc2bSLizhi Hou 		return -ENOMEM;
936b544fc2bSLizhi Hou 
937b544fc2bSLizhi Hou 	ret = of_changeset_add_property(ocs, np, new_pp);
9381c5e3d9bSRob Herring 	if (ret)
9391c5e3d9bSRob Herring 		__of_prop_free(new_pp);
940b544fc2bSLizhi Hou 
941b544fc2bSLizhi Hou 	return ret;
942b544fc2bSLizhi Hou }
943b544fc2bSLizhi Hou 
944b544fc2bSLizhi Hou /**
945b544fc2bSLizhi Hou  * of_changeset_add_prop_string - Add a string property to a changeset
946b544fc2bSLizhi Hou  *
947b544fc2bSLizhi Hou  * @ocs:	changeset pointer
948b544fc2bSLizhi Hou  * @np:		device node pointer
949b544fc2bSLizhi Hou  * @prop_name:	name of the property to be added
950b544fc2bSLizhi Hou  * @str:	pointer to null terminated string
951b544fc2bSLizhi Hou  *
952b544fc2bSLizhi Hou  * Create a string property and add it to a changeset.
953b544fc2bSLizhi Hou  *
954b544fc2bSLizhi Hou  * Return: 0 on success, a negative error value in case of an error.
955b544fc2bSLizhi Hou  */
of_changeset_add_prop_string(struct of_changeset * ocs,struct device_node * np,const char * prop_name,const char * str)956b544fc2bSLizhi Hou int of_changeset_add_prop_string(struct of_changeset *ocs,
957b544fc2bSLizhi Hou 				 struct device_node *np,
958b544fc2bSLizhi Hou 				 const char *prop_name, const char *str)
959b544fc2bSLizhi Hou {
960b544fc2bSLizhi Hou 	struct property prop;
961b544fc2bSLizhi Hou 
962b544fc2bSLizhi Hou 	prop.name = (char *)prop_name;
963b544fc2bSLizhi Hou 	prop.length = strlen(str) + 1;
964b544fc2bSLizhi Hou 	prop.value = (void *)str;
965b544fc2bSLizhi Hou 
966b544fc2bSLizhi Hou 	return of_changeset_add_prop_helper(ocs, np, &prop);
967b544fc2bSLizhi Hou }
968b544fc2bSLizhi Hou EXPORT_SYMBOL_GPL(of_changeset_add_prop_string);
969b544fc2bSLizhi Hou 
970b544fc2bSLizhi Hou /**
971b544fc2bSLizhi Hou  * of_changeset_add_prop_string_array - Add a string list property to
972b544fc2bSLizhi Hou  * a changeset
973b544fc2bSLizhi Hou  *
974b544fc2bSLizhi Hou  * @ocs:	changeset pointer
975b544fc2bSLizhi Hou  * @np:		device node pointer
976b544fc2bSLizhi Hou  * @prop_name:	name of the property to be added
977b544fc2bSLizhi Hou  * @str_array:	pointer to an array of null terminated strings
978b544fc2bSLizhi Hou  * @sz:		number of string array elements
979b544fc2bSLizhi Hou  *
980b544fc2bSLizhi Hou  * Create a string list property and add it to a changeset.
981b544fc2bSLizhi Hou  *
982b544fc2bSLizhi Hou  * Return: 0 on success, a negative error value in case of an error.
983b544fc2bSLizhi Hou  */
of_changeset_add_prop_string_array(struct of_changeset * ocs,struct device_node * np,const char * prop_name,const char * const * str_array,size_t sz)984b544fc2bSLizhi Hou int of_changeset_add_prop_string_array(struct of_changeset *ocs,
985b544fc2bSLizhi Hou 				       struct device_node *np,
986b544fc2bSLizhi Hou 				       const char *prop_name,
9876badc62fSHerve Codina 				       const char * const *str_array, size_t sz)
988b544fc2bSLizhi Hou {
989b544fc2bSLizhi Hou 	struct property prop;
990b544fc2bSLizhi Hou 	int i, ret;
991b544fc2bSLizhi Hou 	char *vp;
992b544fc2bSLizhi Hou 
993b544fc2bSLizhi Hou 	prop.name = (char *)prop_name;
994b544fc2bSLizhi Hou 
995b544fc2bSLizhi Hou 	prop.length = 0;
996b544fc2bSLizhi Hou 	for (i = 0; i < sz; i++)
997b544fc2bSLizhi Hou 		prop.length += strlen(str_array[i]) + 1;
998b544fc2bSLizhi Hou 
999b544fc2bSLizhi Hou 	prop.value = kmalloc(prop.length, GFP_KERNEL);
1000b544fc2bSLizhi Hou 	if (!prop.value)
1001b544fc2bSLizhi Hou 		return -ENOMEM;
1002b544fc2bSLizhi Hou 
1003b544fc2bSLizhi Hou 	vp = prop.value;
1004b544fc2bSLizhi Hou 	for (i = 0; i < sz; i++) {
1005b544fc2bSLizhi Hou 		vp += snprintf(vp, (char *)prop.value + prop.length - vp, "%s",
1006b544fc2bSLizhi Hou 			       str_array[i]) + 1;
1007b544fc2bSLizhi Hou 	}
1008b544fc2bSLizhi Hou 	ret = of_changeset_add_prop_helper(ocs, np, &prop);
1009b544fc2bSLizhi Hou 	kfree(prop.value);
1010b544fc2bSLizhi Hou 
1011b544fc2bSLizhi Hou 	return ret;
1012b544fc2bSLizhi Hou }
1013b544fc2bSLizhi Hou EXPORT_SYMBOL_GPL(of_changeset_add_prop_string_array);
1014b544fc2bSLizhi Hou 
1015b544fc2bSLizhi Hou /**
1016b544fc2bSLizhi Hou  * of_changeset_add_prop_u32_array - Add a property of 32 bit integers
1017b544fc2bSLizhi Hou  * property to a changeset
1018b544fc2bSLizhi Hou  *
1019b544fc2bSLizhi Hou  * @ocs:	changeset pointer
1020b544fc2bSLizhi Hou  * @np:		device node pointer
1021b544fc2bSLizhi Hou  * @prop_name:	name of the property to be added
1022b544fc2bSLizhi Hou  * @array:	pointer to an array of 32 bit integers
1023b544fc2bSLizhi Hou  * @sz:		number of array elements
1024b544fc2bSLizhi Hou  *
1025b544fc2bSLizhi Hou  * Create a property of 32 bit integers and add it to a changeset.
1026b544fc2bSLizhi Hou  *
1027b544fc2bSLizhi Hou  * Return: 0 on success, a negative error value in case of an error.
1028b544fc2bSLizhi Hou  */
of_changeset_add_prop_u32_array(struct of_changeset * ocs,struct device_node * np,const char * prop_name,const u32 * array,size_t sz)1029b544fc2bSLizhi Hou int of_changeset_add_prop_u32_array(struct of_changeset *ocs,
1030b544fc2bSLizhi Hou 				    struct device_node *np,
1031b544fc2bSLizhi Hou 				    const char *prop_name,
1032b544fc2bSLizhi Hou 				    const u32 *array, size_t sz)
1033b544fc2bSLizhi Hou {
1034b544fc2bSLizhi Hou 	struct property prop;
103540b0f174SRob Herring 	__be32 *val __free(kfree) = kcalloc(sz, sizeof(__be32), GFP_KERNEL);
103640b0f174SRob Herring 	int i;
1037b544fc2bSLizhi Hou 
1038b544fc2bSLizhi Hou 	if (!val)
1039b544fc2bSLizhi Hou 		return -ENOMEM;
1040b544fc2bSLizhi Hou 
1041b544fc2bSLizhi Hou 	for (i = 0; i < sz; i++)
1042b544fc2bSLizhi Hou 		val[i] = cpu_to_be32(array[i]);
1043b544fc2bSLizhi Hou 	prop.name = (char *)prop_name;
1044b544fc2bSLizhi Hou 	prop.length = sizeof(u32) * sz;
1045b544fc2bSLizhi Hou 	prop.value = (void *)val;
1046b544fc2bSLizhi Hou 
104740b0f174SRob Herring 	return of_changeset_add_prop_helper(ocs, np, &prop);
1048b544fc2bSLizhi Hou }
1049b544fc2bSLizhi Hou EXPORT_SYMBOL_GPL(of_changeset_add_prop_u32_array);
1050*f2b388d6SHerve Codina 
1051*f2b388d6SHerve Codina /**
1052*f2b388d6SHerve Codina  * of_changeset_add_prop_bool - Add a boolean property (i.e. a property without
1053*f2b388d6SHerve Codina  * any values) to a changeset.
1054*f2b388d6SHerve Codina  *
1055*f2b388d6SHerve Codina  * @ocs:	changeset pointer
1056*f2b388d6SHerve Codina  * @np:		device node pointer
1057*f2b388d6SHerve Codina  * @prop_name:	name of the property to be added
1058*f2b388d6SHerve Codina  *
1059*f2b388d6SHerve Codina  * Create a boolean property and add it to a changeset.
1060*f2b388d6SHerve Codina  *
1061*f2b388d6SHerve Codina  * Return: 0 on success, a negative error value in case of an error.
1062*f2b388d6SHerve Codina  */
of_changeset_add_prop_bool(struct of_changeset * ocs,struct device_node * np,const char * prop_name)1063*f2b388d6SHerve Codina int of_changeset_add_prop_bool(struct of_changeset *ocs, struct device_node *np,
1064*f2b388d6SHerve Codina 			       const char *prop_name)
1065*f2b388d6SHerve Codina {
1066*f2b388d6SHerve Codina 	struct property prop;
1067*f2b388d6SHerve Codina 
1068*f2b388d6SHerve Codina 	prop.name = (char *)prop_name;
1069*f2b388d6SHerve Codina 	prop.length = 0;
1070*f2b388d6SHerve Codina 	prop.value = NULL;
1071*f2b388d6SHerve Codina 
1072*f2b388d6SHerve Codina 	return of_changeset_add_prop_helper(ocs, np, &prop);
1073*f2b388d6SHerve Codina }
1074*f2b388d6SHerve Codina EXPORT_SYMBOL_GPL(of_changeset_add_prop_bool);
1075