static int of_overlay_apply_single_property(struct of_overlay *ov, struct device_node *target, struct property *prop) { struct property *propn, *tprop; /* NOTE: Multiple changes of single properties not supported */ tprop = of_find_property(target, prop->name, NULL); /* special properties are not meant to be updated (silent NOP) */ if (of_prop_cmp(prop->name, "name") == 0 || of_prop_cmp(prop->name, "phandle") == 0 || of_prop_cmp(prop->name, "linux,phandle") == 0) return 0; propn = __of_prop_dup(prop, GFP_KERNEL); if (propn == NULL) return -ENOMEM; /* not found? add */ if (tprop == NULL) return of_changeset_add_property(&ov->cset, target, propn); /* found? update */ return of_changeset_update_property(&ov->cset, target, propn); }
/** * add_changeset_property() - add @overlay_prop to overlay changeset * @ovcs: overlay changeset * @target_node: where to place @overlay_prop in live tree * @overlay_prop: property to add or update, from overlay tree * @is_symbols_prop: 1 if @overlay_prop is from node "/__symbols__" * * If @overlay_prop does not already exist in @target_node, add changeset entry * to add @overlay_prop in @target_node, else add changeset entry to update * value of @overlay_prop. * * Some special properties are not updated (no error returned). * * Update of property in symbols node is not allowed. * * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if * invalid @overlay. */ static int add_changeset_property(struct overlay_changeset *ovcs, struct device_node *target_node, struct property *overlay_prop, bool is_symbols_prop) { struct property *new_prop = NULL, *prop; int ret = 0; prop = of_find_property(target_node, overlay_prop->name, NULL); if (!of_prop_cmp(overlay_prop->name, "name") || !of_prop_cmp(overlay_prop->name, "phandle") || !of_prop_cmp(overlay_prop->name, "linux,phandle")) return 0; if (is_symbols_prop) { if (prop) return -EINVAL; new_prop = dup_and_fixup_symbol_prop(ovcs, overlay_prop); } else { new_prop = __of_prop_dup(overlay_prop, GFP_KERNEL); } if (!new_prop) return -ENOMEM; if (!prop) ret = of_changeset_add_property(&ovcs->cset, target_node, new_prop); else ret = of_changeset_update_property(&ovcs->cset, target_node, new_prop); if (ret) { kfree(new_prop->name); kfree(new_prop->value); kfree(new_prop); } return ret; }
static struct property *__of_find_property(const struct device_node *np, const char *name, int *lenp) { struct property *pp; if (!np) return NULL; for (pp = np->properties; pp; pp = pp->next) { if (of_prop_cmp(pp->name, name) == 0) { if (lenp) *lenp = pp->length; break; } } return pp; }
struct property *of_find_property(const struct device_node *np, const char *name, int *lenp) { struct property *pp; read_lock(&devtree_lock); for (pp = np->properties; pp != 0; pp = pp->next) { if (of_prop_cmp(pp->name, name) == 0) { if (lenp != 0) *lenp = pp->length; break; } } read_unlock(&devtree_lock); return pp; }
/** * of_find_node_with_property - Find a node which has a property with * the given name. * @from: The node to start searching from or NULL, the node * you pass will not be searched, only the next one * will; typically, you pass what the previous call * returned. of_node_put() will be called on it * @prop_name: The name of the property to look for. * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */ struct device_node *of_find_node_with_property(struct device_node *from, const char *prop_name) { struct device_node *np; struct property *pp; read_lock(&devtree_lock); np = from ? from->allnext : allnodes; for (; np; np = np->allnext) { for (pp = np->properties; pp != 0; pp = pp->next) { if (of_prop_cmp(pp->name, prop_name) == 0) { of_node_get(np); goto out; } } } out: of_node_put(from); read_unlock(&devtree_lock); return np; }
/** * of_find_node_with_property - Find a node which has a property with * the given name. * @from: The node to start searching from or NULL, the node * you pass will not be searched, only the next one * will; typically, you pass what the previous call * returned. of_node_put() will be called on it * @prop_name: The name of the property to look for. * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */ struct device_node *of_find_node_with_property(struct device_node *from, const char *prop_name) { struct device_node *np; struct property *pp; unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); np = from ? from->allnext : of_allnodes; for (; np; np = np->allnext) { for (pp = np->properties; pp; pp = pp->next) { if (of_prop_cmp(pp->name, prop_name) == 0) { of_node_get(np); goto out; } } } out: of_node_put(from); raw_spin_unlock_irqrestore(&devtree_lock, flags); return np; }