linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH next] OF: convert devtree lock from rw_lock to raw spinlock
@ 2013-02-04 16:05 Paul Gortmaker
  2013-02-04 17:54 ` David Miller
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Paul Gortmaker @ 2013-02-04 16:05 UTC (permalink / raw)
  To: Rob Herring
  Cc: Grant Likely, Sam Ravnborg, devicetree-discuss, linux-kernel,
	sparclinux, linux-rt-users, Thomas Gleixner, Paul Gortmaker

From: Thomas Gleixner <tglx@linutronix.de>

With the locking cleanup in place (from "OF: Fixup resursive
locking code paths"), we can now do the conversion from the
rw_lock to a raw spinlock as required for preempt-rt.

The previous cleanup and the this conversion were originally
separate since they predated when mainline got raw spinlock (in
commit c2f21ce2e31286a "locking: Implement new raw_spinlock").

So, at that point in time, the cleanup was considered plausible
for mainline, but not this conversion.  In any case, we've kept
them separate as it makes for easier review and better bisection.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
[PG: taken from preempt-rt, update subject & add a commit log]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---

[ Patch against linux-next of Feb4, where the recursive
  locking cleanup currently is.  Boot tested on ppc 8548,
  compile tested for sparc and arm defconfigs ]

 arch/sparc/kernel/prom_common.c |  4 +-
 drivers/of/base.c               | 96 +++++++++++++++++++++++------------------
 include/linux/of.h              |  2 +-
 3 files changed, 57 insertions(+), 45 deletions(-)

diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c
index 1303021..9f20566 100644
--- a/arch/sparc/kernel/prom_common.c
+++ b/arch/sparc/kernel/prom_common.c
@@ -64,7 +64,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
 	err = -ENODEV;
 
 	mutex_lock(&of_set_property_mutex);
-	write_lock(&devtree_lock);
+	raw_spin_lock(&devtree_lock);
 	prevp = &dp->properties;
 	while (*prevp) {
 		struct property *prop = *prevp;
@@ -91,7 +91,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
 		}
 		prevp = &(*prevp)->next;
 	}
-	write_unlock(&devtree_lock);
+	raw_spin_unlock(&devtree_lock);
 	mutex_unlock(&of_set_property_mutex);
 
 	/* XXX Upate procfs if necessary... */
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 16ee7a0..4a2f58b 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -55,7 +55,7 @@ static DEFINE_MUTEX(of_aliases_mutex);
 /* use when traversing tree through the allnext, child, sibling,
  * or parent members of struct device_node.
  */
-DEFINE_RWLOCK(devtree_lock);
+DEFINE_RAW_SPINLOCK(devtree_lock);
 
 int of_n_addr_cells(struct device_node *np)
 {
@@ -188,10 +188,11 @@ struct property *of_find_property(const struct device_node *np,
 				  int *lenp)
 {
 	struct property *pp;
+	unsigned long flags;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	pp = __of_find_property(np, name, lenp);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
 	return pp;
 }
@@ -209,13 +210,13 @@ struct device_node *of_find_all_nodes(struct device_node *prev)
 {
 	struct device_node *np;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock(&devtree_lock);
 	np = prev ? prev->allnext : of_allnodes;
 	for (; np != NULL; np = np->allnext)
 		if (of_node_get(np))
 			break;
 	of_node_put(prev);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock(&devtree_lock);
 	return np;
 }
 EXPORT_SYMBOL(of_find_all_nodes);
@@ -274,11 +275,12 @@ static int __of_device_is_compatible(const struct device_node *device,
 int of_device_is_compatible(const struct device_node *device,
 		const char *compat)
 {
+	unsigned long flags;
 	int res;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	res = __of_device_is_compatible(device, compat);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return res;
 }
 EXPORT_SYMBOL(of_device_is_compatible);
@@ -340,13 +342,14 @@ EXPORT_SYMBOL(of_device_is_available);
 struct device_node *of_get_parent(const struct device_node *node)
 {
 	struct device_node *np;
+	unsigned long flags;
 
 	if (!node)
 		return NULL;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	np = of_node_get(node->parent);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return np;
 }
 EXPORT_SYMBOL(of_get_parent);
@@ -365,14 +368,15 @@ EXPORT_SYMBOL(of_get_parent);
 struct device_node *of_get_next_parent(struct device_node *node)
 {
 	struct device_node *parent;
+	unsigned long flags;
 
 	if (!node)
 		return NULL;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	parent = of_node_get(node->parent);
 	of_node_put(node);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return parent;
 }
 
@@ -388,14 +392,15 @@ struct device_node *of_get_next_child(const struct device_node *node,
 	struct device_node *prev)
 {
 	struct device_node *next;
+	unsigned long flags;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	next = prev ? prev->sibling : node->child;
 	for (; next; next = next->sibling)
 		if (of_node_get(next))
 			break;
 	of_node_put(prev);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return next;
 }
 EXPORT_SYMBOL(of_get_next_child);
@@ -413,7 +418,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
 {
 	struct device_node *next;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock(&devtree_lock);
 	next = prev ? prev->sibling : node->child;
 	for (; next; next = next->sibling) {
 		if (!of_device_is_available(next))
@@ -422,7 +427,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
 			break;
 	}
 	of_node_put(prev);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock(&devtree_lock);
 	return next;
 }
 EXPORT_SYMBOL(of_get_next_available_child);
@@ -460,14 +465,15 @@ EXPORT_SYMBOL(of_get_child_by_name);
 struct device_node *of_find_node_by_path(const char *path)
 {
 	struct device_node *np = of_allnodes;
+	unsigned long flags;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	for (; np; np = np->allnext) {
 		if (np->full_name && (of_node_cmp(np->full_name, path) == 0)
 		    && of_node_get(np))
 			break;
 	}
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return np;
 }
 EXPORT_SYMBOL(of_find_node_by_path);
@@ -487,15 +493,16 @@ struct device_node *of_find_node_by_name(struct device_node *from,
 	const char *name)
 {
 	struct device_node *np;
+	unsigned long flags;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	np = from ? from->allnext : of_allnodes;
 	for (; np; np = np->allnext)
 		if (np->name && (of_node_cmp(np->name, name) == 0)
 		    && of_node_get(np))
 			break;
 	of_node_put(from);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return np;
 }
 EXPORT_SYMBOL(of_find_node_by_name);
@@ -516,15 +523,16 @@ struct device_node *of_find_node_by_type(struct device_node *from,
 	const char *type)
 {
 	struct device_node *np;
+	unsigned long flags;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	np = from ? from->allnext : of_allnodes;
 	for (; np; np = np->allnext)
 		if (np->type && (of_node_cmp(np->type, type) == 0)
 		    && of_node_get(np))
 			break;
 	of_node_put(from);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return np;
 }
 EXPORT_SYMBOL(of_find_node_by_type);
@@ -547,8 +555,9 @@ struct device_node *of_find_compatible_node(struct device_node *from,
 	const char *type, const char *compatible)
 {
 	struct device_node *np;
+	unsigned long flags;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	np = from ? from->allnext : of_allnodes;
 	for (; np; np = np->allnext) {
 		if (type
@@ -559,7 +568,7 @@ struct device_node *of_find_compatible_node(struct device_node *from,
 			break;
 	}
 	of_node_put(from);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return np;
 }
 EXPORT_SYMBOL(of_find_compatible_node);
@@ -581,8 +590,9 @@ struct device_node *of_find_node_with_property(struct device_node *from,
 {
 	struct device_node *np;
 	struct property *pp;
+	unsigned long flags;
 
-	read_lock(&devtree_lock);
+	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) {
@@ -594,7 +604,7 @@ struct device_node *of_find_node_with_property(struct device_node *from,
 	}
 out:
 	of_node_put(from);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return np;
 }
 EXPORT_SYMBOL(of_find_node_with_property);
@@ -635,10 +645,11 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
 					 const struct device_node *node)
 {
 	const struct of_device_id *match;
+	unsigned long flags;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	match = __of_match_node(matches, node);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return match;
 }
 EXPORT_SYMBOL(of_match_node);
@@ -662,11 +673,12 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
 {
 	struct device_node *np;
 	const struct of_device_id *m;
+	unsigned long flags;
 
 	if (match)
 		*match = NULL;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	np = from ? from->allnext : of_allnodes;
 	for (; np; np = np->allnext) {
 		m = __of_match_node(matches, np);
@@ -677,7 +689,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
 		}
 	}
 	of_node_put(from);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return np;
 }
 EXPORT_SYMBOL(of_find_matching_node_and_match);
@@ -720,12 +732,12 @@ struct device_node *of_find_node_by_phandle(phandle handle)
 {
 	struct device_node *np;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock(&devtree_lock);
 	for (np = of_allnodes; np; np = np->allnext)
 		if (np->phandle == handle)
 			break;
 	of_node_get(np);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock(&devtree_lock);
 	return np;
 }
 EXPORT_SYMBOL(of_find_node_by_phandle);
@@ -1197,18 +1209,18 @@ int of_add_property(struct device_node *np, struct property *prop)
 		return rc;
 
 	prop->next = NULL;
-	write_lock_irqsave(&devtree_lock, flags);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	next = &np->properties;
 	while (*next) {
 		if (strcmp(prop->name, (*next)->name) == 0) {
 			/* duplicate ! don't insert it */
-			write_unlock_irqrestore(&devtree_lock, flags);
+			raw_spin_unlock_irqrestore(&devtree_lock, flags);
 			return -1;
 		}
 		next = &(*next)->next;
 	}
 	*next = prop;
-	write_unlock_irqrestore(&devtree_lock, flags);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
 #ifdef CONFIG_PROC_DEVICETREE
 	/* try to add to proc as well if it was initialized */
@@ -1238,7 +1250,7 @@ int of_remove_property(struct device_node *np, struct property *prop)
 	if (rc)
 		return rc;
 
-	write_lock_irqsave(&devtree_lock, flags);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	next = &np->properties;
 	while (*next) {
 		if (*next == prop) {
@@ -1251,7 +1263,7 @@ int of_remove_property(struct device_node *np, struct property *prop)
 		}
 		next = &(*next)->next;
 	}
-	write_unlock_irqrestore(&devtree_lock, flags);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
 	if (!found)
 		return -ENODEV;
@@ -1291,7 +1303,7 @@ int of_update_property(struct device_node *np, struct property *newprop)
 	if (!oldprop)
 		return of_add_property(np, newprop);
 
-	write_lock_irqsave(&devtree_lock, flags);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	next = &np->properties;
 	while (*next) {
 		if (*next == oldprop) {
@@ -1305,7 +1317,7 @@ int of_update_property(struct device_node *np, struct property *newprop)
 		}
 		next = &(*next)->next;
 	}
-	write_unlock_irqrestore(&devtree_lock, flags);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
 	if (!found)
 		return -ENODEV;
@@ -1378,12 +1390,12 @@ int of_attach_node(struct device_node *np)
 	if (rc)
 		return rc;
 
-	write_lock_irqsave(&devtree_lock, flags);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	np->sibling = np->parent->child;
 	np->allnext = of_allnodes;
 	np->parent->child = np;
 	of_allnodes = np;
-	write_unlock_irqrestore(&devtree_lock, flags);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
 	of_add_proc_dt_entry(np);
 	return 0;
@@ -1426,7 +1438,7 @@ int of_detach_node(struct device_node *np)
 	if (rc)
 		return rc;
 
-	write_lock_irqsave(&devtree_lock, flags);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 
 	if (of_node_check_flag(np, OF_DETACHED)) {
 		/* someone already detached it */
@@ -1463,7 +1475,7 @@ int of_detach_node(struct device_node *np)
 	}
 
 	of_node_set_flag(np, OF_DETACHED);
-	write_unlock_irqrestore(&devtree_lock, flags);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
 	of_remove_proc_dt_entry(np);
 	return rc;
diff --git a/include/linux/of.h b/include/linux/of.h
index 5ebcc5c..bb35c42 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -92,7 +92,7 @@ static inline void of_node_put(struct device_node *node) { }
 extern struct device_node *of_allnodes;
 extern struct device_node *of_chosen;
 extern struct device_node *of_aliases;
-extern rwlock_t devtree_lock;
+extern raw_spinlock_t devtree_lock;
 
 static inline bool of_have_populated_dt(void)
 {
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH next] OF: convert devtree lock from rw_lock to raw spinlock
  2013-02-04 16:05 [PATCH next] OF: convert devtree lock from rw_lock to raw spinlock Paul Gortmaker
@ 2013-02-04 17:54 ` David Miller
  2013-02-06 16:04 ` Rob Herring
  2013-02-06 20:30 ` [PATCH next v2] " Paul Gortmaker
  2 siblings, 0 replies; 10+ messages in thread
From: David Miller @ 2013-02-04 17:54 UTC (permalink / raw)
  To: paul.gortmaker
  Cc: rob.herring, grant.likely, sam, devicetree-discuss, linux-kernel,
	sparclinux, linux-rt-users, tglx

From: Paul Gortmaker <paul.gortmaker@windriver.com>
Date: Mon,  4 Feb 2013 11:05:21 -0500

> From: Thomas Gleixner <tglx@linutronix.de>
> 
> With the locking cleanup in place (from "OF: Fixup resursive
> locking code paths"), we can now do the conversion from the
> rw_lock to a raw spinlock as required for preempt-rt.
> 
> The previous cleanup and the this conversion were originally
> separate since they predated when mainline got raw spinlock (in
> commit c2f21ce2e31286a "locking: Implement new raw_spinlock").
> 
> So, at that point in time, the cleanup was considered plausible
> for mainline, but not this conversion.  In any case, we've kept
> them separate as it makes for easier review and better bisection.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> [PG: taken from preempt-rt, update subject & add a commit log]
> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH next] OF: convert devtree lock from rw_lock to raw spinlock
  2013-02-04 16:05 [PATCH next] OF: convert devtree lock from rw_lock to raw spinlock Paul Gortmaker
  2013-02-04 17:54 ` David Miller
@ 2013-02-06 16:04 ` Rob Herring
  2013-02-06 20:30 ` [PATCH next v2] " Paul Gortmaker
  2 siblings, 0 replies; 10+ messages in thread
From: Rob Herring @ 2013-02-06 16:04 UTC (permalink / raw)
  To: Paul Gortmaker
  Cc: Rob Herring, linux-rt-users, devicetree-discuss, linux-kernel,
	sparclinux, Thomas Gleixner, Sam Ravnborg

On 02/04/2013 10:05 AM, Paul Gortmaker wrote:
> From: Thomas Gleixner <tglx@linutronix.de>
> 
> With the locking cleanup in place (from "OF: Fixup resursive
> locking code paths"), we can now do the conversion from the
> rw_lock to a raw spinlock as required for preempt-rt.
> 
> The previous cleanup and the this conversion were originally
> separate since they predated when mainline got raw spinlock (in
> commit c2f21ce2e31286a "locking: Implement new raw_spinlock").
> 
> So, at that point in time, the cleanup was considered plausible
> for mainline, but not this conversion.  In any case, we've kept
> them separate as it makes for easier review and better bisection.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> [PG: taken from preempt-rt, update subject & add a commit log]
> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
> ---
> 
> [ Patch against linux-next of Feb4, where the recursive
>   locking cleanup currently is.  Boot tested on ppc 8548,
>   compile tested for sparc and arm defconfigs ]
> 

Applied.

Rob

>  arch/sparc/kernel/prom_common.c |  4 +-
>  drivers/of/base.c               | 96 +++++++++++++++++++++++------------------
>  include/linux/of.h              |  2 +-
>  3 files changed, 57 insertions(+), 45 deletions(-)
> 
> diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c
> index 1303021..9f20566 100644
> --- a/arch/sparc/kernel/prom_common.c
> +++ b/arch/sparc/kernel/prom_common.c
> @@ -64,7 +64,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
>  	err = -ENODEV;
>  
>  	mutex_lock(&of_set_property_mutex);
> -	write_lock(&devtree_lock);
> +	raw_spin_lock(&devtree_lock);
>  	prevp = &dp->properties;
>  	while (*prevp) {
>  		struct property *prop = *prevp;
> @@ -91,7 +91,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
>  		}
>  		prevp = &(*prevp)->next;
>  	}
> -	write_unlock(&devtree_lock);
> +	raw_spin_unlock(&devtree_lock);
>  	mutex_unlock(&of_set_property_mutex);
>  
>  	/* XXX Upate procfs if necessary... */
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 16ee7a0..4a2f58b 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -55,7 +55,7 @@ static DEFINE_MUTEX(of_aliases_mutex);
>  /* use when traversing tree through the allnext, child, sibling,
>   * or parent members of struct device_node.
>   */
> -DEFINE_RWLOCK(devtree_lock);
> +DEFINE_RAW_SPINLOCK(devtree_lock);
>  
>  int of_n_addr_cells(struct device_node *np)
>  {
> @@ -188,10 +188,11 @@ struct property *of_find_property(const struct device_node *np,
>  				  int *lenp)
>  {
>  	struct property *pp;
> +	unsigned long flags;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	pp = __of_find_property(np, name, lenp);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  
>  	return pp;
>  }
> @@ -209,13 +210,13 @@ struct device_node *of_find_all_nodes(struct device_node *prev)
>  {
>  	struct device_node *np;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock(&devtree_lock);
>  	np = prev ? prev->allnext : of_allnodes;
>  	for (; np != NULL; np = np->allnext)
>  		if (of_node_get(np))
>  			break;
>  	of_node_put(prev);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock(&devtree_lock);
>  	return np;
>  }
>  EXPORT_SYMBOL(of_find_all_nodes);
> @@ -274,11 +275,12 @@ static int __of_device_is_compatible(const struct device_node *device,
>  int of_device_is_compatible(const struct device_node *device,
>  		const char *compat)
>  {
> +	unsigned long flags;
>  	int res;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	res = __of_device_is_compatible(device, compat);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return res;
>  }
>  EXPORT_SYMBOL(of_device_is_compatible);
> @@ -340,13 +342,14 @@ EXPORT_SYMBOL(of_device_is_available);
>  struct device_node *of_get_parent(const struct device_node *node)
>  {
>  	struct device_node *np;
> +	unsigned long flags;
>  
>  	if (!node)
>  		return NULL;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	np = of_node_get(node->parent);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return np;
>  }
>  EXPORT_SYMBOL(of_get_parent);
> @@ -365,14 +368,15 @@ EXPORT_SYMBOL(of_get_parent);
>  struct device_node *of_get_next_parent(struct device_node *node)
>  {
>  	struct device_node *parent;
> +	unsigned long flags;
>  
>  	if (!node)
>  		return NULL;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	parent = of_node_get(node->parent);
>  	of_node_put(node);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return parent;
>  }
>  
> @@ -388,14 +392,15 @@ struct device_node *of_get_next_child(const struct device_node *node,
>  	struct device_node *prev)
>  {
>  	struct device_node *next;
> +	unsigned long flags;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	next = prev ? prev->sibling : node->child;
>  	for (; next; next = next->sibling)
>  		if (of_node_get(next))
>  			break;
>  	of_node_put(prev);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return next;
>  }
>  EXPORT_SYMBOL(of_get_next_child);
> @@ -413,7 +418,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
>  {
>  	struct device_node *next;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock(&devtree_lock);
>  	next = prev ? prev->sibling : node->child;
>  	for (; next; next = next->sibling) {
>  		if (!of_device_is_available(next))
> @@ -422,7 +427,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
>  			break;
>  	}
>  	of_node_put(prev);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock(&devtree_lock);
>  	return next;
>  }
>  EXPORT_SYMBOL(of_get_next_available_child);
> @@ -460,14 +465,15 @@ EXPORT_SYMBOL(of_get_child_by_name);
>  struct device_node *of_find_node_by_path(const char *path)
>  {
>  	struct device_node *np = of_allnodes;
> +	unsigned long flags;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	for (; np; np = np->allnext) {
>  		if (np->full_name && (of_node_cmp(np->full_name, path) == 0)
>  		    && of_node_get(np))
>  			break;
>  	}
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return np;
>  }
>  EXPORT_SYMBOL(of_find_node_by_path);
> @@ -487,15 +493,16 @@ struct device_node *of_find_node_by_name(struct device_node *from,
>  	const char *name)
>  {
>  	struct device_node *np;
> +	unsigned long flags;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	np = from ? from->allnext : of_allnodes;
>  	for (; np; np = np->allnext)
>  		if (np->name && (of_node_cmp(np->name, name) == 0)
>  		    && of_node_get(np))
>  			break;
>  	of_node_put(from);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return np;
>  }
>  EXPORT_SYMBOL(of_find_node_by_name);
> @@ -516,15 +523,16 @@ struct device_node *of_find_node_by_type(struct device_node *from,
>  	const char *type)
>  {
>  	struct device_node *np;
> +	unsigned long flags;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	np = from ? from->allnext : of_allnodes;
>  	for (; np; np = np->allnext)
>  		if (np->type && (of_node_cmp(np->type, type) == 0)
>  		    && of_node_get(np))
>  			break;
>  	of_node_put(from);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return np;
>  }
>  EXPORT_SYMBOL(of_find_node_by_type);
> @@ -547,8 +555,9 @@ struct device_node *of_find_compatible_node(struct device_node *from,
>  	const char *type, const char *compatible)
>  {
>  	struct device_node *np;
> +	unsigned long flags;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	np = from ? from->allnext : of_allnodes;
>  	for (; np; np = np->allnext) {
>  		if (type
> @@ -559,7 +568,7 @@ struct device_node *of_find_compatible_node(struct device_node *from,
>  			break;
>  	}
>  	of_node_put(from);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return np;
>  }
>  EXPORT_SYMBOL(of_find_compatible_node);
> @@ -581,8 +590,9 @@ struct device_node *of_find_node_with_property(struct device_node *from,
>  {
>  	struct device_node *np;
>  	struct property *pp;
> +	unsigned long flags;
>  
> -	read_lock(&devtree_lock);
> +	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) {
> @@ -594,7 +604,7 @@ struct device_node *of_find_node_with_property(struct device_node *from,
>  	}
>  out:
>  	of_node_put(from);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return np;
>  }
>  EXPORT_SYMBOL(of_find_node_with_property);
> @@ -635,10 +645,11 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
>  					 const struct device_node *node)
>  {
>  	const struct of_device_id *match;
> +	unsigned long flags;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	match = __of_match_node(matches, node);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return match;
>  }
>  EXPORT_SYMBOL(of_match_node);
> @@ -662,11 +673,12 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
>  {
>  	struct device_node *np;
>  	const struct of_device_id *m;
> +	unsigned long flags;
>  
>  	if (match)
>  		*match = NULL;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	np = from ? from->allnext : of_allnodes;
>  	for (; np; np = np->allnext) {
>  		m = __of_match_node(matches, np);
> @@ -677,7 +689,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
>  		}
>  	}
>  	of_node_put(from);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return np;
>  }
>  EXPORT_SYMBOL(of_find_matching_node_and_match);
> @@ -720,12 +732,12 @@ struct device_node *of_find_node_by_phandle(phandle handle)
>  {
>  	struct device_node *np;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock(&devtree_lock);
>  	for (np = of_allnodes; np; np = np->allnext)
>  		if (np->phandle == handle)
>  			break;
>  	of_node_get(np);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock(&devtree_lock);
>  	return np;
>  }
>  EXPORT_SYMBOL(of_find_node_by_phandle);
> @@ -1197,18 +1209,18 @@ int of_add_property(struct device_node *np, struct property *prop)
>  		return rc;
>  
>  	prop->next = NULL;
> -	write_lock_irqsave(&devtree_lock, flags);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	next = &np->properties;
>  	while (*next) {
>  		if (strcmp(prop->name, (*next)->name) == 0) {
>  			/* duplicate ! don't insert it */
> -			write_unlock_irqrestore(&devtree_lock, flags);
> +			raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  			return -1;
>  		}
>  		next = &(*next)->next;
>  	}
>  	*next = prop;
> -	write_unlock_irqrestore(&devtree_lock, flags);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  
>  #ifdef CONFIG_PROC_DEVICETREE
>  	/* try to add to proc as well if it was initialized */
> @@ -1238,7 +1250,7 @@ int of_remove_property(struct device_node *np, struct property *prop)
>  	if (rc)
>  		return rc;
>  
> -	write_lock_irqsave(&devtree_lock, flags);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	next = &np->properties;
>  	while (*next) {
>  		if (*next == prop) {
> @@ -1251,7 +1263,7 @@ int of_remove_property(struct device_node *np, struct property *prop)
>  		}
>  		next = &(*next)->next;
>  	}
> -	write_unlock_irqrestore(&devtree_lock, flags);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  
>  	if (!found)
>  		return -ENODEV;
> @@ -1291,7 +1303,7 @@ int of_update_property(struct device_node *np, struct property *newprop)
>  	if (!oldprop)
>  		return of_add_property(np, newprop);
>  
> -	write_lock_irqsave(&devtree_lock, flags);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	next = &np->properties;
>  	while (*next) {
>  		if (*next == oldprop) {
> @@ -1305,7 +1317,7 @@ int of_update_property(struct device_node *np, struct property *newprop)
>  		}
>  		next = &(*next)->next;
>  	}
> -	write_unlock_irqrestore(&devtree_lock, flags);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  
>  	if (!found)
>  		return -ENODEV;
> @@ -1378,12 +1390,12 @@ int of_attach_node(struct device_node *np)
>  	if (rc)
>  		return rc;
>  
> -	write_lock_irqsave(&devtree_lock, flags);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	np->sibling = np->parent->child;
>  	np->allnext = of_allnodes;
>  	np->parent->child = np;
>  	of_allnodes = np;
> -	write_unlock_irqrestore(&devtree_lock, flags);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  
>  	of_add_proc_dt_entry(np);
>  	return 0;
> @@ -1426,7 +1438,7 @@ int of_detach_node(struct device_node *np)
>  	if (rc)
>  		return rc;
>  
> -	write_lock_irqsave(&devtree_lock, flags);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  
>  	if (of_node_check_flag(np, OF_DETACHED)) {
>  		/* someone already detached it */
> @@ -1463,7 +1475,7 @@ int of_detach_node(struct device_node *np)
>  	}
>  
>  	of_node_set_flag(np, OF_DETACHED);
> -	write_unlock_irqrestore(&devtree_lock, flags);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  
>  	of_remove_proc_dt_entry(np);
>  	return rc;
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 5ebcc5c..bb35c42 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -92,7 +92,7 @@ static inline void of_node_put(struct device_node *node) { }
>  extern struct device_node *of_allnodes;
>  extern struct device_node *of_chosen;
>  extern struct device_node *of_aliases;
> -extern rwlock_t devtree_lock;
> +extern raw_spinlock_t devtree_lock;
>  
>  static inline bool of_have_populated_dt(void)
>  {
> 


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH next v2] OF: convert devtree lock from rw_lock to raw spinlock
  2013-02-04 16:05 [PATCH next] OF: convert devtree lock from rw_lock to raw spinlock Paul Gortmaker
  2013-02-04 17:54 ` David Miller
  2013-02-06 16:04 ` Rob Herring
@ 2013-02-06 20:30 ` Paul Gortmaker
  2013-02-08 23:09   ` Rob Herring
  2 siblings, 1 reply; 10+ messages in thread
From: Paul Gortmaker @ 2013-02-06 20:30 UTC (permalink / raw)
  To: Rob Herring
  Cc: Grant Likely, Sam Ravnborg, devicetree-discuss, sparclinux,
	linux-rt-users, linux-kernel, Thomas Gleixner, Paul Gortmaker

From: Thomas Gleixner <tglx@linutronix.de>

With the locking cleanup in place (from "OF: Fixup resursive
locking code paths"), we can now do the conversion from the
rw_lock to a raw spinlock as required for preempt-rt.

The previous cleanup and this conversion were originally
separate since they predated when mainline got raw spinlock (in
commit c2f21ce2e31286a "locking: Implement new raw_spinlock").

So, at that point in time, the cleanup was considered plausible
for mainline, but not this conversion.  In any case, we've kept
them separate as it makes for easier review and better bisection.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
[PG: taken from preempt-rt, update subject & add a commit log]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---

[v2: recent commit e81b329 ("powerpc+of: Add /proc device tree
 updating to of node add/remove") added two more instances of
 write_unlock that also needed converting to raw_spin_unlock.
 Retested (boot) on sbc8548, defconfig builds on arm/sparc; no
 new warnings observed.]

 arch/sparc/kernel/prom_common.c |   4 +-
 drivers/of/base.c               | 100 ++++++++++++++++++++++------------------
 include/linux/of.h              |   2 +-
 3 files changed, 59 insertions(+), 47 deletions(-)

diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c
index 1303021..9f20566 100644
--- a/arch/sparc/kernel/prom_common.c
+++ b/arch/sparc/kernel/prom_common.c
@@ -64,7 +64,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
 	err = -ENODEV;
 
 	mutex_lock(&of_set_property_mutex);
-	write_lock(&devtree_lock);
+	raw_spin_lock(&devtree_lock);
 	prevp = &dp->properties;
 	while (*prevp) {
 		struct property *prop = *prevp;
@@ -91,7 +91,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
 		}
 		prevp = &(*prevp)->next;
 	}
-	write_unlock(&devtree_lock);
+	raw_spin_unlock(&devtree_lock);
 	mutex_unlock(&of_set_property_mutex);
 
 	/* XXX Upate procfs if necessary... */
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 16ee7a0..f86be55 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -55,7 +55,7 @@ static DEFINE_MUTEX(of_aliases_mutex);
 /* use when traversing tree through the allnext, child, sibling,
  * or parent members of struct device_node.
  */
-DEFINE_RWLOCK(devtree_lock);
+DEFINE_RAW_SPINLOCK(devtree_lock);
 
 int of_n_addr_cells(struct device_node *np)
 {
@@ -188,10 +188,11 @@ struct property *of_find_property(const struct device_node *np,
 				  int *lenp)
 {
 	struct property *pp;
+	unsigned long flags;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	pp = __of_find_property(np, name, lenp);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
 	return pp;
 }
@@ -209,13 +210,13 @@ struct device_node *of_find_all_nodes(struct device_node *prev)
 {
 	struct device_node *np;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock(&devtree_lock);
 	np = prev ? prev->allnext : of_allnodes;
 	for (; np != NULL; np = np->allnext)
 		if (of_node_get(np))
 			break;
 	of_node_put(prev);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock(&devtree_lock);
 	return np;
 }
 EXPORT_SYMBOL(of_find_all_nodes);
@@ -274,11 +275,12 @@ static int __of_device_is_compatible(const struct device_node *device,
 int of_device_is_compatible(const struct device_node *device,
 		const char *compat)
 {
+	unsigned long flags;
 	int res;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	res = __of_device_is_compatible(device, compat);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return res;
 }
 EXPORT_SYMBOL(of_device_is_compatible);
@@ -340,13 +342,14 @@ EXPORT_SYMBOL(of_device_is_available);
 struct device_node *of_get_parent(const struct device_node *node)
 {
 	struct device_node *np;
+	unsigned long flags;
 
 	if (!node)
 		return NULL;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	np = of_node_get(node->parent);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return np;
 }
 EXPORT_SYMBOL(of_get_parent);
@@ -365,14 +368,15 @@ EXPORT_SYMBOL(of_get_parent);
 struct device_node *of_get_next_parent(struct device_node *node)
 {
 	struct device_node *parent;
+	unsigned long flags;
 
 	if (!node)
 		return NULL;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	parent = of_node_get(node->parent);
 	of_node_put(node);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return parent;
 }
 
@@ -388,14 +392,15 @@ struct device_node *of_get_next_child(const struct device_node *node,
 	struct device_node *prev)
 {
 	struct device_node *next;
+	unsigned long flags;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	next = prev ? prev->sibling : node->child;
 	for (; next; next = next->sibling)
 		if (of_node_get(next))
 			break;
 	of_node_put(prev);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return next;
 }
 EXPORT_SYMBOL(of_get_next_child);
@@ -413,7 +418,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
 {
 	struct device_node *next;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock(&devtree_lock);
 	next = prev ? prev->sibling : node->child;
 	for (; next; next = next->sibling) {
 		if (!of_device_is_available(next))
@@ -422,7 +427,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
 			break;
 	}
 	of_node_put(prev);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock(&devtree_lock);
 	return next;
 }
 EXPORT_SYMBOL(of_get_next_available_child);
@@ -460,14 +465,15 @@ EXPORT_SYMBOL(of_get_child_by_name);
 struct device_node *of_find_node_by_path(const char *path)
 {
 	struct device_node *np = of_allnodes;
+	unsigned long flags;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	for (; np; np = np->allnext) {
 		if (np->full_name && (of_node_cmp(np->full_name, path) == 0)
 		    && of_node_get(np))
 			break;
 	}
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return np;
 }
 EXPORT_SYMBOL(of_find_node_by_path);
@@ -487,15 +493,16 @@ struct device_node *of_find_node_by_name(struct device_node *from,
 	const char *name)
 {
 	struct device_node *np;
+	unsigned long flags;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	np = from ? from->allnext : of_allnodes;
 	for (; np; np = np->allnext)
 		if (np->name && (of_node_cmp(np->name, name) == 0)
 		    && of_node_get(np))
 			break;
 	of_node_put(from);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return np;
 }
 EXPORT_SYMBOL(of_find_node_by_name);
@@ -516,15 +523,16 @@ struct device_node *of_find_node_by_type(struct device_node *from,
 	const char *type)
 {
 	struct device_node *np;
+	unsigned long flags;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	np = from ? from->allnext : of_allnodes;
 	for (; np; np = np->allnext)
 		if (np->type && (of_node_cmp(np->type, type) == 0)
 		    && of_node_get(np))
 			break;
 	of_node_put(from);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return np;
 }
 EXPORT_SYMBOL(of_find_node_by_type);
@@ -547,8 +555,9 @@ struct device_node *of_find_compatible_node(struct device_node *from,
 	const char *type, const char *compatible)
 {
 	struct device_node *np;
+	unsigned long flags;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	np = from ? from->allnext : of_allnodes;
 	for (; np; np = np->allnext) {
 		if (type
@@ -559,7 +568,7 @@ struct device_node *of_find_compatible_node(struct device_node *from,
 			break;
 	}
 	of_node_put(from);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return np;
 }
 EXPORT_SYMBOL(of_find_compatible_node);
@@ -581,8 +590,9 @@ struct device_node *of_find_node_with_property(struct device_node *from,
 {
 	struct device_node *np;
 	struct property *pp;
+	unsigned long flags;
 
-	read_lock(&devtree_lock);
+	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) {
@@ -594,7 +604,7 @@ struct device_node *of_find_node_with_property(struct device_node *from,
 	}
 out:
 	of_node_put(from);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return np;
 }
 EXPORT_SYMBOL(of_find_node_with_property);
@@ -635,10 +645,11 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
 					 const struct device_node *node)
 {
 	const struct of_device_id *match;
+	unsigned long flags;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	match = __of_match_node(matches, node);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return match;
 }
 EXPORT_SYMBOL(of_match_node);
@@ -662,11 +673,12 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
 {
 	struct device_node *np;
 	const struct of_device_id *m;
+	unsigned long flags;
 
 	if (match)
 		*match = NULL;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	np = from ? from->allnext : of_allnodes;
 	for (; np; np = np->allnext) {
 		m = __of_match_node(matches, np);
@@ -677,7 +689,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
 		}
 	}
 	of_node_put(from);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return np;
 }
 EXPORT_SYMBOL(of_find_matching_node_and_match);
@@ -720,12 +732,12 @@ struct device_node *of_find_node_by_phandle(phandle handle)
 {
 	struct device_node *np;
 
-	read_lock(&devtree_lock);
+	raw_spin_lock(&devtree_lock);
 	for (np = of_allnodes; np; np = np->allnext)
 		if (np->phandle == handle)
 			break;
 	of_node_get(np);
-	read_unlock(&devtree_lock);
+	raw_spin_unlock(&devtree_lock);
 	return np;
 }
 EXPORT_SYMBOL(of_find_node_by_phandle);
@@ -1197,18 +1209,18 @@ int of_add_property(struct device_node *np, struct property *prop)
 		return rc;
 
 	prop->next = NULL;
-	write_lock_irqsave(&devtree_lock, flags);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	next = &np->properties;
 	while (*next) {
 		if (strcmp(prop->name, (*next)->name) == 0) {
 			/* duplicate ! don't insert it */
-			write_unlock_irqrestore(&devtree_lock, flags);
+			raw_spin_unlock_irqrestore(&devtree_lock, flags);
 			return -1;
 		}
 		next = &(*next)->next;
 	}
 	*next = prop;
-	write_unlock_irqrestore(&devtree_lock, flags);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
 #ifdef CONFIG_PROC_DEVICETREE
 	/* try to add to proc as well if it was initialized */
@@ -1238,7 +1250,7 @@ int of_remove_property(struct device_node *np, struct property *prop)
 	if (rc)
 		return rc;
 
-	write_lock_irqsave(&devtree_lock, flags);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	next = &np->properties;
 	while (*next) {
 		if (*next == prop) {
@@ -1251,7 +1263,7 @@ int of_remove_property(struct device_node *np, struct property *prop)
 		}
 		next = &(*next)->next;
 	}
-	write_unlock_irqrestore(&devtree_lock, flags);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
 	if (!found)
 		return -ENODEV;
@@ -1291,7 +1303,7 @@ int of_update_property(struct device_node *np, struct property *newprop)
 	if (!oldprop)
 		return of_add_property(np, newprop);
 
-	write_lock_irqsave(&devtree_lock, flags);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	next = &np->properties;
 	while (*next) {
 		if (*next == oldprop) {
@@ -1305,7 +1317,7 @@ int of_update_property(struct device_node *np, struct property *newprop)
 		}
 		next = &(*next)->next;
 	}
-	write_unlock_irqrestore(&devtree_lock, flags);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
 	if (!found)
 		return -ENODEV;
@@ -1378,12 +1390,12 @@ int of_attach_node(struct device_node *np)
 	if (rc)
 		return rc;
 
-	write_lock_irqsave(&devtree_lock, flags);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 	np->sibling = np->parent->child;
 	np->allnext = of_allnodes;
 	np->parent->child = np;
 	of_allnodes = np;
-	write_unlock_irqrestore(&devtree_lock, flags);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
 	of_add_proc_dt_entry(np);
 	return 0;
@@ -1426,17 +1438,17 @@ int of_detach_node(struct device_node *np)
 	if (rc)
 		return rc;
 
-	write_lock_irqsave(&devtree_lock, flags);
+	raw_spin_lock_irqsave(&devtree_lock, flags);
 
 	if (of_node_check_flag(np, OF_DETACHED)) {
 		/* someone already detached it */
-		write_unlock_irqrestore(&devtree_lock, flags);
+		raw_spin_unlock_irqrestore(&devtree_lock, flags);
 		return rc;
 	}
 
 	parent = np->parent;
 	if (!parent) {
-		write_unlock_irqrestore(&devtree_lock, flags);
+		raw_spin_unlock_irqrestore(&devtree_lock, flags);
 		return rc;
 	}
 
@@ -1463,7 +1475,7 @@ int of_detach_node(struct device_node *np)
 	}
 
 	of_node_set_flag(np, OF_DETACHED);
-	write_unlock_irqrestore(&devtree_lock, flags);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
 	of_remove_proc_dt_entry(np);
 	return rc;
diff --git a/include/linux/of.h b/include/linux/of.h
index 5ebcc5c..bb35c42 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -92,7 +92,7 @@ static inline void of_node_put(struct device_node *node) { }
 extern struct device_node *of_allnodes;
 extern struct device_node *of_chosen;
 extern struct device_node *of_aliases;
-extern rwlock_t devtree_lock;
+extern raw_spinlock_t devtree_lock;
 
 static inline bool of_have_populated_dt(void)
 {
-- 
1.8.1.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH next v2] OF: convert devtree lock from rw_lock to raw spinlock
  2013-02-06 20:30 ` [PATCH next v2] " Paul Gortmaker
@ 2013-02-08 23:09   ` Rob Herring
  2013-02-11 19:29     ` Stephen Warren
  0 siblings, 1 reply; 10+ messages in thread
From: Rob Herring @ 2013-02-08 23:09 UTC (permalink / raw)
  To: Paul Gortmaker
  Cc: Grant Likely, Sam Ravnborg, devicetree-discuss, sparclinux,
	linux-rt-users, linux-kernel, Thomas Gleixner

On 02/06/2013 02:30 PM, Paul Gortmaker wrote:
> From: Thomas Gleixner <tglx@linutronix.de>
> 
> With the locking cleanup in place (from "OF: Fixup resursive
> locking code paths"), we can now do the conversion from the
> rw_lock to a raw spinlock as required for preempt-rt.
> 
> The previous cleanup and this conversion were originally
> separate since they predated when mainline got raw spinlock (in
> commit c2f21ce2e31286a "locking: Implement new raw_spinlock").
> 
> So, at that point in time, the cleanup was considered plausible
> for mainline, but not this conversion.  In any case, we've kept
> them separate as it makes for easier review and better bisection.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> [PG: taken from preempt-rt, update subject & add a commit log]
> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
> ---
> 
> [v2: recent commit e81b329 ("powerpc+of: Add /proc device tree
>  updating to of node add/remove") added two more instances of
>  write_unlock that also needed converting to raw_spin_unlock.
>  Retested (boot) on sbc8548, defconfig builds on arm/sparc; no
>  new warnings observed.]
> 
>  arch/sparc/kernel/prom_common.c |   4 +-
>  drivers/of/base.c               | 100 ++++++++++++++++++++++------------------
>  include/linux/of.h              |   2 +-
>  3 files changed, 59 insertions(+), 47 deletions(-)

Applied.

Rob

> 
> diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c
> index 1303021..9f20566 100644
> --- a/arch/sparc/kernel/prom_common.c
> +++ b/arch/sparc/kernel/prom_common.c
> @@ -64,7 +64,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
>  	err = -ENODEV;
>  
>  	mutex_lock(&of_set_property_mutex);
> -	write_lock(&devtree_lock);
> +	raw_spin_lock(&devtree_lock);
>  	prevp = &dp->properties;
>  	while (*prevp) {
>  		struct property *prop = *prevp;
> @@ -91,7 +91,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
>  		}
>  		prevp = &(*prevp)->next;
>  	}
> -	write_unlock(&devtree_lock);
> +	raw_spin_unlock(&devtree_lock);
>  	mutex_unlock(&of_set_property_mutex);
>  
>  	/* XXX Upate procfs if necessary... */
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 16ee7a0..f86be55 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -55,7 +55,7 @@ static DEFINE_MUTEX(of_aliases_mutex);
>  /* use when traversing tree through the allnext, child, sibling,
>   * or parent members of struct device_node.
>   */
> -DEFINE_RWLOCK(devtree_lock);
> +DEFINE_RAW_SPINLOCK(devtree_lock);
>  
>  int of_n_addr_cells(struct device_node *np)
>  {
> @@ -188,10 +188,11 @@ struct property *of_find_property(const struct device_node *np,
>  				  int *lenp)
>  {
>  	struct property *pp;
> +	unsigned long flags;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	pp = __of_find_property(np, name, lenp);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  
>  	return pp;
>  }
> @@ -209,13 +210,13 @@ struct device_node *of_find_all_nodes(struct device_node *prev)
>  {
>  	struct device_node *np;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock(&devtree_lock);
>  	np = prev ? prev->allnext : of_allnodes;
>  	for (; np != NULL; np = np->allnext)
>  		if (of_node_get(np))
>  			break;
>  	of_node_put(prev);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock(&devtree_lock);
>  	return np;
>  }
>  EXPORT_SYMBOL(of_find_all_nodes);
> @@ -274,11 +275,12 @@ static int __of_device_is_compatible(const struct device_node *device,
>  int of_device_is_compatible(const struct device_node *device,
>  		const char *compat)
>  {
> +	unsigned long flags;
>  	int res;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	res = __of_device_is_compatible(device, compat);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return res;
>  }
>  EXPORT_SYMBOL(of_device_is_compatible);
> @@ -340,13 +342,14 @@ EXPORT_SYMBOL(of_device_is_available);
>  struct device_node *of_get_parent(const struct device_node *node)
>  {
>  	struct device_node *np;
> +	unsigned long flags;
>  
>  	if (!node)
>  		return NULL;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	np = of_node_get(node->parent);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return np;
>  }
>  EXPORT_SYMBOL(of_get_parent);
> @@ -365,14 +368,15 @@ EXPORT_SYMBOL(of_get_parent);
>  struct device_node *of_get_next_parent(struct device_node *node)
>  {
>  	struct device_node *parent;
> +	unsigned long flags;
>  
>  	if (!node)
>  		return NULL;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	parent = of_node_get(node->parent);
>  	of_node_put(node);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return parent;
>  }
>  
> @@ -388,14 +392,15 @@ struct device_node *of_get_next_child(const struct device_node *node,
>  	struct device_node *prev)
>  {
>  	struct device_node *next;
> +	unsigned long flags;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	next = prev ? prev->sibling : node->child;
>  	for (; next; next = next->sibling)
>  		if (of_node_get(next))
>  			break;
>  	of_node_put(prev);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return next;
>  }
>  EXPORT_SYMBOL(of_get_next_child);
> @@ -413,7 +418,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
>  {
>  	struct device_node *next;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock(&devtree_lock);
>  	next = prev ? prev->sibling : node->child;
>  	for (; next; next = next->sibling) {
>  		if (!of_device_is_available(next))
> @@ -422,7 +427,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
>  			break;
>  	}
>  	of_node_put(prev);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock(&devtree_lock);
>  	return next;
>  }
>  EXPORT_SYMBOL(of_get_next_available_child);
> @@ -460,14 +465,15 @@ EXPORT_SYMBOL(of_get_child_by_name);
>  struct device_node *of_find_node_by_path(const char *path)
>  {
>  	struct device_node *np = of_allnodes;
> +	unsigned long flags;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	for (; np; np = np->allnext) {
>  		if (np->full_name && (of_node_cmp(np->full_name, path) == 0)
>  		    && of_node_get(np))
>  			break;
>  	}
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return np;
>  }
>  EXPORT_SYMBOL(of_find_node_by_path);
> @@ -487,15 +493,16 @@ struct device_node *of_find_node_by_name(struct device_node *from,
>  	const char *name)
>  {
>  	struct device_node *np;
> +	unsigned long flags;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	np = from ? from->allnext : of_allnodes;
>  	for (; np; np = np->allnext)
>  		if (np->name && (of_node_cmp(np->name, name) == 0)
>  		    && of_node_get(np))
>  			break;
>  	of_node_put(from);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return np;
>  }
>  EXPORT_SYMBOL(of_find_node_by_name);
> @@ -516,15 +523,16 @@ struct device_node *of_find_node_by_type(struct device_node *from,
>  	const char *type)
>  {
>  	struct device_node *np;
> +	unsigned long flags;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	np = from ? from->allnext : of_allnodes;
>  	for (; np; np = np->allnext)
>  		if (np->type && (of_node_cmp(np->type, type) == 0)
>  		    && of_node_get(np))
>  			break;
>  	of_node_put(from);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return np;
>  }
>  EXPORT_SYMBOL(of_find_node_by_type);
> @@ -547,8 +555,9 @@ struct device_node *of_find_compatible_node(struct device_node *from,
>  	const char *type, const char *compatible)
>  {
>  	struct device_node *np;
> +	unsigned long flags;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	np = from ? from->allnext : of_allnodes;
>  	for (; np; np = np->allnext) {
>  		if (type
> @@ -559,7 +568,7 @@ struct device_node *of_find_compatible_node(struct device_node *from,
>  			break;
>  	}
>  	of_node_put(from);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return np;
>  }
>  EXPORT_SYMBOL(of_find_compatible_node);
> @@ -581,8 +590,9 @@ struct device_node *of_find_node_with_property(struct device_node *from,
>  {
>  	struct device_node *np;
>  	struct property *pp;
> +	unsigned long flags;
>  
> -	read_lock(&devtree_lock);
> +	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) {
> @@ -594,7 +604,7 @@ struct device_node *of_find_node_with_property(struct device_node *from,
>  	}
>  out:
>  	of_node_put(from);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return np;
>  }
>  EXPORT_SYMBOL(of_find_node_with_property);
> @@ -635,10 +645,11 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
>  					 const struct device_node *node)
>  {
>  	const struct of_device_id *match;
> +	unsigned long flags;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	match = __of_match_node(matches, node);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return match;
>  }
>  EXPORT_SYMBOL(of_match_node);
> @@ -662,11 +673,12 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
>  {
>  	struct device_node *np;
>  	const struct of_device_id *m;
> +	unsigned long flags;
>  
>  	if (match)
>  		*match = NULL;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	np = from ? from->allnext : of_allnodes;
>  	for (; np; np = np->allnext) {
>  		m = __of_match_node(matches, np);
> @@ -677,7 +689,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
>  		}
>  	}
>  	of_node_put(from);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	return np;
>  }
>  EXPORT_SYMBOL(of_find_matching_node_and_match);
> @@ -720,12 +732,12 @@ struct device_node *of_find_node_by_phandle(phandle handle)
>  {
>  	struct device_node *np;
>  
> -	read_lock(&devtree_lock);
> +	raw_spin_lock(&devtree_lock);
>  	for (np = of_allnodes; np; np = np->allnext)
>  		if (np->phandle == handle)
>  			break;
>  	of_node_get(np);
> -	read_unlock(&devtree_lock);
> +	raw_spin_unlock(&devtree_lock);
>  	return np;
>  }
>  EXPORT_SYMBOL(of_find_node_by_phandle);
> @@ -1197,18 +1209,18 @@ int of_add_property(struct device_node *np, struct property *prop)
>  		return rc;
>  
>  	prop->next = NULL;
> -	write_lock_irqsave(&devtree_lock, flags);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	next = &np->properties;
>  	while (*next) {
>  		if (strcmp(prop->name, (*next)->name) == 0) {
>  			/* duplicate ! don't insert it */
> -			write_unlock_irqrestore(&devtree_lock, flags);
> +			raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  			return -1;
>  		}
>  		next = &(*next)->next;
>  	}
>  	*next = prop;
> -	write_unlock_irqrestore(&devtree_lock, flags);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  
>  #ifdef CONFIG_PROC_DEVICETREE
>  	/* try to add to proc as well if it was initialized */
> @@ -1238,7 +1250,7 @@ int of_remove_property(struct device_node *np, struct property *prop)
>  	if (rc)
>  		return rc;
>  
> -	write_lock_irqsave(&devtree_lock, flags);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	next = &np->properties;
>  	while (*next) {
>  		if (*next == prop) {
> @@ -1251,7 +1263,7 @@ int of_remove_property(struct device_node *np, struct property *prop)
>  		}
>  		next = &(*next)->next;
>  	}
> -	write_unlock_irqrestore(&devtree_lock, flags);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  
>  	if (!found)
>  		return -ENODEV;
> @@ -1291,7 +1303,7 @@ int of_update_property(struct device_node *np, struct property *newprop)
>  	if (!oldprop)
>  		return of_add_property(np, newprop);
>  
> -	write_lock_irqsave(&devtree_lock, flags);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	next = &np->properties;
>  	while (*next) {
>  		if (*next == oldprop) {
> @@ -1305,7 +1317,7 @@ int of_update_property(struct device_node *np, struct property *newprop)
>  		}
>  		next = &(*next)->next;
>  	}
> -	write_unlock_irqrestore(&devtree_lock, flags);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  
>  	if (!found)
>  		return -ENODEV;
> @@ -1378,12 +1390,12 @@ int of_attach_node(struct device_node *np)
>  	if (rc)
>  		return rc;
>  
> -	write_lock_irqsave(&devtree_lock, flags);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  	np->sibling = np->parent->child;
>  	np->allnext = of_allnodes;
>  	np->parent->child = np;
>  	of_allnodes = np;
> -	write_unlock_irqrestore(&devtree_lock, flags);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  
>  	of_add_proc_dt_entry(np);
>  	return 0;
> @@ -1426,17 +1438,17 @@ int of_detach_node(struct device_node *np)
>  	if (rc)
>  		return rc;
>  
> -	write_lock_irqsave(&devtree_lock, flags);
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>  
>  	if (of_node_check_flag(np, OF_DETACHED)) {
>  		/* someone already detached it */
> -		write_unlock_irqrestore(&devtree_lock, flags);
> +		raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  		return rc;
>  	}
>  
>  	parent = np->parent;
>  	if (!parent) {
> -		write_unlock_irqrestore(&devtree_lock, flags);
> +		raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  		return rc;
>  	}
>  
> @@ -1463,7 +1475,7 @@ int of_detach_node(struct device_node *np)
>  	}
>  
>  	of_node_set_flag(np, OF_DETACHED);
> -	write_unlock_irqrestore(&devtree_lock, flags);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  
>  	of_remove_proc_dt_entry(np);
>  	return rc;
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 5ebcc5c..bb35c42 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -92,7 +92,7 @@ static inline void of_node_put(struct device_node *node) { }
>  extern struct device_node *of_allnodes;
>  extern struct device_node *of_chosen;
>  extern struct device_node *of_aliases;
> -extern rwlock_t devtree_lock;
> +extern raw_spinlock_t devtree_lock;
>  
>  static inline bool of_have_populated_dt(void)
>  {
> 


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH next v2] OF: convert devtree lock from rw_lock to raw spinlock
  2013-02-08 23:09   ` Rob Herring
@ 2013-02-11 19:29     ` Stephen Warren
  2013-02-11 19:54       ` Rob Herring
  0 siblings, 1 reply; 10+ messages in thread
From: Stephen Warren @ 2013-02-11 19:29 UTC (permalink / raw)
  To: Rob Herring, Thomas Gleixner
  Cc: Paul Gortmaker, linux-rt-users, devicetree-discuss, linux-kernel,
	sparclinux, Sam Ravnborg, linux-next

On 02/08/2013 04:09 PM, Rob Herring wrote:
> On 02/06/2013 02:30 PM, Paul Gortmaker wrote:
>> From: Thomas Gleixner <tglx@linutronix.de>
>>
>> With the locking cleanup in place (from "OF: Fixup resursive
>> locking code paths"), we can now do the conversion from the
>> rw_lock to a raw spinlock as required for preempt-rt.
>>
>> The previous cleanup and this conversion were originally
>> separate since they predated when mainline got raw spinlock (in
>> commit c2f21ce2e31286a "locking: Implement new raw_spinlock").
>>
>> So, at that point in time, the cleanup was considered plausible
>> for mainline, but not this conversion.  In any case, we've kept
>> them separate as it makes for easier review and better bisection.
>>
>> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
>> [PG: taken from preempt-rt, update subject & add a commit log]
>> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
>> ---
>>
>> [v2: recent commit e81b329 ("powerpc+of: Add /proc device tree
>>  updating to of node add/remove") added two more instances of
>>  write_unlock that also needed converting to raw_spin_unlock.
>>  Retested (boot) on sbc8548, defconfig builds on arm/sparc; no
>>  new warnings observed.]
>>
>>  arch/sparc/kernel/prom_common.c |   4 +-
>>  drivers/of/base.c               | 100 ++++++++++++++++++++++------------------
>>  include/linux/of.h              |   2 +-
>>  3 files changed, 59 insertions(+), 47 deletions(-)
> 
> Applied.

This commit is present in next-20130211, and causes a boot failure
(hang) early while booting on Tegra. Reverting just this one commit
solves the issue.

I'll see if I can track down where the issue is. Given the commit
description, I assume there's some new recursive lock issue that snuck
in between the previous fix for them and this commit? Any hints welcome.

One thing I wonder looking at the patch: Most paths use
raw_spin_lock_irqsave() but a few use just raw_spin_lock(). I wonder how
that decision was made?

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH next v2] OF: convert devtree lock from rw_lock to raw spinlock
  2013-02-11 19:29     ` Stephen Warren
@ 2013-02-11 19:54       ` Rob Herring
  2013-02-11 22:18         ` Grant Likely
  0 siblings, 1 reply; 10+ messages in thread
From: Rob Herring @ 2013-02-11 19:54 UTC (permalink / raw)
  To: Stephen Warren, Paul Gortmaker
  Cc: Thomas Gleixner, linux-rt-users, devicetree-discuss,
	linux-kernel, sparclinux, Sam Ravnborg, linux-next

On 02/11/2013 01:29 PM, Stephen Warren wrote:
> On 02/08/2013 04:09 PM, Rob Herring wrote:
>> On 02/06/2013 02:30 PM, Paul Gortmaker wrote:
>>> From: Thomas Gleixner <tglx@linutronix.de>
>>>
>>> With the locking cleanup in place (from "OF: Fixup resursive
>>> locking code paths"), we can now do the conversion from the
>>> rw_lock to a raw spinlock as required for preempt-rt.
>>>
>>> The previous cleanup and this conversion were originally
>>> separate since they predated when mainline got raw spinlock (in
>>> commit c2f21ce2e31286a "locking: Implement new raw_spinlock").
>>>
>>> So, at that point in time, the cleanup was considered plausible
>>> for mainline, but not this conversion.  In any case, we've kept
>>> them separate as it makes for easier review and better bisection.
>>>
>>> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
>>> [PG: taken from preempt-rt, update subject & add a commit log]
>>> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
>>> ---
>>>
>>> [v2: recent commit e81b329 ("powerpc+of: Add /proc device tree
>>>  updating to of node add/remove") added two more instances of
>>>  write_unlock that also needed converting to raw_spin_unlock.
>>>  Retested (boot) on sbc8548, defconfig builds on arm/sparc; no
>>>  new warnings observed.]
>>>
>>>  arch/sparc/kernel/prom_common.c |   4 +-
>>>  drivers/of/base.c               | 100 ++++++++++++++++++++++------------------
>>>  include/linux/of.h              |   2 +-
>>>  3 files changed, 59 insertions(+), 47 deletions(-)
>>
>> Applied.
> 
> This commit is present in next-20130211, and causes a boot failure
> (hang) early while booting on Tegra. Reverting just this one commit
> solves the issue.
> 
> I'll see if I can track down where the issue is. Given the commit
> description, I assume there's some new recursive lock issue that snuck
> in between the previous fix for them and this commit? Any hints welcome.
> 
> One thing I wonder looking at the patch: Most paths use
> raw_spin_lock_irqsave() but a few use just raw_spin_lock(). I wonder how
> that decision was made?

I found the problem. of_get_next_available_child ->
of_device_is_available -> of_get_property -> of_get_property. An
unlocked version of of_device_is_available is needed here.

Rob

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH next v2] OF: convert devtree lock from rw_lock to raw spinlock
  2013-02-11 19:54       ` Rob Herring
@ 2013-02-11 22:18         ` Grant Likely
  2013-02-11 22:21           ` Rob Herring
  0 siblings, 1 reply; 10+ messages in thread
From: Grant Likely @ 2013-02-11 22:18 UTC (permalink / raw)
  To: Rob Herring
  Cc: Stephen Warren, Paul Gortmaker, Thomas Gleixner, rt-users,
	devicetree-discuss, Linux Kernel Mailing List, sparclinux,
	Sam Ravnborg, linux-next

On Mon, Feb 11, 2013 at 7:54 PM, Rob Herring <robherring2@gmail.com> wrote:
> On 02/11/2013 01:29 PM, Stephen Warren wrote:
>> On 02/08/2013 04:09 PM, Rob Herring wrote:
>>> On 02/06/2013 02:30 PM, Paul Gortmaker wrote:
>>>> From: Thomas Gleixner <tglx@linutronix.de>
>>>>
>>>> With the locking cleanup in place (from "OF: Fixup resursive
>>>> locking code paths"), we can now do the conversion from the
>>>> rw_lock to a raw spinlock as required for preempt-rt.
>>>>
>>>> The previous cleanup and this conversion were originally
>>>> separate since they predated when mainline got raw spinlock (in
>>>> commit c2f21ce2e31286a "locking: Implement new raw_spinlock").
>>>>
>>>> So, at that point in time, the cleanup was considered plausible
>>>> for mainline, but not this conversion.  In any case, we've kept
>>>> them separate as it makes for easier review and better bisection.
>>>>
>>>> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
>>>> [PG: taken from preempt-rt, update subject & add a commit log]
>>>> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
>>>> ---
>>>>
>>>> [v2: recent commit e81b329 ("powerpc+of: Add /proc device tree
>>>>  updating to of node add/remove") added two more instances of
>>>>  write_unlock that also needed converting to raw_spin_unlock.
>>>>  Retested (boot) on sbc8548, defconfig builds on arm/sparc; no
>>>>  new warnings observed.]
>>>>
>>>>  arch/sparc/kernel/prom_common.c |   4 +-
>>>>  drivers/of/base.c               | 100 ++++++++++++++++++++++------------------
>>>>  include/linux/of.h              |   2 +-
>>>>  3 files changed, 59 insertions(+), 47 deletions(-)
>>>
>>> Applied.
>>
>> This commit is present in next-20130211, and causes a boot failure
>> (hang) early while booting on Tegra. Reverting just this one commit
>> solves the issue.
>>
>> I'll see if I can track down where the issue is. Given the commit
>> description, I assume there's some new recursive lock issue that snuck
>> in between the previous fix for them and this commit? Any hints welcome.
>>
>> One thing I wonder looking at the patch: Most paths use
>> raw_spin_lock_irqsave() but a few use just raw_spin_lock(). I wonder how
>> that decision was made?
>
> I found the problem. of_get_next_available_child ->
> of_device_is_available -> of_get_property -> of_get_property. An
> unlocked version of of_device_is_available is needed here.

Oops, I had testbooted on a single core machine which would mask the
issue. I've crafted a fix and am posting it for review before I apply
it.

g.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH next v2] OF: convert devtree lock from rw_lock to raw spinlock
  2013-02-11 22:18         ` Grant Likely
@ 2013-02-11 22:21           ` Rob Herring
  2013-02-11 22:29             ` Grant Likely
  0 siblings, 1 reply; 10+ messages in thread
From: Rob Herring @ 2013-02-11 22:21 UTC (permalink / raw)
  To: Grant Likely
  Cc: Stephen Warren, Paul Gortmaker, Thomas Gleixner, rt-users,
	devicetree-discuss, Linux Kernel Mailing List, sparclinux,
	Sam Ravnborg, linux-next

On 02/11/2013 04:18 PM, Grant Likely wrote:
> On Mon, Feb 11, 2013 at 7:54 PM, Rob Herring <robherring2@gmail.com> wrote:
>> On 02/11/2013 01:29 PM, Stephen Warren wrote:
>>> On 02/08/2013 04:09 PM, Rob Herring wrote:
>>>> On 02/06/2013 02:30 PM, Paul Gortmaker wrote:
>>>>> From: Thomas Gleixner <tglx@linutronix.de>
>>>>>
>>>>> With the locking cleanup in place (from "OF: Fixup resursive
>>>>> locking code paths"), we can now do the conversion from the
>>>>> rw_lock to a raw spinlock as required for preempt-rt.
>>>>>
>>>>> The previous cleanup and this conversion were originally
>>>>> separate since they predated when mainline got raw spinlock (in
>>>>> commit c2f21ce2e31286a "locking: Implement new raw_spinlock").
>>>>>
>>>>> So, at that point in time, the cleanup was considered plausible
>>>>> for mainline, but not this conversion.  In any case, we've kept
>>>>> them separate as it makes for easier review and better bisection.
>>>>>
>>>>> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
>>>>> [PG: taken from preempt-rt, update subject & add a commit log]
>>>>> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
>>>>> ---
>>>>>
>>>>> [v2: recent commit e81b329 ("powerpc+of: Add /proc device tree
>>>>>  updating to of node add/remove") added two more instances of
>>>>>  write_unlock that also needed converting to raw_spin_unlock.
>>>>>  Retested (boot) on sbc8548, defconfig builds on arm/sparc; no
>>>>>  new warnings observed.]
>>>>>
>>>>>  arch/sparc/kernel/prom_common.c |   4 +-
>>>>>  drivers/of/base.c               | 100 ++++++++++++++++++++++------------------
>>>>>  include/linux/of.h              |   2 +-
>>>>>  3 files changed, 59 insertions(+), 47 deletions(-)
>>>>
>>>> Applied.
>>>
>>> This commit is present in next-20130211, and causes a boot failure
>>> (hang) early while booting on Tegra. Reverting just this one commit
>>> solves the issue.
>>>
>>> I'll see if I can track down where the issue is. Given the commit
>>> description, I assume there's some new recursive lock issue that snuck
>>> in between the previous fix for them and this commit? Any hints welcome.
>>>
>>> One thing I wonder looking at the patch: Most paths use
>>> raw_spin_lock_irqsave() but a few use just raw_spin_lock(). I wonder how
>>> that decision was made?
>>
>> I found the problem. of_get_next_available_child ->
>> of_device_is_available -> of_get_property -> of_get_property. An
>> unlocked version of of_device_is_available is needed here.
> 
> Oops, I had testbooted on a single core machine which would mask the
> issue. I've crafted a fix and am posting it for review before I apply
> it.
> 

I'm in the process of applying Stephen's fix.

Rob

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH next v2] OF: convert devtree lock from rw_lock to raw spinlock
  2013-02-11 22:21           ` Rob Herring
@ 2013-02-11 22:29             ` Grant Likely
  0 siblings, 0 replies; 10+ messages in thread
From: Grant Likely @ 2013-02-11 22:29 UTC (permalink / raw)
  To: Rob Herring
  Cc: Stephen Warren, Paul Gortmaker, Thomas Gleixner, rt-users,
	devicetree-discuss, Linux Kernel Mailing List, sparclinux,
	Sam Ravnborg, linux-next

On Mon, Feb 11, 2013 at 10:21 PM, Rob Herring <robherring2@gmail.com> wrote:
> On 02/11/2013 04:18 PM, Grant Likely wrote:
>> On Mon, Feb 11, 2013 at 7:54 PM, Rob Herring <robherring2@gmail.com> wrote:
>>> I found the problem. of_get_next_available_child ->
>>> of_device_is_available -> of_get_property -> of_get_property. An
>>> unlocked version of of_device_is_available is needed here.
>>
>> Oops, I had testbooted on a single core machine which would mask the
>> issue. I've crafted a fix and am posting it for review before I apply
>> it.
>>
>
> I'm in the process of applying Stephen's fix.

I didn't actually see Stephen's fix until just now, after I had
already written, posted and pushed out basically the same thing. :-)

g.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2013-02-11 22:30 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-04 16:05 [PATCH next] OF: convert devtree lock from rw_lock to raw spinlock Paul Gortmaker
2013-02-04 17:54 ` David Miller
2013-02-06 16:04 ` Rob Herring
2013-02-06 20:30 ` [PATCH next v2] " Paul Gortmaker
2013-02-08 23:09   ` Rob Herring
2013-02-11 19:29     ` Stephen Warren
2013-02-11 19:54       ` Rob Herring
2013-02-11 22:18         ` Grant Likely
2013-02-11 22:21           ` Rob Herring
2013-02-11 22:29             ` Grant Likely

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).