diff options
Diffstat (limited to 'drivers/of/base.c')
-rw-r--r-- | drivers/of/base.c | 100 |
1 files changed, 56 insertions, 44 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index 16ee7a08e044..f86be5594a15 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -55,7 +55,7 @@ static DEFINE_MUTEX(of_aliases_mutex); | |||
55 | /* use when traversing tree through the allnext, child, sibling, | 55 | /* use when traversing tree through the allnext, child, sibling, |
56 | * or parent members of struct device_node. | 56 | * or parent members of struct device_node. |
57 | */ | 57 | */ |
58 | DEFINE_RWLOCK(devtree_lock); | 58 | DEFINE_RAW_SPINLOCK(devtree_lock); |
59 | 59 | ||
60 | int of_n_addr_cells(struct device_node *np) | 60 | int of_n_addr_cells(struct device_node *np) |
61 | { | 61 | { |
@@ -188,10 +188,11 @@ struct property *of_find_property(const struct device_node *np, | |||
188 | int *lenp) | 188 | int *lenp) |
189 | { | 189 | { |
190 | struct property *pp; | 190 | struct property *pp; |
191 | unsigned long flags; | ||
191 | 192 | ||
192 | read_lock(&devtree_lock); | 193 | raw_spin_lock_irqsave(&devtree_lock, flags); |
193 | pp = __of_find_property(np, name, lenp); | 194 | pp = __of_find_property(np, name, lenp); |
194 | read_unlock(&devtree_lock); | 195 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
195 | 196 | ||
196 | return pp; | 197 | return pp; |
197 | } | 198 | } |
@@ -209,13 +210,13 @@ struct device_node *of_find_all_nodes(struct device_node *prev) | |||
209 | { | 210 | { |
210 | struct device_node *np; | 211 | struct device_node *np; |
211 | 212 | ||
212 | read_lock(&devtree_lock); | 213 | raw_spin_lock(&devtree_lock); |
213 | np = prev ? prev->allnext : of_allnodes; | 214 | np = prev ? prev->allnext : of_allnodes; |
214 | for (; np != NULL; np = np->allnext) | 215 | for (; np != NULL; np = np->allnext) |
215 | if (of_node_get(np)) | 216 | if (of_node_get(np)) |
216 | break; | 217 | break; |
217 | of_node_put(prev); | 218 | of_node_put(prev); |
218 | read_unlock(&devtree_lock); | 219 | raw_spin_unlock(&devtree_lock); |
219 | return np; | 220 | return np; |
220 | } | 221 | } |
221 | EXPORT_SYMBOL(of_find_all_nodes); | 222 | EXPORT_SYMBOL(of_find_all_nodes); |
@@ -274,11 +275,12 @@ static int __of_device_is_compatible(const struct device_node *device, | |||
274 | int of_device_is_compatible(const struct device_node *device, | 275 | int of_device_is_compatible(const struct device_node *device, |
275 | const char *compat) | 276 | const char *compat) |
276 | { | 277 | { |
278 | unsigned long flags; | ||
277 | int res; | 279 | int res; |
278 | 280 | ||
279 | read_lock(&devtree_lock); | 281 | raw_spin_lock_irqsave(&devtree_lock, flags); |
280 | res = __of_device_is_compatible(device, compat); | 282 | res = __of_device_is_compatible(device, compat); |
281 | read_unlock(&devtree_lock); | 283 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
282 | return res; | 284 | return res; |
283 | } | 285 | } |
284 | EXPORT_SYMBOL(of_device_is_compatible); | 286 | EXPORT_SYMBOL(of_device_is_compatible); |
@@ -340,13 +342,14 @@ EXPORT_SYMBOL(of_device_is_available); | |||
340 | struct device_node *of_get_parent(const struct device_node *node) | 342 | struct device_node *of_get_parent(const struct device_node *node) |
341 | { | 343 | { |
342 | struct device_node *np; | 344 | struct device_node *np; |
345 | unsigned long flags; | ||
343 | 346 | ||
344 | if (!node) | 347 | if (!node) |
345 | return NULL; | 348 | return NULL; |
346 | 349 | ||
347 | read_lock(&devtree_lock); | 350 | raw_spin_lock_irqsave(&devtree_lock, flags); |
348 | np = of_node_get(node->parent); | 351 | np = of_node_get(node->parent); |
349 | read_unlock(&devtree_lock); | 352 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
350 | return np; | 353 | return np; |
351 | } | 354 | } |
352 | EXPORT_SYMBOL(of_get_parent); | 355 | EXPORT_SYMBOL(of_get_parent); |
@@ -365,14 +368,15 @@ EXPORT_SYMBOL(of_get_parent); | |||
365 | struct device_node *of_get_next_parent(struct device_node *node) | 368 | struct device_node *of_get_next_parent(struct device_node *node) |
366 | { | 369 | { |
367 | struct device_node *parent; | 370 | struct device_node *parent; |
371 | unsigned long flags; | ||
368 | 372 | ||
369 | if (!node) | 373 | if (!node) |
370 | return NULL; | 374 | return NULL; |
371 | 375 | ||
372 | read_lock(&devtree_lock); | 376 | raw_spin_lock_irqsave(&devtree_lock, flags); |
373 | parent = of_node_get(node->parent); | 377 | parent = of_node_get(node->parent); |
374 | of_node_put(node); | 378 | of_node_put(node); |
375 | read_unlock(&devtree_lock); | 379 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
376 | return parent; | 380 | return parent; |
377 | } | 381 | } |
378 | 382 | ||
@@ -388,14 +392,15 @@ struct device_node *of_get_next_child(const struct device_node *node, | |||
388 | struct device_node *prev) | 392 | struct device_node *prev) |
389 | { | 393 | { |
390 | struct device_node *next; | 394 | struct device_node *next; |
395 | unsigned long flags; | ||
391 | 396 | ||
392 | read_lock(&devtree_lock); | 397 | raw_spin_lock_irqsave(&devtree_lock, flags); |
393 | next = prev ? prev->sibling : node->child; | 398 | next = prev ? prev->sibling : node->child; |
394 | for (; next; next = next->sibling) | 399 | for (; next; next = next->sibling) |
395 | if (of_node_get(next)) | 400 | if (of_node_get(next)) |
396 | break; | 401 | break; |
397 | of_node_put(prev); | 402 | of_node_put(prev); |
398 | read_unlock(&devtree_lock); | 403 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
399 | return next; | 404 | return next; |
400 | } | 405 | } |
401 | EXPORT_SYMBOL(of_get_next_child); | 406 | EXPORT_SYMBOL(of_get_next_child); |
@@ -413,7 +418,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node, | |||
413 | { | 418 | { |
414 | struct device_node *next; | 419 | struct device_node *next; |
415 | 420 | ||
416 | read_lock(&devtree_lock); | 421 | raw_spin_lock(&devtree_lock); |
417 | next = prev ? prev->sibling : node->child; | 422 | next = prev ? prev->sibling : node->child; |
418 | for (; next; next = next->sibling) { | 423 | for (; next; next = next->sibling) { |
419 | if (!of_device_is_available(next)) | 424 | if (!of_device_is_available(next)) |
@@ -422,7 +427,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node, | |||
422 | break; | 427 | break; |
423 | } | 428 | } |
424 | of_node_put(prev); | 429 | of_node_put(prev); |
425 | read_unlock(&devtree_lock); | 430 | raw_spin_unlock(&devtree_lock); |
426 | return next; | 431 | return next; |
427 | } | 432 | } |
428 | EXPORT_SYMBOL(of_get_next_available_child); | 433 | EXPORT_SYMBOL(of_get_next_available_child); |
@@ -460,14 +465,15 @@ EXPORT_SYMBOL(of_get_child_by_name); | |||
460 | struct device_node *of_find_node_by_path(const char *path) | 465 | struct device_node *of_find_node_by_path(const char *path) |
461 | { | 466 | { |
462 | struct device_node *np = of_allnodes; | 467 | struct device_node *np = of_allnodes; |
468 | unsigned long flags; | ||
463 | 469 | ||
464 | read_lock(&devtree_lock); | 470 | raw_spin_lock_irqsave(&devtree_lock, flags); |
465 | for (; np; np = np->allnext) { | 471 | for (; np; np = np->allnext) { |
466 | if (np->full_name && (of_node_cmp(np->full_name, path) == 0) | 472 | if (np->full_name && (of_node_cmp(np->full_name, path) == 0) |
467 | && of_node_get(np)) | 473 | && of_node_get(np)) |
468 | break; | 474 | break; |
469 | } | 475 | } |
470 | read_unlock(&devtree_lock); | 476 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
471 | return np; | 477 | return np; |
472 | } | 478 | } |
473 | EXPORT_SYMBOL(of_find_node_by_path); | 479 | EXPORT_SYMBOL(of_find_node_by_path); |
@@ -487,15 +493,16 @@ struct device_node *of_find_node_by_name(struct device_node *from, | |||
487 | const char *name) | 493 | const char *name) |
488 | { | 494 | { |
489 | struct device_node *np; | 495 | struct device_node *np; |
496 | unsigned long flags; | ||
490 | 497 | ||
491 | read_lock(&devtree_lock); | 498 | raw_spin_lock_irqsave(&devtree_lock, flags); |
492 | np = from ? from->allnext : of_allnodes; | 499 | np = from ? from->allnext : of_allnodes; |
493 | for (; np; np = np->allnext) | 500 | for (; np; np = np->allnext) |
494 | if (np->name && (of_node_cmp(np->name, name) == 0) | 501 | if (np->name && (of_node_cmp(np->name, name) == 0) |
495 | && of_node_get(np)) | 502 | && of_node_get(np)) |
496 | break; | 503 | break; |
497 | of_node_put(from); | 504 | of_node_put(from); |
498 | read_unlock(&devtree_lock); | 505 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
499 | return np; | 506 | return np; |
500 | } | 507 | } |
501 | EXPORT_SYMBOL(of_find_node_by_name); | 508 | EXPORT_SYMBOL(of_find_node_by_name); |
@@ -516,15 +523,16 @@ struct device_node *of_find_node_by_type(struct device_node *from, | |||
516 | const char *type) | 523 | const char *type) |
517 | { | 524 | { |
518 | struct device_node *np; | 525 | struct device_node *np; |
526 | unsigned long flags; | ||
519 | 527 | ||
520 | read_lock(&devtree_lock); | 528 | raw_spin_lock_irqsave(&devtree_lock, flags); |
521 | np = from ? from->allnext : of_allnodes; | 529 | np = from ? from->allnext : of_allnodes; |
522 | for (; np; np = np->allnext) | 530 | for (; np; np = np->allnext) |
523 | if (np->type && (of_node_cmp(np->type, type) == 0) | 531 | if (np->type && (of_node_cmp(np->type, type) == 0) |
524 | && of_node_get(np)) | 532 | && of_node_get(np)) |
525 | break; | 533 | break; |
526 | of_node_put(from); | 534 | of_node_put(from); |
527 | read_unlock(&devtree_lock); | 535 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
528 | return np; | 536 | return np; |
529 | } | 537 | } |
530 | EXPORT_SYMBOL(of_find_node_by_type); | 538 | EXPORT_SYMBOL(of_find_node_by_type); |
@@ -547,8 +555,9 @@ struct device_node *of_find_compatible_node(struct device_node *from, | |||
547 | const char *type, const char *compatible) | 555 | const char *type, const char *compatible) |
548 | { | 556 | { |
549 | struct device_node *np; | 557 | struct device_node *np; |
558 | unsigned long flags; | ||
550 | 559 | ||
551 | read_lock(&devtree_lock); | 560 | raw_spin_lock_irqsave(&devtree_lock, flags); |
552 | np = from ? from->allnext : of_allnodes; | 561 | np = from ? from->allnext : of_allnodes; |
553 | for (; np; np = np->allnext) { | 562 | for (; np; np = np->allnext) { |
554 | if (type | 563 | if (type |
@@ -559,7 +568,7 @@ struct device_node *of_find_compatible_node(struct device_node *from, | |||
559 | break; | 568 | break; |
560 | } | 569 | } |
561 | of_node_put(from); | 570 | of_node_put(from); |
562 | read_unlock(&devtree_lock); | 571 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
563 | return np; | 572 | return np; |
564 | } | 573 | } |
565 | EXPORT_SYMBOL(of_find_compatible_node); | 574 | EXPORT_SYMBOL(of_find_compatible_node); |
@@ -581,8 +590,9 @@ struct device_node *of_find_node_with_property(struct device_node *from, | |||
581 | { | 590 | { |
582 | struct device_node *np; | 591 | struct device_node *np; |
583 | struct property *pp; | 592 | struct property *pp; |
593 | unsigned long flags; | ||
584 | 594 | ||
585 | read_lock(&devtree_lock); | 595 | raw_spin_lock_irqsave(&devtree_lock, flags); |
586 | np = from ? from->allnext : of_allnodes; | 596 | np = from ? from->allnext : of_allnodes; |
587 | for (; np; np = np->allnext) { | 597 | for (; np; np = np->allnext) { |
588 | for (pp = np->properties; pp; pp = pp->next) { | 598 | for (pp = np->properties; pp; pp = pp->next) { |
@@ -594,7 +604,7 @@ struct device_node *of_find_node_with_property(struct device_node *from, | |||
594 | } | 604 | } |
595 | out: | 605 | out: |
596 | of_node_put(from); | 606 | of_node_put(from); |
597 | read_unlock(&devtree_lock); | 607 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
598 | return np; | 608 | return np; |
599 | } | 609 | } |
600 | EXPORT_SYMBOL(of_find_node_with_property); | 610 | 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, | |||
635 | const struct device_node *node) | 645 | const struct device_node *node) |
636 | { | 646 | { |
637 | const struct of_device_id *match; | 647 | const struct of_device_id *match; |
648 | unsigned long flags; | ||
638 | 649 | ||
639 | read_lock(&devtree_lock); | 650 | raw_spin_lock_irqsave(&devtree_lock, flags); |
640 | match = __of_match_node(matches, node); | 651 | match = __of_match_node(matches, node); |
641 | read_unlock(&devtree_lock); | 652 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
642 | return match; | 653 | return match; |
643 | } | 654 | } |
644 | EXPORT_SYMBOL(of_match_node); | 655 | EXPORT_SYMBOL(of_match_node); |
@@ -662,11 +673,12 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from, | |||
662 | { | 673 | { |
663 | struct device_node *np; | 674 | struct device_node *np; |
664 | const struct of_device_id *m; | 675 | const struct of_device_id *m; |
676 | unsigned long flags; | ||
665 | 677 | ||
666 | if (match) | 678 | if (match) |
667 | *match = NULL; | 679 | *match = NULL; |
668 | 680 | ||
669 | read_lock(&devtree_lock); | 681 | raw_spin_lock_irqsave(&devtree_lock, flags); |
670 | np = from ? from->allnext : of_allnodes; | 682 | np = from ? from->allnext : of_allnodes; |
671 | for (; np; np = np->allnext) { | 683 | for (; np; np = np->allnext) { |
672 | m = __of_match_node(matches, np); | 684 | m = __of_match_node(matches, np); |
@@ -677,7 +689,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from, | |||
677 | } | 689 | } |
678 | } | 690 | } |
679 | of_node_put(from); | 691 | of_node_put(from); |
680 | read_unlock(&devtree_lock); | 692 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
681 | return np; | 693 | return np; |
682 | } | 694 | } |
683 | EXPORT_SYMBOL(of_find_matching_node_and_match); | 695 | EXPORT_SYMBOL(of_find_matching_node_and_match); |
@@ -720,12 +732,12 @@ struct device_node *of_find_node_by_phandle(phandle handle) | |||
720 | { | 732 | { |
721 | struct device_node *np; | 733 | struct device_node *np; |
722 | 734 | ||
723 | read_lock(&devtree_lock); | 735 | raw_spin_lock(&devtree_lock); |
724 | for (np = of_allnodes; np; np = np->allnext) | 736 | for (np = of_allnodes; np; np = np->allnext) |
725 | if (np->phandle == handle) | 737 | if (np->phandle == handle) |
726 | break; | 738 | break; |
727 | of_node_get(np); | 739 | of_node_get(np); |
728 | read_unlock(&devtree_lock); | 740 | raw_spin_unlock(&devtree_lock); |
729 | return np; | 741 | return np; |
730 | } | 742 | } |
731 | EXPORT_SYMBOL(of_find_node_by_phandle); | 743 | EXPORT_SYMBOL(of_find_node_by_phandle); |
@@ -1197,18 +1209,18 @@ int of_add_property(struct device_node *np, struct property *prop) | |||
1197 | return rc; | 1209 | return rc; |
1198 | 1210 | ||
1199 | prop->next = NULL; | 1211 | prop->next = NULL; |
1200 | write_lock_irqsave(&devtree_lock, flags); | 1212 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1201 | next = &np->properties; | 1213 | next = &np->properties; |
1202 | while (*next) { | 1214 | while (*next) { |
1203 | if (strcmp(prop->name, (*next)->name) == 0) { | 1215 | if (strcmp(prop->name, (*next)->name) == 0) { |
1204 | /* duplicate ! don't insert it */ | 1216 | /* duplicate ! don't insert it */ |
1205 | write_unlock_irqrestore(&devtree_lock, flags); | 1217 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1206 | return -1; | 1218 | return -1; |
1207 | } | 1219 | } |
1208 | next = &(*next)->next; | 1220 | next = &(*next)->next; |
1209 | } | 1221 | } |
1210 | *next = prop; | 1222 | *next = prop; |
1211 | write_unlock_irqrestore(&devtree_lock, flags); | 1223 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1212 | 1224 | ||
1213 | #ifdef CONFIG_PROC_DEVICETREE | 1225 | #ifdef CONFIG_PROC_DEVICETREE |
1214 | /* try to add to proc as well if it was initialized */ | 1226 | /* 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) | |||
1238 | if (rc) | 1250 | if (rc) |
1239 | return rc; | 1251 | return rc; |
1240 | 1252 | ||
1241 | write_lock_irqsave(&devtree_lock, flags); | 1253 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1242 | next = &np->properties; | 1254 | next = &np->properties; |
1243 | while (*next) { | 1255 | while (*next) { |
1244 | if (*next == prop) { | 1256 | if (*next == prop) { |
@@ -1251,7 +1263,7 @@ int of_remove_property(struct device_node *np, struct property *prop) | |||
1251 | } | 1263 | } |
1252 | next = &(*next)->next; | 1264 | next = &(*next)->next; |
1253 | } | 1265 | } |
1254 | write_unlock_irqrestore(&devtree_lock, flags); | 1266 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1255 | 1267 | ||
1256 | if (!found) | 1268 | if (!found) |
1257 | return -ENODEV; | 1269 | return -ENODEV; |
@@ -1291,7 +1303,7 @@ int of_update_property(struct device_node *np, struct property *newprop) | |||
1291 | if (!oldprop) | 1303 | if (!oldprop) |
1292 | return of_add_property(np, newprop); | 1304 | return of_add_property(np, newprop); |
1293 | 1305 | ||
1294 | write_lock_irqsave(&devtree_lock, flags); | 1306 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1295 | next = &np->properties; | 1307 | next = &np->properties; |
1296 | while (*next) { | 1308 | while (*next) { |
1297 | if (*next == oldprop) { | 1309 | if (*next == oldprop) { |
@@ -1305,7 +1317,7 @@ int of_update_property(struct device_node *np, struct property *newprop) | |||
1305 | } | 1317 | } |
1306 | next = &(*next)->next; | 1318 | next = &(*next)->next; |
1307 | } | 1319 | } |
1308 | write_unlock_irqrestore(&devtree_lock, flags); | 1320 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1309 | 1321 | ||
1310 | if (!found) | 1322 | if (!found) |
1311 | return -ENODEV; | 1323 | return -ENODEV; |
@@ -1378,12 +1390,12 @@ int of_attach_node(struct device_node *np) | |||
1378 | if (rc) | 1390 | if (rc) |
1379 | return rc; | 1391 | return rc; |
1380 | 1392 | ||
1381 | write_lock_irqsave(&devtree_lock, flags); | 1393 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1382 | np->sibling = np->parent->child; | 1394 | np->sibling = np->parent->child; |
1383 | np->allnext = of_allnodes; | 1395 | np->allnext = of_allnodes; |
1384 | np->parent->child = np; | 1396 | np->parent->child = np; |
1385 | of_allnodes = np; | 1397 | of_allnodes = np; |
1386 | write_unlock_irqrestore(&devtree_lock, flags); | 1398 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1387 | 1399 | ||
1388 | of_add_proc_dt_entry(np); | 1400 | of_add_proc_dt_entry(np); |
1389 | return 0; | 1401 | return 0; |
@@ -1426,17 +1438,17 @@ int of_detach_node(struct device_node *np) | |||
1426 | if (rc) | 1438 | if (rc) |
1427 | return rc; | 1439 | return rc; |
1428 | 1440 | ||
1429 | write_lock_irqsave(&devtree_lock, flags); | 1441 | raw_spin_lock_irqsave(&devtree_lock, flags); |
1430 | 1442 | ||
1431 | if (of_node_check_flag(np, OF_DETACHED)) { | 1443 | if (of_node_check_flag(np, OF_DETACHED)) { |
1432 | /* someone already detached it */ | 1444 | /* someone already detached it */ |
1433 | write_unlock_irqrestore(&devtree_lock, flags); | 1445 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1434 | return rc; | 1446 | return rc; |
1435 | } | 1447 | } |
1436 | 1448 | ||
1437 | parent = np->parent; | 1449 | parent = np->parent; |
1438 | if (!parent) { | 1450 | if (!parent) { |
1439 | write_unlock_irqrestore(&devtree_lock, flags); | 1451 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1440 | return rc; | 1452 | return rc; |
1441 | } | 1453 | } |
1442 | 1454 | ||
@@ -1463,7 +1475,7 @@ int of_detach_node(struct device_node *np) | |||
1463 | } | 1475 | } |
1464 | 1476 | ||
1465 | of_node_set_flag(np, OF_DETACHED); | 1477 | of_node_set_flag(np, OF_DETACHED); |
1466 | write_unlock_irqrestore(&devtree_lock, flags); | 1478 | raw_spin_unlock_irqrestore(&devtree_lock, flags); |
1467 | 1479 | ||
1468 | of_remove_proc_dt_entry(np); | 1480 | of_remove_proc_dt_entry(np); |
1469 | return rc; | 1481 | return rc; |