xref: /linux/drivers/of/dynamic.c (revision 0d638a07d3a1e98a7598eb2812a6236324e4c55f)
16afc0dc3SGrant Likely /*
26afc0dc3SGrant Likely  * Support for dynamic device trees.
36afc0dc3SGrant Likely  *
46afc0dc3SGrant Likely  * On some platforms, the device tree can be manipulated at runtime.
56afc0dc3SGrant Likely  * The routines in this section support adding, removing and changing
66afc0dc3SGrant Likely  * device tree nodes.
76afc0dc3SGrant Likely  */
86afc0dc3SGrant Likely 
9606ad42aSRob Herring #define pr_fmt(fmt)	"OF: " fmt
10606ad42aSRob Herring 
116afc0dc3SGrant Likely #include <linux/of.h>
126afc0dc3SGrant Likely #include <linux/spinlock.h>
136afc0dc3SGrant Likely #include <linux/slab.h>
146afc0dc3SGrant Likely #include <linux/string.h>
156afc0dc3SGrant Likely #include <linux/proc_fs.h>
166afc0dc3SGrant Likely 
176afc0dc3SGrant Likely #include "of_private.h"
186afc0dc3SGrant Likely 
196afc0dc3SGrant Likely /**
206afc0dc3SGrant Likely  * of_node_get() - Increment refcount of a node
216afc0dc3SGrant Likely  * @node:	Node to inc refcount, NULL is supported to simplify writing of
226afc0dc3SGrant Likely  *		callers
236afc0dc3SGrant Likely  *
246afc0dc3SGrant Likely  * Returns node.
256afc0dc3SGrant Likely  */
266afc0dc3SGrant Likely struct device_node *of_node_get(struct device_node *node)
276afc0dc3SGrant Likely {
286afc0dc3SGrant Likely 	if (node)
296afc0dc3SGrant Likely 		kobject_get(&node->kobj);
306afc0dc3SGrant Likely 	return node;
316afc0dc3SGrant Likely }
326afc0dc3SGrant Likely EXPORT_SYMBOL(of_node_get);
336afc0dc3SGrant Likely 
346afc0dc3SGrant Likely /**
356afc0dc3SGrant Likely  * of_node_put() - Decrement refcount of a node
366afc0dc3SGrant Likely  * @node:	Node to dec refcount, NULL is supported to simplify writing of
376afc0dc3SGrant Likely  *		callers
386afc0dc3SGrant Likely  */
396afc0dc3SGrant Likely void of_node_put(struct device_node *node)
406afc0dc3SGrant Likely {
416afc0dc3SGrant Likely 	if (node)
426afc0dc3SGrant Likely 		kobject_put(&node->kobj);
436afc0dc3SGrant Likely }
446afc0dc3SGrant Likely EXPORT_SYMBOL(of_node_put);
456afc0dc3SGrant Likely 
468a2b22a2SGrant Likely void __of_detach_node_sysfs(struct device_node *np)
476afc0dc3SGrant Likely {
486afc0dc3SGrant Likely 	struct property *pp;
496afc0dc3SGrant Likely 
50ef69d740SGaurav Minocha 	if (!IS_ENABLED(CONFIG_SYSFS))
51ef69d740SGaurav Minocha 		return;
52ef69d740SGaurav Minocha 
536afc0dc3SGrant Likely 	BUG_ON(!of_node_is_initialized(np));
548a2b22a2SGrant Likely 	if (!of_kset)
558a2b22a2SGrant Likely 		return;
566afc0dc3SGrant Likely 
576afc0dc3SGrant Likely 	/* only remove properties if on sysfs */
586afc0dc3SGrant Likely 	if (of_node_is_attached(np)) {
596afc0dc3SGrant Likely 		for_each_property_of_node(np, pp)
60d9fc8807SFrank Rowand 			__of_sysfs_remove_bin_file(np, pp);
616afc0dc3SGrant Likely 		kobject_del(&np->kobj);
626afc0dc3SGrant Likely 	}
636afc0dc3SGrant Likely 
646afc0dc3SGrant Likely 	/* finally remove the kobj_init ref */
656afc0dc3SGrant Likely 	of_node_put(np);
666afc0dc3SGrant Likely }
676afc0dc3SGrant Likely 
686afc0dc3SGrant Likely static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);
696afc0dc3SGrant Likely 
706afc0dc3SGrant Likely int of_reconfig_notifier_register(struct notifier_block *nb)
716afc0dc3SGrant Likely {
726afc0dc3SGrant Likely 	return blocking_notifier_chain_register(&of_reconfig_chain, nb);
736afc0dc3SGrant Likely }
746afc0dc3SGrant Likely EXPORT_SYMBOL_GPL(of_reconfig_notifier_register);
756afc0dc3SGrant Likely 
766afc0dc3SGrant Likely int of_reconfig_notifier_unregister(struct notifier_block *nb)
776afc0dc3SGrant Likely {
786afc0dc3SGrant Likely 	return blocking_notifier_chain_unregister(&of_reconfig_chain, nb);
796afc0dc3SGrant Likely }
806afc0dc3SGrant Likely EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister);
816afc0dc3SGrant Likely 
8200aa3720SGrant Likely #ifdef DEBUG
8300aa3720SGrant Likely const char *action_names[] = {
8400aa3720SGrant Likely 	[OF_RECONFIG_ATTACH_NODE] = "ATTACH_NODE",
8500aa3720SGrant Likely 	[OF_RECONFIG_DETACH_NODE] = "DETACH_NODE",
8600aa3720SGrant Likely 	[OF_RECONFIG_ADD_PROPERTY] = "ADD_PROPERTY",
8700aa3720SGrant Likely 	[OF_RECONFIG_REMOVE_PROPERTY] = "REMOVE_PROPERTY",
8800aa3720SGrant Likely 	[OF_RECONFIG_UPDATE_PROPERTY] = "UPDATE_PROPERTY",
8900aa3720SGrant Likely };
9000aa3720SGrant Likely #endif
9100aa3720SGrant Likely 
92f5242e5aSGrant Likely int of_reconfig_notify(unsigned long action, struct of_reconfig_data *p)
936afc0dc3SGrant Likely {
946afc0dc3SGrant Likely 	int rc;
9500aa3720SGrant Likely #ifdef DEBUG
96f5242e5aSGrant Likely 	struct of_reconfig_data *pr = p;
976afc0dc3SGrant Likely 
9800aa3720SGrant Likely 	switch (action) {
9900aa3720SGrant Likely 	case OF_RECONFIG_ATTACH_NODE:
10000aa3720SGrant Likely 	case OF_RECONFIG_DETACH_NODE:
101*0d638a07SRob Herring 		pr_debug("notify %-15s %pOF\n", action_names[action],
102*0d638a07SRob Herring 			pr->dn);
10300aa3720SGrant Likely 		break;
10400aa3720SGrant Likely 	case OF_RECONFIG_ADD_PROPERTY:
10500aa3720SGrant Likely 	case OF_RECONFIG_REMOVE_PROPERTY:
10600aa3720SGrant Likely 	case OF_RECONFIG_UPDATE_PROPERTY:
107*0d638a07SRob Herring 		pr_debug("notify %-15s %pOF:%s\n", action_names[action],
108*0d638a07SRob Herring 			pr->dn, pr->prop->name);
10900aa3720SGrant Likely 		break;
11000aa3720SGrant Likely 
11100aa3720SGrant Likely 	}
11200aa3720SGrant Likely #endif
1136afc0dc3SGrant Likely 	rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p);
1146afc0dc3SGrant Likely 	return notifier_to_errno(rc);
1156afc0dc3SGrant Likely }
1166afc0dc3SGrant Likely 
117b53a2340SPantelis Antoniou /*
118b53a2340SPantelis Antoniou  * of_reconfig_get_state_change()	- Returns new state of device
119b53a2340SPantelis Antoniou  * @action	- action of the of notifier
120b53a2340SPantelis Antoniou  * @arg		- argument of the of notifier
121b53a2340SPantelis Antoniou  *
122b53a2340SPantelis Antoniou  * Returns the new state of a device based on the notifier used.
123b53a2340SPantelis Antoniou  * Returns 0 on device going from enabled to disabled, 1 on device
124b53a2340SPantelis Antoniou  * going from disabled to enabled and -1 on no change.
125b53a2340SPantelis Antoniou  */
126f5242e5aSGrant Likely int of_reconfig_get_state_change(unsigned long action, struct of_reconfig_data *pr)
127b53a2340SPantelis Antoniou {
128f5242e5aSGrant Likely 	struct property *prop, *old_prop = NULL;
129b53a2340SPantelis Antoniou 	int is_status, status_state, old_status_state, prev_state, new_state;
130b53a2340SPantelis Antoniou 
131b53a2340SPantelis Antoniou 	/* figure out if a device should be created or destroyed */
132b53a2340SPantelis Antoniou 	switch (action) {
133b53a2340SPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
134b53a2340SPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
135f5242e5aSGrant Likely 		prop = of_find_property(pr->dn, "status", NULL);
136b53a2340SPantelis Antoniou 		break;
137b53a2340SPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
138b53a2340SPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
139b53a2340SPantelis Antoniou 		prop = pr->prop;
140b53a2340SPantelis Antoniou 		break;
141b53a2340SPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
142b53a2340SPantelis Antoniou 		prop = pr->prop;
143b53a2340SPantelis Antoniou 		old_prop = pr->old_prop;
144b53a2340SPantelis Antoniou 		break;
145b53a2340SPantelis Antoniou 	default:
146b53a2340SPantelis Antoniou 		return OF_RECONFIG_NO_CHANGE;
147b53a2340SPantelis Antoniou 	}
148b53a2340SPantelis Antoniou 
149b53a2340SPantelis Antoniou 	is_status = 0;
150b53a2340SPantelis Antoniou 	status_state = -1;
151b53a2340SPantelis Antoniou 	old_status_state = -1;
152b53a2340SPantelis Antoniou 	prev_state = -1;
153b53a2340SPantelis Antoniou 	new_state = -1;
154b53a2340SPantelis Antoniou 
155b53a2340SPantelis Antoniou 	if (prop && !strcmp(prop->name, "status")) {
156b53a2340SPantelis Antoniou 		is_status = 1;
157b53a2340SPantelis Antoniou 		status_state = !strcmp(prop->value, "okay") ||
158b53a2340SPantelis Antoniou 			       !strcmp(prop->value, "ok");
159b53a2340SPantelis Antoniou 		if (old_prop)
160b53a2340SPantelis Antoniou 			old_status_state = !strcmp(old_prop->value, "okay") ||
161b53a2340SPantelis Antoniou 					   !strcmp(old_prop->value, "ok");
162b53a2340SPantelis Antoniou 	}
163b53a2340SPantelis Antoniou 
164b53a2340SPantelis Antoniou 	switch (action) {
165b53a2340SPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
166b53a2340SPantelis Antoniou 		prev_state = 0;
167b53a2340SPantelis Antoniou 		/* -1 & 0 status either missing or okay */
168b53a2340SPantelis Antoniou 		new_state = status_state != 0;
169b53a2340SPantelis Antoniou 		break;
170b53a2340SPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
171b53a2340SPantelis Antoniou 		/* -1 & 0 status either missing or okay */
172b53a2340SPantelis Antoniou 		prev_state = status_state != 0;
173b53a2340SPantelis Antoniou 		new_state = 0;
174b53a2340SPantelis Antoniou 		break;
175b53a2340SPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
176b53a2340SPantelis Antoniou 		if (is_status) {
177b53a2340SPantelis Antoniou 			/* no status property -> enabled (legacy) */
178b53a2340SPantelis Antoniou 			prev_state = 1;
179b53a2340SPantelis Antoniou 			new_state = status_state;
180b53a2340SPantelis Antoniou 		}
181b53a2340SPantelis Antoniou 		break;
182b53a2340SPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
183b53a2340SPantelis Antoniou 		if (is_status) {
184b53a2340SPantelis Antoniou 			prev_state = status_state;
185b53a2340SPantelis Antoniou 			/* no status property -> enabled (legacy) */
186b53a2340SPantelis Antoniou 			new_state = 1;
187b53a2340SPantelis Antoniou 		}
188b53a2340SPantelis Antoniou 		break;
189b53a2340SPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
190b53a2340SPantelis Antoniou 		if (is_status) {
191b53a2340SPantelis Antoniou 			prev_state = old_status_state != 0;
192b53a2340SPantelis Antoniou 			new_state = status_state != 0;
193b53a2340SPantelis Antoniou 		}
194b53a2340SPantelis Antoniou 		break;
195b53a2340SPantelis Antoniou 	}
196b53a2340SPantelis Antoniou 
197b53a2340SPantelis Antoniou 	if (prev_state == new_state)
198b53a2340SPantelis Antoniou 		return OF_RECONFIG_NO_CHANGE;
199b53a2340SPantelis Antoniou 
200b53a2340SPantelis Antoniou 	return new_state ? OF_RECONFIG_CHANGE_ADD : OF_RECONFIG_CHANGE_REMOVE;
201b53a2340SPantelis Antoniou }
202b53a2340SPantelis Antoniou EXPORT_SYMBOL_GPL(of_reconfig_get_state_change);
203b53a2340SPantelis Antoniou 
2046afc0dc3SGrant Likely int of_property_notify(int action, struct device_node *np,
205259092a3SGrant Likely 		       struct property *prop, struct property *oldprop)
2066afc0dc3SGrant Likely {
207f5242e5aSGrant Likely 	struct of_reconfig_data pr;
2086afc0dc3SGrant Likely 
2096afc0dc3SGrant Likely 	/* only call notifiers if the node is attached */
2106afc0dc3SGrant Likely 	if (!of_node_is_attached(np))
2116afc0dc3SGrant Likely 		return 0;
2126afc0dc3SGrant Likely 
2136afc0dc3SGrant Likely 	pr.dn = np;
2146afc0dc3SGrant Likely 	pr.prop = prop;
215259092a3SGrant Likely 	pr.old_prop = oldprop;
2166afc0dc3SGrant Likely 	return of_reconfig_notify(action, &pr);
2176afc0dc3SGrant Likely }
2186afc0dc3SGrant Likely 
21924996951SFrank Rowand static void __of_attach_node(struct device_node *np)
220d8c50088SPantelis Antoniou {
221a25095d4SGrant Likely 	const __be32 *phandle;
222a25095d4SGrant Likely 	int sz;
223a25095d4SGrant Likely 
224a25095d4SGrant Likely 	np->name = __of_get_property(np, "name", NULL) ? : "<NULL>";
225a25095d4SGrant Likely 	np->type = __of_get_property(np, "device_type", NULL) ? : "<NULL>";
226a25095d4SGrant Likely 
227a25095d4SGrant Likely 	phandle = __of_get_property(np, "phandle", &sz);
228a25095d4SGrant Likely 	if (!phandle)
229a25095d4SGrant Likely 		phandle = __of_get_property(np, "linux,phandle", &sz);
230f76502aaSGeert Uytterhoeven 	if (IS_ENABLED(CONFIG_PPC_PSERIES) && !phandle)
231a25095d4SGrant Likely 		phandle = __of_get_property(np, "ibm,phandle", &sz);
232a25095d4SGrant Likely 	np->phandle = (phandle && (sz >= 4)) ? be32_to_cpup(phandle) : 0;
233a25095d4SGrant Likely 
2346162dbe4SGrant Likely 	np->child = NULL;
235d8c50088SPantelis Antoniou 	np->sibling = np->parent->child;
236d8c50088SPantelis Antoniou 	np->parent->child = np;
237d8c50088SPantelis Antoniou 	of_node_clear_flag(np, OF_DETACHED);
238d8c50088SPantelis Antoniou }
239d8c50088SPantelis Antoniou 
2406afc0dc3SGrant Likely /**
2416afc0dc3SGrant Likely  * of_attach_node() - Plug a device node into the tree and global list.
2426afc0dc3SGrant Likely  */
2436afc0dc3SGrant Likely int of_attach_node(struct device_node *np)
2446afc0dc3SGrant Likely {
245f5242e5aSGrant Likely 	struct of_reconfig_data rd;
2466afc0dc3SGrant Likely 	unsigned long flags;
2476afc0dc3SGrant Likely 
248f5242e5aSGrant Likely 	memset(&rd, 0, sizeof(rd));
249f5242e5aSGrant Likely 	rd.dn = np;
250f5242e5aSGrant Likely 
2518a2b22a2SGrant Likely 	mutex_lock(&of_mutex);
2526afc0dc3SGrant Likely 	raw_spin_lock_irqsave(&devtree_lock, flags);
253d8c50088SPantelis Antoniou 	__of_attach_node(np);
2546afc0dc3SGrant Likely 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
2556afc0dc3SGrant Likely 
2568a2b22a2SGrant Likely 	__of_attach_node_sysfs(np);
2578a2b22a2SGrant Likely 	mutex_unlock(&of_mutex);
258259092a3SGrant Likely 
259f5242e5aSGrant Likely 	of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, &rd);
260259092a3SGrant Likely 
2616afc0dc3SGrant Likely 	return 0;
2626afc0dc3SGrant Likely }
2636afc0dc3SGrant Likely 
264d8c50088SPantelis Antoniou void __of_detach_node(struct device_node *np)
2656afc0dc3SGrant Likely {
2666afc0dc3SGrant Likely 	struct device_node *parent;
2676afc0dc3SGrant Likely 
268d8c50088SPantelis Antoniou 	if (WARN_ON(of_node_check_flag(np, OF_DETACHED)))
269d8c50088SPantelis Antoniou 		return;
2706afc0dc3SGrant Likely 
2716afc0dc3SGrant Likely 	parent = np->parent;
272d8c50088SPantelis Antoniou 	if (WARN_ON(!parent))
273d8c50088SPantelis Antoniou 		return;
2746afc0dc3SGrant Likely 
2756afc0dc3SGrant Likely 	if (parent->child == np)
2766afc0dc3SGrant Likely 		parent->child = np->sibling;
2776afc0dc3SGrant Likely 	else {
2786afc0dc3SGrant Likely 		struct device_node *prevsib;
2796afc0dc3SGrant Likely 		for (prevsib = np->parent->child;
2806afc0dc3SGrant Likely 		     prevsib->sibling != np;
2816afc0dc3SGrant Likely 		     prevsib = prevsib->sibling)
2826afc0dc3SGrant Likely 			;
2836afc0dc3SGrant Likely 		prevsib->sibling = np->sibling;
2846afc0dc3SGrant Likely 	}
2856afc0dc3SGrant Likely 
2866afc0dc3SGrant Likely 	of_node_set_flag(np, OF_DETACHED);
287d8c50088SPantelis Antoniou }
288d8c50088SPantelis Antoniou 
289d8c50088SPantelis Antoniou /**
290d8c50088SPantelis Antoniou  * of_detach_node() - "Unplug" a node from the device tree.
291d8c50088SPantelis Antoniou  *
292d8c50088SPantelis Antoniou  * The caller must hold a reference to the node.  The memory associated with
293d8c50088SPantelis Antoniou  * the node is not freed until its refcount goes to zero.
294d8c50088SPantelis Antoniou  */
295d8c50088SPantelis Antoniou int of_detach_node(struct device_node *np)
296d8c50088SPantelis Antoniou {
297f5242e5aSGrant Likely 	struct of_reconfig_data rd;
298d8c50088SPantelis Antoniou 	unsigned long flags;
299d8c50088SPantelis Antoniou 	int rc = 0;
300d8c50088SPantelis Antoniou 
301f5242e5aSGrant Likely 	memset(&rd, 0, sizeof(rd));
302f5242e5aSGrant Likely 	rd.dn = np;
303f5242e5aSGrant Likely 
3048a2b22a2SGrant Likely 	mutex_lock(&of_mutex);
305d8c50088SPantelis Antoniou 	raw_spin_lock_irqsave(&devtree_lock, flags);
306d8c50088SPantelis Antoniou 	__of_detach_node(np);
3076afc0dc3SGrant Likely 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
3086afc0dc3SGrant Likely 
3098a2b22a2SGrant Likely 	__of_detach_node_sysfs(np);
3108a2b22a2SGrant Likely 	mutex_unlock(&of_mutex);
311259092a3SGrant Likely 
312f5242e5aSGrant Likely 	of_reconfig_notify(OF_RECONFIG_DETACH_NODE, &rd);
313259092a3SGrant Likely 
3146afc0dc3SGrant Likely 	return rc;
3156afc0dc3SGrant Likely }
316bb91f923SGavin Shan EXPORT_SYMBOL_GPL(of_detach_node);
3176afc0dc3SGrant Likely 
3186afc0dc3SGrant Likely /**
3196afc0dc3SGrant Likely  * of_node_release() - release a dynamically allocated node
3206afc0dc3SGrant Likely  * @kref: kref element of the node to be released
3216afc0dc3SGrant Likely  *
3226afc0dc3SGrant Likely  * In of_node_put() this function is passed to kref_put() as the destructor.
3236afc0dc3SGrant Likely  */
3246afc0dc3SGrant Likely void of_node_release(struct kobject *kobj)
3256afc0dc3SGrant Likely {
3266afc0dc3SGrant Likely 	struct device_node *node = kobj_to_device_node(kobj);
3276afc0dc3SGrant Likely 	struct property *prop = node->properties;
3286afc0dc3SGrant Likely 
3296afc0dc3SGrant Likely 	/* We should never be releasing nodes that haven't been detached. */
3306afc0dc3SGrant Likely 	if (!of_node_check_flag(node, OF_DETACHED)) {
331*0d638a07SRob Herring 		pr_err("ERROR: Bad of_node_put() on %pOF\n", node);
3326afc0dc3SGrant Likely 		dump_stack();
3336afc0dc3SGrant Likely 		return;
3346afc0dc3SGrant Likely 	}
3356afc0dc3SGrant Likely 	if (!of_node_check_flag(node, OF_DYNAMIC))
3366afc0dc3SGrant Likely 		return;
3376afc0dc3SGrant Likely 
3386afc0dc3SGrant Likely 	while (prop) {
3396afc0dc3SGrant Likely 		struct property *next = prop->next;
3406afc0dc3SGrant Likely 		kfree(prop->name);
3416afc0dc3SGrant Likely 		kfree(prop->value);
3426afc0dc3SGrant Likely 		kfree(prop);
3436afc0dc3SGrant Likely 		prop = next;
3446afc0dc3SGrant Likely 
3456afc0dc3SGrant Likely 		if (!prop) {
3466afc0dc3SGrant Likely 			prop = node->deadprops;
3476afc0dc3SGrant Likely 			node->deadprops = NULL;
3486afc0dc3SGrant Likely 		}
3496afc0dc3SGrant Likely 	}
3506afc0dc3SGrant Likely 	kfree(node->full_name);
3516afc0dc3SGrant Likely 	kfree(node->data);
3526afc0dc3SGrant Likely 	kfree(node);
3536afc0dc3SGrant Likely }
35469843396SPantelis Antoniou 
35569843396SPantelis Antoniou /**
35669843396SPantelis Antoniou  * __of_prop_dup - Copy a property dynamically.
35769843396SPantelis Antoniou  * @prop:	Property to copy
35869843396SPantelis Antoniou  * @allocflags:	Allocation flags (typically pass GFP_KERNEL)
35969843396SPantelis Antoniou  *
36069843396SPantelis Antoniou  * Copy a property by dynamically allocating the memory of both the
36127b3383aSGeert Uytterhoeven  * property structure and the property name & contents. The property's
36269843396SPantelis Antoniou  * flags have the OF_DYNAMIC bit set so that we can differentiate between
36369843396SPantelis Antoniou  * dynamically allocated properties and not.
36469843396SPantelis Antoniou  * Returns the newly allocated property or NULL on out of memory error.
36569843396SPantelis Antoniou  */
36669843396SPantelis Antoniou struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags)
36769843396SPantelis Antoniou {
36869843396SPantelis Antoniou 	struct property *new;
36969843396SPantelis Antoniou 
37069843396SPantelis Antoniou 	new = kzalloc(sizeof(*new), allocflags);
37169843396SPantelis Antoniou 	if (!new)
37269843396SPantelis Antoniou 		return NULL;
37369843396SPantelis Antoniou 
37469843396SPantelis Antoniou 	/*
37569843396SPantelis Antoniou 	 * NOTE: There is no check for zero length value.
376b6ae5dc5SGrant Likely 	 * In case of a boolean property, this will allocate a value
37769843396SPantelis Antoniou 	 * of zero bytes. We do this to work around the use
37869843396SPantelis Antoniou 	 * of of_get_property() calls on boolean values.
37969843396SPantelis Antoniou 	 */
38069843396SPantelis Antoniou 	new->name = kstrdup(prop->name, allocflags);
38169843396SPantelis Antoniou 	new->value = kmemdup(prop->value, prop->length, allocflags);
38269843396SPantelis Antoniou 	new->length = prop->length;
38369843396SPantelis Antoniou 	if (!new->name || !new->value)
38469843396SPantelis Antoniou 		goto err_free;
38569843396SPantelis Antoniou 
38669843396SPantelis Antoniou 	/* mark the property as dynamic */
38769843396SPantelis Antoniou 	of_property_set_flag(new, OF_DYNAMIC);
38869843396SPantelis Antoniou 
38969843396SPantelis Antoniou 	return new;
39069843396SPantelis Antoniou 
39169843396SPantelis Antoniou  err_free:
39269843396SPantelis Antoniou 	kfree(new->name);
39369843396SPantelis Antoniou 	kfree(new->value);
39469843396SPantelis Antoniou 	kfree(new);
39569843396SPantelis Antoniou 	return NULL;
39669843396SPantelis Antoniou }
39769843396SPantelis Antoniou 
39869843396SPantelis Antoniou /**
399e5179581SGrant Likely  * __of_node_dup() - Duplicate or create an empty device node dynamically.
400e5179581SGrant Likely  * @fmt: Format string (plus vargs) for new full name of the device node
40169843396SPantelis Antoniou  *
402e5179581SGrant Likely  * Create an device tree node, either by duplicating an empty node or by allocating
403e5179581SGrant Likely  * an empty one suitable for further modification.  The node data are
404e5179581SGrant Likely  * dynamically allocated and all the node flags have the OF_DYNAMIC &
405e5179581SGrant Likely  * OF_DETACHED bits set. Returns the newly allocated node or NULL on out of
406e5179581SGrant Likely  * memory error.
40769843396SPantelis Antoniou  */
408e5179581SGrant Likely struct device_node *__of_node_dup(const struct device_node *np, const char *fmt, ...)
40969843396SPantelis Antoniou {
410ef8bbd73SGrant Likely 	va_list vargs;
41169843396SPantelis Antoniou 	struct device_node *node;
41269843396SPantelis Antoniou 
413ef8bbd73SGrant Likely 	node = kzalloc(sizeof(*node), GFP_KERNEL);
41469843396SPantelis Antoniou 	if (!node)
41569843396SPantelis Antoniou 		return NULL;
416ef8bbd73SGrant Likely 	va_start(vargs, fmt);
417ef8bbd73SGrant Likely 	node->full_name = kvasprintf(GFP_KERNEL, fmt, vargs);
418ef8bbd73SGrant Likely 	va_end(vargs);
419e5179581SGrant Likely 	if (!node->full_name) {
420e5179581SGrant Likely 		kfree(node);
421e5179581SGrant Likely 		return NULL;
422e5179581SGrant Likely 	}
42369843396SPantelis Antoniou 
424ef8bbd73SGrant Likely 	of_node_set_flag(node, OF_DYNAMIC);
425ef8bbd73SGrant Likely 	of_node_set_flag(node, OF_DETACHED);
42669843396SPantelis Antoniou 	of_node_init(node);
42769843396SPantelis Antoniou 
428e5179581SGrant Likely 	/* Iterate over and duplicate all properties */
429e5179581SGrant Likely 	if (np) {
430e5179581SGrant Likely 		struct property *pp, *new_pp;
431e5179581SGrant Likely 		for_each_property_of_node(np, pp) {
432e5179581SGrant Likely 			new_pp = __of_prop_dup(pp, GFP_KERNEL);
433e5179581SGrant Likely 			if (!new_pp)
434e5179581SGrant Likely 				goto err_prop;
435e5179581SGrant Likely 			if (__of_add_property(node, new_pp)) {
436e5179581SGrant Likely 				kfree(new_pp->name);
437e5179581SGrant Likely 				kfree(new_pp->value);
438e5179581SGrant Likely 				kfree(new_pp);
439e5179581SGrant Likely 				goto err_prop;
440e5179581SGrant Likely 			}
441e5179581SGrant Likely 		}
442e5179581SGrant Likely 	}
44369843396SPantelis Antoniou 	return node;
44469843396SPantelis Antoniou 
445e5179581SGrant Likely  err_prop:
446e5179581SGrant Likely 	of_node_put(node); /* Frees the node and properties */
44769843396SPantelis Antoniou 	return NULL;
44869843396SPantelis Antoniou }
449201c910bSPantelis Antoniou 
450201c910bSPantelis Antoniou static void __of_changeset_entry_destroy(struct of_changeset_entry *ce)
451201c910bSPantelis Antoniou {
452201c910bSPantelis Antoniou 	of_node_put(ce->np);
453201c910bSPantelis Antoniou 	list_del(&ce->node);
454201c910bSPantelis Antoniou 	kfree(ce);
455201c910bSPantelis Antoniou }
456201c910bSPantelis Antoniou 
457201c910bSPantelis Antoniou #ifdef DEBUG
458201c910bSPantelis Antoniou static void __of_changeset_entry_dump(struct of_changeset_entry *ce)
459201c910bSPantelis Antoniou {
460201c910bSPantelis Antoniou 	switch (ce->action) {
461201c910bSPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
462201c910bSPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
463201c910bSPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
464*0d638a07SRob Herring 		pr_debug("cset<%p> %-15s %pOF/%s\n", ce, action_names[ce->action],
465*0d638a07SRob Herring 			ce->np, ce->prop->name);
466201c910bSPantelis Antoniou 		break;
467201c910bSPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
468201c910bSPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
469*0d638a07SRob Herring 		pr_debug("cset<%p> %-15s %pOF\n", ce, action_names[ce->action],
470*0d638a07SRob Herring 			ce->np);
471201c910bSPantelis Antoniou 		break;
472201c910bSPantelis Antoniou 	}
473201c910bSPantelis Antoniou }
474201c910bSPantelis Antoniou #else
475201c910bSPantelis Antoniou static inline void __of_changeset_entry_dump(struct of_changeset_entry *ce)
476201c910bSPantelis Antoniou {
477201c910bSPantelis Antoniou 	/* empty */
478201c910bSPantelis Antoniou }
479201c910bSPantelis Antoniou #endif
480201c910bSPantelis Antoniou 
481201c910bSPantelis Antoniou static void __of_changeset_entry_invert(struct of_changeset_entry *ce,
482201c910bSPantelis Antoniou 					  struct of_changeset_entry *rce)
483201c910bSPantelis Antoniou {
484201c910bSPantelis Antoniou 	memcpy(rce, ce, sizeof(*rce));
485201c910bSPantelis Antoniou 
486201c910bSPantelis Antoniou 	switch (ce->action) {
487201c910bSPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
488201c910bSPantelis Antoniou 		rce->action = OF_RECONFIG_DETACH_NODE;
489201c910bSPantelis Antoniou 		break;
490201c910bSPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
491201c910bSPantelis Antoniou 		rce->action = OF_RECONFIG_ATTACH_NODE;
492201c910bSPantelis Antoniou 		break;
493201c910bSPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
494201c910bSPantelis Antoniou 		rce->action = OF_RECONFIG_REMOVE_PROPERTY;
495201c910bSPantelis Antoniou 		break;
496201c910bSPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
497201c910bSPantelis Antoniou 		rce->action = OF_RECONFIG_ADD_PROPERTY;
498201c910bSPantelis Antoniou 		break;
499201c910bSPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
500201c910bSPantelis Antoniou 		rce->old_prop = ce->prop;
501201c910bSPantelis Antoniou 		rce->prop = ce->old_prop;
502b9c43856SPantelis Antoniou 		/* update was used but original property did not exist */
503b9c43856SPantelis Antoniou 		if (!rce->prop) {
504b9c43856SPantelis Antoniou 			rce->action = OF_RECONFIG_REMOVE_PROPERTY;
505b9c43856SPantelis Antoniou 			rce->prop = ce->prop;
506b9c43856SPantelis Antoniou 		}
507201c910bSPantelis Antoniou 		break;
508201c910bSPantelis Antoniou 	}
509201c910bSPantelis Antoniou }
510201c910bSPantelis Antoniou 
511201c910bSPantelis Antoniou static void __of_changeset_entry_notify(struct of_changeset_entry *ce, bool revert)
512201c910bSPantelis Antoniou {
513f5242e5aSGrant Likely 	struct of_reconfig_data rd;
514201c910bSPantelis Antoniou 	struct of_changeset_entry ce_inverted;
515201c910bSPantelis Antoniou 	int ret;
516201c910bSPantelis Antoniou 
517201c910bSPantelis Antoniou 	if (revert) {
518201c910bSPantelis Antoniou 		__of_changeset_entry_invert(ce, &ce_inverted);
519201c910bSPantelis Antoniou 		ce = &ce_inverted;
520201c910bSPantelis Antoniou 	}
521201c910bSPantelis Antoniou 
522201c910bSPantelis Antoniou 	switch (ce->action) {
523201c910bSPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
524201c910bSPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
525f5242e5aSGrant Likely 		memset(&rd, 0, sizeof(rd));
526f5242e5aSGrant Likely 		rd.dn = ce->np;
527f5242e5aSGrant Likely 		ret = of_reconfig_notify(ce->action, &rd);
528201c910bSPantelis Antoniou 		break;
529201c910bSPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
530201c910bSPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
531201c910bSPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
532201c910bSPantelis Antoniou 		ret = of_property_notify(ce->action, ce->np, ce->prop, ce->old_prop);
533201c910bSPantelis Antoniou 		break;
534201c910bSPantelis Antoniou 	default:
535606ad42aSRob Herring 		pr_err("invalid devicetree changeset action: %i\n",
536201c910bSPantelis Antoniou 			(int)ce->action);
537201c910bSPantelis Antoniou 		return;
538201c910bSPantelis Antoniou 	}
539201c910bSPantelis Antoniou 
540201c910bSPantelis Antoniou 	if (ret)
541*0d638a07SRob Herring 		pr_err("changeset notifier error @%pOF\n", ce->np);
542201c910bSPantelis Antoniou }
543201c910bSPantelis Antoniou 
544201c910bSPantelis Antoniou static int __of_changeset_entry_apply(struct of_changeset_entry *ce)
545201c910bSPantelis Antoniou {
546201c910bSPantelis Antoniou 	struct property *old_prop, **propp;
547201c910bSPantelis Antoniou 	unsigned long flags;
548201c910bSPantelis Antoniou 	int ret = 0;
549201c910bSPantelis Antoniou 
550201c910bSPantelis Antoniou 	__of_changeset_entry_dump(ce);
551201c910bSPantelis Antoniou 
552201c910bSPantelis Antoniou 	raw_spin_lock_irqsave(&devtree_lock, flags);
553201c910bSPantelis Antoniou 	switch (ce->action) {
554201c910bSPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
555201c910bSPantelis Antoniou 		__of_attach_node(ce->np);
556201c910bSPantelis Antoniou 		break;
557201c910bSPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
558201c910bSPantelis Antoniou 		__of_detach_node(ce->np);
559201c910bSPantelis Antoniou 		break;
560201c910bSPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
561201c910bSPantelis Antoniou 		/* If the property is in deadprops then it must be removed */
562201c910bSPantelis Antoniou 		for (propp = &ce->np->deadprops; *propp; propp = &(*propp)->next) {
563201c910bSPantelis Antoniou 			if (*propp == ce->prop) {
564201c910bSPantelis Antoniou 				*propp = ce->prop->next;
565201c910bSPantelis Antoniou 				ce->prop->next = NULL;
566201c910bSPantelis Antoniou 				break;
567201c910bSPantelis Antoniou 			}
568201c910bSPantelis Antoniou 		}
569201c910bSPantelis Antoniou 
570201c910bSPantelis Antoniou 		ret = __of_add_property(ce->np, ce->prop);
571201c910bSPantelis Antoniou 		if (ret) {
572*0d638a07SRob Herring 			pr_err("changeset: add_property failed @%pOF/%s\n",
573*0d638a07SRob Herring 				ce->np,
574201c910bSPantelis Antoniou 				ce->prop->name);
575201c910bSPantelis Antoniou 			break;
576201c910bSPantelis Antoniou 		}
577201c910bSPantelis Antoniou 		break;
578201c910bSPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
579201c910bSPantelis Antoniou 		ret = __of_remove_property(ce->np, ce->prop);
580201c910bSPantelis Antoniou 		if (ret) {
581*0d638a07SRob Herring 			pr_err("changeset: remove_property failed @%pOF/%s\n",
582*0d638a07SRob Herring 				ce->np,
583201c910bSPantelis Antoniou 				ce->prop->name);
584201c910bSPantelis Antoniou 			break;
585201c910bSPantelis Antoniou 		}
586201c910bSPantelis Antoniou 		break;
587201c910bSPantelis Antoniou 
588201c910bSPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
589201c910bSPantelis Antoniou 		/* If the property is in deadprops then it must be removed */
590201c910bSPantelis Antoniou 		for (propp = &ce->np->deadprops; *propp; propp = &(*propp)->next) {
591201c910bSPantelis Antoniou 			if (*propp == ce->prop) {
592201c910bSPantelis Antoniou 				*propp = ce->prop->next;
593201c910bSPantelis Antoniou 				ce->prop->next = NULL;
594201c910bSPantelis Antoniou 				break;
595201c910bSPantelis Antoniou 			}
596201c910bSPantelis Antoniou 		}
597201c910bSPantelis Antoniou 
598201c910bSPantelis Antoniou 		ret = __of_update_property(ce->np, ce->prop, &old_prop);
599201c910bSPantelis Antoniou 		if (ret) {
600*0d638a07SRob Herring 			pr_err("changeset: update_property failed @%pOF/%s\n",
601*0d638a07SRob Herring 				ce->np,
602201c910bSPantelis Antoniou 				ce->prop->name);
603201c910bSPantelis Antoniou 			break;
604201c910bSPantelis Antoniou 		}
605201c910bSPantelis Antoniou 		break;
606201c910bSPantelis Antoniou 	default:
607201c910bSPantelis Antoniou 		ret = -EINVAL;
608201c910bSPantelis Antoniou 	}
609201c910bSPantelis Antoniou 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
610201c910bSPantelis Antoniou 
611201c910bSPantelis Antoniou 	if (ret)
612201c910bSPantelis Antoniou 		return ret;
613201c910bSPantelis Antoniou 
614201c910bSPantelis Antoniou 	switch (ce->action) {
615201c910bSPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
616201c910bSPantelis Antoniou 		__of_attach_node_sysfs(ce->np);
617201c910bSPantelis Antoniou 		break;
618201c910bSPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
619201c910bSPantelis Antoniou 		__of_detach_node_sysfs(ce->np);
620201c910bSPantelis Antoniou 		break;
621201c910bSPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
622201c910bSPantelis Antoniou 		/* ignore duplicate names */
623201c910bSPantelis Antoniou 		__of_add_property_sysfs(ce->np, ce->prop);
624201c910bSPantelis Antoniou 		break;
625201c910bSPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
626201c910bSPantelis Antoniou 		__of_remove_property_sysfs(ce->np, ce->prop);
627201c910bSPantelis Antoniou 		break;
628201c910bSPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
629201c910bSPantelis Antoniou 		__of_update_property_sysfs(ce->np, ce->prop, ce->old_prop);
630201c910bSPantelis Antoniou 		break;
631201c910bSPantelis Antoniou 	}
632201c910bSPantelis Antoniou 
633201c910bSPantelis Antoniou 	return 0;
634201c910bSPantelis Antoniou }
635201c910bSPantelis Antoniou 
636201c910bSPantelis Antoniou static inline int __of_changeset_entry_revert(struct of_changeset_entry *ce)
637201c910bSPantelis Antoniou {
638201c910bSPantelis Antoniou 	struct of_changeset_entry ce_inverted;
639201c910bSPantelis Antoniou 
640201c910bSPantelis Antoniou 	__of_changeset_entry_invert(ce, &ce_inverted);
641201c910bSPantelis Antoniou 	return __of_changeset_entry_apply(&ce_inverted);
642201c910bSPantelis Antoniou }
643201c910bSPantelis Antoniou 
644201c910bSPantelis Antoniou /**
645201c910bSPantelis Antoniou  * of_changeset_init - Initialize a changeset for use
646201c910bSPantelis Antoniou  *
647201c910bSPantelis Antoniou  * @ocs:	changeset pointer
648201c910bSPantelis Antoniou  *
649201c910bSPantelis Antoniou  * Initialize a changeset structure
650201c910bSPantelis Antoniou  */
651201c910bSPantelis Antoniou void of_changeset_init(struct of_changeset *ocs)
652201c910bSPantelis Antoniou {
653201c910bSPantelis Antoniou 	memset(ocs, 0, sizeof(*ocs));
654201c910bSPantelis Antoniou 	INIT_LIST_HEAD(&ocs->entries);
655201c910bSPantelis Antoniou }
65618322377SGavin Shan EXPORT_SYMBOL_GPL(of_changeset_init);
657201c910bSPantelis Antoniou 
658201c910bSPantelis Antoniou /**
659201c910bSPantelis Antoniou  * of_changeset_destroy - Destroy a changeset
660201c910bSPantelis Antoniou  *
661201c910bSPantelis Antoniou  * @ocs:	changeset pointer
662201c910bSPantelis Antoniou  *
663201c910bSPantelis Antoniou  * Destroys a changeset. Note that if a changeset is applied,
664201c910bSPantelis Antoniou  * its changes to the tree cannot be reverted.
665201c910bSPantelis Antoniou  */
666201c910bSPantelis Antoniou void of_changeset_destroy(struct of_changeset *ocs)
667201c910bSPantelis Antoniou {
668201c910bSPantelis Antoniou 	struct of_changeset_entry *ce, *cen;
669201c910bSPantelis Antoniou 
670201c910bSPantelis Antoniou 	list_for_each_entry_safe_reverse(ce, cen, &ocs->entries, node)
671201c910bSPantelis Antoniou 		__of_changeset_entry_destroy(ce);
672201c910bSPantelis Antoniou }
67318322377SGavin Shan EXPORT_SYMBOL_GPL(of_changeset_destroy);
674201c910bSPantelis Antoniou 
67518322377SGavin Shan int __of_changeset_apply(struct of_changeset *ocs)
676201c910bSPantelis Antoniou {
677201c910bSPantelis Antoniou 	struct of_changeset_entry *ce;
678201c910bSPantelis Antoniou 	int ret;
679201c910bSPantelis Antoniou 
680201c910bSPantelis Antoniou 	/* perform the rest of the work */
681606ad42aSRob Herring 	pr_debug("changeset: applying...\n");
682201c910bSPantelis Antoniou 	list_for_each_entry(ce, &ocs->entries, node) {
683201c910bSPantelis Antoniou 		ret = __of_changeset_entry_apply(ce);
684201c910bSPantelis Antoniou 		if (ret) {
685606ad42aSRob Herring 			pr_err("Error applying changeset (%d)\n", ret);
686201c910bSPantelis Antoniou 			list_for_each_entry_continue_reverse(ce, &ocs->entries, node)
687201c910bSPantelis Antoniou 				__of_changeset_entry_revert(ce);
688201c910bSPantelis Antoniou 			return ret;
689201c910bSPantelis Antoniou 		}
690201c910bSPantelis Antoniou 	}
691606ad42aSRob Herring 	pr_debug("changeset: applied, emitting notifiers.\n");
692201c910bSPantelis Antoniou 
693201c910bSPantelis Antoniou 	/* drop the global lock while emitting notifiers */
694201c910bSPantelis Antoniou 	mutex_unlock(&of_mutex);
695201c910bSPantelis Antoniou 	list_for_each_entry(ce, &ocs->entries, node)
696201c910bSPantelis Antoniou 		__of_changeset_entry_notify(ce, 0);
697201c910bSPantelis Antoniou 	mutex_lock(&of_mutex);
698606ad42aSRob Herring 	pr_debug("changeset: notifiers sent.\n");
699201c910bSPantelis Antoniou 
700201c910bSPantelis Antoniou 	return 0;
701201c910bSPantelis Antoniou }
702201c910bSPantelis Antoniou 
703201c910bSPantelis Antoniou /**
70418322377SGavin Shan  * of_changeset_apply - Applies a changeset
705201c910bSPantelis Antoniou  *
706201c910bSPantelis Antoniou  * @ocs:	changeset pointer
707201c910bSPantelis Antoniou  *
70818322377SGavin Shan  * Applies a changeset to the live tree.
70918322377SGavin Shan  * Any side-effects of live tree state changes are applied here on
71018322377SGavin Shan  * success, like creation/destruction of devices and side-effects
71118322377SGavin Shan  * like creation of sysfs properties and directories.
712201c910bSPantelis Antoniou  * Returns 0 on success, a negative error value in case of an error.
71318322377SGavin Shan  * On error the partially applied effects are reverted.
714201c910bSPantelis Antoniou  */
71518322377SGavin Shan int of_changeset_apply(struct of_changeset *ocs)
71618322377SGavin Shan {
71718322377SGavin Shan 	int ret;
71818322377SGavin Shan 
71918322377SGavin Shan 	mutex_lock(&of_mutex);
72018322377SGavin Shan 	ret = __of_changeset_apply(ocs);
72118322377SGavin Shan 	mutex_unlock(&of_mutex);
72218322377SGavin Shan 
72318322377SGavin Shan 	return ret;
72418322377SGavin Shan }
72518322377SGavin Shan EXPORT_SYMBOL_GPL(of_changeset_apply);
72618322377SGavin Shan 
72718322377SGavin Shan int __of_changeset_revert(struct of_changeset *ocs)
728201c910bSPantelis Antoniou {
729201c910bSPantelis Antoniou 	struct of_changeset_entry *ce;
730201c910bSPantelis Antoniou 	int ret;
731201c910bSPantelis Antoniou 
732606ad42aSRob Herring 	pr_debug("changeset: reverting...\n");
733201c910bSPantelis Antoniou 	list_for_each_entry_reverse(ce, &ocs->entries, node) {
734201c910bSPantelis Antoniou 		ret = __of_changeset_entry_revert(ce);
735201c910bSPantelis Antoniou 		if (ret) {
736606ad42aSRob Herring 			pr_err("Error reverting changeset (%d)\n", ret);
737201c910bSPantelis Antoniou 			list_for_each_entry_continue(ce, &ocs->entries, node)
738201c910bSPantelis Antoniou 				__of_changeset_entry_apply(ce);
739201c910bSPantelis Antoniou 			return ret;
740201c910bSPantelis Antoniou 		}
741201c910bSPantelis Antoniou 	}
742606ad42aSRob Herring 	pr_debug("changeset: reverted, emitting notifiers.\n");
743201c910bSPantelis Antoniou 
744201c910bSPantelis Antoniou 	/* drop the global lock while emitting notifiers */
745201c910bSPantelis Antoniou 	mutex_unlock(&of_mutex);
746201c910bSPantelis Antoniou 	list_for_each_entry_reverse(ce, &ocs->entries, node)
747201c910bSPantelis Antoniou 		__of_changeset_entry_notify(ce, 1);
748201c910bSPantelis Antoniou 	mutex_lock(&of_mutex);
749606ad42aSRob Herring 	pr_debug("changeset: notifiers sent.\n");
750201c910bSPantelis Antoniou 
751201c910bSPantelis Antoniou 	return 0;
752201c910bSPantelis Antoniou }
753201c910bSPantelis Antoniou 
754201c910bSPantelis Antoniou /**
75518322377SGavin Shan  * of_changeset_revert - Reverts an applied changeset
75618322377SGavin Shan  *
75718322377SGavin Shan  * @ocs:	changeset pointer
75818322377SGavin Shan  *
75918322377SGavin Shan  * Reverts a changeset returning the state of the tree to what it
76018322377SGavin Shan  * was before the application.
76118322377SGavin Shan  * Any side-effects like creation/destruction of devices and
76218322377SGavin Shan  * removal of sysfs properties and directories are applied.
76318322377SGavin Shan  * Returns 0 on success, a negative error value in case of an error.
76418322377SGavin Shan  */
76518322377SGavin Shan int of_changeset_revert(struct of_changeset *ocs)
76618322377SGavin Shan {
76718322377SGavin Shan 	int ret;
76818322377SGavin Shan 
76918322377SGavin Shan 	mutex_lock(&of_mutex);
77018322377SGavin Shan 	ret = __of_changeset_revert(ocs);
77118322377SGavin Shan 	mutex_unlock(&of_mutex);
77218322377SGavin Shan 
77318322377SGavin Shan 	return ret;
77418322377SGavin Shan }
77518322377SGavin Shan EXPORT_SYMBOL_GPL(of_changeset_revert);
77618322377SGavin Shan 
77718322377SGavin Shan /**
778201c910bSPantelis Antoniou  * of_changeset_action - Perform a changeset action
779201c910bSPantelis Antoniou  *
780201c910bSPantelis Antoniou  * @ocs:	changeset pointer
781201c910bSPantelis Antoniou  * @action:	action to perform
782201c910bSPantelis Antoniou  * @np:		Pointer to device node
783201c910bSPantelis Antoniou  * @prop:	Pointer to property
784201c910bSPantelis Antoniou  *
785201c910bSPantelis Antoniou  * On action being one of:
786201c910bSPantelis Antoniou  * + OF_RECONFIG_ATTACH_NODE
787201c910bSPantelis Antoniou  * + OF_RECONFIG_DETACH_NODE,
788201c910bSPantelis Antoniou  * + OF_RECONFIG_ADD_PROPERTY
789201c910bSPantelis Antoniou  * + OF_RECONFIG_REMOVE_PROPERTY,
790201c910bSPantelis Antoniou  * + OF_RECONFIG_UPDATE_PROPERTY
791201c910bSPantelis Antoniou  * Returns 0 on success, a negative error value in case of an error.
792201c910bSPantelis Antoniou  */
793201c910bSPantelis Antoniou int of_changeset_action(struct of_changeset *ocs, unsigned long action,
794201c910bSPantelis Antoniou 		struct device_node *np, struct property *prop)
795201c910bSPantelis Antoniou {
796201c910bSPantelis Antoniou 	struct of_changeset_entry *ce;
797201c910bSPantelis Antoniou 
798201c910bSPantelis Antoniou 	ce = kzalloc(sizeof(*ce), GFP_KERNEL);
799606ad42aSRob Herring 	if (!ce)
800201c910bSPantelis Antoniou 		return -ENOMEM;
801606ad42aSRob Herring 
802201c910bSPantelis Antoniou 	/* get a reference to the node */
803201c910bSPantelis Antoniou 	ce->action = action;
804201c910bSPantelis Antoniou 	ce->np = of_node_get(np);
805201c910bSPantelis Antoniou 	ce->prop = prop;
806201c910bSPantelis Antoniou 
807201c910bSPantelis Antoniou 	if (action == OF_RECONFIG_UPDATE_PROPERTY && prop)
808201c910bSPantelis Antoniou 		ce->old_prop = of_find_property(np, prop->name, NULL);
809201c910bSPantelis Antoniou 
810201c910bSPantelis Antoniou 	/* add it to the list */
811201c910bSPantelis Antoniou 	list_add_tail(&ce->node, &ocs->entries);
812201c910bSPantelis Antoniou 	return 0;
813201c910bSPantelis Antoniou }
81418322377SGavin Shan EXPORT_SYMBOL_GPL(of_changeset_action);
815