xref: /linux/drivers/of/dynamic.c (revision 74df14cd301a1433947077e79ce2c610654a32e7)
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 
126afc0dc3SGrant Likely #include <linux/of.h>
136afc0dc3SGrant Likely #include <linux/spinlock.h>
146afc0dc3SGrant Likely #include <linux/slab.h>
156afc0dc3SGrant Likely #include <linux/string.h>
166afc0dc3SGrant Likely #include <linux/proc_fs.h>
176afc0dc3SGrant Likely 
186afc0dc3SGrant Likely #include "of_private.h"
196afc0dc3SGrant Likely 
204c2bb574SRob Herring static struct device_node *kobj_to_device_node(struct kobject *kobj)
214c2bb574SRob Herring {
224c2bb574SRob Herring 	return container_of(kobj, struct device_node, kobj);
234c2bb574SRob Herring }
244c2bb574SRob Herring 
256afc0dc3SGrant Likely /**
266afc0dc3SGrant Likely  * of_node_get() - Increment refcount of a node
276afc0dc3SGrant Likely  * @node:	Node to inc refcount, NULL is supported to simplify writing of
286afc0dc3SGrant Likely  *		callers
296afc0dc3SGrant Likely  *
308c8239c2SRob Herring  * Return: The node with refcount incremented.
316afc0dc3SGrant Likely  */
326afc0dc3SGrant Likely struct device_node *of_node_get(struct device_node *node)
336afc0dc3SGrant Likely {
346afc0dc3SGrant Likely 	if (node)
356afc0dc3SGrant Likely 		kobject_get(&node->kobj);
366afc0dc3SGrant Likely 	return node;
376afc0dc3SGrant Likely }
386afc0dc3SGrant Likely EXPORT_SYMBOL(of_node_get);
396afc0dc3SGrant Likely 
406afc0dc3SGrant Likely /**
416afc0dc3SGrant Likely  * of_node_put() - Decrement refcount of a node
426afc0dc3SGrant Likely  * @node:	Node to dec refcount, NULL is supported to simplify writing of
436afc0dc3SGrant Likely  *		callers
446afc0dc3SGrant Likely  */
456afc0dc3SGrant Likely void of_node_put(struct device_node *node)
466afc0dc3SGrant Likely {
476afc0dc3SGrant Likely 	if (node)
486afc0dc3SGrant Likely 		kobject_put(&node->kobj);
496afc0dc3SGrant Likely }
506afc0dc3SGrant Likely EXPORT_SYMBOL(of_node_put);
516afc0dc3SGrant Likely 
526afc0dc3SGrant Likely static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);
536afc0dc3SGrant Likely 
546afc0dc3SGrant Likely int of_reconfig_notifier_register(struct notifier_block *nb)
556afc0dc3SGrant Likely {
566afc0dc3SGrant Likely 	return blocking_notifier_chain_register(&of_reconfig_chain, nb);
576afc0dc3SGrant Likely }
586afc0dc3SGrant Likely EXPORT_SYMBOL_GPL(of_reconfig_notifier_register);
596afc0dc3SGrant Likely 
606afc0dc3SGrant Likely int of_reconfig_notifier_unregister(struct notifier_block *nb)
616afc0dc3SGrant Likely {
626afc0dc3SGrant Likely 	return blocking_notifier_chain_unregister(&of_reconfig_chain, nb);
636afc0dc3SGrant Likely }
646afc0dc3SGrant Likely EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister);
656afc0dc3SGrant Likely 
6600aa3720SGrant Likely #ifdef DEBUG
6700aa3720SGrant Likely const char *action_names[] = {
6800aa3720SGrant Likely 	[OF_RECONFIG_ATTACH_NODE] = "ATTACH_NODE",
6900aa3720SGrant Likely 	[OF_RECONFIG_DETACH_NODE] = "DETACH_NODE",
7000aa3720SGrant Likely 	[OF_RECONFIG_ADD_PROPERTY] = "ADD_PROPERTY",
7100aa3720SGrant Likely 	[OF_RECONFIG_REMOVE_PROPERTY] = "REMOVE_PROPERTY",
7200aa3720SGrant Likely 	[OF_RECONFIG_UPDATE_PROPERTY] = "UPDATE_PROPERTY",
7300aa3720SGrant Likely };
7400aa3720SGrant Likely #endif
7500aa3720SGrant Likely 
76f5242e5aSGrant Likely int of_reconfig_notify(unsigned long action, struct of_reconfig_data *p)
776afc0dc3SGrant Likely {
786afc0dc3SGrant Likely 	int rc;
7900aa3720SGrant Likely #ifdef DEBUG
80f5242e5aSGrant Likely 	struct of_reconfig_data *pr = p;
816afc0dc3SGrant Likely 
8200aa3720SGrant Likely 	switch (action) {
8300aa3720SGrant Likely 	case OF_RECONFIG_ATTACH_NODE:
8400aa3720SGrant Likely 	case OF_RECONFIG_DETACH_NODE:
850d638a07SRob Herring 		pr_debug("notify %-15s %pOF\n", action_names[action],
860d638a07SRob Herring 			pr->dn);
8700aa3720SGrant Likely 		break;
8800aa3720SGrant Likely 	case OF_RECONFIG_ADD_PROPERTY:
8900aa3720SGrant Likely 	case OF_RECONFIG_REMOVE_PROPERTY:
9000aa3720SGrant Likely 	case OF_RECONFIG_UPDATE_PROPERTY:
910d638a07SRob Herring 		pr_debug("notify %-15s %pOF:%s\n", action_names[action],
920d638a07SRob Herring 			pr->dn, pr->prop->name);
9300aa3720SGrant Likely 		break;
9400aa3720SGrant Likely 
9500aa3720SGrant Likely 	}
9600aa3720SGrant Likely #endif
976afc0dc3SGrant Likely 	rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p);
986afc0dc3SGrant Likely 	return notifier_to_errno(rc);
996afc0dc3SGrant Likely }
1006afc0dc3SGrant Likely 
101b53a2340SPantelis Antoniou /*
102b53a2340SPantelis Antoniou  * of_reconfig_get_state_change()	- Returns new state of device
103b53a2340SPantelis Antoniou  * @action	- action of the of notifier
104b53a2340SPantelis Antoniou  * @arg		- argument of the of notifier
105b53a2340SPantelis Antoniou  *
106b53a2340SPantelis Antoniou  * Returns the new state of a device based on the notifier used.
1078c8239c2SRob Herring  *
1088c8239c2SRob Herring  * Return: 0 on device going from enabled to disabled, 1 on device
109b53a2340SPantelis Antoniou  * going from disabled to enabled and -1 on no change.
110b53a2340SPantelis Antoniou  */
111f5242e5aSGrant Likely int of_reconfig_get_state_change(unsigned long action, struct of_reconfig_data *pr)
112b53a2340SPantelis Antoniou {
113f5242e5aSGrant Likely 	struct property *prop, *old_prop = NULL;
114b53a2340SPantelis Antoniou 	int is_status, status_state, old_status_state, prev_state, new_state;
115b53a2340SPantelis Antoniou 
116b53a2340SPantelis Antoniou 	/* figure out if a device should be created or destroyed */
117b53a2340SPantelis Antoniou 	switch (action) {
118b53a2340SPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
119b53a2340SPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
120f5242e5aSGrant Likely 		prop = of_find_property(pr->dn, "status", NULL);
121b53a2340SPantelis Antoniou 		break;
122b53a2340SPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
123b53a2340SPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
124b53a2340SPantelis Antoniou 		prop = pr->prop;
125b53a2340SPantelis Antoniou 		break;
126b53a2340SPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
127b53a2340SPantelis Antoniou 		prop = pr->prop;
128b53a2340SPantelis Antoniou 		old_prop = pr->old_prop;
129b53a2340SPantelis Antoniou 		break;
130b53a2340SPantelis Antoniou 	default:
131b53a2340SPantelis Antoniou 		return OF_RECONFIG_NO_CHANGE;
132b53a2340SPantelis Antoniou 	}
133b53a2340SPantelis Antoniou 
134b53a2340SPantelis Antoniou 	is_status = 0;
135b53a2340SPantelis Antoniou 	status_state = -1;
136b53a2340SPantelis Antoniou 	old_status_state = -1;
137b53a2340SPantelis Antoniou 	prev_state = -1;
138b53a2340SPantelis Antoniou 	new_state = -1;
139b53a2340SPantelis Antoniou 
140b53a2340SPantelis Antoniou 	if (prop && !strcmp(prop->name, "status")) {
141b53a2340SPantelis Antoniou 		is_status = 1;
142b53a2340SPantelis Antoniou 		status_state = !strcmp(prop->value, "okay") ||
143b53a2340SPantelis Antoniou 			       !strcmp(prop->value, "ok");
144b53a2340SPantelis Antoniou 		if (old_prop)
145b53a2340SPantelis Antoniou 			old_status_state = !strcmp(old_prop->value, "okay") ||
146b53a2340SPantelis Antoniou 					   !strcmp(old_prop->value, "ok");
147b53a2340SPantelis Antoniou 	}
148b53a2340SPantelis Antoniou 
149b53a2340SPantelis Antoniou 	switch (action) {
150b53a2340SPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
151b53a2340SPantelis Antoniou 		prev_state = 0;
152b53a2340SPantelis Antoniou 		/* -1 & 0 status either missing or okay */
153b53a2340SPantelis Antoniou 		new_state = status_state != 0;
154b53a2340SPantelis Antoniou 		break;
155b53a2340SPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
156b53a2340SPantelis Antoniou 		/* -1 & 0 status either missing or okay */
157b53a2340SPantelis Antoniou 		prev_state = status_state != 0;
158b53a2340SPantelis Antoniou 		new_state = 0;
159b53a2340SPantelis Antoniou 		break;
160b53a2340SPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
161b53a2340SPantelis Antoniou 		if (is_status) {
162b53a2340SPantelis Antoniou 			/* no status property -> enabled (legacy) */
163b53a2340SPantelis Antoniou 			prev_state = 1;
164b53a2340SPantelis Antoniou 			new_state = status_state;
165b53a2340SPantelis Antoniou 		}
166b53a2340SPantelis Antoniou 		break;
167b53a2340SPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
168b53a2340SPantelis Antoniou 		if (is_status) {
169b53a2340SPantelis Antoniou 			prev_state = status_state;
170b53a2340SPantelis Antoniou 			/* no status property -> enabled (legacy) */
171b53a2340SPantelis Antoniou 			new_state = 1;
172b53a2340SPantelis Antoniou 		}
173b53a2340SPantelis Antoniou 		break;
174b53a2340SPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
175b53a2340SPantelis Antoniou 		if (is_status) {
176b53a2340SPantelis Antoniou 			prev_state = old_status_state != 0;
177b53a2340SPantelis Antoniou 			new_state = status_state != 0;
178b53a2340SPantelis Antoniou 		}
179b53a2340SPantelis Antoniou 		break;
180b53a2340SPantelis Antoniou 	}
181b53a2340SPantelis Antoniou 
182b53a2340SPantelis Antoniou 	if (prev_state == new_state)
183b53a2340SPantelis Antoniou 		return OF_RECONFIG_NO_CHANGE;
184b53a2340SPantelis Antoniou 
185b53a2340SPantelis Antoniou 	return new_state ? OF_RECONFIG_CHANGE_ADD : OF_RECONFIG_CHANGE_REMOVE;
186b53a2340SPantelis Antoniou }
187b53a2340SPantelis Antoniou EXPORT_SYMBOL_GPL(of_reconfig_get_state_change);
188b53a2340SPantelis Antoniou 
1896afc0dc3SGrant Likely int of_property_notify(int action, struct device_node *np,
190259092a3SGrant Likely 		       struct property *prop, struct property *oldprop)
1916afc0dc3SGrant Likely {
192f5242e5aSGrant Likely 	struct of_reconfig_data pr;
1936afc0dc3SGrant Likely 
1946afc0dc3SGrant Likely 	/* only call notifiers if the node is attached */
1956afc0dc3SGrant Likely 	if (!of_node_is_attached(np))
1966afc0dc3SGrant Likely 		return 0;
1976afc0dc3SGrant Likely 
1986afc0dc3SGrant Likely 	pr.dn = np;
1996afc0dc3SGrant Likely 	pr.prop = prop;
200259092a3SGrant Likely 	pr.old_prop = oldprop;
2016afc0dc3SGrant Likely 	return of_reconfig_notify(action, &pr);
2026afc0dc3SGrant Likely }
2036afc0dc3SGrant Likely 
20424996951SFrank Rowand static void __of_attach_node(struct device_node *np)
205d8c50088SPantelis Antoniou {
206a25095d4SGrant Likely 	const __be32 *phandle;
207a25095d4SGrant Likely 	int sz;
208a25095d4SGrant Likely 
209f9627881SFrank Rowand 	if (!of_node_check_flag(np, OF_OVERLAY)) {
210f9627881SFrank Rowand 		np->name = __of_get_property(np, "name", NULL);
211f9627881SFrank Rowand 		if (!np->name)
212f9627881SFrank Rowand 			np->name = "<NULL>";
213a25095d4SGrant Likely 
214a25095d4SGrant Likely 		phandle = __of_get_property(np, "phandle", &sz);
215a25095d4SGrant Likely 		if (!phandle)
216a25095d4SGrant Likely 			phandle = __of_get_property(np, "linux,phandle", &sz);
217f76502aaSGeert Uytterhoeven 		if (IS_ENABLED(CONFIG_PPC_PSERIES) && !phandle)
218a25095d4SGrant Likely 			phandle = __of_get_property(np, "ibm,phandle", &sz);
219f9627881SFrank Rowand 		if (phandle && (sz >= 4))
220f9627881SFrank Rowand 			np->phandle = be32_to_cpup(phandle);
221f9627881SFrank Rowand 		else
222f9627881SFrank Rowand 			np->phandle = 0;
223f9627881SFrank Rowand 	}
224a25095d4SGrant Likely 
2256162dbe4SGrant Likely 	np->child = NULL;
226d8c50088SPantelis Antoniou 	np->sibling = np->parent->child;
227d8c50088SPantelis Antoniou 	np->parent->child = np;
228d8c50088SPantelis Antoniou 	of_node_clear_flag(np, OF_DETACHED);
229d8c50088SPantelis Antoniou }
230d8c50088SPantelis Antoniou 
2316afc0dc3SGrant Likely /**
2326afc0dc3SGrant Likely  * of_attach_node() - Plug a device node into the tree and global list.
2333cb025d9SLee Jones  * @np:		Pointer to the caller's Device Node
2346afc0dc3SGrant Likely  */
2356afc0dc3SGrant Likely int of_attach_node(struct device_node *np)
2366afc0dc3SGrant Likely {
237f5242e5aSGrant Likely 	struct of_reconfig_data rd;
2386afc0dc3SGrant Likely 	unsigned long flags;
2396afc0dc3SGrant Likely 
240f5242e5aSGrant Likely 	memset(&rd, 0, sizeof(rd));
241f5242e5aSGrant Likely 	rd.dn = np;
242f5242e5aSGrant Likely 
2438a2b22a2SGrant Likely 	mutex_lock(&of_mutex);
2446afc0dc3SGrant Likely 	raw_spin_lock_irqsave(&devtree_lock, flags);
245d8c50088SPantelis Antoniou 	__of_attach_node(np);
2466afc0dc3SGrant Likely 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
2476afc0dc3SGrant Likely 
2488a2b22a2SGrant Likely 	__of_attach_node_sysfs(np);
2498a2b22a2SGrant Likely 	mutex_unlock(&of_mutex);
250259092a3SGrant Likely 
251f5242e5aSGrant Likely 	of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, &rd);
252259092a3SGrant Likely 
2536afc0dc3SGrant Likely 	return 0;
2546afc0dc3SGrant Likely }
2556afc0dc3SGrant Likely 
256d8c50088SPantelis Antoniou void __of_detach_node(struct device_node *np)
2576afc0dc3SGrant Likely {
2586afc0dc3SGrant Likely 	struct device_node *parent;
2596afc0dc3SGrant Likely 
260d8c50088SPantelis Antoniou 	if (WARN_ON(of_node_check_flag(np, OF_DETACHED)))
261d8c50088SPantelis Antoniou 		return;
2626afc0dc3SGrant Likely 
2636afc0dc3SGrant Likely 	parent = np->parent;
264d8c50088SPantelis Antoniou 	if (WARN_ON(!parent))
265d8c50088SPantelis Antoniou 		return;
2666afc0dc3SGrant Likely 
2676afc0dc3SGrant Likely 	if (parent->child == np)
2686afc0dc3SGrant Likely 		parent->child = np->sibling;
2696afc0dc3SGrant Likely 	else {
2706afc0dc3SGrant Likely 		struct device_node *prevsib;
2716afc0dc3SGrant Likely 		for (prevsib = np->parent->child;
2726afc0dc3SGrant Likely 		     prevsib->sibling != np;
2736afc0dc3SGrant Likely 		     prevsib = prevsib->sibling)
2746afc0dc3SGrant Likely 			;
2756afc0dc3SGrant Likely 		prevsib->sibling = np->sibling;
2766afc0dc3SGrant Likely 	}
2776afc0dc3SGrant Likely 
2786afc0dc3SGrant Likely 	of_node_set_flag(np, OF_DETACHED);
2795801169aSFrank Rowand 
2805801169aSFrank Rowand 	/* race with of_find_node_by_phandle() prevented by devtree_lock */
28190dc0d1cSRob Herring 	__of_phandle_cache_inv_entry(np->phandle);
282d8c50088SPantelis Antoniou }
283d8c50088SPantelis Antoniou 
284d8c50088SPantelis Antoniou /**
285d8c50088SPantelis Antoniou  * of_detach_node() - "Unplug" a node from the device tree.
2863cb025d9SLee Jones  * @np:		Pointer to the caller's Device Node
287d8c50088SPantelis Antoniou  */
288d8c50088SPantelis Antoniou int of_detach_node(struct device_node *np)
289d8c50088SPantelis Antoniou {
290f5242e5aSGrant Likely 	struct of_reconfig_data rd;
291d8c50088SPantelis Antoniou 	unsigned long flags;
292d8c50088SPantelis Antoniou 
293f5242e5aSGrant Likely 	memset(&rd, 0, sizeof(rd));
294f5242e5aSGrant Likely 	rd.dn = np;
295f5242e5aSGrant Likely 
2968a2b22a2SGrant Likely 	mutex_lock(&of_mutex);
297d8c50088SPantelis Antoniou 	raw_spin_lock_irqsave(&devtree_lock, flags);
298d8c50088SPantelis Antoniou 	__of_detach_node(np);
2996afc0dc3SGrant Likely 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
3006afc0dc3SGrant Likely 
3018a2b22a2SGrant Likely 	__of_detach_node_sysfs(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 
310070ea018SLixin Wang static void property_list_free(struct property *prop_list)
311070ea018SLixin Wang {
312070ea018SLixin Wang 	struct property *prop, *next;
313070ea018SLixin Wang 
314070ea018SLixin Wang 	for (prop = prop_list; prop != NULL; prop = next) {
315070ea018SLixin Wang 		next = prop->next;
316070ea018SLixin Wang 		kfree(prop->name);
317070ea018SLixin Wang 		kfree(prop->value);
318070ea018SLixin Wang 		kfree(prop);
319070ea018SLixin Wang 	}
320070ea018SLixin Wang }
321070ea018SLixin Wang 
3226afc0dc3SGrant Likely /**
3236afc0dc3SGrant Likely  * of_node_release() - release a dynamically allocated node
3243cb025d9SLee Jones  * @kobj: kernel object of the node to be released
3256afc0dc3SGrant Likely  *
3266afc0dc3SGrant Likely  * In of_node_put() this function is passed to kref_put() as the destructor.
3276afc0dc3SGrant Likely  */
3286afc0dc3SGrant Likely void of_node_release(struct kobject *kobj)
3296afc0dc3SGrant Likely {
3306afc0dc3SGrant Likely 	struct device_node *node = kobj_to_device_node(kobj);
3316afc0dc3SGrant Likely 
3326afc0dc3SGrant Likely 	/* We should never be releasing nodes that haven't been detached. */
3336afc0dc3SGrant Likely 	if (!of_node_check_flag(node, OF_DETACHED)) {
3340d638a07SRob Herring 		pr_err("ERROR: Bad of_node_put() on %pOF\n", node);
335*74df14cdSFrank Rowand 
336*74df14cdSFrank Rowand 		/*
337*74df14cdSFrank Rowand 		 * of unittests will test this path.  Do not print the stack
338*74df14cdSFrank Rowand 		 * trace when the error is caused by unittest so that we do
339*74df14cdSFrank Rowand 		 * not display what a normal developer might reasonably
340*74df14cdSFrank Rowand 		 * consider a real bug.
341*74df14cdSFrank Rowand 		 */
342*74df14cdSFrank Rowand 		if (!IS_ENABLED(CONFIG_OF_UNITTEST) ||
343*74df14cdSFrank Rowand 		    strcmp(node->parent->full_name, "testcase-data")) {
3446afc0dc3SGrant Likely 			dump_stack();
345*74df14cdSFrank Rowand 			pr_err("ERROR: next of_node_put() on this node will result in a kboject warning 'refcount_t: underflow; use-after-free.'\n");
346*74df14cdSFrank Rowand 		}
347*74df14cdSFrank Rowand 
3486afc0dc3SGrant Likely 		return;
3496afc0dc3SGrant Likely 	}
3506afc0dc3SGrant Likely 	if (!of_node_check_flag(node, OF_DYNAMIC))
3516afc0dc3SGrant Likely 		return;
3526afc0dc3SGrant Likely 
353144552c7SFrank Rowand 	if (of_node_check_flag(node, OF_OVERLAY)) {
354144552c7SFrank Rowand 
355144552c7SFrank Rowand 		if (!of_node_check_flag(node, OF_OVERLAY_FREE_CSET)) {
356144552c7SFrank Rowand 			/* premature refcount of zero, do not free memory */
357144552c7SFrank Rowand 			pr_err("ERROR: memory leak before free overlay changeset,  %pOF\n",
358144552c7SFrank Rowand 			       node);
359144552c7SFrank Rowand 			return;
360144552c7SFrank Rowand 		}
361144552c7SFrank Rowand 
362144552c7SFrank Rowand 		/*
363144552c7SFrank Rowand 		 * If node->properties non-empty then properties were added
364144552c7SFrank Rowand 		 * to this node either by different overlay that has not
365144552c7SFrank Rowand 		 * yet been removed, or by a non-overlay mechanism.
366144552c7SFrank Rowand 		 */
367144552c7SFrank Rowand 		if (node->properties)
368144552c7SFrank Rowand 			pr_err("ERROR: %s(), unexpected properties in %pOF\n",
369144552c7SFrank Rowand 			       __func__, node);
370144552c7SFrank Rowand 	}
371144552c7SFrank Rowand 
372070ea018SLixin Wang 	property_list_free(node->properties);
373070ea018SLixin Wang 	property_list_free(node->deadprops);
3747b337cb3SSaravana Kannan 	fwnode_links_purge(of_fwnode_handle(node));
3756afc0dc3SGrant Likely 
3766afc0dc3SGrant Likely 	kfree(node->full_name);
3776afc0dc3SGrant Likely 	kfree(node->data);
3786afc0dc3SGrant Likely 	kfree(node);
3796afc0dc3SGrant Likely }
38069843396SPantelis Antoniou 
38169843396SPantelis Antoniou /**
38269843396SPantelis Antoniou  * __of_prop_dup - Copy a property dynamically.
38369843396SPantelis Antoniou  * @prop:	Property to copy
38469843396SPantelis Antoniou  * @allocflags:	Allocation flags (typically pass GFP_KERNEL)
38569843396SPantelis Antoniou  *
38669843396SPantelis Antoniou  * Copy a property by dynamically allocating the memory of both the
38727b3383aSGeert Uytterhoeven  * property structure and the property name & contents. The property's
38869843396SPantelis Antoniou  * flags have the OF_DYNAMIC bit set so that we can differentiate between
38969843396SPantelis Antoniou  * dynamically allocated properties and not.
3908c8239c2SRob Herring  *
3918c8239c2SRob Herring  * Return: The newly allocated property or NULL on out of memory error.
39269843396SPantelis Antoniou  */
39369843396SPantelis Antoniou struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags)
39469843396SPantelis Antoniou {
39569843396SPantelis Antoniou 	struct property *new;
39669843396SPantelis Antoniou 
39769843396SPantelis Antoniou 	new = kzalloc(sizeof(*new), allocflags);
39869843396SPantelis Antoniou 	if (!new)
39969843396SPantelis Antoniou 		return NULL;
40069843396SPantelis Antoniou 
40169843396SPantelis Antoniou 	/*
40269843396SPantelis Antoniou 	 * NOTE: There is no check for zero length value.
403b6ae5dc5SGrant Likely 	 * In case of a boolean property, this will allocate a value
40469843396SPantelis Antoniou 	 * of zero bytes. We do this to work around the use
40569843396SPantelis Antoniou 	 * of of_get_property() calls on boolean values.
40669843396SPantelis Antoniou 	 */
40769843396SPantelis Antoniou 	new->name = kstrdup(prop->name, allocflags);
40869843396SPantelis Antoniou 	new->value = kmemdup(prop->value, prop->length, allocflags);
40969843396SPantelis Antoniou 	new->length = prop->length;
41069843396SPantelis Antoniou 	if (!new->name || !new->value)
41169843396SPantelis Antoniou 		goto err_free;
41269843396SPantelis Antoniou 
41369843396SPantelis Antoniou 	/* mark the property as dynamic */
41469843396SPantelis Antoniou 	of_property_set_flag(new, OF_DYNAMIC);
41569843396SPantelis Antoniou 
41669843396SPantelis Antoniou 	return new;
41769843396SPantelis Antoniou 
41869843396SPantelis Antoniou  err_free:
41969843396SPantelis Antoniou 	kfree(new->name);
42069843396SPantelis Antoniou 	kfree(new->value);
42169843396SPantelis Antoniou 	kfree(new);
42269843396SPantelis Antoniou 	return NULL;
42369843396SPantelis Antoniou }
42469843396SPantelis Antoniou 
42569843396SPantelis Antoniou /**
426e5179581SGrant Likely  * __of_node_dup() - Duplicate or create an empty device node dynamically.
427b89dae18SFrank Rowand  * @np:		if not NULL, contains properties to be duplicated in new node
428b89dae18SFrank Rowand  * @full_name:	string value to be duplicated into new node's full_name field
42969843396SPantelis Antoniou  *
430b89dae18SFrank Rowand  * Create a device tree node, optionally duplicating the properties of
431b89dae18SFrank Rowand  * another node.  The node data are dynamically allocated and all the node
432b89dae18SFrank Rowand  * flags have the OF_DYNAMIC & OF_DETACHED bits set.
433b89dae18SFrank Rowand  *
4348c8239c2SRob Herring  * Return: The newly allocated node or NULL on out of memory error.
43569843396SPantelis Antoniou  */
436b89dae18SFrank Rowand struct device_node *__of_node_dup(const struct device_node *np,
437b89dae18SFrank Rowand 				  const char *full_name)
43869843396SPantelis Antoniou {
43969843396SPantelis Antoniou 	struct device_node *node;
44069843396SPantelis Antoniou 
441ef8bbd73SGrant Likely 	node = kzalloc(sizeof(*node), GFP_KERNEL);
44269843396SPantelis Antoniou 	if (!node)
44369843396SPantelis Antoniou 		return NULL;
444b89dae18SFrank Rowand 	node->full_name = kstrdup(full_name, GFP_KERNEL);
445e5179581SGrant Likely 	if (!node->full_name) {
446e5179581SGrant Likely 		kfree(node);
447e5179581SGrant Likely 		return NULL;
448e5179581SGrant Likely 	}
44969843396SPantelis Antoniou 
450ef8bbd73SGrant Likely 	of_node_set_flag(node, OF_DYNAMIC);
451ef8bbd73SGrant Likely 	of_node_set_flag(node, OF_DETACHED);
45269843396SPantelis Antoniou 	of_node_init(node);
45369843396SPantelis Antoniou 
454e5179581SGrant Likely 	/* Iterate over and duplicate all properties */
455e5179581SGrant Likely 	if (np) {
456e5179581SGrant Likely 		struct property *pp, *new_pp;
457e5179581SGrant Likely 		for_each_property_of_node(np, pp) {
458e5179581SGrant Likely 			new_pp = __of_prop_dup(pp, GFP_KERNEL);
459e5179581SGrant Likely 			if (!new_pp)
460e5179581SGrant Likely 				goto err_prop;
461e5179581SGrant Likely 			if (__of_add_property(node, new_pp)) {
462e5179581SGrant Likely 				kfree(new_pp->name);
463e5179581SGrant Likely 				kfree(new_pp->value);
464e5179581SGrant Likely 				kfree(new_pp);
465e5179581SGrant Likely 				goto err_prop;
466e5179581SGrant Likely 			}
467e5179581SGrant Likely 		}
468e5179581SGrant Likely 	}
46969843396SPantelis Antoniou 	return node;
47069843396SPantelis Antoniou 
471e5179581SGrant Likely  err_prop:
472e5179581SGrant Likely 	of_node_put(node); /* Frees the node and properties */
47369843396SPantelis Antoniou 	return NULL;
47469843396SPantelis Antoniou }
475201c910bSPantelis Antoniou 
476201c910bSPantelis Antoniou static void __of_changeset_entry_destroy(struct of_changeset_entry *ce)
477201c910bSPantelis Antoniou {
478144552c7SFrank Rowand 	if (ce->action == OF_RECONFIG_ATTACH_NODE &&
479144552c7SFrank Rowand 	    of_node_check_flag(ce->np, OF_OVERLAY)) {
480144552c7SFrank Rowand 		if (kref_read(&ce->np->kobj.kref) > 1) {
481144552c7SFrank 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",
482144552c7SFrank Rowand 			       kref_read(&ce->np->kobj.kref), ce->np);
483144552c7SFrank Rowand 		} else {
484144552c7SFrank Rowand 			of_node_set_flag(ce->np, OF_OVERLAY_FREE_CSET);
485144552c7SFrank Rowand 		}
486144552c7SFrank Rowand 	}
487144552c7SFrank Rowand 
488201c910bSPantelis Antoniou 	of_node_put(ce->np);
489201c910bSPantelis Antoniou 	list_del(&ce->node);
490201c910bSPantelis Antoniou 	kfree(ce);
491201c910bSPantelis Antoniou }
492201c910bSPantelis Antoniou 
493201c910bSPantelis Antoniou #ifdef DEBUG
494201c910bSPantelis Antoniou static void __of_changeset_entry_dump(struct of_changeset_entry *ce)
495201c910bSPantelis Antoniou {
496201c910bSPantelis Antoniou 	switch (ce->action) {
497201c910bSPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
498201c910bSPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
499201c910bSPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
5000d638a07SRob Herring 		pr_debug("cset<%p> %-15s %pOF/%s\n", ce, action_names[ce->action],
5010d638a07SRob Herring 			ce->np, ce->prop->name);
502201c910bSPantelis Antoniou 		break;
503201c910bSPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
504201c910bSPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
5050d638a07SRob Herring 		pr_debug("cset<%p> %-15s %pOF\n", ce, action_names[ce->action],
5060d638a07SRob Herring 			ce->np);
507201c910bSPantelis Antoniou 		break;
508201c910bSPantelis Antoniou 	}
509201c910bSPantelis Antoniou }
510201c910bSPantelis Antoniou #else
511201c910bSPantelis Antoniou static inline void __of_changeset_entry_dump(struct of_changeset_entry *ce)
512201c910bSPantelis Antoniou {
513201c910bSPantelis Antoniou 	/* empty */
514201c910bSPantelis Antoniou }
515201c910bSPantelis Antoniou #endif
516201c910bSPantelis Antoniou 
517201c910bSPantelis Antoniou static void __of_changeset_entry_invert(struct of_changeset_entry *ce,
518201c910bSPantelis Antoniou 					  struct of_changeset_entry *rce)
519201c910bSPantelis Antoniou {
520201c910bSPantelis Antoniou 	memcpy(rce, ce, sizeof(*rce));
521201c910bSPantelis Antoniou 
522201c910bSPantelis Antoniou 	switch (ce->action) {
523201c910bSPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
524201c910bSPantelis Antoniou 		rce->action = OF_RECONFIG_DETACH_NODE;
525201c910bSPantelis Antoniou 		break;
526201c910bSPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
527201c910bSPantelis Antoniou 		rce->action = OF_RECONFIG_ATTACH_NODE;
528201c910bSPantelis Antoniou 		break;
529201c910bSPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
530201c910bSPantelis Antoniou 		rce->action = OF_RECONFIG_REMOVE_PROPERTY;
531201c910bSPantelis Antoniou 		break;
532201c910bSPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
533201c910bSPantelis Antoniou 		rce->action = OF_RECONFIG_ADD_PROPERTY;
534201c910bSPantelis Antoniou 		break;
535201c910bSPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
536201c910bSPantelis Antoniou 		rce->old_prop = ce->prop;
537201c910bSPantelis Antoniou 		rce->prop = ce->old_prop;
538b9c43856SPantelis Antoniou 		/* update was used but original property did not exist */
539b9c43856SPantelis Antoniou 		if (!rce->prop) {
540b9c43856SPantelis Antoniou 			rce->action = OF_RECONFIG_REMOVE_PROPERTY;
541b9c43856SPantelis Antoniou 			rce->prop = ce->prop;
542b9c43856SPantelis Antoniou 		}
543201c910bSPantelis Antoniou 		break;
544201c910bSPantelis Antoniou 	}
545201c910bSPantelis Antoniou }
546201c910bSPantelis Antoniou 
54724789c5cSFrank Rowand static int __of_changeset_entry_notify(struct of_changeset_entry *ce,
54824789c5cSFrank Rowand 		bool revert)
549201c910bSPantelis Antoniou {
550f5242e5aSGrant Likely 	struct of_reconfig_data rd;
551201c910bSPantelis Antoniou 	struct of_changeset_entry ce_inverted;
55224789c5cSFrank Rowand 	int ret = 0;
553201c910bSPantelis Antoniou 
554201c910bSPantelis Antoniou 	if (revert) {
555201c910bSPantelis Antoniou 		__of_changeset_entry_invert(ce, &ce_inverted);
556201c910bSPantelis Antoniou 		ce = &ce_inverted;
557201c910bSPantelis Antoniou 	}
558201c910bSPantelis Antoniou 
559201c910bSPantelis Antoniou 	switch (ce->action) {
560201c910bSPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
561201c910bSPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
562f5242e5aSGrant Likely 		memset(&rd, 0, sizeof(rd));
563f5242e5aSGrant Likely 		rd.dn = ce->np;
564f5242e5aSGrant Likely 		ret = of_reconfig_notify(ce->action, &rd);
565201c910bSPantelis Antoniou 		break;
566201c910bSPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
567201c910bSPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
568201c910bSPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
569201c910bSPantelis Antoniou 		ret = of_property_notify(ce->action, ce->np, ce->prop, ce->old_prop);
570201c910bSPantelis Antoniou 		break;
571201c910bSPantelis Antoniou 	default:
572606ad42aSRob Herring 		pr_err("invalid devicetree changeset action: %i\n",
573201c910bSPantelis Antoniou 			(int)ce->action);
57424789c5cSFrank Rowand 		ret = -EINVAL;
575201c910bSPantelis Antoniou 	}
576201c910bSPantelis Antoniou 
577201c910bSPantelis Antoniou 	if (ret)
5780d638a07SRob Herring 		pr_err("changeset notifier error @%pOF\n", ce->np);
57924789c5cSFrank Rowand 	return ret;
580201c910bSPantelis Antoniou }
581201c910bSPantelis Antoniou 
582201c910bSPantelis Antoniou static int __of_changeset_entry_apply(struct of_changeset_entry *ce)
583201c910bSPantelis Antoniou {
584201c910bSPantelis Antoniou 	struct property *old_prop, **propp;
585201c910bSPantelis Antoniou 	unsigned long flags;
586201c910bSPantelis Antoniou 	int ret = 0;
587201c910bSPantelis Antoniou 
588201c910bSPantelis Antoniou 	__of_changeset_entry_dump(ce);
589201c910bSPantelis Antoniou 
590201c910bSPantelis Antoniou 	raw_spin_lock_irqsave(&devtree_lock, flags);
591201c910bSPantelis Antoniou 	switch (ce->action) {
592201c910bSPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
593201c910bSPantelis Antoniou 		__of_attach_node(ce->np);
594201c910bSPantelis Antoniou 		break;
595201c910bSPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
596201c910bSPantelis Antoniou 		__of_detach_node(ce->np);
597201c910bSPantelis Antoniou 		break;
598201c910bSPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
599201c910bSPantelis Antoniou 		/* If the property is in deadprops then it must be removed */
600201c910bSPantelis Antoniou 		for (propp = &ce->np->deadprops; *propp; propp = &(*propp)->next) {
601201c910bSPantelis Antoniou 			if (*propp == ce->prop) {
602201c910bSPantelis Antoniou 				*propp = ce->prop->next;
603201c910bSPantelis Antoniou 				ce->prop->next = NULL;
604201c910bSPantelis Antoniou 				break;
605201c910bSPantelis Antoniou 			}
606201c910bSPantelis Antoniou 		}
607201c910bSPantelis Antoniou 
608201c910bSPantelis Antoniou 		ret = __of_add_property(ce->np, ce->prop);
609201c910bSPantelis Antoniou 		if (ret) {
6100d638a07SRob Herring 			pr_err("changeset: add_property failed @%pOF/%s\n",
6110d638a07SRob Herring 				ce->np,
612201c910bSPantelis Antoniou 				ce->prop->name);
613201c910bSPantelis Antoniou 			break;
614201c910bSPantelis Antoniou 		}
615201c910bSPantelis Antoniou 		break;
616201c910bSPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
617201c910bSPantelis Antoniou 		ret = __of_remove_property(ce->np, ce->prop);
618201c910bSPantelis Antoniou 		if (ret) {
6190d638a07SRob Herring 			pr_err("changeset: remove_property failed @%pOF/%s\n",
6200d638a07SRob Herring 				ce->np,
621201c910bSPantelis Antoniou 				ce->prop->name);
622201c910bSPantelis Antoniou 			break;
623201c910bSPantelis Antoniou 		}
624201c910bSPantelis Antoniou 		break;
625201c910bSPantelis Antoniou 
626201c910bSPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
627201c910bSPantelis Antoniou 		/* If the property is in deadprops then it must be removed */
628201c910bSPantelis Antoniou 		for (propp = &ce->np->deadprops; *propp; propp = &(*propp)->next) {
629201c910bSPantelis Antoniou 			if (*propp == ce->prop) {
630201c910bSPantelis Antoniou 				*propp = ce->prop->next;
631201c910bSPantelis Antoniou 				ce->prop->next = NULL;
632201c910bSPantelis Antoniou 				break;
633201c910bSPantelis Antoniou 			}
634201c910bSPantelis Antoniou 		}
635201c910bSPantelis Antoniou 
636201c910bSPantelis Antoniou 		ret = __of_update_property(ce->np, ce->prop, &old_prop);
637201c910bSPantelis Antoniou 		if (ret) {
6380d638a07SRob Herring 			pr_err("changeset: update_property failed @%pOF/%s\n",
6390d638a07SRob Herring 				ce->np,
640201c910bSPantelis Antoniou 				ce->prop->name);
641201c910bSPantelis Antoniou 			break;
642201c910bSPantelis Antoniou 		}
643201c910bSPantelis Antoniou 		break;
644201c910bSPantelis Antoniou 	default:
645201c910bSPantelis Antoniou 		ret = -EINVAL;
646201c910bSPantelis Antoniou 	}
647201c910bSPantelis Antoniou 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
648201c910bSPantelis Antoniou 
649201c910bSPantelis Antoniou 	if (ret)
650201c910bSPantelis Antoniou 		return ret;
651201c910bSPantelis Antoniou 
652201c910bSPantelis Antoniou 	switch (ce->action) {
653201c910bSPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
654201c910bSPantelis Antoniou 		__of_attach_node_sysfs(ce->np);
655201c910bSPantelis Antoniou 		break;
656201c910bSPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
657201c910bSPantelis Antoniou 		__of_detach_node_sysfs(ce->np);
658201c910bSPantelis Antoniou 		break;
659201c910bSPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
660201c910bSPantelis Antoniou 		/* ignore duplicate names */
661201c910bSPantelis Antoniou 		__of_add_property_sysfs(ce->np, ce->prop);
662201c910bSPantelis Antoniou 		break;
663201c910bSPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
664201c910bSPantelis Antoniou 		__of_remove_property_sysfs(ce->np, ce->prop);
665201c910bSPantelis Antoniou 		break;
666201c910bSPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
667201c910bSPantelis Antoniou 		__of_update_property_sysfs(ce->np, ce->prop, ce->old_prop);
668201c910bSPantelis Antoniou 		break;
669201c910bSPantelis Antoniou 	}
670201c910bSPantelis Antoniou 
671201c910bSPantelis Antoniou 	return 0;
672201c910bSPantelis Antoniou }
673201c910bSPantelis Antoniou 
674201c910bSPantelis Antoniou static inline int __of_changeset_entry_revert(struct of_changeset_entry *ce)
675201c910bSPantelis Antoniou {
676201c910bSPantelis Antoniou 	struct of_changeset_entry ce_inverted;
677201c910bSPantelis Antoniou 
678201c910bSPantelis Antoniou 	__of_changeset_entry_invert(ce, &ce_inverted);
679201c910bSPantelis Antoniou 	return __of_changeset_entry_apply(&ce_inverted);
680201c910bSPantelis Antoniou }
681201c910bSPantelis Antoniou 
682201c910bSPantelis Antoniou /**
683201c910bSPantelis Antoniou  * of_changeset_init - Initialize a changeset for use
684201c910bSPantelis Antoniou  *
685201c910bSPantelis Antoniou  * @ocs:	changeset pointer
686201c910bSPantelis Antoniou  *
687201c910bSPantelis Antoniou  * Initialize a changeset structure
688201c910bSPantelis Antoniou  */
689201c910bSPantelis Antoniou void of_changeset_init(struct of_changeset *ocs)
690201c910bSPantelis Antoniou {
691201c910bSPantelis Antoniou 	memset(ocs, 0, sizeof(*ocs));
692201c910bSPantelis Antoniou 	INIT_LIST_HEAD(&ocs->entries);
693201c910bSPantelis Antoniou }
69418322377SGavin Shan EXPORT_SYMBOL_GPL(of_changeset_init);
695201c910bSPantelis Antoniou 
696201c910bSPantelis Antoniou /**
697201c910bSPantelis Antoniou  * of_changeset_destroy - Destroy a changeset
698201c910bSPantelis Antoniou  *
699201c910bSPantelis Antoniou  * @ocs:	changeset pointer
700201c910bSPantelis Antoniou  *
701201c910bSPantelis Antoniou  * Destroys a changeset. Note that if a changeset is applied,
702201c910bSPantelis Antoniou  * its changes to the tree cannot be reverted.
703201c910bSPantelis Antoniou  */
704201c910bSPantelis Antoniou void of_changeset_destroy(struct of_changeset *ocs)
705201c910bSPantelis Antoniou {
706201c910bSPantelis Antoniou 	struct of_changeset_entry *ce, *cen;
707201c910bSPantelis Antoniou 
708201c910bSPantelis Antoniou 	list_for_each_entry_safe_reverse(ce, cen, &ocs->entries, node)
709201c910bSPantelis Antoniou 		__of_changeset_entry_destroy(ce);
710201c910bSPantelis Antoniou }
71118322377SGavin Shan EXPORT_SYMBOL_GPL(of_changeset_destroy);
712201c910bSPantelis Antoniou 
71324789c5cSFrank Rowand /*
71424789c5cSFrank Rowand  * Apply the changeset entries in @ocs.
71524789c5cSFrank Rowand  * If apply fails, an attempt is made to revert the entries that were
71624789c5cSFrank Rowand  * successfully applied.
71724789c5cSFrank Rowand  *
71824789c5cSFrank Rowand  * If multiple revert errors occur then only the final revert error is reported.
71924789c5cSFrank Rowand  *
72024789c5cSFrank Rowand  * Returns 0 on success, a negative error value in case of an error.
72124789c5cSFrank Rowand  * If a revert error occurs, it is returned in *ret_revert.
72224789c5cSFrank Rowand  */
72324789c5cSFrank Rowand int __of_changeset_apply_entries(struct of_changeset *ocs, int *ret_revert)
724201c910bSPantelis Antoniou {
725201c910bSPantelis Antoniou 	struct of_changeset_entry *ce;
72624789c5cSFrank Rowand 	int ret, ret_tmp;
727201c910bSPantelis Antoniou 
728606ad42aSRob Herring 	pr_debug("changeset: applying...\n");
729201c910bSPantelis Antoniou 	list_for_each_entry(ce, &ocs->entries, node) {
730201c910bSPantelis Antoniou 		ret = __of_changeset_entry_apply(ce);
731201c910bSPantelis Antoniou 		if (ret) {
732606ad42aSRob Herring 			pr_err("Error applying changeset (%d)\n", ret);
73324789c5cSFrank Rowand 			list_for_each_entry_continue_reverse(ce, &ocs->entries,
73424789c5cSFrank Rowand 							     node) {
73524789c5cSFrank Rowand 				ret_tmp = __of_changeset_entry_revert(ce);
73624789c5cSFrank Rowand 				if (ret_tmp)
73724789c5cSFrank Rowand 					*ret_revert = ret_tmp;
73824789c5cSFrank Rowand 			}
739201c910bSPantelis Antoniou 			return ret;
740201c910bSPantelis Antoniou 		}
741201c910bSPantelis Antoniou 	}
74224789c5cSFrank Rowand 
74324789c5cSFrank Rowand 	return 0;
74424789c5cSFrank Rowand }
74524789c5cSFrank Rowand 
74624789c5cSFrank Rowand /*
74724789c5cSFrank Rowand  * Returns 0 on success, a negative error value in case of an error.
74824789c5cSFrank Rowand  *
749e9d92e40SGeert Uytterhoeven  * If multiple changeset entry notification errors occur then only the
75024789c5cSFrank Rowand  * final notification error is reported.
75124789c5cSFrank Rowand  */
75224789c5cSFrank Rowand int __of_changeset_apply_notify(struct of_changeset *ocs)
75324789c5cSFrank Rowand {
75424789c5cSFrank Rowand 	struct of_changeset_entry *ce;
75524789c5cSFrank Rowand 	int ret = 0, ret_tmp;
75624789c5cSFrank Rowand 
75724789c5cSFrank Rowand 	pr_debug("changeset: emitting notifiers.\n");
758201c910bSPantelis Antoniou 
759201c910bSPantelis Antoniou 	/* drop the global lock while emitting notifiers */
760201c910bSPantelis Antoniou 	mutex_unlock(&of_mutex);
76124789c5cSFrank Rowand 	list_for_each_entry(ce, &ocs->entries, node) {
76224789c5cSFrank Rowand 		ret_tmp = __of_changeset_entry_notify(ce, 0);
76324789c5cSFrank Rowand 		if (ret_tmp)
76424789c5cSFrank Rowand 			ret = ret_tmp;
76524789c5cSFrank Rowand 	}
766201c910bSPantelis Antoniou 	mutex_lock(&of_mutex);
767606ad42aSRob Herring 	pr_debug("changeset: notifiers sent.\n");
768201c910bSPantelis Antoniou 
76924789c5cSFrank Rowand 	return ret;
77024789c5cSFrank Rowand }
77124789c5cSFrank Rowand 
77224789c5cSFrank Rowand /*
77324789c5cSFrank Rowand  * Returns 0 on success, a negative error value in case of an error.
77424789c5cSFrank Rowand  *
77524789c5cSFrank Rowand  * If a changeset entry apply fails, an attempt is made to revert any
77624789c5cSFrank Rowand  * previous entries in the changeset.  If any of the reverts fails,
77724789c5cSFrank Rowand  * that failure is not reported.  Thus the state of the device tree
77824789c5cSFrank Rowand  * is unknown if an apply error occurs.
77924789c5cSFrank Rowand  */
78024789c5cSFrank Rowand static int __of_changeset_apply(struct of_changeset *ocs)
78124789c5cSFrank Rowand {
78224789c5cSFrank Rowand 	int ret, ret_revert = 0;
78324789c5cSFrank Rowand 
78424789c5cSFrank Rowand 	ret = __of_changeset_apply_entries(ocs, &ret_revert);
78524789c5cSFrank Rowand 	if (!ret)
78624789c5cSFrank Rowand 		ret = __of_changeset_apply_notify(ocs);
78724789c5cSFrank Rowand 
78824789c5cSFrank Rowand 	return ret;
789201c910bSPantelis Antoniou }
790201c910bSPantelis Antoniou 
791201c910bSPantelis Antoniou /**
79218322377SGavin Shan  * of_changeset_apply - Applies a changeset
793201c910bSPantelis Antoniou  *
794201c910bSPantelis Antoniou  * @ocs:	changeset pointer
795201c910bSPantelis Antoniou  *
79618322377SGavin Shan  * Applies a changeset to the live tree.
79718322377SGavin Shan  * Any side-effects of live tree state changes are applied here on
79818322377SGavin Shan  * success, like creation/destruction of devices and side-effects
79918322377SGavin Shan  * like creation of sysfs properties and directories.
8008c8239c2SRob Herring  *
8018c8239c2SRob Herring  * Return: 0 on success, a negative error value in case of an error.
80218322377SGavin Shan  * On error the partially applied effects are reverted.
803201c910bSPantelis Antoniou  */
80418322377SGavin Shan int of_changeset_apply(struct of_changeset *ocs)
80518322377SGavin Shan {
80618322377SGavin Shan 	int ret;
80718322377SGavin Shan 
80818322377SGavin Shan 	mutex_lock(&of_mutex);
80918322377SGavin Shan 	ret = __of_changeset_apply(ocs);
81018322377SGavin Shan 	mutex_unlock(&of_mutex);
81118322377SGavin Shan 
81218322377SGavin Shan 	return ret;
81318322377SGavin Shan }
81418322377SGavin Shan EXPORT_SYMBOL_GPL(of_changeset_apply);
81518322377SGavin Shan 
81624789c5cSFrank Rowand /*
81724789c5cSFrank Rowand  * Revert the changeset entries in @ocs.
81824789c5cSFrank Rowand  * If revert fails, an attempt is made to re-apply the entries that were
81924789c5cSFrank Rowand  * successfully removed.
82024789c5cSFrank Rowand  *
82124789c5cSFrank Rowand  * If multiple re-apply errors occur then only the final apply error is
82224789c5cSFrank Rowand  * reported.
82324789c5cSFrank Rowand  *
82424789c5cSFrank Rowand  * Returns 0 on success, a negative error value in case of an error.
82524789c5cSFrank Rowand  * If an apply error occurs, it is returned in *ret_apply.
82624789c5cSFrank Rowand  */
82724789c5cSFrank Rowand int __of_changeset_revert_entries(struct of_changeset *ocs, int *ret_apply)
828201c910bSPantelis Antoniou {
829201c910bSPantelis Antoniou 	struct of_changeset_entry *ce;
83024789c5cSFrank Rowand 	int ret, ret_tmp;
831201c910bSPantelis Antoniou 
832606ad42aSRob Herring 	pr_debug("changeset: reverting...\n");
833201c910bSPantelis Antoniou 	list_for_each_entry_reverse(ce, &ocs->entries, node) {
834201c910bSPantelis Antoniou 		ret = __of_changeset_entry_revert(ce);
835201c910bSPantelis Antoniou 		if (ret) {
836606ad42aSRob Herring 			pr_err("Error reverting changeset (%d)\n", ret);
83724789c5cSFrank Rowand 			list_for_each_entry_continue(ce, &ocs->entries, node) {
83824789c5cSFrank Rowand 				ret_tmp = __of_changeset_entry_apply(ce);
83924789c5cSFrank Rowand 				if (ret_tmp)
84024789c5cSFrank Rowand 					*ret_apply = ret_tmp;
84124789c5cSFrank Rowand 			}
842201c910bSPantelis Antoniou 			return ret;
843201c910bSPantelis Antoniou 		}
844201c910bSPantelis Antoniou 	}
84524789c5cSFrank Rowand 
84624789c5cSFrank Rowand 	return 0;
84724789c5cSFrank Rowand }
84824789c5cSFrank Rowand 
84924789c5cSFrank Rowand /*
850e9d92e40SGeert Uytterhoeven  * If multiple changeset entry notification errors occur then only the
85124789c5cSFrank Rowand  * final notification error is reported.
85224789c5cSFrank Rowand  */
85324789c5cSFrank Rowand int __of_changeset_revert_notify(struct of_changeset *ocs)
85424789c5cSFrank Rowand {
85524789c5cSFrank Rowand 	struct of_changeset_entry *ce;
85624789c5cSFrank Rowand 	int ret = 0, ret_tmp;
85724789c5cSFrank Rowand 
85824789c5cSFrank Rowand 	pr_debug("changeset: emitting notifiers.\n");
859201c910bSPantelis Antoniou 
860201c910bSPantelis Antoniou 	/* drop the global lock while emitting notifiers */
861201c910bSPantelis Antoniou 	mutex_unlock(&of_mutex);
86224789c5cSFrank Rowand 	list_for_each_entry_reverse(ce, &ocs->entries, node) {
86324789c5cSFrank Rowand 		ret_tmp = __of_changeset_entry_notify(ce, 1);
86424789c5cSFrank Rowand 		if (ret_tmp)
86524789c5cSFrank Rowand 			ret = ret_tmp;
86624789c5cSFrank Rowand 	}
867201c910bSPantelis Antoniou 	mutex_lock(&of_mutex);
868606ad42aSRob Herring 	pr_debug("changeset: notifiers sent.\n");
869201c910bSPantelis Antoniou 
87024789c5cSFrank Rowand 	return ret;
87124789c5cSFrank Rowand }
87224789c5cSFrank Rowand 
87324789c5cSFrank Rowand static int __of_changeset_revert(struct of_changeset *ocs)
87424789c5cSFrank Rowand {
87524789c5cSFrank Rowand 	int ret, ret_reply;
87624789c5cSFrank Rowand 
87724789c5cSFrank Rowand 	ret_reply = 0;
87824789c5cSFrank Rowand 	ret = __of_changeset_revert_entries(ocs, &ret_reply);
87924789c5cSFrank Rowand 
88024789c5cSFrank Rowand 	if (!ret)
88124789c5cSFrank Rowand 		ret = __of_changeset_revert_notify(ocs);
88224789c5cSFrank Rowand 
88324789c5cSFrank Rowand 	return ret;
884201c910bSPantelis Antoniou }
885201c910bSPantelis Antoniou 
886201c910bSPantelis Antoniou /**
88718322377SGavin Shan  * of_changeset_revert - Reverts an applied changeset
88818322377SGavin Shan  *
88918322377SGavin Shan  * @ocs:	changeset pointer
89018322377SGavin Shan  *
89118322377SGavin Shan  * Reverts a changeset returning the state of the tree to what it
89218322377SGavin Shan  * was before the application.
89318322377SGavin Shan  * Any side-effects like creation/destruction of devices and
89418322377SGavin Shan  * removal of sysfs properties and directories are applied.
8958c8239c2SRob Herring  *
8968c8239c2SRob Herring  * Return: 0 on success, a negative error value in case of an error.
89718322377SGavin Shan  */
89818322377SGavin Shan int of_changeset_revert(struct of_changeset *ocs)
89918322377SGavin Shan {
90018322377SGavin Shan 	int ret;
90118322377SGavin Shan 
90218322377SGavin Shan 	mutex_lock(&of_mutex);
90318322377SGavin Shan 	ret = __of_changeset_revert(ocs);
90418322377SGavin Shan 	mutex_unlock(&of_mutex);
90518322377SGavin Shan 
90618322377SGavin Shan 	return ret;
90718322377SGavin Shan }
90818322377SGavin Shan EXPORT_SYMBOL_GPL(of_changeset_revert);
90918322377SGavin Shan 
91018322377SGavin Shan /**
9110290c4caSFrank Rowand  * of_changeset_action - Add an action to the tail of the changeset list
912201c910bSPantelis Antoniou  *
913201c910bSPantelis Antoniou  * @ocs:	changeset pointer
914201c910bSPantelis Antoniou  * @action:	action to perform
915201c910bSPantelis Antoniou  * @np:		Pointer to device node
916201c910bSPantelis Antoniou  * @prop:	Pointer to property
917201c910bSPantelis Antoniou  *
918201c910bSPantelis Antoniou  * On action being one of:
919201c910bSPantelis Antoniou  * + OF_RECONFIG_ATTACH_NODE
920201c910bSPantelis Antoniou  * + OF_RECONFIG_DETACH_NODE,
921201c910bSPantelis Antoniou  * + OF_RECONFIG_ADD_PROPERTY
922201c910bSPantelis Antoniou  * + OF_RECONFIG_REMOVE_PROPERTY,
923201c910bSPantelis Antoniou  * + OF_RECONFIG_UPDATE_PROPERTY
9248c8239c2SRob Herring  *
9258c8239c2SRob Herring  * Return: 0 on success, a negative error value in case of an error.
926201c910bSPantelis Antoniou  */
927201c910bSPantelis Antoniou int of_changeset_action(struct of_changeset *ocs, unsigned long action,
928201c910bSPantelis Antoniou 		struct device_node *np, struct property *prop)
929201c910bSPantelis Antoniou {
930201c910bSPantelis Antoniou 	struct of_changeset_entry *ce;
931201c910bSPantelis Antoniou 
932201c910bSPantelis Antoniou 	ce = kzalloc(sizeof(*ce), GFP_KERNEL);
933606ad42aSRob Herring 	if (!ce)
934201c910bSPantelis Antoniou 		return -ENOMEM;
935606ad42aSRob Herring 
936201c910bSPantelis Antoniou 	/* get a reference to the node */
937201c910bSPantelis Antoniou 	ce->action = action;
938201c910bSPantelis Antoniou 	ce->np = of_node_get(np);
939201c910bSPantelis Antoniou 	ce->prop = prop;
940201c910bSPantelis Antoniou 
941201c910bSPantelis Antoniou 	if (action == OF_RECONFIG_UPDATE_PROPERTY && prop)
942201c910bSPantelis Antoniou 		ce->old_prop = of_find_property(np, prop->name, NULL);
943201c910bSPantelis Antoniou 
944201c910bSPantelis Antoniou 	/* add it to the list */
945201c910bSPantelis Antoniou 	list_add_tail(&ce->node, &ocs->entries);
946201c910bSPantelis Antoniou 	return 0;
947201c910bSPantelis Antoniou }
94818322377SGavin Shan EXPORT_SYMBOL_GPL(of_changeset_action);
949