diff options
author | Joerg Roedel <jroedel@suse.de> | 2016-04-04 11:49:18 -0400 |
---|---|---|
committer | Rob Herring <robh@kernel.org> | 2016-04-19 18:25:13 -0400 |
commit | cd209b412c8a5d632b51af1e45576f0d00b8105f (patch) | |
tree | 72164b609b058fe318f0f7dcd6d87d08f05ae842 | |
parent | 74e1fbb1375a3ede3e17da22911761ce9bc8f53f (diff) |
of: Move phandle walking to of_phandle_iterator_next()
Move the code to walk over the phandles out of the loop in
__of_parse_phandle_with_args() to a separate function that
just works with the iterator handle: of_phandle_iterator_next().
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Signed-off-by: Rob Herring <robh@kernel.org>
-rw-r--r-- | drivers/of/base.c | 130 | ||||
-rw-r--r-- | include/linux/of.h | 7 |
2 files changed, 81 insertions, 56 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index 1c6f43b5737d..69286ec206f7 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -1465,6 +1465,75 @@ int of_phandle_iterator_init(struct of_phandle_iterator *it, | |||
1465 | return 0; | 1465 | return 0; |
1466 | } | 1466 | } |
1467 | 1467 | ||
1468 | int of_phandle_iterator_next(struct of_phandle_iterator *it) | ||
1469 | { | ||
1470 | uint32_t count = 0; | ||
1471 | |||
1472 | if (it->node) { | ||
1473 | of_node_put(it->node); | ||
1474 | it->node = NULL; | ||
1475 | } | ||
1476 | |||
1477 | if (!it->cur || it->phandle_end >= it->list_end) | ||
1478 | return -ENOENT; | ||
1479 | |||
1480 | it->cur = it->phandle_end; | ||
1481 | |||
1482 | /* If phandle is 0, then it is an empty entry with no arguments. */ | ||
1483 | it->phandle = be32_to_cpup(it->cur++); | ||
1484 | |||
1485 | if (it->phandle) { | ||
1486 | |||
1487 | /* | ||
1488 | * Find the provider node and parse the #*-cells property to | ||
1489 | * determine the argument length. | ||
1490 | */ | ||
1491 | it->node = of_find_node_by_phandle(it->phandle); | ||
1492 | |||
1493 | if (it->cells_name) { | ||
1494 | if (!it->node) { | ||
1495 | pr_err("%s: could not find phandle\n", | ||
1496 | it->parent->full_name); | ||
1497 | goto err; | ||
1498 | } | ||
1499 | |||
1500 | if (of_property_read_u32(it->node, it->cells_name, | ||
1501 | &count)) { | ||
1502 | pr_err("%s: could not get %s for %s\n", | ||
1503 | it->parent->full_name, | ||
1504 | it->cells_name, | ||
1505 | it->node->full_name); | ||
1506 | goto err; | ||
1507 | } | ||
1508 | } else { | ||
1509 | count = it->cell_count; | ||
1510 | } | ||
1511 | |||
1512 | /* | ||
1513 | * Make sure that the arguments actually fit in the remaining | ||
1514 | * property data length | ||
1515 | */ | ||
1516 | if (it->cur + count > it->list_end) { | ||
1517 | pr_err("%s: arguments longer than property\n", | ||
1518 | it->parent->full_name); | ||
1519 | goto err; | ||
1520 | } | ||
1521 | } | ||
1522 | |||
1523 | it->phandle_end = it->cur + count; | ||
1524 | it->cur_count = count; | ||
1525 | |||
1526 | return 0; | ||
1527 | |||
1528 | err: | ||
1529 | if (it->node) { | ||
1530 | of_node_put(it->node); | ||
1531 | it->node = NULL; | ||
1532 | } | ||
1533 | |||
1534 | return -EINVAL; | ||
1535 | } | ||
1536 | |||
1468 | static int __of_parse_phandle_with_args(const struct device_node *np, | 1537 | static int __of_parse_phandle_with_args(const struct device_node *np, |
1469 | const char *list_name, | 1538 | const char *list_name, |
1470 | const char *cells_name, | 1539 | const char *cells_name, |
@@ -1480,59 +1549,9 @@ static int __of_parse_phandle_with_args(const struct device_node *np, | |||
1480 | return rc; | 1549 | return rc; |
1481 | 1550 | ||
1482 | /* Loop over the phandles until all the requested entry is found */ | 1551 | /* Loop over the phandles until all the requested entry is found */ |
1483 | while (it.cur < it.list_end) { | 1552 | while ((rc = of_phandle_iterator_next(&it)) == 0) { |
1484 | rc = -EINVAL; | ||
1485 | it.cur_count = 0; | ||
1486 | |||
1487 | /* | ||
1488 | * If phandle is 0, then it is an empty entry with no | ||
1489 | * arguments. Skip forward to the next entry. | ||
1490 | */ | ||
1491 | it.phandle = be32_to_cpup(it.cur++); | ||
1492 | if (it.phandle) { | ||
1493 | /* | ||
1494 | * Find the provider node and parse the #*-cells | ||
1495 | * property to determine the argument length. | ||
1496 | * | ||
1497 | * This is not needed if the cell count is hard-coded | ||
1498 | * (i.e. cells_name not set, but cell_count is set), | ||
1499 | * except when we're going to return the found node | ||
1500 | * below. | ||
1501 | */ | ||
1502 | if (it.cells_name || cur_index == index) { | ||
1503 | it.node = of_find_node_by_phandle(it.phandle); | ||
1504 | if (!it.node) { | ||
1505 | pr_err("%s: could not find phandle\n", | ||
1506 | it.parent->full_name); | ||
1507 | goto err; | ||
1508 | } | ||
1509 | } | ||
1510 | |||
1511 | if (it.cells_name) { | ||
1512 | if (of_property_read_u32(it.node, it.cells_name, | ||
1513 | &it.cur_count)) { | ||
1514 | pr_err("%s: could not get %s for %s\n", | ||
1515 | it.parent->full_name, it.cells_name, | ||
1516 | it.node->full_name); | ||
1517 | goto err; | ||
1518 | } | ||
1519 | } else { | ||
1520 | it.cur_count = it.cell_count; | ||
1521 | } | ||
1522 | |||
1523 | /* | ||
1524 | * Make sure that the arguments actually fit in the | ||
1525 | * remaining property data length | ||
1526 | */ | ||
1527 | if (it.cur + it.cur_count > it.list_end) { | ||
1528 | pr_err("%s: arguments longer than property\n", | ||
1529 | it.parent->full_name); | ||
1530 | goto err; | ||
1531 | } | ||
1532 | } | ||
1533 | |||
1534 | /* | 1553 | /* |
1535 | * All of the error cases above bail out of the loop, so at | 1554 | * All of the error cases bail out of the loop, so at |
1536 | * this point, the parsing is successful. If the requested | 1555 | * this point, the parsing is successful. If the requested |
1537 | * index matches, then fill the out_args structure and return, | 1556 | * index matches, then fill the out_args structure and return, |
1538 | * or return -ENOENT for an empty entry. | 1557 | * or return -ENOENT for an empty entry. |
@@ -1558,9 +1577,6 @@ static int __of_parse_phandle_with_args(const struct device_node *np, | |||
1558 | return 0; | 1577 | return 0; |
1559 | } | 1578 | } |
1560 | 1579 | ||
1561 | of_node_put(it.node); | ||
1562 | it.node = NULL; | ||
1563 | it.cur += it.cur_count; | ||
1564 | cur_index++; | 1580 | cur_index++; |
1565 | } | 1581 | } |
1566 | 1582 | ||
@@ -1570,7 +1586,9 @@ static int __of_parse_phandle_with_args(const struct device_node *np, | |||
1570 | * -EINVAL : parsing error on data | 1586 | * -EINVAL : parsing error on data |
1571 | * [1..n] : Number of phandle (count mode; when index = -1) | 1587 | * [1..n] : Number of phandle (count mode; when index = -1) |
1572 | */ | 1588 | */ |
1573 | rc = index < 0 ? cur_index : -ENOENT; | 1589 | if (rc == -ENOENT && index < 0) |
1590 | rc = cur_index; | ||
1591 | |||
1574 | err: | 1592 | err: |
1575 | if (it.node) | 1593 | if (it.node) |
1576 | of_node_put(it.node); | 1594 | of_node_put(it.node); |
diff --git a/include/linux/of.h b/include/linux/of.h index 0f187dbb890b..1f5e108f6716 100644 --- a/include/linux/of.h +++ b/include/linux/of.h | |||
@@ -358,6 +358,8 @@ extern int of_phandle_iterator_init(struct of_phandle_iterator *it, | |||
358 | const char *cells_name, | 358 | const char *cells_name, |
359 | int cell_count); | 359 | int cell_count); |
360 | 360 | ||
361 | extern int of_phandle_iterator_next(struct of_phandle_iterator *it); | ||
362 | |||
361 | extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)); | 363 | extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)); |
362 | extern int of_alias_get_id(struct device_node *np, const char *stem); | 364 | extern int of_alias_get_id(struct device_node *np, const char *stem); |
363 | extern int of_alias_get_highest_id(const char *stem); | 365 | extern int of_alias_get_highest_id(const char *stem); |
@@ -641,6 +643,11 @@ static inline int of_phandle_iterator_init(struct of_phandle_iterator *it, | |||
641 | return -ENOSYS; | 643 | return -ENOSYS; |
642 | } | 644 | } |
643 | 645 | ||
646 | static inline int of_phandle_iterator_next(struct of_phandle_iterator *it) | ||
647 | { | ||
648 | return -ENOSYS; | ||
649 | } | ||
650 | |||
644 | static inline int of_alias_get_id(struct device_node *np, const char *stem) | 651 | static inline int of_alias_get_id(struct device_node *np, const char *stem) |
645 | { | 652 | { |
646 | return -ENOSYS; | 653 | return -ENOSYS; |