diff options
author | Jason Cooper <jason@lakedaemon.net> | 2014-09-14 03:53:54 -0400 |
---|---|---|
committer | Jason Cooper <jason@lakedaemon.net> | 2014-09-14 03:53:54 -0400 |
commit | 468a903c0e5147e3f93187f0b808a3ef957fd00e (patch) | |
tree | 63542d05b1c0f730ec1ad5f915dc4eb3c015e616 | |
parent | ce92bfe88ba38e76371feb93307125fac3f800f0 (diff) | |
parent | 087fe000f086c933f831044cbd0e69b4e140f38c (diff) |
Merge branch 'irqchip/handle_domain' into irqchip/core
31 files changed, 116 insertions, 130 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c49a775937db..5918d40bb12e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -24,6 +24,7 @@ config ARM | |||
24 | select GENERIC_SMP_IDLE_THREAD | 24 | select GENERIC_SMP_IDLE_THREAD |
25 | select GENERIC_STRNCPY_FROM_USER | 25 | select GENERIC_STRNCPY_FROM_USER |
26 | select GENERIC_STRNLEN_USER | 26 | select GENERIC_STRNLEN_USER |
27 | select HANDLE_DOMAIN_IRQ | ||
27 | select HARDIRQS_SW_RESEND | 28 | select HARDIRQS_SW_RESEND |
28 | select HAVE_ARCH_AUDITSYSCALL if (AEABI && !OABI_COMPAT) | 29 | select HAVE_ARCH_AUDITSYSCALL if (AEABI && !OABI_COMPAT) |
29 | select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL | 30 | select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL |
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 2c4257604513..0509d07c96ab 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c | |||
@@ -65,24 +65,7 @@ int arch_show_interrupts(struct seq_file *p, int prec) | |||
65 | */ | 65 | */ |
66 | void handle_IRQ(unsigned int irq, struct pt_regs *regs) | 66 | void handle_IRQ(unsigned int irq, struct pt_regs *regs) |
67 | { | 67 | { |
68 | struct pt_regs *old_regs = set_irq_regs(regs); | 68 | __handle_domain_irq(NULL, irq, false, regs); |
69 | |||
70 | irq_enter(); | ||
71 | |||
72 | /* | ||
73 | * Some hardware gives randomly wrong interrupts. Rather | ||
74 | * than crashing, do something sensible. | ||
75 | */ | ||
76 | if (unlikely(irq >= nr_irqs)) { | ||
77 | if (printk_ratelimit()) | ||
78 | printk(KERN_WARNING "Bad IRQ%u\n", irq); | ||
79 | ack_bad_irq(irq); | ||
80 | } else { | ||
81 | generic_handle_irq(irq); | ||
82 | } | ||
83 | |||
84 | irq_exit(); | ||
85 | set_irq_regs(old_regs); | ||
86 | } | 69 | } |
87 | 70 | ||
88 | /* | 71 | /* |
diff --git a/arch/arm/mach-imx/avic.c b/arch/arm/mach-imx/avic.c index 24b103c67f82..1a8932335b21 100644 --- a/arch/arm/mach-imx/avic.c +++ b/arch/arm/mach-imx/avic.c | |||
@@ -144,7 +144,7 @@ static void __exception_irq_entry avic_handle_irq(struct pt_regs *regs) | |||
144 | if (nivector == 0xffff) | 144 | if (nivector == 0xffff) |
145 | break; | 145 | break; |
146 | 146 | ||
147 | handle_IRQ(irq_find_mapping(domain, nivector), regs); | 147 | handle_domain_irq(domain, nivector, regs); |
148 | } while (1); | 148 | } while (1); |
149 | } | 149 | } |
150 | 150 | ||
diff --git a/arch/arm/mach-imx/tzic.c b/arch/arm/mach-imx/tzic.c index 1d4f384ca773..4de65eeda1eb 100644 --- a/arch/arm/mach-imx/tzic.c +++ b/arch/arm/mach-imx/tzic.c | |||
@@ -141,8 +141,7 @@ static void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs) | |||
141 | while (stat) { | 141 | while (stat) { |
142 | handled = 1; | 142 | handled = 1; |
143 | irqofs = fls(stat) - 1; | 143 | irqofs = fls(stat) - 1; |
144 | handle_IRQ(irq_find_mapping(domain, | 144 | handle_domain_irq(domain, irqofs + i * 32, regs); |
145 | irqofs + i * 32), regs); | ||
146 | stat &= ~(1 << irqofs); | 145 | stat &= ~(1 << irqofs); |
147 | } | 146 | } |
148 | } | 147 | } |
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index 35b8590c322e..a62ba5aebe63 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c | |||
@@ -248,8 +248,7 @@ out: | |||
248 | irqnr &= ACTIVEIRQ_MASK; | 248 | irqnr &= ACTIVEIRQ_MASK; |
249 | 249 | ||
250 | if (irqnr) { | 250 | if (irqnr) { |
251 | irqnr = irq_find_mapping(domain, irqnr); | 251 | handle_domain_irq(domain, irqnr, regs); |
252 | handle_IRQ(irqnr, regs); | ||
253 | handled_irq = 1; | 252 | handled_irq = 1; |
254 | } | 253 | } |
255 | } while (irqnr); | 254 | } while (irqnr); |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index fd4e81a4e1ce..1f16ed96f3f6 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig | |||
@@ -30,6 +30,7 @@ config ARM64 | |||
30 | select GENERIC_STRNCPY_FROM_USER | 30 | select GENERIC_STRNCPY_FROM_USER |
31 | select GENERIC_STRNLEN_USER | 31 | select GENERIC_STRNLEN_USER |
32 | select GENERIC_TIME_VSYSCALL | 32 | select GENERIC_TIME_VSYSCALL |
33 | select HANDLE_DOMAIN_IRQ | ||
33 | select HARDIRQS_SW_RESEND | 34 | select HARDIRQS_SW_RESEND |
34 | select HAVE_ARCH_AUDITSYSCALL | 35 | select HAVE_ARCH_AUDITSYSCALL |
35 | select HAVE_ARCH_JUMP_LABEL | 36 | select HAVE_ARCH_JUMP_LABEL |
diff --git a/arch/arm64/include/asm/hardirq.h b/arch/arm64/include/asm/hardirq.h index 0be67821f9ce..e8a3268a891c 100644 --- a/arch/arm64/include/asm/hardirq.h +++ b/arch/arm64/include/asm/hardirq.h | |||
@@ -47,8 +47,6 @@ static inline void ack_bad_irq(unsigned int irq) | |||
47 | irq_err_count++; | 47 | irq_err_count++; |
48 | } | 48 | } |
49 | 49 | ||
50 | extern void handle_IRQ(unsigned int, struct pt_regs *); | ||
51 | |||
52 | /* | 50 | /* |
53 | * No arch-specific IRQ flags. | 51 | * No arch-specific IRQ flags. |
54 | */ | 52 | */ |
diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c index 0f08dfd69ebc..67ca197277ee 100644 --- a/arch/arm64/kernel/irq.c +++ b/arch/arm64/kernel/irq.c | |||
@@ -40,33 +40,6 @@ int arch_show_interrupts(struct seq_file *p, int prec) | |||
40 | return 0; | 40 | return 0; |
41 | } | 41 | } |
42 | 42 | ||
43 | /* | ||
44 | * handle_IRQ handles all hardware IRQ's. Decoded IRQs should | ||
45 | * not come via this function. Instead, they should provide their | ||
46 | * own 'handler'. Used by platform code implementing C-based 1st | ||
47 | * level decoding. | ||
48 | */ | ||
49 | void handle_IRQ(unsigned int irq, struct pt_regs *regs) | ||
50 | { | ||
51 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
52 | |||
53 | irq_enter(); | ||
54 | |||
55 | /* | ||
56 | * Some hardware gives randomly wrong interrupts. Rather | ||
57 | * than crashing, do something sensible. | ||
58 | */ | ||
59 | if (unlikely(irq >= nr_irqs)) { | ||
60 | pr_warn_ratelimited("Bad IRQ%u\n", irq); | ||
61 | ack_bad_irq(irq); | ||
62 | } else { | ||
63 | generic_handle_irq(irq); | ||
64 | } | ||
65 | |||
66 | irq_exit(); | ||
67 | set_irq_regs(old_regs); | ||
68 | } | ||
69 | |||
70 | void __init set_handle_irq(void (*handle_irq)(struct pt_regs *)) | 43 | void __init set_handle_irq(void (*handle_irq)(struct pt_regs *)) |
71 | { | 44 | { |
72 | if (handle_arch_irq) | 45 | if (handle_arch_irq) |
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig index 88e83368bbf5..e5a693b16da2 100644 --- a/arch/openrisc/Kconfig +++ b/arch/openrisc/Kconfig | |||
@@ -8,6 +8,7 @@ config OPENRISC | |||
8 | select OF | 8 | select OF |
9 | select OF_EARLY_FLATTREE | 9 | select OF_EARLY_FLATTREE |
10 | select IRQ_DOMAIN | 10 | select IRQ_DOMAIN |
11 | select HANDLE_DOMAIN_IRQ | ||
11 | select HAVE_MEMBLOCK | 12 | select HAVE_MEMBLOCK |
12 | select ARCH_REQUIRE_GPIOLIB | 13 | select ARCH_REQUIRE_GPIOLIB |
13 | select HAVE_ARCH_TRACEHOOK | 14 | select HAVE_ARCH_TRACEHOOK |
diff --git a/arch/openrisc/include/asm/irq.h b/arch/openrisc/include/asm/irq.h index b84634cc95eb..d9eee0a2b7b4 100644 --- a/arch/openrisc/include/asm/irq.h +++ b/arch/openrisc/include/asm/irq.h | |||
@@ -24,7 +24,6 @@ | |||
24 | 24 | ||
25 | #define NO_IRQ (-1) | 25 | #define NO_IRQ (-1) |
26 | 26 | ||
27 | void handle_IRQ(unsigned int, struct pt_regs *); | ||
28 | extern void set_handle_irq(void (*handle_irq)(struct pt_regs *)); | 27 | extern void set_handle_irq(void (*handle_irq)(struct pt_regs *)); |
29 | 28 | ||
30 | #endif /* __ASM_OPENRISC_IRQ_H__ */ | 29 | #endif /* __ASM_OPENRISC_IRQ_H__ */ |
diff --git a/arch/openrisc/kernel/irq.c b/arch/openrisc/kernel/irq.c index 967eb1430203..35e478a93116 100644 --- a/arch/openrisc/kernel/irq.c +++ b/arch/openrisc/kernel/irq.c | |||
@@ -48,18 +48,6 @@ void __init set_handle_irq(void (*handle_irq)(struct pt_regs *)) | |||
48 | handle_arch_irq = handle_irq; | 48 | handle_arch_irq = handle_irq; |
49 | } | 49 | } |
50 | 50 | ||
51 | void handle_IRQ(unsigned int irq, struct pt_regs *regs) | ||
52 | { | ||
53 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
54 | |||
55 | irq_enter(); | ||
56 | |||
57 | generic_handle_irq(irq); | ||
58 | |||
59 | irq_exit(); | ||
60 | set_irq_regs(old_regs); | ||
61 | } | ||
62 | |||
63 | void __irq_entry do_IRQ(struct pt_regs *regs) | 51 | void __irq_entry do_IRQ(struct pt_regs *regs) |
64 | { | 52 | { |
65 | handle_arch_irq(regs); | 53 | handle_arch_irq(regs); |
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 574aba0eba4e..fa75a29a0408 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c | |||
@@ -393,13 +393,15 @@ static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained) | |||
393 | if (!(msimask & BIT(msinr))) | 393 | if (!(msimask & BIT(msinr))) |
394 | continue; | 394 | continue; |
395 | 395 | ||
396 | irq = irq_find_mapping(armada_370_xp_msi_domain, | 396 | if (is_chained) { |
397 | msinr - 16); | 397 | irq = irq_find_mapping(armada_370_xp_msi_domain, |
398 | 398 | msinr - 16); | |
399 | if (is_chained) | ||
400 | generic_handle_irq(irq); | 399 | generic_handle_irq(irq); |
401 | else | 400 | } else { |
402 | handle_IRQ(irq, regs); | 401 | irq = msinr - 16; |
402 | handle_domain_irq(armada_370_xp_msi_domain, | ||
403 | irq, regs); | ||
404 | } | ||
403 | } | 405 | } |
404 | } | 406 | } |
405 | #else | 407 | #else |
@@ -444,9 +446,8 @@ armada_370_xp_handle_irq(struct pt_regs *regs) | |||
444 | break; | 446 | break; |
445 | 447 | ||
446 | if (irqnr > 1) { | 448 | if (irqnr > 1) { |
447 | irqnr = irq_find_mapping(armada_370_xp_mpic_domain, | 449 | handle_domain_irq(armada_370_xp_mpic_domain, |
448 | irqnr); | 450 | irqnr, regs); |
449 | handle_IRQ(irqnr, regs); | ||
450 | continue; | 451 | continue; |
451 | } | 452 | } |
452 | 453 | ||
diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c index a82869e9fb26..9a2cf3c1a3a5 100644 --- a/drivers/irqchip/irq-atmel-aic.c +++ b/drivers/irqchip/irq-atmel-aic.c | |||
@@ -68,12 +68,10 @@ aic_handle(struct pt_regs *regs) | |||
68 | irqnr = irq_reg_readl(gc->reg_base + AT91_AIC_IVR); | 68 | irqnr = irq_reg_readl(gc->reg_base + AT91_AIC_IVR); |
69 | irqstat = irq_reg_readl(gc->reg_base + AT91_AIC_ISR); | 69 | irqstat = irq_reg_readl(gc->reg_base + AT91_AIC_ISR); |
70 | 70 | ||
71 | irqnr = irq_find_mapping(aic_domain, irqnr); | ||
72 | |||
73 | if (!irqstat) | 71 | if (!irqstat) |
74 | irq_reg_writel(0, gc->reg_base + AT91_AIC_EOICR); | 72 | irq_reg_writel(0, gc->reg_base + AT91_AIC_EOICR); |
75 | else | 73 | else |
76 | handle_IRQ(irqnr, regs); | 74 | handle_domain_irq(aic_domain, irqnr, regs); |
77 | } | 75 | } |
78 | 76 | ||
79 | static int aic_retrigger(struct irq_data *d) | 77 | static int aic_retrigger(struct irq_data *d) |
diff --git a/drivers/irqchip/irq-atmel-aic5.c b/drivers/irqchip/irq-atmel-aic5.c index edb227081524..04fe2c1b5178 100644 --- a/drivers/irqchip/irq-atmel-aic5.c +++ b/drivers/irqchip/irq-atmel-aic5.c | |||
@@ -78,12 +78,10 @@ aic5_handle(struct pt_regs *regs) | |||
78 | irqnr = irq_reg_readl(gc->reg_base + AT91_AIC5_IVR); | 78 | irqnr = irq_reg_readl(gc->reg_base + AT91_AIC5_IVR); |
79 | irqstat = irq_reg_readl(gc->reg_base + AT91_AIC5_ISR); | 79 | irqstat = irq_reg_readl(gc->reg_base + AT91_AIC5_ISR); |
80 | 80 | ||
81 | irqnr = irq_find_mapping(aic5_domain, irqnr); | ||
82 | |||
83 | if (!irqstat) | 81 | if (!irqstat) |
84 | irq_reg_writel(0, gc->reg_base + AT91_AIC5_EOICR); | 82 | irq_reg_writel(0, gc->reg_base + AT91_AIC5_EOICR); |
85 | else | 83 | else |
86 | handle_IRQ(irqnr, regs); | 84 | handle_domain_irq(aic5_domain, irqnr, regs); |
87 | } | 85 | } |
88 | 86 | ||
89 | static void aic5_mask(struct irq_data *d) | 87 | static void aic5_mask(struct irq_data *d) |
diff --git a/drivers/irqchip/irq-clps711x.c b/drivers/irqchip/irq-clps711x.c index 33340dc97d1d..33127f131d78 100644 --- a/drivers/irqchip/irq-clps711x.c +++ b/drivers/irqchip/irq-clps711x.c | |||
@@ -76,24 +76,20 @@ static struct { | |||
76 | 76 | ||
77 | static asmlinkage void __exception_irq_entry clps711x_irqh(struct pt_regs *regs) | 77 | static asmlinkage void __exception_irq_entry clps711x_irqh(struct pt_regs *regs) |
78 | { | 78 | { |
79 | u32 irqnr, irqstat; | 79 | u32 irqstat; |
80 | 80 | ||
81 | do { | 81 | do { |
82 | irqstat = readw_relaxed(clps711x_intc->intmr[0]) & | 82 | irqstat = readw_relaxed(clps711x_intc->intmr[0]) & |
83 | readw_relaxed(clps711x_intc->intsr[0]); | 83 | readw_relaxed(clps711x_intc->intsr[0]); |
84 | if (irqstat) { | 84 | if (irqstat) |
85 | irqnr = irq_find_mapping(clps711x_intc->domain, | 85 | handle_domain_irq(clps711x_intc->domain, |
86 | fls(irqstat) - 1); | 86 | fls(irqstat) - 1, regs); |
87 | handle_IRQ(irqnr, regs); | ||
88 | } | ||
89 | 87 | ||
90 | irqstat = readw_relaxed(clps711x_intc->intmr[1]) & | 88 | irqstat = readw_relaxed(clps711x_intc->intmr[1]) & |
91 | readw_relaxed(clps711x_intc->intsr[1]); | 89 | readw_relaxed(clps711x_intc->intsr[1]); |
92 | if (irqstat) { | 90 | if (irqstat) |
93 | irqnr = irq_find_mapping(clps711x_intc->domain, | 91 | handle_domain_irq(clps711x_intc->domain, |
94 | fls(irqstat) - 1 + 16); | 92 | fls(irqstat) - 1 + 16, regs); |
95 | handle_IRQ(irqnr, regs); | ||
96 | } | ||
97 | } while (irqstat); | 93 | } while (irqstat); |
98 | } | 94 | } |
99 | 95 | ||
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 57eaa5a0b1e3..9e3144975696 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c | |||
@@ -274,14 +274,13 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs | |||
274 | irqnr = gic_read_iar(); | 274 | irqnr = gic_read_iar(); |
275 | 275 | ||
276 | if (likely(irqnr > 15 && irqnr < 1020)) { | 276 | if (likely(irqnr > 15 && irqnr < 1020)) { |
277 | u64 irq = irq_find_mapping(gic_data.domain, irqnr); | 277 | int err; |
278 | if (likely(irq)) { | 278 | err = handle_domain_irq(gic_data.domain, irqnr, regs); |
279 | handle_IRQ(irq, regs); | 279 | if (err) { |
280 | continue; | 280 | WARN_ONCE(true, "Unexpected SPI received!\n"); |
281 | gic_write_eoir(irqnr); | ||
281 | } | 282 | } |
282 | 283 | continue; | |
283 | WARN_ONCE(true, "Unexpected SPI received!\n"); | ||
284 | gic_write_eoir(irqnr); | ||
285 | } | 284 | } |
286 | if (irqnr < 16) { | 285 | if (irqnr < 16) { |
287 | gic_write_eoir(irqnr); | 286 | gic_write_eoir(irqnr); |
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 2500f6ba29e1..55aa6f62c77c 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c | |||
@@ -270,8 +270,7 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) | |||
270 | irqnr = irqstat & GICC_IAR_INT_ID_MASK; | 270 | irqnr = irqstat & GICC_IAR_INT_ID_MASK; |
271 | 271 | ||
272 | if (likely(irqnr > 15 && irqnr < 1021)) { | 272 | if (likely(irqnr > 15 && irqnr < 1021)) { |
273 | irqnr = irq_find_mapping(gic->domain, irqnr); | 273 | handle_domain_irq(gic->domain, irqnr, regs); |
274 | handle_IRQ(irqnr, regs); | ||
275 | continue; | 274 | continue; |
276 | } | 275 | } |
277 | if (irqnr < 16) { | 276 | if (irqnr < 16) { |
diff --git a/drivers/irqchip/irq-mmp.c b/drivers/irqchip/irq-mmp.c index 1c3e2c9b46ba..c0da57bdb89d 100644 --- a/drivers/irqchip/irq-mmp.c +++ b/drivers/irqchip/irq-mmp.c | |||
@@ -196,26 +196,24 @@ static struct mmp_intc_conf mmp2_conf = { | |||
196 | 196 | ||
197 | static void __exception_irq_entry mmp_handle_irq(struct pt_regs *regs) | 197 | static void __exception_irq_entry mmp_handle_irq(struct pt_regs *regs) |
198 | { | 198 | { |
199 | int irq, hwirq; | 199 | int hwirq; |
200 | 200 | ||
201 | hwirq = readl_relaxed(mmp_icu_base + PJ1_INT_SEL); | 201 | hwirq = readl_relaxed(mmp_icu_base + PJ1_INT_SEL); |
202 | if (!(hwirq & SEL_INT_PENDING)) | 202 | if (!(hwirq & SEL_INT_PENDING)) |
203 | return; | 203 | return; |
204 | hwirq &= SEL_INT_NUM_MASK; | 204 | hwirq &= SEL_INT_NUM_MASK; |
205 | irq = irq_find_mapping(icu_data[0].domain, hwirq); | 205 | handle_domain_irq(icu_data[0].domain, hwirq, regs); |
206 | handle_IRQ(irq, regs); | ||
207 | } | 206 | } |
208 | 207 | ||
209 | static void __exception_irq_entry mmp2_handle_irq(struct pt_regs *regs) | 208 | static void __exception_irq_entry mmp2_handle_irq(struct pt_regs *regs) |
210 | { | 209 | { |
211 | int irq, hwirq; | 210 | int hwirq; |
212 | 211 | ||
213 | hwirq = readl_relaxed(mmp_icu_base + PJ4_INT_SEL); | 212 | hwirq = readl_relaxed(mmp_icu_base + PJ4_INT_SEL); |
214 | if (!(hwirq & SEL_INT_PENDING)) | 213 | if (!(hwirq & SEL_INT_PENDING)) |
215 | return; | 214 | return; |
216 | hwirq &= SEL_INT_NUM_MASK; | 215 | hwirq &= SEL_INT_NUM_MASK; |
217 | irq = irq_find_mapping(icu_data[0].domain, hwirq); | 216 | handle_domain_irq(icu_data[0].domain, hwirq, regs); |
218 | handle_IRQ(irq, regs); | ||
219 | } | 217 | } |
220 | 218 | ||
221 | /* MMP (ARMv5) */ | 219 | /* MMP (ARMv5) */ |
diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c index 4044ff287663..e4acf1e3f8e3 100644 --- a/drivers/irqchip/irq-mxs.c +++ b/drivers/irqchip/irq-mxs.c | |||
@@ -78,8 +78,7 @@ asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs) | |||
78 | 78 | ||
79 | irqnr = __raw_readl(icoll_base + HW_ICOLL_STAT_OFFSET); | 79 | irqnr = __raw_readl(icoll_base + HW_ICOLL_STAT_OFFSET); |
80 | __raw_writel(irqnr, icoll_base + HW_ICOLL_VECTOR); | 80 | __raw_writel(irqnr, icoll_base + HW_ICOLL_VECTOR); |
81 | irqnr = irq_find_mapping(icoll_domain, irqnr); | 81 | handle_domain_irq(icoll_domain, irqnr, regs); |
82 | handle_IRQ(irqnr, regs); | ||
83 | } | 82 | } |
84 | 83 | ||
85 | static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq, | 84 | static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq, |
diff --git a/drivers/irqchip/irq-or1k-pic.c b/drivers/irqchip/irq-or1k-pic.c index 17ff033d9925..e93d079fe069 100644 --- a/drivers/irqchip/irq-or1k-pic.c +++ b/drivers/irqchip/irq-or1k-pic.c | |||
@@ -113,7 +113,7 @@ static inline int pic_get_irq(int first) | |||
113 | else | 113 | else |
114 | hwirq = hwirq + first - 1; | 114 | hwirq = hwirq + first - 1; |
115 | 115 | ||
116 | return irq_find_mapping(root_domain, hwirq); | 116 | return hwirq; |
117 | } | 117 | } |
118 | 118 | ||
119 | static void or1k_pic_handle_irq(struct pt_regs *regs) | 119 | static void or1k_pic_handle_irq(struct pt_regs *regs) |
@@ -121,7 +121,7 @@ static void or1k_pic_handle_irq(struct pt_regs *regs) | |||
121 | int irq = -1; | 121 | int irq = -1; |
122 | 122 | ||
123 | while ((irq = pic_get_irq(irq + 1)) != NO_IRQ) | 123 | while ((irq = pic_get_irq(irq + 1)) != NO_IRQ) |
124 | handle_IRQ(irq, regs); | 124 | handle_domain_irq(root_domain, irq, regs); |
125 | } | 125 | } |
126 | 126 | ||
127 | static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) | 127 | static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) |
diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c index 34d18b48bb78..ad0c0f6f1d65 100644 --- a/drivers/irqchip/irq-orion.c +++ b/drivers/irqchip/irq-orion.c | |||
@@ -43,9 +43,8 @@ __exception_irq_entry orion_handle_irq(struct pt_regs *regs) | |||
43 | gc->mask_cache; | 43 | gc->mask_cache; |
44 | while (stat) { | 44 | while (stat) { |
45 | u32 hwirq = __fls(stat); | 45 | u32 hwirq = __fls(stat); |
46 | u32 irq = irq_find_mapping(orion_irq_domain, | 46 | handle_domain_irq(orion_irq_domain, |
47 | gc->irq_base + hwirq); | 47 | gc->irq_base + hwirq, regs); |
48 | handle_IRQ(irq, regs); | ||
49 | stat &= ~(1 << hwirq); | 48 | stat &= ~(1 << hwirq); |
50 | } | 49 | } |
51 | } | 50 | } |
diff --git a/drivers/irqchip/irq-s3c24xx.c b/drivers/irqchip/irq-s3c24xx.c index 78a6accd205f..c8d373fcd823 100644 --- a/drivers/irqchip/irq-s3c24xx.c +++ b/drivers/irqchip/irq-s3c24xx.c | |||
@@ -339,7 +339,6 @@ static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc, | |||
339 | { | 339 | { |
340 | int pnd; | 340 | int pnd; |
341 | int offset; | 341 | int offset; |
342 | int irq; | ||
343 | 342 | ||
344 | pnd = __raw_readl(intc->reg_intpnd); | 343 | pnd = __raw_readl(intc->reg_intpnd); |
345 | if (!pnd) | 344 | if (!pnd) |
@@ -365,8 +364,7 @@ static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc, | |||
365 | if (!(pnd & (1 << offset))) | 364 | if (!(pnd & (1 << offset))) |
366 | offset = __ffs(pnd); | 365 | offset = __ffs(pnd); |
367 | 366 | ||
368 | irq = irq_find_mapping(intc->domain, intc_offset + offset); | 367 | handle_domain_irq(intc->domain, intc_offset + offset, regs); |
369 | handle_IRQ(irq, regs); | ||
370 | return true; | 368 | return true; |
371 | } | 369 | } |
372 | 370 | ||
diff --git a/drivers/irqchip/irq-sirfsoc.c b/drivers/irqchip/irq-sirfsoc.c index 5e54f6d71e77..a469355df352 100644 --- a/drivers/irqchip/irq-sirfsoc.c +++ b/drivers/irqchip/irq-sirfsoc.c | |||
@@ -50,12 +50,10 @@ sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num) | |||
50 | static void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs) | 50 | static void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs) |
51 | { | 51 | { |
52 | void __iomem *base = sirfsoc_irqdomain->host_data; | 52 | void __iomem *base = sirfsoc_irqdomain->host_data; |
53 | u32 irqstat, irqnr; | 53 | u32 irqstat; |
54 | 54 | ||
55 | irqstat = readl_relaxed(base + SIRFSOC_INIT_IRQ_ID); | 55 | irqstat = readl_relaxed(base + SIRFSOC_INIT_IRQ_ID); |
56 | irqnr = irq_find_mapping(sirfsoc_irqdomain, irqstat & 0xff); | 56 | handle_domain_irq(sirfsoc_irqdomain, irqstat & 0xff, regs); |
57 | |||
58 | handle_IRQ(irqnr, regs); | ||
59 | } | 57 | } |
60 | 58 | ||
61 | static int __init sirfsoc_irq_init(struct device_node *np, | 59 | static int __init sirfsoc_irq_init(struct device_node *np, |
diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c index 6fcef4a95a18..64155b686081 100644 --- a/drivers/irqchip/irq-sun4i.c +++ b/drivers/irqchip/irq-sun4i.c | |||
@@ -136,7 +136,7 @@ IRQCHIP_DECLARE(allwinner_sun4i_ic, "allwinner,sun4i-a10-ic", sun4i_of_init); | |||
136 | 136 | ||
137 | static void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs) | 137 | static void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs) |
138 | { | 138 | { |
139 | u32 irq, hwirq; | 139 | u32 hwirq; |
140 | 140 | ||
141 | /* | 141 | /* |
142 | * hwirq == 0 can mean one of 3 things: | 142 | * hwirq == 0 can mean one of 3 things: |
@@ -154,8 +154,7 @@ static void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs) | |||
154 | return; | 154 | return; |
155 | 155 | ||
156 | do { | 156 | do { |
157 | irq = irq_find_mapping(sun4i_irq_domain, hwirq); | 157 | handle_domain_irq(sun4i_irq_domain, hwirq, regs); |
158 | handle_IRQ(irq, regs); | ||
159 | hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2; | 158 | hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2; |
160 | } while (hwirq != 0); | 159 | } while (hwirq != 0); |
161 | } | 160 | } |
diff --git a/drivers/irqchip/irq-versatile-fpga.c b/drivers/irqchip/irq-versatile-fpga.c index ccf58548b161..1ab451729a5c 100644 --- a/drivers/irqchip/irq-versatile-fpga.c +++ b/drivers/irqchip/irq-versatile-fpga.c | |||
@@ -96,7 +96,7 @@ static int handle_one_fpga(struct fpga_irq_data *f, struct pt_regs *regs) | |||
96 | 96 | ||
97 | while ((status = readl(f->base + IRQ_STATUS))) { | 97 | while ((status = readl(f->base + IRQ_STATUS))) { |
98 | irq = ffs(status) - 1; | 98 | irq = ffs(status) - 1; |
99 | handle_IRQ(irq_find_mapping(f->domain, irq), regs); | 99 | handle_domain_irq(f->domain, irq, regs); |
100 | handled = 1; | 100 | handled = 1; |
101 | } | 101 | } |
102 | 102 | ||
diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c index 7d35287f9e90..54089debf2dc 100644 --- a/drivers/irqchip/irq-vic.c +++ b/drivers/irqchip/irq-vic.c | |||
@@ -219,7 +219,7 @@ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs) | |||
219 | 219 | ||
220 | while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) { | 220 | while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) { |
221 | irq = ffs(stat) - 1; | 221 | irq = ffs(stat) - 1; |
222 | handle_IRQ(irq_find_mapping(vic->domain, irq), regs); | 222 | handle_domain_irq(vic->domain, irq, regs); |
223 | handled = 1; | 223 | handled = 1; |
224 | } | 224 | } |
225 | 225 | ||
diff --git a/drivers/irqchip/irq-vt8500.c b/drivers/irqchip/irq-vt8500.c index eb6e91efdec8..b7af816f2769 100644 --- a/drivers/irqchip/irq-vt8500.c +++ b/drivers/irqchip/irq-vt8500.c | |||
@@ -181,7 +181,7 @@ static struct irq_domain_ops vt8500_irq_domain_ops = { | |||
181 | static void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs) | 181 | static void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs) |
182 | { | 182 | { |
183 | u32 stat, i; | 183 | u32 stat, i; |
184 | int irqnr, virq; | 184 | int irqnr; |
185 | void __iomem *base; | 185 | void __iomem *base; |
186 | 186 | ||
187 | /* Loop through each active controller */ | 187 | /* Loop through each active controller */ |
@@ -198,8 +198,7 @@ static void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs) | |||
198 | continue; | 198 | continue; |
199 | } | 199 | } |
200 | 200 | ||
201 | virq = irq_find_mapping(intc[i].domain, irqnr); | 201 | handle_domain_irq(intc[i].domain, irqnr, regs); |
202 | handle_IRQ(virq, regs); | ||
203 | } | 202 | } |
204 | } | 203 | } |
205 | 204 | ||
diff --git a/drivers/irqchip/irq-zevio.c b/drivers/irqchip/irq-zevio.c index ceb3a4318f73..e4ef74ed454a 100644 --- a/drivers/irqchip/irq-zevio.c +++ b/drivers/irqchip/irq-zevio.c | |||
@@ -56,8 +56,7 @@ static void __exception_irq_entry zevio_handle_irq(struct pt_regs *regs) | |||
56 | 56 | ||
57 | while (readl(zevio_irq_io + IO_STATUS)) { | 57 | while (readl(zevio_irq_io + IO_STATUS)) { |
58 | irqnr = readl(zevio_irq_io + IO_CURRENT); | 58 | irqnr = readl(zevio_irq_io + IO_CURRENT); |
59 | irqnr = irq_find_mapping(zevio_irq_domain, irqnr); | 59 | handle_domain_irq(zevio_irq_domain, irqnr, regs); |
60 | handle_IRQ(irqnr, regs); | ||
61 | }; | 60 | }; |
62 | } | 61 | } |
63 | 62 | ||
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index 472c021a2d4f..ff24667cd86c 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h | |||
@@ -12,6 +12,8 @@ struct irq_affinity_notify; | |||
12 | struct proc_dir_entry; | 12 | struct proc_dir_entry; |
13 | struct module; | 13 | struct module; |
14 | struct irq_desc; | 14 | struct irq_desc; |
15 | struct irq_domain; | ||
16 | struct pt_regs; | ||
15 | 17 | ||
16 | /** | 18 | /** |
17 | * struct irq_desc - interrupt descriptor | 19 | * struct irq_desc - interrupt descriptor |
@@ -118,6 +120,23 @@ static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *de | |||
118 | 120 | ||
119 | int generic_handle_irq(unsigned int irq); | 121 | int generic_handle_irq(unsigned int irq); |
120 | 122 | ||
123 | #ifdef CONFIG_HANDLE_DOMAIN_IRQ | ||
124 | /* | ||
125 | * Convert a HW interrupt number to a logical one using a IRQ domain, | ||
126 | * and handle the result interrupt number. Return -EINVAL if | ||
127 | * conversion failed. Providing a NULL domain indicates that the | ||
128 | * conversion has already been done. | ||
129 | */ | ||
130 | int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq, | ||
131 | bool lookup, struct pt_regs *regs); | ||
132 | |||
133 | static inline int handle_domain_irq(struct irq_domain *domain, | ||
134 | unsigned int hwirq, struct pt_regs *regs) | ||
135 | { | ||
136 | return __handle_domain_irq(domain, hwirq, true, regs); | ||
137 | } | ||
138 | #endif | ||
139 | |||
121 | /* Test to see if a driver has successfully requested an irq */ | 140 | /* Test to see if a driver has successfully requested an irq */ |
122 | static inline int irq_has_action(unsigned int irq) | 141 | static inline int irq_has_action(unsigned int irq) |
123 | { | 142 | { |
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig index d269cecdfbf0..225086b2652e 100644 --- a/kernel/irq/Kconfig +++ b/kernel/irq/Kconfig | |||
@@ -55,6 +55,9 @@ config GENERIC_IRQ_CHIP | |||
55 | config IRQ_DOMAIN | 55 | config IRQ_DOMAIN |
56 | bool | 56 | bool |
57 | 57 | ||
58 | config HANDLE_DOMAIN_IRQ | ||
59 | bool | ||
60 | |||
58 | config IRQ_DOMAIN_DEBUG | 61 | config IRQ_DOMAIN_DEBUG |
59 | bool "Expose hardware/virtual IRQ mapping via debugfs" | 62 | bool "Expose hardware/virtual IRQ mapping via debugfs" |
60 | depends on IRQ_DOMAIN && DEBUG_FS | 63 | depends on IRQ_DOMAIN && DEBUG_FS |
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 1487a123db5c..a1782f88f0af 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/kernel_stat.h> | 14 | #include <linux/kernel_stat.h> |
15 | #include <linux/radix-tree.h> | 15 | #include <linux/radix-tree.h> |
16 | #include <linux/bitmap.h> | 16 | #include <linux/bitmap.h> |
17 | #include <linux/irqdomain.h> | ||
17 | 18 | ||
18 | #include "internals.h" | 19 | #include "internals.h" |
19 | 20 | ||
@@ -336,6 +337,47 @@ int generic_handle_irq(unsigned int irq) | |||
336 | } | 337 | } |
337 | EXPORT_SYMBOL_GPL(generic_handle_irq); | 338 | EXPORT_SYMBOL_GPL(generic_handle_irq); |
338 | 339 | ||
340 | #ifdef CONFIG_HANDLE_DOMAIN_IRQ | ||
341 | /** | ||
342 | * __handle_domain_irq - Invoke the handler for a HW irq belonging to a domain | ||
343 | * @domain: The domain where to perform the lookup | ||
344 | * @hwirq: The HW irq number to convert to a logical one | ||
345 | * @lookup: Whether to perform the domain lookup or not | ||
346 | * @regs: Register file coming from the low-level handling code | ||
347 | * | ||
348 | * Returns: 0 on success, or -EINVAL if conversion has failed | ||
349 | */ | ||
350 | int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq, | ||
351 | bool lookup, struct pt_regs *regs) | ||
352 | { | ||
353 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
354 | unsigned int irq = hwirq; | ||
355 | int ret = 0; | ||
356 | |||
357 | irq_enter(); | ||
358 | |||
359 | #ifdef CONFIG_IRQ_DOMAIN | ||
360 | if (lookup) | ||
361 | irq = irq_find_mapping(domain, hwirq); | ||
362 | #endif | ||
363 | |||
364 | /* | ||
365 | * Some hardware gives randomly wrong interrupts. Rather | ||
366 | * than crashing, do something sensible. | ||
367 | */ | ||
368 | if (unlikely(!irq || irq >= nr_irqs)) { | ||
369 | ack_bad_irq(irq); | ||
370 | ret = -EINVAL; | ||
371 | } else { | ||
372 | generic_handle_irq(irq); | ||
373 | } | ||
374 | |||
375 | irq_exit(); | ||
376 | set_irq_regs(old_regs); | ||
377 | return ret; | ||
378 | } | ||
379 | #endif | ||
380 | |||
339 | /* Dynamic interrupt handling */ | 381 | /* Dynamic interrupt handling */ |
340 | 382 | ||
341 | /** | 383 | /** |