Commit 925df9b3 authored by Thomas Gleixner's avatar Thomas Gleixner

OF: Fixup resursive locking code paths

The conversion of devtree_lock from rwlock to spinlock unearthed
recursive locking pathes. Instead of going down the hassle of having
an atomic_rwlock implementation fixup the code pathes to avoid the
recursive locking.
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent b4f4919b
...@@ -59,16 +59,14 @@ int of_n_size_cells(struct device_node *np) ...@@ -59,16 +59,14 @@ int of_n_size_cells(struct device_node *np)
} }
EXPORT_SYMBOL(of_n_size_cells); EXPORT_SYMBOL(of_n_size_cells);
struct property *of_find_property(const struct device_node *np, static struct property *__of_find_property(const struct device_node *np,
const char *name, const char *name, int *lenp)
int *lenp)
{ {
struct property *pp; struct property *pp;
if (!np) if (!np)
return NULL; return NULL;
atomic_spin_lock(&devtree_lock);
for (pp = np->properties; pp != 0; pp = pp->next) { for (pp = np->properties; pp != 0; pp = pp->next) {
if (of_prop_cmp(pp->name, name) == 0) { if (of_prop_cmp(pp->name, name) == 0) {
if (lenp != 0) if (lenp != 0)
...@@ -76,18 +74,42 @@ struct property *of_find_property(const struct device_node *np, ...@@ -76,18 +74,42 @@ struct property *of_find_property(const struct device_node *np,
break; break;
} }
} }
return pp;
}
struct property *of_find_property(const struct device_node *np,
const char *name,
int *lenp)
{
struct property *pp;
atomic_spin_lock(&devtree_lock);
pp = __of_find_property(np, name, lenp);
atomic_spin_unlock(&devtree_lock); atomic_spin_unlock(&devtree_lock);
return pp; return pp;
} }
EXPORT_SYMBOL(of_find_property); EXPORT_SYMBOL(of_find_property);
/*
* 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 * Find a property with a given name for a given node
* and return the value. * and return the value.
*/ */
const void *of_get_property(const struct device_node *np, const char *name, 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); struct property *pp = of_find_property(np, name, lenp);
...@@ -98,13 +120,13 @@ EXPORT_SYMBOL(of_get_property); ...@@ -98,13 +120,13 @@ EXPORT_SYMBOL(of_get_property);
/** Checks if the given "compat" string matches one of the strings in /** Checks if the given "compat" string matches one of the strings in
* the device's "compatible" property * the device's "compatible" property
*/ */
int of_device_is_compatible(const struct device_node *device, static int __of_device_is_compatible(const struct device_node *device,
const char *compat) const char *compat)
{ {
const char* cp; const char* cp;
int cplen, l; int uninitialized_var(cplen), l;
cp = of_get_property(device, "compatible", &cplen); cp = __of_get_property(device, "compatible", &cplen);
if (cp == NULL) if (cp == NULL)
return 0; return 0;
while (cplen > 0) { while (cplen > 0) {
...@@ -117,6 +139,20 @@ int of_device_is_compatible(const struct device_node *device, ...@@ -117,6 +139,20 @@ int of_device_is_compatible(const struct device_node *device,
return 0; 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;
atomic_spin_lock(&devtree_lock);
res = __of_device_is_compatible(device, compat);
atomic_spin_unlock(&devtree_lock);
return res;
}
EXPORT_SYMBOL(of_device_is_compatible); EXPORT_SYMBOL(of_device_is_compatible);
/** /**
...@@ -319,7 +355,8 @@ struct device_node *of_find_compatible_node(struct device_node *from, ...@@ -319,7 +355,8 @@ struct device_node *of_find_compatible_node(struct device_node *from,
if (type if (type
&& !(np->type && (of_node_cmp(np->type, type) == 0))) && !(np->type && (of_node_cmp(np->type, type) == 0)))
continue; continue;
if (of_device_is_compatible(np, compatible) && of_node_get(np)) if (__of_device_is_compatible(np, compatible) &&
of_node_get(np))
break; break;
} }
of_node_put(from); of_node_put(from);
...@@ -363,15 +400,9 @@ out: ...@@ -363,15 +400,9 @@ out:
} }
EXPORT_SYMBOL(of_find_node_with_property); EXPORT_SYMBOL(of_find_node_with_property);
/** static const struct of_device_id *
* of_match_node - Tell if an device_node has a matching of_match structure __of_match_node(const struct of_device_id *matches,
* @matches: array of of device match structures to search in const struct device_node *node)
* @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)
{ {
while (matches->name[0] || matches->type[0] || matches->compatible[0]) { while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
int match = 1; int match = 1;
...@@ -382,14 +413,32 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches, ...@@ -382,14 +413,32 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
match &= node->type match &= node->type
&& !strcmp(matches->type, node->type); && !strcmp(matches->type, node->type);
if (matches->compatible[0]) if (matches->compatible[0])
match &= of_device_is_compatible(node, match &= __of_device_is_compatible(node,
matches->compatible); matches->compatible);
if (match) if (match)
return matches; return matches;
matches++; matches++;
} }
return NULL; 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;
atomic_spin_lock(&devtree_lock);
match = __of_match_node(matches, node);
atomic_spin_unlock(&devtree_lock);
return match;
}
EXPORT_SYMBOL(of_match_node); EXPORT_SYMBOL(of_match_node);
/** /**
...@@ -412,7 +461,7 @@ struct device_node *of_find_matching_node(struct device_node *from, ...@@ -412,7 +461,7 @@ struct device_node *of_find_matching_node(struct device_node *from,
atomic_spin_lock(&devtree_lock); atomic_spin_lock(&devtree_lock);
np = from ? from->allnext : allnodes; np = from ? from->allnext : allnodes;
for (; np; np = np->allnext) { 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))
break; break;
} }
of_node_put(from); of_node_put(from);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment