xref: /linux/drivers/of/dynamic.c (revision e51795815ef1a7adc018cbaf05aac46e3d24eda8)
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 
96afc0dc3SGrant Likely #include <linux/of.h>
106afc0dc3SGrant Likely #include <linux/spinlock.h>
116afc0dc3SGrant Likely #include <linux/slab.h>
126afc0dc3SGrant Likely #include <linux/string.h>
136afc0dc3SGrant Likely #include <linux/proc_fs.h>
146afc0dc3SGrant Likely 
156afc0dc3SGrant Likely #include "of_private.h"
166afc0dc3SGrant Likely 
176afc0dc3SGrant Likely /**
186afc0dc3SGrant Likely  * of_node_get() - Increment refcount of a node
196afc0dc3SGrant Likely  * @node:	Node to inc refcount, NULL is supported to simplify writing of
206afc0dc3SGrant Likely  *		callers
216afc0dc3SGrant Likely  *
226afc0dc3SGrant Likely  * Returns node.
236afc0dc3SGrant Likely  */
246afc0dc3SGrant Likely struct device_node *of_node_get(struct device_node *node)
256afc0dc3SGrant Likely {
266afc0dc3SGrant Likely 	if (node)
276afc0dc3SGrant Likely 		kobject_get(&node->kobj);
286afc0dc3SGrant Likely 	return node;
296afc0dc3SGrant Likely }
306afc0dc3SGrant Likely EXPORT_SYMBOL(of_node_get);
316afc0dc3SGrant Likely 
326afc0dc3SGrant Likely /**
336afc0dc3SGrant Likely  * of_node_put() - Decrement refcount of a node
346afc0dc3SGrant Likely  * @node:	Node to dec refcount, NULL is supported to simplify writing of
356afc0dc3SGrant Likely  *		callers
366afc0dc3SGrant Likely  */
376afc0dc3SGrant Likely void of_node_put(struct device_node *node)
386afc0dc3SGrant Likely {
396afc0dc3SGrant Likely 	if (node)
406afc0dc3SGrant Likely 		kobject_put(&node->kobj);
416afc0dc3SGrant Likely }
426afc0dc3SGrant Likely EXPORT_SYMBOL(of_node_put);
436afc0dc3SGrant Likely 
448a2b22a2SGrant Likely void __of_detach_node_sysfs(struct device_node *np)
456afc0dc3SGrant Likely {
466afc0dc3SGrant Likely 	struct property *pp;
476afc0dc3SGrant Likely 
48ef69d740SGaurav Minocha 	if (!IS_ENABLED(CONFIG_SYSFS))
49ef69d740SGaurav Minocha 		return;
50ef69d740SGaurav Minocha 
516afc0dc3SGrant Likely 	BUG_ON(!of_node_is_initialized(np));
528a2b22a2SGrant Likely 	if (!of_kset)
538a2b22a2SGrant Likely 		return;
546afc0dc3SGrant Likely 
556afc0dc3SGrant Likely 	/* only remove properties if on sysfs */
566afc0dc3SGrant Likely 	if (of_node_is_attached(np)) {
576afc0dc3SGrant Likely 		for_each_property_of_node(np, pp)
586afc0dc3SGrant Likely 			sysfs_remove_bin_file(&np->kobj, &pp->attr);
596afc0dc3SGrant Likely 		kobject_del(&np->kobj);
606afc0dc3SGrant Likely 	}
616afc0dc3SGrant Likely 
626afc0dc3SGrant Likely 	/* finally remove the kobj_init ref */
636afc0dc3SGrant Likely 	of_node_put(np);
646afc0dc3SGrant Likely }
656afc0dc3SGrant Likely 
666afc0dc3SGrant Likely static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);
676afc0dc3SGrant Likely 
686afc0dc3SGrant Likely int of_reconfig_notifier_register(struct notifier_block *nb)
696afc0dc3SGrant Likely {
706afc0dc3SGrant Likely 	return blocking_notifier_chain_register(&of_reconfig_chain, nb);
716afc0dc3SGrant Likely }
726afc0dc3SGrant Likely EXPORT_SYMBOL_GPL(of_reconfig_notifier_register);
736afc0dc3SGrant Likely 
746afc0dc3SGrant Likely int of_reconfig_notifier_unregister(struct notifier_block *nb)
756afc0dc3SGrant Likely {
766afc0dc3SGrant Likely 	return blocking_notifier_chain_unregister(&of_reconfig_chain, nb);
776afc0dc3SGrant Likely }
786afc0dc3SGrant Likely EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister);
796afc0dc3SGrant Likely 
806afc0dc3SGrant Likely int of_reconfig_notify(unsigned long action, void *p)
816afc0dc3SGrant Likely {
826afc0dc3SGrant Likely 	int rc;
836afc0dc3SGrant Likely 
846afc0dc3SGrant Likely 	rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p);
856afc0dc3SGrant Likely 	return notifier_to_errno(rc);
866afc0dc3SGrant Likely }
876afc0dc3SGrant Likely 
886afc0dc3SGrant Likely int of_property_notify(int action, struct device_node *np,
89259092a3SGrant Likely 		       struct property *prop, struct property *oldprop)
906afc0dc3SGrant Likely {
916afc0dc3SGrant Likely 	struct of_prop_reconfig pr;
926afc0dc3SGrant Likely 
936afc0dc3SGrant Likely 	/* only call notifiers if the node is attached */
946afc0dc3SGrant Likely 	if (!of_node_is_attached(np))
956afc0dc3SGrant Likely 		return 0;
966afc0dc3SGrant Likely 
976afc0dc3SGrant Likely 	pr.dn = np;
986afc0dc3SGrant Likely 	pr.prop = prop;
99259092a3SGrant Likely 	pr.old_prop = oldprop;
1006afc0dc3SGrant Likely 	return of_reconfig_notify(action, &pr);
1016afc0dc3SGrant Likely }
1026afc0dc3SGrant Likely 
103d8c50088SPantelis Antoniou void __of_attach_node(struct device_node *np)
104d8c50088SPantelis Antoniou {
105a25095d4SGrant Likely 	const __be32 *phandle;
106a25095d4SGrant Likely 	int sz;
107a25095d4SGrant Likely 
108a25095d4SGrant Likely 	np->name = __of_get_property(np, "name", NULL) ? : "<NULL>";
109a25095d4SGrant Likely 	np->type = __of_get_property(np, "device_type", NULL) ? : "<NULL>";
110a25095d4SGrant Likely 
111a25095d4SGrant Likely 	phandle = __of_get_property(np, "phandle", &sz);
112a25095d4SGrant Likely 	if (!phandle)
113a25095d4SGrant Likely 		phandle = __of_get_property(np, "linux,phandle", &sz);
114a25095d4SGrant Likely 	if (IS_ENABLED(PPC_PSERIES) && !phandle)
115a25095d4SGrant Likely 		phandle = __of_get_property(np, "ibm,phandle", &sz);
116a25095d4SGrant Likely 	np->phandle = (phandle && (sz >= 4)) ? be32_to_cpup(phandle) : 0;
117a25095d4SGrant Likely 
1186162dbe4SGrant Likely 	np->child = NULL;
119d8c50088SPantelis Antoniou 	np->sibling = np->parent->child;
120d8c50088SPantelis Antoniou 	np->parent->child = np;
121d8c50088SPantelis Antoniou 	of_node_clear_flag(np, OF_DETACHED);
122d8c50088SPantelis Antoniou }
123d8c50088SPantelis Antoniou 
1246afc0dc3SGrant Likely /**
1256afc0dc3SGrant Likely  * of_attach_node() - Plug a device node into the tree and global list.
1266afc0dc3SGrant Likely  */
1276afc0dc3SGrant Likely int of_attach_node(struct device_node *np)
1286afc0dc3SGrant Likely {
1296afc0dc3SGrant Likely 	unsigned long flags;
1306afc0dc3SGrant Likely 
1318a2b22a2SGrant Likely 	mutex_lock(&of_mutex);
1326afc0dc3SGrant Likely 	raw_spin_lock_irqsave(&devtree_lock, flags);
133d8c50088SPantelis Antoniou 	__of_attach_node(np);
1346afc0dc3SGrant Likely 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1356afc0dc3SGrant Likely 
1368a2b22a2SGrant Likely 	__of_attach_node_sysfs(np);
1378a2b22a2SGrant Likely 	mutex_unlock(&of_mutex);
138259092a3SGrant Likely 
139259092a3SGrant Likely 	of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np);
140259092a3SGrant Likely 
1416afc0dc3SGrant Likely 	return 0;
1426afc0dc3SGrant Likely }
1436afc0dc3SGrant Likely 
144d8c50088SPantelis Antoniou void __of_detach_node(struct device_node *np)
1456afc0dc3SGrant Likely {
1466afc0dc3SGrant Likely 	struct device_node *parent;
1476afc0dc3SGrant Likely 
148d8c50088SPantelis Antoniou 	if (WARN_ON(of_node_check_flag(np, OF_DETACHED)))
149d8c50088SPantelis Antoniou 		return;
1506afc0dc3SGrant Likely 
1516afc0dc3SGrant Likely 	parent = np->parent;
152d8c50088SPantelis Antoniou 	if (WARN_ON(!parent))
153d8c50088SPantelis Antoniou 		return;
1546afc0dc3SGrant Likely 
1556afc0dc3SGrant Likely 	if (parent->child == np)
1566afc0dc3SGrant Likely 		parent->child = np->sibling;
1576afc0dc3SGrant Likely 	else {
1586afc0dc3SGrant Likely 		struct device_node *prevsib;
1596afc0dc3SGrant Likely 		for (prevsib = np->parent->child;
1606afc0dc3SGrant Likely 		     prevsib->sibling != np;
1616afc0dc3SGrant Likely 		     prevsib = prevsib->sibling)
1626afc0dc3SGrant Likely 			;
1636afc0dc3SGrant Likely 		prevsib->sibling = np->sibling;
1646afc0dc3SGrant Likely 	}
1656afc0dc3SGrant Likely 
1666afc0dc3SGrant Likely 	of_node_set_flag(np, OF_DETACHED);
167d8c50088SPantelis Antoniou }
168d8c50088SPantelis Antoniou 
169d8c50088SPantelis Antoniou /**
170d8c50088SPantelis Antoniou  * of_detach_node() - "Unplug" a node from the device tree.
171d8c50088SPantelis Antoniou  *
172d8c50088SPantelis Antoniou  * The caller must hold a reference to the node.  The memory associated with
173d8c50088SPantelis Antoniou  * the node is not freed until its refcount goes to zero.
174d8c50088SPantelis Antoniou  */
175d8c50088SPantelis Antoniou int of_detach_node(struct device_node *np)
176d8c50088SPantelis Antoniou {
177d8c50088SPantelis Antoniou 	unsigned long flags;
178d8c50088SPantelis Antoniou 	int rc = 0;
179d8c50088SPantelis Antoniou 
1808a2b22a2SGrant Likely 	mutex_lock(&of_mutex);
181d8c50088SPantelis Antoniou 	raw_spin_lock_irqsave(&devtree_lock, flags);
182d8c50088SPantelis Antoniou 	__of_detach_node(np);
1836afc0dc3SGrant Likely 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1846afc0dc3SGrant Likely 
1858a2b22a2SGrant Likely 	__of_detach_node_sysfs(np);
1868a2b22a2SGrant Likely 	mutex_unlock(&of_mutex);
187259092a3SGrant Likely 
188259092a3SGrant Likely 	of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
189259092a3SGrant Likely 
1906afc0dc3SGrant Likely 	return rc;
1916afc0dc3SGrant Likely }
1926afc0dc3SGrant Likely 
1936afc0dc3SGrant Likely /**
1946afc0dc3SGrant Likely  * of_node_release() - release a dynamically allocated node
1956afc0dc3SGrant Likely  * @kref: kref element of the node to be released
1966afc0dc3SGrant Likely  *
1976afc0dc3SGrant Likely  * In of_node_put() this function is passed to kref_put() as the destructor.
1986afc0dc3SGrant Likely  */
1996afc0dc3SGrant Likely void of_node_release(struct kobject *kobj)
2006afc0dc3SGrant Likely {
2016afc0dc3SGrant Likely 	struct device_node *node = kobj_to_device_node(kobj);
2026afc0dc3SGrant Likely 	struct property *prop = node->properties;
2036afc0dc3SGrant Likely 
2046afc0dc3SGrant Likely 	/* We should never be releasing nodes that haven't been detached. */
2056afc0dc3SGrant Likely 	if (!of_node_check_flag(node, OF_DETACHED)) {
2066afc0dc3SGrant Likely 		pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name);
2076afc0dc3SGrant Likely 		dump_stack();
2086afc0dc3SGrant Likely 		return;
2096afc0dc3SGrant Likely 	}
2106afc0dc3SGrant Likely 
2116afc0dc3SGrant Likely 	if (!of_node_check_flag(node, OF_DYNAMIC))
2126afc0dc3SGrant Likely 		return;
2136afc0dc3SGrant Likely 
2146afc0dc3SGrant Likely 	while (prop) {
2156afc0dc3SGrant Likely 		struct property *next = prop->next;
2166afc0dc3SGrant Likely 		kfree(prop->name);
2176afc0dc3SGrant Likely 		kfree(prop->value);
2186afc0dc3SGrant Likely 		kfree(prop);
2196afc0dc3SGrant Likely 		prop = next;
2206afc0dc3SGrant Likely 
2216afc0dc3SGrant Likely 		if (!prop) {
2226afc0dc3SGrant Likely 			prop = node->deadprops;
2236afc0dc3SGrant Likely 			node->deadprops = NULL;
2246afc0dc3SGrant Likely 		}
2256afc0dc3SGrant Likely 	}
2266afc0dc3SGrant Likely 	kfree(node->full_name);
2276afc0dc3SGrant Likely 	kfree(node->data);
2286afc0dc3SGrant Likely 	kfree(node);
2296afc0dc3SGrant Likely }
23069843396SPantelis Antoniou 
23169843396SPantelis Antoniou /**
23269843396SPantelis Antoniou  * __of_prop_dup - Copy a property dynamically.
23369843396SPantelis Antoniou  * @prop:	Property to copy
23469843396SPantelis Antoniou  * @allocflags:	Allocation flags (typically pass GFP_KERNEL)
23569843396SPantelis Antoniou  *
23669843396SPantelis Antoniou  * Copy a property by dynamically allocating the memory of both the
23727b3383aSGeert Uytterhoeven  * property structure and the property name & contents. The property's
23869843396SPantelis Antoniou  * flags have the OF_DYNAMIC bit set so that we can differentiate between
23969843396SPantelis Antoniou  * dynamically allocated properties and not.
24069843396SPantelis Antoniou  * Returns the newly allocated property or NULL on out of memory error.
24169843396SPantelis Antoniou  */
24269843396SPantelis Antoniou struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags)
24369843396SPantelis Antoniou {
24469843396SPantelis Antoniou 	struct property *new;
24569843396SPantelis Antoniou 
24669843396SPantelis Antoniou 	new = kzalloc(sizeof(*new), allocflags);
24769843396SPantelis Antoniou 	if (!new)
24869843396SPantelis Antoniou 		return NULL;
24969843396SPantelis Antoniou 
25069843396SPantelis Antoniou 	/*
25169843396SPantelis Antoniou 	 * NOTE: There is no check for zero length value.
252b6ae5dc5SGrant Likely 	 * In case of a boolean property, this will allocate a value
25369843396SPantelis Antoniou 	 * of zero bytes. We do this to work around the use
25469843396SPantelis Antoniou 	 * of of_get_property() calls on boolean values.
25569843396SPantelis Antoniou 	 */
25669843396SPantelis Antoniou 	new->name = kstrdup(prop->name, allocflags);
25769843396SPantelis Antoniou 	new->value = kmemdup(prop->value, prop->length, allocflags);
25869843396SPantelis Antoniou 	new->length = prop->length;
25969843396SPantelis Antoniou 	if (!new->name || !new->value)
26069843396SPantelis Antoniou 		goto err_free;
26169843396SPantelis Antoniou 
26269843396SPantelis Antoniou 	/* mark the property as dynamic */
26369843396SPantelis Antoniou 	of_property_set_flag(new, OF_DYNAMIC);
26469843396SPantelis Antoniou 
26569843396SPantelis Antoniou 	return new;
26669843396SPantelis Antoniou 
26769843396SPantelis Antoniou  err_free:
26869843396SPantelis Antoniou 	kfree(new->name);
26969843396SPantelis Antoniou 	kfree(new->value);
27069843396SPantelis Antoniou 	kfree(new);
27169843396SPantelis Antoniou 	return NULL;
27269843396SPantelis Antoniou }
27369843396SPantelis Antoniou 
27469843396SPantelis Antoniou /**
275*e5179581SGrant Likely  * __of_node_dup() - Duplicate or create an empty device node dynamically.
276*e5179581SGrant Likely  * @fmt: Format string (plus vargs) for new full name of the device node
27769843396SPantelis Antoniou  *
278*e5179581SGrant Likely  * Create an device tree node, either by duplicating an empty node or by allocating
279*e5179581SGrant Likely  * an empty one suitable for further modification.  The node data are
280*e5179581SGrant Likely  * dynamically allocated and all the node flags have the OF_DYNAMIC &
281*e5179581SGrant Likely  * OF_DETACHED bits set. Returns the newly allocated node or NULL on out of
282*e5179581SGrant Likely  * memory error.
28369843396SPantelis Antoniou  */
284*e5179581SGrant Likely struct device_node *__of_node_dup(const struct device_node *np, const char *fmt, ...)
28569843396SPantelis Antoniou {
286ef8bbd73SGrant Likely 	va_list vargs;
28769843396SPantelis Antoniou 	struct device_node *node;
28869843396SPantelis Antoniou 
289ef8bbd73SGrant Likely 	node = kzalloc(sizeof(*node), GFP_KERNEL);
29069843396SPantelis Antoniou 	if (!node)
29169843396SPantelis Antoniou 		return NULL;
292ef8bbd73SGrant Likely 	va_start(vargs, fmt);
293ef8bbd73SGrant Likely 	node->full_name = kvasprintf(GFP_KERNEL, fmt, vargs);
294ef8bbd73SGrant Likely 	va_end(vargs);
295*e5179581SGrant Likely 	if (!node->full_name) {
296*e5179581SGrant Likely 		kfree(node);
297*e5179581SGrant Likely 		return NULL;
298*e5179581SGrant Likely 	}
29969843396SPantelis Antoniou 
300ef8bbd73SGrant Likely 	of_node_set_flag(node, OF_DYNAMIC);
301ef8bbd73SGrant Likely 	of_node_set_flag(node, OF_DETACHED);
30269843396SPantelis Antoniou 	of_node_init(node);
30369843396SPantelis Antoniou 
304*e5179581SGrant Likely 	/* Iterate over and duplicate all properties */
305*e5179581SGrant Likely 	if (np) {
306*e5179581SGrant Likely 		struct property *pp, *new_pp;
307*e5179581SGrant Likely 		for_each_property_of_node(np, pp) {
308*e5179581SGrant Likely 			new_pp = __of_prop_dup(pp, GFP_KERNEL);
309*e5179581SGrant Likely 			if (!new_pp)
310*e5179581SGrant Likely 				goto err_prop;
311*e5179581SGrant Likely 			if (__of_add_property(node, new_pp)) {
312*e5179581SGrant Likely 				kfree(new_pp->name);
313*e5179581SGrant Likely 				kfree(new_pp->value);
314*e5179581SGrant Likely 				kfree(new_pp);
315*e5179581SGrant Likely 				goto err_prop;
316*e5179581SGrant Likely 			}
317*e5179581SGrant Likely 		}
318*e5179581SGrant Likely 	}
31969843396SPantelis Antoniou 	return node;
32069843396SPantelis Antoniou 
321*e5179581SGrant Likely  err_prop:
322*e5179581SGrant Likely 	of_node_put(node); /* Frees the node and properties */
32369843396SPantelis Antoniou 	return NULL;
32469843396SPantelis Antoniou }
325201c910bSPantelis Antoniou 
326201c910bSPantelis Antoniou static void __of_changeset_entry_destroy(struct of_changeset_entry *ce)
327201c910bSPantelis Antoniou {
328201c910bSPantelis Antoniou 	of_node_put(ce->np);
329201c910bSPantelis Antoniou 	list_del(&ce->node);
330201c910bSPantelis Antoniou 	kfree(ce);
331201c910bSPantelis Antoniou }
332201c910bSPantelis Antoniou 
333201c910bSPantelis Antoniou #ifdef DEBUG
334201c910bSPantelis Antoniou static void __of_changeset_entry_dump(struct of_changeset_entry *ce)
335201c910bSPantelis Antoniou {
336201c910bSPantelis Antoniou 	switch (ce->action) {
337201c910bSPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
338201c910bSPantelis Antoniou 		pr_debug("%p: %s %s/%s\n",
339201c910bSPantelis Antoniou 			ce, "ADD_PROPERTY   ", ce->np->full_name,
340201c910bSPantelis Antoniou 			ce->prop->name);
341201c910bSPantelis Antoniou 		break;
342201c910bSPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
343201c910bSPantelis Antoniou 		pr_debug("%p: %s %s/%s\n",
344201c910bSPantelis Antoniou 			ce, "REMOVE_PROPERTY", ce->np->full_name,
345201c910bSPantelis Antoniou 			ce->prop->name);
346201c910bSPantelis Antoniou 		break;
347201c910bSPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
348201c910bSPantelis Antoniou 		pr_debug("%p: %s %s/%s\n",
349201c910bSPantelis Antoniou 			ce, "UPDATE_PROPERTY", ce->np->full_name,
350201c910bSPantelis Antoniou 			ce->prop->name);
351201c910bSPantelis Antoniou 		break;
352201c910bSPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
353201c910bSPantelis Antoniou 		pr_debug("%p: %s %s\n",
354201c910bSPantelis Antoniou 			ce, "ATTACH_NODE    ", ce->np->full_name);
355201c910bSPantelis Antoniou 		break;
356201c910bSPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
357201c910bSPantelis Antoniou 		pr_debug("%p: %s %s\n",
358201c910bSPantelis Antoniou 			ce, "DETACH_NODE    ", ce->np->full_name);
359201c910bSPantelis Antoniou 		break;
360201c910bSPantelis Antoniou 	}
361201c910bSPantelis Antoniou }
362201c910bSPantelis Antoniou #else
363201c910bSPantelis Antoniou static inline void __of_changeset_entry_dump(struct of_changeset_entry *ce)
364201c910bSPantelis Antoniou {
365201c910bSPantelis Antoniou 	/* empty */
366201c910bSPantelis Antoniou }
367201c910bSPantelis Antoniou #endif
368201c910bSPantelis Antoniou 
369201c910bSPantelis Antoniou static void __of_changeset_entry_invert(struct of_changeset_entry *ce,
370201c910bSPantelis Antoniou 					  struct of_changeset_entry *rce)
371201c910bSPantelis Antoniou {
372201c910bSPantelis Antoniou 	memcpy(rce, ce, sizeof(*rce));
373201c910bSPantelis Antoniou 
374201c910bSPantelis Antoniou 	switch (ce->action) {
375201c910bSPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
376201c910bSPantelis Antoniou 		rce->action = OF_RECONFIG_DETACH_NODE;
377201c910bSPantelis Antoniou 		break;
378201c910bSPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
379201c910bSPantelis Antoniou 		rce->action = OF_RECONFIG_ATTACH_NODE;
380201c910bSPantelis Antoniou 		break;
381201c910bSPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
382201c910bSPantelis Antoniou 		rce->action = OF_RECONFIG_REMOVE_PROPERTY;
383201c910bSPantelis Antoniou 		break;
384201c910bSPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
385201c910bSPantelis Antoniou 		rce->action = OF_RECONFIG_ADD_PROPERTY;
386201c910bSPantelis Antoniou 		break;
387201c910bSPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
388201c910bSPantelis Antoniou 		rce->old_prop = ce->prop;
389201c910bSPantelis Antoniou 		rce->prop = ce->old_prop;
390201c910bSPantelis Antoniou 		break;
391201c910bSPantelis Antoniou 	}
392201c910bSPantelis Antoniou }
393201c910bSPantelis Antoniou 
394201c910bSPantelis Antoniou static void __of_changeset_entry_notify(struct of_changeset_entry *ce, bool revert)
395201c910bSPantelis Antoniou {
396201c910bSPantelis Antoniou 	struct of_changeset_entry ce_inverted;
397201c910bSPantelis Antoniou 	int ret;
398201c910bSPantelis Antoniou 
399201c910bSPantelis Antoniou 	if (revert) {
400201c910bSPantelis Antoniou 		__of_changeset_entry_invert(ce, &ce_inverted);
401201c910bSPantelis Antoniou 		ce = &ce_inverted;
402201c910bSPantelis Antoniou 	}
403201c910bSPantelis Antoniou 
404201c910bSPantelis Antoniou 	switch (ce->action) {
405201c910bSPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
406201c910bSPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
407201c910bSPantelis Antoniou 		ret = of_reconfig_notify(ce->action, ce->np);
408201c910bSPantelis Antoniou 		break;
409201c910bSPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
410201c910bSPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
411201c910bSPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
412201c910bSPantelis Antoniou 		ret = of_property_notify(ce->action, ce->np, ce->prop, ce->old_prop);
413201c910bSPantelis Antoniou 		break;
414201c910bSPantelis Antoniou 	default:
415201c910bSPantelis Antoniou 		pr_err("%s: invalid devicetree changeset action: %i\n", __func__,
416201c910bSPantelis Antoniou 			(int)ce->action);
417201c910bSPantelis Antoniou 		return;
418201c910bSPantelis Antoniou 	}
419201c910bSPantelis Antoniou 
420201c910bSPantelis Antoniou 	if (ret)
421201c910bSPantelis Antoniou 		pr_err("%s: notifier error @%s\n", __func__, ce->np->full_name);
422201c910bSPantelis Antoniou }
423201c910bSPantelis Antoniou 
424201c910bSPantelis Antoniou static int __of_changeset_entry_apply(struct of_changeset_entry *ce)
425201c910bSPantelis Antoniou {
426201c910bSPantelis Antoniou 	struct property *old_prop, **propp;
427201c910bSPantelis Antoniou 	unsigned long flags;
428201c910bSPantelis Antoniou 	int ret = 0;
429201c910bSPantelis Antoniou 
430201c910bSPantelis Antoniou 	__of_changeset_entry_dump(ce);
431201c910bSPantelis Antoniou 
432201c910bSPantelis Antoniou 	raw_spin_lock_irqsave(&devtree_lock, flags);
433201c910bSPantelis Antoniou 	switch (ce->action) {
434201c910bSPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
435201c910bSPantelis Antoniou 		__of_attach_node(ce->np);
436201c910bSPantelis Antoniou 		break;
437201c910bSPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
438201c910bSPantelis Antoniou 		__of_detach_node(ce->np);
439201c910bSPantelis Antoniou 		break;
440201c910bSPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
441201c910bSPantelis Antoniou 		/* If the property is in deadprops then it must be removed */
442201c910bSPantelis Antoniou 		for (propp = &ce->np->deadprops; *propp; propp = &(*propp)->next) {
443201c910bSPantelis Antoniou 			if (*propp == ce->prop) {
444201c910bSPantelis Antoniou 				*propp = ce->prop->next;
445201c910bSPantelis Antoniou 				ce->prop->next = NULL;
446201c910bSPantelis Antoniou 				break;
447201c910bSPantelis Antoniou 			}
448201c910bSPantelis Antoniou 		}
449201c910bSPantelis Antoniou 
450201c910bSPantelis Antoniou 		ret = __of_add_property(ce->np, ce->prop);
451201c910bSPantelis Antoniou 		if (ret) {
452201c910bSPantelis Antoniou 			pr_err("%s: add_property failed @%s/%s\n",
453201c910bSPantelis Antoniou 				__func__, ce->np->full_name,
454201c910bSPantelis Antoniou 				ce->prop->name);
455201c910bSPantelis Antoniou 			break;
456201c910bSPantelis Antoniou 		}
457201c910bSPantelis Antoniou 		break;
458201c910bSPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
459201c910bSPantelis Antoniou 		ret = __of_remove_property(ce->np, ce->prop);
460201c910bSPantelis Antoniou 		if (ret) {
461201c910bSPantelis Antoniou 			pr_err("%s: remove_property failed @%s/%s\n",
462201c910bSPantelis Antoniou 				__func__, ce->np->full_name,
463201c910bSPantelis Antoniou 				ce->prop->name);
464201c910bSPantelis Antoniou 			break;
465201c910bSPantelis Antoniou 		}
466201c910bSPantelis Antoniou 		break;
467201c910bSPantelis Antoniou 
468201c910bSPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
469201c910bSPantelis Antoniou 		/* If the property is in deadprops then it must be removed */
470201c910bSPantelis Antoniou 		for (propp = &ce->np->deadprops; *propp; propp = &(*propp)->next) {
471201c910bSPantelis Antoniou 			if (*propp == ce->prop) {
472201c910bSPantelis Antoniou 				*propp = ce->prop->next;
473201c910bSPantelis Antoniou 				ce->prop->next = NULL;
474201c910bSPantelis Antoniou 				break;
475201c910bSPantelis Antoniou 			}
476201c910bSPantelis Antoniou 		}
477201c910bSPantelis Antoniou 
478201c910bSPantelis Antoniou 		ret = __of_update_property(ce->np, ce->prop, &old_prop);
479201c910bSPantelis Antoniou 		if (ret) {
480201c910bSPantelis Antoniou 			pr_err("%s: update_property failed @%s/%s\n",
481201c910bSPantelis Antoniou 				__func__, ce->np->full_name,
482201c910bSPantelis Antoniou 				ce->prop->name);
483201c910bSPantelis Antoniou 			break;
484201c910bSPantelis Antoniou 		}
485201c910bSPantelis Antoniou 		break;
486201c910bSPantelis Antoniou 	default:
487201c910bSPantelis Antoniou 		ret = -EINVAL;
488201c910bSPantelis Antoniou 	}
489201c910bSPantelis Antoniou 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
490201c910bSPantelis Antoniou 
491201c910bSPantelis Antoniou 	if (ret)
492201c910bSPantelis Antoniou 		return ret;
493201c910bSPantelis Antoniou 
494201c910bSPantelis Antoniou 	switch (ce->action) {
495201c910bSPantelis Antoniou 	case OF_RECONFIG_ATTACH_NODE:
496201c910bSPantelis Antoniou 		__of_attach_node_sysfs(ce->np);
497201c910bSPantelis Antoniou 		break;
498201c910bSPantelis Antoniou 	case OF_RECONFIG_DETACH_NODE:
499201c910bSPantelis Antoniou 		__of_detach_node_sysfs(ce->np);
500201c910bSPantelis Antoniou 		break;
501201c910bSPantelis Antoniou 	case OF_RECONFIG_ADD_PROPERTY:
502201c910bSPantelis Antoniou 		/* ignore duplicate names */
503201c910bSPantelis Antoniou 		__of_add_property_sysfs(ce->np, ce->prop);
504201c910bSPantelis Antoniou 		break;
505201c910bSPantelis Antoniou 	case OF_RECONFIG_REMOVE_PROPERTY:
506201c910bSPantelis Antoniou 		__of_remove_property_sysfs(ce->np, ce->prop);
507201c910bSPantelis Antoniou 		break;
508201c910bSPantelis Antoniou 	case OF_RECONFIG_UPDATE_PROPERTY:
509201c910bSPantelis Antoniou 		__of_update_property_sysfs(ce->np, ce->prop, ce->old_prop);
510201c910bSPantelis Antoniou 		break;
511201c910bSPantelis Antoniou 	}
512201c910bSPantelis Antoniou 
513201c910bSPantelis Antoniou 	return 0;
514201c910bSPantelis Antoniou }
515201c910bSPantelis Antoniou 
516201c910bSPantelis Antoniou static inline int __of_changeset_entry_revert(struct of_changeset_entry *ce)
517201c910bSPantelis Antoniou {
518201c910bSPantelis Antoniou 	struct of_changeset_entry ce_inverted;
519201c910bSPantelis Antoniou 
520201c910bSPantelis Antoniou 	__of_changeset_entry_invert(ce, &ce_inverted);
521201c910bSPantelis Antoniou 	return __of_changeset_entry_apply(&ce_inverted);
522201c910bSPantelis Antoniou }
523201c910bSPantelis Antoniou 
524201c910bSPantelis Antoniou /**
525201c910bSPantelis Antoniou  * of_changeset_init - Initialize a changeset for use
526201c910bSPantelis Antoniou  *
527201c910bSPantelis Antoniou  * @ocs:	changeset pointer
528201c910bSPantelis Antoniou  *
529201c910bSPantelis Antoniou  * Initialize a changeset structure
530201c910bSPantelis Antoniou  */
531201c910bSPantelis Antoniou void of_changeset_init(struct of_changeset *ocs)
532201c910bSPantelis Antoniou {
533201c910bSPantelis Antoniou 	memset(ocs, 0, sizeof(*ocs));
534201c910bSPantelis Antoniou 	INIT_LIST_HEAD(&ocs->entries);
535201c910bSPantelis Antoniou }
536201c910bSPantelis Antoniou 
537201c910bSPantelis Antoniou /**
538201c910bSPantelis Antoniou  * of_changeset_destroy - Destroy a changeset
539201c910bSPantelis Antoniou  *
540201c910bSPantelis Antoniou  * @ocs:	changeset pointer
541201c910bSPantelis Antoniou  *
542201c910bSPantelis Antoniou  * Destroys a changeset. Note that if a changeset is applied,
543201c910bSPantelis Antoniou  * its changes to the tree cannot be reverted.
544201c910bSPantelis Antoniou  */
545201c910bSPantelis Antoniou void of_changeset_destroy(struct of_changeset *ocs)
546201c910bSPantelis Antoniou {
547201c910bSPantelis Antoniou 	struct of_changeset_entry *ce, *cen;
548201c910bSPantelis Antoniou 
549201c910bSPantelis Antoniou 	list_for_each_entry_safe_reverse(ce, cen, &ocs->entries, node)
550201c910bSPantelis Antoniou 		__of_changeset_entry_destroy(ce);
551201c910bSPantelis Antoniou }
552201c910bSPantelis Antoniou 
553201c910bSPantelis Antoniou /**
554201c910bSPantelis Antoniou  * of_changeset_apply - Applies a changeset
555201c910bSPantelis Antoniou  *
556201c910bSPantelis Antoniou  * @ocs:	changeset pointer
557201c910bSPantelis Antoniou  *
558201c910bSPantelis Antoniou  * Applies a changeset to the live tree.
559201c910bSPantelis Antoniou  * Any side-effects of live tree state changes are applied here on
560201c910bSPantelis Antoniou  * sucess, like creation/destruction of devices and side-effects
561201c910bSPantelis Antoniou  * like creation of sysfs properties and directories.
562201c910bSPantelis Antoniou  * Returns 0 on success, a negative error value in case of an error.
563201c910bSPantelis Antoniou  * On error the partially applied effects are reverted.
564201c910bSPantelis Antoniou  */
565201c910bSPantelis Antoniou int of_changeset_apply(struct of_changeset *ocs)
566201c910bSPantelis Antoniou {
567201c910bSPantelis Antoniou 	struct of_changeset_entry *ce;
568201c910bSPantelis Antoniou 	int ret;
569201c910bSPantelis Antoniou 
570201c910bSPantelis Antoniou 	/* perform the rest of the work */
571201c910bSPantelis Antoniou 	pr_debug("of_changeset: applying...\n");
572201c910bSPantelis Antoniou 	list_for_each_entry(ce, &ocs->entries, node) {
573201c910bSPantelis Antoniou 		ret = __of_changeset_entry_apply(ce);
574201c910bSPantelis Antoniou 		if (ret) {
575201c910bSPantelis Antoniou 			pr_err("%s: Error applying changeset (%d)\n", __func__, ret);
576201c910bSPantelis Antoniou 			list_for_each_entry_continue_reverse(ce, &ocs->entries, node)
577201c910bSPantelis Antoniou 				__of_changeset_entry_revert(ce);
578201c910bSPantelis Antoniou 			return ret;
579201c910bSPantelis Antoniou 		}
580201c910bSPantelis Antoniou 	}
581201c910bSPantelis Antoniou 	pr_debug("of_changeset: applied, emitting notifiers.\n");
582201c910bSPantelis Antoniou 
583201c910bSPantelis Antoniou 	/* drop the global lock while emitting notifiers */
584201c910bSPantelis Antoniou 	mutex_unlock(&of_mutex);
585201c910bSPantelis Antoniou 	list_for_each_entry(ce, &ocs->entries, node)
586201c910bSPantelis Antoniou 		__of_changeset_entry_notify(ce, 0);
587201c910bSPantelis Antoniou 	mutex_lock(&of_mutex);
588201c910bSPantelis Antoniou 	pr_debug("of_changeset: notifiers sent.\n");
589201c910bSPantelis Antoniou 
590201c910bSPantelis Antoniou 	return 0;
591201c910bSPantelis Antoniou }
592201c910bSPantelis Antoniou 
593201c910bSPantelis Antoniou /**
594201c910bSPantelis Antoniou  * of_changeset_revert - Reverts an applied changeset
595201c910bSPantelis Antoniou  *
596201c910bSPantelis Antoniou  * @ocs:	changeset pointer
597201c910bSPantelis Antoniou  *
598201c910bSPantelis Antoniou  * Reverts a changeset returning the state of the tree to what it
599201c910bSPantelis Antoniou  * was before the application.
600201c910bSPantelis Antoniou  * Any side-effects like creation/destruction of devices and
601201c910bSPantelis Antoniou  * removal of sysfs properties and directories are applied.
602201c910bSPantelis Antoniou  * Returns 0 on success, a negative error value in case of an error.
603201c910bSPantelis Antoniou  */
604201c910bSPantelis Antoniou int of_changeset_revert(struct of_changeset *ocs)
605201c910bSPantelis Antoniou {
606201c910bSPantelis Antoniou 	struct of_changeset_entry *ce;
607201c910bSPantelis Antoniou 	int ret;
608201c910bSPantelis Antoniou 
609201c910bSPantelis Antoniou 	pr_debug("of_changeset: reverting...\n");
610201c910bSPantelis Antoniou 	list_for_each_entry_reverse(ce, &ocs->entries, node) {
611201c910bSPantelis Antoniou 		ret = __of_changeset_entry_revert(ce);
612201c910bSPantelis Antoniou 		if (ret) {
613201c910bSPantelis Antoniou 			pr_err("%s: Error reverting changeset (%d)\n", __func__, ret);
614201c910bSPantelis Antoniou 			list_for_each_entry_continue(ce, &ocs->entries, node)
615201c910bSPantelis Antoniou 				__of_changeset_entry_apply(ce);
616201c910bSPantelis Antoniou 			return ret;
617201c910bSPantelis Antoniou 		}
618201c910bSPantelis Antoniou 	}
619201c910bSPantelis Antoniou 	pr_debug("of_changeset: reverted, emitting notifiers.\n");
620201c910bSPantelis Antoniou 
621201c910bSPantelis Antoniou 	/* drop the global lock while emitting notifiers */
622201c910bSPantelis Antoniou 	mutex_unlock(&of_mutex);
623201c910bSPantelis Antoniou 	list_for_each_entry_reverse(ce, &ocs->entries, node)
624201c910bSPantelis Antoniou 		__of_changeset_entry_notify(ce, 1);
625201c910bSPantelis Antoniou 	mutex_lock(&of_mutex);
626201c910bSPantelis Antoniou 	pr_debug("of_changeset: notifiers sent.\n");
627201c910bSPantelis Antoniou 
628201c910bSPantelis Antoniou 	return 0;
629201c910bSPantelis Antoniou }
630201c910bSPantelis Antoniou 
631201c910bSPantelis Antoniou /**
632201c910bSPantelis Antoniou  * of_changeset_action - Perform a changeset action
633201c910bSPantelis Antoniou  *
634201c910bSPantelis Antoniou  * @ocs:	changeset pointer
635201c910bSPantelis Antoniou  * @action:	action to perform
636201c910bSPantelis Antoniou  * @np:		Pointer to device node
637201c910bSPantelis Antoniou  * @prop:	Pointer to property
638201c910bSPantelis Antoniou  *
639201c910bSPantelis Antoniou  * On action being one of:
640201c910bSPantelis Antoniou  * + OF_RECONFIG_ATTACH_NODE
641201c910bSPantelis Antoniou  * + OF_RECONFIG_DETACH_NODE,
642201c910bSPantelis Antoniou  * + OF_RECONFIG_ADD_PROPERTY
643201c910bSPantelis Antoniou  * + OF_RECONFIG_REMOVE_PROPERTY,
644201c910bSPantelis Antoniou  * + OF_RECONFIG_UPDATE_PROPERTY
645201c910bSPantelis Antoniou  * Returns 0 on success, a negative error value in case of an error.
646201c910bSPantelis Antoniou  */
647201c910bSPantelis Antoniou int of_changeset_action(struct of_changeset *ocs, unsigned long action,
648201c910bSPantelis Antoniou 		struct device_node *np, struct property *prop)
649201c910bSPantelis Antoniou {
650201c910bSPantelis Antoniou 	struct of_changeset_entry *ce;
651201c910bSPantelis Antoniou 
652201c910bSPantelis Antoniou 	ce = kzalloc(sizeof(*ce), GFP_KERNEL);
653201c910bSPantelis Antoniou 	if (!ce) {
654201c910bSPantelis Antoniou 		pr_err("%s: Failed to allocate\n", __func__);
655201c910bSPantelis Antoniou 		return -ENOMEM;
656201c910bSPantelis Antoniou 	}
657201c910bSPantelis Antoniou 	/* get a reference to the node */
658201c910bSPantelis Antoniou 	ce->action = action;
659201c910bSPantelis Antoniou 	ce->np = of_node_get(np);
660201c910bSPantelis Antoniou 	ce->prop = prop;
661201c910bSPantelis Antoniou 
662201c910bSPantelis Antoniou 	if (action == OF_RECONFIG_UPDATE_PROPERTY && prop)
663201c910bSPantelis Antoniou 		ce->old_prop = of_find_property(np, prop->name, NULL);
664201c910bSPantelis Antoniou 
665201c910bSPantelis Antoniou 	/* add it to the list */
666201c910bSPantelis Antoniou 	list_add_tail(&ce->node, &ocs->entries);
667201c910bSPantelis Antoniou 	return 0;
668201c910bSPantelis Antoniou }
669