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