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> |
