diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-01 14:22:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-01 14:22:57 -0400 |
commit | 683b6c6f82a60fabf47012581c2cfbf1b037ab95 (patch) | |
tree | 6a3fdf26b98aebf4b0b9eca8d242ba89e0565d8b | |
parent | 1ead65812486cda65093683a99b8907a7242fa93 (diff) | |
parent | 1b422ecd27866985b9f35d0d2b5ae6e9122dd4c0 (diff) |
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq code updates from Thomas Gleixner:
"The irq department proudly presents:
- Another tree wide sweep of irq infrastructure abuse. Clear winner
of the trainwreck engineering contest was:
#include "../../../kernel/irq/settings.h"
- Tree wide update of irq_set_affinity() callbacks which miss a cpu
online check when picking a single cpu out of the affinity mask.
- Tree wide consolidation of interrupt statistics.
- Updates to the threaded interrupt infrastructure to allow explicit
wakeup of the interrupt thread and a variant of synchronize_irq()
which synchronizes only the hard interrupt handler. Both are
needed to replace the homebrewn thread handling in the mmc/sdhci
code.
- New irq chip callbacks to allow proper support for GPIO based irqs.
The GPIO based interrupts need to request/release GPIO resources
from request/free_irq.
- A few new ARM interrupt chips. No revolutionary new hardware, just
differently wreckaged variations of the scheme.
- Small improvments, cleanups and updates all over the place"
I was hoping that that trainwreck engineering contest was a April Fools'
joke. But no.
* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (68 commits)
irqchip: sun7i/sun6i: Disable NMI before registering the handler
ARM: sun7i/sun6i: dts: Fix IRQ number for sun6i NMI controller
ARM: sun7i/sun6i: irqchip: Update the documentation
ARM: sun7i/sun6i: dts: Add NMI irqchip support
ARM: sun7i/sun6i: irqchip: Add irqchip driver for NMI controller
genirq: Export symbol no_action()
arm: omap: Fix typo in ams-delta-fiq.c
m68k: atari: Fix the last kernel_stat.h fallout
irqchip: sun4i: Simplify sun4i_irq_ack
irqchip: sun4i: Use handle_fasteoi_irq for all interrupts
genirq: procfs: Make smp_affinity values go+r
softirq: Add linux/irq.h to make it compile again
m68k: amiga: Add linux/irq.h to make it compile again
irqchip: sun4i: Don't ack IRQs > 0, fix acking of IRQ 0
irqchip: sun4i: Fix a comment about mask register initialization
irqchip: sun4i: Fix irq 0 not working
genirq: Add a new IRQCHIP_EOI_THREADED flag
genirq: Document IRQCHIP_ONESHOT_SAFE flag
ARM: sunxi: dt: Convert to the new irq controller compatibles
irqchip: sunxi: Change compatibles
...
82 files changed, 705 insertions, 393 deletions
diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt index d74091a8a3bf..5fc03134a999 100644 --- a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt +++ b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt | |||
@@ -1,4 +1,4 @@ | |||
1 | Marvell Armada 370 and Armada XP Interrupt Controller | 1 | Marvell Armada 370, 375, 38x, XP Interrupt Controller |
2 | ----------------------------------------------------- | 2 | ----------------------------------------------------- |
3 | 3 | ||
4 | Required properties: | 4 | Required properties: |
@@ -16,7 +16,13 @@ Required properties: | |||
16 | automatically map to the interrupt controller registers of the | 16 | automatically map to the interrupt controller registers of the |
17 | current CPU) | 17 | current CPU) |
18 | 18 | ||
19 | Optional properties: | ||
19 | 20 | ||
21 | - interrupts: If defined, then it indicates that this MPIC is | ||
22 | connected as a slave to another interrupt controller. This is | ||
23 | typically the case on Armada 375 and Armada 38x, where the MPIC is | ||
24 | connected as a slave to the Cortex-A9 GIC. The provided interrupt | ||
25 | indicate to which GIC interrupt the MPIC output is connected. | ||
20 | 26 | ||
21 | Example: | 27 | Example: |
22 | 28 | ||
diff --git a/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun4i-ic.txt b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun4i-ic.txt index 32cec4b26cd0..b290ca150d30 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun4i-ic.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun4i-ic.txt | |||
@@ -2,7 +2,7 @@ Allwinner Sunxi Interrupt Controller | |||
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | 4 | ||
5 | - compatible : should be "allwinner,sun4i-ic" | 5 | - compatible : should be "allwinner,sun4i-a10-ic" |
6 | - reg : Specifies base physical address and size of the registers. | 6 | - reg : Specifies base physical address and size of the registers. |
7 | - interrupt-controller : Identifies the node as an interrupt controller | 7 | - interrupt-controller : Identifies the node as an interrupt controller |
8 | - #interrupt-cells : Specifies the number of cells needed to encode an | 8 | - #interrupt-cells : Specifies the number of cells needed to encode an |
@@ -11,7 +11,7 @@ Required properties: | |||
11 | Example: | 11 | Example: |
12 | 12 | ||
13 | intc: interrupt-controller { | 13 | intc: interrupt-controller { |
14 | compatible = "allwinner,sun4i-ic"; | 14 | compatible = "allwinner,sun4i-a10-ic"; |
15 | reg = <0x01c20400 0x400>; | 15 | reg = <0x01c20400 0x400>; |
16 | interrupt-controller; | 16 | interrupt-controller; |
17 | #interrupt-cells = <1>; | 17 | #interrupt-cells = <1>; |
diff --git a/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun67i-sc-nmi.txt b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun67i-sc-nmi.txt new file mode 100644 index 000000000000..d1c5cdabc3e0 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun67i-sc-nmi.txt | |||
@@ -0,0 +1,27 @@ | |||
1 | Allwinner Sunxi NMI Controller | ||
2 | ============================== | ||
3 | |||
4 | Required properties: | ||
5 | |||
6 | - compatible : should be "allwinner,sun7i-a20-sc-nmi" or | ||
7 | "allwinner,sun6i-a31-sc-nmi" | ||
8 | - reg : Specifies base physical address and size of the registers. | ||
9 | - interrupt-controller : Identifies the node as an interrupt controller | ||
10 | - #interrupt-cells : Specifies the number of cells needed to encode an | ||
11 | interrupt source. The value shall be 2. The first cell is the IRQ number, the | ||
12 | second cell the trigger type as defined in interrupt.txt in this directory. | ||
13 | - interrupt-parent: Specifies the parent interrupt controller. | ||
14 | - interrupts: Specifies the interrupt line (NMI) which is handled by | ||
15 | the interrupt controller in the parent controller's notation. This value | ||
16 | shall be the NMI. | ||
17 | |||
18 | Example: | ||
19 | |||
20 | sc-nmi-intc@01c00030 { | ||
21 | compatible = "allwinner,sun7i-a20-sc-nmi"; | ||
22 | interrupt-controller; | ||
23 | #interrupt-cells = <2>; | ||
24 | reg = <0x01c00030 0x0c>; | ||
25 | interrupt-parent = <&gic>; | ||
26 | interrupts = <0 0 4>; | ||
27 | }; | ||
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi index 2ce61228d5f9..249b6e0ba737 100644 --- a/arch/arm/boot/dts/sun4i-a10.dtsi +++ b/arch/arm/boot/dts/sun4i-a10.dtsi | |||
@@ -331,7 +331,7 @@ | |||
331 | }; | 331 | }; |
332 | 332 | ||
333 | intc: interrupt-controller@01c20400 { | 333 | intc: interrupt-controller@01c20400 { |
334 | compatible = "allwinner,sun4i-ic"; | 334 | compatible = "allwinner,sun4i-a10-ic"; |
335 | reg = <0x01c20400 0x400>; | 335 | reg = <0x01c20400 0x400>; |
336 | interrupt-controller; | 336 | interrupt-controller; |
337 | #interrupt-cells = <1>; | 337 | #interrupt-cells = <1>; |
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi index 29dd32d8e77e..ddb25452d78e 100644 --- a/arch/arm/boot/dts/sun5i-a10s.dtsi +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi | |||
@@ -294,7 +294,7 @@ | |||
294 | }; | 294 | }; |
295 | 295 | ||
296 | intc: interrupt-controller@01c20400 { | 296 | intc: interrupt-controller@01c20400 { |
297 | compatible = "allwinner,sun4i-ic"; | 297 | compatible = "allwinner,sun4i-a10-ic"; |
298 | reg = <0x01c20400 0x400>; | 298 | reg = <0x01c20400 0x400>; |
299 | interrupt-controller; | 299 | interrupt-controller; |
300 | #interrupt-cells = <1>; | 300 | #interrupt-cells = <1>; |
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi index e63bb383b43d..b373c74a9b3d 100644 --- a/arch/arm/boot/dts/sun5i-a13.dtsi +++ b/arch/arm/boot/dts/sun5i-a13.dtsi | |||
@@ -275,7 +275,7 @@ | |||
275 | ranges; | 275 | ranges; |
276 | 276 | ||
277 | intc: interrupt-controller@01c20400 { | 277 | intc: interrupt-controller@01c20400 { |
278 | compatible = "allwinner,sun4i-ic"; | 278 | compatible = "allwinner,sun4i-a10-ic"; |
279 | reg = <0x01c20400 0x400>; | 279 | reg = <0x01c20400 0x400>; |
280 | interrupt-controller; | 280 | interrupt-controller; |
281 | #interrupt-cells = <1>; | 281 | #interrupt-cells = <1>; |
diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index 996fff54c8a2..38d43febda4c 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi | |||
@@ -190,6 +190,14 @@ | |||
190 | #size-cells = <1>; | 190 | #size-cells = <1>; |
191 | ranges; | 191 | ranges; |
192 | 192 | ||
193 | nmi_intc: interrupt-controller@01f00c0c { | ||
194 | compatible = "allwinner,sun6i-a31-sc-nmi"; | ||
195 | interrupt-controller; | ||
196 | #interrupt-cells = <2>; | ||
197 | reg = <0x01f00c0c 0x38>; | ||
198 | interrupts = <0 32 4>; | ||
199 | }; | ||
200 | |||
193 | pio: pinctrl@01c20800 { | 201 | pio: pinctrl@01c20800 { |
194 | compatible = "allwinner,sun6i-a31-pinctrl"; | 202 | compatible = "allwinner,sun6i-a31-pinctrl"; |
195 | reg = <0x01c20800 0x400>; | 203 | reg = <0x01c20800 0x400>; |
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi index dddc8ac2d522..cadcf2f9881d 100644 --- a/arch/arm/boot/dts/sun7i-a20.dtsi +++ b/arch/arm/boot/dts/sun7i-a20.dtsi | |||
@@ -339,6 +339,14 @@ | |||
339 | #size-cells = <1>; | 339 | #size-cells = <1>; |
340 | ranges; | 340 | ranges; |
341 | 341 | ||
342 | nmi_intc: interrupt-controller@01c00030 { | ||
343 | compatible = "allwinner,sun7i-a20-sc-nmi"; | ||
344 | interrupt-controller; | ||
345 | #interrupt-cells = <2>; | ||
346 | reg = <0x01c00030 0x0c>; | ||
347 | interrupts = <0 0 4>; | ||
348 | }; | ||
349 | |||
342 | emac: ethernet@01c0b000 { | 350 | emac: ethernet@01c0b000 { |
343 | compatible = "allwinner,sun4i-a10-emac"; | 351 | compatible = "allwinner,sun4i-a10-emac"; |
344 | reg = <0x01c0b000 0x1000>; | 352 | reg = <0x01c0b000 0x1000>; |
diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c index 7a9b98589db7..29e3fe6a6669 100644 --- a/arch/arm/mach-imx/pm-imx6q.c +++ b/arch/arm/mach-imx/pm-imx6q.c | |||
@@ -120,7 +120,7 @@ static void imx6q_enable_wb(bool enable) | |||
120 | 120 | ||
121 | int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) | 121 | int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) |
122 | { | 122 | { |
123 | struct irq_desc *iomuxc_irq_desc; | 123 | struct irq_data *iomuxc_irq_data = irq_get_irq_data(32); |
124 | u32 val = readl_relaxed(ccm_base + CLPCR); | 124 | u32 val = readl_relaxed(ccm_base + CLPCR); |
125 | 125 | ||
126 | val &= ~BM_CLPCR_LPM; | 126 | val &= ~BM_CLPCR_LPM; |
@@ -167,10 +167,9 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) | |||
167 | * 3) Software should mask IRQ #32 right after CCM Low-Power mode | 167 | * 3) Software should mask IRQ #32 right after CCM Low-Power mode |
168 | * is set (set bits 0-1 of CCM_CLPCR). | 168 | * is set (set bits 0-1 of CCM_CLPCR). |
169 | */ | 169 | */ |
170 | iomuxc_irq_desc = irq_to_desc(32); | 170 | imx_gpc_irq_unmask(iomuxc_irq_data); |
171 | imx_gpc_irq_unmask(&iomuxc_irq_desc->irq_data); | ||
172 | writel_relaxed(val, ccm_base + CLPCR); | 171 | writel_relaxed(val, ccm_base + CLPCR); |
173 | imx_gpc_irq_mask(&iomuxc_irq_desc->irq_data); | 172 | imx_gpc_irq_mask(iomuxc_irq_data); |
174 | 173 | ||
175 | return 0; | 174 | return 0; |
176 | } | 175 | } |
diff --git a/arch/arm/mach-mmp/pm-mmp2.c b/arch/arm/mach-mmp/pm-mmp2.c index 461a191a32d2..43b1a516957f 100644 --- a/arch/arm/mach-mmp/pm-mmp2.c +++ b/arch/arm/mach-mmp/pm-mmp2.c | |||
@@ -27,22 +27,8 @@ | |||
27 | 27 | ||
28 | int mmp2_set_wake(struct irq_data *d, unsigned int on) | 28 | int mmp2_set_wake(struct irq_data *d, unsigned int on) |
29 | { | 29 | { |
30 | int irq = d->irq; | ||
31 | struct irq_desc *desc = irq_to_desc(irq); | ||
32 | unsigned long data = 0; | 30 | unsigned long data = 0; |
33 | 31 | int irq = d->irq; | |
34 | if (unlikely(irq >= nr_irqs)) { | ||
35 | pr_err("IRQ nubmers are out of boundary!\n"); | ||
36 | return -EINVAL; | ||
37 | } | ||
38 | |||
39 | if (on) { | ||
40 | if (desc->action) | ||
41 | desc->action->flags |= IRQF_NO_SUSPEND; | ||
42 | } else { | ||
43 | if (desc->action) | ||
44 | desc->action->flags &= ~IRQF_NO_SUSPEND; | ||
45 | } | ||
46 | 32 | ||
47 | /* enable wakeup sources */ | 33 | /* enable wakeup sources */ |
48 | switch (irq) { | 34 | switch (irq) { |
diff --git a/arch/arm/mach-mmp/pm-pxa910.c b/arch/arm/mach-mmp/pm-pxa910.c index 48981ca801a5..04c9daf9f8d7 100644 --- a/arch/arm/mach-mmp/pm-pxa910.c +++ b/arch/arm/mach-mmp/pm-pxa910.c | |||
@@ -27,22 +27,8 @@ | |||
27 | 27 | ||
28 | int pxa910_set_wake(struct irq_data *data, unsigned int on) | 28 | int pxa910_set_wake(struct irq_data *data, unsigned int on) |
29 | { | 29 | { |
30 | int irq = data->irq; | ||
31 | struct irq_desc *desc = irq_to_desc(data->irq); | ||
32 | uint32_t awucrm = 0, apcr = 0; | 30 | uint32_t awucrm = 0, apcr = 0; |
33 | 31 | int irq = data->irq; | |
34 | if (unlikely(irq >= nr_irqs)) { | ||
35 | pr_err("IRQ nubmers are out of boundary!\n"); | ||
36 | return -EINVAL; | ||
37 | } | ||
38 | |||
39 | if (on) { | ||
40 | if (desc->action) | ||
41 | desc->action->flags |= IRQF_NO_SUSPEND; | ||
42 | } else { | ||
43 | if (desc->action) | ||
44 | desc->action->flags &= ~IRQF_NO_SUSPEND; | ||
45 | } | ||
46 | 32 | ||
47 | /* setting wakeup sources */ | 33 | /* setting wakeup sources */ |
48 | switch (irq) { | 34 | switch (irq) { |
@@ -115,9 +101,11 @@ int pxa910_set_wake(struct irq_data *data, unsigned int on) | |||
115 | if (irq >= IRQ_GPIO_START && irq < IRQ_BOARD_START) { | 101 | if (irq >= IRQ_GPIO_START && irq < IRQ_BOARD_START) { |
116 | awucrm = MPMU_AWUCRM_WAKEUP(2); | 102 | awucrm = MPMU_AWUCRM_WAKEUP(2); |
117 | apcr |= MPMU_APCR_SLPWP2; | 103 | apcr |= MPMU_APCR_SLPWP2; |
118 | } else | 104 | } else { |
105 | /* FIXME: This should return a proper error code ! */ | ||
119 | printk(KERN_ERR "Error: no defined wake up source irq: %d\n", | 106 | printk(KERN_ERR "Error: no defined wake up source irq: %d\n", |
120 | irq); | 107 | irq); |
108 | } | ||
121 | } | 109 | } |
122 | 110 | ||
123 | if (on) { | 111 | if (on) { |
diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c b/arch/arm/mach-omap1/ams-delta-fiq.c index f12a12af3523..d1f12095f315 100644 --- a/arch/arm/mach-omap1/ams-delta-fiq.c +++ b/arch/arm/mach-omap1/ams-delta-fiq.c | |||
@@ -44,13 +44,10 @@ static unsigned int irq_counter[16]; | |||
44 | 44 | ||
45 | static irqreturn_t deferred_fiq(int irq, void *dev_id) | 45 | static irqreturn_t deferred_fiq(int irq, void *dev_id) |
46 | { | 46 | { |
47 | struct irq_desc *irq_desc; | ||
48 | struct irq_chip *irq_chip = NULL; | ||
49 | int gpio, irq_num, fiq_count; | 47 | int gpio, irq_num, fiq_count; |
48 | struct irq_chip *irq_chip; | ||
50 | 49 | ||
51 | irq_desc = irq_to_desc(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK)); | 50 | irq_chip = irq_get_chip(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK)); |
52 | if (irq_desc) | ||
53 | irq_chip = irq_desc->irq_data.chip; | ||
54 | 51 | ||
55 | /* | 52 | /* |
56 | * For each handled GPIO interrupt, keep calling its interrupt handler | 53 | * For each handled GPIO interrupt, keep calling its interrupt handler |
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 1034884b77da..0884f5ecbcc3 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c | |||
@@ -364,7 +364,6 @@ static irqreturn_t smp_irq_move_cleanup_interrupt(int irq, void *dev_id) | |||
364 | 364 | ||
365 | static struct irqaction irq_move_irqaction = { | 365 | static struct irqaction irq_move_irqaction = { |
366 | .handler = smp_irq_move_cleanup_interrupt, | 366 | .handler = smp_irq_move_cleanup_interrupt, |
367 | .flags = IRQF_DISABLED, | ||
368 | .name = "irq_move" | 367 | .name = "irq_move" |
369 | }; | 368 | }; |
370 | 369 | ||
@@ -489,14 +488,13 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) | |||
489 | ia64_srlz_d(); | 488 | ia64_srlz_d(); |
490 | while (vector != IA64_SPURIOUS_INT_VECTOR) { | 489 | while (vector != IA64_SPURIOUS_INT_VECTOR) { |
491 | int irq = local_vector_to_irq(vector); | 490 | int irq = local_vector_to_irq(vector); |
492 | struct irq_desc *desc = irq_to_desc(irq); | ||
493 | 491 | ||
494 | if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) { | 492 | if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) { |
495 | smp_local_flush_tlb(); | 493 | smp_local_flush_tlb(); |
496 | kstat_incr_irqs_this_cpu(irq, desc); | 494 | kstat_incr_irq_this_cpu(irq); |
497 | } else if (unlikely(IS_RESCHEDULE(vector))) { | 495 | } else if (unlikely(IS_RESCHEDULE(vector))) { |
498 | scheduler_ipi(); | 496 | scheduler_ipi(); |
499 | kstat_incr_irqs_this_cpu(irq, desc); | 497 | kstat_incr_irq_this_cpu(irq); |
500 | } else { | 498 | } else { |
501 | ia64_setreg(_IA64_REG_CR_TPR, vector); | 499 | ia64_setreg(_IA64_REG_CR_TPR, vector); |
502 | ia64_srlz_d(); | 500 | ia64_srlz_d(); |
@@ -549,13 +547,12 @@ void ia64_process_pending_intr(void) | |||
549 | */ | 547 | */ |
550 | while (vector != IA64_SPURIOUS_INT_VECTOR) { | 548 | while (vector != IA64_SPURIOUS_INT_VECTOR) { |
551 | int irq = local_vector_to_irq(vector); | 549 | int irq = local_vector_to_irq(vector); |
552 | struct irq_desc *desc = irq_to_desc(irq); | ||
553 | 550 | ||
554 | if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) { | 551 | if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) { |
555 | smp_local_flush_tlb(); | 552 | smp_local_flush_tlb(); |
556 | kstat_incr_irqs_this_cpu(irq, desc); | 553 | kstat_incr_irq_this_cpu(irq); |
557 | } else if (unlikely(IS_RESCHEDULE(vector))) { | 554 | } else if (unlikely(IS_RESCHEDULE(vector))) { |
558 | kstat_incr_irqs_this_cpu(irq, desc); | 555 | kstat_incr_irq_this_cpu(irq); |
559 | } else { | 556 | } else { |
560 | struct pt_regs *old_regs = set_irq_regs(NULL); | 557 | struct pt_regs *old_regs = set_irq_regs(NULL); |
561 | 558 | ||
@@ -602,7 +599,6 @@ static irqreturn_t dummy_handler (int irq, void *dev_id) | |||
602 | 599 | ||
603 | static struct irqaction ipi_irqaction = { | 600 | static struct irqaction ipi_irqaction = { |
604 | .handler = handle_IPI, | 601 | .handler = handle_IPI, |
605 | .flags = IRQF_DISABLED, | ||
606 | .name = "IPI" | 602 | .name = "IPI" |
607 | }; | 603 | }; |
608 | 604 | ||
@@ -611,13 +607,11 @@ static struct irqaction ipi_irqaction = { | |||
611 | */ | 607 | */ |
612 | static struct irqaction resched_irqaction = { | 608 | static struct irqaction resched_irqaction = { |
613 | .handler = dummy_handler, | 609 | .handler = dummy_handler, |
614 | .flags = IRQF_DISABLED, | ||
615 | .name = "resched" | 610 | .name = "resched" |
616 | }; | 611 | }; |
617 | 612 | ||
618 | static struct irqaction tlb_irqaction = { | 613 | static struct irqaction tlb_irqaction = { |
619 | .handler = dummy_handler, | 614 | .handler = dummy_handler, |
620 | .flags = IRQF_DISABLED, | ||
621 | .name = "tlb_flush" | 615 | .name = "tlb_flush" |
622 | }; | 616 | }; |
623 | 617 | ||
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 601502ab7141..db7b36bb068b 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c | |||
@@ -1772,38 +1772,32 @@ __setup("disable_cpe_poll", ia64_mca_disable_cpe_polling); | |||
1772 | 1772 | ||
1773 | static struct irqaction cmci_irqaction = { | 1773 | static struct irqaction cmci_irqaction = { |
1774 | .handler = ia64_mca_cmc_int_handler, | 1774 | .handler = ia64_mca_cmc_int_handler, |
1775 | .flags = IRQF_DISABLED, | ||
1776 | .name = "cmc_hndlr" | 1775 | .name = "cmc_hndlr" |
1777 | }; | 1776 | }; |
1778 | 1777 | ||
1779 | static struct irqaction cmcp_irqaction = { | 1778 | static struct irqaction cmcp_irqaction = { |
1780 | .handler = ia64_mca_cmc_int_caller, | 1779 | .handler = ia64_mca_cmc_int_caller, |
1781 | .flags = IRQF_DISABLED, | ||
1782 | .name = "cmc_poll" | 1780 | .name = "cmc_poll" |
1783 | }; | 1781 | }; |
1784 | 1782 | ||
1785 | static struct irqaction mca_rdzv_irqaction = { | 1783 | static struct irqaction mca_rdzv_irqaction = { |
1786 | .handler = ia64_mca_rendez_int_handler, | 1784 | .handler = ia64_mca_rendez_int_handler, |
1787 | .flags = IRQF_DISABLED, | ||
1788 | .name = "mca_rdzv" | 1785 | .name = "mca_rdzv" |
1789 | }; | 1786 | }; |
1790 | 1787 | ||
1791 | static struct irqaction mca_wkup_irqaction = { | 1788 | static struct irqaction mca_wkup_irqaction = { |
1792 | .handler = ia64_mca_wakeup_int_handler, | 1789 | .handler = ia64_mca_wakeup_int_handler, |
1793 | .flags = IRQF_DISABLED, | ||
1794 | .name = "mca_wkup" | 1790 | .name = "mca_wkup" |
1795 | }; | 1791 | }; |
1796 | 1792 | ||
1797 | #ifdef CONFIG_ACPI | 1793 | #ifdef CONFIG_ACPI |
1798 | static struct irqaction mca_cpe_irqaction = { | 1794 | static struct irqaction mca_cpe_irqaction = { |
1799 | .handler = ia64_mca_cpe_int_handler, | 1795 | .handler = ia64_mca_cpe_int_handler, |
1800 | .flags = IRQF_DISABLED, | ||
1801 | .name = "cpe_hndlr" | 1796 | .name = "cpe_hndlr" |
1802 | }; | 1797 | }; |
1803 | 1798 | ||
1804 | static struct irqaction mca_cpep_irqaction = { | 1799 | static struct irqaction mca_cpep_irqaction = { |
1805 | .handler = ia64_mca_cpe_int_caller, | 1800 | .handler = ia64_mca_cpe_int_caller, |
1806 | .flags = IRQF_DISABLED, | ||
1807 | .name = "cpe_poll" | 1801 | .name = "cpe_poll" |
1808 | }; | 1802 | }; |
1809 | #endif /* CONFIG_ACPI */ | 1803 | #endif /* CONFIG_ACPI */ |
diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c index fb2f1e622877..c430f9198d1b 100644 --- a/arch/ia64/kernel/msi_ia64.c +++ b/arch/ia64/kernel/msi_ia64.c | |||
@@ -17,12 +17,9 @@ static int ia64_set_msi_irq_affinity(struct irq_data *idata, | |||
17 | { | 17 | { |
18 | struct msi_msg msg; | 18 | struct msi_msg msg; |
19 | u32 addr, data; | 19 | u32 addr, data; |
20 | int cpu = first_cpu(*cpu_mask); | 20 | int cpu = cpumask_first_and(cpu_mask, cpu_online_mask); |
21 | unsigned int irq = idata->irq; | 21 | unsigned int irq = idata->irq; |
22 | 22 | ||
23 | if (!cpu_online(cpu)) | ||
24 | return -1; | ||
25 | |||
26 | if (irq_prepare_move(irq, cpu)) | 23 | if (irq_prepare_move(irq, cpu)) |
27 | return -1; | 24 | return -1; |
28 | 25 | ||
@@ -139,10 +136,7 @@ static int dmar_msi_set_affinity(struct irq_data *data, | |||
139 | unsigned int irq = data->irq; | 136 | unsigned int irq = data->irq; |
140 | struct irq_cfg *cfg = irq_cfg + irq; | 137 | struct irq_cfg *cfg = irq_cfg + irq; |
141 | struct msi_msg msg; | 138 | struct msi_msg msg; |
142 | int cpu = cpumask_first(mask); | 139 | int cpu = cpumask_first_and(mask, cpu_online_mask); |
143 | |||
144 | if (!cpu_online(cpu)) | ||
145 | return -1; | ||
146 | 140 | ||
147 | if (irq_prepare_move(irq, cpu)) | 141 | if (irq_prepare_move(irq, cpu)) |
148 | return -1; | 142 | return -1; |
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index cb592773c78b..d841c4bd6864 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c | |||
@@ -6387,7 +6387,6 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx) | |||
6387 | 6387 | ||
6388 | static struct irqaction perfmon_irqaction = { | 6388 | static struct irqaction perfmon_irqaction = { |
6389 | .handler = pfm_interrupt_handler, | 6389 | .handler = pfm_interrupt_handler, |
6390 | .flags = IRQF_DISABLED, | ||
6391 | .name = "perfmon" | 6390 | .name = "perfmon" |
6392 | }; | 6391 | }; |
6393 | 6392 | ||
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index fbaac1afb844..71c52bc7c28d 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c | |||
@@ -380,7 +380,7 @@ static cycle_t itc_get_cycles(struct clocksource *cs) | |||
380 | 380 | ||
381 | static struct irqaction timer_irqaction = { | 381 | static struct irqaction timer_irqaction = { |
382 | .handler = timer_interrupt, | 382 | .handler = timer_interrupt, |
383 | .flags = IRQF_DISABLED | IRQF_IRQPOLL, | 383 | .flags = IRQF_IRQPOLL, |
384 | .name = "timer" | 384 | .name = "timer" |
385 | }; | 385 | }; |
386 | 386 | ||
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index 62cf4dde6a04..85d095154902 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c | |||
@@ -209,8 +209,8 @@ static int sn_set_affinity_irq(struct irq_data *data, | |||
209 | nasid_t nasid; | 209 | nasid_t nasid; |
210 | int slice; | 210 | int slice; |
211 | 211 | ||
212 | nasid = cpuid_to_nasid(cpumask_first(mask)); | 212 | nasid = cpuid_to_nasid(cpumask_first_and(mask, cpu_online_mask)); |
213 | slice = cpuid_to_slice(cpumask_first(mask)); | 213 | slice = cpuid_to_slice(cpumask_first_and(mask, cpu_online_mask)); |
214 | 214 | ||
215 | list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe, | 215 | list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe, |
216 | sn_irq_lh[irq], list) | 216 | sn_irq_lh[irq], list) |
diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c index 2b98b9e088de..afc58d2799ad 100644 --- a/arch/ia64/sn/kernel/msi_sn.c +++ b/arch/ia64/sn/kernel/msi_sn.c | |||
@@ -166,7 +166,7 @@ static int sn_set_msi_irq_affinity(struct irq_data *data, | |||
166 | struct sn_pcibus_provider *provider; | 166 | struct sn_pcibus_provider *provider; |
167 | unsigned int cpu, irq = data->irq; | 167 | unsigned int cpu, irq = data->irq; |
168 | 168 | ||
169 | cpu = cpumask_first(cpu_mask); | 169 | cpu = cpumask_first_and(cpu_mask, cpu_online_mask); |
170 | sn_irq_info = sn_msi_info[irq].sn_irq_info; | 170 | sn_irq_info = sn_msi_info[irq].sn_irq_info; |
171 | if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0) | 171 | if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0) |
172 | return -1; | 172 | return -1; |
diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c index 18c0e29976e3..2081b8cd5591 100644 --- a/arch/m68k/amiga/cia.c +++ b/arch/m68k/amiga/cia.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/seq_file.h> | 19 | #include <linux/seq_file.h> |
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/irq.h> | ||
21 | 22 | ||
22 | #include <asm/irq.h> | 23 | #include <asm/irq.h> |
23 | #include <asm/amigahw.h> | 24 | #include <asm/amigahw.h> |
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c index 3e73a63c066f..3d2b63bedf05 100644 --- a/arch/m68k/atari/ataints.c +++ b/arch/m68k/atari/ataints.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/init.h> | 41 | #include <linux/init.h> |
42 | #include <linux/seq_file.h> | 42 | #include <linux/seq_file.h> |
43 | #include <linux/module.h> | 43 | #include <linux/module.h> |
44 | #include <linux/irq.h> | ||
44 | 45 | ||
45 | #include <asm/traps.h> | 46 | #include <asm/traps.h> |
46 | 47 | ||
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index 077d3a70fed1..5b8d66fbf383 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c | |||
@@ -10,9 +10,9 @@ | |||
10 | #include <linux/types.h> | 10 | #include <linux/types.h> |
11 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
13 | #include <linux/kernel_stat.h> | ||
14 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
15 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/irq.h> | ||
16 | 16 | ||
17 | #include <asm/setup.h> | 17 | #include <asm/setup.h> |
18 | #include <asm/irq.h> | 18 | #include <asm/irq.h> |
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index dfc1b911be04..c1681d65dd5c 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c | |||
@@ -1007,7 +1007,7 @@ static void __irq_entry smtc_clock_tick_interrupt(void) | |||
1007 | int irq = MIPS_CPU_IRQ_BASE + 1; | 1007 | int irq = MIPS_CPU_IRQ_BASE + 1; |
1008 | 1008 | ||
1009 | irq_enter(); | 1009 | irq_enter(); |
1010 | kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); | 1010 | kstat_incr_irq_this_cpu(irq); |
1011 | cd = &per_cpu(mips_clockevent_device, cpu); | 1011 | cd = &per_cpu(mips_clockevent_device, cpu); |
1012 | cd->event_handler(cd); | 1012 | cd->event_handler(cd); |
1013 | irq_exit(); | 1013 | irq_exit(); |
diff --git a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c index 3db64d51798d..58b40ae59335 100644 --- a/arch/mips/sgi-ip22/ip22-int.c +++ b/arch/mips/sgi-ip22/ip22-int.c | |||
@@ -148,7 +148,7 @@ static void __irq_entry indy_buserror_irq(void) | |||
148 | int irq = SGI_BUSERR_IRQ; | 148 | int irq = SGI_BUSERR_IRQ; |
149 | 149 | ||
150 | irq_enter(); | 150 | irq_enter(); |
151 | kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); | 151 | kstat_incr_irq_this_cpu(irq); |
152 | ip22_be_interrupt(irq); | 152 | ip22_be_interrupt(irq); |
153 | irq_exit(); | 153 | irq_exit(); |
154 | } | 154 | } |
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c index 607192449335..045aa89f28d8 100644 --- a/arch/mips/sgi-ip22/ip22-time.c +++ b/arch/mips/sgi-ip22/ip22-time.c | |||
@@ -123,7 +123,7 @@ void __irq_entry indy_8254timer_irq(void) | |||
123 | char c; | 123 | char c; |
124 | 124 | ||
125 | irq_enter(); | 125 | irq_enter(); |
126 | kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); | 126 | kstat_incr_irq_this_cpu(irq); |
127 | printk(KERN_ALERT "Oops, got 8254 interrupt.\n"); | 127 | printk(KERN_ALERT "Oops, got 8254 interrupt.\n"); |
128 | ArcRead(0, &c, 1, &cnt); | 128 | ArcRead(0, &c, 1, &cnt); |
129 | ArcEnterInteractiveMode(); | 129 | ArcEnterInteractiveMode(); |
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c index 09d6e16a70f1..59cfe2659771 100644 --- a/arch/mips/sibyte/bcm1480/irq.c +++ b/arch/mips/sibyte/bcm1480/irq.c | |||
@@ -95,7 +95,7 @@ static int bcm1480_set_affinity(struct irq_data *d, const struct cpumask *mask, | |||
95 | u64 cur_ints; | 95 | u64 cur_ints; |
96 | unsigned long flags; | 96 | unsigned long flags; |
97 | 97 | ||
98 | i = cpumask_first(mask); | 98 | i = cpumask_first_and(mask, cpu_online_mask); |
99 | 99 | ||
100 | /* Convert logical CPU to physical CPU */ | 100 | /* Convert logical CPU to physical CPU */ |
101 | cpu = cpu_logical_map(i); | 101 | cpu = cpu_logical_map(i); |
diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c index 54e2c4de15c1..70d9182b26f1 100644 --- a/arch/mips/sibyte/bcm1480/smp.c +++ b/arch/mips/sibyte/bcm1480/smp.c | |||
@@ -182,7 +182,7 @@ void bcm1480_mailbox_interrupt(void) | |||
182 | int irq = K_BCM1480_INT_MBOX_0_0; | 182 | int irq = K_BCM1480_INT_MBOX_0_0; |
183 | unsigned int action; | 183 | unsigned int action; |
184 | 184 | ||
185 | kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); | 185 | kstat_incr_irq_this_cpu(irq); |
186 | /* Load the mailbox register to figure out what we're supposed to do */ | 186 | /* Load the mailbox register to figure out what we're supposed to do */ |
187 | action = (__raw_readq(mailbox_0_regs[cpu]) >> 48) & 0xffff; | 187 | action = (__raw_readq(mailbox_0_regs[cpu]) >> 48) & 0xffff; |
188 | 188 | ||
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c index fca0cdb99509..6d8dba5cf348 100644 --- a/arch/mips/sibyte/sb1250/irq.c +++ b/arch/mips/sibyte/sb1250/irq.c | |||
@@ -88,7 +88,7 @@ static int sb1250_set_affinity(struct irq_data *d, const struct cpumask *mask, | |||
88 | u64 cur_ints; | 88 | u64 cur_ints; |
89 | unsigned long flags; | 89 | unsigned long flags; |
90 | 90 | ||
91 | i = cpumask_first(mask); | 91 | i = cpumask_first_and(mask, cpu_online_mask); |
92 | 92 | ||
93 | /* Convert logical CPU to physical CPU */ | 93 | /* Convert logical CPU to physical CPU */ |
94 | cpu = cpu_logical_map(i); | 94 | cpu = cpu_logical_map(i); |
diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c index d7b942db0ea5..db976117dd4d 100644 --- a/arch/mips/sibyte/sb1250/smp.c +++ b/arch/mips/sibyte/sb1250/smp.c | |||
@@ -170,7 +170,7 @@ void sb1250_mailbox_interrupt(void) | |||
170 | int irq = K_INT_MBOX_0; | 170 | int irq = K_INT_MBOX_0; |
171 | unsigned int action; | 171 | unsigned int action; |
172 | 172 | ||
173 | kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); | 173 | kstat_incr_irq_this_cpu(irq); |
174 | /* Load the mailbox register to figure out what we're supposed to do */ | 174 | /* Load the mailbox register to figure out what we're supposed to do */ |
175 | action = (____raw_readq(mailbox_regs[cpu]) >> 48) & 0xffff; | 175 | action = (____raw_readq(mailbox_regs[cpu]) >> 48) & 0xffff; |
176 | 176 | ||
diff --git a/arch/mn10300/kernel/cevt-mn10300.c b/arch/mn10300/kernel/cevt-mn10300.c index ccce35e3e179..60f64ca1752a 100644 --- a/arch/mn10300/kernel/cevt-mn10300.c +++ b/arch/mn10300/kernel/cevt-mn10300.c | |||
@@ -113,7 +113,7 @@ int __init init_clockevents(void) | |||
113 | cd->set_next_event = next_event; | 113 | cd->set_next_event = next_event; |
114 | 114 | ||
115 | iact = &per_cpu(timer_irq, cpu); | 115 | iact = &per_cpu(timer_irq, cpu); |
116 | iact->flags = IRQF_DISABLED | IRQF_SHARED | IRQF_TIMER; | 116 | iact->flags = IRQF_SHARED | IRQF_TIMER; |
117 | iact->handler = timer_interrupt; | 117 | iact->handler = timer_interrupt; |
118 | 118 | ||
119 | clockevents_register_device(cd); | 119 | clockevents_register_device(cd); |
diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c index bf6e949a2f87..7ecf69879e2d 100644 --- a/arch/mn10300/kernel/mn10300-serial.c +++ b/arch/mn10300/kernel/mn10300-serial.c | |||
@@ -985,17 +985,17 @@ static int mn10300_serial_startup(struct uart_port *_port) | |||
985 | irq_set_chip(port->tm_irq, &mn10300_serial_pic); | 985 | irq_set_chip(port->tm_irq, &mn10300_serial_pic); |
986 | 986 | ||
987 | if (request_irq(port->rx_irq, mn10300_serial_interrupt, | 987 | if (request_irq(port->rx_irq, mn10300_serial_interrupt, |
988 | IRQF_DISABLED | IRQF_NOBALANCING, | 988 | IRQF_NOBALANCING, |
989 | port->rx_name, port) < 0) | 989 | port->rx_name, port) < 0) |
990 | goto error; | 990 | goto error; |
991 | 991 | ||
992 | if (request_irq(port->tx_irq, mn10300_serial_interrupt, | 992 | if (request_irq(port->tx_irq, mn10300_serial_interrupt, |
993 | IRQF_DISABLED | IRQF_NOBALANCING, | 993 | IRQF_NOBALANCING, |
994 | port->tx_name, port) < 0) | 994 | port->tx_name, port) < 0) |
995 | goto error2; | 995 | goto error2; |
996 | 996 | ||
997 | if (request_irq(port->tm_irq, mn10300_serial_interrupt, | 997 | if (request_irq(port->tm_irq, mn10300_serial_interrupt, |
998 | IRQF_DISABLED | IRQF_NOBALANCING, | 998 | IRQF_NOBALANCING, |
999 | port->tm_name, port) < 0) | 999 | port->tm_name, port) < 0) |
1000 | goto error3; | 1000 | goto error3; |
1001 | mn10300_serial_mask_ack(port->tm_irq); | 1001 | mn10300_serial_mask_ack(port->tm_irq); |
diff --git a/arch/mn10300/kernel/mn10300-watchdog.c b/arch/mn10300/kernel/mn10300-watchdog.c index db64a7166c09..a2d8e6938d67 100644 --- a/arch/mn10300/kernel/mn10300-watchdog.c +++ b/arch/mn10300/kernel/mn10300-watchdog.c | |||
@@ -142,7 +142,7 @@ void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep) | |||
142 | NMICR = NMICR_WDIF; | 142 | NMICR = NMICR_WDIF; |
143 | 143 | ||
144 | nmi_count(smp_processor_id())++; | 144 | nmi_count(smp_processor_id())++; |
145 | kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); | 145 | kstat_incr_irq_this_cpu(irq); |
146 | 146 | ||
147 | for_each_online_cpu(cpu) { | 147 | for_each_online_cpu(cpu) { |
148 | 148 | ||
diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c index a17f9c9c14c9..f984193718b1 100644 --- a/arch/mn10300/kernel/smp.c +++ b/arch/mn10300/kernel/smp.c | |||
@@ -143,7 +143,7 @@ static struct irqaction call_function_ipi = { | |||
143 | static irqreturn_t smp_ipi_timer_interrupt(int irq, void *dev_id); | 143 | static irqreturn_t smp_ipi_timer_interrupt(int irq, void *dev_id); |
144 | static struct irqaction local_timer_ipi = { | 144 | static struct irqaction local_timer_ipi = { |
145 | .handler = smp_ipi_timer_interrupt, | 145 | .handler = smp_ipi_timer_interrupt, |
146 | .flags = IRQF_DISABLED | IRQF_NOBALANCING, | 146 | .flags = IRQF_NOBALANCING, |
147 | .name = "smp local timer IPI" | 147 | .name = "smp local timer IPI" |
148 | }; | 148 | }; |
149 | #endif | 149 | #endif |
diff --git a/arch/mn10300/unit-asb2364/irq-fpga.c b/arch/mn10300/unit-asb2364/irq-fpga.c index e16c216f31dc..073e2ccc4a44 100644 --- a/arch/mn10300/unit-asb2364/irq-fpga.c +++ b/arch/mn10300/unit-asb2364/irq-fpga.c | |||
@@ -76,7 +76,7 @@ static irqreturn_t fpga_interrupt(int irq, void *_mask) | |||
76 | static struct irqaction fpga_irq[] = { | 76 | static struct irqaction fpga_irq[] = { |
77 | [0] = { | 77 | [0] = { |
78 | .handler = fpga_interrupt, | 78 | .handler = fpga_interrupt, |
79 | .flags = IRQF_DISABLED | IRQF_SHARED, | 79 | .flags = IRQF_SHARED, |
80 | .name = "fpga", | 80 | .name = "fpga", |
81 | }, | 81 | }, |
82 | }; | 82 | }; |
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index 8ceac4785609..cfe056fe7f5c 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c | |||
@@ -117,7 +117,7 @@ int cpu_check_affinity(struct irq_data *d, const struct cpumask *dest) | |||
117 | return -EINVAL; | 117 | return -EINVAL; |
118 | 118 | ||
119 | /* whatever mask they set, we just allow one CPU */ | 119 | /* whatever mask they set, we just allow one CPU */ |
120 | cpu_dest = first_cpu(*dest); | 120 | cpu_dest = cpumask_first_and(dest, cpu_online_mask); |
121 | 121 | ||
122 | return cpu_dest; | 122 | return cpu_dest; |
123 | } | 123 | } |
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index fdc679d309ec..bb61ca58ca6d 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c | |||
@@ -143,13 +143,30 @@ static void eeh_disable_irq(struct pci_dev *dev) | |||
143 | static void eeh_enable_irq(struct pci_dev *dev) | 143 | static void eeh_enable_irq(struct pci_dev *dev) |
144 | { | 144 | { |
145 | struct eeh_dev *edev = pci_dev_to_eeh_dev(dev); | 145 | struct eeh_dev *edev = pci_dev_to_eeh_dev(dev); |
146 | struct irq_desc *desc; | ||
147 | 146 | ||
148 | if ((edev->mode) & EEH_DEV_IRQ_DISABLED) { | 147 | if ((edev->mode) & EEH_DEV_IRQ_DISABLED) { |
149 | edev->mode &= ~EEH_DEV_IRQ_DISABLED; | 148 | edev->mode &= ~EEH_DEV_IRQ_DISABLED; |
150 | 149 | /* | |
151 | desc = irq_to_desc(dev->irq); | 150 | * FIXME !!!!! |
152 | if (desc && desc->depth > 0) | 151 | * |
152 | * This is just ass backwards. This maze has | ||
153 | * unbalanced irq_enable/disable calls. So instead of | ||
154 | * finding the root cause it works around the warning | ||
155 | * in the irq_enable code by conditionally calling | ||
156 | * into it. | ||
157 | * | ||
158 | * That's just wrong.The warning in the core code is | ||
159 | * there to tell people to fix their assymetries in | ||
160 | * their own code, not by abusing the core information | ||
161 | * to avoid it. | ||
162 | * | ||
163 | * I so wish that the assymetry would be the other way | ||
164 | * round and a few more irq_disable calls render that | ||
165 | * shit unusable forever. | ||
166 | * | ||
167 | * tglx | ||
168 | */ | ||
169 | if (irqd_irq_disabled(irq_get_irq_data(dev->irq))) | ||
153 | enable_irq(dev->irq); | 170 | enable_irq(dev->irq); |
154 | } | 171 | } |
155 | } | 172 | } |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 1d0848bba049..ca1cd7459c4a 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -465,7 +465,6 @@ static inline void check_stack_overflow(void) | |||
465 | 465 | ||
466 | void __do_irq(struct pt_regs *regs) | 466 | void __do_irq(struct pt_regs *regs) |
467 | { | 467 | { |
468 | struct irq_desc *desc; | ||
469 | unsigned int irq; | 468 | unsigned int irq; |
470 | 469 | ||
471 | irq_enter(); | 470 | irq_enter(); |
@@ -487,11 +486,8 @@ void __do_irq(struct pt_regs *regs) | |||
487 | /* And finally process it */ | 486 | /* And finally process it */ |
488 | if (unlikely(irq == NO_IRQ)) | 487 | if (unlikely(irq == NO_IRQ)) |
489 | __get_cpu_var(irq_stat).spurious_irqs++; | 488 | __get_cpu_var(irq_stat).spurious_irqs++; |
490 | else { | 489 | else |
491 | desc = irq_to_desc(irq); | 490 | generic_handle_irq(irq); |
492 | if (likely(desc)) | ||
493 | desc->handle_irq(irq, desc); | ||
494 | } | ||
495 | 491 | ||
496 | trace_irq_exit(regs); | 492 | trace_irq_exit(regs); |
497 | 493 | ||
diff --git a/arch/powerpc/sysdev/ehv_pic.c b/arch/powerpc/sysdev/ehv_pic.c index b74085cea1af..2d20f10a4203 100644 --- a/arch/powerpc/sysdev/ehv_pic.c +++ b/arch/powerpc/sysdev/ehv_pic.c | |||
@@ -28,8 +28,6 @@ | |||
28 | #include <asm/ehv_pic.h> | 28 | #include <asm/ehv_pic.h> |
29 | #include <asm/fsl_hcalls.h> | 29 | #include <asm/fsl_hcalls.h> |
30 | 30 | ||
31 | #include "../../../kernel/irq/settings.h" | ||
32 | |||
33 | static struct ehv_pic *global_ehv_pic; | 31 | static struct ehv_pic *global_ehv_pic; |
34 | static DEFINE_SPINLOCK(ehv_pic_lock); | 32 | static DEFINE_SPINLOCK(ehv_pic_lock); |
35 | 33 | ||
@@ -113,17 +111,13 @@ static unsigned int ehv_pic_type_to_vecpri(unsigned int type) | |||
113 | int ehv_pic_set_irq_type(struct irq_data *d, unsigned int flow_type) | 111 | int ehv_pic_set_irq_type(struct irq_data *d, unsigned int flow_type) |
114 | { | 112 | { |
115 | unsigned int src = virq_to_hw(d->irq); | 113 | unsigned int src = virq_to_hw(d->irq); |
116 | struct irq_desc *desc = irq_to_desc(d->irq); | ||
117 | unsigned int vecpri, vold, vnew, prio, cpu_dest; | 114 | unsigned int vecpri, vold, vnew, prio, cpu_dest; |
118 | unsigned long flags; | 115 | unsigned long flags; |
119 | 116 | ||
120 | if (flow_type == IRQ_TYPE_NONE) | 117 | if (flow_type == IRQ_TYPE_NONE) |
121 | flow_type = IRQ_TYPE_LEVEL_LOW; | 118 | flow_type = IRQ_TYPE_LEVEL_LOW; |
122 | 119 | ||
123 | irq_settings_clr_level(desc); | 120 | irqd_set_trigger_type(d, flow_type); |
124 | irq_settings_set_trigger_mask(desc, flow_type); | ||
125 | if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) | ||
126 | irq_settings_set_level(desc); | ||
127 | 121 | ||
128 | vecpri = ehv_pic_type_to_vecpri(flow_type); | 122 | vecpri = ehv_pic_type_to_vecpri(flow_type); |
129 | 123 | ||
@@ -144,7 +138,7 @@ int ehv_pic_set_irq_type(struct irq_data *d, unsigned int flow_type) | |||
144 | ev_int_set_config(src, vecpri, prio, cpu_dest); | 138 | ev_int_set_config(src, vecpri, prio, cpu_dest); |
145 | 139 | ||
146 | spin_unlock_irqrestore(&ehv_pic_lock, flags); | 140 | spin_unlock_irqrestore(&ehv_pic_lock, flags); |
147 | return 0; | 141 | return IRQ_SET_MASK_OK_NOCOPY; |
148 | } | 142 | } |
149 | 143 | ||
150 | static struct irq_chip ehv_pic_irq_chip = { | 144 | static struct irq_chip ehv_pic_irq_chip = { |
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index bb27a262c44a..a770be97db4d 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/cpu.h> | 20 | #include <linux/cpu.h> |
21 | #include <linux/irq.h> | ||
21 | #include <asm/irq_regs.h> | 22 | #include <asm/irq_regs.h> |
22 | #include <asm/cputime.h> | 23 | #include <asm/cputime.h> |
23 | #include <asm/lowcore.h> | 24 | #include <asm/lowcore.h> |
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 0833736afa32..65a1ecd77f96 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c | |||
@@ -217,19 +217,6 @@ void __init init_IRQ(void) | |||
217 | } | 217 | } |
218 | 218 | ||
219 | #ifdef CONFIG_HOTPLUG_CPU | 219 | #ifdef CONFIG_HOTPLUG_CPU |
220 | static void route_irq(struct irq_data *data, unsigned int irq, unsigned int cpu) | ||
221 | { | ||
222 | struct irq_desc *desc = irq_to_desc(irq); | ||
223 | struct irq_chip *chip = irq_data_get_irq_chip(data); | ||
224 | |||
225 | printk(KERN_INFO "IRQ%u: moving from cpu%u to cpu%u\n", | ||
226 | irq, data->node, cpu); | ||
227 | |||
228 | raw_spin_lock_irq(&desc->lock); | ||
229 | chip->irq_set_affinity(data, cpumask_of(cpu), false); | ||
230 | raw_spin_unlock_irq(&desc->lock); | ||
231 | } | ||
232 | |||
233 | /* | 220 | /* |
234 | * The CPU has been marked offline. Migrate IRQs off this CPU. If | 221 | * The CPU has been marked offline. Migrate IRQs off this CPU. If |
235 | * the affinity settings do not allow other CPUs, force them onto any | 222 | * the affinity settings do not allow other CPUs, force them onto any |
@@ -250,11 +237,8 @@ void migrate_irqs(void) | |||
250 | irq, cpu); | 237 | irq, cpu); |
251 | 238 | ||
252 | cpumask_setall(data->affinity); | 239 | cpumask_setall(data->affinity); |
253 | newcpu = cpumask_any_and(data->affinity, | ||
254 | cpu_online_mask); | ||
255 | } | 240 | } |
256 | 241 | irq_set_affinity(irq, data->affinity); | |
257 | route_irq(data, irq, newcpu); | ||
258 | } | 242 | } |
259 | } | 243 | } |
260 | } | 244 | } |
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c index c3d82b5f54ca..24e8b8705e7f 100644 --- a/arch/sparc/kernel/time_64.c +++ b/arch/sparc/kernel/time_64.c | |||
@@ -733,7 +733,7 @@ void __irq_entry timer_interrupt(int irq, struct pt_regs *regs) | |||
733 | irq_enter(); | 733 | irq_enter(); |
734 | 734 | ||
735 | local_cpu_data().irq0_irqs++; | 735 | local_cpu_data().irq0_irqs++; |
736 | kstat_incr_irqs_this_cpu(0, irq_to_desc(0)); | 736 | kstat_incr_irq_this_cpu(0); |
737 | 737 | ||
738 | if (unlikely(!evt->event_handler)) { | 738 | if (unlikely(!evt->event_handler)) { |
739 | printk(KERN_WARNING | 739 | printk(KERN_WARNING |
diff --git a/arch/x86/include/asm/floppy.h b/arch/x86/include/asm/floppy.h index d3d74698dce9..1c7eefe32502 100644 --- a/arch/x86/include/asm/floppy.h +++ b/arch/x86/include/asm/floppy.h | |||
@@ -145,10 +145,10 @@ static int fd_request_irq(void) | |||
145 | { | 145 | { |
146 | if (can_use_virtual_dma) | 146 | if (can_use_virtual_dma) |
147 | return request_irq(FLOPPY_IRQ, floppy_hardint, | 147 | return request_irq(FLOPPY_IRQ, floppy_hardint, |
148 | IRQF_DISABLED, "floppy", NULL); | 148 | 0, "floppy", NULL); |
149 | else | 149 | else |
150 | return request_irq(FLOPPY_IRQ, floppy_interrupt, | 150 | return request_irq(FLOPPY_IRQ, floppy_interrupt, |
151 | IRQF_DISABLED, "floppy", NULL); | 151 | 0, "floppy", NULL); |
152 | } | 152 | } |
153 | 153 | ||
154 | static unsigned long dma_mem_alloc(unsigned long size) | 154 | static unsigned long dma_mem_alloc(unsigned long size) |
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h index ab0ae1aa6d0a..230853da4ec0 100644 --- a/arch/x86/include/asm/hardirq.h +++ b/arch/x86/include/asm/hardirq.h | |||
@@ -33,6 +33,9 @@ typedef struct { | |||
33 | #ifdef CONFIG_X86_MCE_THRESHOLD | 33 | #ifdef CONFIG_X86_MCE_THRESHOLD |
34 | unsigned int irq_threshold_count; | 34 | unsigned int irq_threshold_count; |
35 | #endif | 35 | #endif |
36 | #if IS_ENABLED(CONFIG_HYPERV) || defined(CONFIG_XEN) | ||
37 | unsigned int irq_hv_callback_count; | ||
38 | #endif | ||
36 | } ____cacheline_aligned irq_cpustat_t; | 39 | } ____cacheline_aligned irq_cpustat_t; |
37 | 40 | ||
38 | DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); | 41 | DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); |
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index cd9c41938b8a..c163215abb9a 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define _ASM_X86_MSHYPER_H | 2 | #define _ASM_X86_MSHYPER_H |
3 | 3 | ||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | #include <linux/interrupt.h> | ||
5 | #include <asm/hyperv.h> | 6 | #include <asm/hyperv.h> |
6 | 7 | ||
7 | struct ms_hyperv_info { | 8 | struct ms_hyperv_info { |
@@ -16,6 +17,7 @@ void hyperv_callback_vector(void); | |||
16 | #define trace_hyperv_callback_vector hyperv_callback_vector | 17 | #define trace_hyperv_callback_vector hyperv_callback_vector |
17 | #endif | 18 | #endif |
18 | void hyperv_vector_handler(struct pt_regs *regs); | 19 | void hyperv_vector_handler(struct pt_regs *regs); |
19 | void hv_register_vmbus_handler(int irq, irq_handler_t handler); | 20 | void hv_setup_vmbus_irq(void (*handler)(void)); |
21 | void hv_remove_vmbus_irq(void); | ||
20 | 22 | ||
21 | #endif | 23 | #endif |
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 832d05a914ba..76f98fe5b35c 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/hardirq.h> | 17 | #include <linux/hardirq.h> |
18 | #include <linux/efi.h> | 18 | #include <linux/efi.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/irq.h> | ||
20 | #include <asm/processor.h> | 21 | #include <asm/processor.h> |
21 | #include <asm/hypervisor.h> | 22 | #include <asm/hypervisor.h> |
22 | #include <asm/hyperv.h> | 23 | #include <asm/hyperv.h> |
@@ -31,6 +32,45 @@ | |||
31 | struct ms_hyperv_info ms_hyperv; | 32 | struct ms_hyperv_info ms_hyperv; |
32 | EXPORT_SYMBOL_GPL(ms_hyperv); | 33 | EXPORT_SYMBOL_GPL(ms_hyperv); |
33 | 34 | ||
35 | #if IS_ENABLED(CONFIG_HYPERV) | ||
36 | static void (*vmbus_handler)(void); | ||
37 | |||
38 | void hyperv_vector_handler(struct pt_regs *regs) | ||
39 | { | ||
40 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
41 | |||
42 | irq_enter(); | ||
43 | exit_idle(); | ||
44 | |||
45 | inc_irq_stat(irq_hv_callback_count); | ||
46 | if (vmbus_handler) | ||
47 | vmbus_handler(); | ||
48 | |||
49 | irq_exit(); | ||
50 | set_irq_regs(old_regs); | ||
51 | } | ||
52 | |||
53 | void hv_setup_vmbus_irq(void (*handler)(void)) | ||
54 | { | ||
55 | vmbus_handler = handler; | ||
56 | /* | ||
57 | * Setup the IDT for hypervisor callback. Prevent reallocation | ||
58 | * at module reload. | ||
59 | */ | ||
60 | if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors)) | ||
61 | alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, | ||
62 | hyperv_callback_vector); | ||
63 | } | ||
64 | |||
65 | void hv_remove_vmbus_irq(void) | ||
66 | { | ||
67 | /* We have no way to deallocate the interrupt gate */ | ||
68 | vmbus_handler = NULL; | ||
69 | } | ||
70 | EXPORT_SYMBOL_GPL(hv_setup_vmbus_irq); | ||
71 | EXPORT_SYMBOL_GPL(hv_remove_vmbus_irq); | ||
72 | #endif | ||
73 | |||
34 | static uint32_t __init ms_hyperv_platform(void) | 74 | static uint32_t __init ms_hyperv_platform(void) |
35 | { | 75 | { |
36 | u32 eax; | 76 | u32 eax; |
@@ -119,41 +159,3 @@ const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { | |||
119 | .init_platform = ms_hyperv_init_platform, | 159 | .init_platform = ms_hyperv_init_platform, |
120 | }; | 160 | }; |
121 | EXPORT_SYMBOL(x86_hyper_ms_hyperv); | 161 | EXPORT_SYMBOL(x86_hyper_ms_hyperv); |
122 | |||
123 | #if IS_ENABLED(CONFIG_HYPERV) | ||
124 | static int vmbus_irq = -1; | ||
125 | static irq_handler_t vmbus_isr; | ||
126 | |||
127 | void hv_register_vmbus_handler(int irq, irq_handler_t handler) | ||
128 | { | ||
129 | /* | ||
130 | * Setup the IDT for hypervisor callback. | ||
131 | */ | ||
132 | alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, hyperv_callback_vector); | ||
133 | |||
134 | vmbus_irq = irq; | ||
135 | vmbus_isr = handler; | ||
136 | } | ||
137 | |||
138 | void hyperv_vector_handler(struct pt_regs *regs) | ||
139 | { | ||
140 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
141 | struct irq_desc *desc; | ||
142 | |||
143 | irq_enter(); | ||
144 | exit_idle(); | ||
145 | |||
146 | desc = irq_to_desc(vmbus_irq); | ||
147 | |||
148 | if (desc) | ||
149 | generic_handle_irq_desc(vmbus_irq, desc); | ||
150 | |||
151 | irq_exit(); | ||
152 | set_irq_regs(old_regs); | ||
153 | } | ||
154 | #else | ||
155 | void hv_register_vmbus_handler(int irq, irq_handler_t handler) | ||
156 | { | ||
157 | } | ||
158 | #endif | ||
159 | EXPORT_SYMBOL_GPL(hv_register_vmbus_handler); | ||
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index b91abfdd4931..014618dbaa7b 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c | |||
@@ -521,7 +521,7 @@ static int hpet_setup_irq(struct hpet_dev *dev) | |||
521 | { | 521 | { |
522 | 522 | ||
523 | if (request_irq(dev->irq, hpet_interrupt_handler, | 523 | if (request_irq(dev->irq, hpet_interrupt_handler, |
524 | IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING, | 524 | IRQF_TIMER | IRQF_NOBALANCING, |
525 | dev->name, dev)) | 525 | dev->name, dev)) |
526 | return -1; | 526 | return -1; |
527 | 527 | ||
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index d99f31d9a750..42805fac0092 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
@@ -125,6 +125,12 @@ int arch_show_interrupts(struct seq_file *p, int prec) | |||
125 | seq_printf(p, "%10u ", per_cpu(mce_poll_count, j)); | 125 | seq_printf(p, "%10u ", per_cpu(mce_poll_count, j)); |
126 | seq_printf(p, " Machine check polls\n"); | 126 | seq_printf(p, " Machine check polls\n"); |
127 | #endif | 127 | #endif |
128 | #if defined(CONFIG_HYPERV) || defined(CONFIG_XEN) | ||
129 | seq_printf(p, "%*s: ", prec, "THR"); | ||
130 | for_each_online_cpu(j) | ||
131 | seq_printf(p, "%10u ", irq_stats(j)->irq_hv_callback_count); | ||
132 | seq_printf(p, " Hypervisor callback interrupts\n"); | ||
133 | #endif | ||
128 | seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count)); | 134 | seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count)); |
129 | #if defined(CONFIG_X86_IO_APIC) | 135 | #if defined(CONFIG_X86_IO_APIC) |
130 | seq_printf(p, "%*s: %10u\n", prec, "MIS", atomic_read(&irq_mis_count)); | 136 | seq_printf(p, "%*s: %10u\n", prec, "MIS", atomic_read(&irq_mis_count)); |
diff --git a/arch/x86/kernel/time.c b/arch/x86/kernel/time.c index 6ec91c00d84d..bf7ef5ce29df 100644 --- a/arch/x86/kernel/time.c +++ b/arch/x86/kernel/time.c | |||
@@ -62,7 +62,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id) | |||
62 | 62 | ||
63 | static struct irqaction irq0 = { | 63 | static struct irqaction irq0 = { |
64 | .handler = timer_interrupt, | 64 | .handler = timer_interrupt, |
65 | .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER, | 65 | .flags = IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER, |
66 | .name = "timer" | 66 | .name = "timer" |
67 | }; | 67 | }; |
68 | 68 | ||
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index 581521c843a5..4d3acc34a998 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c | |||
@@ -183,7 +183,7 @@ __visible void xen_lock_spinning(struct arch_spinlock *lock, __ticket_t want) | |||
183 | 183 | ||
184 | local_irq_save(flags); | 184 | local_irq_save(flags); |
185 | 185 | ||
186 | kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); | 186 | kstat_incr_irq_this_cpu(irq); |
187 | out: | 187 | out: |
188 | cpumask_clear_cpu(cpu, &waiting_cpus); | 188 | cpumask_clear_cpu(cpu, &waiting_cpus); |
189 | w->lock = NULL; | 189 | w->lock = NULL; |
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c index 482868a2de6e..3eee94f621eb 100644 --- a/arch/xtensa/kernel/irq.c +++ b/arch/xtensa/kernel/irq.c | |||
@@ -155,18 +155,6 @@ void __init init_IRQ(void) | |||
155 | } | 155 | } |
156 | 156 | ||
157 | #ifdef CONFIG_HOTPLUG_CPU | 157 | #ifdef CONFIG_HOTPLUG_CPU |
158 | static void route_irq(struct irq_data *data, unsigned int irq, unsigned int cpu) | ||
159 | { | ||
160 | struct irq_desc *desc = irq_to_desc(irq); | ||
161 | struct irq_chip *chip = irq_data_get_irq_chip(data); | ||
162 | unsigned long flags; | ||
163 | |||
164 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
165 | if (chip->irq_set_affinity) | ||
166 | chip->irq_set_affinity(data, cpumask_of(cpu), false); | ||
167 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
168 | } | ||
169 | |||
170 | /* | 158 | /* |
171 | * The CPU has been marked offline. Migrate IRQs off this CPU. If | 159 | * The CPU has been marked offline. Migrate IRQs off this CPU. If |
172 | * the affinity settings do not allow other CPUs, force them onto any | 160 | * the affinity settings do not allow other CPUs, force them onto any |
@@ -175,10 +163,9 @@ static void route_irq(struct irq_data *data, unsigned int irq, unsigned int cpu) | |||
175 | void migrate_irqs(void) | 163 | void migrate_irqs(void) |
176 | { | 164 | { |
177 | unsigned int i, cpu = smp_processor_id(); | 165 | unsigned int i, cpu = smp_processor_id(); |
178 | struct irq_desc *desc; | ||
179 | 166 | ||
180 | for_each_irq_desc(i, desc) { | 167 | for_each_active_irq(i) { |
181 | struct irq_data *data = irq_desc_get_irq_data(desc); | 168 | struct irq_data *data = irq_get_irq_data(i); |
182 | unsigned int newcpu; | 169 | unsigned int newcpu; |
183 | 170 | ||
184 | if (irqd_is_per_cpu(data)) | 171 | if (irqd_is_per_cpu(data)) |
@@ -194,11 +181,8 @@ void migrate_irqs(void) | |||
194 | i, cpu); | 181 | i, cpu); |
195 | 182 | ||
196 | cpumask_setall(data->affinity); | 183 | cpumask_setall(data->affinity); |
197 | newcpu = cpumask_any_and(data->affinity, | ||
198 | cpu_online_mask); | ||
199 | } | 184 | } |
200 | 185 | irq_set_affinity(i, data->affinity); | |
201 | route_irq(data, i, newcpu); | ||
202 | } | 186 | } |
203 | } | 187 | } |
204 | #endif /* CONFIG_HOTPLUG_CPU */ | 188 | #endif /* CONFIG_HOTPLUG_CPU */ |
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 077bb1bdac34..3f0a95290e14 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/device.h> | 27 | #include <linux/device.h> |
28 | #include <linux/irq.h> | ||
29 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
30 | #include <linux/sysctl.h> | 29 | #include <linux/sysctl.h> |
31 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
@@ -558,9 +557,6 @@ static struct bus_type hv_bus = { | |||
558 | .dev_groups = vmbus_groups, | 557 | .dev_groups = vmbus_groups, |
559 | }; | 558 | }; |
560 | 559 | ||
561 | static const char *driver_name = "hyperv"; | ||
562 | |||
563 | |||
564 | struct onmessage_work_context { | 560 | struct onmessage_work_context { |
565 | struct work_struct work; | 561 | struct work_struct work; |
566 | struct hv_message msg; | 562 | struct hv_message msg; |
@@ -619,7 +615,7 @@ static void vmbus_on_msg_dpc(unsigned long data) | |||
619 | } | 615 | } |
620 | } | 616 | } |
621 | 617 | ||
622 | static irqreturn_t vmbus_isr(int irq, void *dev_id) | 618 | static void vmbus_isr(void) |
623 | { | 619 | { |
624 | int cpu = smp_processor_id(); | 620 | int cpu = smp_processor_id(); |
625 | void *page_addr; | 621 | void *page_addr; |
@@ -629,7 +625,7 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id) | |||
629 | 625 | ||
630 | page_addr = hv_context.synic_event_page[cpu]; | 626 | page_addr = hv_context.synic_event_page[cpu]; |
631 | if (page_addr == NULL) | 627 | if (page_addr == NULL) |
632 | return IRQ_NONE; | 628 | return; |
633 | 629 | ||
634 | event = (union hv_synic_event_flags *)page_addr + | 630 | event = (union hv_synic_event_flags *)page_addr + |
635 | VMBUS_MESSAGE_SINT; | 631 | VMBUS_MESSAGE_SINT; |
@@ -665,28 +661,8 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id) | |||
665 | msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; | 661 | msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; |
666 | 662 | ||
667 | /* Check if there are actual msgs to be processed */ | 663 | /* Check if there are actual msgs to be processed */ |
668 | if (msg->header.message_type != HVMSG_NONE) { | 664 | if (msg->header.message_type != HVMSG_NONE) |
669 | handled = true; | ||
670 | tasklet_schedule(&msg_dpc); | 665 | tasklet_schedule(&msg_dpc); |
671 | } | ||
672 | |||
673 | if (handled) | ||
674 | return IRQ_HANDLED; | ||
675 | else | ||
676 | return IRQ_NONE; | ||
677 | } | ||
678 | |||
679 | /* | ||
680 | * vmbus interrupt flow handler: | ||
681 | * vmbus interrupts can concurrently occur on multiple CPUs and | ||
682 | * can be handled concurrently. | ||
683 | */ | ||
684 | |||
685 | static void vmbus_flow_handler(unsigned int irq, struct irq_desc *desc) | ||
686 | { | ||
687 | kstat_incr_irqs_this_cpu(irq, desc); | ||
688 | |||
689 | desc->action->handler(irq, desc->action->dev_id); | ||
690 | } | 666 | } |
691 | 667 | ||
692 | /* | 668 | /* |
@@ -715,25 +691,7 @@ static int vmbus_bus_init(int irq) | |||
715 | if (ret) | 691 | if (ret) |
716 | goto err_cleanup; | 692 | goto err_cleanup; |
717 | 693 | ||
718 | ret = request_irq(irq, vmbus_isr, 0, driver_name, hv_acpi_dev); | 694 | hv_setup_vmbus_irq(vmbus_isr); |
719 | |||
720 | if (ret != 0) { | ||
721 | pr_err("Unable to request IRQ %d\n", | ||
722 | irq); | ||
723 | goto err_unregister; | ||
724 | } | ||
725 | |||
726 | /* | ||
727 | * Vmbus interrupts can be handled concurrently on | ||
728 | * different CPUs. Establish an appropriate interrupt flow | ||
729 | * handler that can support this model. | ||
730 | */ | ||
731 | irq_set_handler(irq, vmbus_flow_handler); | ||
732 | |||
733 | /* | ||
734 | * Register our interrupt handler. | ||
735 | */ | ||
736 | hv_register_vmbus_handler(irq, vmbus_isr); | ||
737 | 695 | ||
738 | ret = hv_synic_alloc(); | 696 | ret = hv_synic_alloc(); |
739 | if (ret) | 697 | if (ret) |
@@ -753,9 +711,8 @@ static int vmbus_bus_init(int irq) | |||
753 | 711 | ||
754 | err_alloc: | 712 | err_alloc: |
755 | hv_synic_free(); | 713 | hv_synic_free(); |
756 | free_irq(irq, hv_acpi_dev); | 714 | hv_remove_vmbus_irq(); |
757 | 715 | ||
758 | err_unregister: | ||
759 | bus_unregister(&hv_bus); | 716 | bus_unregister(&hv_bus); |
760 | 717 | ||
761 | err_cleanup: | 718 | err_cleanup: |
@@ -947,7 +904,6 @@ static int __init hv_acpi_init(void) | |||
947 | /* | 904 | /* |
948 | * Get irq resources first. | 905 | * Get irq resources first. |
949 | */ | 906 | */ |
950 | |||
951 | ret = acpi_bus_register_driver(&vmbus_acpi_driver); | 907 | ret = acpi_bus_register_driver(&vmbus_acpi_driver); |
952 | 908 | ||
953 | if (ret) | 909 | if (ret) |
@@ -978,8 +934,7 @@ cleanup: | |||
978 | 934 | ||
979 | static void __exit vmbus_exit(void) | 935 | static void __exit vmbus_exit(void) |
980 | { | 936 | { |
981 | 937 | hv_remove_vmbus_irq(); | |
982 | free_irq(irq, hv_acpi_dev); | ||
983 | vmbus_free_channels(); | 938 | vmbus_free_channels(); |
984 | bus_unregister(&hv_bus); | 939 | bus_unregister(&hv_bus); |
985 | hv_cleanup(); | 940 | hv_cleanup(); |
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 5194afb39e78..1c0c151d108c 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile | |||
@@ -12,6 +12,7 @@ obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o | |||
12 | obj-$(CONFIG_ARCH_MOXART) += irq-moxart.o | 12 | obj-$(CONFIG_ARCH_MOXART) += irq-moxart.o |
13 | obj-$(CONFIG_ORION_IRQCHIP) += irq-orion.o | 13 | obj-$(CONFIG_ORION_IRQCHIP) += irq-orion.o |
14 | obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o | 14 | obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o |
15 | obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o | ||
15 | obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o | 16 | obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o |
16 | obj-$(CONFIG_ARM_GIC) += irq-gic.o | 17 | obj-$(CONFIG_ARM_GIC) += irq-gic.o |
17 | obj-$(CONFIG_ARM_NVIC) += irq-nvic.o | 18 | obj-$(CONFIG_ARM_NVIC) += irq-nvic.o |
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 540956465ed2..41be897df8d5 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/irqchip/chained_irq.h> | ||
21 | #include <linux/io.h> | 22 | #include <linux/io.h> |
22 | #include <linux/of_address.h> | 23 | #include <linux/of_address.h> |
23 | #include <linux/of_irq.h> | 24 | #include <linux/of_irq.h> |
@@ -42,6 +43,7 @@ | |||
42 | #define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4) | 43 | #define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4) |
43 | 44 | ||
44 | #define ARMADA_370_XP_CPU_INTACK_OFFS (0x44) | 45 | #define ARMADA_370_XP_CPU_INTACK_OFFS (0x44) |
46 | #define ARMADA_375_PPI_CAUSE (0x10) | ||
45 | 47 | ||
46 | #define ARMADA_370_XP_SW_TRIG_INT_OFFS (0x4) | 48 | #define ARMADA_370_XP_SW_TRIG_INT_OFFS (0x4) |
47 | #define ARMADA_370_XP_IN_DRBEL_MSK_OFFS (0xc) | 49 | #define ARMADA_370_XP_IN_DRBEL_MSK_OFFS (0xc) |
@@ -352,7 +354,63 @@ static struct irq_domain_ops armada_370_xp_mpic_irq_ops = { | |||
352 | .xlate = irq_domain_xlate_onecell, | 354 | .xlate = irq_domain_xlate_onecell, |
353 | }; | 355 | }; |
354 | 356 | ||
355 | static asmlinkage void __exception_irq_entry | 357 | #ifdef CONFIG_PCI_MSI |
358 | static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained) | ||
359 | { | ||
360 | u32 msimask, msinr; | ||
361 | |||
362 | msimask = readl_relaxed(per_cpu_int_base + | ||
363 | ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS) | ||
364 | & PCI_MSI_DOORBELL_MASK; | ||
365 | |||
366 | writel(~msimask, per_cpu_int_base + | ||
367 | ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS); | ||
368 | |||
369 | for (msinr = PCI_MSI_DOORBELL_START; | ||
370 | msinr < PCI_MSI_DOORBELL_END; msinr++) { | ||
371 | int irq; | ||
372 | |||
373 | if (!(msimask & BIT(msinr))) | ||
374 | continue; | ||
375 | |||
376 | irq = irq_find_mapping(armada_370_xp_msi_domain, | ||
377 | msinr - 16); | ||
378 | |||
379 | if (is_chained) | ||
380 | generic_handle_irq(irq); | ||
381 | else | ||
382 | handle_IRQ(irq, regs); | ||
383 | } | ||
384 | } | ||
385 | #else | ||
386 | static void armada_370_xp_handle_msi_irq(struct pt_regs *r, bool b) {} | ||
387 | #endif | ||
388 | |||
389 | static void armada_370_xp_mpic_handle_cascade_irq(unsigned int irq, | ||
390 | struct irq_desc *desc) | ||
391 | { | ||
392 | struct irq_chip *chip = irq_get_chip(irq); | ||
393 | unsigned long irqmap, irqn; | ||
394 | unsigned int cascade_irq; | ||
395 | |||
396 | chained_irq_enter(chip, desc); | ||
397 | |||
398 | irqmap = readl_relaxed(per_cpu_int_base + ARMADA_375_PPI_CAUSE); | ||
399 | |||
400 | if (irqmap & BIT(0)) { | ||
401 | armada_370_xp_handle_msi_irq(NULL, true); | ||
402 | irqmap &= ~BIT(0); | ||
403 | } | ||
404 | |||
405 | for_each_set_bit(irqn, &irqmap, BITS_PER_LONG) { | ||
406 | cascade_irq = irq_find_mapping(armada_370_xp_mpic_domain, irqn); | ||
407 | generic_handle_irq(cascade_irq); | ||
408 | } | ||
409 | |||
410 | chained_irq_exit(chip, desc); | ||
411 | } | ||
412 | |||
413 | static void __exception_irq_entry | ||
356 | armada_370_xp_handle_irq(struct pt_regs *regs) | 414 | armada_370_xp_handle_irq(struct pt_regs *regs) |
357 | { | 415 | { |
358 | u32 irqstat, irqnr; | 416 | u32 irqstat, irqnr; |
@@ -372,31 +430,9 @@ armada_370_xp_handle_irq(struct pt_regs *regs) | |||
372 | continue; | 430 | continue; |
373 | } | 431 | } |
374 | 432 | ||
375 | #ifdef CONFIG_PCI_MSI | ||
376 | /* MSI handling */ | 433 | /* MSI handling */ |
377 | if (irqnr == 1) { | 434 | if (irqnr == 1) |
378 | u32 msimask, msinr; | 435 | armada_370_xp_handle_msi_irq(regs, false); |
379 | |||
380 | msimask = readl_relaxed(per_cpu_int_base + | ||
381 | ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS) | ||
382 | & PCI_MSI_DOORBELL_MASK; | ||
383 | |||
384 | writel(~msimask, per_cpu_int_base + | ||
385 | ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS); | ||
386 | |||
387 | for (msinr = PCI_MSI_DOORBELL_START; | ||
388 | msinr < PCI_MSI_DOORBELL_END; msinr++) { | ||
389 | int irq; | ||
390 | |||
391 | if (!(msimask & BIT(msinr))) | ||
392 | continue; | ||
393 | |||
394 | irq = irq_find_mapping(armada_370_xp_msi_domain, | ||
395 | msinr - 16); | ||
396 | handle_IRQ(irq, regs); | ||
397 | } | ||
398 | } | ||
399 | #endif | ||
400 | 436 | ||
401 | #ifdef CONFIG_SMP | 437 | #ifdef CONFIG_SMP |
402 | /* IPI Handling */ | 438 | /* IPI Handling */ |
@@ -427,6 +463,7 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, | |||
427 | struct device_node *parent) | 463 | struct device_node *parent) |
428 | { | 464 | { |
429 | struct resource main_int_res, per_cpu_int_res; | 465 | struct resource main_int_res, per_cpu_int_res; |
466 | int parent_irq; | ||
430 | u32 control; | 467 | u32 control; |
431 | 468 | ||
432 | BUG_ON(of_address_to_resource(node, 0, &main_int_res)); | 469 | BUG_ON(of_address_to_resource(node, 0, &main_int_res)); |
@@ -455,8 +492,6 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, | |||
455 | 492 | ||
456 | BUG_ON(!armada_370_xp_mpic_domain); | 493 | BUG_ON(!armada_370_xp_mpic_domain); |
457 | 494 | ||
458 | irq_set_default_host(armada_370_xp_mpic_domain); | ||
459 | |||
460 | #ifdef CONFIG_SMP | 495 | #ifdef CONFIG_SMP |
461 | armada_xp_mpic_smp_cpu_init(); | 496 | armada_xp_mpic_smp_cpu_init(); |
462 | 497 | ||
@@ -472,7 +507,14 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, | |||
472 | 507 | ||
473 | armada_370_xp_msi_init(node, main_int_res.start); | 508 | armada_370_xp_msi_init(node, main_int_res.start); |
474 | 509 | ||
475 | set_handle_irq(armada_370_xp_handle_irq); | 510 | parent_irq = irq_of_parse_and_map(node, 0); |
511 | if (parent_irq <= 0) { | ||
512 | irq_set_default_host(armada_370_xp_mpic_domain); | ||
513 | set_handle_irq(armada_370_xp_handle_irq); | ||
514 | } else { | ||
515 | irq_set_chained_handler(parent_irq, | ||
516 | armada_370_xp_mpic_handle_cascade_irq); | ||
517 | } | ||
476 | 518 | ||
477 | return 0; | 519 | return 0; |
478 | } | 520 | } |
diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c index 1693b8e7f26a..5916d6cdafa1 100644 --- a/drivers/irqchip/irq-bcm2835.c +++ b/drivers/irqchip/irq-bcm2835.c | |||
@@ -95,7 +95,7 @@ struct armctrl_ic { | |||
95 | }; | 95 | }; |
96 | 96 | ||
97 | static struct armctrl_ic intc __read_mostly; | 97 | static struct armctrl_ic intc __read_mostly; |
98 | static asmlinkage void __exception_irq_entry bcm2835_handle_irq( | 98 | static void __exception_irq_entry bcm2835_handle_irq( |
99 | struct pt_regs *regs); | 99 | struct pt_regs *regs); |
100 | 100 | ||
101 | static void armctrl_mask_irq(struct irq_data *d) | 101 | static void armctrl_mask_irq(struct irq_data *d) |
@@ -196,7 +196,7 @@ static void armctrl_handle_shortcut(int bank, struct pt_regs *regs, | |||
196 | handle_IRQ(irq_linear_revmap(intc.domain, irq), regs); | 196 | handle_IRQ(irq_linear_revmap(intc.domain, irq), regs); |
197 | } | 197 | } |
198 | 198 | ||
199 | static asmlinkage void __exception_irq_entry bcm2835_handle_irq( | 199 | static void __exception_irq_entry bcm2835_handle_irq( |
200 | struct pt_regs *regs) | 200 | struct pt_regs *regs) |
201 | { | 201 | { |
202 | u32 stat, irq; | 202 | u32 stat, irq; |
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 341c6016812d..531769b2433a 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c | |||
@@ -50,7 +50,7 @@ | |||
50 | 50 | ||
51 | union gic_base { | 51 | union gic_base { |
52 | void __iomem *common_base; | 52 | void __iomem *common_base; |
53 | void __percpu __iomem **percpu_base; | 53 | void __percpu * __iomem *percpu_base; |
54 | }; | 54 | }; |
55 | 55 | ||
56 | struct gic_chip_data { | 56 | struct gic_chip_data { |
@@ -279,7 +279,7 @@ static int gic_set_wake(struct irq_data *d, unsigned int on) | |||
279 | #define gic_set_wake NULL | 279 | #define gic_set_wake NULL |
280 | #endif | 280 | #endif |
281 | 281 | ||
282 | static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) | 282 | static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) |
283 | { | 283 | { |
284 | u32 irqstat, irqnr; | 284 | u32 irqstat, irqnr; |
285 | struct gic_chip_data *gic = &gic_data[0]; | 285 | struct gic_chip_data *gic = &gic_data[0]; |
@@ -648,7 +648,7 @@ static void __init gic_pm_init(struct gic_chip_data *gic) | |||
648 | #endif | 648 | #endif |
649 | 649 | ||
650 | #ifdef CONFIG_SMP | 650 | #ifdef CONFIG_SMP |
651 | void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) | 651 | static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) |
652 | { | 652 | { |
653 | int cpu; | 653 | int cpu; |
654 | unsigned long flags, map = 0; | 654 | unsigned long flags, map = 0; |
@@ -869,7 +869,7 @@ static struct notifier_block gic_cpu_notifier = { | |||
869 | }; | 869 | }; |
870 | #endif | 870 | #endif |
871 | 871 | ||
872 | const struct irq_domain_ops gic_irq_domain_ops = { | 872 | static const struct irq_domain_ops gic_irq_domain_ops = { |
873 | .map = gic_irq_domain_map, | 873 | .map = gic_irq_domain_map, |
874 | .xlate = gic_irq_domain_xlate, | 874 | .xlate = gic_irq_domain_xlate, |
875 | }; | 875 | }; |
@@ -974,7 +974,8 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, | |||
974 | #ifdef CONFIG_OF | 974 | #ifdef CONFIG_OF |
975 | static int gic_cnt __initdata; | 975 | static int gic_cnt __initdata; |
976 | 976 | ||
977 | int __init gic_of_init(struct device_node *node, struct device_node *parent) | 977 | static int __init |
978 | gic_of_init(struct device_node *node, struct device_node *parent) | ||
978 | { | 979 | { |
979 | void __iomem *cpu_base; | 980 | void __iomem *cpu_base; |
980 | void __iomem *dist_base; | 981 | void __iomem *dist_base; |
diff --git a/drivers/irqchip/irq-mmp.c b/drivers/irqchip/irq-mmp.c index 2cb7cd0bc2f5..3c8827fe83f3 100644 --- a/drivers/irqchip/irq-mmp.c +++ b/drivers/irqchip/irq-mmp.c | |||
@@ -194,8 +194,7 @@ static struct mmp_intc_conf mmp2_conf = { | |||
194 | .conf_mask = 0x7f, | 194 | .conf_mask = 0x7f, |
195 | }; | 195 | }; |
196 | 196 | ||
197 | static asmlinkage void __exception_irq_entry | 197 | static void __exception_irq_entry mmp_handle_irq(struct pt_regs *regs) |
198 | mmp_handle_irq(struct pt_regs *regs) | ||
199 | { | 198 | { |
200 | int irq, hwirq; | 199 | int irq, hwirq; |
201 | 200 | ||
@@ -207,8 +206,7 @@ mmp_handle_irq(struct pt_regs *regs) | |||
207 | handle_IRQ(irq, regs); | 206 | handle_IRQ(irq, regs); |
208 | } | 207 | } |
209 | 208 | ||
210 | static asmlinkage void __exception_irq_entry | 209 | static void __exception_irq_entry mmp2_handle_irq(struct pt_regs *regs) |
211 | mmp2_handle_irq(struct pt_regs *regs) | ||
212 | { | 210 | { |
213 | int irq, hwirq; | 211 | int irq, hwirq; |
214 | 212 | ||
diff --git a/drivers/irqchip/irq-moxart.c b/drivers/irqchip/irq-moxart.c index 5552fc2bf28a..00b3cc908f76 100644 --- a/drivers/irqchip/irq-moxart.c +++ b/drivers/irqchip/irq-moxart.c | |||
@@ -44,7 +44,7 @@ struct moxart_irq_data { | |||
44 | 44 | ||
45 | static struct moxart_irq_data intc; | 45 | static struct moxart_irq_data intc; |
46 | 46 | ||
47 | static asmlinkage void __exception_irq_entry handle_irq(struct pt_regs *regs) | 47 | static void __exception_irq_entry handle_irq(struct pt_regs *regs) |
48 | { | 48 | { |
49 | u32 irqstat; | 49 | u32 irqstat; |
50 | int hwirq; | 50 | int hwirq; |
diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c index 8e41be62812e..e25f246cd2fb 100644 --- a/drivers/irqchip/irq-orion.c +++ b/drivers/irqchip/irq-orion.c | |||
@@ -30,7 +30,7 @@ | |||
30 | 30 | ||
31 | static struct irq_domain *orion_irq_domain; | 31 | static struct irq_domain *orion_irq_domain; |
32 | 32 | ||
33 | static asmlinkage void | 33 | static void |
34 | __exception_irq_entry orion_handle_irq(struct pt_regs *regs) | 34 | __exception_irq_entry orion_handle_irq(struct pt_regs *regs) |
35 | { | 35 | { |
36 | struct irq_domain_chip_generic *dgc = orion_irq_domain->gc; | 36 | struct irq_domain_chip_generic *dgc = orion_irq_domain->gc; |
diff --git a/drivers/irqchip/irq-sirfsoc.c b/drivers/irqchip/irq-sirfsoc.c index 3a070c587ed9..581eefe331ae 100644 --- a/drivers/irqchip/irq-sirfsoc.c +++ b/drivers/irqchip/irq-sirfsoc.c | |||
@@ -47,7 +47,7 @@ sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num) | |||
47 | ct->regs.mask = SIRFSOC_INT_RISC_MASK0; | 47 | ct->regs.mask = SIRFSOC_INT_RISC_MASK0; |
48 | } | 48 | } |
49 | 49 | ||
50 | static asmlinkage 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, irqnr; |
diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c index a5438d889245..6fcef4a95a18 100644 --- a/drivers/irqchip/irq-sun4i.c +++ b/drivers/irqchip/irq-sun4i.c | |||
@@ -36,18 +36,16 @@ | |||
36 | static void __iomem *sun4i_irq_base; | 36 | static void __iomem *sun4i_irq_base; |
37 | static struct irq_domain *sun4i_irq_domain; | 37 | static struct irq_domain *sun4i_irq_domain; |
38 | 38 | ||
39 | static asmlinkage void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs); | 39 | static void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs); |
40 | 40 | ||
41 | static void sun4i_irq_ack(struct irq_data *irqd) | 41 | static void sun4i_irq_ack(struct irq_data *irqd) |
42 | { | 42 | { |
43 | unsigned int irq = irqd_to_hwirq(irqd); | 43 | unsigned int irq = irqd_to_hwirq(irqd); |
44 | unsigned int irq_off = irq % 32; | ||
45 | int reg = irq / 32; | ||
46 | u32 val; | ||
47 | 44 | ||
48 | val = readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg)); | 45 | if (irq != 0) |
49 | writel(val | (1 << irq_off), | 46 | return; /* Only IRQ 0 / the ENMI needs to be acked */ |
50 | sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg)); | 47 | |
48 | writel(BIT(0), sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0)); | ||
51 | } | 49 | } |
52 | 50 | ||
53 | static void sun4i_irq_mask(struct irq_data *irqd) | 51 | static void sun4i_irq_mask(struct irq_data *irqd) |
@@ -76,16 +74,16 @@ static void sun4i_irq_unmask(struct irq_data *irqd) | |||
76 | 74 | ||
77 | static struct irq_chip sun4i_irq_chip = { | 75 | static struct irq_chip sun4i_irq_chip = { |
78 | .name = "sun4i_irq", | 76 | .name = "sun4i_irq", |
79 | .irq_ack = sun4i_irq_ack, | 77 | .irq_eoi = sun4i_irq_ack, |
80 | .irq_mask = sun4i_irq_mask, | 78 | .irq_mask = sun4i_irq_mask, |
81 | .irq_unmask = sun4i_irq_unmask, | 79 | .irq_unmask = sun4i_irq_unmask, |
80 | .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED, | ||
82 | }; | 81 | }; |
83 | 82 | ||
84 | static int sun4i_irq_map(struct irq_domain *d, unsigned int virq, | 83 | static int sun4i_irq_map(struct irq_domain *d, unsigned int virq, |
85 | irq_hw_number_t hw) | 84 | irq_hw_number_t hw) |
86 | { | 85 | { |
87 | irq_set_chip_and_handler(virq, &sun4i_irq_chip, | 86 | irq_set_chip_and_handler(virq, &sun4i_irq_chip, handle_fasteoi_irq); |
88 | handle_level_irq); | ||
89 | set_irq_flags(virq, IRQF_VALID | IRQF_PROBE); | 87 | set_irq_flags(virq, IRQF_VALID | IRQF_PROBE); |
90 | 88 | ||
91 | return 0; | 89 | return 0; |
@@ -109,7 +107,7 @@ static int __init sun4i_of_init(struct device_node *node, | |||
109 | writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(1)); | 107 | writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(1)); |
110 | writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(2)); | 108 | writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(2)); |
111 | 109 | ||
112 | /* Mask all the interrupts */ | 110 | /* Unmask all the interrupts, ENABLE_REG(x) is used for masking */ |
113 | writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(0)); | 111 | writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(0)); |
114 | writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(1)); | 112 | writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(1)); |
115 | writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(2)); | 113 | writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(2)); |
@@ -134,16 +132,30 @@ static int __init sun4i_of_init(struct device_node *node, | |||
134 | 132 | ||
135 | return 0; | 133 | return 0; |
136 | } | 134 | } |
137 | IRQCHIP_DECLARE(allwinner_sun4i_ic, "allwinner,sun4i-ic", sun4i_of_init); | 135 | IRQCHIP_DECLARE(allwinner_sun4i_ic, "allwinner,sun4i-a10-ic", sun4i_of_init); |
138 | 136 | ||
139 | static asmlinkage void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs) | 137 | static void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs) |
140 | { | 138 | { |
141 | u32 irq, hwirq; | 139 | u32 irq, hwirq; |
142 | 140 | ||
141 | /* | ||
142 | * hwirq == 0 can mean one of 3 things: | ||
143 | * 1) no more irqs pending | ||
144 | * 2) irq 0 pending | ||
145 | * 3) spurious irq | ||
146 | * So if we immediately get a reading of 0, check the irq-pending reg | ||
147 | * to differentiate between 2 and 3. We only do this once to avoid | ||
148 | * the extra check in the common case of 1 hapening after having | ||
149 | * read the vector-reg once. | ||
150 | */ | ||
143 | hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2; | 151 | hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2; |
144 | while (hwirq != 0) { | 152 | if (hwirq == 0 && |
153 | !(readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0)) & BIT(0))) | ||
154 | return; | ||
155 | |||
156 | do { | ||
145 | irq = irq_find_mapping(sun4i_irq_domain, hwirq); | 157 | irq = irq_find_mapping(sun4i_irq_domain, hwirq); |
146 | handle_IRQ(irq, regs); | 158 | handle_IRQ(irq, regs); |
147 | hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2; | 159 | hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2; |
148 | } | 160 | } while (hwirq != 0); |
149 | } | 161 | } |
diff --git a/drivers/irqchip/irq-sunxi-nmi.c b/drivers/irqchip/irq-sunxi-nmi.c new file mode 100644 index 000000000000..12f547a44ae4 --- /dev/null +++ b/drivers/irqchip/irq-sunxi-nmi.c | |||
@@ -0,0 +1,208 @@ | |||
1 | /* | ||
2 | * Allwinner A20/A31 SoCs NMI IRQ chip driver. | ||
3 | * | ||
4 | * Carlo Caione <carlo.caione@gmail.com> | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public | ||
7 | * License version 2. This program is licensed "as is" without any | ||
8 | * warranty of any kind, whether express or implied. | ||
9 | */ | ||
10 | |||
11 | #include <linux/bitops.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/irq.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/irqdomain.h> | ||
17 | #include <linux/of_irq.h> | ||
18 | #include <linux/of_address.h> | ||
19 | #include <linux/of_platform.h> | ||
20 | #include <linux/irqchip/chained_irq.h> | ||
21 | #include "irqchip.h" | ||
22 | |||
23 | #define SUNXI_NMI_SRC_TYPE_MASK 0x00000003 | ||
24 | |||
25 | enum { | ||
26 | SUNXI_SRC_TYPE_LEVEL_LOW = 0, | ||
27 | SUNXI_SRC_TYPE_EDGE_FALLING, | ||
28 | SUNXI_SRC_TYPE_LEVEL_HIGH, | ||
29 | SUNXI_SRC_TYPE_EDGE_RISING, | ||
30 | }; | ||
31 | |||
32 | struct sunxi_sc_nmi_reg_offs { | ||
33 | u32 ctrl; | ||
34 | u32 pend; | ||
35 | u32 enable; | ||
36 | }; | ||
37 | |||
38 | static struct sunxi_sc_nmi_reg_offs sun7i_reg_offs = { | ||
39 | .ctrl = 0x00, | ||
40 | .pend = 0x04, | ||
41 | .enable = 0x08, | ||
42 | }; | ||
43 | |||
44 | static struct sunxi_sc_nmi_reg_offs sun6i_reg_offs = { | ||
45 | .ctrl = 0x00, | ||
46 | .pend = 0x04, | ||
47 | .enable = 0x34, | ||
48 | }; | ||
49 | |||
50 | static inline void sunxi_sc_nmi_write(struct irq_chip_generic *gc, u32 off, | ||
51 | u32 val) | ||
52 | { | ||
53 | irq_reg_writel(val, gc->reg_base + off); | ||
54 | } | ||
55 | |||
56 | static inline u32 sunxi_sc_nmi_read(struct irq_chip_generic *gc, u32 off) | ||
57 | { | ||
58 | return irq_reg_readl(gc->reg_base + off); | ||
59 | } | ||
60 | |||
61 | static void sunxi_sc_nmi_handle_irq(unsigned int irq, struct irq_desc *desc) | ||
62 | { | ||
63 | struct irq_domain *domain = irq_desc_get_handler_data(desc); | ||
64 | struct irq_chip *chip = irq_get_chip(irq); | ||
65 | unsigned int virq = irq_find_mapping(domain, 0); | ||
66 | |||
67 | chained_irq_enter(chip, desc); | ||
68 | generic_handle_irq(virq); | ||
69 | chained_irq_exit(chip, desc); | ||
70 | } | ||
71 | |||
72 | static int sunxi_sc_nmi_set_type(struct irq_data *data, unsigned int flow_type) | ||
73 | { | ||
74 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data); | ||
75 | struct irq_chip_type *ct = gc->chip_types; | ||
76 | u32 src_type_reg; | ||
77 | u32 ctrl_off = ct->regs.type; | ||
78 | unsigned int src_type; | ||
79 | unsigned int i; | ||
80 | |||
81 | irq_gc_lock(gc); | ||
82 | |||
83 | switch (flow_type & IRQF_TRIGGER_MASK) { | ||
84 | case IRQ_TYPE_EDGE_FALLING: | ||
85 | src_type = SUNXI_SRC_TYPE_EDGE_FALLING; | ||
86 | break; | ||
87 | case IRQ_TYPE_EDGE_RISING: | ||
88 | src_type = SUNXI_SRC_TYPE_EDGE_RISING; | ||
89 | break; | ||
90 | case IRQ_TYPE_LEVEL_HIGH: | ||
91 | src_type = SUNXI_SRC_TYPE_LEVEL_HIGH; | ||
92 | break; | ||
93 | case IRQ_TYPE_NONE: | ||
94 | case IRQ_TYPE_LEVEL_LOW: | ||
95 | src_type = SUNXI_SRC_TYPE_LEVEL_LOW; | ||
96 | break; | ||
97 | default: | ||
98 | irq_gc_unlock(gc); | ||
99 | pr_err("%s: Cannot assign multiple trigger modes to IRQ %d.\n", | ||
100 | __func__, data->irq); | ||
101 | return -EBADR; | ||
102 | } | ||
103 | |||
104 | irqd_set_trigger_type(data, flow_type); | ||
105 | irq_setup_alt_chip(data, flow_type); | ||
106 | |||
107 | for (i = 0; i <= gc->num_ct; i++, ct++) | ||
108 | if (ct->type & flow_type) | ||
109 | ctrl_off = ct->regs.type; | ||
110 | |||
111 | src_type_reg = sunxi_sc_nmi_read(gc, ctrl_off); | ||
112 | src_type_reg &= ~SUNXI_NMI_SRC_TYPE_MASK; | ||
113 | src_type_reg |= src_type; | ||
114 | sunxi_sc_nmi_write(gc, ctrl_off, src_type_reg); | ||
115 | |||
116 | irq_gc_unlock(gc); | ||
117 | |||
118 | return IRQ_SET_MASK_OK; | ||
119 | } | ||
120 | |||
121 | static int __init sunxi_sc_nmi_irq_init(struct device_node *node, | ||
122 | struct sunxi_sc_nmi_reg_offs *reg_offs) | ||
123 | { | ||
124 | struct irq_domain *domain; | ||
125 | struct irq_chip_generic *gc; | ||
126 | unsigned int irq; | ||
127 | unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; | ||
128 | int ret; | ||
129 | |||
130 | |||
131 | domain = irq_domain_add_linear(node, 1, &irq_generic_chip_ops, NULL); | ||
132 | if (!domain) { | ||
133 | pr_err("%s: Could not register interrupt domain.\n", node->name); | ||
134 | return -ENOMEM; | ||
135 | } | ||
136 | |||
137 | ret = irq_alloc_domain_generic_chips(domain, 1, 2, node->name, | ||
138 | handle_fasteoi_irq, clr, 0, | ||
139 | IRQ_GC_INIT_MASK_CACHE); | ||
140 | if (ret) { | ||
141 | pr_err("%s: Could not allocate generic interrupt chip.\n", | ||
142 | node->name); | ||
143 | goto fail_irqd_remove; | ||
144 | } | ||
145 | |||
146 | irq = irq_of_parse_and_map(node, 0); | ||
147 | if (irq <= 0) { | ||
148 | pr_err("%s: unable to parse irq\n", node->name); | ||
149 | ret = -EINVAL; | ||
150 | goto fail_irqd_remove; | ||
151 | } | ||
152 | |||
153 | gc = irq_get_domain_generic_chip(domain, 0); | ||
154 | gc->reg_base = of_iomap(node, 0); | ||
155 | if (!gc->reg_base) { | ||
156 | pr_err("%s: unable to map resource\n", node->name); | ||
157 | ret = -ENOMEM; | ||
158 | goto fail_irqd_remove; | ||
159 | } | ||
160 | |||
161 | gc->chip_types[0].type = IRQ_TYPE_LEVEL_MASK; | ||
162 | gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit; | ||
163 | gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit; | ||
164 | gc->chip_types[0].chip.irq_eoi = irq_gc_ack_set_bit; | ||
165 | gc->chip_types[0].chip.irq_set_type = sunxi_sc_nmi_set_type; | ||
166 | gc->chip_types[0].chip.flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED; | ||
167 | gc->chip_types[0].regs.ack = reg_offs->pend; | ||
168 | gc->chip_types[0].regs.mask = reg_offs->enable; | ||
169 | gc->chip_types[0].regs.type = reg_offs->ctrl; | ||
170 | |||
171 | gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH; | ||
172 | gc->chip_types[1].chip.name = gc->chip_types[0].chip.name; | ||
173 | gc->chip_types[1].chip.irq_ack = irq_gc_ack_set_bit; | ||
174 | gc->chip_types[1].chip.irq_mask = irq_gc_mask_clr_bit; | ||
175 | gc->chip_types[1].chip.irq_unmask = irq_gc_mask_set_bit; | ||
176 | gc->chip_types[1].chip.irq_set_type = sunxi_sc_nmi_set_type; | ||
177 | gc->chip_types[1].regs.ack = reg_offs->pend; | ||
178 | gc->chip_types[1].regs.mask = reg_offs->enable; | ||
179 | gc->chip_types[1].regs.type = reg_offs->ctrl; | ||
180 | gc->chip_types[1].handler = handle_edge_irq; | ||
181 | |||
182 | sunxi_sc_nmi_write(gc, reg_offs->enable, 0); | ||
183 | sunxi_sc_nmi_write(gc, reg_offs->pend, 0x1); | ||
184 | |||
185 | irq_set_handler_data(irq, domain); | ||
186 | irq_set_chained_handler(irq, sunxi_sc_nmi_handle_irq); | ||
187 | |||
188 | return 0; | ||
189 | |||
190 | fail_irqd_remove: | ||
191 | irq_domain_remove(domain); | ||
192 | |||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | static int __init sun6i_sc_nmi_irq_init(struct device_node *node, | ||
197 | struct device_node *parent) | ||
198 | { | ||
199 | return sunxi_sc_nmi_irq_init(node, &sun6i_reg_offs); | ||
200 | } | ||
201 | IRQCHIP_DECLARE(sun6i_sc_nmi, "allwinner,sun6i-a31-sc-nmi", sun6i_sc_nmi_irq_init); | ||
202 | |||
203 | static int __init sun7i_sc_nmi_irq_init(struct device_node *node, | ||
204 | struct device_node *parent) | ||
205 | { | ||
206 | return sunxi_sc_nmi_irq_init(node, &sun7i_reg_offs); | ||
207 | } | ||
208 | IRQCHIP_DECLARE(sun7i_sc_nmi, "allwinner,sun7i-a20-sc-nmi", sun7i_sc_nmi_irq_init); | ||
diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c index 8e21ae0bab46..473f09a74d4d 100644 --- a/drivers/irqchip/irq-vic.c +++ b/drivers/irqchip/irq-vic.c | |||
@@ -228,7 +228,7 @@ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs) | |||
228 | * Keep iterating over all registered VIC's until there are no pending | 228 | * Keep iterating over all registered VIC's until there are no pending |
229 | * interrupts. | 229 | * interrupts. |
230 | */ | 230 | */ |
231 | static asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs) | 231 | static void __exception_irq_entry vic_handle_irq(struct pt_regs *regs) |
232 | { | 232 | { |
233 | int i, handled; | 233 | int i, handled; |
234 | 234 | ||
diff --git a/drivers/irqchip/irq-vt8500.c b/drivers/irqchip/irq-vt8500.c index 1846e7d66681..eb6e91efdec8 100644 --- a/drivers/irqchip/irq-vt8500.c +++ b/drivers/irqchip/irq-vt8500.c | |||
@@ -178,8 +178,7 @@ static struct irq_domain_ops vt8500_irq_domain_ops = { | |||
178 | .xlate = irq_domain_xlate_onecell, | 178 | .xlate = irq_domain_xlate_onecell, |
179 | }; | 179 | }; |
180 | 180 | ||
181 | static asmlinkage | 181 | static void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs) |
182 | void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs) | ||
183 | { | 182 | { |
184 | u32 stat, i; | 183 | u32 stat, i; |
185 | int irqnr, virq; | 184 | int irqnr, virq; |
diff --git a/drivers/irqchip/irq-xtensa-mx.c b/drivers/irqchip/irq-xtensa-mx.c index f693f1bc1348..e1c2f9632893 100644 --- a/drivers/irqchip/irq-xtensa-mx.c +++ b/drivers/irqchip/irq-xtensa-mx.c | |||
@@ -122,7 +122,7 @@ static int xtensa_mx_irq_retrigger(struct irq_data *d) | |||
122 | static int xtensa_mx_irq_set_affinity(struct irq_data *d, | 122 | static int xtensa_mx_irq_set_affinity(struct irq_data *d, |
123 | const struct cpumask *dest, bool force) | 123 | const struct cpumask *dest, bool force) |
124 | { | 124 | { |
125 | unsigned mask = 1u << cpumask_any(dest); | 125 | unsigned mask = 1u << cpumask_any_and(dest, cpu_online_mask); |
126 | 126 | ||
127 | set_er(mask, MIROUT(d->hwirq - HW_IRQ_MX_BASE)); | 127 | set_er(mask, MIROUT(d->hwirq - HW_IRQ_MX_BASE)); |
128 | return 0; | 128 | return 0; |
diff --git a/drivers/irqchip/irq-zevio.c b/drivers/irqchip/irq-zevio.c index 8ed04c4a43ee..ceb3a4318f73 100644 --- a/drivers/irqchip/irq-zevio.c +++ b/drivers/irqchip/irq-zevio.c | |||
@@ -50,7 +50,7 @@ static void zevio_irq_ack(struct irq_data *irqd) | |||
50 | readl(gc->reg_base + regs->ack); | 50 | readl(gc->reg_base + regs->ack); |
51 | } | 51 | } |
52 | 52 | ||
53 | static asmlinkage void __exception_irq_entry zevio_handle_irq(struct pt_regs *regs) | 53 | static void __exception_irq_entry zevio_handle_irq(struct pt_regs *regs) |
54 | { | 54 | { |
55 | int irqnr; | 55 | int irqnr; |
56 | 56 | ||
diff --git a/drivers/irqchip/irqchip.c b/drivers/irqchip/irqchip.c index f496afce29de..cad3e2495552 100644 --- a/drivers/irqchip/irqchip.c +++ b/drivers/irqchip/irqchip.c | |||
@@ -10,8 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/of_irq.h> | 12 | #include <linux/of_irq.h> |
13 | 13 | #include <linux/irqchip.h> | |
14 | #include "irqchip.h" | ||
15 | 14 | ||
16 | /* | 15 | /* |
17 | * This special of_device_id is the sentinel at the end of the | 16 | * This special of_device_id is the sentinel at the end of the |
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 17ce88f79d2b..2e48ecf09e2c 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c | |||
@@ -294,14 +294,12 @@ no_valid_irq: | |||
294 | static void clear_irq(unsigned int irq) | 294 | static void clear_irq(unsigned int irq) |
295 | { | 295 | { |
296 | unsigned int pos, nvec; | 296 | unsigned int pos, nvec; |
297 | struct irq_desc *desc; | ||
298 | struct msi_desc *msi; | 297 | struct msi_desc *msi; |
299 | struct pcie_port *pp; | 298 | struct pcie_port *pp; |
300 | struct irq_data *data = irq_get_irq_data(irq); | 299 | struct irq_data *data = irq_get_irq_data(irq); |
301 | 300 | ||
302 | /* get the port structure */ | 301 | /* get the port structure */ |
303 | desc = irq_to_desc(irq); | 302 | msi = irq_data_get_msi(data); |
304 | msi = irq_desc_get_msi_desc(desc); | ||
305 | pp = sys_to_pcie(msi->dev->bus->sysdata); | 303 | pp = sys_to_pcie(msi->dev->bus->sysdata); |
306 | if (!pp) { | 304 | if (!pp) { |
307 | BUG(); | 305 | BUG(); |
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index d691e6a13aae..9e058c4657a3 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/device.h> | 18 | #include <linux/device.h> |
19 | #include <linux/kernel_stat.h> | 19 | #include <linux/kernel_stat.h> |
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/irq.h> | ||
21 | #include <asm/cio.h> | 22 | #include <asm/cio.h> |
22 | #include <asm/delay.h> | 23 | #include <asm/delay.h> |
23 | #include <asm/irq.h> | 24 | #include <asm/irq.h> |
@@ -584,8 +585,6 @@ static irqreturn_t do_cio_interrupt(int irq, void *dummy) | |||
584 | return IRQ_HANDLED; | 585 | return IRQ_HANDLED; |
585 | } | 586 | } |
586 | 587 | ||
587 | static struct irq_desc *irq_desc_io; | ||
588 | |||
589 | static struct irqaction io_interrupt = { | 588 | static struct irqaction io_interrupt = { |
590 | .name = "IO", | 589 | .name = "IO", |
591 | .handler = do_cio_interrupt, | 590 | .handler = do_cio_interrupt, |
@@ -596,7 +595,6 @@ void __init init_cio_interrupts(void) | |||
596 | irq_set_chip_and_handler(IO_INTERRUPT, | 595 | irq_set_chip_and_handler(IO_INTERRUPT, |
597 | &dummy_irq_chip, handle_percpu_irq); | 596 | &dummy_irq_chip, handle_percpu_irq); |
598 | setup_irq(IO_INTERRUPT, &io_interrupt); | 597 | setup_irq(IO_INTERRUPT, &io_interrupt); |
599 | irq_desc_io = irq_to_desc(IO_INTERRUPT); | ||
600 | } | 598 | } |
601 | 599 | ||
602 | #ifdef CONFIG_CCW_CONSOLE | 600 | #ifdef CONFIG_CCW_CONSOLE |
@@ -623,7 +621,7 @@ void cio_tsch(struct subchannel *sch) | |||
623 | local_bh_disable(); | 621 | local_bh_disable(); |
624 | irq_enter(); | 622 | irq_enter(); |
625 | } | 623 | } |
626 | kstat_incr_irqs_this_cpu(IO_INTERRUPT, irq_desc_io); | 624 | kstat_incr_irq_this_cpu(IO_INTERRUPT); |
627 | if (sch->driver && sch->driver->irq) | 625 | if (sch->driver && sch->driver->irq) |
628 | sch->driver->irq(sch); | 626 | sch->driver->irq(sch); |
629 | else | 627 | else |
diff --git a/drivers/xen/events/events_2l.c b/drivers/xen/events/events_2l.c index d7ff91757307..5db43fc100a4 100644 --- a/drivers/xen/events/events_2l.c +++ b/drivers/xen/events/events_2l.c | |||
@@ -166,7 +166,6 @@ static void evtchn_2l_handle_events(unsigned cpu) | |||
166 | int start_word_idx, start_bit_idx; | 166 | int start_word_idx, start_bit_idx; |
167 | int word_idx, bit_idx; | 167 | int word_idx, bit_idx; |
168 | int i; | 168 | int i; |
169 | struct irq_desc *desc; | ||
170 | struct shared_info *s = HYPERVISOR_shared_info; | 169 | struct shared_info *s = HYPERVISOR_shared_info; |
171 | struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu); | 170 | struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu); |
172 | 171 | ||
@@ -176,11 +175,8 @@ static void evtchn_2l_handle_events(unsigned cpu) | |||
176 | unsigned int evtchn = evtchn_from_irq(irq); | 175 | unsigned int evtchn = evtchn_from_irq(irq); |
177 | word_idx = evtchn / BITS_PER_LONG; | 176 | word_idx = evtchn / BITS_PER_LONG; |
178 | bit_idx = evtchn % BITS_PER_LONG; | 177 | bit_idx = evtchn % BITS_PER_LONG; |
179 | if (active_evtchns(cpu, s, word_idx) & (1ULL << bit_idx)) { | 178 | if (active_evtchns(cpu, s, word_idx) & (1ULL << bit_idx)) |
180 | desc = irq_to_desc(irq); | 179 | generic_handle_irq(irq); |
181 | if (desc) | ||
182 | generic_handle_irq_desc(irq, desc); | ||
183 | } | ||
184 | } | 180 | } |
185 | 181 | ||
186 | /* | 182 | /* |
@@ -245,11 +241,8 @@ static void evtchn_2l_handle_events(unsigned cpu) | |||
245 | port = (word_idx * BITS_PER_EVTCHN_WORD) + bit_idx; | 241 | port = (word_idx * BITS_PER_EVTCHN_WORD) + bit_idx; |
246 | irq = get_evtchn_to_irq(port); | 242 | irq = get_evtchn_to_irq(port); |
247 | 243 | ||
248 | if (irq != -1) { | 244 | if (irq != -1) |
249 | desc = irq_to_desc(irq); | 245 | generic_handle_irq(irq); |
250 | if (desc) | ||
251 | generic_handle_irq_desc(irq, desc); | ||
252 | } | ||
253 | 246 | ||
254 | bit_idx = (bit_idx + 1) % BITS_PER_EVTCHN_WORD; | 247 | bit_idx = (bit_idx + 1) % BITS_PER_EVTCHN_WORD; |
255 | 248 | ||
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index f4a9e3311297..c3458f58de90 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c | |||
@@ -336,9 +336,8 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) | |||
336 | 336 | ||
337 | BUG_ON(irq == -1); | 337 | BUG_ON(irq == -1); |
338 | #ifdef CONFIG_SMP | 338 | #ifdef CONFIG_SMP |
339 | cpumask_copy(irq_to_desc(irq)->irq_data.affinity, cpumask_of(cpu)); | 339 | cpumask_copy(irq_get_irq_data(irq)->affinity, cpumask_of(cpu)); |
340 | #endif | 340 | #endif |
341 | |||
342 | xen_evtchn_port_bind_to_cpu(info, cpu); | 341 | xen_evtchn_port_bind_to_cpu(info, cpu); |
343 | 342 | ||
344 | info->cpu = cpu; | 343 | info->cpu = cpu; |
@@ -373,10 +372,8 @@ static void xen_irq_init(unsigned irq) | |||
373 | { | 372 | { |
374 | struct irq_info *info; | 373 | struct irq_info *info; |
375 | #ifdef CONFIG_SMP | 374 | #ifdef CONFIG_SMP |
376 | struct irq_desc *desc = irq_to_desc(irq); | ||
377 | |||
378 | /* By default all event channels notify CPU#0. */ | 375 | /* By default all event channels notify CPU#0. */ |
379 | cpumask_copy(desc->irq_data.affinity, cpumask_of(0)); | 376 | cpumask_copy(irq_get_irq_data(irq)->affinity, cpumask_of(0)); |
380 | #endif | 377 | #endif |
381 | 378 | ||
382 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 379 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
@@ -490,13 +487,6 @@ static void pirq_query_unmask(int irq) | |||
490 | info->u.pirq.flags |= PIRQ_NEEDS_EOI; | 487 | info->u.pirq.flags |= PIRQ_NEEDS_EOI; |
491 | } | 488 | } |
492 | 489 | ||
493 | static bool probing_irq(int irq) | ||
494 | { | ||
495 | struct irq_desc *desc = irq_to_desc(irq); | ||
496 | |||
497 | return desc && desc->action == NULL; | ||
498 | } | ||
499 | |||
500 | static void eoi_pirq(struct irq_data *data) | 490 | static void eoi_pirq(struct irq_data *data) |
501 | { | 491 | { |
502 | int evtchn = evtchn_from_irq(data->irq); | 492 | int evtchn = evtchn_from_irq(data->irq); |
@@ -538,8 +528,7 @@ static unsigned int __startup_pirq(unsigned int irq) | |||
538 | BIND_PIRQ__WILL_SHARE : 0; | 528 | BIND_PIRQ__WILL_SHARE : 0; |
539 | rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq); | 529 | rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq); |
540 | if (rc != 0) { | 530 | if (rc != 0) { |
541 | if (!probing_irq(irq)) | 531 | pr_warn("Failed to obtain physical IRQ %d\n", irq); |
542 | pr_info("Failed to obtain physical IRQ %d\n", irq); | ||
543 | return 0; | 532 | return 0; |
544 | } | 533 | } |
545 | evtchn = bind_pirq.port; | 534 | evtchn = bind_pirq.port; |
@@ -772,17 +761,12 @@ error_irq: | |||
772 | 761 | ||
773 | int xen_destroy_irq(int irq) | 762 | int xen_destroy_irq(int irq) |
774 | { | 763 | { |
775 | struct irq_desc *desc; | ||
776 | struct physdev_unmap_pirq unmap_irq; | 764 | struct physdev_unmap_pirq unmap_irq; |
777 | struct irq_info *info = info_for_irq(irq); | 765 | struct irq_info *info = info_for_irq(irq); |
778 | int rc = -ENOENT; | 766 | int rc = -ENOENT; |
779 | 767 | ||
780 | mutex_lock(&irq_mapping_update_lock); | 768 | mutex_lock(&irq_mapping_update_lock); |
781 | 769 | ||
782 | desc = irq_to_desc(irq); | ||
783 | if (!desc) | ||
784 | goto out; | ||
785 | |||
786 | if (xen_initial_domain()) { | 770 | if (xen_initial_domain()) { |
787 | unmap_irq.pirq = info->u.pirq.pirq; | 771 | unmap_irq.pirq = info->u.pirq.pirq; |
788 | unmap_irq.domid = info->u.pirq.domid; | 772 | unmap_irq.domid = info->u.pirq.domid; |
@@ -1251,6 +1235,7 @@ void xen_evtchn_do_upcall(struct pt_regs *regs) | |||
1251 | #ifdef CONFIG_X86 | 1235 | #ifdef CONFIG_X86 |
1252 | exit_idle(); | 1236 | exit_idle(); |
1253 | #endif | 1237 | #endif |
1238 | inc_irq_stat(irq_hv_callback_count); | ||
1254 | 1239 | ||
1255 | __xen_evtchn_do_upcall(); | 1240 | __xen_evtchn_do_upcall(); |
1256 | 1241 | ||
@@ -1339,7 +1324,7 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu) | |||
1339 | static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest, | 1324 | static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest, |
1340 | bool force) | 1325 | bool force) |
1341 | { | 1326 | { |
1342 | unsigned tcpu = cpumask_first(dest); | 1327 | unsigned tcpu = cpumask_first_and(dest, cpu_online_mask); |
1343 | 1328 | ||
1344 | return rebind_irq_to_cpu(data->irq, tcpu); | 1329 | return rebind_irq_to_cpu(data->irq, tcpu); |
1345 | } | 1330 | } |
diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c index 1de2a191b395..96109a9972b6 100644 --- a/drivers/xen/events/events_fifo.c +++ b/drivers/xen/events/events_fifo.c | |||
@@ -235,14 +235,10 @@ static uint32_t clear_linked(volatile event_word_t *word) | |||
235 | static void handle_irq_for_port(unsigned port) | 235 | static void handle_irq_for_port(unsigned port) |
236 | { | 236 | { |
237 | int irq; | 237 | int irq; |
238 | struct irq_desc *desc; | ||
239 | 238 | ||
240 | irq = get_evtchn_to_irq(port); | 239 | irq = get_evtchn_to_irq(port); |
241 | if (irq != -1) { | 240 | if (irq != -1) |
242 | desc = irq_to_desc(irq); | 241 | generic_handle_irq(irq); |
243 | if (desc) | ||
244 | generic_handle_irq_desc(irq, desc); | ||
245 | } | ||
246 | } | 242 | } |
247 | 243 | ||
248 | static void consume_one_event(unsigned cpu, | 244 | static void consume_one_event(unsigned cpu, |
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index 12d5f972f23f..cba442ec3c66 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | 10 | ||
11 | extern void synchronize_irq(unsigned int irq); | 11 | extern void synchronize_irq(unsigned int irq); |
12 | extern void synchronize_hardirq(unsigned int irq); | ||
12 | 13 | ||
13 | #if defined(CONFIG_TINY_RCU) | 14 | #if defined(CONFIG_TINY_RCU) |
14 | 15 | ||
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index a2678d35b5a2..c7bfac1c4a7b 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h | |||
@@ -188,6 +188,7 @@ extern void disable_irq(unsigned int irq); | |||
188 | extern void disable_percpu_irq(unsigned int irq); | 188 | extern void disable_percpu_irq(unsigned int irq); |
189 | extern void enable_irq(unsigned int irq); | 189 | extern void enable_irq(unsigned int irq); |
190 | extern void enable_percpu_irq(unsigned int irq, unsigned int type); | 190 | extern void enable_percpu_irq(unsigned int irq, unsigned int type); |
191 | extern void irq_wake_thread(unsigned int irq, void *dev_id); | ||
191 | 192 | ||
192 | /* The following three functions are for the core kernel use only. */ | 193 | /* The following three functions are for the core kernel use only. */ |
193 | extern void suspend_device_irqs(void); | 194 | extern void suspend_device_irqs(void); |
diff --git a/include/linux/irq.h b/include/linux/irq.h index 7dc10036eff5..d278838908cb 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -303,6 +303,10 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d) | |||
303 | * @irq_pm_shutdown: function called from core code on shutdown once per chip | 303 | * @irq_pm_shutdown: function called from core code on shutdown once per chip |
304 | * @irq_calc_mask: Optional function to set irq_data.mask for special cases | 304 | * @irq_calc_mask: Optional function to set irq_data.mask for special cases |
305 | * @irq_print_chip: optional to print special chip info in show_interrupts | 305 | * @irq_print_chip: optional to print special chip info in show_interrupts |
306 | * @irq_request_resources: optional to request resources before calling | ||
307 | * any other callback related to this irq | ||
308 | * @irq_release_resources: optional to release resources acquired with | ||
309 | * irq_request_resources | ||
306 | * @flags: chip specific flags | 310 | * @flags: chip specific flags |
307 | */ | 311 | */ |
308 | struct irq_chip { | 312 | struct irq_chip { |
@@ -336,6 +340,8 @@ struct irq_chip { | |||
336 | void (*irq_calc_mask)(struct irq_data *data); | 340 | void (*irq_calc_mask)(struct irq_data *data); |
337 | 341 | ||
338 | void (*irq_print_chip)(struct irq_data *data, struct seq_file *p); | 342 | void (*irq_print_chip)(struct irq_data *data, struct seq_file *p); |
343 | int (*irq_request_resources)(struct irq_data *data); | ||
344 | void (*irq_release_resources)(struct irq_data *data); | ||
339 | 345 | ||
340 | unsigned long flags; | 346 | unsigned long flags; |
341 | }; | 347 | }; |
@@ -349,6 +355,8 @@ struct irq_chip { | |||
349 | * IRQCHIP_ONOFFLINE_ENABLED: Only call irq_on/off_line callbacks | 355 | * IRQCHIP_ONOFFLINE_ENABLED: Only call irq_on/off_line callbacks |
350 | * when irq enabled | 356 | * when irq enabled |
351 | * IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip | 357 | * IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip |
358 | * IRQCHIP_ONESHOT_SAFE: One shot does not require mask/unmask | ||
359 | * IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode | ||
352 | */ | 360 | */ |
353 | enum { | 361 | enum { |
354 | IRQCHIP_SET_TYPE_MASKED = (1 << 0), | 362 | IRQCHIP_SET_TYPE_MASKED = (1 << 0), |
@@ -357,6 +365,7 @@ enum { | |||
357 | IRQCHIP_ONOFFLINE_ENABLED = (1 << 3), | 365 | IRQCHIP_ONOFFLINE_ENABLED = (1 << 3), |
358 | IRQCHIP_SKIP_SET_WAKE = (1 << 4), | 366 | IRQCHIP_SKIP_SET_WAKE = (1 << 4), |
359 | IRQCHIP_ONESHOT_SAFE = (1 << 5), | 367 | IRQCHIP_ONESHOT_SAFE = (1 << 5), |
368 | IRQCHIP_EOI_THREADED = (1 << 6), | ||
360 | }; | 369 | }; |
361 | 370 | ||
362 | /* This include will go away once we isolated irq_desc usage to core code */ | 371 | /* This include will go away once we isolated irq_desc usage to core code */ |
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index d7c61317db86..ecbc52f9ff77 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h | |||
@@ -51,14 +51,8 @@ DECLARE_PER_CPU(struct kernel_cpustat, kernel_cpustat); | |||
51 | 51 | ||
52 | extern unsigned long long nr_context_switches(void); | 52 | extern unsigned long long nr_context_switches(void); |
53 | 53 | ||
54 | #include <linux/irq.h> | ||
55 | extern unsigned int kstat_irqs_cpu(unsigned int irq, int cpu); | 54 | extern unsigned int kstat_irqs_cpu(unsigned int irq, int cpu); |
56 | 55 | extern void kstat_incr_irq_this_cpu(unsigned int irq); | |
57 | #define kstat_incr_irqs_this_cpu(irqno, DESC) \ | ||
58 | do { \ | ||
59 | __this_cpu_inc(*(DESC)->kstat_irqs); \ | ||
60 | __this_cpu_inc(kstat.irqs_sum); \ | ||
61 | } while (0) | ||
62 | 56 | ||
63 | static inline void kstat_incr_softirqs_this_cpu(unsigned int irq) | 57 | static inline void kstat_incr_softirqs_this_cpu(unsigned int irq) |
64 | { | 58 | { |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index dc04c166c54d..6397df2d6945 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -281,6 +281,19 @@ void unmask_irq(struct irq_desc *desc) | |||
281 | } | 281 | } |
282 | } | 282 | } |
283 | 283 | ||
284 | void unmask_threaded_irq(struct irq_desc *desc) | ||
285 | { | ||
286 | struct irq_chip *chip = desc->irq_data.chip; | ||
287 | |||
288 | if (chip->flags & IRQCHIP_EOI_THREADED) | ||
289 | chip->irq_eoi(&desc->irq_data); | ||
290 | |||
291 | if (chip->irq_unmask) { | ||
292 | chip->irq_unmask(&desc->irq_data); | ||
293 | irq_state_clr_masked(desc); | ||
294 | } | ||
295 | } | ||
296 | |||
284 | /* | 297 | /* |
285 | * handle_nested_irq - Handle a nested irq from a irq thread | 298 | * handle_nested_irq - Handle a nested irq from a irq thread |
286 | * @irq: the interrupt number | 299 | * @irq: the interrupt number |
@@ -435,6 +448,27 @@ static inline void preflow_handler(struct irq_desc *desc) | |||
435 | static inline void preflow_handler(struct irq_desc *desc) { } | 448 | static inline void preflow_handler(struct irq_desc *desc) { } |
436 | #endif | 449 | #endif |
437 | 450 | ||
451 | static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip) | ||
452 | { | ||
453 | if (!(desc->istate & IRQS_ONESHOT)) { | ||
454 | chip->irq_eoi(&desc->irq_data); | ||
455 | return; | ||
456 | } | ||
457 | /* | ||
458 | * We need to unmask in the following cases: | ||
459 | * - Oneshot irq which did not wake the thread (caused by a | ||
460 | * spurious interrupt or a primary handler handling it | ||
461 | * completely). | ||
462 | */ | ||
463 | if (!irqd_irq_disabled(&desc->irq_data) && | ||
464 | irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot) { | ||
465 | chip->irq_eoi(&desc->irq_data); | ||
466 | unmask_irq(desc); | ||
467 | } else if (!(chip->flags & IRQCHIP_EOI_THREADED)) { | ||
468 | chip->irq_eoi(&desc->irq_data); | ||
469 | } | ||
470 | } | ||
471 | |||
438 | /** | 472 | /** |
439 | * handle_fasteoi_irq - irq handler for transparent controllers | 473 | * handle_fasteoi_irq - irq handler for transparent controllers |
440 | * @irq: the interrupt number | 474 | * @irq: the interrupt number |
@@ -448,6 +482,8 @@ static inline void preflow_handler(struct irq_desc *desc) { } | |||
448 | void | 482 | void |
449 | handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | 483 | handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) |
450 | { | 484 | { |
485 | struct irq_chip *chip = desc->irq_data.chip; | ||
486 | |||
451 | raw_spin_lock(&desc->lock); | 487 | raw_spin_lock(&desc->lock); |
452 | 488 | ||
453 | if (unlikely(irqd_irq_inprogress(&desc->irq_data))) | 489 | if (unlikely(irqd_irq_inprogress(&desc->irq_data))) |
@@ -473,18 +509,14 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | |||
473 | preflow_handler(desc); | 509 | preflow_handler(desc); |
474 | handle_irq_event(desc); | 510 | handle_irq_event(desc); |
475 | 511 | ||
476 | if (desc->istate & IRQS_ONESHOT) | 512 | cond_unmask_eoi_irq(desc, chip); |
477 | cond_unmask_irq(desc); | ||
478 | 513 | ||
479 | out_eoi: | ||
480 | desc->irq_data.chip->irq_eoi(&desc->irq_data); | ||
481 | out_unlock: | ||
482 | raw_spin_unlock(&desc->lock); | 514 | raw_spin_unlock(&desc->lock); |
483 | return; | 515 | return; |
484 | out: | 516 | out: |
485 | if (!(desc->irq_data.chip->flags & IRQCHIP_EOI_IF_HANDLED)) | 517 | if (!(chip->flags & IRQCHIP_EOI_IF_HANDLED)) |
486 | goto out_eoi; | 518 | chip->irq_eoi(&desc->irq_data); |
487 | goto out_unlock; | 519 | raw_spin_unlock(&desc->lock); |
488 | } | 520 | } |
489 | 521 | ||
490 | /** | 522 | /** |
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 131ca176b497..635480270858 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c | |||
@@ -41,6 +41,7 @@ irqreturn_t no_action(int cpl, void *dev_id) | |||
41 | { | 41 | { |
42 | return IRQ_NONE; | 42 | return IRQ_NONE; |
43 | } | 43 | } |
44 | EXPORT_SYMBOL_GPL(no_action); | ||
44 | 45 | ||
45 | static void warn_no_thread(unsigned int irq, struct irqaction *action) | 46 | static void warn_no_thread(unsigned int irq, struct irqaction *action) |
46 | { | 47 | { |
@@ -51,7 +52,7 @@ static void warn_no_thread(unsigned int irq, struct irqaction *action) | |||
51 | "but no thread function available.", irq, action->name); | 52 | "but no thread function available.", irq, action->name); |
52 | } | 53 | } |
53 | 54 | ||
54 | static void irq_wake_thread(struct irq_desc *desc, struct irqaction *action) | 55 | void __irq_wake_thread(struct irq_desc *desc, struct irqaction *action) |
55 | { | 56 | { |
56 | /* | 57 | /* |
57 | * In case the thread crashed and was killed we just pretend that | 58 | * In case the thread crashed and was killed we just pretend that |
@@ -157,7 +158,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) | |||
157 | break; | 158 | break; |
158 | } | 159 | } |
159 | 160 | ||
160 | irq_wake_thread(desc, action); | 161 | __irq_wake_thread(desc, action); |
161 | 162 | ||
162 | /* Fall through to add to randomness */ | 163 | /* Fall through to add to randomness */ |
163 | case IRQ_HANDLED: | 164 | case IRQ_HANDLED: |
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index 001fa5bab490..ddf1ffeb79f1 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h | |||
@@ -6,6 +6,7 @@ | |||
6 | * of this file for your non core code. | 6 | * of this file for your non core code. |
7 | */ | 7 | */ |
8 | #include <linux/irqdesc.h> | 8 | #include <linux/irqdesc.h> |
9 | #include <linux/kernel_stat.h> | ||
9 | 10 | ||
10 | #ifdef CONFIG_SPARSE_IRQ | 11 | #ifdef CONFIG_SPARSE_IRQ |
11 | # define IRQ_BITMAP_BITS (NR_IRQS + 8196) | 12 | # define IRQ_BITMAP_BITS (NR_IRQS + 8196) |
@@ -73,6 +74,7 @@ extern void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu); | |||
73 | extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu); | 74 | extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu); |
74 | extern void mask_irq(struct irq_desc *desc); | 75 | extern void mask_irq(struct irq_desc *desc); |
75 | extern void unmask_irq(struct irq_desc *desc); | 76 | extern void unmask_irq(struct irq_desc *desc); |
77 | extern void unmask_threaded_irq(struct irq_desc *desc); | ||
76 | 78 | ||
77 | extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr); | 79 | extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr); |
78 | 80 | ||
@@ -82,6 +84,7 @@ irqreturn_t handle_irq_event(struct irq_desc *desc); | |||
82 | /* Resending of interrupts :*/ | 84 | /* Resending of interrupts :*/ |
83 | void check_irq_resend(struct irq_desc *desc, unsigned int irq); | 85 | void check_irq_resend(struct irq_desc *desc, unsigned int irq); |
84 | bool irq_wait_for_poll(struct irq_desc *desc); | 86 | bool irq_wait_for_poll(struct irq_desc *desc); |
87 | void __irq_wake_thread(struct irq_desc *desc, struct irqaction *action); | ||
85 | 88 | ||
86 | #ifdef CONFIG_PROC_FS | 89 | #ifdef CONFIG_PROC_FS |
87 | extern void register_irq_proc(unsigned int irq, struct irq_desc *desc); | 90 | extern void register_irq_proc(unsigned int irq, struct irq_desc *desc); |
@@ -179,3 +182,9 @@ static inline bool irqd_has_set(struct irq_data *d, unsigned int mask) | |||
179 | { | 182 | { |
180 | return d->state_use_accessors & mask; | 183 | return d->state_use_accessors & mask; |
181 | } | 184 | } |
185 | |||
186 | static inline void kstat_incr_irqs_this_cpu(unsigned int irq, struct irq_desc *desc) | ||
187 | { | ||
188 | __this_cpu_inc(*desc->kstat_irqs); | ||
189 | __this_cpu_inc(kstat.irqs_sum); | ||
190 | } | ||
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 8ab8e9390297..a7174617616b 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c | |||
@@ -489,6 +489,11 @@ void dynamic_irq_cleanup(unsigned int irq) | |||
489 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 489 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
490 | } | 490 | } |
491 | 491 | ||
492 | void kstat_incr_irq_this_cpu(unsigned int irq) | ||
493 | { | ||
494 | kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); | ||
495 | } | ||
496 | |||
492 | unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) | 497 | unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) |
493 | { | 498 | { |
494 | struct irq_desc *desc = irq_to_desc(irq); | 499 | struct irq_desc *desc = irq_to_desc(irq); |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index d3bf660cb57f..2486a4c1a710 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -32,24 +32,10 @@ static int __init setup_forced_irqthreads(char *arg) | |||
32 | early_param("threadirqs", setup_forced_irqthreads); | 32 | early_param("threadirqs", setup_forced_irqthreads); |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | /** | 35 | static void __synchronize_hardirq(struct irq_desc *desc) |
36 | * synchronize_irq - wait for pending IRQ handlers (on other CPUs) | ||
37 | * @irq: interrupt number to wait for | ||
38 | * | ||
39 | * This function waits for any pending IRQ handlers for this interrupt | ||
40 | * to complete before returning. If you use this function while | ||
41 | * holding a resource the IRQ handler may need you will deadlock. | ||
42 | * | ||
43 | * This function may be called - with care - from IRQ context. | ||
44 | */ | ||
45 | void synchronize_irq(unsigned int irq) | ||
46 | { | 36 | { |
47 | struct irq_desc *desc = irq_to_desc(irq); | ||
48 | bool inprogress; | 37 | bool inprogress; |
49 | 38 | ||
50 | if (!desc) | ||
51 | return; | ||
52 | |||
53 | do { | 39 | do { |
54 | unsigned long flags; | 40 | unsigned long flags; |
55 | 41 | ||
@@ -67,12 +53,56 @@ void synchronize_irq(unsigned int irq) | |||
67 | 53 | ||
68 | /* Oops, that failed? */ | 54 | /* Oops, that failed? */ |
69 | } while (inprogress); | 55 | } while (inprogress); |
56 | } | ||
70 | 57 | ||
71 | /* | 58 | /** |
72 | * We made sure that no hardirq handler is running. Now verify | 59 | * synchronize_hardirq - wait for pending hard IRQ handlers (on other CPUs) |
73 | * that no threaded handlers are active. | 60 | * @irq: interrupt number to wait for |
74 | */ | 61 | * |
75 | wait_event(desc->wait_for_threads, !atomic_read(&desc->threads_active)); | 62 | * This function waits for any pending hard IRQ handlers for this |
63 | * interrupt to complete before returning. If you use this | ||
64 | * function while holding a resource the IRQ handler may need you | ||
65 | * will deadlock. It does not take associated threaded handlers | ||
66 | * into account. | ||
67 | * | ||
68 | * Do not use this for shutdown scenarios where you must be sure | ||
69 | * that all parts (hardirq and threaded handler) have completed. | ||
70 | * | ||
71 | * This function may be called - with care - from IRQ context. | ||
72 | */ | ||
73 | void synchronize_hardirq(unsigned int irq) | ||
74 | { | ||
75 | struct irq_desc *desc = irq_to_desc(irq); | ||
76 | |||
77 | if (desc) | ||
78 | __synchronize_hardirq(desc); | ||
79 | } | ||
80 | EXPORT_SYMBOL(synchronize_hardirq); | ||
81 | |||
82 | /** | ||
83 | * synchronize_irq - wait for pending IRQ handlers (on other CPUs) | ||
84 | * @irq: interrupt number to wait for | ||
85 | * | ||
86 | * This function waits for any pending IRQ handlers for this interrupt | ||
87 | * to complete before returning. If you use this function while | ||
88 | * holding a resource the IRQ handler may need you will deadlock. | ||
89 | * | ||
90 | * This function may be called - with care - from IRQ context. | ||
91 | */ | ||
92 | void synchronize_irq(unsigned int irq) | ||
93 | { | ||
94 | struct irq_desc *desc = irq_to_desc(irq); | ||
95 | |||
96 | if (desc) { | ||
97 | __synchronize_hardirq(desc); | ||
98 | /* | ||
99 | * We made sure that no hardirq handler is | ||
100 | * running. Now verify that no threaded handlers are | ||
101 | * active. | ||
102 | */ | ||
103 | wait_event(desc->wait_for_threads, | ||
104 | !atomic_read(&desc->threads_active)); | ||
105 | } | ||
76 | } | 106 | } |
77 | EXPORT_SYMBOL(synchronize_irq); | 107 | EXPORT_SYMBOL(synchronize_irq); |
78 | 108 | ||
@@ -718,7 +748,7 @@ again: | |||
718 | 748 | ||
719 | if (!desc->threads_oneshot && !irqd_irq_disabled(&desc->irq_data) && | 749 | if (!desc->threads_oneshot && !irqd_irq_disabled(&desc->irq_data) && |
720 | irqd_irq_masked(&desc->irq_data)) | 750 | irqd_irq_masked(&desc->irq_data)) |
721 | unmask_irq(desc); | 751 | unmask_threaded_irq(desc); |
722 | 752 | ||
723 | out_unlock: | 753 | out_unlock: |
724 | raw_spin_unlock_irq(&desc->lock); | 754 | raw_spin_unlock_irq(&desc->lock); |
@@ -727,7 +757,7 @@ out_unlock: | |||
727 | 757 | ||
728 | #ifdef CONFIG_SMP | 758 | #ifdef CONFIG_SMP |
729 | /* | 759 | /* |
730 | * Check whether we need to chasnge the affinity of the interrupt thread. | 760 | * Check whether we need to change the affinity of the interrupt thread. |
731 | */ | 761 | */ |
732 | static void | 762 | static void |
733 | irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) | 763 | irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) |
@@ -880,6 +910,33 @@ static int irq_thread(void *data) | |||
880 | return 0; | 910 | return 0; |
881 | } | 911 | } |
882 | 912 | ||
913 | /** | ||
914 | * irq_wake_thread - wake the irq thread for the action identified by dev_id | ||
915 | * @irq: Interrupt line | ||
916 | * @dev_id: Device identity for which the thread should be woken | ||
917 | * | ||
918 | */ | ||
919 | void irq_wake_thread(unsigned int irq, void *dev_id) | ||
920 | { | ||
921 | struct irq_desc *desc = irq_to_desc(irq); | ||
922 | struct irqaction *action; | ||
923 | unsigned long flags; | ||
924 | |||
925 | if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc))) | ||
926 | return; | ||
927 | |||
928 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
929 | for (action = desc->action; action; action = action->next) { | ||
930 | if (action->dev_id == dev_id) { | ||
931 | if (action->thread) | ||
932 | __irq_wake_thread(desc, action); | ||
933 | break; | ||
934 | } | ||
935 | } | ||
936 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
937 | } | ||
938 | EXPORT_SYMBOL_GPL(irq_wake_thread); | ||
939 | |||
883 | static void irq_setup_forced_threading(struct irqaction *new) | 940 | static void irq_setup_forced_threading(struct irqaction *new) |
884 | { | 941 | { |
885 | if (!force_irqthreads) | 942 | if (!force_irqthreads) |
@@ -896,6 +953,23 @@ static void irq_setup_forced_threading(struct irqaction *new) | |||
896 | } | 953 | } |
897 | } | 954 | } |
898 | 955 | ||
956 | static int irq_request_resources(struct irq_desc *desc) | ||
957 | { | ||
958 | struct irq_data *d = &desc->irq_data; | ||
959 | struct irq_chip *c = d->chip; | ||
960 | |||
961 | return c->irq_request_resources ? c->irq_request_resources(d) : 0; | ||
962 | } | ||
963 | |||
964 | static void irq_release_resources(struct irq_desc *desc) | ||
965 | { | ||
966 | struct irq_data *d = &desc->irq_data; | ||
967 | struct irq_chip *c = d->chip; | ||
968 | |||
969 | if (c->irq_release_resources) | ||
970 | c->irq_release_resources(d); | ||
971 | } | ||
972 | |||
899 | /* | 973 | /* |
900 | * Internal function to register an irqaction - typically used to | 974 | * Internal function to register an irqaction - typically used to |
901 | * allocate special interrupts that are part of the architecture. | 975 | * allocate special interrupts that are part of the architecture. |
@@ -1091,6 +1165,13 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
1091 | } | 1165 | } |
1092 | 1166 | ||
1093 | if (!shared) { | 1167 | if (!shared) { |
1168 | ret = irq_request_resources(desc); | ||
1169 | if (ret) { | ||
1170 | pr_err("Failed to request resources for %s (irq %d) on irqchip %s\n", | ||
1171 | new->name, irq, desc->irq_data.chip->name); | ||
1172 | goto out_mask; | ||
1173 | } | ||
1174 | |||
1094 | init_waitqueue_head(&desc->wait_for_threads); | 1175 | init_waitqueue_head(&desc->wait_for_threads); |
1095 | 1176 | ||
1096 | /* Setup the type (level, edge polarity) if configured: */ | 1177 | /* Setup the type (level, edge polarity) if configured: */ |
@@ -1261,8 +1342,10 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id) | |||
1261 | *action_ptr = action->next; | 1342 | *action_ptr = action->next; |
1262 | 1343 | ||
1263 | /* If this was the last handler, shut down the IRQ line: */ | 1344 | /* If this was the last handler, shut down the IRQ line: */ |
1264 | if (!desc->action) | 1345 | if (!desc->action) { |
1265 | irq_shutdown(desc); | 1346 | irq_shutdown(desc); |
1347 | irq_release_resources(desc); | ||
1348 | } | ||
1266 | 1349 | ||
1267 | #ifdef CONFIG_SMP | 1350 | #ifdef CONFIG_SMP |
1268 | /* make sure affinity_hint is cleaned up */ | 1351 | /* make sure affinity_hint is cleaned up */ |
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index 36f6ee181b0c..ac1ba2f11032 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c | |||
@@ -324,15 +324,15 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc) | |||
324 | 324 | ||
325 | #ifdef CONFIG_SMP | 325 | #ifdef CONFIG_SMP |
326 | /* create /proc/irq/<irq>/smp_affinity */ | 326 | /* create /proc/irq/<irq>/smp_affinity */ |
327 | proc_create_data("smp_affinity", 0600, desc->dir, | 327 | proc_create_data("smp_affinity", 0644, desc->dir, |
328 | &irq_affinity_proc_fops, (void *)(long)irq); | 328 | &irq_affinity_proc_fops, (void *)(long)irq); |
329 | 329 | ||
330 | /* create /proc/irq/<irq>/affinity_hint */ | 330 | /* create /proc/irq/<irq>/affinity_hint */ |
331 | proc_create_data("affinity_hint", 0400, desc->dir, | 331 | proc_create_data("affinity_hint", 0444, desc->dir, |
332 | &irq_affinity_hint_proc_fops, (void *)(long)irq); | 332 | &irq_affinity_hint_proc_fops, (void *)(long)irq); |
333 | 333 | ||
334 | /* create /proc/irq/<irq>/smp_affinity_list */ | 334 | /* create /proc/irq/<irq>/smp_affinity_list */ |
335 | proc_create_data("smp_affinity_list", 0600, desc->dir, | 335 | proc_create_data("smp_affinity_list", 0644, desc->dir, |
336 | &irq_affinity_list_proc_fops, (void *)(long)irq); | 336 | &irq_affinity_list_proc_fops, (void *)(long)irq); |
337 | 337 | ||
338 | proc_create_data("node", 0444, desc->dir, | 338 | proc_create_data("node", 0444, desc->dir, |
@@ -372,7 +372,7 @@ void unregister_handler_proc(unsigned int irq, struct irqaction *action) | |||
372 | static void register_default_affinity_proc(void) | 372 | static void register_default_affinity_proc(void) |
373 | { | 373 | { |
374 | #ifdef CONFIG_SMP | 374 | #ifdef CONFIG_SMP |
375 | proc_create("irq/default_smp_affinity", 0600, NULL, | 375 | proc_create("irq/default_smp_affinity", 0644, NULL, |
376 | &default_affinity_proc_fops); | 376 | &default_affinity_proc_fops); |
377 | #endif | 377 | #endif |
378 | } | 378 | } |
diff --git a/kernel/softirq.c b/kernel/softirq.c index 490fcbb1dc5b..b50990a5bea0 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/smp.h> | 25 | #include <linux/smp.h> |
26 | #include <linux/smpboot.h> | 26 | #include <linux/smpboot.h> |
27 | #include <linux/tick.h> | 27 | #include <linux/tick.h> |
28 | #include <linux/irq.h> | ||
28 | 29 | ||
29 | #define CREATE_TRACE_POINTS | 30 | #define CREATE_TRACE_POINTS |
30 | #include <trace/events/irq.h> | 31 | #include <trace/events/irq.h> |