From: Grant Likely <grant.likely@linaro.org>
To: linux-kernel@vger.kernel.org,
Nathan Fontenot <nfont@austin.ibm.com>,
Tyrel Datwyler <turtle.in.the.kernel@gmail.com>,
Pantelis Antoniou <pantelis.antoniou@konsulko.com>,
devicetree@vger.kernel.org
Cc: Grant Likely <grant.likely@linaro.org>
Subject: [PATCH 05/10] of: Create unlocked versions of node and property add/remove functions
Date: Wed, 23 Jul 2014 17:44:19 -0600 [thread overview]
Message-ID: <1406159064-21366-6-git-send-email-grant.likely@linaro.org> (raw)
In-Reply-To: <1406159064-21366-1-git-send-email-grant.likely@linaro.org>
From: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
The DT overlay code will need to manipulate nodes and properties while
already holding the devicetree lock, or on nodes that are not yet
attached to the tree, but the current helper functions don't allow that.
Extract the core behaviour from the accessors and create the following
unlocked variants.
The unlocked variants require either the lock to already be held or for
the nodes to be detached from the tree. Changes to live nodes will not
get updated in sysfs, so the caller must arrange for housekeeping to
take place after dropping the lock.
The new functions are: __of_add_property(), __of_remove_property(),
__of_update_property(), __of_attach_node() and __of_detach_node().
Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
[Remove unnecessary diff hunks and rewrite commit text]
Signed-off-by: Grant Likely <grant.likely@linaro.org>
---
drivers/of/base.c | 91 +++++++++++++++++++++++++++++--------------------
drivers/of/dynamic.c | 63 ++++++++++++++++++----------------
drivers/of/of_private.h | 8 +++++
3 files changed, 96 insertions(+), 66 deletions(-)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 0d8955605738..b403f9d98461 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1659,7 +1659,7 @@ EXPORT_SYMBOL(of_count_phandle_with_args);
/**
* __of_add_property - Add a property to a node without lock operations
*/
-static int __of_add_property(struct device_node *np, struct property *prop)
+int __of_add_property(struct device_node *np, struct property *prop)
{
struct property **next;
@@ -1701,6 +1701,25 @@ int of_add_property(struct device_node *np, struct property *prop)
return rc;
}
+int __of_remove_property(struct device_node *np, struct property *prop)
+{
+ struct property **next;
+
+ for (next = &np->properties; *next; next = &(*next)->next) {
+ if (*next == prop)
+ break;
+ }
+ if (*next == NULL)
+ return -ENODEV;
+
+ /* found the node */
+ *next = prop->next;
+ prop->next = np->deadprops;
+ np->deadprops = prop;
+
+ return 0;
+}
+
/**
* of_remove_property - Remove a property from a node.
*
@@ -1711,9 +1730,7 @@ int of_add_property(struct device_node *np, struct property *prop)
*/
int of_remove_property(struct device_node *np, struct property *prop)
{
- struct property **next;
unsigned long flags;
- int found = 0;
int rc;
rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop);
@@ -1721,22 +1738,11 @@ int of_remove_property(struct device_node *np, struct property *prop)
return rc;
raw_spin_lock_irqsave(&devtree_lock, flags);
- next = &np->properties;
- while (*next) {
- if (*next == prop) {
- /* found the node */
- *next = prop->next;
- prop->next = np->deadprops;
- np->deadprops = prop;
- found = 1;
- break;
- }
- next = &(*next)->next;
- }
+ rc = __of_remove_property(np, prop);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
- if (!found)
- return -ENODEV;
+ if (rc)
+ return rc;
/* at early boot, bail hear and defer setup to of_init() */
if (!of_kset)
@@ -1747,6 +1753,32 @@ int of_remove_property(struct device_node *np, struct property *prop)
return 0;
}
+int __of_update_property(struct device_node *np, struct property *newprop,
+ struct property **oldpropp)
+{
+ struct property **next, *oldprop;
+
+ for (next = &np->properties; *next; next = &(*next)->next) {
+ if (of_prop_cmp((*next)->name, newprop->name) == 0)
+ break;
+ }
+ *oldpropp = oldprop = *next;
+
+ if (oldprop) {
+ /* replace the node */
+ newprop->next = oldprop->next;
+ *next = newprop;
+ oldprop->next = np->deadprops;
+ np->deadprops = oldprop;
+ } else {
+ /* new node */
+ newprop->next = NULL;
+ *next = newprop;
+ }
+
+ return 0;
+}
+
/*
* of_update_property - Update a property in a node, if the property does
* not exist, add it.
@@ -1758,34 +1790,19 @@ int of_remove_property(struct device_node *np, struct property *prop)
*/
int of_update_property(struct device_node *np, struct property *newprop)
{
- struct property **next, *oldprop;
+ struct property *oldprop;
unsigned long flags;
int rc;
+ if (!newprop->name)
+ return -EINVAL;
+
rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop);
if (rc)
return rc;
- if (!newprop->name)
- return -EINVAL;
-
raw_spin_lock_irqsave(&devtree_lock, flags);
- next = &np->properties;
- oldprop = __of_find_property(np, newprop->name, NULL);
- if (!oldprop) {
- /* add the new node */
- rc = __of_add_property(np, newprop);
- } else while (*next) {
- /* replace the node */
- if (*next == oldprop) {
- newprop->next = oldprop->next;
- *next = newprop;
- oldprop->next = np->deadprops;
- np->deadprops = oldprop;
- break;
- }
- next = &(*next)->next;
- }
+ rc = __of_update_property(np, newprop, &oldprop);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
if (rc)
return rc;
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
index e0c4c6e25980..75fcc66fcefd 100644
--- a/drivers/of/dynamic.c
+++ b/drivers/of/dynamic.c
@@ -94,6 +94,15 @@ int of_property_notify(int action, struct device_node *np,
return of_reconfig_notify(action, &pr);
}
+void __of_attach_node(struct device_node *np)
+{
+ np->sibling = np->parent->child;
+ np->allnext = np->parent->allnext;
+ np->parent->allnext = np;
+ np->parent->child = np;
+ of_node_clear_flag(np, OF_DETACHED);
+}
+
/**
* of_attach_node() - Plug a device node into the tree and global list.
*/
@@ -107,46 +116,23 @@ int of_attach_node(struct device_node *np)
return rc;
raw_spin_lock_irqsave(&devtree_lock, flags);
- np->sibling = np->parent->child;
- np->allnext = np->parent->allnext;
- np->parent->allnext = np;
- np->parent->child = np;
- of_node_clear_flag(np, OF_DETACHED);
+ __of_attach_node(np);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
of_node_add(np);
return 0;
}
-/**
- * of_detach_node() - "Unplug" a node from the device tree.
- *
- * The caller must hold a reference to the node. The memory associated with
- * the node is not freed until its refcount goes to zero.
- */
-int of_detach_node(struct device_node *np)
+void __of_detach_node(struct device_node *np)
{
struct device_node *parent;
- unsigned long flags;
- int rc = 0;
-
- rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
- if (rc)
- return rc;
- raw_spin_lock_irqsave(&devtree_lock, flags);
-
- if (of_node_check_flag(np, OF_DETACHED)) {
- /* someone already detached it */
- raw_spin_unlock_irqrestore(&devtree_lock, flags);
- return rc;
- }
+ if (WARN_ON(of_node_check_flag(np, OF_DETACHED)))
+ return;
parent = np->parent;
- if (!parent) {
- raw_spin_unlock_irqrestore(&devtree_lock, flags);
- return rc;
- }
+ if (WARN_ON(!parent))
+ return;
if (of_allnodes == np)
of_allnodes = np->allnext;
@@ -171,6 +157,25 @@ int of_detach_node(struct device_node *np)
}
of_node_set_flag(np, OF_DETACHED);
+}
+
+/**
+ * of_detach_node() - "Unplug" a node from the device tree.
+ *
+ * The caller must hold a reference to the node. The memory associated with
+ * the node is not freed until its refcount goes to zero.
+ */
+int of_detach_node(struct device_node *np)
+{
+ unsigned long flags;
+ int rc = 0;
+
+ rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
+ if (rc)
+ return rc;
+
+ raw_spin_lock_irqsave(&devtree_lock, flags);
+ __of_detach_node(np);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
of_node_remove(np);
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index 1799ed2b3808..0f6089722af9 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -61,4 +61,12 @@ static inline int of_property_notify(int action, struct device_node *np,
struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags);
struct device_node *__of_node_alloc(const char *full_name, gfp_t allocflags);
+extern int __of_add_property(struct device_node *np, struct property *prop);
+extern int __of_remove_property(struct device_node *np, struct property *prop);
+extern int __of_update_property(struct device_node *np,
+ struct property *newprop, struct property **oldprop);
+
+extern void __of_attach_node(struct device_node *np);
+extern void __of_detach_node(struct device_node *np);
+
#endif /* _LINUX_OF_PRIVATE_H */
--
1.9.1
next prev parent reply other threads:[~2014-07-23 23:44 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-23 23:44 [PATCH 00/10] of: Core devicetree changeset support Grant Likely
[not found] ` <1406159064-21366-1-git-send-email-grant.likely-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2014-07-23 23:44 ` [PATCH 01/10] of/platform: Fix of_platform_device_destroy iteration of devices Grant Likely
2014-07-23 23:44 ` [PATCH 02/10] of: rename of_aliases_mutex to just of_mutex Grant Likely
2014-07-23 23:44 ` [PATCH 04/10] OF: Utility helper functions for dynamic nodes Grant Likely
2014-07-25 18:10 ` [PATCH 00/10] of: Core devicetree changeset support Nathan Fontenot
[not found] ` <53D29D87.4060708-V7BBcbaFuwjMbYB6QlFGEg@public.gmane.org>
2014-07-27 14:43 ` Grant Likely
2014-07-23 23:44 ` [PATCH 03/10] of: Move CONFIG_OF_DYNAMIC code into a separate file Grant Likely
2014-07-23 23:44 ` Grant Likely [this message]
2014-07-23 23:44 ` [PATCH 06/10] of: Make devicetree sysfs update functions consistent Grant Likely
2014-07-23 23:44 ` [PATCH 07/10] of: Make sure attached nodes don't carry along extra children Grant Likely
2014-07-23 23:44 ` [PATCH 08/10] of: Move dynamic node fixups out of powerpc and into common code Grant Likely
2014-07-23 23:44 ` [PATCH 09/10] of: Reorder device tree changes and notifiers Grant Likely
2014-07-23 23:44 ` [PATCH 10/10] of: Transactional DT support Grant Likely
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1406159064-21366-6-git-send-email-grant.likely@linaro.org \
--to=grant.likely@linaro.org \
--cc=devicetree@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=nfont@austin.ibm.com \
--cc=pantelis.antoniou@konsulko.com \
--cc=turtle.in.the.kernel@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).