Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Support for dynamic device trees.
0004  *
0005  * On some platforms, the device tree can be manipulated at runtime.
0006  * The routines in this section support adding, removing and changing
0007  * device tree nodes.
0008  */
0009 
0010 #define pr_fmt(fmt) "OF: " fmt
0011 
0012 #include <linux/of.h>
0013 #include <linux/spinlock.h>
0014 #include <linux/slab.h>
0015 #include <linux/string.h>
0016 #include <linux/proc_fs.h>
0017 
0018 #include "of_private.h"
0019 
0020 static struct device_node *kobj_to_device_node(struct kobject *kobj)
0021 {
0022     return container_of(kobj, struct device_node, kobj);
0023 }
0024 
0025 /**
0026  * of_node_get() - Increment refcount of a node
0027  * @node:   Node to inc refcount, NULL is supported to simplify writing of
0028  *      callers
0029  *
0030  * Return: The node with refcount incremented.
0031  */
0032 struct device_node *of_node_get(struct device_node *node)
0033 {
0034     if (node)
0035         kobject_get(&node->kobj);
0036     return node;
0037 }
0038 EXPORT_SYMBOL(of_node_get);
0039 
0040 /**
0041  * of_node_put() - Decrement refcount of a node
0042  * @node:   Node to dec refcount, NULL is supported to simplify writing of
0043  *      callers
0044  */
0045 void of_node_put(struct device_node *node)
0046 {
0047     if (node)
0048         kobject_put(&node->kobj);
0049 }
0050 EXPORT_SYMBOL(of_node_put);
0051 
0052 static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);
0053 
0054 int of_reconfig_notifier_register(struct notifier_block *nb)
0055 {
0056     return blocking_notifier_chain_register(&of_reconfig_chain, nb);
0057 }
0058 EXPORT_SYMBOL_GPL(of_reconfig_notifier_register);
0059 
0060 int of_reconfig_notifier_unregister(struct notifier_block *nb)
0061 {
0062     return blocking_notifier_chain_unregister(&of_reconfig_chain, nb);
0063 }
0064 EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister);
0065 
0066 #ifdef DEBUG
0067 const char *action_names[] = {
0068     [OF_RECONFIG_ATTACH_NODE] = "ATTACH_NODE",
0069     [OF_RECONFIG_DETACH_NODE] = "DETACH_NODE",
0070     [OF_RECONFIG_ADD_PROPERTY] = "ADD_PROPERTY",
0071     [OF_RECONFIG_REMOVE_PROPERTY] = "REMOVE_PROPERTY",
0072     [OF_RECONFIG_UPDATE_PROPERTY] = "UPDATE_PROPERTY",
0073 };
0074 #endif
0075 
0076 int of_reconfig_notify(unsigned long action, struct of_reconfig_data *p)
0077 {
0078     int rc;
0079 #ifdef DEBUG
0080     struct of_reconfig_data *pr = p;
0081 
0082     switch (action) {
0083     case OF_RECONFIG_ATTACH_NODE:
0084     case OF_RECONFIG_DETACH_NODE:
0085         pr_debug("notify %-15s %pOF\n", action_names[action],
0086             pr->dn);
0087         break;
0088     case OF_RECONFIG_ADD_PROPERTY:
0089     case OF_RECONFIG_REMOVE_PROPERTY:
0090     case OF_RECONFIG_UPDATE_PROPERTY:
0091         pr_debug("notify %-15s %pOF:%s\n", action_names[action],
0092             pr->dn, pr->prop->name);
0093         break;
0094 
0095     }
0096 #endif
0097     rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p);
0098     return notifier_to_errno(rc);
0099 }
0100 
0101 /*
0102  * of_reconfig_get_state_change()   - Returns new state of device
0103  * @action  - action of the of notifier
0104  * @arg     - argument of the of notifier
0105  *
0106  * Returns the new state of a device based on the notifier used.
0107  *
0108  * Return: 0 on device going from enabled to disabled, 1 on device
0109  * going from disabled to enabled and -1 on no change.
0110  */
0111 int of_reconfig_get_state_change(unsigned long action, struct of_reconfig_data *pr)
0112 {
0113     struct property *prop, *old_prop = NULL;
0114     int is_status, status_state, old_status_state, prev_state, new_state;
0115 
0116     /* figure out if a device should be created or destroyed */
0117     switch (action) {
0118     case OF_RECONFIG_ATTACH_NODE:
0119     case OF_RECONFIG_DETACH_NODE:
0120         prop = of_find_property(pr->dn, "status", NULL);
0121         break;
0122     case OF_RECONFIG_ADD_PROPERTY:
0123     case OF_RECONFIG_REMOVE_PROPERTY:
0124         prop = pr->prop;
0125         break;
0126     case OF_RECONFIG_UPDATE_PROPERTY:
0127         prop = pr->prop;
0128         old_prop = pr->old_prop;
0129         break;
0130     default:
0131         return OF_RECONFIG_NO_CHANGE;
0132     }
0133 
0134     is_status = 0;
0135     status_state = -1;
0136     old_status_state = -1;
0137     prev_state = -1;
0138     new_state = -1;
0139 
0140     if (prop && !strcmp(prop->name, "status")) {
0141         is_status = 1;
0142         status_state = !strcmp(prop->value, "okay") ||
0143                    !strcmp(prop->value, "ok");
0144         if (old_prop)
0145             old_status_state = !strcmp(old_prop->value, "okay") ||
0146                        !strcmp(old_prop->value, "ok");
0147     }
0148 
0149     switch (action) {
0150     case OF_RECONFIG_ATTACH_NODE:
0151         prev_state = 0;
0152         /* -1 & 0 status either missing or okay */
0153         new_state = status_state != 0;
0154         break;
0155     case OF_RECONFIG_DETACH_NODE:
0156         /* -1 & 0 status either missing or okay */
0157         prev_state = status_state != 0;
0158         new_state = 0;
0159         break;
0160     case OF_RECONFIG_ADD_PROPERTY:
0161         if (is_status) {
0162             /* no status property -> enabled (legacy) */
0163             prev_state = 1;
0164             new_state = status_state;
0165         }
0166         break;
0167     case OF_RECONFIG_REMOVE_PROPERTY:
0168         if (is_status) {
0169             prev_state = status_state;
0170             /* no status property -> enabled (legacy) */
0171             new_state = 1;
0172         }
0173         break;
0174     case OF_RECONFIG_UPDATE_PROPERTY:
0175         if (is_status) {
0176             prev_state = old_status_state != 0;
0177             new_state = status_state != 0;
0178         }
0179         break;
0180     }
0181 
0182     if (prev_state == new_state)
0183         return OF_RECONFIG_NO_CHANGE;
0184 
0185     return new_state ? OF_RECONFIG_CHANGE_ADD : OF_RECONFIG_CHANGE_REMOVE;
0186 }
0187 EXPORT_SYMBOL_GPL(of_reconfig_get_state_change);
0188 
0189 int of_property_notify(int action, struct device_node *np,
0190                struct property *prop, struct property *oldprop)
0191 {
0192     struct of_reconfig_data pr;
0193 
0194     /* only call notifiers if the node is attached */
0195     if (!of_node_is_attached(np))
0196         return 0;
0197 
0198     pr.dn = np;
0199     pr.prop = prop;
0200     pr.old_prop = oldprop;
0201     return of_reconfig_notify(action, &pr);
0202 }
0203 
0204 static void __of_attach_node(struct device_node *np)
0205 {
0206     const __be32 *phandle;
0207     int sz;
0208 
0209     if (!of_node_check_flag(np, OF_OVERLAY)) {
0210         np->name = __of_get_property(np, "name", NULL);
0211         if (!np->name)
0212             np->name = "<NULL>";
0213 
0214         phandle = __of_get_property(np, "phandle", &sz);
0215         if (!phandle)
0216             phandle = __of_get_property(np, "linux,phandle", &sz);
0217         if (IS_ENABLED(CONFIG_PPC_PSERIES) && !phandle)
0218             phandle = __of_get_property(np, "ibm,phandle", &sz);
0219         if (phandle && (sz >= 4))
0220             np->phandle = be32_to_cpup(phandle);
0221         else
0222             np->phandle = 0;
0223     }
0224 
0225     np->child = NULL;
0226     np->sibling = np->parent->child;
0227     np->parent->child = np;
0228     of_node_clear_flag(np, OF_DETACHED);
0229 }
0230 
0231 /**
0232  * of_attach_node() - Plug a device node into the tree and global list.
0233  * @np:     Pointer to the caller's Device Node
0234  */
0235 int of_attach_node(struct device_node *np)
0236 {
0237     struct of_reconfig_data rd;
0238     unsigned long flags;
0239 
0240     memset(&rd, 0, sizeof(rd));
0241     rd.dn = np;
0242 
0243     mutex_lock(&of_mutex);
0244     raw_spin_lock_irqsave(&devtree_lock, flags);
0245     __of_attach_node(np);
0246     raw_spin_unlock_irqrestore(&devtree_lock, flags);
0247 
0248     __of_attach_node_sysfs(np);
0249     mutex_unlock(&of_mutex);
0250 
0251     of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, &rd);
0252 
0253     return 0;
0254 }
0255 
0256 void __of_detach_node(struct device_node *np)
0257 {
0258     struct device_node *parent;
0259 
0260     if (WARN_ON(of_node_check_flag(np, OF_DETACHED)))
0261         return;
0262 
0263     parent = np->parent;
0264     if (WARN_ON(!parent))
0265         return;
0266 
0267     if (parent->child == np)
0268         parent->child = np->sibling;
0269     else {
0270         struct device_node *prevsib;
0271         for (prevsib = np->parent->child;
0272              prevsib->sibling != np;
0273              prevsib = prevsib->sibling)
0274             ;
0275         prevsib->sibling = np->sibling;
0276     }
0277 
0278     of_node_set_flag(np, OF_DETACHED);
0279 
0280     /* race with of_find_node_by_phandle() prevented by devtree_lock */
0281     __of_phandle_cache_inv_entry(np->phandle);
0282 }
0283 
0284 /**
0285  * of_detach_node() - "Unplug" a node from the device tree.
0286  * @np:     Pointer to the caller's Device Node
0287  */
0288 int of_detach_node(struct device_node *np)
0289 {
0290     struct of_reconfig_data rd;
0291     unsigned long flags;
0292 
0293     memset(&rd, 0, sizeof(rd));
0294     rd.dn = np;
0295 
0296     mutex_lock(&of_mutex);
0297     raw_spin_lock_irqsave(&devtree_lock, flags);
0298     __of_detach_node(np);
0299     raw_spin_unlock_irqrestore(&devtree_lock, flags);
0300 
0301     __of_detach_node_sysfs(np);
0302     mutex_unlock(&of_mutex);
0303 
0304     of_reconfig_notify(OF_RECONFIG_DETACH_NODE, &rd);
0305 
0306     return 0;
0307 }
0308 EXPORT_SYMBOL_GPL(of_detach_node);
0309 
0310 static void property_list_free(struct property *prop_list)
0311 {
0312     struct property *prop, *next;
0313 
0314     for (prop = prop_list; prop != NULL; prop = next) {
0315         next = prop->next;
0316         kfree(prop->name);
0317         kfree(prop->value);
0318         kfree(prop);
0319     }
0320 }
0321 
0322 /**
0323  * of_node_release() - release a dynamically allocated node
0324  * @kobj: kernel object of the node to be released
0325  *
0326  * In of_node_put() this function is passed to kref_put() as the destructor.
0327  */
0328 void of_node_release(struct kobject *kobj)
0329 {
0330     struct device_node *node = kobj_to_device_node(kobj);
0331 
0332     /* We should never be releasing nodes that haven't been detached. */
0333     if (!of_node_check_flag(node, OF_DETACHED)) {
0334         pr_err("ERROR: Bad of_node_put() on %pOF\n", node);
0335         dump_stack();
0336         return;
0337     }
0338     if (!of_node_check_flag(node, OF_DYNAMIC))
0339         return;
0340 
0341     if (of_node_check_flag(node, OF_OVERLAY)) {
0342 
0343         if (!of_node_check_flag(node, OF_OVERLAY_FREE_CSET)) {
0344             /* premature refcount of zero, do not free memory */
0345             pr_err("ERROR: memory leak before free overlay changeset,  %pOF\n",
0346                    node);
0347             return;
0348         }
0349 
0350         /*
0351          * If node->properties non-empty then properties were added
0352          * to this node either by different overlay that has not
0353          * yet been removed, or by a non-overlay mechanism.
0354          */
0355         if (node->properties)
0356             pr_err("ERROR: %s(), unexpected properties in %pOF\n",
0357                    __func__, node);
0358     }
0359 
0360     property_list_free(node->properties);
0361     property_list_free(node->deadprops);
0362     fwnode_links_purge(of_fwnode_handle(node));
0363 
0364     kfree(node->full_name);
0365     kfree(node->data);
0366     kfree(node);
0367 }
0368 
0369 /**
0370  * __of_prop_dup - Copy a property dynamically.
0371  * @prop:   Property to copy
0372  * @allocflags: Allocation flags (typically pass GFP_KERNEL)
0373  *
0374  * Copy a property by dynamically allocating the memory of both the
0375  * property structure and the property name & contents. The property's
0376  * flags have the OF_DYNAMIC bit set so that we can differentiate between
0377  * dynamically allocated properties and not.
0378  *
0379  * Return: The newly allocated property or NULL on out of memory error.
0380  */
0381 struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags)
0382 {
0383     struct property *new;
0384 
0385     new = kzalloc(sizeof(*new), allocflags);
0386     if (!new)
0387         return NULL;
0388 
0389     /*
0390      * NOTE: There is no check for zero length value.
0391      * In case of a boolean property, this will allocate a value
0392      * of zero bytes. We do this to work around the use
0393      * of of_get_property() calls on boolean values.
0394      */
0395     new->name = kstrdup(prop->name, allocflags);
0396     new->value = kmemdup(prop->value, prop->length, allocflags);
0397     new->length = prop->length;
0398     if (!new->name || !new->value)
0399         goto err_free;
0400 
0401     /* mark the property as dynamic */
0402     of_property_set_flag(new, OF_DYNAMIC);
0403 
0404     return new;
0405 
0406  err_free:
0407     kfree(new->name);
0408     kfree(new->value);
0409     kfree(new);
0410     return NULL;
0411 }
0412 
0413 /**
0414  * __of_node_dup() - Duplicate or create an empty device node dynamically.
0415  * @np:     if not NULL, contains properties to be duplicated in new node
0416  * @full_name:  string value to be duplicated into new node's full_name field
0417  *
0418  * Create a device tree node, optionally duplicating the properties of
0419  * another node.  The node data are dynamically allocated and all the node
0420  * flags have the OF_DYNAMIC & OF_DETACHED bits set.
0421  *
0422  * Return: The newly allocated node or NULL on out of memory error.
0423  */
0424 struct device_node *__of_node_dup(const struct device_node *np,
0425                   const char *full_name)
0426 {
0427     struct device_node *node;
0428 
0429     node = kzalloc(sizeof(*node), GFP_KERNEL);
0430     if (!node)
0431         return NULL;
0432     node->full_name = kstrdup(full_name, GFP_KERNEL);
0433     if (!node->full_name) {
0434         kfree(node);
0435         return NULL;
0436     }
0437 
0438     of_node_set_flag(node, OF_DYNAMIC);
0439     of_node_set_flag(node, OF_DETACHED);
0440     of_node_init(node);
0441 
0442     /* Iterate over and duplicate all properties */
0443     if (np) {
0444         struct property *pp, *new_pp;
0445         for_each_property_of_node(np, pp) {
0446             new_pp = __of_prop_dup(pp, GFP_KERNEL);
0447             if (!new_pp)
0448                 goto err_prop;
0449             if (__of_add_property(node, new_pp)) {
0450                 kfree(new_pp->name);
0451                 kfree(new_pp->value);
0452                 kfree(new_pp);
0453                 goto err_prop;
0454             }
0455         }
0456     }
0457     return node;
0458 
0459  err_prop:
0460     of_node_put(node); /* Frees the node and properties */
0461     return NULL;
0462 }
0463 
0464 static void __of_changeset_entry_destroy(struct of_changeset_entry *ce)
0465 {
0466     if (ce->action == OF_RECONFIG_ATTACH_NODE &&
0467         of_node_check_flag(ce->np, OF_OVERLAY)) {
0468         if (kref_read(&ce->np->kobj.kref) > 1) {
0469             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",
0470                    kref_read(&ce->np->kobj.kref), ce->np);
0471         } else {
0472             of_node_set_flag(ce->np, OF_OVERLAY_FREE_CSET);
0473         }
0474     }
0475 
0476     of_node_put(ce->np);
0477     list_del(&ce->node);
0478     kfree(ce);
0479 }
0480 
0481 #ifdef DEBUG
0482 static void __of_changeset_entry_dump(struct of_changeset_entry *ce)
0483 {
0484     switch (ce->action) {
0485     case OF_RECONFIG_ADD_PROPERTY:
0486     case OF_RECONFIG_REMOVE_PROPERTY:
0487     case OF_RECONFIG_UPDATE_PROPERTY:
0488         pr_debug("cset<%p> %-15s %pOF/%s\n", ce, action_names[ce->action],
0489             ce->np, ce->prop->name);
0490         break;
0491     case OF_RECONFIG_ATTACH_NODE:
0492     case OF_RECONFIG_DETACH_NODE:
0493         pr_debug("cset<%p> %-15s %pOF\n", ce, action_names[ce->action],
0494             ce->np);
0495         break;
0496     }
0497 }
0498 #else
0499 static inline void __of_changeset_entry_dump(struct of_changeset_entry *ce)
0500 {
0501     /* empty */
0502 }
0503 #endif
0504 
0505 static void __of_changeset_entry_invert(struct of_changeset_entry *ce,
0506                       struct of_changeset_entry *rce)
0507 {
0508     memcpy(rce, ce, sizeof(*rce));
0509 
0510     switch (ce->action) {
0511     case OF_RECONFIG_ATTACH_NODE:
0512         rce->action = OF_RECONFIG_DETACH_NODE;
0513         break;
0514     case OF_RECONFIG_DETACH_NODE:
0515         rce->action = OF_RECONFIG_ATTACH_NODE;
0516         break;
0517     case OF_RECONFIG_ADD_PROPERTY:
0518         rce->action = OF_RECONFIG_REMOVE_PROPERTY;
0519         break;
0520     case OF_RECONFIG_REMOVE_PROPERTY:
0521         rce->action = OF_RECONFIG_ADD_PROPERTY;
0522         break;
0523     case OF_RECONFIG_UPDATE_PROPERTY:
0524         rce->old_prop = ce->prop;
0525         rce->prop = ce->old_prop;
0526         /* update was used but original property did not exist */
0527         if (!rce->prop) {
0528             rce->action = OF_RECONFIG_REMOVE_PROPERTY;
0529             rce->prop = ce->prop;
0530         }
0531         break;
0532     }
0533 }
0534 
0535 static int __of_changeset_entry_notify(struct of_changeset_entry *ce,
0536         bool revert)
0537 {
0538     struct of_reconfig_data rd;
0539     struct of_changeset_entry ce_inverted;
0540     int ret = 0;
0541 
0542     if (revert) {
0543         __of_changeset_entry_invert(ce, &ce_inverted);
0544         ce = &ce_inverted;
0545     }
0546 
0547     switch (ce->action) {
0548     case OF_RECONFIG_ATTACH_NODE:
0549     case OF_RECONFIG_DETACH_NODE:
0550         memset(&rd, 0, sizeof(rd));
0551         rd.dn = ce->np;
0552         ret = of_reconfig_notify(ce->action, &rd);
0553         break;
0554     case OF_RECONFIG_ADD_PROPERTY:
0555     case OF_RECONFIG_REMOVE_PROPERTY:
0556     case OF_RECONFIG_UPDATE_PROPERTY:
0557         ret = of_property_notify(ce->action, ce->np, ce->prop, ce->old_prop);
0558         break;
0559     default:
0560         pr_err("invalid devicetree changeset action: %i\n",
0561             (int)ce->action);
0562         ret = -EINVAL;
0563     }
0564 
0565     if (ret)
0566         pr_err("changeset notifier error @%pOF\n", ce->np);
0567     return ret;
0568 }
0569 
0570 static int __of_changeset_entry_apply(struct of_changeset_entry *ce)
0571 {
0572     struct property *old_prop, **propp;
0573     unsigned long flags;
0574     int ret = 0;
0575 
0576     __of_changeset_entry_dump(ce);
0577 
0578     raw_spin_lock_irqsave(&devtree_lock, flags);
0579     switch (ce->action) {
0580     case OF_RECONFIG_ATTACH_NODE:
0581         __of_attach_node(ce->np);
0582         break;
0583     case OF_RECONFIG_DETACH_NODE:
0584         __of_detach_node(ce->np);
0585         break;
0586     case OF_RECONFIG_ADD_PROPERTY:
0587         /* If the property is in deadprops then it must be removed */
0588         for (propp = &ce->np->deadprops; *propp; propp = &(*propp)->next) {
0589             if (*propp == ce->prop) {
0590                 *propp = ce->prop->next;
0591                 ce->prop->next = NULL;
0592                 break;
0593             }
0594         }
0595 
0596         ret = __of_add_property(ce->np, ce->prop);
0597         if (ret) {
0598             pr_err("changeset: add_property failed @%pOF/%s\n",
0599                 ce->np,
0600                 ce->prop->name);
0601             break;
0602         }
0603         break;
0604     case OF_RECONFIG_REMOVE_PROPERTY:
0605         ret = __of_remove_property(ce->np, ce->prop);
0606         if (ret) {
0607             pr_err("changeset: remove_property failed @%pOF/%s\n",
0608                 ce->np,
0609                 ce->prop->name);
0610             break;
0611         }
0612         break;
0613 
0614     case OF_RECONFIG_UPDATE_PROPERTY:
0615         /* If the property is in deadprops then it must be removed */
0616         for (propp = &ce->np->deadprops; *propp; propp = &(*propp)->next) {
0617             if (*propp == ce->prop) {
0618                 *propp = ce->prop->next;
0619                 ce->prop->next = NULL;
0620                 break;
0621             }
0622         }
0623 
0624         ret = __of_update_property(ce->np, ce->prop, &old_prop);
0625         if (ret) {
0626             pr_err("changeset: update_property failed @%pOF/%s\n",
0627                 ce->np,
0628                 ce->prop->name);
0629             break;
0630         }
0631         break;
0632     default:
0633         ret = -EINVAL;
0634     }
0635     raw_spin_unlock_irqrestore(&devtree_lock, flags);
0636 
0637     if (ret)
0638         return ret;
0639 
0640     switch (ce->action) {
0641     case OF_RECONFIG_ATTACH_NODE:
0642         __of_attach_node_sysfs(ce->np);
0643         break;
0644     case OF_RECONFIG_DETACH_NODE:
0645         __of_detach_node_sysfs(ce->np);
0646         break;
0647     case OF_RECONFIG_ADD_PROPERTY:
0648         /* ignore duplicate names */
0649         __of_add_property_sysfs(ce->np, ce->prop);
0650         break;
0651     case OF_RECONFIG_REMOVE_PROPERTY:
0652         __of_remove_property_sysfs(ce->np, ce->prop);
0653         break;
0654     case OF_RECONFIG_UPDATE_PROPERTY:
0655         __of_update_property_sysfs(ce->np, ce->prop, ce->old_prop);
0656         break;
0657     }
0658 
0659     return 0;
0660 }
0661 
0662 static inline int __of_changeset_entry_revert(struct of_changeset_entry *ce)
0663 {
0664     struct of_changeset_entry ce_inverted;
0665 
0666     __of_changeset_entry_invert(ce, &ce_inverted);
0667     return __of_changeset_entry_apply(&ce_inverted);
0668 }
0669 
0670 /**
0671  * of_changeset_init - Initialize a changeset for use
0672  *
0673  * @ocs:    changeset pointer
0674  *
0675  * Initialize a changeset structure
0676  */
0677 void of_changeset_init(struct of_changeset *ocs)
0678 {
0679     memset(ocs, 0, sizeof(*ocs));
0680     INIT_LIST_HEAD(&ocs->entries);
0681 }
0682 EXPORT_SYMBOL_GPL(of_changeset_init);
0683 
0684 /**
0685  * of_changeset_destroy - Destroy a changeset
0686  *
0687  * @ocs:    changeset pointer
0688  *
0689  * Destroys a changeset. Note that if a changeset is applied,
0690  * its changes to the tree cannot be reverted.
0691  */
0692 void of_changeset_destroy(struct of_changeset *ocs)
0693 {
0694     struct of_changeset_entry *ce, *cen;
0695 
0696     list_for_each_entry_safe_reverse(ce, cen, &ocs->entries, node)
0697         __of_changeset_entry_destroy(ce);
0698 }
0699 EXPORT_SYMBOL_GPL(of_changeset_destroy);
0700 
0701 /*
0702  * Apply the changeset entries in @ocs.
0703  * If apply fails, an attempt is made to revert the entries that were
0704  * successfully applied.
0705  *
0706  * If multiple revert errors occur then only the final revert error is reported.
0707  *
0708  * Returns 0 on success, a negative error value in case of an error.
0709  * If a revert error occurs, it is returned in *ret_revert.
0710  */
0711 int __of_changeset_apply_entries(struct of_changeset *ocs, int *ret_revert)
0712 {
0713     struct of_changeset_entry *ce;
0714     int ret, ret_tmp;
0715 
0716     pr_debug("changeset: applying...\n");
0717     list_for_each_entry(ce, &ocs->entries, node) {
0718         ret = __of_changeset_entry_apply(ce);
0719         if (ret) {
0720             pr_err("Error applying changeset (%d)\n", ret);
0721             list_for_each_entry_continue_reverse(ce, &ocs->entries,
0722                                  node) {
0723                 ret_tmp = __of_changeset_entry_revert(ce);
0724                 if (ret_tmp)
0725                     *ret_revert = ret_tmp;
0726             }
0727             return ret;
0728         }
0729     }
0730 
0731     return 0;
0732 }
0733 
0734 /*
0735  * Returns 0 on success, a negative error value in case of an error.
0736  *
0737  * If multiple changeset entry notification errors occur then only the
0738  * final notification error is reported.
0739  */
0740 int __of_changeset_apply_notify(struct of_changeset *ocs)
0741 {
0742     struct of_changeset_entry *ce;
0743     int ret = 0, ret_tmp;
0744 
0745     pr_debug("changeset: emitting notifiers.\n");
0746 
0747     /* drop the global lock while emitting notifiers */
0748     mutex_unlock(&of_mutex);
0749     list_for_each_entry(ce, &ocs->entries, node) {
0750         ret_tmp = __of_changeset_entry_notify(ce, 0);
0751         if (ret_tmp)
0752             ret = ret_tmp;
0753     }
0754     mutex_lock(&of_mutex);
0755     pr_debug("changeset: notifiers sent.\n");
0756 
0757     return ret;
0758 }
0759 
0760 /*
0761  * Returns 0 on success, a negative error value in case of an error.
0762  *
0763  * If a changeset entry apply fails, an attempt is made to revert any
0764  * previous entries in the changeset.  If any of the reverts fails,
0765  * that failure is not reported.  Thus the state of the device tree
0766  * is unknown if an apply error occurs.
0767  */
0768 static int __of_changeset_apply(struct of_changeset *ocs)
0769 {
0770     int ret, ret_revert = 0;
0771 
0772     ret = __of_changeset_apply_entries(ocs, &ret_revert);
0773     if (!ret)
0774         ret = __of_changeset_apply_notify(ocs);
0775 
0776     return ret;
0777 }
0778 
0779 /**
0780  * of_changeset_apply - Applies a changeset
0781  *
0782  * @ocs:    changeset pointer
0783  *
0784  * Applies a changeset to the live tree.
0785  * Any side-effects of live tree state changes are applied here on
0786  * success, like creation/destruction of devices and side-effects
0787  * like creation of sysfs properties and directories.
0788  *
0789  * Return: 0 on success, a negative error value in case of an error.
0790  * On error the partially applied effects are reverted.
0791  */
0792 int of_changeset_apply(struct of_changeset *ocs)
0793 {
0794     int ret;
0795 
0796     mutex_lock(&of_mutex);
0797     ret = __of_changeset_apply(ocs);
0798     mutex_unlock(&of_mutex);
0799 
0800     return ret;
0801 }
0802 EXPORT_SYMBOL_GPL(of_changeset_apply);
0803 
0804 /*
0805  * Revert the changeset entries in @ocs.
0806  * If revert fails, an attempt is made to re-apply the entries that were
0807  * successfully removed.
0808  *
0809  * If multiple re-apply errors occur then only the final apply error is
0810  * reported.
0811  *
0812  * Returns 0 on success, a negative error value in case of an error.
0813  * If an apply error occurs, it is returned in *ret_apply.
0814  */
0815 int __of_changeset_revert_entries(struct of_changeset *ocs, int *ret_apply)
0816 {
0817     struct of_changeset_entry *ce;
0818     int ret, ret_tmp;
0819 
0820     pr_debug("changeset: reverting...\n");
0821     list_for_each_entry_reverse(ce, &ocs->entries, node) {
0822         ret = __of_changeset_entry_revert(ce);
0823         if (ret) {
0824             pr_err("Error reverting changeset (%d)\n", ret);
0825             list_for_each_entry_continue(ce, &ocs->entries, node) {
0826                 ret_tmp = __of_changeset_entry_apply(ce);
0827                 if (ret_tmp)
0828                     *ret_apply = ret_tmp;
0829             }
0830             return ret;
0831         }
0832     }
0833 
0834     return 0;
0835 }
0836 
0837 /*
0838  * If multiple changeset entry notification errors occur then only the
0839  * final notification error is reported.
0840  */
0841 int __of_changeset_revert_notify(struct of_changeset *ocs)
0842 {
0843     struct of_changeset_entry *ce;
0844     int ret = 0, ret_tmp;
0845 
0846     pr_debug("changeset: emitting notifiers.\n");
0847 
0848     /* drop the global lock while emitting notifiers */
0849     mutex_unlock(&of_mutex);
0850     list_for_each_entry_reverse(ce, &ocs->entries, node) {
0851         ret_tmp = __of_changeset_entry_notify(ce, 1);
0852         if (ret_tmp)
0853             ret = ret_tmp;
0854     }
0855     mutex_lock(&of_mutex);
0856     pr_debug("changeset: notifiers sent.\n");
0857 
0858     return ret;
0859 }
0860 
0861 static int __of_changeset_revert(struct of_changeset *ocs)
0862 {
0863     int ret, ret_reply;
0864 
0865     ret_reply = 0;
0866     ret = __of_changeset_revert_entries(ocs, &ret_reply);
0867 
0868     if (!ret)
0869         ret = __of_changeset_revert_notify(ocs);
0870 
0871     return ret;
0872 }
0873 
0874 /**
0875  * of_changeset_revert - Reverts an applied changeset
0876  *
0877  * @ocs:    changeset pointer
0878  *
0879  * Reverts a changeset returning the state of the tree to what it
0880  * was before the application.
0881  * Any side-effects like creation/destruction of devices and
0882  * removal of sysfs properties and directories are applied.
0883  *
0884  * Return: 0 on success, a negative error value in case of an error.
0885  */
0886 int of_changeset_revert(struct of_changeset *ocs)
0887 {
0888     int ret;
0889 
0890     mutex_lock(&of_mutex);
0891     ret = __of_changeset_revert(ocs);
0892     mutex_unlock(&of_mutex);
0893 
0894     return ret;
0895 }
0896 EXPORT_SYMBOL_GPL(of_changeset_revert);
0897 
0898 /**
0899  * of_changeset_action - Add an action to the tail of the changeset list
0900  *
0901  * @ocs:    changeset pointer
0902  * @action: action to perform
0903  * @np:     Pointer to device node
0904  * @prop:   Pointer to property
0905  *
0906  * On action being one of:
0907  * + OF_RECONFIG_ATTACH_NODE
0908  * + OF_RECONFIG_DETACH_NODE,
0909  * + OF_RECONFIG_ADD_PROPERTY
0910  * + OF_RECONFIG_REMOVE_PROPERTY,
0911  * + OF_RECONFIG_UPDATE_PROPERTY
0912  *
0913  * Return: 0 on success, a negative error value in case of an error.
0914  */
0915 int of_changeset_action(struct of_changeset *ocs, unsigned long action,
0916         struct device_node *np, struct property *prop)
0917 {
0918     struct of_changeset_entry *ce;
0919 
0920     ce = kzalloc(sizeof(*ce), GFP_KERNEL);
0921     if (!ce)
0922         return -ENOMEM;
0923 
0924     /* get a reference to the node */
0925     ce->action = action;
0926     ce->np = of_node_get(np);
0927     ce->prop = prop;
0928 
0929     if (action == OF_RECONFIG_UPDATE_PROPERTY && prop)
0930         ce->old_prop = of_find_property(np, prop->name, NULL);
0931 
0932     /* add it to the list */
0933     list_add_tail(&ce->node, &ocs->entries);
0934     return 0;
0935 }
0936 EXPORT_SYMBOL_GPL(of_changeset_action);