diff options
author | Masahiro Yamada <yamada.masahiro@socionext.com> | 2015-11-24 08:10:26 -0500 |
---|---|---|
committer | Rob Herring <robh@kernel.org> | 2015-12-09 16:30:57 -0500 |
commit | 264041e3796133003f010303629a249f9caa3275 (patch) | |
tree | bab7ea1e9572cc8cc0fccc226503bd653b740421 /drivers/of | |
parent | e9e5f6365073b5f717172834986df8e2ec5a80b4 (diff) |
of/irq: optimize device node matching loop in of_irq_init()
Currently, of_irq_init() iterates over interrupt controller nodes
with for_each_matching_node(), and then gets each init function with
of_match_node() later.
This routine can be optimized with for_each_matching_node_and_match().
It allows to get the interrupt controller node and its init function
at the same time, saving __of_match_node() callings.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: Rob Herring <robh@kernel.org>
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/irq.c | 27 |
1 files changed, 13 insertions, 14 deletions
diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 902b89be7217..4c0da87b417c 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c | |||
@@ -472,6 +472,7 @@ EXPORT_SYMBOL_GPL(of_irq_to_resource_table); | |||
472 | 472 | ||
473 | struct of_intc_desc { | 473 | struct of_intc_desc { |
474 | struct list_head list; | 474 | struct list_head list; |
475 | of_irq_init_cb_t irq_init_cb; | ||
475 | struct device_node *dev; | 476 | struct device_node *dev; |
476 | struct device_node *interrupt_parent; | 477 | struct device_node *interrupt_parent; |
477 | }; | 478 | }; |
@@ -485,6 +486,7 @@ struct of_intc_desc { | |||
485 | */ | 486 | */ |
486 | void __init of_irq_init(const struct of_device_id *matches) | 487 | void __init of_irq_init(const struct of_device_id *matches) |
487 | { | 488 | { |
489 | const struct of_device_id *match; | ||
488 | struct device_node *np, *parent = NULL; | 490 | struct device_node *np, *parent = NULL; |
489 | struct of_intc_desc *desc, *temp_desc; | 491 | struct of_intc_desc *desc, *temp_desc; |
490 | struct list_head intc_desc_list, intc_parent_list; | 492 | struct list_head intc_desc_list, intc_parent_list; |
@@ -492,10 +494,15 @@ void __init of_irq_init(const struct of_device_id *matches) | |||
492 | INIT_LIST_HEAD(&intc_desc_list); | 494 | INIT_LIST_HEAD(&intc_desc_list); |
493 | INIT_LIST_HEAD(&intc_parent_list); | 495 | INIT_LIST_HEAD(&intc_parent_list); |
494 | 496 | ||
495 | for_each_matching_node(np, matches) { | 497 | for_each_matching_node_and_match(np, matches, &match) { |
496 | if (!of_find_property(np, "interrupt-controller", NULL) || | 498 | if (!of_find_property(np, "interrupt-controller", NULL) || |
497 | !of_device_is_available(np)) | 499 | !of_device_is_available(np)) |
498 | continue; | 500 | continue; |
501 | |||
502 | if (WARN(!match->data, "of_irq_init: no init function for %s\n", | ||
503 | match->compatible)) | ||
504 | continue; | ||
505 | |||
499 | /* | 506 | /* |
500 | * Here, we allocate and populate an of_intc_desc with the node | 507 | * Here, we allocate and populate an of_intc_desc with the node |
501 | * pointer, interrupt-parent device_node etc. | 508 | * pointer, interrupt-parent device_node etc. |
@@ -506,6 +513,7 @@ void __init of_irq_init(const struct of_device_id *matches) | |||
506 | goto err; | 513 | goto err; |
507 | } | 514 | } |
508 | 515 | ||
516 | desc->irq_init_cb = match->data; | ||
509 | desc->dev = of_node_get(np); | 517 | desc->dev = of_node_get(np); |
510 | desc->interrupt_parent = of_irq_find_parent(np); | 518 | desc->interrupt_parent = of_irq_find_parent(np); |
511 | if (desc->interrupt_parent == np) | 519 | if (desc->interrupt_parent == np) |
@@ -525,27 +533,18 @@ void __init of_irq_init(const struct of_device_id *matches) | |||
525 | * The assumption is that NULL parent means a root controller. | 533 | * The assumption is that NULL parent means a root controller. |
526 | */ | 534 | */ |
527 | list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) { | 535 | list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) { |
528 | const struct of_device_id *match; | ||
529 | int ret; | 536 | int ret; |
530 | of_irq_init_cb_t irq_init_cb; | ||
531 | 537 | ||
532 | if (desc->interrupt_parent != parent) | 538 | if (desc->interrupt_parent != parent) |
533 | continue; | 539 | continue; |
534 | 540 | ||
535 | list_del(&desc->list); | 541 | list_del(&desc->list); |
536 | match = of_match_node(matches, desc->dev); | ||
537 | if (WARN(!match->data, | ||
538 | "of_irq_init: no init function for %s\n", | ||
539 | match->compatible)) { | ||
540 | kfree(desc); | ||
541 | continue; | ||
542 | } | ||
543 | 542 | ||
544 | pr_debug("of_irq_init: init %s @ %p, parent %p\n", | 543 | pr_debug("of_irq_init: init %s (%p), parent %p\n", |
545 | match->compatible, | 544 | desc->dev->full_name, |
546 | desc->dev, desc->interrupt_parent); | 545 | desc->dev, desc->interrupt_parent); |
547 | irq_init_cb = (of_irq_init_cb_t)match->data; | 546 | ret = desc->irq_init_cb(desc->dev, |
548 | ret = irq_init_cb(desc->dev, desc->interrupt_parent); | 547 | desc->interrupt_parent); |
549 | if (ret) { | 548 | if (ret) { |
550 | kfree(desc); | 549 | kfree(desc); |
551 | continue; | 550 | continue; |