| From 236c6fa18598ae8b914238bba620cb72320e7c4b Mon Sep 17 00:00:00 2001 | |
| From: Thomas Gleixner <tglx@linutronix.de> | |
| Date: Thu, 13 Aug 2009 09:04:10 +0200 | |
| Subject: [PATCH] OF: Fixup resursive locking code paths | |
| commit 925df9b36dc9abe0bab32cbd2ac544d773da71ff in tip. | |
| 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: Thomas Gleixner <tglx@linutronix.de> | |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> | |
| --- | |
| drivers/of/base.c | 93 ++++++++++++++++++++++++++++++++++++++++------------ | |
| 1 files changed, 71 insertions(+), 22 deletions(-) | |
| diff --git a/drivers/of/base.c b/drivers/of/base.c | |
| index 4e40618..a05713e 100644 | |
| --- a/drivers/of/base.c | |
| +++ b/drivers/of/base.c | |
| @@ -138,16 +138,14 @@ void of_node_put(struct device_node *node) | |
| EXPORT_SYMBOL(of_node_put); | |
| #endif /* !CONFIG_SPARC */ | |
| -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; | |
| - raw_spin_lock(&devtree_lock); | |
| for (pp = np->properties; pp != 0; pp = pp->next) { | |
| if (of_prop_cmp(pp->name, name) == 0) { | |
| if (lenp != 0) | |
| @@ -155,6 +153,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; | |
| + | |
| + raw_spin_lock(&devtree_lock); | |
| + pp = __of_find_property(np, name, lenp); | |
| raw_spin_unlock(&devtree_lock); | |
| return pp; | |
| @@ -188,8 +198,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); | |
| @@ -200,13 +222,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; | |
| + int uninitialized_var(cplen), l; | |
| - cp = of_get_property(device, "compatible", &cplen); | |
| + cp = __of_get_property(device, "compatible", &cplen); | |
| if (cp == NULL) | |
| return 0; | |
| while (cplen > 0) { | |
| @@ -219,6 +241,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; | |
| + | |
| + raw_spin_lock(&devtree_lock); | |
| + res = __of_device_is_compatible(device, compat); | |
| + raw_spin_unlock(&devtree_lock); | |
| + return res; | |
| +} | |
| EXPORT_SYMBOL(of_device_is_compatible); | |
| /** | |
| @@ -442,7 +478,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); | |
| @@ -486,15 +523,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) | |
| { | |
| while (matches->name[0] || matches->type[0] || matches->compatible[0]) { | |
| int match = 1; | |
| @@ -505,14 +536,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; | |
| + | |
| + raw_spin_lock(&devtree_lock); | |
| + match = __of_match_node(matches, node); | |
| + raw_spin_unlock(&devtree_lock); | |
| + return match; | |
| +} | |
| EXPORT_SYMBOL(of_match_node); | |
| /** | |
| @@ -535,7 +584,7 @@ struct device_node *of_find_matching_node(struct device_node *from, | |
| raw_spin_lock(&devtree_lock); | |
| np = from ? from->allnext : 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)) | |
| break; | |
| } | |
| of_node_put(from); | |
| -- | |
| 1.7.0.4 | |