diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2014-11-26 18:55:31 +0100 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2014-11-27 14:01:55 +0100 |
commit | 9a343b9eb8c1f8db9dae804709a6578379a538f3 (patch) | |
tree | 524bd793b8f74539cf474d16497a9b200b403d60 | |
parent | Linux 3.18-rc6 (diff) | |
download | linux-9a343b9eb8c1f8db9dae804709a6578379a538f3.tar.xz linux-9a343b9eb8c1f8db9dae804709a6578379a538f3.zip |
ARM: tegra: irq: fix buggy usage of irq_data irq field
The crazy gic_arch_extn thing that Tegra uses contains multiple
references to the irq field in struct irq_data, and uses this
to directly poke hardware register.
But irq is the *virtual* irq number, something that has nothing
to do with the actual HW irq (stored in the hwirq field). And once
we put the stacked domain code in action, the whole thing explodes,
as these two values are *very* different:
root@bacon-fat:~# cat /proc/interrupts
CPU0 CPU1
16: 25801 2075 GIC 29 twd
17: 0 0 GIC 73 timer0
112: 0 0 GPIO 58 c8000600.sdhci cd
123: 0 0 GPIO 69 c8000200.sdhci cd
279: 1126 0 GIC 122 serial
281: 0 0 GIC 70 7000c000.i2c
282: 0 0 GIC 116 7000c400.i2c
283: 0 0 GIC 124 7000c500.i2c
284: 300 0 GIC 85 7000d000.i2c
[...]
Just replacing all instances of irq with hwirq fixes the issue.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r-- | arch/arm/mach-tegra/irq.c | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c index da7be13aecce..ab95f5391a2b 100644 --- a/arch/arm/mach-tegra/irq.c +++ b/arch/arm/mach-tegra/irq.c @@ -99,42 +99,42 @@ static inline void tegra_irq_write_mask(unsigned int irq, unsigned long reg) static void tegra_mask(struct irq_data *d) { - if (d->irq < FIRST_LEGACY_IRQ) + if (d->hwirq < FIRST_LEGACY_IRQ) return; - tegra_irq_write_mask(d->irq, ICTLR_CPU_IER_CLR); + tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IER_CLR); } static void tegra_unmask(struct irq_data *d) { - if (d->irq < FIRST_LEGACY_IRQ) + if (d->hwirq < FIRST_LEGACY_IRQ) return; - tegra_irq_write_mask(d->irq, ICTLR_CPU_IER_SET); + tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IER_SET); } static void tegra_ack(struct irq_data *d) { - if (d->irq < FIRST_LEGACY_IRQ) + if (d->hwirq < FIRST_LEGACY_IRQ) return; - tegra_irq_write_mask(d->irq, ICTLR_CPU_IEP_FIR_CLR); + tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_CLR); } static void tegra_eoi(struct irq_data *d) { - if (d->irq < FIRST_LEGACY_IRQ) + if (d->hwirq < FIRST_LEGACY_IRQ) return; - tegra_irq_write_mask(d->irq, ICTLR_CPU_IEP_FIR_CLR); + tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_CLR); } static int tegra_retrigger(struct irq_data *d) { - if (d->irq < FIRST_LEGACY_IRQ) + if (d->hwirq < FIRST_LEGACY_IRQ) return 0; - tegra_irq_write_mask(d->irq, ICTLR_CPU_IEP_FIR_SET); + tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_SET); return 1; } @@ -142,7 +142,7 @@ static int tegra_retrigger(struct irq_data *d) #ifdef CONFIG_PM_SLEEP static int tegra_set_wake(struct irq_data *d, unsigned int enable) { - u32 irq = d->irq; + u32 irq = d->hwirq; u32 index, mask; if (irq < FIRST_LEGACY_IRQ || |