[PATCH] OF: Fixup resursive locking code paths

Rob Herring robherring2 at gmail.com
Mon Jan 28 13:12:02 EST 2013


On 01/25/2013 12:21 PM, Paul Gortmaker wrote:
> From: Thomas Gleixner <tglx at linutronix.de>
> 
> There is no real reason to use a rwlock for devtree_lock. It even
> could be a mutex, but unfortunately it's locked from cpu hotplug
> paths which can't schedule :(
> 
> So it needs to become a raw lock on rt as well.  The devtree_lock would
> be the only user of a raw_rw_lock, so we are better off cleaning up the
> recursive locking paths which allows us to convert devtree_lock to a
> read_lock.
> 
> Here we do the standard thing of introducing __foo() as the "raw"
> version of foo(), so that we can take better control of the locking.
> The "raw" versions are not exported and are for internal use within
> the file itself.
> 
> Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
> Signed-off-by: Paul Gortmaker <paul.gortmaker at windriver.com>
> ---

Applied for 3.9.

Rob

> 
> [This has been living in the RT tree for several releases, and I've
>  put it on top of 3.8-rc4 mainline and tested it independently there
>  on a ppc sbc8548 board as well.  So it would be nice to get this in 3.9]
> 
>  drivers/of/base.c | 91 ++++++++++++++++++++++++++++++++++++++++++-------------
>  1 file changed, 70 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 2390ddb..21195a1 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -164,16 +164,14 @@ void of_node_put(struct device_node *node)
>  EXPORT_SYMBOL(of_node_put);
>  #endif /* CONFIG_OF_DYNAMIC */
>  
> -struct property *of_find_property(const struct device_node *np,
> -				  const char *name,
> -				  int *lenp)
> +static struct property *__of_find_property(const struct device_node *np,
> +					   const char *name, int *lenp)
>  {
>  	struct property *pp;
>  
>  	if (!np)
>  		return NULL;
>  
> -	read_lock(&devtree_lock);
>  	for (pp = np->properties; pp; pp = pp->next) {
>  		if (of_prop_cmp(pp->name, name) == 0) {
>  			if (lenp)
> @@ -181,6 +179,18 @@ struct property *of_find_property(const struct device_node *np,
>  			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);
> +	pp = __of_find_property(np, name, lenp);
>  	read_unlock(&devtree_lock);
>  
>  	return pp;
> @@ -214,8 +224,20 @@ EXPORT_SYMBOL(of_find_all_nodes);
>   * Find a property with a given name for a given node
>   * and return the value.
>   */
> +static const void *__of_get_property(const struct device_node *np,
> +				     const char *name, int *lenp)
> +{
> +	struct property *pp = __of_find_property(np, name, lenp);
> +
> +	return pp ? pp->value : NULL;
> +}
> +
> +/*
> + * Find a property with a given name for a given node
> + * and return the value.
> + */
>  const void *of_get_property(const struct device_node *np, const char *name,
> -			 int *lenp)
> +			    int *lenp)
>  {
>  	struct property *pp = of_find_property(np, name, lenp);
>  
> @@ -226,13 +248,13 @@ EXPORT_SYMBOL(of_get_property);
>  /** Checks if the given "compat" string matches one of the strings in
>   * the device's "compatible" property
>   */
> -int of_device_is_compatible(const struct device_node *device,
> -		const char *compat)
> +static int __of_device_is_compatible(const struct device_node *device,
> +				     const char *compat)
>  {
>  	const char* cp;
>  	int cplen, l;
>  
> -	cp = of_get_property(device, "compatible", &cplen);
> +	cp = __of_get_property(device, "compatible", &cplen);
>  	if (cp == NULL)
>  		return 0;
>  	while (cplen > 0) {
> @@ -245,6 +267,20 @@ int of_device_is_compatible(const struct device_node *device,
>  
>  	return 0;
>  }
> +
> +/** Checks if the given "compat" string matches one of the strings in
> + * the device's "compatible" property
> + */
> +int of_device_is_compatible(const struct device_node *device,
> +		const char *compat)
> +{
> +	int res;
> +
> +	read_lock(&devtree_lock);
> +	res = __of_device_is_compatible(device, compat);
> +	read_unlock(&devtree_lock);
> +	return res;
> +}
>  EXPORT_SYMBOL(of_device_is_compatible);
>  
>  /**
> @@ -518,7 +554,8 @@ struct device_node *of_find_compatible_node(struct device_node *from,
>  		if (type
>  		    && !(np->type && (of_node_cmp(np->type, type) == 0)))
>  			continue;
> -		if (of_device_is_compatible(np, compatible) && of_node_get(np))
> +		if (__of_device_is_compatible(np, compatible) &&
> +		    of_node_get(np))
>  			break;
>  	}
>  	of_node_put(from);
> @@ -562,15 +599,9 @@ out:
>  }
>  EXPORT_SYMBOL(of_find_node_with_property);
>  
> -/**
> - * of_match_node - Tell if an device_node has a matching of_match structure
> - *	@matches:	array of of device match structures to search in
> - *	@node:		the of device structure to match against
> - *
> - *	Low level utility function used by device matching.
> - */
> -const struct of_device_id *of_match_node(const struct of_device_id *matches,
> -					 const struct device_node *node)
> +static
> +const struct of_device_id *__of_match_node(const struct of_device_id *matches,
> +					   const struct device_node *node)
>  {
>  	if (!matches)
>  		return NULL;
> @@ -584,14 +615,32 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
>  			match &= node->type
>  				&& !strcmp(matches->type, node->type);
>  		if (matches->compatible[0])
> -			match &= of_device_is_compatible(node,
> -						matches->compatible);
> +			match &= __of_device_is_compatible(node,
> +							   matches->compatible);
>  		if (match)
>  			return matches;
>  		matches++;
>  	}
>  	return NULL;
>  }
> +
> +/**
> + * of_match_node - Tell if an device_node has a matching of_match structure
> + *	@matches:	array of of device match structures to search in
> + *	@node:		the of device structure to match against
> + *
> + *	Low level utility function used by device matching.
> + */
> +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;
> +
> +	read_lock(&devtree_lock);
> +	match = __of_match_node(matches, node);
> +	read_unlock(&devtree_lock);
> +	return match;
> +}
>  EXPORT_SYMBOL(of_match_node);
>  
>  /**
> @@ -619,7 +668,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
>  	read_lock(&devtree_lock);
>  	np = from ? from->allnext : of_allnodes;
>  	for (; np; np = np->allnext) {
> -		if (of_match_node(matches, np) && of_node_get(np)) {
> +		if (__of_match_node(matches, np) && of_node_get(np)) {
>  			if (match)
>  				*match = matches;
>  			break;
> 



More information about the devicetree-discuss mailing list