aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/of
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2013-01-25 13:21:47 -0500
committerRob Herring <rob.herring@calxeda.com>2013-01-27 21:20:23 -0500
commit28d0e36bf96863df1195f8f7b9fd559142873389 (patch)
treec11d2627a91d81e69f20d9813f4d4224a0c7aeff /drivers/of
parent425140af9e7040adc84a1b3f2c198eaf6eebc5aa (diff)
OF: Fixup resursive locking code paths
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@linutronix.de> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Diffstat (limited to 'drivers/of')
-rw-r--r--drivers/of/base.c91
1 files changed, 70 insertions, 21 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 960ae5bf3ddc..16ee7a08e044 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -164,16 +164,14 @@ void of_node_put(struct device_node *node)
164EXPORT_SYMBOL(of_node_put); 164EXPORT_SYMBOL(of_node_put);
165#endif /* CONFIG_OF_DYNAMIC */ 165#endif /* CONFIG_OF_DYNAMIC */
166 166
167struct property *of_find_property(const struct device_node *np, 167static struct property *__of_find_property(const struct device_node *np,
168 const char *name, 168 const char *name, int *lenp)
169 int *lenp)
170{ 169{
171 struct property *pp; 170 struct property *pp;
172 171
173 if (!np) 172 if (!np)
174 return NULL; 173 return NULL;
175 174
176 read_lock(&devtree_lock);
177 for (pp = np->properties; pp; pp = pp->next) { 175 for (pp = np->properties; pp; pp = pp->next) {
178 if (of_prop_cmp(pp->name, name) == 0) { 176 if (of_prop_cmp(pp->name, name) == 0) {
179 if (lenp) 177 if (lenp)
@@ -181,6 +179,18 @@ struct property *of_find_property(const struct device_node *np,
181 break; 179 break;
182 } 180 }
183 } 181 }
182
183 return pp;
184}
185
186struct property *of_find_property(const struct device_node *np,
187 const char *name,
188 int *lenp)
189{
190 struct property *pp;
191
192 read_lock(&devtree_lock);
193 pp = __of_find_property(np, name, lenp);
184 read_unlock(&devtree_lock); 194 read_unlock(&devtree_lock);
185 195
186 return pp; 196 return pp;
@@ -214,8 +224,20 @@ EXPORT_SYMBOL(of_find_all_nodes);
214 * Find a property with a given name for a given node 224 * Find a property with a given name for a given node
215 * and return the value. 225 * and return the value.
216 */ 226 */
227static const void *__of_get_property(const struct device_node *np,
228 const char *name, int *lenp)
229{
230 struct property *pp = __of_find_property(np, name, lenp);
231
232 return pp ? pp->value : NULL;
233}
234
235/*
236 * Find a property with a given name for a given node
237 * and return the value.
238 */
217const void *of_get_property(const struct device_node *np, const char *name, 239const void *of_get_property(const struct device_node *np, const char *name,
218 int *lenp) 240 int *lenp)
219{ 241{
220 struct property *pp = of_find_property(np, name, lenp); 242 struct property *pp = of_find_property(np, name, lenp);
221 243
@@ -226,13 +248,13 @@ EXPORT_SYMBOL(of_get_property);
226/** Checks if the given "compat" string matches one of the strings in 248/** Checks if the given "compat" string matches one of the strings in
227 * the device's "compatible" property 249 * the device's "compatible" property
228 */ 250 */
229int of_device_is_compatible(const struct device_node *device, 251static int __of_device_is_compatible(const struct device_node *device,
230 const char *compat) 252 const char *compat)
231{ 253{
232 const char* cp; 254 const char* cp;
233 int cplen, l; 255 int cplen, l;
234 256
235 cp = of_get_property(device, "compatible", &cplen); 257 cp = __of_get_property(device, "compatible", &cplen);
236 if (cp == NULL) 258 if (cp == NULL)
237 return 0; 259 return 0;
238 while (cplen > 0) { 260 while (cplen > 0) {
@@ -245,6 +267,20 @@ int of_device_is_compatible(const struct device_node *device,
245 267
246 return 0; 268 return 0;
247} 269}
270
271/** Checks if the given "compat" string matches one of the strings in
272 * the device's "compatible" property
273 */
274int of_device_is_compatible(const struct device_node *device,
275 const char *compat)
276{
277 int res;
278
279 read_lock(&devtree_lock);
280 res = __of_device_is_compatible(device, compat);
281 read_unlock(&devtree_lock);
282 return res;
283}
248EXPORT_SYMBOL(of_device_is_compatible); 284EXPORT_SYMBOL(of_device_is_compatible);
249 285
250/** 286/**
@@ -518,7 +554,8 @@ struct device_node *of_find_compatible_node(struct device_node *from,
518 if (type 554 if (type
519 && !(np->type && (of_node_cmp(np->type, type) == 0))) 555 && !(np->type && (of_node_cmp(np->type, type) == 0)))
520 continue; 556 continue;
521 if (of_device_is_compatible(np, compatible) && of_node_get(np)) 557 if (__of_device_is_compatible(np, compatible) &&
558 of_node_get(np))
522 break; 559 break;
523 } 560 }
524 of_node_put(from); 561 of_node_put(from);
@@ -562,15 +599,9 @@ out:
562} 599}
563EXPORT_SYMBOL(of_find_node_with_property); 600EXPORT_SYMBOL(of_find_node_with_property);
564 601
565/** 602static
566 * of_match_node - Tell if an device_node has a matching of_match structure 603const struct of_device_id *__of_match_node(const struct of_device_id *matches,
567 * @matches: array of of device match structures to search in 604 const struct device_node *node)
568 * @node: the of device structure to match against
569 *
570 * Low level utility function used by device matching.
571 */
572const struct of_device_id *of_match_node(const struct of_device_id *matches,
573 const struct device_node *node)
574{ 605{
575 if (!matches) 606 if (!matches)
576 return NULL; 607 return NULL;
@@ -584,14 +615,32 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
584 match &= node->type 615 match &= node->type
585 && !strcmp(matches->type, node->type); 616 && !strcmp(matches->type, node->type);
586 if (matches->compatible[0]) 617 if (matches->compatible[0])
587 match &= of_device_is_compatible(node, 618 match &= __of_device_is_compatible(node,
588 matches->compatible); 619 matches->compatible);
589 if (match) 620 if (match)
590 return matches; 621 return matches;
591 matches++; 622 matches++;
592 } 623 }
593 return NULL; 624 return NULL;
594} 625}
626
627/**
628 * of_match_node - Tell if an device_node has a matching of_match structure
629 * @matches: array of of device match structures to search in
630 * @node: the of device structure to match against
631 *
632 * Low level utility function used by device matching.
633 */
634const struct of_device_id *of_match_node(const struct of_device_id *matches,
635 const struct device_node *node)
636{
637 const struct of_device_id *match;
638
639 read_lock(&devtree_lock);
640 match = __of_match_node(matches, node);
641 read_unlock(&devtree_lock);
642 return match;
643}
595EXPORT_SYMBOL(of_match_node); 644EXPORT_SYMBOL(of_match_node);
596 645
597/** 646/**
@@ -620,7 +669,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
620 read_lock(&devtree_lock); 669 read_lock(&devtree_lock);
621 np = from ? from->allnext : of_allnodes; 670 np = from ? from->allnext : of_allnodes;
622 for (; np; np = np->allnext) { 671 for (; np; np = np->allnext) {
623 m = of_match_node(matches, np); 672 m = __of_match_node(matches, np);
624 if (m && of_node_get(np)) { 673 if (m && of_node_get(np)) {
625 if (match) 674 if (match)
626 *match = m; 675 *match = m;