diff options
| author | Paul Burton <paul.burton@imgtec.com> | 2016-08-19 13:07:14 -0400 |
|---|---|---|
| committer | Thomas Gleixner <tglx@linutronix.de> | 2016-08-22 12:37:51 -0400 |
| commit | 6a33fa2b87513fee44cb8f0cd17b1acd6316bc6b (patch) | |
| tree | 18dc3a7448a3db01cd41025bab34ce0317307c55 | |
| parent | 3ee0ce2a54dff07d09440723594df89bc1a12e79 (diff) | |
irqchip/mips-gic: Cleanup chip and handler setup
gic_shared_irq_domain_map() is called from gic_irq_domain_alloc() where
the wrong chip has been set, and is then overwritten. Tidy this up by
setting the correct chip the first time, and setting the
handle_level_irq handler from gic_irq_domain_alloc() too.
gic_shared_irq_domain_map() is also called from gic_irq_domain_map(),
which now calls irq_set_chip_and_handler() to retain its previous
behaviour.
This patch prepares for a follow-on which will call
gic_shared_irq_domain_map() from a callback where the lock on the struct
irq_desc is held, which without this change would cause the call to
irq_set_chip_and_handler() to lead to a deadlock.
Fixes: c98c1822ee13 ("irqchip/mips-gic: Add device hierarchy domain")
Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: stable@vger.kernel.org
Link: http://lkml.kernel.org/r/20160819170715.27820-1-paul.burton@imgtec.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
| -rw-r--r-- | drivers/irqchip/irq-mips-gic.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index c5f33c3bd228..2e0f49992a98 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c | |||
| @@ -713,9 +713,6 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq, | |||
| 713 | unsigned long flags; | 713 | unsigned long flags; |
| 714 | int i; | 714 | int i; |
| 715 | 715 | ||
| 716 | irq_set_chip_and_handler(virq, &gic_level_irq_controller, | ||
| 717 | handle_level_irq); | ||
| 718 | |||
| 719 | spin_lock_irqsave(&gic_lock, flags); | 716 | spin_lock_irqsave(&gic_lock, flags); |
| 720 | gic_map_to_pin(intr, gic_cpu_pin); | 717 | gic_map_to_pin(intr, gic_cpu_pin); |
| 721 | gic_map_to_vpe(intr, mips_cm_vp_id(vpe)); | 718 | gic_map_to_vpe(intr, mips_cm_vp_id(vpe)); |
| @@ -732,6 +729,10 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq, | |||
| 732 | { | 729 | { |
| 733 | if (GIC_HWIRQ_TO_LOCAL(hw) < GIC_NUM_LOCAL_INTRS) | 730 | if (GIC_HWIRQ_TO_LOCAL(hw) < GIC_NUM_LOCAL_INTRS) |
| 734 | return gic_local_irq_domain_map(d, virq, hw); | 731 | return gic_local_irq_domain_map(d, virq, hw); |
| 732 | |||
| 733 | irq_set_chip_and_handler(virq, &gic_level_irq_controller, | ||
| 734 | handle_level_irq); | ||
| 735 | |||
| 735 | return gic_shared_irq_domain_map(d, virq, hw, 0); | 736 | return gic_shared_irq_domain_map(d, virq, hw, 0); |
| 736 | } | 737 | } |
| 737 | 738 | ||
| @@ -771,11 +772,13 @@ static int gic_irq_domain_alloc(struct irq_domain *d, unsigned int virq, | |||
| 771 | hwirq = GIC_SHARED_TO_HWIRQ(base_hwirq + i); | 772 | hwirq = GIC_SHARED_TO_HWIRQ(base_hwirq + i); |
| 772 | 773 | ||
| 773 | ret = irq_domain_set_hwirq_and_chip(d, virq + i, hwirq, | 774 | ret = irq_domain_set_hwirq_and_chip(d, virq + i, hwirq, |
| 774 | &gic_edge_irq_controller, | 775 | &gic_level_irq_controller, |
| 775 | NULL); | 776 | NULL); |
| 776 | if (ret) | 777 | if (ret) |
| 777 | goto error; | 778 | goto error; |
| 778 | 779 | ||
| 780 | irq_set_handler(virq + i, handle_level_irq); | ||
| 781 | |||
| 779 | ret = gic_shared_irq_domain_map(d, virq + i, hwirq, cpu); | 782 | ret = gic_shared_irq_domain_map(d, virq + i, hwirq, cpu); |
| 780 | if (ret) | 783 | if (ret) |
| 781 | goto error; | 784 | goto error; |
