Commit 683b6c6f authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 1ead6581 1b422ecd
Marvell Armada 370 and Armada XP Interrupt Controller Marvell Armada 370, 375, 38x, XP Interrupt Controller
----------------------------------------------------- -----------------------------------------------------
Required properties: Required properties:
...@@ -16,7 +16,13 @@ Required properties: ...@@ -16,7 +16,13 @@ Required properties:
automatically map to the interrupt controller registers of the automatically map to the interrupt controller registers of the
current CPU) current CPU)
Optional properties:
- interrupts: If defined, then it indicates that this MPIC is
connected as a slave to another interrupt controller. This is
typically the case on Armada 375 and Armada 38x, where the MPIC is
connected as a slave to the Cortex-A9 GIC. The provided interrupt
indicate to which GIC interrupt the MPIC output is connected.
Example: Example:
......
...@@ -2,7 +2,7 @@ Allwinner Sunxi Interrupt Controller ...@@ -2,7 +2,7 @@ Allwinner Sunxi Interrupt Controller
Required properties: Required properties:
- compatible : should be "allwinner,sun4i-ic" - compatible : should be "allwinner,sun4i-a10-ic"
- reg : Specifies base physical address and size of the registers. - reg : Specifies base physical address and size of the registers.
- interrupt-controller : Identifies the node as an interrupt controller - interrupt-controller : Identifies the node as an interrupt controller
- #interrupt-cells : Specifies the number of cells needed to encode an - #interrupt-cells : Specifies the number of cells needed to encode an
...@@ -11,7 +11,7 @@ Required properties: ...@@ -11,7 +11,7 @@ Required properties:
Example: Example:
intc: interrupt-controller { intc: interrupt-controller {
compatible = "allwinner,sun4i-ic"; compatible = "allwinner,sun4i-a10-ic";
reg = <0x01c20400 0x400>; reg = <0x01c20400 0x400>;
interrupt-controller; interrupt-controller;
#interrupt-cells = <1>; #interrupt-cells = <1>;
......
Allwinner Sunxi NMI Controller
==============================
Required properties:
- compatible : should be "allwinner,sun7i-a20-sc-nmi" or
"allwinner,sun6i-a31-sc-nmi"
- reg : Specifies base physical address and size of the registers.
- interrupt-controller : Identifies the node as an interrupt controller
- #interrupt-cells : Specifies the number of cells needed to encode an
interrupt source. The value shall be 2. The first cell is the IRQ number, the
second cell the trigger type as defined in interrupt.txt in this directory.
- interrupt-parent: Specifies the parent interrupt controller.
- interrupts: Specifies the interrupt line (NMI) which is handled by
the interrupt controller in the parent controller's notation. This value
shall be the NMI.
Example:
sc-nmi-intc@01c00030 {
compatible = "allwinner,sun7i-a20-sc-nmi";
interrupt-controller;
#interrupt-cells = <2>;
reg = <0x01c00030 0x0c>;
interrupt-parent = <&gic>;
interrupts = <0 0 4>;
};
...@@ -331,7 +331,7 @@ mdio@01c0b080 { ...@@ -331,7 +331,7 @@ mdio@01c0b080 {
}; };
intc: interrupt-controller@01c20400 { intc: interrupt-controller@01c20400 {
compatible = "allwinner,sun4i-ic"; compatible = "allwinner,sun4i-a10-ic";
reg = <0x01c20400 0x400>; reg = <0x01c20400 0x400>;
interrupt-controller; interrupt-controller;
#interrupt-cells = <1>; #interrupt-cells = <1>;
......
...@@ -294,7 +294,7 @@ mdio@01c0b080 { ...@@ -294,7 +294,7 @@ mdio@01c0b080 {
}; };
intc: interrupt-controller@01c20400 { intc: interrupt-controller@01c20400 {
compatible = "allwinner,sun4i-ic"; compatible = "allwinner,sun4i-a10-ic";
reg = <0x01c20400 0x400>; reg = <0x01c20400 0x400>;
interrupt-controller; interrupt-controller;
#interrupt-cells = <1>; #interrupt-cells = <1>;
......
...@@ -275,7 +275,7 @@ soc@01c00000 { ...@@ -275,7 +275,7 @@ soc@01c00000 {
ranges; ranges;
intc: interrupt-controller@01c20400 { intc: interrupt-controller@01c20400 {
compatible = "allwinner,sun4i-ic"; compatible = "allwinner,sun4i-a10-ic";
reg = <0x01c20400 0x400>; reg = <0x01c20400 0x400>;
interrupt-controller; interrupt-controller;
#interrupt-cells = <1>; #interrupt-cells = <1>;
......
...@@ -190,6 +190,14 @@ soc@01c00000 { ...@@ -190,6 +190,14 @@ soc@01c00000 {
#size-cells = <1>; #size-cells = <1>;
ranges; ranges;
nmi_intc: interrupt-controller@01f00c0c {
compatible = "allwinner,sun6i-a31-sc-nmi";
interrupt-controller;
#interrupt-cells = <2>;
reg = <0x01f00c0c 0x38>;
interrupts = <0 32 4>;
};
pio: pinctrl@01c20800 { pio: pinctrl@01c20800 {
compatible = "allwinner,sun6i-a31-pinctrl"; compatible = "allwinner,sun6i-a31-pinctrl";
reg = <0x01c20800 0x400>; reg = <0x01c20800 0x400>;
......
...@@ -339,6 +339,14 @@ soc@01c00000 { ...@@ -339,6 +339,14 @@ soc@01c00000 {
#size-cells = <1>; #size-cells = <1>;
ranges; ranges;
nmi_intc: interrupt-controller@01c00030 {
compatible = "allwinner,sun7i-a20-sc-nmi";
interrupt-controller;
#interrupt-cells = <2>;
reg = <0x01c00030 0x0c>;
interrupts = <0 0 4>;
};
emac: ethernet@01c0b000 { emac: ethernet@01c0b000 {
compatible = "allwinner,sun4i-a10-emac"; compatible = "allwinner,sun4i-a10-emac";
reg = <0x01c0b000 0x1000>; reg = <0x01c0b000 0x1000>;
......
...@@ -120,7 +120,7 @@ static void imx6q_enable_wb(bool enable) ...@@ -120,7 +120,7 @@ static void imx6q_enable_wb(bool enable)
int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
{ {
struct irq_desc *iomuxc_irq_desc; struct irq_data *iomuxc_irq_data = irq_get_irq_data(32);
u32 val = readl_relaxed(ccm_base + CLPCR); u32 val = readl_relaxed(ccm_base + CLPCR);
val &= ~BM_CLPCR_LPM; val &= ~BM_CLPCR_LPM;
...@@ -167,10 +167,9 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) ...@@ -167,10 +167,9 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
* 3) Software should mask IRQ #32 right after CCM Low-Power mode * 3) Software should mask IRQ #32 right after CCM Low-Power mode
* is set (set bits 0-1 of CCM_CLPCR). * is set (set bits 0-1 of CCM_CLPCR).
*/ */
iomuxc_irq_desc = irq_to_desc(32); imx_gpc_irq_unmask(iomuxc_irq_data);
imx_gpc_irq_unmask(&iomuxc_irq_desc->irq_data);
writel_relaxed(val, ccm_base + CLPCR); writel_relaxed(val, ccm_base + CLPCR);
imx_gpc_irq_mask(&iomuxc_irq_desc->irq_data); imx_gpc_irq_mask(iomuxc_irq_data);
return 0; return 0;
} }
......
...@@ -27,22 +27,8 @@ ...@@ -27,22 +27,8 @@
int mmp2_set_wake(struct irq_data *d, unsigned int on) int mmp2_set_wake(struct irq_data *d, unsigned int on)
{ {
int irq = d->irq;
struct irq_desc *desc = irq_to_desc(irq);
unsigned long data = 0; unsigned long data = 0;
int irq = d->irq;
if (unlikely(irq >= nr_irqs)) {
pr_err("IRQ nubmers are out of boundary!\n");
return -EINVAL;
}
if (on) {
if (desc->action)
desc->action->flags |= IRQF_NO_SUSPEND;
} else {
if (desc->action)
desc->action->flags &= ~IRQF_NO_SUSPEND;
}
/* enable wakeup sources */ /* enable wakeup sources */
switch (irq) { switch (irq) {
......
...@@ -27,22 +27,8 @@ ...@@ -27,22 +27,8 @@
int pxa910_set_wake(struct irq_data *data, unsigned int on) int pxa910_set_wake(struct irq_data *data, unsigned int on)
{ {
int irq = data->irq;
struct irq_desc *desc = irq_to_desc(data->irq);
uint32_t awucrm = 0, apcr = 0; uint32_t awucrm = 0, apcr = 0;
int irq = data->irq;
if (unlikely(irq >= nr_irqs)) {
pr_err("IRQ nubmers are out of boundary!\n");
return -EINVAL;
}
if (on) {
if (desc->action)
desc->action->flags |= IRQF_NO_SUSPEND;
} else {
if (desc->action)
desc->action->flags &= ~IRQF_NO_SUSPEND;
}
/* setting wakeup sources */ /* setting wakeup sources */
switch (irq) { switch (irq) {
...@@ -115,9 +101,11 @@ int pxa910_set_wake(struct irq_data *data, unsigned int on) ...@@ -115,9 +101,11 @@ int pxa910_set_wake(struct irq_data *data, unsigned int on)
if (irq >= IRQ_GPIO_START && irq < IRQ_BOARD_START) { if (irq >= IRQ_GPIO_START && irq < IRQ_BOARD_START) {
awucrm = MPMU_AWUCRM_WAKEUP(2); awucrm = MPMU_AWUCRM_WAKEUP(2);
apcr |= MPMU_APCR_SLPWP2; apcr |= MPMU_APCR_SLPWP2;
} else } else {
/* FIXME: This should return a proper error code ! */
printk(KERN_ERR "Error: no defined wake up source irq: %d\n", printk(KERN_ERR "Error: no defined wake up source irq: %d\n",
irq); irq);
}
} }
if (on) { if (on) {
......
...@@ -44,13 +44,10 @@ static unsigned int irq_counter[16]; ...@@ -44,13 +44,10 @@ static unsigned int irq_counter[16];
static irqreturn_t deferred_fiq(int irq, void *dev_id) static irqreturn_t deferred_fiq(int irq, void *dev_id)
{ {
struct irq_desc *irq_desc;
struct irq_chip *irq_chip = NULL;
int gpio, irq_num, fiq_count; int gpio, irq_num, fiq_count;
struct irq_chip *irq_chip;
irq_desc = irq_to_desc(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK)); irq_chip = irq_get_chip(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK));
if (irq_desc)
irq_chip = irq_desc->irq_data.chip;
/* /*
* For each handled GPIO interrupt, keep calling its interrupt handler * For each handled GPIO interrupt, keep calling its interrupt handler
......
...@@ -364,7 +364,6 @@ static irqreturn_t smp_irq_move_cleanup_interrupt(int irq, void *dev_id) ...@@ -364,7 +364,6 @@ static irqreturn_t smp_irq_move_cleanup_interrupt(int irq, void *dev_id)
static struct irqaction irq_move_irqaction = { static struct irqaction irq_move_irqaction = {
.handler = smp_irq_move_cleanup_interrupt, .handler = smp_irq_move_cleanup_interrupt,
.flags = IRQF_DISABLED,
.name = "irq_move" .name = "irq_move"
}; };
...@@ -489,14 +488,13 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) ...@@ -489,14 +488,13 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
ia64_srlz_d(); ia64_srlz_d();
while (vector != IA64_SPURIOUS_INT_VECTOR) { while (vector != IA64_SPURIOUS_INT_VECTOR) {
int irq = local_vector_to_irq(vector); int irq = local_vector_to_irq(vector);
struct irq_desc *desc = irq_to_desc(irq);
if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) { if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) {
smp_local_flush_tlb(); smp_local_flush_tlb();
kstat_incr_irqs_this_cpu(irq, desc); kstat_incr_irq_this_cpu(irq);
} else if (unlikely(IS_RESCHEDULE(vector))) { } else if (unlikely(IS_RESCHEDULE(vector))) {
scheduler_ipi(); scheduler_ipi();
kstat_incr_irqs_this_cpu(irq, desc); kstat_incr_irq_this_cpu(irq);
} else { } else {
ia64_setreg(_IA64_REG_CR_TPR, vector); ia64_setreg(_IA64_REG_CR_TPR, vector);
ia64_srlz_d(); ia64_srlz_d();
...@@ -549,13 +547,12 @@ void ia64_process_pending_intr(void) ...@@ -549,13 +547,12 @@ void ia64_process_pending_intr(void)
*/ */
while (vector != IA64_SPURIOUS_INT_VECTOR) { while (vector != IA64_SPURIOUS_INT_VECTOR) {
int irq = local_vector_to_irq(vector); int irq = local_vector_to_irq(vector);
struct irq_desc *desc = irq_to_desc(irq);
if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) { if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) {
smp_local_flush_tlb(); smp_local_flush_tlb();
kstat_incr_irqs_this_cpu(irq, desc); kstat_incr_irq_this_cpu(irq);
} else if (unlikely(IS_RESCHEDULE(vector))) { } else if (unlikely(IS_RESCHEDULE(vector))) {
kstat_incr_irqs_this_cpu(irq, desc); kstat_incr_irq_this_cpu(irq);
} else { } else {
struct pt_regs *old_regs = set_irq_regs(NULL); struct pt_regs *old_regs = set_irq_regs(NULL);
...@@ -602,7 +599,6 @@ static irqreturn_t dummy_handler (int irq, void *dev_id) ...@@ -602,7 +599,6 @@ static irqreturn_t dummy_handler (int irq, void *dev_id)
static struct irqaction ipi_irqaction = { static struct irqaction ipi_irqaction = {
.handler = handle_IPI, .handler = handle_IPI,
.flags = IRQF_DISABLED,
.name = "IPI" .name = "IPI"
}; };
...@@ -611,13 +607,11 @@ static struct irqaction ipi_irqaction = { ...@@ -611,13 +607,11 @@ static struct irqaction ipi_irqaction = {
*/ */
static struct irqaction resched_irqaction = { static struct irqaction resched_irqaction = {
.handler = dummy_handler, .handler = dummy_handler,
.flags = IRQF_DISABLED,
.name = "resched" .name = "resched"
}; };
static struct irqaction tlb_irqaction = { static struct irqaction tlb_irqaction = {
.handler = dummy_handler, .handler = dummy_handler,
.flags = IRQF_DISABLED,
.name = "tlb_flush" .name = "tlb_flush"
}; };
......
...@@ -1772,38 +1772,32 @@ __setup("disable_cpe_poll", ia64_mca_disable_cpe_polling); ...@@ -1772,38 +1772,32 @@ __setup("disable_cpe_poll", ia64_mca_disable_cpe_polling);
static struct irqaction cmci_irqaction = { static struct irqaction cmci_irqaction = {
.handler = ia64_mca_cmc_int_handler, .handler = ia64_mca_cmc_int_handler,
.flags = IRQF_DISABLED,
.name = "cmc_hndlr" .name = "cmc_hndlr"
}; };
static struct irqaction cmcp_irqaction = { static struct irqaction cmcp_irqaction = {
.handler = ia64_mca_cmc_int_caller, .handler = ia64_mca_cmc_int_caller,
.flags = IRQF_DISABLED,
.name = "cmc_poll" .name = "cmc_poll"
}; };
static struct irqaction mca_rdzv_irqaction = { static struct irqaction mca_rdzv_irqaction = {
.handler = ia64_mca_rendez_int_handler, .handler = ia64_mca_rendez_int_handler,
.flags = IRQF_DISABLED,
.name = "mca_rdzv" .name = "mca_rdzv"
}; };
static struct irqaction mca_wkup_irqaction = { static struct irqaction mca_wkup_irqaction = {
.handler = ia64_mca_wakeup_int_handler, .handler = ia64_mca_wakeup_int_handler,
.flags = IRQF_DISABLED,
.name = "mca_wkup" .name = "mca_wkup"
}; };
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static struct irqaction mca_cpe_irqaction = { static struct irqaction mca_cpe_irqaction = {
.handler = ia64_mca_cpe_int_handler, .handler = ia64_mca_cpe_int_handler,
.flags = IRQF_DISABLED,
.name = "cpe_hndlr" .name = "cpe_hndlr"
}; };
static struct irqaction mca_cpep_irqaction = { static struct irqaction mca_cpep_irqaction = {
.handler = ia64_mca_cpe_int_caller, .handler = ia64_mca_cpe_int_caller,
.flags = IRQF_DISABLED,
.name = "cpe_poll" .name = "cpe_poll"
}; };
#endif /* CONFIG_ACPI */ #endif /* CONFIG_ACPI */
......
...@@ -17,12 +17,9 @@ static int ia64_set_msi_irq_affinity(struct irq_data *idata, ...@@ -17,12 +17,9 @@ static int ia64_set_msi_irq_affinity(struct irq_data *idata,
{ {
struct msi_msg msg; struct msi_msg msg;
u32 addr, data; u32 addr, data;
int cpu = first_cpu(*cpu_mask); int cpu = cpumask_first_and(cpu_mask, cpu_online_mask);
unsigned int irq = idata->irq; unsigned int irq = idata->irq;
if (!cpu_online(cpu))
return -1;
if (irq_prepare_move(irq, cpu)) if (irq_prepare_move(irq, cpu))
return -1; return -1;
...@@ -139,10 +136,7 @@ static int dmar_msi_set_affinity(struct irq_data *data, ...@@ -139,10 +136,7 @@ static int dmar_msi_set_affinity(struct irq_data *data,
unsigned int irq = data->irq; unsigned int irq = data->irq;
struct irq_cfg *cfg = irq_cfg + irq; struct irq_cfg *cfg = irq_cfg + irq;
struct msi_msg msg; struct msi_msg msg;
int cpu = cpumask_first(mask); int cpu = cpumask_first_and(mask, cpu_online_mask);
if (!cpu_online(cpu))
return -1;
if (irq_prepare_move(irq, cpu)) if (irq_prepare_move(irq, cpu))
return -1; return -1;
......
...@@ -6387,7 +6387,6 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx) ...@@ -6387,7 +6387,6 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx)
static struct irqaction perfmon_irqaction = { static struct irqaction perfmon_irqaction = {
.handler = pfm_interrupt_handler, .handler = pfm_interrupt_handler,
.flags = IRQF_DISABLED,
.name = "perfmon" .name = "perfmon"
}; };
......
...@@ -380,7 +380,7 @@ static cycle_t itc_get_cycles(struct clocksource *cs) ...@@ -380,7 +380,7 @@ static cycle_t itc_get_cycles(struct clocksource *cs)
static struct irqaction timer_irqaction = { static struct irqaction timer_irqaction = {
.handler = timer_interrupt, .handler = timer_interrupt,
.flags = IRQF_DISABLED | IRQF_IRQPOLL, .flags = IRQF_IRQPOLL,
.name = "timer" .name = "timer"
}; };
......
...@@ -209,8 +209,8 @@ static int sn_set_affinity_irq(struct irq_data *data, ...@@ -209,8 +209,8 @@ static int sn_set_affinity_irq(struct irq_data *data,
nasid_t nasid; nasid_t nasid;
int slice; int slice;
nasid = cpuid_to_nasid(cpumask_first(mask)); nasid = cpuid_to_nasid(cpumask_first_and(mask, cpu_online_mask));
slice = cpuid_to_slice(cpumask_first(mask)); slice = cpuid_to_slice(cpumask_first_and(mask, cpu_online_mask));
list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe, list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
sn_irq_lh[irq], list) sn_irq_lh[irq], list)
......
...@@ -166,7 +166,7 @@ static int sn_set_msi_irq_affinity(struct irq_data *data, ...@@ -166,7 +166,7 @@ static int sn_set_msi_irq_affinity(struct irq_data *data,
struct sn_pcibus_provider *provider; struct sn_pcibus_provider *provider;
unsigned int cpu, irq = data->irq; unsigned int cpu, irq = data->irq;
cpu = cpumask_first(cpu_mask); cpu = cpumask_first_and(cpu_mask, cpu_online_mask);
sn_irq_info = sn_msi_info[irq].sn_irq_info; sn_irq_info = sn_msi_info[irq].sn_irq_info;
if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0) if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
return -1; return -1;
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/amigahw.h> #include <asm/amigahw.h>
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/irq.h>
#include <asm/traps.h> #include <asm/traps.h>
......
...@@ -10,9 +10,9 @@ ...@@ -10,9 +10,9 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/irq.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/irq.h> #include <asm/irq.h>
......
...@@ -1007,7 +1007,7 @@ static void __irq_entry smtc_clock_tick_interrupt(void) ...@@ -1007,7 +1007,7 @@ static void __irq_entry smtc_clock_tick_interrupt(void)
int irq = MIPS_CPU_IRQ_BASE + 1; int irq = MIPS_CPU_IRQ_BASE + 1;
irq_enter(); irq_enter();
kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); kstat_incr_irq_this_cpu(irq);
cd = &per_cpu(mips_clockevent_device, cpu); cd = &per_cpu(mips_clockevent_device, cpu);
cd->event_handler(cd); cd->event_handler(cd);
irq_exit(); irq_exit();
......
...@@ -148,7 +148,7 @@ static void __irq_entry indy_buserror_irq(void) ...@@ -148,7 +148,7 @@ static void __irq_entry indy_buserror_irq(void)
int irq = SGI_BUSERR_IRQ; int irq = SGI_BUSERR_IRQ;
irq_enter(); irq_enter();
kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); kstat_incr_irq_this_cpu(irq);
ip22_be_interrupt(irq); ip22_be_interrupt(irq);
irq_exit(); irq_exit();
} }
......
...@@ -123,7 +123,7 @@ void __irq_entry indy_8254timer_irq(void) ...@@ -123,7 +123,7 @@ void __irq_entry indy_8254timer_irq(void)
char c; char c;
irq_enter(); irq_enter();
kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); kstat_incr_irq_this_cpu(irq);
printk(KERN_ALERT "Oops, got 8254 interrupt.\n"); printk(KERN_ALERT "Oops, got 8254 interrupt.\n");
ArcRead(0, &c, 1, &cnt); ArcRead(0, &c, 1, &cnt);
ArcEnterInteractiveMode(); ArcEnterInteractiveMode();
......
...@@ -95,7 +95,7 @@ static int bcm1480_set_affinity(struct irq_data *d, const struct cpumask *mask, ...@@ -95,7 +95,7 @@ static int bcm1480_set_affinity(struct irq_data *d, const struct cpumask *mask,
u64 cur_ints; u64 cur_ints;
unsigned long flags; unsigned long flags;
i = cpumask_first(mask); i = cpumask_first_and(mask, cpu_online_mask);
/* Convert logical CPU to physical CPU */ /* Convert logical CPU to physical CPU */
cpu = cpu_logical_map(i); cpu = cpu_logical_map(i);
......
...@@ -182,7 +182,7 @@ void bcm1480_mailbox_interrupt(void) ...@@ -182,7 +182,7 @@ void bcm1480_mailbox_interrupt(void)
int irq = K_BCM1480_INT_MBOX_0_0; int irq = K_BCM1480_INT_MBOX_0_0;
unsigned int action; unsigned int action;
kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); kstat_incr_irq_this_cpu(irq);
/* Load the mailbox register to figure out what we're supposed to do */ /* Load the mailbox register to figure out what we're supposed to do */
action = (__raw_readq(mailbox_0_regs[cpu]) >> 48) & 0xffff; action = (__raw_readq(mailbox_0_regs[cpu]) >> 48) & 0xffff;
......
...@@ -88,7 +88,7 @@ static int sb1250_set_affinity(struct irq_data *d, const struct cpumask *mask, ...@@ -88,7 +88,7 @@ static int sb1250_set_affinity(struct irq_data *d, const struct cpumask *mask,
u64 cur_ints; u64 cur_ints;
unsigned long flags; unsigned long flags;
i = cpumask_first(mask); i = cpumask_first_and(mask, cpu_online_mask);
/* Convert logical CPU to physical CPU */ /* Convert logical CPU to physical CPU */
cpu = cpu_logical_map(i); cpu = cpu_logical_map(i);
......
...@@ -170,7 +170,7 @@ void sb1250_mailbox_interrupt(void) ...@@ -170,7 +170,7 @@ void sb1250_mailbox_interrupt(void)
int irq = K_INT_MBOX_0; int irq = K_INT_MBOX_0;
unsigned int action; unsigned int action;
kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); kstat_incr_irq_this_cpu(irq);
/* Load the mailbox register to figure out what we're supposed to do */ /* Load the mailbox register to figure out what we're supposed to do */
action = (____raw_readq(mailbox_regs[cpu]) >> 48) & 0xffff; action = (____raw_readq(mailbox_regs[cpu]) >> 48) & 0xffff;
......
...@@ -113,7 +113,7 @@ int __init init_clockevents(void) ...@@ -113,7 +113,7 @@ int __init init_clockevents(void)
cd->set_next_event = next_event; cd->set_next_event = next_event;
iact = &per_cpu(timer_irq, cpu); iact = &per_cpu(timer_irq, cpu);
iact->flags = IRQF_DISABLED | IRQF_SHARED | IRQF_TIMER; iact->flags = IRQF_SHARED | IRQF_TIMER;
iact->handler = timer_interrupt; iact->handler = timer_interrupt;
clockevents_register_device(cd); clockevents_register_device(cd);
......
...@@ -985,17 +985,17 @@ static int mn10300_serial_startup(struct uart_port *_port) ...@@ -985,17 +985,17 @@ static int mn10300_serial_startup(struct uart_port *_port)
irq_set_chip(port->tm_irq, &mn10300_serial_pic); irq_set_chip(port->tm_irq, &mn10300_serial_pic);
if (request_irq(port->rx_irq, mn10300_serial_interrupt, if (request_irq(port->rx_irq, mn10300_serial_interrupt,
IRQF_DISABLED | IRQF_NOBALANCING, IRQF_NOBALANCING,
port->rx_name, port) < 0) port->rx_name, port) < 0)
goto error; goto error;
if (request_irq(port->tx_irq, mn10300_serial_interrupt, if (request_irq(port->tx_irq, mn10300_serial_interrupt,
IRQF_DISABLED | IRQF_NOBALANCING, IRQF_NOBALANCING,
port->tx_name, port) < 0) port->tx_name, port) < 0)
goto error2; goto error2;
if (request_irq(port->tm_irq, mn10300_serial_interrupt, if (request_irq(port->tm_irq, mn10300_serial_interrupt,
IRQF_DISABLED | IRQF_NOBALANCING, IRQF_NOBALANCING,
port->tm_name, port) < 0) port->tm_name, port) < 0)
goto error3; goto error3;
mn10300_serial_mask_ack(port->tm_irq); mn10300_serial_mask_ack(port->tm_irq);
......
...@@ -142,7 +142,7 @@ void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep) ...@@ -142,7 +142,7 @@ void watchdog_interrupt(struct pt_regs *regs, enum exception_code excep)
NMICR = NMICR_WDIF; NMICR = NMICR_WDIF;
nmi_count(smp_processor_id())++; nmi_count(smp_processor_id())++;
kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); kstat_incr_irq_this_cpu(irq);
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
......
...@@ -143,7 +143,7 @@ static struct irqaction call_function_ipi = { ...@@ -143,7 +143,7 @@ static struct irqaction call_function_ipi = {
static irqreturn_t smp_ipi_timer_interrupt(int irq, void *dev_id); static irqreturn_t smp_ipi_timer_interrupt(int irq, void *dev_id);
static struct irqaction local_timer_ipi = { static struct irqaction local_timer_ipi = {
.handler = smp_ipi_timer_interrupt, .handler = smp_ipi_timer_interrupt,
.flags = IRQF_DISABLED | IRQF_NOBALANCING, .flags = IRQF_NOBALANCING,
.name = "smp local timer IPI" .name = "smp local timer IPI"
}; };
#endif #endif
......
...@@ -76,7 +76,7 @@ static irqreturn_t fpga_interrupt(int irq, void *_mask) ...@@ -76,7 +76,7 @@ static irqreturn_t fpga_interrupt(int irq, void *_mask)
static struct irqaction fpga_irq[] = { static struct irqaction fpga_irq[] = {
[0] = { [0] = {
.handler = fpga_interrupt, .handler = fpga_interrupt,
.flags = IRQF_DISABLED | IRQF_SHARED, .flags = IRQF_SHARED,
.name = "fpga", .name = "fpga",
}, },
}; };
......
...@@ -117,7 +117,7 @@ int cpu_check_affinity(struct irq_data *d, const struct cpumask *dest) ...@@ -117,7 +117,7 @@ int cpu_check_affinity(struct irq_data *d, const struct cpumask *dest)
return -EINVAL; return -EINVAL;
/* whatever mask they set, we just allow one CPU */ /* whatever mask they set, we just allow one CPU */
cpu_dest = first_cpu(*dest); cpu_dest = cpumask_first_and(dest, cpu_online_mask);
return cpu_dest; return cpu_dest;
} }
......
...@@ -143,13 +143,30 @@ static void eeh_disable_irq(struct pci_dev *dev) ...@@ -143,13 +143,30 @@ static void eeh_disable_irq(struct pci_dev *dev)
static void eeh_enable_irq(struct pci_dev *dev) static void eeh_enable_irq(struct pci_dev *dev)
{ {
struct eeh_dev *edev = pci_dev_to_eeh_dev(dev); struct eeh_dev *edev = pci_dev_to_eeh_dev(dev);
struct irq_desc *desc;
if ((edev->mode) & EEH_DEV_IRQ_DISABLED) { if ((edev->mode) & EEH_DEV_IRQ_DISABLED) {
edev->mode &= ~EEH_DEV_IRQ_DISABLED; edev->mode &= ~EEH_DEV_IRQ_DISABLED;
/*
desc = irq_to_desc(dev->irq); * FIXME !!!!!
if (desc && desc->depth > 0) *
* This is just ass backwards. This maze has
* unbalanced irq_enable/disable calls. So instead of
* finding the root cause it works around the warning
* in the irq_enable code by conditionally calling
* into it.
*
* That's just wrong.The warning in the core code is
* there to tell people to fix their assymetries in
* their own code, not by abusing the core information
* to avoid it.
*
* I so wish that the assymetry would be the other way
* round and a few more irq_disable calls render that
* shit unusable forever.
*
* tglx
*/
if (irqd_irq_disabled(irq_get_irq_data(dev->irq)))
enable_irq(dev->irq); enable_irq(dev->irq);
} }
} }
......
...@@ -465,7 +465,6 @@ static inline void check_stack_overflow(void) ...@@ -465,7 +465,6 @@ static inline void check_stack_overflow(void)
void __do_irq(struct pt_regs *regs) void __do_irq(struct pt_regs *regs)
{ {
struct irq_desc *desc;
unsigned int irq; unsigned int irq;
irq_enter(); irq_enter();
...@@ -487,11 +486,8 @@ void __do_irq(struct pt_regs *regs) ...@@ -487,11 +486,8 @@ void __do_irq(struct pt_regs *regs)
/* And finally process it */ /* And finally process it */
if (unlikely(irq == NO_IRQ)) if (unlikely(irq == NO_IRQ))
__get_cpu_var(irq_stat).spurious_irqs++; __get_cpu_var(irq_stat).spurious_irqs++;
else { else
desc = irq_to_desc(irq); generic_handle_irq(irq);
if (likely(desc))
desc->handle_irq(irq, desc);
}
trace_irq_exit(regs); trace_irq_exit(regs);
......
...@@ -28,8 +28,6 @@ ...@@ -28,8 +28,6 @@
#include <asm/ehv_pic.h> #include <asm/ehv_pic.h>
#include <asm/fsl_hcalls.h> #include <asm/fsl_hcalls.h>
#include "../../../kernel/irq/settings.h"
static struct ehv_pic *global_ehv_pic; static struct ehv_pic *global_ehv_pic;
static DEFINE_SPINLOCK(ehv_pic_lock); static DEFINE_SPINLOCK(ehv_pic_lock);
...@@ -113,17 +111,13 @@ static unsigned int ehv_pic_type_to_vecpri(unsigned int type) ...@@ -113,17 +111,13 @@ static unsigned int ehv_pic_type_to_vecpri(unsigned int type)
int ehv_pic_set_irq_type(struct irq_data *d, unsigned int flow_type) int ehv_pic_set_irq_type(struct irq_data *d, unsigned int flow_type)
{ {
unsigned int src = virq_to_hw(d->irq); unsigned int src = virq_to_hw(d->irq);
struct irq_desc *desc = irq_to_desc(d->irq);
unsigned int vecpri, vold, vnew, prio, cpu_dest; unsigned int vecpri, vold, vnew, prio, cpu_dest;
unsigned long flags; unsigned long flags;
if (flow_type == IRQ_TYPE_NONE) if (flow_type == IRQ_TYPE_NONE)
flow_type = IRQ_TYPE_LEVEL_LOW; flow_type = IRQ_TYPE_LEVEL_LOW;
irq_settings_clr_level(desc); irqd_set_trigger_type(d, flow_type);
irq_settings_set_trigger_mask(desc, flow_type);
if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
irq_settings_set_level(desc);
vecpri = ehv_pic_type_to_vecpri(flow_type); vecpri = ehv_pic_type_to_vecpri(flow_type);
...@@ -144,7 +138,7 @@ int ehv_pic_set_irq_type(struct irq_data *d, unsigned int flow_type) ...@@ -144,7 +138,7 @@ int ehv_pic_set_irq_type(struct irq_data *d, unsigned int flow_type)
ev_int_set_config(src, vecpri, prio, cpu_dest); ev_int_set_config(src, vecpri, prio, cpu_dest);
spin_unlock_irqrestore(&ehv_pic_lock, flags); spin_unlock_irqrestore(&ehv_pic_lock, flags);
return 0; return IRQ_SET_MASK_OK_NOCOPY;
} }
static struct irq_chip ehv_pic_irq_chip = { static struct irq_chip ehv_pic_irq_chip = {
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/irq.h>
#include <asm/irq_regs.h> #include <asm/irq_regs.h>
#include <asm/cputime.h> #include <asm/cputime.h>
#include <asm/lowcore.h> #include <asm/lowcore.h>
......
...@@ -217,19 +217,6 @@ void __init init_IRQ(void) ...@@ -217,19 +217,6 @@ void __init init_IRQ(void)
} }
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
static void route_irq(struct irq_data *data, unsigned int irq, unsigned int cpu)
{
struct irq_desc *desc = irq_to_desc(irq);
struct irq_chip *chip = irq_data_get_irq_chip(data);
printk(KERN_INFO "IRQ%u: moving from cpu%u to cpu%u\n",
irq, data->node, cpu);
raw_spin_lock_irq(&desc->lock);
chip->irq_set_affinity(data, cpumask_of(cpu), false);
raw_spin_unlock_irq(&desc->lock);
}
/* /*
* The CPU has been marked offline. Migrate IRQs off this CPU. If * The CPU has been marked offline. Migrate IRQs off this CPU. If
* the affinity settings do not allow other CPUs, force them onto any * the affinity settings do not allow other CPUs, force them onto any
...@@ -250,11 +237,8 @@ void migrate_irqs(void) ...@@ -250,11 +237,8 @@ void migrate_irqs(void)
irq, cpu); irq, cpu);
cpumask_setall(data->affinity); cpumask_setall(data->affinity);
newcpu = cpumask_any_and(data->affinity,
cpu_online_mask);
} }
irq_set_affinity(irq, data->affinity);
route_irq(data, irq, newcpu);
} }
} }
} }
......
...@@ -733,7 +733,7 @@ void __irq_entry timer_interrupt(int irq, struct pt_regs *regs) ...@@ -733,7 +733,7 @@ void __irq_entry timer_interrupt(int irq, struct pt_regs *regs)
irq_enter(); irq_enter();
local_cpu_data().irq0_irqs++; local_cpu_data().irq0_irqs++;
kstat_incr_irqs_this_cpu(0, irq_to_desc(0)); kstat_incr_irq_this_cpu(0);
if (unlikely(!evt->event_handler)) { if (unlikely(!evt->event_handler)) {
printk(KERN_WARNING printk(KERN_WARNING
......
...@@ -145,10 +145,10 @@ static int fd_request_irq(void) ...@@ -145,10 +145,10 @@ static int fd_request_irq(void)
{ {
if (can_use_virtual_dma) if (can_use_virtual_dma)
return request_irq(FLOPPY_IRQ, floppy_hardint, return request_irq(FLOPPY_IRQ, floppy_hardint,
IRQF_DISABLED, "floppy", NULL); 0, "floppy", NULL);
else else
return request_irq(FLOPPY_IRQ, floppy_interrupt, return request_irq(FLOPPY_IRQ, floppy_interrupt,
IRQF_DISABLED, "floppy", NULL); 0, "floppy", NULL);
} }
static unsigned long dma_mem_alloc(unsigned long size) static unsigned long dma_mem_alloc(unsigned long size)
......
...@@ -33,6 +33,9 @@ typedef struct { ...@@ -33,6 +33,9 @@ typedef struct {
#ifdef CONFIG_X86_MCE_THRESHOLD #ifdef CONFIG_X86_MCE_THRESHOLD
unsigned int irq_threshold_count; unsigned int irq_threshold_count;
#endif #endif
#if IS_ENABLED(CONFIG_HYPERV) || defined(CONFIG_XEN)
unsigned int irq_hv_callback_count;
#endif
} ____cacheline_aligned irq_cpustat_t; } ____cacheline_aligned irq_cpustat_t;
DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define _ASM_X86_MSHYPER_H #define _ASM_X86_MSHYPER_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/interrupt.h>
#include <asm/hyperv.h> #include <asm/hyperv.h>
struct ms_hyperv_info { struct ms_hyperv_info {
...@@ -16,6 +17,7 @@ void hyperv_callback_vector(void); ...@@ -16,6 +17,7 @@ void hyperv_callback_vector(void);
#define trace_hyperv_callback_vector hyperv_callback_vector #define trace_hyperv_callback_vector hyperv_callback_vector
#endif #endif
void hyperv_vector_handler(struct pt_regs *regs); void hyperv_vector_handler(struct pt_regs *regs);
void hv_register_vmbus_handler(int irq, irq_handler_t handler); void hv_setup_vmbus_irq(void (*handler)(void));
void hv_remove_vmbus_irq(void);
#endif #endif
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/hardirq.h> #include <linux/hardirq.h>
#include <linux/efi.h> #include <linux/efi.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/hypervisor.h> #include <asm/hypervisor.h>
#include <asm/hyperv.h> #include <asm/hyperv.h>
...@@ -31,6 +32,45 @@ ...@@ -31,6 +32,45 @@
struct ms_hyperv_info ms_hyperv; struct ms_hyperv_info ms_hyperv;
EXPORT_SYMBOL_GPL(ms_hyperv); EXPORT_SYMBOL_GPL(ms_hyperv);
#if IS_ENABLED(CONFIG_HYPERV)
static void (*vmbus_handler)(void);
void hyperv_vector_handler(struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
irq_enter();
exit_idle();
inc_irq_stat(irq_hv_callback_count);
if (vmbus_handler)
vmbus_handler();
irq_exit();
set_irq_regs(old_regs);
}
void hv_setup_vmbus_irq(void (*handler)(void))
{
vmbus_handler = handler;
/*
* Setup the IDT for hypervisor callback. Prevent reallocation
* at module reload.
*/
if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors))
alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR,
hyperv_callback_vector);
}
void hv_remove_vmbus_irq(void)
{
/* We have no way to deallocate the interrupt gate */
vmbus_handler = NULL;
}
EXPORT_SYMBOL_GPL(hv_setup_vmbus_irq);
EXPORT_SYMBOL_GPL(hv_remove_vmbus_irq);
#endif
static uint32_t __init ms_hyperv_platform(void) static uint32_t __init ms_hyperv_platform(void)
{ {
u32 eax; u32 eax;
...@@ -119,41 +159,3 @@ const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { ...@@ -119,41 +159,3 @@ const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
.init_platform = ms_hyperv_init_platform, .init_platform = ms_hyperv_init_platform,
}; };
EXPORT_SYMBOL(x86_hyper_ms_hyperv); EXPORT_SYMBOL(x86_hyper_ms_hyperv);
#if IS_ENABLED(CONFIG_HYPERV)
static int vmbus_irq = -1;
static irq_handler_t vmbus_isr;
void hv_register_vmbus_handler(int irq, irq_handler_t handler)
{
/*
* Setup the IDT for hypervisor callback.
*/
alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, hyperv_callback_vector);
vmbus_irq = irq;
vmbus_isr = handler;
}
void hyperv_vector_handler(struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
struct irq_desc *desc;
irq_enter();
exit_idle();
desc = irq_to_desc(vmbus_irq);
if (desc)
generic_handle_irq_desc(vmbus_irq, desc);
irq_exit();
set_irq_regs(old_regs);
}
#else
void hv_register_vmbus_handler(int irq, irq_handler_t handler)
{
}
#endif
EXPORT_SYMBOL_GPL(hv_register_vmbus_handler);
...@@ -521,7 +521,7 @@ static int hpet_setup_irq(struct hpet_dev *dev) ...@@ -521,7 +521,7 @@ static int hpet_setup_irq(struct hpet_dev *dev)
{ {
if (request_irq(dev->irq, hpet_interrupt_handler, if (request_irq(dev->irq, hpet_interrupt_handler,
IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING, IRQF_TIMER | IRQF_NOBALANCING,
dev->name, dev)) dev->name, dev))
return -1; return -1;
......
...@@ -124,6 +124,12 @@ int arch_show_interrupts(struct seq_file *p, int prec) ...@@ -124,6 +124,12 @@ int arch_show_interrupts(struct seq_file *p, int prec)
for_each_online_cpu(j) for_each_online_cpu(j)
seq_printf(p, "%10u ", per_cpu(mce_poll_count, j)); seq_printf(p, "%10u ", per_cpu(mce_poll_count, j));
seq_printf(p, " Machine check polls\n"); seq_printf(p, " Machine check polls\n");
#endif
#if defined(CONFIG_HYPERV) || defined(CONFIG_XEN)
seq_printf(p, "%*s: ", prec, "THR");
for_each_online_cpu(j)
seq_printf(p, "%10u ", irq_stats(j)->irq_hv_callback_count);
seq_printf(p, " Hypervisor callback interrupts\n");
#endif #endif
seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count)); seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
#if defined(CONFIG_X86_IO_APIC) #if defined(CONFIG_X86_IO_APIC)
......
...@@ -62,7 +62,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id) ...@@ -62,7 +62,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
static struct irqaction irq0 = { static struct irqaction irq0 = {
.handler = timer_interrupt, .handler = timer_interrupt,
.flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER, .flags = IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER,
.name = "timer" .name = "timer"
}; };
......
...@@ -183,7 +183,7 @@ __visible void xen_lock_spinning(struct arch_spinlock *lock, __ticket_t want) ...@@ -183,7 +183,7 @@ __visible void xen_lock_spinning(struct arch_spinlock *lock, __ticket_t want)
local_irq_save(flags); local_irq_save(flags);
kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq)); kstat_incr_irq_this_cpu(irq);
out: out:
cpumask_clear_cpu(cpu, &waiting_cpus); cpumask_clear_cpu(cpu, &waiting_cpus);
w->lock = NULL; w->lock = NULL;
......
...@@ -155,18 +155,6 @@ void __init init_IRQ(void) ...@@ -155,18 +155,6 @@ void __init init_IRQ(void)
} }
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
static void route_irq(struct irq_data *data, unsigned int irq, unsigned int cpu)
{
struct irq_desc *desc = irq_to_desc(irq);
struct irq_chip *chip = irq_data_get_irq_chip(data);
unsigned long flags;
raw_spin_lock_irqsave(&desc->lock, flags);
if (chip->irq_set_affinity)
chip->irq_set_affinity(data, cpumask_of(cpu), false);
raw_spin_unlock_irqrestore(&desc->lock, flags);
}
/* /*
* The CPU has been marked offline. Migrate IRQs off this CPU. If * The CPU has been marked offline. Migrate IRQs off this CPU. If
* the affinity settings do not allow other CPUs, force them onto any * 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,10 +163,9 @@ static void route_irq(struct irq_data *data, unsigned int irq, unsigned int cpu)
void migrate_irqs(void) void migrate_irqs(void)
{ {
unsigned int i, cpu = smp_processor_id(); unsigned int i, cpu = smp_processor_id();
struct irq_desc *desc;
for_each_irq_desc(i, desc) { for_each_active_irq(i) {
struct irq_data *data = irq_desc_get_irq_data(desc); struct irq_data *data = irq_get_irq_data(i);
unsigned int newcpu; unsigned int newcpu;
if (irqd_is_per_cpu(data)) if (irqd_is_per_cpu(data))
...@@ -194,11 +181,8 @@ void migrate_irqs(void) ...@@ -194,11 +181,8 @@ void migrate_irqs(void)
i, cpu); i, cpu);
cpumask_setall(data->affinity); cpumask_setall(data->affinity);
newcpu = cpumask_any_and(data->affinity,
cpu_online_mask);
} }
irq_set_affinity(i, data->affinity);
route_irq(data, i, newcpu);
} }
} }
#endif /* CONFIG_HOTPLUG_CPU */ #endif /* CONFIG_HOTPLUG_CPU */
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/sysctl.h> #include <linux/sysctl.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -558,9 +557,6 @@ static struct bus_type hv_bus = { ...@@ -558,9 +557,6 @@ static struct bus_type hv_bus = {
.dev_groups = vmbus_groups, .dev_groups = vmbus_groups,
}; };
static const char *driver_name = "hyperv";
struct onmessage_work_context { struct onmessage_work_context {
struct work_struct work; struct work_struct work;
struct hv_message msg; struct hv_message msg;
...@@ -619,7 +615,7 @@ static void vmbus_on_msg_dpc(unsigned long data) ...@@ -619,7 +615,7 @@ static void vmbus_on_msg_dpc(unsigned long data)
} }
} }
static irqreturn_t vmbus_isr(int irq, void *dev_id) static void vmbus_isr(void)
{ {
int cpu = smp_processor_id(); int cpu = smp_processor_id();
void *page_addr; void *page_addr;
...@@ -629,7 +625,7 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id) ...@@ -629,7 +625,7 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id)
page_addr = hv_context.synic_event_page[cpu]; page_addr = hv_context.synic_event_page[cpu];
if (page_addr == NULL) if (page_addr == NULL)
return IRQ_NONE; return;
event = (union hv_synic_event_flags *)page_addr + event = (union hv_synic_event_flags *)page_addr +
VMBUS_MESSAGE_SINT; VMBUS_MESSAGE_SINT;
...@@ -665,28 +661,8 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id) ...@@ -665,28 +661,8 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id)
msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
/* Check if there are actual msgs to be processed */ /* Check if there are actual msgs to be processed */
if (msg->header.message_type != HVMSG_NONE) { if (msg->header.message_type != HVMSG_NONE)
handled = true;
tasklet_schedule(&msg_dpc); tasklet_schedule(&msg_dpc);
}
if (handled)
return IRQ_HANDLED;
else
return IRQ_NONE;
}
/*
* vmbus interrupt flow handler:
* vmbus interrupts can concurrently occur on multiple CPUs and
* can be handled concurrently.
*/
static void vmbus_flow_handler(unsigned int irq, struct irq_desc *desc)
{
kstat_incr_irqs_this_cpu(irq, desc);
desc->action->handler(irq, desc->action->dev_id);
} }
/* /*
...@@ -715,25 +691,7 @@ static int vmbus_bus_init(int irq) ...@@ -715,25 +691,7 @@ static int vmbus_bus_init(int irq)
if (ret) if (ret)
goto err_cleanup; goto err_cleanup;
ret = request_irq(irq, vmbus_isr, 0, driver_name, hv_acpi_dev); hv_setup_vmbus_irq(vmbus_isr);
if (ret != 0) {
pr_err("Unable to request IRQ %d\n",
irq);
goto err_unregister;
}
/*
* Vmbus interrupts can be handled concurrently on
* different CPUs. Establish an appropriate interrupt flow
* handler that can support this model.
*/
irq_set_handler(irq, vmbus_flow_handler);
/*
* Register our interrupt handler.
*/
hv_register_vmbus_handler(irq, vmbus_isr);
ret = hv_synic_alloc(); ret = hv_synic_alloc();
if (ret) if (ret)
...@@ -753,9 +711,8 @@ static int vmbus_bus_init(int irq) ...@@ -753,9 +711,8 @@ static int vmbus_bus_init(int irq)
err_alloc: err_alloc:
hv_synic_free(); hv_synic_free();
free_irq(irq, hv_acpi_dev); hv_remove_vmbus_irq();
err_unregister:
bus_unregister(&hv_bus); bus_unregister(&hv_bus);
err_cleanup: err_cleanup:
...@@ -947,7 +904,6 @@ static int __init hv_acpi_init(void) ...@@ -947,7 +904,6 @@ static int __init hv_acpi_init(void)
/* /*
* Get irq resources first. * Get irq resources first.
*/ */
ret = acpi_bus_register_driver(&vmbus_acpi_driver); ret = acpi_bus_register_driver(&vmbus_acpi_driver);
if (ret) if (ret)
...@@ -978,8 +934,7 @@ static int __init hv_acpi_init(void) ...@@ -978,8 +934,7 @@ static int __init hv_acpi_init(void)
static void __exit vmbus_exit(void) static void __exit vmbus_exit(void)
{ {
hv_remove_vmbus_irq();
free_irq(irq, hv_acpi_dev);
vmbus_free_channels(); vmbus_free_channels();
bus_unregister(&hv_bus); bus_unregister(&hv_bus);
hv_cleanup(); hv_cleanup();
......
...@@ -12,6 +12,7 @@ obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o ...@@ -12,6 +12,7 @@ obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o
obj-$(CONFIG_ARCH_MOXART) += irq-moxart.o obj-$(CONFIG_ARCH_MOXART) += irq-moxart.o
obj-$(CONFIG_ORION_IRQCHIP) += irq-orion.o obj-$(CONFIG_ORION_IRQCHIP) += irq-orion.o
obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o
obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o
obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
obj-$(CONFIG_ARM_GIC) += irq-gic.o obj-$(CONFIG_ARM_GIC) += irq-gic.o
obj-$(CONFIG_ARM_NVIC) += irq-nvic.o obj-$(CONFIG_ARM_NVIC) += irq-nvic.o
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
...@@ -42,6 +43,7 @@ ...@@ -42,6 +43,7 @@
#define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4) #define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4)
#define ARMADA_370_XP_CPU_INTACK_OFFS (0x44) #define ARMADA_370_XP_CPU_INTACK_OFFS (0x44)
#define ARMADA_375_PPI_CAUSE (0x10)
#define ARMADA_370_XP_SW_TRIG_INT_OFFS (0x4) #define ARMADA_370_XP_SW_TRIG_INT_OFFS (0x4)
#define ARMADA_370_XP_IN_DRBEL_MSK_OFFS (0xc) #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,7 +354,63 @@ static struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
.xlate = irq_domain_xlate_onecell, .xlate = irq_domain_xlate_onecell,
}; };
static asmlinkage void __exception_irq_entry #ifdef CONFIG_PCI_MSI
static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained)
{
u32 msimask, msinr;
msimask = readl_relaxed(per_cpu_int_base +
ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
& PCI_MSI_DOORBELL_MASK;
writel(~msimask, per_cpu_int_base +
ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
for (msinr = PCI_MSI_DOORBELL_START;
msinr < PCI_MSI_DOORBELL_END; msinr++) {
int irq;
if (!(msimask & BIT(msinr)))
continue;
irq = irq_find_mapping(armada_370_xp_msi_domain,
msinr - 16);
if (is_chained)
generic_handle_irq(irq);
else
handle_IRQ(irq, regs);
}
}
#else
static void armada_370_xp_handle_msi_irq(struct pt_regs *r, bool b) {}
#endif
static void armada_370_xp_mpic_handle_cascade_irq(unsigned int irq,
struct irq_desc *desc)
{
struct irq_chip *chip = irq_get_chip(irq);
unsigned long irqmap, irqn;
unsigned int cascade_irq;
chained_irq_enter(chip, desc);
irqmap = readl_relaxed(per_cpu_int_base + ARMADA_375_PPI_CAUSE);
if (irqmap & BIT(0)) {
armada_370_xp_handle_msi_irq(NULL, true);
irqmap &= ~BIT(0);
}
for_each_set_bit(irqn, &irqmap, BITS_PER_LONG) {
cascade_irq = irq_find_mapping(armada_370_xp_mpic_domain, irqn);
generic_handle_irq(cascade_irq);
}
chained_irq_exit(chip, desc);
}
static void __exception_irq_entry
armada_370_xp_handle_irq(struct pt_regs *regs) armada_370_xp_handle_irq(struct pt_regs *regs)
{ {
u32 irqstat, irqnr; u32 irqstat, irqnr;
...@@ -372,31 +430,9 @@ armada_370_xp_handle_irq(struct pt_regs *regs) ...@@ -372,31 +430,9 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
continue; continue;
} }
#ifdef CONFIG_PCI_MSI
/* MSI handling */ /* MSI handling */
if (irqnr == 1) { if (irqnr == 1)
u32 msimask, msinr; armada_370_xp_handle_msi_irq(regs, false);
msimask = readl_relaxed(per_cpu_int_base +
ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
& PCI_MSI_DOORBELL_MASK;
writel(~msimask, per_cpu_int_base +
ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
for (msinr = PCI_MSI_DOORBELL_START;
msinr < PCI_MSI_DOORBELL_END; msinr++) {
int irq;
if (!(msimask & BIT(msinr)))
continue;
irq = irq_find_mapping(armada_370_xp_msi_domain,
msinr - 16);
handle_IRQ(irq, regs);
}
}
#endif
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* IPI Handling */ /* IPI Handling */
...@@ -427,6 +463,7 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, ...@@ -427,6 +463,7 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
struct device_node *parent) struct device_node *parent)
{ {
struct resource main_int_res, per_cpu_int_res; struct resource main_int_res, per_cpu_int_res;
int parent_irq;
u32 control; u32 control;
BUG_ON(of_address_to_resource(node, 0, &main_int_res)); 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,8 +492,6 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
BUG_ON(!armada_370_xp_mpic_domain); BUG_ON(!armada_370_xp_mpic_domain);
irq_set_default_host(armada_370_xp_mpic_domain);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
armada_xp_mpic_smp_cpu_init(); armada_xp_mpic_smp_cpu_init();
...@@ -472,7 +507,14 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, ...@@ -472,7 +507,14 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
armada_370_xp_msi_init(node, main_int_res.start); armada_370_xp_msi_init(node, main_int_res.start);
set_handle_irq(armada_370_xp_handle_irq); parent_irq = irq_of_parse_and_map(node, 0);
if (parent_irq <= 0) {
irq_set_default_host(armada_370_xp_mpic_domain);
set_handle_irq(armada_370_xp_handle_irq);
} else {
irq_set_chained_handler(parent_irq,
armada_370_xp_mpic_handle_cascade_irq);
}
return 0; return 0;
} }
......
...@@ -95,7 +95,7 @@ struct armctrl_ic { ...@@ -95,7 +95,7 @@ struct armctrl_ic {
}; };
static struct armctrl_ic intc __read_mostly; static struct armctrl_ic intc __read_mostly;
static asmlinkage void __exception_irq_entry bcm2835_handle_irq( static void __exception_irq_entry bcm2835_handle_irq(
struct pt_regs *regs); struct pt_regs *regs);
static void armctrl_mask_irq(struct irq_data *d) 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,7 +196,7 @@ static void armctrl_handle_shortcut(int bank, struct pt_regs *regs,
handle_IRQ(irq_linear_revmap(intc.domain, irq), regs); handle_IRQ(irq_linear_revmap(intc.domain, irq), regs);
} }
static asmlinkage void __exception_irq_entry bcm2835_handle_irq( static void __exception_irq_entry bcm2835_handle_irq(
struct pt_regs *regs) struct pt_regs *regs)
{ {
u32 stat, irq; u32 stat, irq;
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
union gic_base { union gic_base {
void __iomem *common_base; void __iomem *common_base;
void __percpu __iomem **percpu_base; void __percpu * __iomem *percpu_base;
}; };
struct gic_chip_data { struct gic_chip_data {
...@@ -279,7 +279,7 @@ static int gic_set_wake(struct irq_data *d, unsigned int on) ...@@ -279,7 +279,7 @@ static int gic_set_wake(struct irq_data *d, unsigned int on)
#define gic_set_wake NULL #define gic_set_wake NULL
#endif #endif
static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
{ {
u32 irqstat, irqnr; u32 irqstat, irqnr;
struct gic_chip_data *gic = &gic_data[0]; struct gic_chip_data *gic = &gic_data[0];
...@@ -648,7 +648,7 @@ static void __init gic_pm_init(struct gic_chip_data *gic) ...@@ -648,7 +648,7 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
#endif #endif
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
{ {
int cpu; int cpu;
unsigned long flags, map = 0; unsigned long flags, map = 0;
...@@ -869,7 +869,7 @@ static struct notifier_block gic_cpu_notifier = { ...@@ -869,7 +869,7 @@ static struct notifier_block gic_cpu_notifier = {
}; };
#endif #endif
const struct irq_domain_ops gic_irq_domain_ops = { static const struct irq_domain_ops gic_irq_domain_ops = {
.map = gic_irq_domain_map, .map = gic_irq_domain_map,
.xlate = gic_irq_domain_xlate, .xlate = gic_irq_domain_xlate,
}; };
...@@ -974,7 +974,8 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, ...@@ -974,7 +974,8 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
#ifdef CONFIG_OF #ifdef CONFIG_OF
static int gic_cnt __initdata; static int gic_cnt __initdata;
int __init gic_of_init(struct device_node *node, struct device_node *parent) static int __init
gic_of_init(struct device_node *node, struct device_node *parent)
{ {
void __iomem *cpu_base; void __iomem *cpu_base;
void __iomem *dist_base; void __iomem *dist_base;
......
...@@ -194,8 +194,7 @@ static struct mmp_intc_conf mmp2_conf = { ...@@ -194,8 +194,7 @@ static struct mmp_intc_conf mmp2_conf = {
.conf_mask = 0x7f, .conf_mask = 0x7f,
}; };
static asmlinkage void __exception_irq_entry static void __exception_irq_entry mmp_handle_irq(struct pt_regs *regs)
mmp_handle_irq(struct pt_regs *regs)
{ {
int irq, hwirq; int irq, hwirq;
...@@ -207,8 +206,7 @@ mmp_handle_irq(struct pt_regs *regs) ...@@ -207,8 +206,7 @@ mmp_handle_irq(struct pt_regs *regs)
handle_IRQ(irq, regs); handle_IRQ(irq, regs);
} }
static asmlinkage void __exception_irq_entry static void __exception_irq_entry mmp2_handle_irq(struct pt_regs *regs)
mmp2_handle_irq(struct pt_regs *regs)
{ {
int irq, hwirq; int irq, hwirq;
......
...@@ -44,7 +44,7 @@ struct moxart_irq_data { ...@@ -44,7 +44,7 @@ struct moxart_irq_data {
static struct moxart_irq_data intc; static struct moxart_irq_data intc;
static asmlinkage void __exception_irq_entry handle_irq(struct pt_regs *regs) static void __exception_irq_entry handle_irq(struct pt_regs *regs)
{ {
u32 irqstat; u32 irqstat;
int hwirq; int hwirq;
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
static struct irq_domain *orion_irq_domain; static struct irq_domain *orion_irq_domain;
static asmlinkage void static void
__exception_irq_entry orion_handle_irq(struct pt_regs *regs) __exception_irq_entry orion_handle_irq(struct pt_regs *regs)
{ {
struct irq_domain_chip_generic *dgc = orion_irq_domain->gc; struct irq_domain_chip_generic *dgc = orion_irq_domain->gc;
......
...@@ -47,7 +47,7 @@ sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num) ...@@ -47,7 +47,7 @@ sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
ct->regs.mask = SIRFSOC_INT_RISC_MASK0; ct->regs.mask = SIRFSOC_INT_RISC_MASK0;
} }
static asmlinkage void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs) static void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs)
{ {
void __iomem *base = sirfsoc_irqdomain->host_data; void __iomem *base = sirfsoc_irqdomain->host_data;
u32 irqstat, irqnr; u32 irqstat, irqnr;
......
...@@ -36,18 +36,16 @@ ...@@ -36,18 +36,16 @@
static void __iomem *sun4i_irq_base; static void __iomem *sun4i_irq_base;
static struct irq_domain *sun4i_irq_domain; static struct irq_domain *sun4i_irq_domain;
static asmlinkage void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs); static void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs);
static void sun4i_irq_ack(struct irq_data *irqd) static void sun4i_irq_ack(struct irq_data *irqd)
{ {
unsigned int irq = irqd_to_hwirq(irqd); unsigned int irq = irqd_to_hwirq(irqd);
unsigned int irq_off = irq % 32;
int reg = irq / 32;
u32 val;
val = readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg)); if (irq != 0)
writel(val | (1 << irq_off), return; /* Only IRQ 0 / the ENMI needs to be acked */
sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
writel(BIT(0), sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0));
} }
static void sun4i_irq_mask(struct irq_data *irqd) static void sun4i_irq_mask(struct irq_data *irqd)
...@@ -76,16 +74,16 @@ static void sun4i_irq_unmask(struct irq_data *irqd) ...@@ -76,16 +74,16 @@ static void sun4i_irq_unmask(struct irq_data *irqd)
static struct irq_chip sun4i_irq_chip = { static struct irq_chip sun4i_irq_chip = {
.name = "sun4i_irq", .name = "sun4i_irq",
.irq_ack = sun4i_irq_ack, .irq_eoi = sun4i_irq_ack,
.irq_mask = sun4i_irq_mask, .irq_mask = sun4i_irq_mask,
.irq_unmask = sun4i_irq_unmask, .irq_unmask = sun4i_irq_unmask,
.flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED,
}; };
static int sun4i_irq_map(struct irq_domain *d, unsigned int virq, static int sun4i_irq_map(struct irq_domain *d, unsigned int virq,
irq_hw_number_t hw) irq_hw_number_t hw)
{ {
irq_set_chip_and_handler(virq, &sun4i_irq_chip, irq_set_chip_and_handler(virq, &sun4i_irq_chip, handle_fasteoi_irq);
handle_level_irq);
set_irq_flags(virq, IRQF_VALID | IRQF_PROBE); set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
return 0; return 0;
...@@ -109,7 +107,7 @@ static int __init sun4i_of_init(struct device_node *node, ...@@ -109,7 +107,7 @@ static int __init sun4i_of_init(struct device_node *node,
writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(1)); writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(1));
writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(2)); writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(2));
/* Mask all the interrupts */ /* Unmask all the interrupts, ENABLE_REG(x) is used for masking */
writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(0)); writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(0));
writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(1)); writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(1));
writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(2)); 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,16 +132,30 @@ static int __init sun4i_of_init(struct device_node *node,
return 0; return 0;
} }
IRQCHIP_DECLARE(allwinner_sun4i_ic, "allwinner,sun4i-ic", sun4i_of_init); IRQCHIP_DECLARE(allwinner_sun4i_ic, "allwinner,sun4i-a10-ic", sun4i_of_init);
static asmlinkage void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs) static void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs)
{ {
u32 irq, hwirq; u32 irq, hwirq;
/*
* hwirq == 0 can mean one of 3 things:
* 1) no more irqs pending
* 2) irq 0 pending
* 3) spurious irq
* So if we immediately get a reading of 0, check the irq-pending reg
* to differentiate between 2 and 3. We only do this once to avoid
* the extra check in the common case of 1 hapening after having
* read the vector-reg once.
*/
hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2; hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2;
while (hwirq != 0) { if (hwirq == 0 &&
!(readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0)) & BIT(0)))
return;
do {
irq = irq_find_mapping(sun4i_irq_domain, hwirq); irq = irq_find_mapping(sun4i_irq_domain, hwirq);
handle_IRQ(irq, regs); handle_IRQ(irq, regs);
hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2; hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2;
} } while (hwirq != 0);
} }
/*
* Allwinner A20/A31 SoCs NMI IRQ chip driver.
*
* Carlo Caione <carlo.caione@gmail.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/irqchip/chained_irq.h>
#include "irqchip.h"
#define SUNXI_NMI_SRC_TYPE_MASK 0x00000003
enum {
SUNXI_SRC_TYPE_LEVEL_LOW = 0,
SUNXI_SRC_TYPE_EDGE_FALLING,
SUNXI_SRC_TYPE_LEVEL_HIGH,
SUNXI_SRC_TYPE_EDGE_RISING,
};
struct sunxi_sc_nmi_reg_offs {
u32 ctrl;
u32 pend;
u32 enable;
};
static struct sunxi_sc_nmi_reg_offs sun7i_reg_offs = {
.ctrl = 0x00,
.pend = 0x04,
.enable = 0x08,
};
static struct sunxi_sc_nmi_reg_offs sun6i_reg_offs = {
.ctrl = 0x00,
.pend = 0x04,
.enable = 0x34,
};
static inline void sunxi_sc_nmi_write(struct irq_chip_generic *gc, u32 off,
u32 val)
{
irq_reg_writel(val, gc->reg_base + off);
}
static inline u32 sunxi_sc_nmi_read(struct irq_chip_generic *gc, u32 off)
{
return irq_reg_readl(gc->reg_base + off);
}
static void sunxi_sc_nmi_handle_irq(unsigned int irq, struct irq_desc *desc)
{
struct irq_domain *domain = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_get_chip(irq);
unsigned int virq = irq_find_mapping(domain, 0);
chained_irq_enter(chip, desc);
generic_handle_irq(virq);
chained_irq_exit(chip, desc);
}
static int sunxi_sc_nmi_set_type(struct irq_data *data, unsigned int flow_type)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
struct irq_chip_type *ct = gc->chip_types;
u32 src_type_reg;
u32 ctrl_off = ct->regs.type;
unsigned int src_type;
unsigned int i;
irq_gc_lock(gc);
switch (flow_type & IRQF_TRIGGER_MASK) {
case IRQ_TYPE_EDGE_FALLING:
src_type = SUNXI_SRC_TYPE_EDGE_FALLING;
break;
case IRQ_TYPE_EDGE_RISING:
src_type = SUNXI_SRC_TYPE_EDGE_RISING;
break;
case IRQ_TYPE_LEVEL_HIGH:
src_type = SUNXI_SRC_TYPE_LEVEL_HIGH;
break;
case IRQ_TYPE_NONE:
case IRQ_TYPE_LEVEL_LOW:
src_type = SUNXI_SRC_TYPE_LEVEL_LOW;
break;
default:
irq_gc_unlock(gc);
pr_err("%s: Cannot assign multiple trigger modes to IRQ %d.\n",
__func__, data->irq);
return -EBADR;
}
irqd_set_trigger_type(data, flow_type);
irq_setup_alt_chip(data, flow_type);
for (i = 0; i <= gc->num_ct; i++, ct++)
if (ct->type & flow_type)
ctrl_off = ct->regs.type;
src_type_reg = sunxi_sc_nmi_read(gc, ctrl_off);
src_type_reg &= ~SUNXI_NMI_SRC_TYPE_MASK;
src_type_reg |= src_type;
sunxi_sc_nmi_write(gc, ctrl_off, src_type_reg);
irq_gc_unlock(gc);
return IRQ_SET_MASK_OK;
}
static int __init sunxi_sc_nmi_irq_init(struct device_node *node,
struct sunxi_sc_nmi_reg_offs *reg_offs)
{
struct irq_domain *domain;
struct irq_chip_generic *gc;
unsigned int irq;
unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
int ret;
domain = irq_domain_add_linear(node, 1, &irq_generic_chip_ops, NULL);
if (!domain) {
pr_err("%s: Could not register interrupt domain.\n", node->name);
return -ENOMEM;
}
ret = irq_alloc_domain_generic_chips(domain, 1, 2, node->name,
handle_fasteoi_irq, clr, 0,
IRQ_GC_INIT_MASK_CACHE);
if (ret) {
pr_err("%s: Could not allocate generic interrupt chip.\n",
node->name);
goto fail_irqd_remove;
}
irq = irq_of_parse_and_map(node, 0);
if (irq <= 0) {
pr_err("%s: unable to parse irq\n", node->name);
ret = -EINVAL;
goto fail_irqd_remove;
}
gc = irq_get_domain_generic_chip(domain, 0);
gc->reg_base = of_iomap(node, 0);
if (!gc->reg_base) {
pr_err("%s: unable to map resource\n", node->name);
ret = -ENOMEM;
goto fail_irqd_remove;
}
gc->chip_types[0].type = IRQ_TYPE_LEVEL_MASK;
gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
gc->chip_types[0].chip.irq_eoi = irq_gc_ack_set_bit;
gc->chip_types[0].chip.irq_set_type = sunxi_sc_nmi_set_type;
gc->chip_types[0].chip.flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED;
gc->chip_types[0].regs.ack = reg_offs->pend;
gc->chip_types[0].regs.mask = reg_offs->enable;
gc->chip_types[0].regs.type = reg_offs->ctrl;
gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH;
gc->chip_types[1].chip.name = gc->chip_types[0].chip.name;
gc->chip_types[1].chip.irq_ack = irq_gc_ack_set_bit;
gc->chip_types[1].chip.irq_mask = irq_gc_mask_clr_bit;
gc->chip_types[1].chip.irq_unmask = irq_gc_mask_set_bit;
gc->chip_types[1].chip.irq_set_type = sunxi_sc_nmi_set_type;
gc->chip_types[1].regs.ack = reg_offs->pend;
gc->chip_types[1].regs.mask = reg_offs->enable;
gc->chip_types[1].regs.type = reg_offs->ctrl;
gc->chip_types[1].handler = handle_edge_irq;
sunxi_sc_nmi_write(gc, reg_offs->enable, 0);
sunxi_sc_nmi_write(gc, reg_offs->pend, 0x1);
irq_set_handler_data(irq, domain);
irq_set_chained_handler(irq, sunxi_sc_nmi_handle_irq);
return 0;
fail_irqd_remove:
irq_domain_remove(domain);
return ret;
}
static int __init sun6i_sc_nmi_irq_init(struct device_node *node,
struct device_node *parent)
{
return sunxi_sc_nmi_irq_init(node, &sun6i_reg_offs);
}
IRQCHIP_DECLARE(sun6i_sc_nmi, "allwinner,sun6i-a31-sc-nmi", sun6i_sc_nmi_irq_init);
static int __init sun7i_sc_nmi_irq_init(struct device_node *node,
struct device_node *parent)
{
return sunxi_sc_nmi_irq_init(node, &sun7i_reg_offs);
}
IRQCHIP_DECLARE(sun7i_sc_nmi, "allwinner,sun7i-a20-sc-nmi", sun7i_sc_nmi_irq_init);
...@@ -228,7 +228,7 @@ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs) ...@@ -228,7 +228,7 @@ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
* Keep iterating over all registered VIC's until there are no pending * Keep iterating over all registered VIC's until there are no pending
* interrupts. * interrupts.
*/ */
static asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs) static void __exception_irq_entry vic_handle_irq(struct pt_regs *regs)
{ {
int i, handled; int i, handled;
......
...@@ -178,8 +178,7 @@ static struct irq_domain_ops vt8500_irq_domain_ops = { ...@@ -178,8 +178,7 @@ static struct irq_domain_ops vt8500_irq_domain_ops = {
.xlate = irq_domain_xlate_onecell, .xlate = irq_domain_xlate_onecell,
}; };
static asmlinkage static void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs)
void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs)
{ {
u32 stat, i; u32 stat, i;
int irqnr, virq; int irqnr, virq;
......
...@@ -122,7 +122,7 @@ static int xtensa_mx_irq_retrigger(struct irq_data *d) ...@@ -122,7 +122,7 @@ static int xtensa_mx_irq_retrigger(struct irq_data *d)
static int xtensa_mx_irq_set_affinity(struct irq_data *d, static int xtensa_mx_irq_set_affinity(struct irq_data *d,
const struct cpumask *dest, bool force) const struct cpumask *dest, bool force)
{ {
unsigned mask = 1u << cpumask_any(dest); unsigned mask = 1u << cpumask_any_and(dest, cpu_online_mask);
set_er(mask, MIROUT(d->hwirq - HW_IRQ_MX_BASE)); set_er(mask, MIROUT(d->hwirq - HW_IRQ_MX_BASE));
return 0; return 0;
......
...@@ -50,7 +50,7 @@ static void zevio_irq_ack(struct irq_data *irqd) ...@@ -50,7 +50,7 @@ static void zevio_irq_ack(struct irq_data *irqd)
readl(gc->reg_base + regs->ack); readl(gc->reg_base + regs->ack);
} }
static asmlinkage void __exception_irq_entry zevio_handle_irq(struct pt_regs *regs) static void __exception_irq_entry zevio_handle_irq(struct pt_regs *regs)
{ {
int irqnr; int irqnr;
......
...@@ -10,8 +10,7 @@ ...@@ -10,8 +10,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/irqchip.h>
#include "irqchip.h"
/* /*
* This special of_device_id is the sentinel at the end of the * This special of_device_id is the sentinel at the end of the
......
...@@ -294,14 +294,12 @@ static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos) ...@@ -294,14 +294,12 @@ static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
static void clear_irq(unsigned int irq) static void clear_irq(unsigned int irq)
{ {
unsigned int pos, nvec; unsigned int pos, nvec;
struct irq_desc *desc;
struct msi_desc *msi; struct msi_desc *msi;
struct pcie_port *pp; struct pcie_port *pp;
struct irq_data *data = irq_get_irq_data(irq); struct irq_data *data = irq_get_irq_data(irq);
/* get the port structure */ /* get the port structure */
desc = irq_to_desc(irq); msi = irq_data_get_msi(data);
msi = irq_desc_get_msi_desc(desc);
pp = sys_to_pcie(msi->dev->bus->sysdata); pp = sys_to_pcie(msi->dev->bus->sysdata);
if (!pp) { if (!pp) {
BUG(); BUG();
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/kernel_stat.h> #include <linux/kernel_stat.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/cio.h> #include <asm/cio.h>
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/irq.h> #include <asm/irq.h>
...@@ -584,8 +585,6 @@ static irqreturn_t do_cio_interrupt(int irq, void *dummy) ...@@ -584,8 +585,6 @@ static irqreturn_t do_cio_interrupt(int irq, void *dummy)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static struct irq_desc *irq_desc_io;
static struct irqaction io_interrupt = { static struct irqaction io_interrupt = {
.name = "IO", .name = "IO",
.handler = do_cio_interrupt, .handler = do_cio_interrupt,
...@@ -596,7 +595,6 @@ void __init init_cio_interrupts(void) ...@@ -596,7 +595,6 @@ void __init init_cio_interrupts(void)
irq_set_chip_and_handler(IO_INTERRUPT, irq_set_chip_and_handler(IO_INTERRUPT,
&dummy_irq_chip, handle_percpu_irq); &dummy_irq_chip, handle_percpu_irq);
setup_irq(IO_INTERRUPT, &io_interrupt); setup_irq(IO_INTERRUPT, &io_interrupt);
irq_desc_io = irq_to_desc(IO_INTERRUPT);
} }
#ifdef CONFIG_CCW_CONSOLE #ifdef CONFIG_CCW_CONSOLE
...@@ -623,7 +621,7 @@ void cio_tsch(struct subchannel *sch) ...@@ -623,7 +621,7 @@ void cio_tsch(struct subchannel *sch)
local_bh_disable(); local_bh_disable();
irq_enter(); irq_enter();
} }
kstat_incr_irqs_this_cpu(IO_INTERRUPT, irq_desc_io); kstat_incr_irq_this_cpu(IO_INTERRUPT);
if (sch->driver && sch->driver->irq) if (sch->driver && sch->driver->irq)
sch->driver->irq(sch); sch->driver->irq(sch);
else else
......
...@@ -166,7 +166,6 @@ static void evtchn_2l_handle_events(unsigned cpu) ...@@ -166,7 +166,6 @@ static void evtchn_2l_handle_events(unsigned cpu)
int start_word_idx, start_bit_idx; int start_word_idx, start_bit_idx;
int word_idx, bit_idx; int word_idx, bit_idx;
int i; int i;
struct irq_desc *desc;
struct shared_info *s = HYPERVISOR_shared_info; struct shared_info *s = HYPERVISOR_shared_info;
struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu); struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu);
...@@ -176,11 +175,8 @@ static void evtchn_2l_handle_events(unsigned cpu) ...@@ -176,11 +175,8 @@ static void evtchn_2l_handle_events(unsigned cpu)
unsigned int evtchn = evtchn_from_irq(irq); unsigned int evtchn = evtchn_from_irq(irq);
word_idx = evtchn / BITS_PER_LONG; word_idx = evtchn / BITS_PER_LONG;
bit_idx = evtchn % BITS_PER_LONG; bit_idx = evtchn % BITS_PER_LONG;
if (active_evtchns(cpu, s, word_idx) & (1ULL << bit_idx)) { if (active_evtchns(cpu, s, word_idx) & (1ULL << bit_idx))
desc = irq_to_desc(irq); generic_handle_irq(irq);
if (desc)
generic_handle_irq_desc(irq, desc);
}
} }
/* /*
...@@ -245,11 +241,8 @@ static void evtchn_2l_handle_events(unsigned cpu) ...@@ -245,11 +241,8 @@ static void evtchn_2l_handle_events(unsigned cpu)
port = (word_idx * BITS_PER_EVTCHN_WORD) + bit_idx; port = (word_idx * BITS_PER_EVTCHN_WORD) + bit_idx;
irq = get_evtchn_to_irq(port); irq = get_evtchn_to_irq(port);
if (irq != -1) { if (irq != -1)
desc = irq_to_desc(irq); generic_handle_irq(irq);
if (desc)
generic_handle_irq_desc(irq, desc);
}
bit_idx = (bit_idx + 1) % BITS_PER_EVTCHN_WORD; bit_idx = (bit_idx + 1) % BITS_PER_EVTCHN_WORD;
......
...@@ -336,9 +336,8 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) ...@@ -336,9 +336,8 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
BUG_ON(irq == -1); BUG_ON(irq == -1);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
cpumask_copy(irq_to_desc(irq)->irq_data.affinity, cpumask_of(cpu)); cpumask_copy(irq_get_irq_data(irq)->affinity, cpumask_of(cpu));
#endif #endif
xen_evtchn_port_bind_to_cpu(info, cpu); xen_evtchn_port_bind_to_cpu(info, cpu);
info->cpu = cpu; info->cpu = cpu;
...@@ -373,10 +372,8 @@ static void xen_irq_init(unsigned irq) ...@@ -373,10 +372,8 @@ static void xen_irq_init(unsigned irq)
{ {
struct irq_info *info; struct irq_info *info;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
struct irq_desc *desc = irq_to_desc(irq);
/* By default all event channels notify CPU#0. */ /* By default all event channels notify CPU#0. */
cpumask_copy(desc->irq_data.affinity, cpumask_of(0)); cpumask_copy(irq_get_irq_data(irq)->affinity, cpumask_of(0));
#endif #endif
info = kzalloc(sizeof(*info), GFP_KERNEL); info = kzalloc(sizeof(*info), GFP_KERNEL);
...@@ -490,13 +487,6 @@ static void pirq_query_unmask(int irq) ...@@ -490,13 +487,6 @@ static void pirq_query_unmask(int irq)
info->u.pirq.flags |= PIRQ_NEEDS_EOI; info->u.pirq.flags |= PIRQ_NEEDS_EOI;
} }
static bool probing_irq(int irq)
{
struct irq_desc *desc = irq_to_desc(irq);
return desc && desc->action == NULL;
}
static void eoi_pirq(struct irq_data *data) static void eoi_pirq(struct irq_data *data)
{ {
int evtchn = evtchn_from_irq(data->irq); int evtchn = evtchn_from_irq(data->irq);
...@@ -538,8 +528,7 @@ static unsigned int __startup_pirq(unsigned int irq) ...@@ -538,8 +528,7 @@ static unsigned int __startup_pirq(unsigned int irq)
BIND_PIRQ__WILL_SHARE : 0; BIND_PIRQ__WILL_SHARE : 0;
rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq); rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq);
if (rc != 0) { if (rc != 0) {
if (!probing_irq(irq)) pr_warn("Failed to obtain physical IRQ %d\n", irq);
pr_info("Failed to obtain physical IRQ %d\n", irq);
return 0; return 0;
} }
evtchn = bind_pirq.port; evtchn = bind_pirq.port;
...@@ -772,17 +761,12 @@ int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, ...@@ -772,17 +761,12 @@ int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
int xen_destroy_irq(int irq) int xen_destroy_irq(int irq)
{ {
struct irq_desc *desc;
struct physdev_unmap_pirq unmap_irq; struct physdev_unmap_pirq unmap_irq;
struct irq_info *info = info_for_irq(irq); struct irq_info *info = info_for_irq(irq);
int rc = -ENOENT; int rc = -ENOENT;
mutex_lock(&irq_mapping_update_lock); mutex_lock(&irq_mapping_update_lock);
desc = irq_to_desc(irq);
if (!desc)
goto out;
if (xen_initial_domain()) { if (xen_initial_domain()) {
unmap_irq.pirq = info->u.pirq.pirq; unmap_irq.pirq = info->u.pirq.pirq;
unmap_irq.domid = info->u.pirq.domid; unmap_irq.domid = info->u.pirq.domid;
...@@ -1251,6 +1235,7 @@ void xen_evtchn_do_upcall(struct pt_regs *regs) ...@@ -1251,6 +1235,7 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
#ifdef CONFIG_X86 #ifdef CONFIG_X86
exit_idle(); exit_idle();
#endif #endif
inc_irq_stat(irq_hv_callback_count);
__xen_evtchn_do_upcall(); __xen_evtchn_do_upcall();
...@@ -1339,7 +1324,7 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu) ...@@ -1339,7 +1324,7 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest, static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest,
bool force) bool force)
{ {
unsigned tcpu = cpumask_first(dest); unsigned tcpu = cpumask_first_and(dest, cpu_online_mask);
return rebind_irq_to_cpu(data->irq, tcpu); return rebind_irq_to_cpu(data->irq, tcpu);
} }
......
...@@ -235,14 +235,10 @@ static uint32_t clear_linked(volatile event_word_t *word) ...@@ -235,14 +235,10 @@ static uint32_t clear_linked(volatile event_word_t *word)
static void handle_irq_for_port(unsigned port) static void handle_irq_for_port(unsigned port)
{ {
int irq; int irq;
struct irq_desc *desc;
irq = get_evtchn_to_irq(port); irq = get_evtchn_to_irq(port);
if (irq != -1) { if (irq != -1)
desc = irq_to_desc(irq); generic_handle_irq(irq);
if (desc)
generic_handle_irq_desc(irq, desc);
}
} }
static void consume_one_event(unsigned cpu, static void consume_one_event(unsigned cpu,
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
extern void synchronize_irq(unsigned int irq); extern void synchronize_irq(unsigned int irq);
extern void synchronize_hardirq(unsigned int irq);
#if defined(CONFIG_TINY_RCU) #if defined(CONFIG_TINY_RCU)
......
...@@ -188,6 +188,7 @@ extern void disable_irq(unsigned int irq); ...@@ -188,6 +188,7 @@ extern void disable_irq(unsigned int irq);
extern void disable_percpu_irq(unsigned int irq); extern void disable_percpu_irq(unsigned int irq);
extern void enable_irq(unsigned int irq); extern void enable_irq(unsigned int irq);
extern void enable_percpu_irq(unsigned int irq, unsigned int type); extern void enable_percpu_irq(unsigned int irq, unsigned int type);
extern void irq_wake_thread(unsigned int irq, void *dev_id);
/* The following three functions are for the core kernel use only. */ /* The following three functions are for the core kernel use only. */
extern void suspend_device_irqs(void); extern void suspend_device_irqs(void);
......
...@@ -303,6 +303,10 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d) ...@@ -303,6 +303,10 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
* @irq_pm_shutdown: function called from core code on shutdown once per chip * @irq_pm_shutdown: function called from core code on shutdown once per chip
* @irq_calc_mask: Optional function to set irq_data.mask for special cases * @irq_calc_mask: Optional function to set irq_data.mask for special cases
* @irq_print_chip: optional to print special chip info in show_interrupts * @irq_print_chip: optional to print special chip info in show_interrupts
* @irq_request_resources: optional to request resources before calling
* any other callback related to this irq
* @irq_release_resources: optional to release resources acquired with
* irq_request_resources
* @flags: chip specific flags * @flags: chip specific flags
*/ */
struct irq_chip { struct irq_chip {
...@@ -336,6 +340,8 @@ struct irq_chip { ...@@ -336,6 +340,8 @@ struct irq_chip {
void (*irq_calc_mask)(struct irq_data *data); void (*irq_calc_mask)(struct irq_data *data);
void (*irq_print_chip)(struct irq_data *data, struct seq_file *p); void (*irq_print_chip)(struct irq_data *data, struct seq_file *p);
int (*irq_request_resources)(struct irq_data *data);
void (*irq_release_resources)(struct irq_data *data);
unsigned long flags; unsigned long flags;
}; };
...@@ -349,6 +355,8 @@ struct irq_chip { ...@@ -349,6 +355,8 @@ struct irq_chip {
* IRQCHIP_ONOFFLINE_ENABLED: Only call irq_on/off_line callbacks * IRQCHIP_ONOFFLINE_ENABLED: Only call irq_on/off_line callbacks
* when irq enabled * when irq enabled
* IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip * IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip
* IRQCHIP_ONESHOT_SAFE: One shot does not require mask/unmask
* IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode
*/ */
enum { enum {
IRQCHIP_SET_TYPE_MASKED = (1 << 0), IRQCHIP_SET_TYPE_MASKED = (1 << 0),
...@@ -357,6 +365,7 @@ enum { ...@@ -357,6 +365,7 @@ enum {
IRQCHIP_ONOFFLINE_ENABLED = (1 << 3), IRQCHIP_ONOFFLINE_ENABLED = (1 << 3),
IRQCHIP_SKIP_SET_WAKE = (1 << 4), IRQCHIP_SKIP_SET_WAKE = (1 << 4),
IRQCHIP_ONESHOT_SAFE = (1 << 5), IRQCHIP_ONESHOT_SAFE = (1 << 5),
IRQCHIP_EOI_THREADED = (1 << 6),
}; };
/* This include will go away once we isolated irq_desc usage to core code */ /* This include will go away once we isolated irq_desc usage to core code */
......
...@@ -51,14 +51,8 @@ DECLARE_PER_CPU(struct kernel_cpustat, kernel_cpustat); ...@@ -51,14 +51,8 @@ DECLARE_PER_CPU(struct kernel_cpustat, kernel_cpustat);
extern unsigned long long nr_context_switches(void); extern unsigned long long nr_context_switches(void);
#include <linux/irq.h>
extern unsigned int kstat_irqs_cpu(unsigned int irq, int cpu); extern unsigned int kstat_irqs_cpu(unsigned int irq, int cpu);
extern void kstat_incr_irq_this_cpu(unsigned int irq);
#define kstat_incr_irqs_this_cpu(irqno, DESC) \
do { \
__this_cpu_inc(*(DESC)->kstat_irqs); \
__this_cpu_inc(kstat.irqs_sum); \
} while (0)
static inline void kstat_incr_softirqs_this_cpu(unsigned int irq) static inline void kstat_incr_softirqs_this_cpu(unsigned int irq)
{ {
......
...@@ -281,6 +281,19 @@ void unmask_irq(struct irq_desc *desc) ...@@ -281,6 +281,19 @@ void unmask_irq(struct irq_desc *desc)
} }
} }
void unmask_threaded_irq(struct irq_desc *desc)
{
struct irq_chip *chip = desc->irq_data.chip;
if (chip->flags & IRQCHIP_EOI_THREADED)
chip->irq_eoi(&desc->irq_data);
if (chip->irq_unmask) {
chip->irq_unmask(&desc->irq_data);
irq_state_clr_masked(desc);
}
}
/* /*
* handle_nested_irq - Handle a nested irq from a irq thread * handle_nested_irq - Handle a nested irq from a irq thread
* @irq: the interrupt number * @irq: the interrupt number
...@@ -435,6 +448,27 @@ static inline void preflow_handler(struct irq_desc *desc) ...@@ -435,6 +448,27 @@ static inline void preflow_handler(struct irq_desc *desc)
static inline void preflow_handler(struct irq_desc *desc) { } static inline void preflow_handler(struct irq_desc *desc) { }
#endif #endif
static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip)
{
if (!(desc->istate & IRQS_ONESHOT)) {
chip->irq_eoi(&desc->irq_data);
return;
}
/*
* We need to unmask in the following cases:
* - Oneshot irq which did not wake the thread (caused by a
* spurious interrupt or a primary handler handling it
* completely).
*/
if (!irqd_irq_disabled(&desc->irq_data) &&
irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot) {
chip->irq_eoi(&desc->irq_data);
unmask_irq(desc);
} else if (!(chip->flags & IRQCHIP_EOI_THREADED)) {
chip->irq_eoi(&desc->irq_data);
}
}
/** /**
* handle_fasteoi_irq - irq handler for transparent controllers * handle_fasteoi_irq - irq handler for transparent controllers
* @irq: the interrupt number * @irq: the interrupt number
...@@ -448,6 +482,8 @@ static inline void preflow_handler(struct irq_desc *desc) { } ...@@ -448,6 +482,8 @@ static inline void preflow_handler(struct irq_desc *desc) { }
void void
handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
{ {
struct irq_chip *chip = desc->irq_data.chip;
raw_spin_lock(&desc->lock); raw_spin_lock(&desc->lock);
if (unlikely(irqd_irq_inprogress(&desc->irq_data))) if (unlikely(irqd_irq_inprogress(&desc->irq_data)))
...@@ -473,18 +509,14 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) ...@@ -473,18 +509,14 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
preflow_handler(desc); preflow_handler(desc);
handle_irq_event(desc); handle_irq_event(desc);
if (desc->istate & IRQS_ONESHOT) cond_unmask_eoi_irq(desc, chip);
cond_unmask_irq(desc);
out_eoi:
desc->irq_data.chip->irq_eoi(&desc->irq_data);
out_unlock:
raw_spin_unlock(&desc->lock); raw_spin_unlock(&desc->lock);
return; return;
out: out:
if (!(desc->irq_data.chip->flags & IRQCHIP_EOI_IF_HANDLED)) if (!(chip->flags & IRQCHIP_EOI_IF_HANDLED))
goto out_eoi; chip->irq_eoi(&desc->irq_data);
goto out_unlock; raw_spin_unlock(&desc->lock);
} }
/** /**
......
...@@ -41,6 +41,7 @@ irqreturn_t no_action(int cpl, void *dev_id) ...@@ -41,6 +41,7 @@ irqreturn_t no_action(int cpl, void *dev_id)
{ {
return IRQ_NONE; return IRQ_NONE;
} }
EXPORT_SYMBOL_GPL(no_action);
static void warn_no_thread(unsigned int irq, struct irqaction *action) static void warn_no_thread(unsigned int irq, struct irqaction *action)
{ {
...@@ -51,7 +52,7 @@ static void warn_no_thread(unsigned int irq, struct irqaction *action) ...@@ -51,7 +52,7 @@ static void warn_no_thread(unsigned int irq, struct irqaction *action)
"but no thread function available.", irq, action->name); "but no thread function available.", irq, action->name);
} }
static void irq_wake_thread(struct irq_desc *desc, struct irqaction *action) void __irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
{ {
/* /*
* In case the thread crashed and was killed we just pretend that * 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,7 +158,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
break; break;
} }
irq_wake_thread(desc, action); __irq_wake_thread(desc, action);
/* Fall through to add to randomness */ /* Fall through to add to randomness */
case IRQ_HANDLED: case IRQ_HANDLED:
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* of this file for your non core code. * of this file for your non core code.
*/ */
#include <linux/irqdesc.h> #include <linux/irqdesc.h>
#include <linux/kernel_stat.h>
#ifdef CONFIG_SPARSE_IRQ #ifdef CONFIG_SPARSE_IRQ
# define IRQ_BITMAP_BITS (NR_IRQS + 8196) # define IRQ_BITMAP_BITS (NR_IRQS + 8196)
...@@ -73,6 +74,7 @@ extern void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu); ...@@ -73,6 +74,7 @@ extern void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu);
extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu); extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu);
extern void mask_irq(struct irq_desc *desc); extern void mask_irq(struct irq_desc *desc);
extern void unmask_irq(struct irq_desc *desc); extern void unmask_irq(struct irq_desc *desc);
extern void unmask_threaded_irq(struct irq_desc *desc);
extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr); extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr);
...@@ -82,6 +84,7 @@ irqreturn_t handle_irq_event(struct irq_desc *desc); ...@@ -82,6 +84,7 @@ irqreturn_t handle_irq_event(struct irq_desc *desc);
/* Resending of interrupts :*/ /* Resending of interrupts :*/
void check_irq_resend(struct irq_desc *desc, unsigned int irq); void check_irq_resend(struct irq_desc *desc, unsigned int irq);
bool irq_wait_for_poll(struct irq_desc *desc); bool irq_wait_for_poll(struct irq_desc *desc);
void __irq_wake_thread(struct irq_desc *desc, struct irqaction *action);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
extern void register_irq_proc(unsigned int irq, struct irq_desc *desc); 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,3 +182,9 @@ static inline bool irqd_has_set(struct irq_data *d, unsigned int mask)
{ {
return d->state_use_accessors & mask; return d->state_use_accessors & mask;
} }
static inline void kstat_incr_irqs_this_cpu(unsigned int irq, struct irq_desc *desc)
{
__this_cpu_inc(*desc->kstat_irqs);
__this_cpu_inc(kstat.irqs_sum);
}
...@@ -489,6 +489,11 @@ void dynamic_irq_cleanup(unsigned int irq) ...@@ -489,6 +489,11 @@ void dynamic_irq_cleanup(unsigned int irq)
raw_spin_unlock_irqrestore(&desc->lock, flags); raw_spin_unlock_irqrestore(&desc->lock, flags);
} }
void kstat_incr_irq_this_cpu(unsigned int irq)
{
kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
}
unsigned int kstat_irqs_cpu(unsigned int irq, int cpu) unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
{ {
struct irq_desc *desc = irq_to_desc(irq); struct irq_desc *desc = irq_to_desc(irq);
......
...@@ -32,24 +32,10 @@ static int __init setup_forced_irqthreads(char *arg) ...@@ -32,24 +32,10 @@ static int __init setup_forced_irqthreads(char *arg)
early_param("threadirqs", setup_forced_irqthreads); early_param("threadirqs", setup_forced_irqthreads);
#endif #endif
/** static void __synchronize_hardirq(struct irq_desc *desc)
* synchronize_irq - wait for pending IRQ handlers (on other CPUs)
* @irq: interrupt number to wait for
*
* This function waits for any pending IRQ handlers for this interrupt
* to complete before returning. If you use this function while
* holding a resource the IRQ handler may need you will deadlock.
*
* This function may be called - with care - from IRQ context.
*/
void synchronize_irq(unsigned int irq)
{ {
struct irq_desc *desc = irq_to_desc(irq);
bool inprogress; bool inprogress;
if (!desc)
return;
do { do {
unsigned long flags; unsigned long flags;
...@@ -67,12 +53,56 @@ void synchronize_irq(unsigned int irq) ...@@ -67,12 +53,56 @@ void synchronize_irq(unsigned int irq)
/* Oops, that failed? */ /* Oops, that failed? */
} while (inprogress); } while (inprogress);
}
/* /**
* We made sure that no hardirq handler is running. Now verify * synchronize_hardirq - wait for pending hard IRQ handlers (on other CPUs)
* that no threaded handlers are active. * @irq: interrupt number to wait for
*/ *
wait_event(desc->wait_for_threads, !atomic_read(&desc->threads_active)); * This function waits for any pending hard IRQ handlers for this
* interrupt to complete before returning. If you use this
* function while holding a resource the IRQ handler may need you
* will deadlock. It does not take associated threaded handlers
* into account.
*
* Do not use this for shutdown scenarios where you must be sure
* that all parts (hardirq and threaded handler) have completed.
*
* This function may be called - with care - from IRQ context.
*/
void synchronize_hardirq(unsigned int irq)
{
struct irq_desc *desc = irq_to_desc(irq);
if (desc)
__synchronize_hardirq(desc);
}
EXPORT_SYMBOL(synchronize_hardirq);
/**
* synchronize_irq - wait for pending IRQ handlers (on other CPUs)
* @irq: interrupt number to wait for
*
* This function waits for any pending IRQ handlers for this interrupt
* to complete before returning. If you use this function while
* holding a resource the IRQ handler may need you will deadlock.
*
* This function may be called - with care - from IRQ context.
*/
void synchronize_irq(unsigned int irq)
{
struct irq_desc *desc = irq_to_desc(irq);
if (desc) {
__synchronize_hardirq(desc);
/*
* We made sure that no hardirq handler is
* running. Now verify that no threaded handlers are
* active.
*/
wait_event(desc->wait_for_threads,
!atomic_read(&desc->threads_active));
}
} }
EXPORT_SYMBOL(synchronize_irq); EXPORT_SYMBOL(synchronize_irq);
...@@ -718,7 +748,7 @@ static void irq_finalize_oneshot(struct irq_desc *desc, ...@@ -718,7 +748,7 @@ static void irq_finalize_oneshot(struct irq_desc *desc,
if (!desc->threads_oneshot && !irqd_irq_disabled(&desc->irq_data) && if (!desc->threads_oneshot && !irqd_irq_disabled(&desc->irq_data) &&
irqd_irq_masked(&desc->irq_data)) irqd_irq_masked(&desc->irq_data))
unmask_irq(desc); unmask_threaded_irq(desc);
out_unlock: out_unlock:
raw_spin_unlock_irq(&desc->lock); raw_spin_unlock_irq(&desc->lock);
...@@ -727,7 +757,7 @@ static void irq_finalize_oneshot(struct irq_desc *desc, ...@@ -727,7 +757,7 @@ static void irq_finalize_oneshot(struct irq_desc *desc,
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* /*
* Check whether we need to chasnge the affinity of the interrupt thread. * Check whether we need to change the affinity of the interrupt thread.
*/ */
static void static void
irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action)
...@@ -880,6 +910,33 @@ static int irq_thread(void *data) ...@@ -880,6 +910,33 @@ static int irq_thread(void *data)
return 0; return 0;
} }
/**
* irq_wake_thread - wake the irq thread for the action identified by dev_id
* @irq: Interrupt line
* @dev_id: Device identity for which the thread should be woken
*
*/
void irq_wake_thread(unsigned int irq, void *dev_id)
{
struct irq_desc *desc = irq_to_desc(irq);
struct irqaction *action;
unsigned long flags;
if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc)))
return;
raw_spin_lock_irqsave(&desc->lock, flags);
for (action = desc->action; action; action = action->next) {
if (action->dev_id == dev_id) {
if (action->thread)
__irq_wake_thread(desc, action);
break;
}
}
raw_spin_unlock_irqrestore(&desc->lock, flags);
}
EXPORT_SYMBOL_GPL(irq_wake_thread);
static void irq_setup_forced_threading(struct irqaction *new) static void irq_setup_forced_threading(struct irqaction *new)
{ {
if (!force_irqthreads) if (!force_irqthreads)
...@@ -896,6 +953,23 @@ static void irq_setup_forced_threading(struct irqaction *new) ...@@ -896,6 +953,23 @@ static void irq_setup_forced_threading(struct irqaction *new)
} }
} }
static int irq_request_resources(struct irq_desc *desc)
{
struct irq_data *d = &desc->irq_data;
struct irq_chip *c = d->chip;
return c->irq_request_resources ? c->irq_request_resources(d) : 0;
}
static void irq_release_resources(struct irq_desc *desc)
{
struct irq_data *d = &desc->irq_data;
struct irq_chip *c = d->chip;
if (c->irq_release_resources)
c->irq_release_resources(d);
}
/* /*
* Internal function to register an irqaction - typically used to * Internal function to register an irqaction - typically used to
* allocate special interrupts that are part of the architecture. * 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,6 +1165,13 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
} }
if (!shared) { if (!shared) {
ret = irq_request_resources(desc);
if (ret) {
pr_err("Failed to request resources for %s (irq %d) on irqchip %s\n",
new->name, irq, desc->irq_data.chip->name);
goto out_mask;
}
init_waitqueue_head(&desc->wait_for_threads); init_waitqueue_head(&desc->wait_for_threads);
/* Setup the type (level, edge polarity) if configured: */ /* Setup the type (level, edge polarity) if configured: */
...@@ -1261,8 +1342,10 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id) ...@@ -1261,8 +1342,10 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
*action_ptr = action->next; *action_ptr = action->next;
/* If this was the last handler, shut down the IRQ line: */ /* If this was the last handler, shut down the IRQ line: */
if (!desc->action) if (!desc->action) {
irq_shutdown(desc); irq_shutdown(desc);
irq_release_resources(desc);
}
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* make sure affinity_hint is cleaned up */ /* make sure affinity_hint is cleaned up */
......
...@@ -324,15 +324,15 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc) ...@@ -324,15 +324,15 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* create /proc/irq/<irq>/smp_affinity */ /* create /proc/irq/<irq>/smp_affinity */
proc_create_data("smp_affinity", 0600, desc->dir, proc_create_data("smp_affinity", 0644, desc->dir,
&irq_affinity_proc_fops, (void *)(long)irq); &irq_affinity_proc_fops, (void *)(long)irq);
/* create /proc/irq/<irq>/affinity_hint */ /* create /proc/irq/<irq>/affinity_hint */
proc_create_data("affinity_hint", 0400, desc->dir, proc_create_data("affinity_hint", 0444, desc->dir,
&irq_affinity_hint_proc_fops, (void *)(long)irq); &irq_affinity_hint_proc_fops, (void *)(long)irq);
/* create /proc/irq/<irq>/smp_affinity_list */ /* create /proc/irq/<irq>/smp_affinity_list */
proc_create_data("smp_affinity_list", 0600, desc->dir, proc_create_data("smp_affinity_list", 0644, desc->dir,
&irq_affinity_list_proc_fops, (void *)(long)irq); &irq_affinity_list_proc_fops, (void *)(long)irq);
proc_create_data("node", 0444, desc->dir, proc_create_data("node", 0444, desc->dir,
...@@ -372,7 +372,7 @@ void unregister_handler_proc(unsigned int irq, struct irqaction *action) ...@@ -372,7 +372,7 @@ void unregister_handler_proc(unsigned int irq, struct irqaction *action)
static void register_default_affinity_proc(void) static void register_default_affinity_proc(void)
{ {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
proc_create("irq/default_smp_affinity", 0600, NULL, proc_create("irq/default_smp_affinity", 0644, NULL,
&default_affinity_proc_fops); &default_affinity_proc_fops);
#endif #endif
} }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/smpboot.h> #include <linux/smpboot.h>
#include <linux/tick.h> #include <linux/tick.h>
#include <linux/irq.h>
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <trace/events/irq.h> #include <trace/events/irq.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment