brintos

brintos / linux-shallow public Read only

0
0
Text · 27.0 KiB · 110104a Raw
1075 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Support for dynamic device trees.4 *5 * On some platforms, the device tree can be manipulated at runtime.6 * The routines in this section support adding, removing and changing7 * device tree nodes.8 */9 10#define pr_fmt(fmt)	"OF: " fmt11 12#include <linux/cleanup.h>13#include <linux/device.h>14#include <linux/of.h>15#include <linux/spinlock.h>16#include <linux/slab.h>17#include <linux/string.h>18#include <linux/proc_fs.h>19 20#include "of_private.h"21 22static struct device_node *kobj_to_device_node(struct kobject *kobj)23{24	return container_of(kobj, struct device_node, kobj);25}26 27/**28 * of_node_get() - Increment refcount of a node29 * @node:	Node to inc refcount, NULL is supported to simplify writing of30 *		callers31 *32 * Return: The node with refcount incremented.33 */34struct device_node *of_node_get(struct device_node *node)35{36	if (node)37		kobject_get(&node->kobj);38	return node;39}40EXPORT_SYMBOL(of_node_get);41 42/**43 * of_node_put() - Decrement refcount of a node44 * @node:	Node to dec refcount, NULL is supported to simplify writing of45 *		callers46 */47void of_node_put(struct device_node *node)48{49	if (node)50		kobject_put(&node->kobj);51}52EXPORT_SYMBOL(of_node_put);53 54static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);55 56int of_reconfig_notifier_register(struct notifier_block *nb)57{58	return blocking_notifier_chain_register(&of_reconfig_chain, nb);59}60EXPORT_SYMBOL_GPL(of_reconfig_notifier_register);61 62int of_reconfig_notifier_unregister(struct notifier_block *nb)63{64	return blocking_notifier_chain_unregister(&of_reconfig_chain, nb);65}66EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister);67 68static const char *action_names[] = {69	[0] = "INVALID",70	[OF_RECONFIG_ATTACH_NODE] = "ATTACH_NODE",71	[OF_RECONFIG_DETACH_NODE] = "DETACH_NODE",72	[OF_RECONFIG_ADD_PROPERTY] = "ADD_PROPERTY",73	[OF_RECONFIG_REMOVE_PROPERTY] = "REMOVE_PROPERTY",74	[OF_RECONFIG_UPDATE_PROPERTY] = "UPDATE_PROPERTY",75};76 77#define _do_print(func, prefix, action, node, prop, ...) ({	\78	func("changeset: " prefix "%-15s %pOF%s%s\n",		\79	     ##__VA_ARGS__, action_names[action], node,		\80	     prop ? ":" : "", prop ? prop->name : "");		\81})82#define of_changeset_action_err(...) _do_print(pr_err, __VA_ARGS__)83#define of_changeset_action_debug(...) _do_print(pr_debug, __VA_ARGS__)84 85int of_reconfig_notify(unsigned long action, struct of_reconfig_data *p)86{87	int rc;88	struct of_reconfig_data *pr = p;89 90	of_changeset_action_debug("notify: ", action, pr->dn, pr->prop);91 92	rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p);93	return notifier_to_errno(rc);94}95 96/*97 * of_reconfig_get_state_change()	- Returns new state of device98 * @action	- action of the of notifier99 * @arg		- argument of the of notifier100 *101 * Returns the new state of a device based on the notifier used.102 *103 * Return: OF_RECONFIG_CHANGE_REMOVE on device going from enabled to104 * disabled, OF_RECONFIG_CHANGE_ADD on device going from disabled to105 * enabled and OF_RECONFIG_NO_CHANGE on no change.106 */107int of_reconfig_get_state_change(unsigned long action, struct of_reconfig_data *pr)108{109	struct property *prop, *old_prop = NULL;110	int is_status, status_state, old_status_state, prev_state, new_state;111 112	/* figure out if a device should be created or destroyed */113	switch (action) {114	case OF_RECONFIG_ATTACH_NODE:115	case OF_RECONFIG_DETACH_NODE:116		prop = of_find_property(pr->dn, "status", NULL);117		break;118	case OF_RECONFIG_ADD_PROPERTY:119	case OF_RECONFIG_REMOVE_PROPERTY:120		prop = pr->prop;121		break;122	case OF_RECONFIG_UPDATE_PROPERTY:123		prop = pr->prop;124		old_prop = pr->old_prop;125		break;126	default:127		return OF_RECONFIG_NO_CHANGE;128	}129 130	is_status = 0;131	status_state = -1;132	old_status_state = -1;133	prev_state = -1;134	new_state = -1;135 136	if (prop && !strcmp(prop->name, "status")) {137		is_status = 1;138		status_state = !strcmp(prop->value, "okay") ||139			       !strcmp(prop->value, "ok");140		if (old_prop)141			old_status_state = !strcmp(old_prop->value, "okay") ||142					   !strcmp(old_prop->value, "ok");143	}144 145	switch (action) {146	case OF_RECONFIG_ATTACH_NODE:147		prev_state = 0;148		/* -1 & 0 status either missing or okay */149		new_state = status_state != 0;150		break;151	case OF_RECONFIG_DETACH_NODE:152		/* -1 & 0 status either missing or okay */153		prev_state = status_state != 0;154		new_state = 0;155		break;156	case OF_RECONFIG_ADD_PROPERTY:157		if (is_status) {158			/* no status property -> enabled (legacy) */159			prev_state = 1;160			new_state = status_state;161		}162		break;163	case OF_RECONFIG_REMOVE_PROPERTY:164		if (is_status) {165			prev_state = status_state;166			/* no status property -> enabled (legacy) */167			new_state = 1;168		}169		break;170	case OF_RECONFIG_UPDATE_PROPERTY:171		if (is_status) {172			prev_state = old_status_state != 0;173			new_state = status_state != 0;174		}175		break;176	}177 178	if (prev_state == new_state)179		return OF_RECONFIG_NO_CHANGE;180 181	return new_state ? OF_RECONFIG_CHANGE_ADD : OF_RECONFIG_CHANGE_REMOVE;182}183EXPORT_SYMBOL_GPL(of_reconfig_get_state_change);184 185int of_property_notify(int action, struct device_node *np,186		       struct property *prop, struct property *oldprop)187{188	struct of_reconfig_data pr;189 190	/* only call notifiers if the node is attached */191	if (!of_node_is_attached(np))192		return 0;193 194	pr.dn = np;195	pr.prop = prop;196	pr.old_prop = oldprop;197	return of_reconfig_notify(action, &pr);198}199 200static void __of_attach_node(struct device_node *np)201{202	const __be32 *phandle;203	int sz;204	unsigned long flags;205 206	raw_spin_lock_irqsave(&devtree_lock, flags);207 208	if (!of_node_check_flag(np, OF_OVERLAY)) {209		np->name = __of_get_property(np, "name", NULL);210		if (!np->name)211			np->name = "<NULL>";212 213		phandle = __of_get_property(np, "phandle", &sz);214		if (!phandle)215			phandle = __of_get_property(np, "linux,phandle", &sz);216		if (IS_ENABLED(CONFIG_PPC_PSERIES) && !phandle)217			phandle = __of_get_property(np, "ibm,phandle", &sz);218		if (phandle && (sz >= 4))219			np->phandle = be32_to_cpup(phandle);220		else221			np->phandle = 0;222	}223 224	np->child = NULL;225	np->sibling = np->parent->child;226	np->parent->child = np;227	of_node_clear_flag(np, OF_DETACHED);228	np->fwnode.flags |= FWNODE_FLAG_NOT_DEVICE;229 230	raw_spin_unlock_irqrestore(&devtree_lock, flags);231 232	__of_attach_node_sysfs(np);233}234 235/**236 * of_attach_node() - Plug a device node into the tree and global list.237 * @np:		Pointer to the caller's Device Node238 */239int of_attach_node(struct device_node *np)240{241	struct of_reconfig_data rd;242 243	memset(&rd, 0, sizeof(rd));244	rd.dn = np;245 246	mutex_lock(&of_mutex);247	__of_attach_node(np);248	mutex_unlock(&of_mutex);249 250	of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, &rd);251 252	return 0;253}254 255void __of_detach_node(struct device_node *np)256{257	struct device_node *parent;258	unsigned long flags;259 260	raw_spin_lock_irqsave(&devtree_lock, flags);261 262	parent = np->parent;263	if (WARN_ON(of_node_check_flag(np, OF_DETACHED) || !parent)) {264		raw_spin_unlock_irqrestore(&devtree_lock, flags);265		return;266	}267 268	if (parent->child == np)269		parent->child = np->sibling;270	else {271		struct device_node *prevsib;272		for (prevsib = np->parent->child;273		     prevsib->sibling != np;274		     prevsib = prevsib->sibling)275			;276		prevsib->sibling = np->sibling;277	}278 279	of_node_set_flag(np, OF_DETACHED);280 281	/* race with of_find_node_by_phandle() prevented by devtree_lock */282	__of_phandle_cache_inv_entry(np->phandle);283 284	raw_spin_unlock_irqrestore(&devtree_lock, flags);285 286	__of_detach_node_sysfs(np);287}288 289/**290 * of_detach_node() - "Unplug" a node from the device tree.291 * @np:		Pointer to the caller's Device Node292 */293int of_detach_node(struct device_node *np)294{295	struct of_reconfig_data rd;296 297	memset(&rd, 0, sizeof(rd));298	rd.dn = np;299 300	mutex_lock(&of_mutex);301	__of_detach_node(np);302	mutex_unlock(&of_mutex);303 304	of_reconfig_notify(OF_RECONFIG_DETACH_NODE, &rd);305 306	return 0;307}308EXPORT_SYMBOL_GPL(of_detach_node);309 310void __of_prop_free(struct property *prop)311{312	kfree(prop->name);313	kfree(prop->value);314	kfree(prop);315}316 317static void property_list_free(struct property *prop_list)318{319	struct property *prop, *next;320 321	for (prop = prop_list; prop != NULL; prop = next) {322		next = prop->next;323		__of_prop_free(prop);324	}325}326 327/**328 * of_node_release() - release a dynamically allocated node329 * @kobj: kernel object of the node to be released330 *331 * In of_node_put() this function is passed to kref_put() as the destructor.332 */333void of_node_release(struct kobject *kobj)334{335	struct device_node *node = kobj_to_device_node(kobj);336 337	/*338	 * can not use '"%pOF", node' in pr_err() calls from this function339	 * because an of_node_get(node) when refcount is already zero340	 * will result in an error and a stack dump341	 */342 343	/* We should never be releasing nodes that haven't been detached. */344	if (!of_node_check_flag(node, OF_DETACHED)) {345 346		pr_err("ERROR: %s() detected bad of_node_put() on %pOF/%s\n",347			__func__, node->parent, node->full_name);348 349		/*350		 * of unittests will test this path.  Do not print the stack351		 * trace when the error is caused by unittest so that we do352		 * not display what a normal developer might reasonably353		 * consider a real bug.354		 */355		if (!IS_ENABLED(CONFIG_OF_UNITTEST) ||356		    strcmp(node->parent->full_name, "testcase-data")) {357			dump_stack();358			pr_err("ERROR: next of_node_put() on this node will result in a kobject warning 'refcount_t: underflow; use-after-free.'\n");359		}360 361		return;362	}363	if (!of_node_check_flag(node, OF_DYNAMIC))364		return;365 366	if (of_node_check_flag(node, OF_OVERLAY)) {367 368		if (!of_node_check_flag(node, OF_OVERLAY_FREE_CSET)) {369			/* premature refcount of zero, do not free memory */370			pr_err("ERROR: memory leak before free overlay changeset,  %pOF\n",371			       node);372			return;373		}374 375		/*376		 * If node->properties non-empty then properties were added377		 * to this node either by different overlay that has not378		 * yet been removed, or by a non-overlay mechanism.379		 */380		if (node->properties)381			pr_err("ERROR: %s(), unexpected properties in %pOF\n",382			       __func__, node);383	}384 385	if (node->child)386		pr_err("ERROR: %s() unexpected children for %pOF/%s\n",387			__func__, node->parent, node->full_name);388 389	property_list_free(node->properties);390	property_list_free(node->deadprops);391	fwnode_links_purge(of_fwnode_handle(node));392 393	kfree(node->full_name);394	kfree(node->data);395	kfree(node);396}397 398/**399 * __of_prop_dup - Copy a property dynamically.400 * @prop:	Property to copy401 * @allocflags:	Allocation flags (typically pass GFP_KERNEL)402 *403 * Copy a property by dynamically allocating the memory of both the404 * property structure and the property name & contents. The property's405 * flags have the OF_DYNAMIC bit set so that we can differentiate between406 * dynamically allocated properties and not.407 *408 * Return: The newly allocated property or NULL on out of memory error.409 */410struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags)411{412	struct property *new;413 414	new = kzalloc(sizeof(*new), allocflags);415	if (!new)416		return NULL;417 418	/*419	 * NOTE: There is no check for zero length value.420	 * In case of a boolean property, this will allocate a value421	 * of zero bytes. We do this to work around the use422	 * of of_get_property() calls on boolean values.423	 */424	new->name = kstrdup(prop->name, allocflags);425	new->value = kmemdup(prop->value, prop->length, allocflags);426	new->length = prop->length;427	if (!new->name || !new->value)428		goto err_free;429 430	/* mark the property as dynamic */431	of_property_set_flag(new, OF_DYNAMIC);432 433	return new;434 435 err_free:436	__of_prop_free(new);437	return NULL;438}439 440/**441 * __of_node_dup() - Duplicate or create an empty device node dynamically.442 * @np:		if not NULL, contains properties to be duplicated in new node443 * @full_name:	string value to be duplicated into new node's full_name field444 *445 * Create a device tree node, optionally duplicating the properties of446 * another node.  The node data are dynamically allocated and all the node447 * flags have the OF_DYNAMIC & OF_DETACHED bits set.448 *449 * Return: The newly allocated node or NULL on out of memory error.  Use450 * of_node_put() on it when done to free the memory allocated for it.451 */452struct device_node *__of_node_dup(const struct device_node *np,453				  const char *full_name)454{455	struct device_node *node;456 457	node = kzalloc(sizeof(*node), GFP_KERNEL);458	if (!node)459		return NULL;460	node->full_name = kstrdup(full_name, GFP_KERNEL);461	if (!node->full_name) {462		kfree(node);463		return NULL;464	}465 466	of_node_set_flag(node, OF_DYNAMIC);467	of_node_set_flag(node, OF_DETACHED);468	of_node_init(node);469 470	/* Iterate over and duplicate all properties */471	if (np) {472		struct property *pp, *new_pp;473		for_each_property_of_node(np, pp) {474			new_pp = __of_prop_dup(pp, GFP_KERNEL);475			if (!new_pp)476				goto err_prop;477			if (__of_add_property(node, new_pp)) {478				__of_prop_free(new_pp);479				goto err_prop;480			}481		}482	}483	return node;484 485 err_prop:486	of_node_put(node); /* Frees the node and properties */487	return NULL;488}489 490/**491 * of_changeset_create_node - Dynamically create a device node and attach to492 * a given changeset.493 *494 * @ocs: Pointer to changeset495 * @parent: Pointer to parent device node496 * @full_name: Node full name497 *498 * Return: Pointer to the created device node or NULL in case of an error.499 */500struct device_node *of_changeset_create_node(struct of_changeset *ocs,501					     struct device_node *parent,502					     const char *full_name)503{504	struct device_node *np;505	int ret;506 507	np = __of_node_dup(NULL, full_name);508	if (!np)509		return NULL;510	np->parent = parent;511 512	ret = of_changeset_attach_node(ocs, np);513	if (ret) {514		of_node_put(np);515		return NULL;516	}517 518	return np;519}520EXPORT_SYMBOL(of_changeset_create_node);521 522static void __of_changeset_entry_destroy(struct of_changeset_entry *ce)523{524	if (ce->action == OF_RECONFIG_ATTACH_NODE &&525	    of_node_check_flag(ce->np, OF_OVERLAY)) {526		if (kref_read(&ce->np->kobj.kref) > 1) {527			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",528			       kref_read(&ce->np->kobj.kref), ce->np);529		} else {530			of_node_set_flag(ce->np, OF_OVERLAY_FREE_CSET);531		}532	}533 534	of_node_put(ce->np);535	list_del(&ce->node);536	kfree(ce);537}538 539static void __of_changeset_entry_invert(struct of_changeset_entry *ce,540					  struct of_changeset_entry *rce)541{542	memcpy(rce, ce, sizeof(*rce));543 544	switch (ce->action) {545	case OF_RECONFIG_ATTACH_NODE:546		rce->action = OF_RECONFIG_DETACH_NODE;547		break;548	case OF_RECONFIG_DETACH_NODE:549		rce->action = OF_RECONFIG_ATTACH_NODE;550		break;551	case OF_RECONFIG_ADD_PROPERTY:552		rce->action = OF_RECONFIG_REMOVE_PROPERTY;553		break;554	case OF_RECONFIG_REMOVE_PROPERTY:555		rce->action = OF_RECONFIG_ADD_PROPERTY;556		break;557	case OF_RECONFIG_UPDATE_PROPERTY:558		rce->old_prop = ce->prop;559		rce->prop = ce->old_prop;560		/* update was used but original property did not exist */561		if (!rce->prop) {562			rce->action = OF_RECONFIG_REMOVE_PROPERTY;563			rce->prop = ce->prop;564		}565		break;566	}567}568 569static int __of_changeset_entry_notify(struct of_changeset_entry *ce,570		bool revert)571{572	struct of_reconfig_data rd;573	struct of_changeset_entry ce_inverted;574	int ret = 0;575 576	if (revert) {577		__of_changeset_entry_invert(ce, &ce_inverted);578		ce = &ce_inverted;579	}580 581	switch (ce->action) {582	case OF_RECONFIG_ATTACH_NODE:583	case OF_RECONFIG_DETACH_NODE:584		memset(&rd, 0, sizeof(rd));585		rd.dn = ce->np;586		ret = of_reconfig_notify(ce->action, &rd);587		break;588	case OF_RECONFIG_ADD_PROPERTY:589	case OF_RECONFIG_REMOVE_PROPERTY:590	case OF_RECONFIG_UPDATE_PROPERTY:591		ret = of_property_notify(ce->action, ce->np, ce->prop, ce->old_prop);592		break;593	default:594		pr_err("invalid devicetree changeset action: %i\n",595			(int)ce->action);596		ret = -EINVAL;597	}598 599	if (ret)600		pr_err("changeset notifier error @%pOF\n", ce->np);601	return ret;602}603 604static int __of_changeset_entry_apply(struct of_changeset_entry *ce)605{606	int ret = 0;607 608	of_changeset_action_debug("apply: ", ce->action, ce->np, ce->prop);609 610	switch (ce->action) {611	case OF_RECONFIG_ATTACH_NODE:612		__of_attach_node(ce->np);613		break;614	case OF_RECONFIG_DETACH_NODE:615		__of_detach_node(ce->np);616		break;617	case OF_RECONFIG_ADD_PROPERTY:618		ret = __of_add_property(ce->np, ce->prop);619		break;620	case OF_RECONFIG_REMOVE_PROPERTY:621		ret = __of_remove_property(ce->np, ce->prop);622		break;623 624	case OF_RECONFIG_UPDATE_PROPERTY:625		ret = __of_update_property(ce->np, ce->prop, &ce->old_prop);626		break;627	default:628		ret = -EINVAL;629	}630 631	if (ret) {632		of_changeset_action_err("apply failed: ", ce->action, ce->np, ce->prop);633		return ret;634	}635 636	return 0;637}638 639static inline int __of_changeset_entry_revert(struct of_changeset_entry *ce)640{641	struct of_changeset_entry ce_inverted;642 643	__of_changeset_entry_invert(ce, &ce_inverted);644	return __of_changeset_entry_apply(&ce_inverted);645}646 647/**648 * of_changeset_init - Initialize a changeset for use649 *650 * @ocs:	changeset pointer651 *652 * Initialize a changeset structure653 */654void of_changeset_init(struct of_changeset *ocs)655{656	memset(ocs, 0, sizeof(*ocs));657	INIT_LIST_HEAD(&ocs->entries);658}659EXPORT_SYMBOL_GPL(of_changeset_init);660 661/**662 * of_changeset_destroy - Destroy a changeset663 *664 * @ocs:	changeset pointer665 *666 * Destroys a changeset. Note that if a changeset is applied,667 * its changes to the tree cannot be reverted.668 */669void of_changeset_destroy(struct of_changeset *ocs)670{671	struct of_changeset_entry *ce, *cen;672 673	/*674	 * When a device is deleted, the device links to/from it are also queued675	 * for deletion. Until these device links are freed, the devices676	 * themselves aren't freed. If the device being deleted is due to an677	 * overlay change, this device might be holding a reference to a device678	 * node that will be freed. So, wait until all already pending device679	 * links are deleted before freeing a device node. This ensures we don't680	 * free any device node that has a non-zero reference count.681	 */682	device_link_wait_removal();683 684	list_for_each_entry_safe_reverse(ce, cen, &ocs->entries, node)685		__of_changeset_entry_destroy(ce);686}687EXPORT_SYMBOL_GPL(of_changeset_destroy);688 689/*690 * Apply the changeset entries in @ocs.691 * If apply fails, an attempt is made to revert the entries that were692 * successfully applied.693 *694 * If multiple revert errors occur then only the final revert error is reported.695 *696 * Returns 0 on success, a negative error value in case of an error.697 * If a revert error occurs, it is returned in *ret_revert.698 */699int __of_changeset_apply_entries(struct of_changeset *ocs, int *ret_revert)700{701	struct of_changeset_entry *ce;702	int ret, ret_tmp;703 704	pr_debug("changeset: applying...\n");705	list_for_each_entry(ce, &ocs->entries, node) {706		ret = __of_changeset_entry_apply(ce);707		if (ret) {708			pr_err("Error applying changeset (%d)\n", ret);709			list_for_each_entry_continue_reverse(ce, &ocs->entries,710							     node) {711				ret_tmp = __of_changeset_entry_revert(ce);712				if (ret_tmp)713					*ret_revert = ret_tmp;714			}715			return ret;716		}717	}718 719	return 0;720}721 722/*723 * Returns 0 on success, a negative error value in case of an error.724 *725 * If multiple changeset entry notification errors occur then only the726 * final notification error is reported.727 */728int __of_changeset_apply_notify(struct of_changeset *ocs)729{730	struct of_changeset_entry *ce;731	int ret = 0, ret_tmp;732 733	pr_debug("changeset: emitting notifiers.\n");734 735	/* drop the global lock while emitting notifiers */736	mutex_unlock(&of_mutex);737	list_for_each_entry(ce, &ocs->entries, node) {738		ret_tmp = __of_changeset_entry_notify(ce, 0);739		if (ret_tmp)740			ret = ret_tmp;741	}742	mutex_lock(&of_mutex);743	pr_debug("changeset: notifiers sent.\n");744 745	return ret;746}747 748/*749 * Returns 0 on success, a negative error value in case of an error.750 *751 * If a changeset entry apply fails, an attempt is made to revert any752 * previous entries in the changeset.  If any of the reverts fails,753 * that failure is not reported.  Thus the state of the device tree754 * is unknown if an apply error occurs.755 */756static int __of_changeset_apply(struct of_changeset *ocs)757{758	int ret, ret_revert = 0;759 760	ret = __of_changeset_apply_entries(ocs, &ret_revert);761	if (!ret)762		ret = __of_changeset_apply_notify(ocs);763 764	return ret;765}766 767/**768 * of_changeset_apply - Applies a changeset769 *770 * @ocs:	changeset pointer771 *772 * Applies a changeset to the live tree.773 * Any side-effects of live tree state changes are applied here on774 * success, like creation/destruction of devices and side-effects775 * like creation of sysfs properties and directories.776 *777 * Return: 0 on success, a negative error value in case of an error.778 * On error the partially applied effects are reverted.779 */780int of_changeset_apply(struct of_changeset *ocs)781{782	int ret;783 784	mutex_lock(&of_mutex);785	ret = __of_changeset_apply(ocs);786	mutex_unlock(&of_mutex);787 788	return ret;789}790EXPORT_SYMBOL_GPL(of_changeset_apply);791 792/*793 * Revert the changeset entries in @ocs.794 * If revert fails, an attempt is made to re-apply the entries that were795 * successfully removed.796 *797 * If multiple re-apply errors occur then only the final apply error is798 * reported.799 *800 * Returns 0 on success, a negative error value in case of an error.801 * If an apply error occurs, it is returned in *ret_apply.802 */803int __of_changeset_revert_entries(struct of_changeset *ocs, int *ret_apply)804{805	struct of_changeset_entry *ce;806	int ret, ret_tmp;807 808	pr_debug("changeset: reverting...\n");809	list_for_each_entry_reverse(ce, &ocs->entries, node) {810		ret = __of_changeset_entry_revert(ce);811		if (ret) {812			pr_err("Error reverting changeset (%d)\n", ret);813			list_for_each_entry_continue(ce, &ocs->entries, node) {814				ret_tmp = __of_changeset_entry_apply(ce);815				if (ret_tmp)816					*ret_apply = ret_tmp;817			}818			return ret;819		}820	}821 822	return 0;823}824 825/*826 * If multiple changeset entry notification errors occur then only the827 * final notification error is reported.828 */829int __of_changeset_revert_notify(struct of_changeset *ocs)830{831	struct of_changeset_entry *ce;832	int ret = 0, ret_tmp;833 834	pr_debug("changeset: emitting notifiers.\n");835 836	/* drop the global lock while emitting notifiers */837	mutex_unlock(&of_mutex);838	list_for_each_entry_reverse(ce, &ocs->entries, node) {839		ret_tmp = __of_changeset_entry_notify(ce, 1);840		if (ret_tmp)841			ret = ret_tmp;842	}843	mutex_lock(&of_mutex);844	pr_debug("changeset: notifiers sent.\n");845 846	return ret;847}848 849static int __of_changeset_revert(struct of_changeset *ocs)850{851	int ret, ret_reply;852 853	ret_reply = 0;854	ret = __of_changeset_revert_entries(ocs, &ret_reply);855 856	if (!ret)857		ret = __of_changeset_revert_notify(ocs);858 859	return ret;860}861 862/**863 * of_changeset_revert - Reverts an applied changeset864 *865 * @ocs:	changeset pointer866 *867 * Reverts a changeset returning the state of the tree to what it868 * was before the application.869 * Any side-effects like creation/destruction of devices and870 * removal of sysfs properties and directories are applied.871 *872 * Return: 0 on success, a negative error value in case of an error.873 */874int of_changeset_revert(struct of_changeset *ocs)875{876	int ret;877 878	mutex_lock(&of_mutex);879	ret = __of_changeset_revert(ocs);880	mutex_unlock(&of_mutex);881 882	return ret;883}884EXPORT_SYMBOL_GPL(of_changeset_revert);885 886/**887 * of_changeset_action - Add an action to the tail of the changeset list888 *889 * @ocs:	changeset pointer890 * @action:	action to perform891 * @np:		Pointer to device node892 * @prop:	Pointer to property893 *894 * On action being one of:895 * + OF_RECONFIG_ATTACH_NODE896 * + OF_RECONFIG_DETACH_NODE,897 * + OF_RECONFIG_ADD_PROPERTY898 * + OF_RECONFIG_REMOVE_PROPERTY,899 * + OF_RECONFIG_UPDATE_PROPERTY900 *901 * Return: 0 on success, a negative error value in case of an error.902 */903int of_changeset_action(struct of_changeset *ocs, unsigned long action,904		struct device_node *np, struct property *prop)905{906	struct of_changeset_entry *ce;907 908	if (WARN_ON(action >= ARRAY_SIZE(action_names)))909		return -EINVAL;910 911	ce = kzalloc(sizeof(*ce), GFP_KERNEL);912	if (!ce)913		return -ENOMEM;914 915	/* get a reference to the node */916	ce->action = action;917	ce->np = of_node_get(np);918	ce->prop = prop;919 920	/* add it to the list */921	list_add_tail(&ce->node, &ocs->entries);922	return 0;923}924EXPORT_SYMBOL_GPL(of_changeset_action);925 926static int of_changeset_add_prop_helper(struct of_changeset *ocs,927					struct device_node *np,928					const struct property *pp)929{930	struct property *new_pp;931	int ret;932 933	new_pp = __of_prop_dup(pp, GFP_KERNEL);934	if (!new_pp)935		return -ENOMEM;936 937	ret = of_changeset_add_property(ocs, np, new_pp);938	if (ret)939		__of_prop_free(new_pp);940 941	return ret;942}943 944/**945 * of_changeset_add_prop_string - Add a string property to a changeset946 *947 * @ocs:	changeset pointer948 * @np:		device node pointer949 * @prop_name:	name of the property to be added950 * @str:	pointer to null terminated string951 *952 * Create a string property and add it to a changeset.953 *954 * Return: 0 on success, a negative error value in case of an error.955 */956int of_changeset_add_prop_string(struct of_changeset *ocs,957				 struct device_node *np,958				 const char *prop_name, const char *str)959{960	struct property prop;961 962	prop.name = (char *)prop_name;963	prop.length = strlen(str) + 1;964	prop.value = (void *)str;965 966	return of_changeset_add_prop_helper(ocs, np, &prop);967}968EXPORT_SYMBOL_GPL(of_changeset_add_prop_string);969 970/**971 * of_changeset_add_prop_string_array - Add a string list property to972 * a changeset973 *974 * @ocs:	changeset pointer975 * @np:		device node pointer976 * @prop_name:	name of the property to be added977 * @str_array:	pointer to an array of null terminated strings978 * @sz:		number of string array elements979 *980 * Create a string list property and add it to a changeset.981 *982 * Return: 0 on success, a negative error value in case of an error.983 */984int of_changeset_add_prop_string_array(struct of_changeset *ocs,985				       struct device_node *np,986				       const char *prop_name,987				       const char * const *str_array, size_t sz)988{989	struct property prop;990	int i, ret;991	char *vp;992 993	prop.name = (char *)prop_name;994 995	prop.length = 0;996	for (i = 0; i < sz; i++)997		prop.length += strlen(str_array[i]) + 1;998 999	prop.value = kmalloc(prop.length, GFP_KERNEL);1000	if (!prop.value)1001		return -ENOMEM;1002 1003	vp = prop.value;1004	for (i = 0; i < sz; i++) {1005		vp += snprintf(vp, (char *)prop.value + prop.length - vp, "%s",1006			       str_array[i]) + 1;1007	}1008	ret = of_changeset_add_prop_helper(ocs, np, &prop);1009	kfree(prop.value);1010 1011	return ret;1012}1013EXPORT_SYMBOL_GPL(of_changeset_add_prop_string_array);1014 1015/**1016 * of_changeset_add_prop_u32_array - Add a property of 32 bit integers1017 * property to a changeset1018 *1019 * @ocs:	changeset pointer1020 * @np:		device node pointer1021 * @prop_name:	name of the property to be added1022 * @array:	pointer to an array of 32 bit integers1023 * @sz:		number of array elements1024 *1025 * Create a property of 32 bit integers and add it to a changeset.1026 *1027 * Return: 0 on success, a negative error value in case of an error.1028 */1029int of_changeset_add_prop_u32_array(struct of_changeset *ocs,1030				    struct device_node *np,1031				    const char *prop_name,1032				    const u32 *array, size_t sz)1033{1034	struct property prop;1035	__be32 *val __free(kfree) = kcalloc(sz, sizeof(__be32), GFP_KERNEL);1036	int i;1037 1038	if (!val)1039		return -ENOMEM;1040 1041	for (i = 0; i < sz; i++)1042		val[i] = cpu_to_be32(array[i]);1043	prop.name = (char *)prop_name;1044	prop.length = sizeof(u32) * sz;1045	prop.value = (void *)val;1046 1047	return of_changeset_add_prop_helper(ocs, np, &prop);1048}1049EXPORT_SYMBOL_GPL(of_changeset_add_prop_u32_array);1050 1051/**1052 * of_changeset_add_prop_bool - Add a boolean property (i.e. a property without1053 * any values) to a changeset.1054 *1055 * @ocs:	changeset pointer1056 * @np:		device node pointer1057 * @prop_name:	name of the property to be added1058 *1059 * Create a boolean property and add it to a changeset.1060 *1061 * Return: 0 on success, a negative error value in case of an error.1062 */1063int of_changeset_add_prop_bool(struct of_changeset *ocs, struct device_node *np,1064			       const char *prop_name)1065{1066	struct property prop;1067 1068	prop.name = (char *)prop_name;1069	prop.length = 0;1070	prop.value = NULL;1071 1072	return of_changeset_add_prop_helper(ocs, np, &prop);1073}1074EXPORT_SYMBOL_GPL(of_changeset_add_prop_bool);1075