diff options
| author | Marc Zyngier <marc.zyngier@arm.com> | 2014-11-24 09:35:09 -0500 |
|---|---|---|
| committer | Jason Cooper <jason@lakedaemon.net> | 2014-11-26 10:55:11 -0500 |
| commit | 443acc4f37f61e343f3577dc28d7e7fd8b499465 (patch) | |
| tree | e75db0912f5bce93d2e0bf33f7a011ba9ff372e9 | |
| parent | be091d468a0a09a7f4b1645e20cd6d36a353e51a (diff) | |
irqchip: GICv3: Convert to domain hierarchy
In order to start supporting stacked domains, convert the GICv3
code base to the new domain hierarchy framework, which mostly
amounts to supporting the new alloc/free callbacks.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Link: https://lkml.kernel.org/r/1416839720-18400-3-git-send-email-marc.zyngier@arm.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
| -rw-r--r-- | drivers/irqchip/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/irqchip/irq-gic-v3.c | 42 |
2 files changed, 38 insertions, 5 deletions
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index b21f12f1766d..4631685dfe43 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig | |||
| @@ -14,6 +14,7 @@ config ARM_GIC_V3 | |||
| 14 | bool | 14 | bool |
| 15 | select IRQ_DOMAIN | 15 | select IRQ_DOMAIN |
| 16 | select MULTI_IRQ_HANDLER | 16 | select MULTI_IRQ_HANDLER |
| 17 | select IRQ_DOMAIN_HIERARCHY | ||
| 17 | 18 | ||
| 18 | config ARM_NVIC | 19 | config ARM_NVIC |
| 19 | bool | 20 | bool |
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index aa17ae805a70..4cb355aff3c6 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c | |||
| @@ -594,14 +594,14 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, | |||
| 594 | /* PPIs */ | 594 | /* PPIs */ |
| 595 | if (hw < 32) { | 595 | if (hw < 32) { |
| 596 | irq_set_percpu_devid(irq); | 596 | irq_set_percpu_devid(irq); |
| 597 | irq_set_chip_and_handler(irq, &gic_chip, | 597 | irq_domain_set_info(d, irq, hw, &gic_chip, d->host_data, |
| 598 | handle_percpu_devid_irq); | 598 | handle_percpu_devid_irq, NULL, NULL); |
| 599 | set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN); | 599 | set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN); |
| 600 | } | 600 | } |
| 601 | /* SPIs */ | 601 | /* SPIs */ |
| 602 | if (hw >= 32 && hw < gic_data.irq_nr) { | 602 | if (hw >= 32 && hw < gic_data.irq_nr) { |
| 603 | irq_set_chip_and_handler(irq, &gic_chip, | 603 | irq_domain_set_info(d, irq, hw, &gic_chip, d->host_data, |
| 604 | handle_fasteoi_irq); | 604 | handle_fasteoi_irq, NULL, NULL); |
| 605 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | 605 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
| 606 | } | 606 | } |
| 607 | irq_set_chip_data(irq, d->host_data); | 607 | irq_set_chip_data(irq, d->host_data); |
| @@ -633,9 +633,41 @@ static int gic_irq_domain_xlate(struct irq_domain *d, | |||
| 633 | return 0; | 633 | return 0; |
| 634 | } | 634 | } |
| 635 | 635 | ||
| 636 | static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, | ||
| 637 | unsigned int nr_irqs, void *arg) | ||
| 638 | { | ||
| 639 | int i, ret; | ||
| 640 | irq_hw_number_t hwirq; | ||
| 641 | unsigned int type = IRQ_TYPE_NONE; | ||
| 642 | struct of_phandle_args *irq_data = arg; | ||
| 643 | |||
| 644 | ret = gic_irq_domain_xlate(domain, irq_data->np, irq_data->args, | ||
| 645 | irq_data->args_count, &hwirq, &type); | ||
| 646 | if (ret) | ||
| 647 | return ret; | ||
| 648 | |||
| 649 | for (i = 0; i < nr_irqs; i++) | ||
| 650 | gic_irq_domain_map(domain, virq + i, hwirq + i); | ||
| 651 | |||
| 652 | return 0; | ||
| 653 | } | ||
| 654 | |||
| 655 | static void gic_irq_domain_free(struct irq_domain *domain, unsigned int virq, | ||
| 656 | unsigned int nr_irqs) | ||
| 657 | { | ||
| 658 | int i; | ||
| 659 | |||
| 660 | for (i = 0; i < nr_irqs; i++) { | ||
| 661 | struct irq_data *d = irq_domain_get_irq_data(domain, virq + i); | ||
| 662 | irq_set_handler(virq + i, NULL); | ||
| 663 | irq_domain_reset_irq_data(d); | ||
| 664 | } | ||
| 665 | } | ||
| 666 | |||
| 636 | static const struct irq_domain_ops gic_irq_domain_ops = { | 667 | static const struct irq_domain_ops gic_irq_domain_ops = { |
| 637 | .map = gic_irq_domain_map, | ||
| 638 | .xlate = gic_irq_domain_xlate, | 668 | .xlate = gic_irq_domain_xlate, |
| 669 | .alloc = gic_irq_domain_alloc, | ||
| 670 | .free = gic_irq_domain_free, | ||
| 639 | }; | 671 | }; |
| 640 | 672 | ||
| 641 | static int __init gic_of_init(struct device_node *node, struct device_node *parent) | 673 | static int __init gic_of_init(struct device_node *node, struct device_node *parent) |
