Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 Sep 2015 21:33:35 +0000 (14:33 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 Sep 2015 21:33:35 +0000 (14:33 -0700)
Pull irq updates from Thomas Gleixner:
 "This updated pull request does not contain the last few GIC related
  patches which were reported to cause a regression.  There is a fix
  available, but I let it breed for a couple of days first.

  The irq departement provides:

   - new infrastructure to support non PCI based MSI interrupts
   - a couple of new irq chip drivers
   - the usual pile of fixlets and updates to irq chip drivers
   - preparatory changes for removal of the irq argument from interrupt
     flow handlers
   - preparatory changes to remove IRQF_VALID"

* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (129 commits)
  irqchip/imx-gpcv2: IMX GPCv2 driver for wakeup sources
  irqchip: Add bcm2836 interrupt controller for Raspberry Pi 2
  irqchip: Add documentation for the bcm2836 interrupt controller
  irqchip/bcm2835: Add support for being used as a second level controller
  irqchip/bcm2835: Refactor handle_IRQ() calls out of MAKE_HWIRQ
  PCI: xilinx: Fix typo in function name
  irqchip/gic: Ensure gic_cpu_if_up/down() programs correct GIC instance
  irqchip/gic: Only allow the primary GIC to set the CPU map
  PCI/MSI: pci-xgene-msi: Consolidate chained IRQ handler install/remove
  unicore32/irq: Prepare puv3_gpio_handler for irq argument removal
  tile/pci_gx: Prepare trio_handle_level_irq for irq argument removal
  m68k/irq: Prepare irq handlers for irq argument removal
  C6X/megamode-pic: Prepare megamod_irq_cascade for irq argument removal
  blackfin: Prepare irq handlers for irq argument removal
  arc/irq: Prepare idu_cascade_isr for irq argument removal
  sparc/irq: Use access helper irq_data_get_affinity_mask()
  sparc/irq: Use helper irq_data_get_irq_handler_data()
  parisc/irq: Use access helper irq_data_get_affinity_mask()
  mn10300/irq: Use access helper irq_data_get_affinity_mask()
  irqchip/i8259: Prepare i8259_irq_dispatch for irq argument removal
  ...

161 files changed:
Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2836-l1-intc.txt [new file with mode: 0644]
arch/alpha/kernel/irq.c
arch/arc/kernel/mcip.c
arch/arm/mach-shmobile/setup-r8a7779.c
arch/arm/mach-ux500/cpu.c
arch/arm/mach-vexpress/tc2_pm.c
arch/arm/mach-zynq/common.c
arch/avr32/mach-at32ap/extint.c
arch/avr32/mach-at32ap/pio.c
arch/blackfin/mach-bf537/ints-priority.c
arch/blackfin/mach-common/ints-priority.c
arch/c6x/platforms/megamod-pic.c
arch/ia64/kernel/iosapic.c
arch/ia64/kernel/irq.c
arch/ia64/kernel/msi_ia64.c
arch/ia64/sn/kernel/msi_sn.c
arch/m68k/coldfire/intc-5272.c
arch/m68k/mac/oss.c
arch/m68k/mac/psc.c
arch/microblaze/kernel/intc.c
arch/mips/Kconfig
arch/mips/ath79/irq.c
arch/mips/bmips/irq.c
arch/mips/kernel/Makefile
arch/mips/pci/msi-octeon.c
arch/mn10300/kernel/cevt-mn10300.c
arch/mn10300/kernel/irq.c
arch/parisc/kernel/irq.c
arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
arch/powerpc/platforms/cell/axon_msi.c
arch/powerpc/platforms/cell/interrupt.c
arch/powerpc/platforms/embedded6xx/flipper-pic.c
arch/powerpc/platforms/pasemi/msi.c
arch/powerpc/platforms/powermac/pic.c
arch/powerpc/platforms/powernv/opal-irqchip.c
arch/powerpc/platforms/powernv/pci.c
arch/powerpc/platforms/ps3/interrupt.c
arch/powerpc/platforms/pseries/msi.c
arch/powerpc/sysdev/ehv_pic.c
arch/powerpc/sysdev/fsl_msi.c
arch/powerpc/sysdev/i8259.c
arch/powerpc/sysdev/ipic.c
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/mpic_u3msi.c
arch/powerpc/sysdev/ppc4xx_hsta_msi.c
arch/powerpc/sysdev/ppc4xx_msi.c
arch/powerpc/sysdev/qe_lib/qe_ic.c
arch/powerpc/sysdev/xics/ics-opal.c
arch/powerpc/sysdev/xics/ics-rtas.c
arch/powerpc/sysdev/xics/xics-common.c
arch/s390/pci/pci.c
arch/sh/boards/mach-se/7343/irq.c
arch/sh/boards/mach-se/7722/irq.c
arch/sh/boards/mach-se/7724/irq.c
arch/sh/boards/mach-x3proto/gpio.c
arch/sh/kernel/irq.c
arch/sparc/kernel/irq_64.c
arch/sparc/kernel/leon_kernel.c
arch/sparc/kernel/pci.c
arch/sparc/kernel/sun4d_irq.c
arch/sparc/kernel/sun4m_irq.c
arch/tile/kernel/pci_gx.c
arch/unicore32/kernel/irq.c
arch/x86/pci/xen.c
arch/xtensa/kernel/irq.c
drivers/base/Makefile
drivers/base/core.c
drivers/base/platform-msi.c [new file with mode: 0644]
drivers/irqchip/Kconfig
drivers/irqchip/Makefile
drivers/irqchip/exynos-combiner.c
drivers/irqchip/irq-armada-370-xp.c
drivers/irqchip/irq-atmel-aic.c
drivers/irqchip/irq-atmel-aic5.c
drivers/irqchip/irq-bcm2835.c
drivers/irqchip/irq-bcm2836.c [new file with mode: 0644]
drivers/irqchip/irq-bcm7038-l1.c
drivers/irqchip/irq-bcm7120-l2.c
drivers/irqchip/irq-brcmstb-l2.c
drivers/irqchip/irq-clps711x.c
drivers/irqchip/irq-crossbar.c
drivers/irqchip/irq-digicolor.c
drivers/irqchip/irq-dw-apb-ictl.c
drivers/irqchip/irq-gic-v2m.c
drivers/irqchip/irq-gic-v3-its-pci-msi.c [new file with mode: 0644]
drivers/irqchip/irq-gic-v3-its-platform-msi.c [new file with mode: 0644]
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-hip04.c
drivers/irqchip/irq-i8259.c [moved from arch/mips/kernel/i8259.c with 98% similarity]
drivers/irqchip/irq-imgpdc.c
drivers/irqchip/irq-imx-gpcv2.c [new file with mode: 0644]
drivers/irqchip/irq-ingenic.c
drivers/irqchip/irq-keystone.c
drivers/irqchip/irq-metag-ext.c
drivers/irqchip/irq-metag.c
drivers/irqchip/irq-mips-cpu.c
drivers/irqchip/irq-mips-gic.c
drivers/irqchip/irq-mmp.c
drivers/irqchip/irq-moxart.c
drivers/irqchip/irq-mtk-sysirq.c
drivers/irqchip/irq-mxs.c
drivers/irqchip/irq-nvic.c
drivers/irqchip/irq-omap-intc.c
drivers/irqchip/irq-or1k-pic.c
drivers/irqchip/irq-orion.c
drivers/irqchip/irq-renesas-h8300h.c
drivers/irqchip/irq-renesas-h8s.c
drivers/irqchip/irq-renesas-irqc.c
drivers/irqchip/irq-s3c24xx.c
drivers/irqchip/irq-sirfsoc.c
drivers/irqchip/irq-sun4i.c
drivers/irqchip/irq-sunxi-nmi.c
drivers/irqchip/irq-tb10x.c
drivers/irqchip/irq-tegra.c
drivers/irqchip/irq-versatile-fpga.c
drivers/irqchip/irq-vf610-mscm-ir.c
drivers/irqchip/irq-vic.c
drivers/irqchip/irq-vt8500.c
drivers/irqchip/irq-xtensa-mx.c
drivers/irqchip/irq-xtensa-pic.c
drivers/irqchip/irq-zevio.c
drivers/irqchip/irqchip.h [deleted file]
drivers/irqchip/spear-shirq.c
drivers/of/irq.c
drivers/of/platform.c
drivers/parisc/iosapic.c
drivers/pci/host/pci-keystone-dw.c
drivers/pci/host/pci-keystone.c
drivers/pci/host/pci-xgene-msi.c
drivers/pci/host/pcie-designware.c
drivers/pci/host/pcie-xilinx.c
drivers/pci/msi.c
drivers/pci/of.c
drivers/pci/probe.c
drivers/pci/xen-pcifront.c
drivers/sh/intc/chip.c
drivers/sh/intc/core.c
drivers/sh/intc/virq.c
drivers/spmi/spmi-pmic-arb.c
include/linux/device.h
include/linux/irq.h
include/linux/irqchip/arm-gic-v3.h
include/linux/irqchip/arm-gic.h
include/linux/irqdomain.h
include/linux/msi.h
include/linux/of_irq.h
include/linux/pci.h
kernel/irq/chip.c
kernel/irq/generic-chip.c
kernel/irq/handle.c
kernel/irq/internals.h
kernel/irq/irqdesc.c
kernel/irq/irqdomain.c
kernel/irq/manage.c
kernel/irq/msi.c
kernel/irq/pm.c
kernel/irq/resend.c
kernel/irq/spurious.c

index 7da578d72123374f74e1d41575dc316c34a5fa9d..2d6c8bb4d827b99e9f1c807b655888dc16c8e575 100644 (file)
@@ -5,9 +5,14 @@ The BCM2835 contains a custom top-level interrupt controller, which supports
 controller, or the HW block containing it, is referred to occasionally
 as "armctrl" in the SoC documentation, hence naming of this binding.
 
+The BCM2836 contains the same interrupt controller with the same
+interrupts, but the per-CPU interrupt controller is the root, and an
+interrupt there indicates that the ARMCTRL has an interrupt to handle.
+
 Required properties:
 
-- compatible : should be "brcm,bcm2835-armctrl-ic"
+- compatible : should be "brcm,bcm2835-armctrl-ic" or
+                 "brcm,bcm2836-armctrl-ic"
 - 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
@@ -20,6 +25,12 @@ Required properties:
   The 2nd cell contains the interrupt number within the bank. Valid values
   are 0..7 for bank 0, and 0..31 for bank 1.
 
+Additional required properties for brcm,bcm2836-armctrl-ic:
+- interrupt-parent : Specifies the parent interrupt controller when this
+  controller is the second level.
+- interrupts : Specifies the interrupt on the parent for this interrupt
+  controller to handle.
+
 The interrupt sources are as follows:
 
 Bank 0:
@@ -102,9 +113,21 @@ Bank 2:
 
 Example:
 
+/* BCM2835, first level */
 intc: interrupt-controller {
        compatible = "brcm,bcm2835-armctrl-ic";
        reg = <0x7e00b200 0x200>;
        interrupt-controller;
        #interrupt-cells = <2>;
 };
+
+/* BCM2836, second level */
+intc: interrupt-controller {
+       compatible = "brcm,bcm2836-armctrl-ic";
+       reg = <0x7e00b200 0x200>;
+       interrupt-controller;
+       #interrupt-cells = <2>;
+
+       interrupt-parent = <&local_intc>;
+       interrupts = <8>;
+};
diff --git a/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2836-l1-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2836-l1-intc.txt
new file mode 100644 (file)
index 0000000..f320dcd
--- /dev/null
@@ -0,0 +1,37 @@
+BCM2836 per-CPU interrupt controller
+
+The BCM2836 has a per-cpu interrupt controller for the timer, PMU
+events, and SMP IPIs.  One of the CPUs may receive interrupts for the
+peripheral (GPU) events, which chain to the BCM2835-style interrupt
+controller.
+
+Required properties:
+
+- compatible:          Should be "brcm,bcm2836-l1-intc"
+- 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 1
+
+Please refer to interrupts.txt in this directory for details of the common
+Interrupt Controllers bindings used by client devices.
+
+The interrupt sources are as follows:
+
+0: CNTPSIRQ
+1: CNTPNSIRQ
+2: CNTHPIRQ
+3: CNTVIRQ
+8: GPU_FAST
+9: PMU_FAST
+
+Example:
+
+local_intc: local_intc {
+       compatible = "brcm,bcm2836-l1-intc";
+       reg = <0x40000000 0x100>;
+       interrupt-controller;
+       #interrupt-cells = <1>;
+       interrupt-parent = <&local_intc>;
+};
index 51f2c8654253f2bd6667ccff24c0db09a7f80ccc..2804648c8ff4008d15761145b92167e721212935 100644 (file)
@@ -59,7 +59,7 @@ int irq_select_affinity(unsigned int irq)
                cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0);
        last_cpu = cpu;
 
-       cpumask_copy(data->affinity, cpumask_of(cpu));
+       cpumask_copy(irq_data_get_affinity_mask(data), cpumask_of(cpu));
        chip->irq_set_affinity(data, cpumask_of(cpu), false);
        return 0;
 }
index 2fb86589054de6c0b051325463ebd03236c70299..d9e44b62df05d81a31305048aa91290784980e9d 100644 (file)
@@ -252,9 +252,10 @@ static struct irq_chip idu_irq_chip = {
 
 static int idu_first_irq;
 
-static void idu_cascade_isr(unsigned int core_irq, struct irq_desc *desc)
+static void idu_cascade_isr(unsigned int __core_irq, struct irq_desc *desc)
 {
        struct irq_domain *domain = irq_desc_get_handler_data(desc);
+       unsigned int core_irq = irq_desc_get_irq(desc);
        unsigned int idu_irq;
 
        idu_irq = core_irq - idu_first_irq;
index 7ca8919995471bfdf2a6bbccea4224604a2e2c9a..6bfa6407a27c0baed01a04c17f223b0e6087c5cf 100644 (file)
@@ -62,8 +62,6 @@ static void __init r8a7779_map_io(void)
 
 static void __init r8a7779_init_irq_dt(void)
 {
-       gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE);
-
        irqchip_init();
 
        /* route all interrupts to ARM */
index b316e18a76aa1d14ba5d7ce5bc7a77f9fc8bb930..41b81c4fbe636593ef26f1dc2de110b435ff61cf 100644 (file)
@@ -56,7 +56,6 @@ void __init ux500_init_irq(void)
        struct device_node *np;
        struct resource r;
 
-       gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND);
        irqchip_init();
        np = of_find_compatible_node(NULL, NULL, "stericsson,db8500-prcmu");
        of_address_to_resource(np, 0, &r);
index b3328cd46c332b61d3981ed008947dbe45f8a1b2..1aa4ccece69f97cb06dacb98f146d91bde6560d2 100644 (file)
@@ -80,7 +80,7 @@ static void tc2_pm_cpu_powerdown_prepare(unsigned int cpu, unsigned int cluster)
         * to the CPU by disabling the GIC CPU IF to prevent wfi
         * from completing execution behind power controller back
         */
-       gic_cpu_if_down();
+       gic_cpu_if_down(0);
 }
 
 static void tc2_pm_cluster_powerdown_prepare(unsigned int cluster)
index 6bd4a43e1a7835fecd005e09808de61cece7cdd0..5a6e4e20ca0a98ae07d39d6b764d2f799fc1448d 100644 (file)
@@ -186,7 +186,6 @@ static void __init zynq_map_io(void)
 
 static void __init zynq_irq_init(void)
 {
-       gic_set_irqchip_flags(IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND);
        irqchip_init();
 }
 
index 2d48b6a461664e5fd03d775cc4ba922dd56dacf7..d51ff8f1c541dd8cded2935f6890ce5c48dcb85e 100644 (file)
@@ -128,9 +128,9 @@ static int eic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 
        irqd_set_trigger_type(d, flow_type);
        if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
-               __irq_set_handler_locked(irq, handle_level_irq);
+               irq_set_handler_locked(d, handle_level_irq);
        else
-               __irq_set_handler_locked(irq, handle_edge_irq);
+               irq_set_handler_locked(d, handle_edge_irq);
 
        return IRQ_SET_MASK_OK_NOCOPY;
 }
index 903c7d81d0d521a1b8bcf523c609f83516d8e952..157a5e0e789f6744d62672dd0a03ca066d960079 100644 (file)
@@ -286,7 +286,7 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
        struct pio_device       *pio = irq_desc_get_chip_data(desc);
        unsigned                gpio_irq;
 
-       gpio_irq = (unsigned) irq_get_handler_data(irq);
+       gpio_irq = (unsigned) irq_desc_get_handler_data(desc);
        for (;;) {
                u32             isr;
 
@@ -312,7 +312,6 @@ gpio_irq_setup(struct pio_device *pio, int irq, int gpio_irq)
        unsigned        i;
 
        irq_set_chip_data(irq, pio);
-       irq_set_handler_data(irq, (void *)gpio_irq);
 
        for (i = 0; i < 32; i++, gpio_irq++) {
                irq_set_chip_data(gpio_irq, pio);
@@ -320,7 +319,8 @@ gpio_irq_setup(struct pio_device *pio, int irq, int gpio_irq)
                                         handle_simple_irq);
        }
 
-       irq_set_chained_handler(irq, gpio_irq_handler);
+       irq_set_chained_handler_and_data(irq, gpio_irq_handler,
+                                        (void *)gpio_irq);
 }
 
 /*--------------------------------------------------------------------------*/
index 2137a209a22bdc8f427c1e29c46cc42c97448e28..14b2f74554dc6de142955b98482cbd8c4ff3e76b 100644 (file)
@@ -182,9 +182,11 @@ static struct irq_chip bf537_mac_rx_irqchip = {
        .irq_unmask = bf537_mac_rx_unmask_irq,
 };
 
-static void bf537_demux_mac_rx_irq(unsigned int int_irq,
+static void bf537_demux_mac_rx_irq(unsigned int __int_irq,
                                   struct irq_desc *desc)
 {
+       unsigned int int_irq = irq_desc_get_irq(desc);
+
        if (bfin_read_DMA1_IRQ_STATUS() & (DMA_DONE | DMA_ERR))
                bfin_handle_irq(IRQ_MAC_RX);
        else
index 7236bdfc71e6ae330efa1efb29ffbb8b79c3cf47..a6d1b03cdf3693d2905e27ff113f6bbe34c7c056 100644 (file)
@@ -194,7 +194,8 @@ void bfin_internal_unmask_irq(unsigned int irq)
 #ifdef CONFIG_SMP
 static void bfin_internal_unmask_irq_chip(struct irq_data *d)
 {
-       bfin_internal_unmask_irq_affinity(d->irq, d->affinity);
+       bfin_internal_unmask_irq_affinity(d->irq,
+                                         irq_data_get_affinity_mask(d));
 }
 
 static int bfin_internal_set_affinity(struct irq_data *d,
@@ -685,12 +686,12 @@ void bfin_demux_mac_status_irq(unsigned int int_err_irq,
 }
 #endif
 
-static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle)
+static inline void bfin_set_irq_handler(struct irq_data *d, irq_flow_handler_t handle)
 {
 #ifdef CONFIG_IPIPE
        handle = handle_level_irq;
 #endif
-       __irq_set_handler_locked(irq, handle);
+       irq_set_handler_locked(d, handle);
 }
 
 #ifdef CONFIG_GPIO_ADI
@@ -802,9 +803,9 @@ static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type)
        }
 
        if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
-               bfin_set_irq_handler(irq, handle_edge_irq);
+               bfin_set_irq_handler(d, handle_edge_irq);
        else
-               bfin_set_irq_handler(irq, handle_level_irq);
+               bfin_set_irq_handler(d, handle_level_irq);
 
        return 0;
 }
@@ -824,9 +825,9 @@ static void bfin_demux_gpio_block(unsigned int irq)
        }
 }
 
-void bfin_demux_gpio_irq(unsigned int inta_irq,
-                       struct irq_desc *desc)
+void bfin_demux_gpio_irq(unsigned int __inta_irq, struct irq_desc *desc)
 {
+       unsigned int inta_irq = irq_desc_get_irq(desc);
        unsigned int irq;
 
        switch (inta_irq) {
index 74e3371eb8245bc4c769eff1b8923707c0fc883f..d487698e978a16411cf27b98ea02253ed84c4f44 100644 (file)
@@ -93,10 +93,11 @@ static struct irq_chip megamod_chip = {
        .irq_unmask     = unmask_megamod,
 };
 
-static void megamod_irq_cascade(unsigned int irq, struct irq_desc *desc)
+static void megamod_irq_cascade(unsigned int __irq, struct irq_desc *desc)
 {
        struct megamod_cascade_data *cascade;
        struct megamod_pic *pic;
+       unsigned int irq;
        u32 events;
        int n, idx;
 
@@ -282,8 +283,8 @@ static struct megamod_pic * __init init_megamod_pic(struct device_node *np)
                soc_writel(~0, &pic->regs->evtmask[i]);
                soc_writel(~0, &pic->regs->evtclr[i]);
 
-               irq_set_handler_data(irq, &cascade_data[i]);
-               irq_set_chained_handler(irq, megamod_irq_cascade);
+               irq_set_chained_handler_and_data(irq, megamod_irq_cascade,
+                                                &cascade_data[i]);
        }
 
        /* Finally, set up the MUX registers */
index bc9501e36e776257c53f190df8db2411c7cac273..d2fae054d988cdc9326ad249434bb8ec50b0b45e 100644 (file)
@@ -610,9 +610,9 @@ register_intr (unsigned int gsi, int irq, unsigned char delivery,
                               chip->name, irq_type->name);
                chip = irq_type;
        }
-       __irq_set_chip_handler_name_locked(irq, chip, trigger == IOSAPIC_EDGE ?
-                                          handle_edge_irq : handle_level_irq,
-                                          NULL);
+       irq_set_chip_handler_name_locked(irq_get_irq_data(irq), chip,
+               trigger == IOSAPIC_EDGE ? handle_edge_irq : handle_level_irq,
+               NULL);
        return 0;
 }
 
@@ -838,7 +838,7 @@ iosapic_unregister_intr (unsigned int gsi)
        if (iosapic_intr_info[irq].count == 0) {
 #ifdef CONFIG_SMP
                /* Clear affinity */
-               cpumask_setall(irq_get_irq_data(irq)->affinity);
+               cpumask_setall(irq_get_affinity_mask(irq));
 #endif
                /* Clear the interrupt information */
                iosapic_intr_info[irq].dest = 0;
index 812a1e6b317966610811bb10d97e7c1cdab84a80..de4fc00dea98a8a6208cf7d50c805e7c5cd1bd0b 100644 (file)
@@ -67,7 +67,7 @@ static char irq_redir [NR_IRQS]; // = { [0 ... NR_IRQS-1] = 1 };
 void set_irq_affinity_info (unsigned int irq, int hwid, int redir)
 {
        if (irq < NR_IRQS) {
-               cpumask_copy(irq_get_irq_data(irq)->affinity,
+               cpumask_copy(irq_get_affinity_mask(irq),
                             cpumask_of(cpu_logical_id(hwid)));
                irq_redir[irq] = (char) (redir & 0xff);
        }
@@ -119,8 +119,8 @@ static void migrate_irqs(void)
                if (irqd_is_per_cpu(data))
                        continue;
 
-               if (cpumask_any_and(data->affinity, cpu_online_mask)
-                   >= nr_cpu_ids) {
+               if (cpumask_any_and(irq_data_get_affinity_mask(data),
+                                   cpu_online_mask) >= nr_cpu_ids) {
                        /*
                         * Save it for phase 2 processing
                         */
index d70bf15c690a53227142b6027ce7bb116475ed9d..af4eaec0f7c348019eb787ef2224106925bfac35 100644 (file)
@@ -23,7 +23,7 @@ static int ia64_set_msi_irq_affinity(struct irq_data *idata,
        if (irq_prepare_move(irq, cpu))
                return -1;
 
-       __get_cached_msi_msg(idata->msi_desc, &msg);
+       __get_cached_msi_msg(irq_data_get_msi_desc(idata), &msg);
 
        addr = msg.address_lo;
        addr &= MSI_ADDR_DEST_ID_MASK;
@@ -36,7 +36,7 @@ static int ia64_set_msi_irq_affinity(struct irq_data *idata,
        msg.data = data;
 
        pci_write_msi_msg(irq, &msg);
-       cpumask_copy(idata->affinity, cpumask_of(cpu));
+       cpumask_copy(irq_data_get_affinity_mask(idata), cpumask_of(cpu));
 
        return 0;
 }
@@ -148,7 +148,7 @@ static int dmar_msi_set_affinity(struct irq_data *data,
        msg.address_lo |= MSI_ADDR_DEST_ID_CPU(cpu_physical_id(cpu));
 
        dmar_msi_write(irq, &msg);
-       cpumask_copy(data->affinity, mask);
+       cpumask_copy(irq_data_get_affinity_mask(data), mask);
 
        return 0;
 }
index a0eb27b66d13c8aa88005066adaf8ef6bd2d314d..fb25065b22c626d8af13b29f29a3a8b3248b96bf 100644 (file)
@@ -175,7 +175,7 @@ static int sn_set_msi_irq_affinity(struct irq_data *data,
         * Release XIO resources for the old MSI PCI address
         */
 
-       __get_cached_msi_msg(data->msi_desc, &msg);
+       __get_cached_msi_msg(irq_data_get_msi_desc(data), &msg);
        sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
        pdev = sn_pdev->pdi_linux_pcidev;
        provider = SN_PCIDEV_BUSPROVIDER(pdev);
@@ -206,7 +206,7 @@ static int sn_set_msi_irq_affinity(struct irq_data *data,
        msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
 
        pci_write_msi_msg(irq, &msg);
-       cpumask_copy(data->affinity, cpu_mask);
+       cpumask_copy(irq_data_get_affinity_mask(data), cpu_mask);
 
        return 0;
 }
index d1e2fbad327cecaa4c785e4b270177a6c030cbb5..47371de60427bd61b4d8c0f6abb6f5de95978c80 100644 (file)
@@ -143,8 +143,10 @@ static int intc_irq_set_type(struct irq_data *d, unsigned int type)
  * We need to be careful with the masking/acking due to the side effects
  * of masking an interrupt.
  */
-static void intc_external_irq(unsigned int irq, struct irq_desc *desc)
+static void intc_external_irq(unsigned int __irq, struct irq_desc *desc)
 {
+       unsigned int irq = irq_desc_get_irq(desc);
+
        irq_desc_get_chip(desc)->irq_ack(&desc->irq_data);
        handle_simple_irq(irq, desc);
 }
index bb11dceed7ed2e947ea31f9393539c8b2e6f5c41..191610d97689932ba8413af2ccc27b77e3addc9f 100644 (file)
@@ -63,13 +63,15 @@ void __init oss_nubus_init(void)
  * Handle miscellaneous OSS interrupts.
  */
 
-static void oss_irq(unsigned int irq, struct irq_desc *desc)
+static void oss_irq(unsigned int __irq, struct irq_desc *desc)
 {
        int events = oss->irq_pending &
-                    (OSS_IP_IOPSCC | OSS_IP_SCSI | OSS_IP_IOPISM);
+               (OSS_IP_IOPSCC | OSS_IP_SCSI | OSS_IP_IOPISM);
 
 #ifdef DEBUG_IRQS
        if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) {
+               unsigned int irq = irq_desc_get_irq(desc);
+
                printk("oss_irq: irq %u events = 0x%04X\n", irq,
                        (int) oss->irq_pending);
        }
index 272dde481d170e815d740d0880ae613c3567cca8..3b9e302e7a37f5fa80336bca8f5af07e131b5fbc 100644 (file)
@@ -113,9 +113,10 @@ void __init psc_init(void)
  * PSC interrupt handler. It's a lot like the VIA interrupt handler.
  */
 
-static void psc_irq(unsigned int irq, struct irq_desc *desc)
+static void psc_irq(unsigned int __irq, struct irq_desc *desc)
 {
        unsigned int offset = (unsigned int)irq_desc_get_handler_data(desc);
+       unsigned int irq = irq_desc_get_irq(desc);
        int pIFR        = pIFRbase + offset;
        int pIER        = pIERbase + offset;
        int irq_num;
index 719feee1e043be1625a01d9ad587bd6a719ee0fe..90bec7d71f8562165a2c0cd9f758ac2b78d40599 100644 (file)
 
 #include <linux/irqdomain.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/of_address.h>
 #include <linux/io.h>
 #include <linux/bug.h>
 
-#include "../../drivers/irqchip/irqchip.h"
-
 static void __iomem *intc_baseaddr;
 
 /* No one else should require these constants, so define them locally here. */
index c6d28bce0b408f2f01e95f2d0f561df39dc21d73..4ab9a794bbcd4cc5121ff6c6f8e2b062c75474ad 100644 (file)
@@ -1071,10 +1071,6 @@ config HOTPLUG_CPU
 config SYS_SUPPORTS_HOTPLUG_CPU
        bool
 
-config I8259
-       bool
-       select IRQ_DOMAIN
-
 config MIPS_BONITO64
        bool
 
index afb009603f7fad138ccc12a1c26ffc7bd5422bf6..2021be20d9d940513baf267a7d20a5cedfca8bd2 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/interrupt.h>
 #include <linux/irqchip.h>
 #include <linux/of_irq.h>
-#include "../../../drivers/irqchip/irqchip.h"
 
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
index 14552e58ff7e46463725d35fd3036c62a2901cca..e7fc6f9348baa2e6bc06f881ced25aec7fb40b46 100644 (file)
@@ -34,5 +34,5 @@ void __init arch_init_irq(void)
        irqchip_init();
 }
 
-OF_DECLARE_2(irqchip, mips_cpu_intc, "mti,cpu-interrupt-controller",
+IRQCHIP_DECLARE(mips_cpu_intc, "mti,cpu-interrupt-controller",
             mips_cpu_irq_of_init);
index 3f5cf8aff6f344756b7a08441a771795b944828a..3156c8d253c1c03d70958137d44d3e41cdd26d83 100644 (file)
@@ -61,7 +61,6 @@ obj-$(CONFIG_MIPS_VPE_APSP_API) += rtlx.o
 obj-$(CONFIG_MIPS_VPE_APSP_API_CMP) += rtlx-cmp.o
 obj-$(CONFIG_MIPS_VPE_APSP_API_MT) += rtlx-mt.o
 
-obj-$(CONFIG_I8259)            += i8259.o
 obj-$(CONFIG_IRQ_CPU_RM7K)     += irq-rm7000.o
 obj-$(CONFIG_MIPS_MSC)         += irq-msc01.o
 obj-$(CONFIG_IRQ_TXX9)         += irq_txx9.o
index cffaaf4aae3cb294da6c62c6492e38aba21d2e26..2a5bb849b10efa742a82f8855708b4afcc8a9c4e 100644 (file)
@@ -200,7 +200,7 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
        if (type == PCI_CAP_ID_MSI && nvec > 1)
                return 1;
 
-       list_for_each_entry(entry, &dev->msi_list, list) {
+       for_each_pci_msi_entry(entry, dev) {
                ret = arch_setup_msi_irq(dev, entry);
                if (ret < 0)
                        return ret;
index 3aae9f5a98aac5c98d8858512e77fbdb1ce3d14d..d9b34dd44f04f902354da47561fd9b2cce1f5542 100644 (file)
@@ -116,7 +116,7 @@ int __init init_clockevents(void)
        {
                struct irq_data *data;
                data = irq_get_irq_data(cd->irq);
-               cpumask_copy(data->affinity, cpumask_of(cpu));
+               cpumask_copy(irq_data_get_affinity_mask(data), cpumask_of(cpu));
                iact->flags |= IRQF_NOBALANCING;
        }
 #endif
index 480de70f405980c1828f84b6a0eeba5c75203b73..c716437baa2cdbb3658a015cf6895a366b104122 100644 (file)
@@ -87,7 +87,8 @@ static void mn10300_cpupic_mask_ack(struct irq_data *d)
                tmp2 = GxICR(irq);
 
                irq_affinity_online[irq] =
-                       cpumask_any_and(d->affinity, cpu_online_mask);
+                       cpumask_any_and(irq_data_get_affinity_mask(d),
+                                       cpu_online_mask);
                CROSS_GxICR(irq, irq_affinity_online[irq]) =
                        (tmp & (GxICR_LEVEL | GxICR_ENABLE)) | GxICR_DETECT;
                tmp = CROSS_GxICR(irq, irq_affinity_online[irq]);
@@ -124,7 +125,7 @@ static void mn10300_cpupic_unmask_clear(struct irq_data *d)
        } else {
                tmp = GxICR(irq);
 
-               irq_affinity_online[irq] = cpumask_any_and(d->affinity,
+               irq_affinity_online[irq] = cpumask_any_and(irq_data_get_affinity_mask(d),
                                                           cpu_online_mask);
                CROSS_GxICR(irq, irq_affinity_online[irq]) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
                tmp = CROSS_GxICR(irq, irq_affinity_online[irq]);
@@ -316,15 +317,16 @@ void migrate_irqs(void)
        self = smp_processor_id();
        for (irq = 0; irq < NR_IRQS; irq++) {
                struct irq_data *data = irq_get_irq_data(irq);
+               struct cpumask *mask = irq_data_get_affinity_mask(data);
 
                if (irqd_is_per_cpu(data))
                        continue;
 
-               if (cpumask_test_cpu(self, data->affinity) &&
+               if (cpumask_test_cpu(self, mask) &&
                    !cpumask_intersects(&irq_affinity[irq], cpu_online_mask)) {
                        int cpu_id;
                        cpu_id = cpumask_first(cpu_online_mask);
-                       cpumask_set_cpu(cpu_id, data->affinity);
+                       cpumask_set_cpu(cpu_id, mask);
                }
                /* We need to operate irq_affinity_online atomically. */
                arch_local_cli_save(flags);
@@ -335,8 +337,7 @@ void migrate_irqs(void)
                        GxICR(irq) = x & GxICR_LEVEL;
                        tmp = GxICR(irq);
 
-                       new = cpumask_any_and(data->affinity,
-                                             cpu_online_mask);
+                       new = cpumask_any_and(mask, cpu_online_mask);
                        irq_affinity_online[irq] = new;
 
                        CROSS_GxICR(irq, new) =
index f3191db6e2e94151868129466924b2a456b91ede..413ec3c3f9cc509099b25bf3fc60e0de8195ba53 100644 (file)
@@ -131,7 +131,7 @@ static int cpu_set_affinity_irq(struct irq_data *d, const struct cpumask *dest,
        if (cpu_dest < 0)
                return -1;
 
-       cpumask_copy(d->affinity, dest);
+       cpumask_copy(irq_data_get_affinity_mask(d), dest);
 
        return 0;
 }
@@ -339,7 +339,7 @@ unsigned long txn_affinity_addr(unsigned int irq, int cpu)
 {
 #ifdef CONFIG_SMP
        struct irq_data *d = irq_get_irq_data(irq);
-       cpumask_copy(d->affinity, cpumask_of(cpu));
+       cpumask_copy(irq_data_get_affinity_mask(d), cpumask_of(cpu));
 #endif
 
        return per_cpu(cpu_data, cpu).txn_addr;
@@ -508,7 +508,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
        unsigned long eirr_val;
        int irq, cpu = smp_processor_id();
 #ifdef CONFIG_SMP
-       struct irq_desc *desc;
+       struct irq_data *irq_data;
        cpumask_t dest;
 #endif
 
@@ -522,9 +522,9 @@ void do_cpu_irq_mask(struct pt_regs *regs)
        irq = eirr_to_irq(eirr_val);
 
 #ifdef CONFIG_SMP
-       desc = irq_to_desc(irq);
-       cpumask_copy(&dest, desc->irq_data.affinity);
-       if (irqd_is_per_cpu(&desc->irq_data) &&
+       irq_data = irq_get_irq_data(irq);
+       cpumask_copy(&dest, irq_data_get_affinity_mask(irq_data));
+       if (irqd_is_per_cpu(irq_data) &&
            !cpumask_test_cpu(smp_processor_id(), &dest)) {
                int cpu = cpumask_first(&dest);
 
index ca3a062ed1b928327a15d34d3f6bbb89f0913648..11090ab4bf59a38f2b78074fd8b7a9e10467656d 100644 (file)
@@ -123,7 +123,8 @@ cpld_pic_cascade(unsigned int irq, struct irq_desc *desc)
 }
 
 static int
-cpld_pic_host_match(struct irq_domain *h, struct device_node *node)
+cpld_pic_host_match(struct irq_domain *h, struct device_node *node,
+                   enum irq_domain_bus_token bus_token)
 {
        return cpld_pic_node == node;
 }
index fe51de4fcf135a1d1b355efcd8c20915c3a1b80e..306888acb737a0d94a11fc70497b93e7c173e55d 100644 (file)
@@ -213,7 +213,7 @@ static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)
                return -ENODEV;
        }
 
-       entry = list_first_entry(&dev->msi_list, struct msi_desc, list);
+       entry = first_pci_msi_entry(dev);
 
        for (; dn; dn = of_get_next_parent(dn)) {
                if (entry->msi_attrib.is_64) {
@@ -269,7 +269,7 @@ static int axon_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
        if (rc)
                return rc;
 
-       list_for_each_entry(entry, &dev->msi_list, list) {
+       for_each_pci_msi_entry(entry, dev) {
                virq = irq_create_direct_mapping(msic->irq_domain);
                if (virq == NO_IRQ) {
                        dev_warn(&dev->dev,
@@ -292,7 +292,7 @@ static void axon_msi_teardown_msi_irqs(struct pci_dev *dev)
 
        dev_dbg(&dev->dev, "axon_msi: tearing down msi irqs\n");
 
-       list_for_each_entry(entry, &dev->msi_list, list) {
+       for_each_pci_msi_entry(entry, dev) {
                if (entry->irq == NO_IRQ)
                        continue;
 
index 3af8324c122e60ba952b137bc912806f0f596f9a..a15f1efc295f936d3de64bb17a62d76c86778a1c 100644 (file)
@@ -222,7 +222,8 @@ void iic_request_IPIs(void)
 #endif /* CONFIG_SMP */
 
 
-static int iic_host_match(struct irq_domain *h, struct device_node *node)
+static int iic_host_match(struct irq_domain *h, struct device_node *node,
+                         enum irq_domain_bus_token bus_token)
 {
        return of_device_is_compatible(node,
                                    "IBM,CBEA-Internal-Interrupt-Controller");
index 4cde8e7da4b8e0f9ec8afdd9fd1d0d0eb8f8090a..b7866e01483d5d4eb7f7e816ca38da8a8c1c42b6 100644 (file)
@@ -108,7 +108,8 @@ static int flipper_pic_map(struct irq_domain *h, unsigned int virq,
        return 0;
 }
 
-static int flipper_pic_match(struct irq_domain *h, struct device_node *np)
+static int flipper_pic_match(struct irq_domain *h, struct device_node *np,
+                            enum irq_domain_bus_token bus_token)
 {
        return 1;
 }
index 27f2b187a91b5a17a15f4630defab5216eaf3e2d..e66ef19433387854820e91a2b515d737fd7fd270 100644 (file)
@@ -66,7 +66,7 @@ static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev)
 
        pr_debug("pasemi_msi_teardown_msi_irqs, pdev %p\n", pdev);
 
-       list_for_each_entry(entry, &pdev->msi_list, list) {
+       for_each_pci_msi_entry(entry, pdev) {
                if (entry->irq == NO_IRQ)
                        continue;
 
@@ -94,7 +94,7 @@ static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
        msg.address_hi = 0;
        msg.address_lo = PASEMI_MSI_ADDR;
 
-       list_for_each_entry(entry, &pdev->msi_list, list) {
+       for_each_pci_msi_entry(entry, pdev) {
                /* Allocate 16 interrupts for now, since that's the grouping for
                 * affinity. This can be changed later if it turns out 32 is too
                 * few MSIs for someone, but restrictions will apply to how the
index 59cfc9d63c2d51a711448c1de281cf42fcf04349..6f4f8b060def53cc1afc55b80ffd3f230766bb81 100644 (file)
@@ -268,7 +268,8 @@ static struct irqaction gatwick_cascade_action = {
        .name           = "cascade",
 };
 
-static int pmac_pic_host_match(struct irq_domain *h, struct device_node *node)
+static int pmac_pic_host_match(struct irq_domain *h, struct device_node *node,
+                              enum irq_domain_bus_token bus_token)
 {
        /* We match all, we don't always have a node anyway */
        return 1;
index e2e7d75f52f39234487e1ba51c9014f2c3427b78..2c91ee7800b90e09edb93a35aa162da74071ba8c 100644 (file)
@@ -134,7 +134,8 @@ static void opal_handle_irq_work(struct irq_work *work)
        opal_handle_events(be64_to_cpu(last_outstanding_events));
 }
 
-static int opal_event_match(struct irq_domain *h, struct device_node *node)
+static int opal_event_match(struct irq_domain *h, struct device_node *node,
+                           enum irq_domain_bus_token bus_token)
 {
        return h->of_node == node;
 }
index 765d8ed558d0e16a6dddc16dc7d67d6b6b44b2ce..bc6d4e02e29c1dbc356d2722ba137234221d5a10 100644 (file)
@@ -61,7 +61,7 @@ int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
        if (pdev->no_64bit_msi && !phb->msi32_support)
                return -ENODEV;
 
-       list_for_each_entry(entry, &pdev->msi_list, list) {
+       for_each_pci_msi_entry(entry, pdev) {
                if (!entry->msi_attrib.is_64 && !phb->msi32_support) {
                        pr_warn("%s: Supports only 64-bit MSIs\n",
                                pci_name(pdev));
@@ -103,7 +103,7 @@ void pnv_teardown_msi_irqs(struct pci_dev *pdev)
        if (WARN_ON(!phb))
                return;
 
-       list_for_each_entry(entry, &pdev->msi_list, list) {
+       for_each_pci_msi_entry(entry, pdev) {
                if (entry->irq == NO_IRQ)
                        continue;
                irq_set_msi_desc(entry->irq, NULL);
index a6c42f34303aaa3ae0d47542493006fcd952bded..638c4060938e387aa55629a085dd0fa1ad993e4c 100644 (file)
@@ -678,7 +678,8 @@ static int ps3_host_map(struct irq_domain *h, unsigned int virq,
        return 0;
 }
 
-static int ps3_host_match(struct irq_domain *h, struct device_node *np)
+static int ps3_host_match(struct irq_domain *h, struct device_node *np,
+                         enum irq_domain_bus_token bus_token)
 {
        /* Match all */
        return 1;
index c22bb647cce678cdc9eac5121d1efddeaf00e37e..272e9ec1ab54173b95db1c57f93dff60cf2276fe 100644 (file)
@@ -118,7 +118,7 @@ static void rtas_teardown_msi_irqs(struct pci_dev *pdev)
 {
        struct msi_desc *entry;
 
-       list_for_each_entry(entry, &pdev->msi_list, list) {
+       for_each_pci_msi_entry(entry, pdev) {
                if (entry->irq == NO_IRQ)
                        continue;
 
@@ -350,7 +350,7 @@ static int check_msix_entries(struct pci_dev *pdev)
         * So we must reject such requests. */
 
        expected = 0;
-       list_for_each_entry(entry, &pdev->msi_list, list) {
+       for_each_pci_msi_entry(entry, pdev) {
                if (entry->msi_attrib.entry_nr != expected) {
                        pr_debug("rtas_msi: bad MSI-X entries.\n");
                        return -EINVAL;
@@ -462,7 +462,7 @@ again:
        }
 
        i = 0;
-       list_for_each_entry(entry, &pdev->msi_list, list) {
+       for_each_pci_msi_entry(entry, pdev) {
                hwirq = rtas_query_irq_number(pdn, i++);
                if (hwirq < 0) {
                        pr_debug("rtas_msi: error (%d) getting hwirq\n", rc);
index 2d20f10a42030394581c001e9f19793ebe4667bd..eca0b00794fa567edb3edc2d12650328b4dec486 100644 (file)
@@ -177,7 +177,8 @@ unsigned int ehv_pic_get_irq(void)
        return irq_linear_revmap(global_ehv_pic->irqhost, irq);
 }
 
-static int ehv_pic_host_match(struct irq_domain *h, struct device_node *node)
+static int ehv_pic_host_match(struct irq_domain *h, struct device_node *node,
+                             enum irq_domain_bus_token bus_token)
 {
        /* Exact match, unless ehv_pic node is NULL */
        return h->of_node == NULL || h->of_node == node;
index 5236e5427c38c2c922a2266a16ea4d172db3ef21..5916da1856a78d924230ede7353ed84a8b1fa8a0 100644 (file)
@@ -129,7 +129,7 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
        struct msi_desc *entry;
        struct fsl_msi *msi_data;
 
-       list_for_each_entry(entry, &pdev->msi_list, list) {
+       for_each_pci_msi_entry(entry, pdev) {
                if (entry->irq == NO_IRQ)
                        continue;
                msi_data = irq_get_chip_data(entry->irq);
@@ -219,7 +219,7 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
                }
        }
 
-       list_for_each_entry(entry, &pdev->msi_list, list) {
+       for_each_pci_msi_entry(entry, pdev) {
                /*
                 * Loop over all the MSI devices until we find one that has an
                 * available interrupt.
index 31c33475c7b7042e2224a1094c9070c558096990..e1a9c2c2d5d357c7e88083d60a6f89c0d04219c2 100644 (file)
@@ -162,7 +162,8 @@ static struct resource pic_edgectrl_iores = {
        .flags = IORESOURCE_BUSY,
 };
 
-static int i8259_host_match(struct irq_domain *h, struct device_node *node)
+static int i8259_host_match(struct irq_domain *h, struct device_node *node,
+                           enum irq_domain_bus_token bus_token)
 {
        return h->of_node == NULL || h->of_node == node;
 }
index d78f1364b639d8ab0f208d37b0ef8662b3d7568e..6b2b689148104a25003fba7380af676f2a85e055 100644 (file)
@@ -671,7 +671,8 @@ static struct irq_chip ipic_edge_irq_chip = {
        .irq_set_type   = ipic_set_irq_type,
 };
 
-static int ipic_host_match(struct irq_domain *h, struct device_node *node)
+static int ipic_host_match(struct irq_domain *h, struct device_node *node,
+                          enum irq_domain_bus_token bus_token)
 {
        /* Exact match, unless ipic node is NULL */
        return h->of_node == NULL || h->of_node == node;
index c8e73332eaad5ab1d08ef3036be34b4b484d8ef6..97a8ae8f94dd5d3fe77753c4546c6c7ab6329a49 100644 (file)
@@ -1007,7 +1007,8 @@ static struct irq_chip mpic_irq_ht_chip = {
 #endif /* CONFIG_MPIC_U3_HT_IRQS */
 
 
-static int mpic_host_match(struct irq_domain *h, struct device_node *node)
+static int mpic_host_match(struct irq_domain *h, struct device_node *node,
+                          enum irq_domain_bus_token bus_token)
 {
        /* Exact match, unless mpic node is NULL */
        return h->of_node == NULL || h->of_node == node;
index fc46ef3b816eb3ee6b0796775c4eb77b4e9bcbd5..70fbd5694a8bcd3c171bc9615edf14e86cdde7b1 100644 (file)
@@ -108,7 +108,7 @@ static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)
 {
        struct msi_desc *entry;
 
-        list_for_each_entry(entry, &pdev->msi_list, list) {
+       for_each_pci_msi_entry(entry, pdev) {
                if (entry->irq == NO_IRQ)
                        continue;
 
@@ -140,7 +140,7 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
                return -ENXIO;
        }
 
-       list_for_each_entry(entry, &pdev->msi_list, list) {
+       for_each_pci_msi_entry(entry, pdev) {
                hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1);
                if (hwirq < 0) {
                        pr_debug("u3msi: failed allocating hwirq\n");
index 87f9623ca805d6ba601919784df3c7e6d38e488f..af3c144b92c14ffd870d64a36558414287c799b2 100644 (file)
@@ -51,7 +51,7 @@ static int hsta_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
                return -EINVAL;
        }
 
-       list_for_each_entry(entry, &dev->msi_list, list) {
+       for_each_pci_msi_entry(entry, dev) {
                irq = msi_bitmap_alloc_hwirqs(&ppc4xx_hsta_msi.bmp, 1);
                if (irq < 0) {
                        pr_debug("%s: Failed to allocate msi interrupt\n",
@@ -109,7 +109,7 @@ static void hsta_teardown_msi_irqs(struct pci_dev *dev)
        struct msi_desc *entry;
        int irq;
 
-       list_for_each_entry(entry, &dev->msi_list, list) {
+       for_each_pci_msi_entry(entry, dev) {
                if (entry->irq == NO_IRQ)
                        continue;
 
index 6eb21f2ea5857295d33bc5f9e8da87b7f0d9071f..24d0470c1698fb2bbbe81008e575ca54a35c33ce 100644 (file)
@@ -93,7 +93,7 @@ static int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
        if (!msi_data->msi_virqs)
                return -ENOMEM;
 
-       list_for_each_entry(entry, &dev->msi_list, list) {
+       for_each_pci_msi_entry(entry, dev) {
                int_no = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);
                if (int_no >= 0)
                        break;
@@ -127,7 +127,7 @@ void ppc4xx_teardown_msi_irqs(struct pci_dev *dev)
 
        dev_dbg(&dev->dev, "PCIE-MSI: tearing down msi irqs\n");
 
-       list_for_each_entry(entry, &dev->msi_list, list) {
+       for_each_pci_msi_entry(entry, dev) {
                if (entry->irq == NO_IRQ)
                        continue;
                irq_set_msi_desc(entry->irq, NULL);
index 6512cd8caa517d92496110e8119af46ae067d242..47b352e4bc743f532aa637d9d18daf7319207f92 100644 (file)
@@ -244,7 +244,8 @@ static struct irq_chip qe_ic_irq_chip = {
        .irq_mask_ack = qe_ic_mask_irq,
 };
 
-static int qe_ic_host_match(struct irq_domain *h, struct device_node *node)
+static int qe_ic_host_match(struct irq_domain *h, struct device_node *node,
+                           enum irq_domain_bus_token bus_token)
 {
        /* Exact match, unless qe_ic node is NULL */
        return h->of_node == NULL || h->of_node == node;
index 68c7e5cc98e09c3175b7e7ade03734887bc5c805..11ac964d51752f3ce4c55a9953b02e0ee9936e08 100644 (file)
@@ -72,7 +72,7 @@ static unsigned int ics_opal_startup(struct irq_data *d)
         * card, using the MSI mask bits. Firmware doesn't appear to unmask
         * at that level, so we do it here by hand.
         */
-       if (d->msi_desc)
+       if (irq_data_get_msi_desc(d))
                pci_msi_unmask_irq(d);
 #endif
 
index 0af97deb83f31db04c1d2f33612529a923c76a8a..d1c625c4cc5a4081686f2c83f7d2f0a51dbdd53e 100644 (file)
@@ -75,7 +75,7 @@ static unsigned int ics_rtas_startup(struct irq_data *d)
         * card, using the MSI mask bits. Firmware doesn't appear to unmask
         * at that level, so we do it here by hand.
         */
-       if (d->msi_desc)
+       if (irq_data_get_msi_desc(d))
                pci_msi_unmask_irq(d);
 #endif
        /* unmask it */
index 08c248eb491bad53e82afe28a73b510d4aa87f86..47e43b7b076bb2e4aa0cd3790e132185b422f9ae 100644 (file)
@@ -298,7 +298,8 @@ int xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask,
 }
 #endif /* CONFIG_SMP */
 
-static int xics_host_match(struct irq_domain *h, struct device_node *node)
+static int xics_host_match(struct irq_domain *h, struct device_node *node,
+                          enum irq_domain_bus_token bus_token)
 {
        struct ics *ics;
 
index 17c04c7269e79d1d1c4c69ccc46769b07d62339e..7ef12a3ace3aef665bd7b1bb637cc0d9dafcc6bd 100644 (file)
@@ -409,7 +409,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
 
        /* Request MSI interrupts */
        hwirq = 0;
-       list_for_each_entry(msi, &pdev->msi_list, list) {
+       for_each_pci_msi_entry(msi, pdev) {
                rc = -EIO;
                irq = irq_alloc_desc(0);        /* Alloc irq on node 0 */
                if (irq < 0)
@@ -435,7 +435,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
        return (msi_vecs == nvec) ? 0 : msi_vecs;
 
 out_msi:
-       list_for_each_entry(msi, &pdev->msi_list, list) {
+       for_each_pci_msi_entry(msi, pdev) {
                if (hwirq-- == 0)
                        break;
                irq_set_msi_desc(msi->irq, NULL);
@@ -465,7 +465,7 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev)
                return;
 
        /* Release MSI interrupts */
-       list_for_each_entry(msi, &pdev->msi_list, list) {
+       for_each_pci_msi_entry(msi, pdev) {
                if (msi->msi_attrib.is_msix)
                        __pci_msix_desc_mask_irq(msi, 1);
                else
index 1087dba9b0152317c2b806ccd627db8ab4173f47..6f97a8f0d0d65718c09282fd146e8ca2d3a0c96e 100644 (file)
@@ -31,7 +31,7 @@ struct irq_domain *se7343_irq_domain;
 
 static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_data *data = irq_get_irq_data(irq);
+       struct irq_data *data = irq_desc_get_irq_data(desc);
        struct irq_chip *chip = irq_data_get_irq_chip(data);
        unsigned long mask;
        int bit;
index 00e699232621dccf9c67beaf3eb6d145c25f0d9b..60aebd14ccf8c5cd44e287d0ec958a78a136ca4f 100644 (file)
@@ -30,7 +30,7 @@ struct irq_domain *se7722_irq_domain;
 
 static void se7722_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_data *data = irq_get_irq_data(irq);
+       struct irq_data *data = irq_desc_get_irq_data(desc);
        struct irq_chip *chip = irq_data_get_irq_chip(data);
        unsigned long mask;
        int bit;
index 5d1d3ec9a6cdd26de792e3538020fb7c45a9f073..9f20338986521ba2d81b89a5a2f3b3c9d3fdfcd8 100644 (file)
@@ -92,8 +92,9 @@ static struct irq_chip se7724_irq_chip __read_mostly = {
        .irq_unmask     = enable_se7724_irq,
 };
 
-static void se7724_irq_demux(unsigned int irq, struct irq_desc *desc)
+static void se7724_irq_demux(unsigned int __irq, struct irq_desc *desc)
 {
+       unsigned int irq = irq_desc_get_irq(desc);
        struct fpga_irq set = get_fpga_irq(irq);
        unsigned short intv = __raw_readw(set.sraddr);
        unsigned int ext_irq = set.base;
index f035a7ac6456213f94d0ddae409f8746d4b9b9f5..24555c364d5bccfd0ff4e8ffa737d757a421aa3f 100644 (file)
@@ -62,7 +62,7 @@ static int x3proto_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
 
 static void x3proto_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_data *data = irq_get_irq_data(irq);
+       struct irq_data *data = irq_desc_get_irq_data(desc);
        struct irq_chip *chip = irq_data_get_irq_chip(data);
        unsigned long mask;
        int pin;
index eb10ff84015c4c92f28e03756f90859705802d70..6c0378c0b8b5cc179cbf06269e94a02a5d1283c2 100644 (file)
@@ -227,16 +227,17 @@ void migrate_irqs(void)
        for_each_active_irq(irq) {
                struct irq_data *data = irq_get_irq_data(irq);
 
-               if (data->node == cpu) {
-                       unsigned int newcpu = cpumask_any_and(data->affinity,
+               if (irq_data_get_node(data) == cpu) {
+                       struct cpumask *mask = irq_data_get_affinity_mask(data);
+                       unsigned int newcpu = cpumask_any_and(mask,
                                                              cpu_online_mask);
                        if (newcpu >= nr_cpu_ids) {
                                pr_info_ratelimited("IRQ%u no longer affine to CPU%u\n",
                                                    irq, cpu);
 
-                               cpumask_setall(data->affinity);
+                               cpumask_setall(mask);
                        }
-                       irq_set_affinity(irq, data->affinity);
+                       irq_set_affinity(irq, mask);
                }
        }
 }
index 4033c23bdfa6cc76a9ef4b34ad671da39b6b5077..e22416ce56ea9e09380bcb771abf4bf89dddfc51 100644 (file)
@@ -210,21 +210,21 @@ struct irq_handler_data {
 
 static inline unsigned int irq_data_to_handle(struct irq_data *data)
 {
-       struct irq_handler_data *ihd = data->handler_data;
+       struct irq_handler_data *ihd = irq_data_get_irq_handler_data(data);
 
        return ihd->dev_handle;
 }
 
 static inline unsigned int irq_data_to_ino(struct irq_data *data)
 {
-       struct irq_handler_data *ihd = data->handler_data;
+       struct irq_handler_data *ihd = irq_data_get_irq_handler_data(data);
 
        return ihd->dev_ino;
 }
 
 static inline unsigned long irq_data_to_sysino(struct irq_data *data)
 {
-       struct irq_handler_data *ihd = data->handler_data;
+       struct irq_handler_data *ihd = irq_data_get_irq_handler_data(data);
 
        return ihd->sysino;
 }
@@ -370,13 +370,15 @@ static int irq_choose_cpu(unsigned int irq, const struct cpumask *affinity)
 
 static void sun4u_irq_enable(struct irq_data *data)
 {
-       struct irq_handler_data *handler_data = data->handler_data;
+       struct irq_handler_data *handler_data;
 
+       handler_data = irq_data_get_irq_handler_data(data);
        if (likely(handler_data)) {
                unsigned long cpuid, imap, val;
                unsigned int tid;
 
-               cpuid = irq_choose_cpu(data->irq, data->affinity);
+               cpuid = irq_choose_cpu(data->irq,
+                                      irq_data_get_affinity_mask(data));
                imap = handler_data->imap;
 
                tid = sun4u_compute_tid(imap, cpuid);
@@ -393,8 +395,9 @@ static void sun4u_irq_enable(struct irq_data *data)
 static int sun4u_set_affinity(struct irq_data *data,
                               const struct cpumask *mask, bool force)
 {
-       struct irq_handler_data *handler_data = data->handler_data;
+       struct irq_handler_data *handler_data;
 
+       handler_data = irq_data_get_irq_handler_data(data);
        if (likely(handler_data)) {
                unsigned long cpuid, imap, val;
                unsigned int tid;
@@ -438,15 +441,17 @@ static void sun4u_irq_disable(struct irq_data *data)
 
 static void sun4u_irq_eoi(struct irq_data *data)
 {
-       struct irq_handler_data *handler_data = data->handler_data;
+       struct irq_handler_data *handler_data;
 
+       handler_data = irq_data_get_irq_handler_data(data);
        if (likely(handler_data))
                upa_writeq(ICLR_IDLE, handler_data->iclr);
 }
 
 static void sun4v_irq_enable(struct irq_data *data)
 {
-       unsigned long cpuid = irq_choose_cpu(data->irq, data->affinity);
+       unsigned long cpuid = irq_choose_cpu(data->irq,
+                                            irq_data_get_affinity_mask(data));
        unsigned int ino = irq_data_to_sysino(data);
        int err;
 
@@ -508,7 +513,7 @@ static void sun4v_virq_enable(struct irq_data *data)
        unsigned long cpuid;
        int err;
 
-       cpuid = irq_choose_cpu(data->irq, data->affinity);
+       cpuid = irq_choose_cpu(data->irq, irq_data_get_affinity_mask(data));
 
        err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
        if (err != HV_EOK)
@@ -881,8 +886,8 @@ void fixup_irqs(void)
                if (desc->action && !irqd_is_per_cpu(data)) {
                        if (data->chip->irq_set_affinity)
                                data->chip->irq_set_affinity(data,
-                                                            data->affinity,
-                                                            false);
+                                       irq_data_get_affinity_mask(data),
+                                       false);
                }
                raw_spin_unlock_irqrestore(&desc->lock, flags);
        }
index 9bbb8f2bbfcce1d0925be62ce3af8e525cfc5082..0299f052a2efc0a2f67321a51fa46094d0cf0fed 100644 (file)
@@ -126,7 +126,7 @@ static int leon_set_affinity(struct irq_data *data, const struct cpumask *dest,
        int oldcpu, newcpu;
 
        mask = (unsigned long)data->chip_data;
-       oldcpu = irq_choose_cpu(data->affinity);
+       oldcpu = irq_choose_cpu(irq_data_get_affinity_mask(data));
        newcpu = irq_choose_cpu(dest);
 
        if (oldcpu == newcpu)
@@ -149,7 +149,7 @@ static void leon_unmask_irq(struct irq_data *data)
        int cpu;
 
        mask = (unsigned long)data->chip_data;
-       cpu = irq_choose_cpu(data->affinity);
+       cpu = irq_choose_cpu(irq_data_get_affinity_mask(data));
        spin_lock_irqsave(&leon_irq_lock, flags);
        oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(cpu));
        LEON3_BYPASS_STORE_PA(LEON_IMASK(cpu), (oldmask | mask));
@@ -162,7 +162,7 @@ static void leon_mask_irq(struct irq_data *data)
        int cpu;
 
        mask = (unsigned long)data->chip_data;
-       cpu = irq_choose_cpu(data->affinity);
+       cpu = irq_choose_cpu(irq_data_get_affinity_mask(data));
        spin_lock_irqsave(&leon_irq_lock, flags);
        oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(cpu));
        LEON3_BYPASS_STORE_PA(LEON_IMASK(cpu), (oldmask & ~mask));
index 3a0e1a986bfe3cf89c9f3cb92ac04c056b0f86eb..3a14a35592fe928754d7d1d946110b576a4bd95f 100644 (file)
@@ -914,7 +914,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
 void arch_teardown_msi_irq(unsigned int irq)
 {
        struct msi_desc *entry = irq_get_msi_desc(irq);
-       struct pci_dev *pdev = entry->dev;
+       struct pci_dev *pdev = msi_desc_to_pci_dev(entry);
        struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
 
        if (pbm->teardown_msi_irq)
index a1bb2675b2801ac44891f3acf50320613e35a025..a87d0e47c1681dc2714cc52ebdcb98420880c172 100644 (file)
@@ -188,7 +188,7 @@ void sun4d_handler_irq(unsigned int pil, struct pt_regs *regs)
 
 static void sun4d_mask_irq(struct irq_data *data)
 {
-       struct sun4d_handler_data *handler_data = data->handler_data;
+       struct sun4d_handler_data *handler_data = irq_data_get_irq_handler_data(data);
        unsigned int real_irq;
 #ifdef CONFIG_SMP
        int cpuid = handler_data->cpuid;
@@ -206,7 +206,7 @@ static void sun4d_mask_irq(struct irq_data *data)
 
 static void sun4d_unmask_irq(struct irq_data *data)
 {
-       struct sun4d_handler_data *handler_data = data->handler_data;
+       struct sun4d_handler_data *handler_data = irq_data_get_irq_handler_data(data);
        unsigned int real_irq;
 #ifdef CONFIG_SMP
        int cpuid = handler_data->cpuid;
index 8bb3b3fddea71dfe73cfee142b371c8d7e531660..da737c712fa89b3d9809c3ac7bd8a14cbcbeb415 100644 (file)
@@ -188,9 +188,10 @@ static unsigned long sun4m_imask[0x50] = {
 
 static void sun4m_mask_irq(struct irq_data *data)
 {
-       struct sun4m_handler_data *handler_data = data->handler_data;
+       struct sun4m_handler_data *handler_data;
        int cpu = smp_processor_id();
 
+       handler_data = irq_data_get_irq_handler_data(data);
        if (handler_data->mask) {
                unsigned long flags;
 
@@ -206,9 +207,10 @@ static void sun4m_mask_irq(struct irq_data *data)
 
 static void sun4m_unmask_irq(struct irq_data *data)
 {
-       struct sun4m_handler_data *handler_data = data->handler_data;
+       struct sun4m_handler_data *handler_data;
        int cpu = smp_processor_id();
 
+       handler_data = irq_data_get_irq_handler_data(data);
        if (handler_data->mask) {
                unsigned long flags;
 
index b1df847d0686706e455580293fe692255745282b..b3f73fd764a35b60002b507ea029c732363d4a6f 100644 (file)
@@ -304,11 +304,12 @@ static struct irq_chip tilegx_legacy_irq_chip = {
  * to Linux which just calls handle_level_irq() after clearing the
  * MAC INTx Assert status bit associated with this interrupt.
  */
-static void trio_handle_level_irq(unsigned int irq, struct irq_desc *desc)
+static void trio_handle_level_irq(unsigned int __irq, struct irq_desc *desc)
 {
        struct pci_controller *controller = irq_desc_get_handler_data(desc);
        gxio_trio_context_t *trio_context = controller->trio;
        uint64_t intx = (uint64_t)irq_desc_get_chip_data(desc);
+       unsigned int irq = irq_desc_get_irq(desc);
        int mac = controller->mac;
        unsigned int reg_offset;
        uint64_t level_mask;
@@ -1442,7 +1443,7 @@ static struct pci_ops tile_cfg_ops = {
 /* MSI support starts here. */
 static unsigned int tilegx_msi_startup(struct irq_data *d)
 {
-       if (d->msi_desc)
+       if (irq_data_get_msi_desc(d))
                pci_msi_unmask_irq(d);
 
        return 0;
index 0be5ccd7ccd223c17b7979ba192abade30e17c1c..c53729d92e8df72529e5370f100a5b51b84977ce 100644 (file)
@@ -112,10 +112,9 @@ static struct irq_chip puv3_low_gpio_chip = {
  * irq_controller_lock held, and IRQs disabled.  Decode the IRQ
  * and call the handler.
  */
-static void
-puv3_gpio_handler(unsigned int irq, struct irq_desc *desc)
+static void puv3_gpio_handler(unsigned int __irq, struct irq_desc *desc)
 {
-       unsigned int mask;
+       unsigned int mask, irq;
 
        mask = readl(GPIO_GEDR);
        do {
index d22f4b5bbc04d896088558b65026303e714f16c8..ff31ab464213fc49f21d0dde5bdcb14cc0763020 100644 (file)
@@ -179,7 +179,7 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
        if (ret)
                goto error;
        i = 0;
-       list_for_each_entry(msidesc, &dev->msi_list, list) {
+       for_each_pci_msi_entry(msidesc, dev) {
                irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i],
                                               (type == PCI_CAP_ID_MSI) ? nvec : 1,
                                               (type == PCI_CAP_ID_MSIX) ?
@@ -230,7 +230,7 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
        if (type == PCI_CAP_ID_MSI && nvec > 1)
                return 1;
 
-       list_for_each_entry(msidesc, &dev->msi_list, list) {
+       for_each_pci_msi_entry(msidesc, dev) {
                __pci_read_msi_msg(msidesc, &msg);
                pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) |
                        ((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff);
@@ -274,7 +274,7 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
        int ret = 0;
        struct msi_desc *msidesc;
 
-       list_for_each_entry(msidesc, &dev->msi_list, list) {
+       for_each_pci_msi_entry(msidesc, dev) {
                struct physdev_map_pirq map_irq;
                domid_t domid;
 
@@ -386,7 +386,7 @@ static void xen_teardown_msi_irqs(struct pci_dev *dev)
 {
        struct msi_desc *msidesc;
 
-       msidesc = list_entry(dev->msi_list.next, struct msi_desc, list);
+       msidesc = first_pci_msi_entry(dev);
        if (msidesc->msi_attrib.is_msix)
                xen_pci_frontend_disable_msix(dev);
        else
index 6df31cacc4b884c85c509a552edddcca55c0418a..4ac3d23161cf782484da4f0c89b9394e1911a07f 100644 (file)
@@ -177,23 +177,25 @@ void migrate_irqs(void)
 
        for_each_active_irq(i) {
                struct irq_data *data = irq_get_irq_data(i);
+               struct cpumask *mask;
                unsigned int newcpu;
 
                if (irqd_is_per_cpu(data))
                        continue;
 
-               if (!cpumask_test_cpu(cpu, data->affinity))
+               mask = irq_data_get_affinity_mask(data);
+               if (!cpumask_test_cpu(cpu, mask))
                        continue;
 
-               newcpu = cpumask_any_and(data->affinity, cpu_online_mask);
+               newcpu = cpumask_any_and(mask, cpu_online_mask);
 
                if (newcpu >= nr_cpu_ids) {
                        pr_info_ratelimited("IRQ%u no longer affine to CPU%u\n",
                                            i, cpu);
 
-                       cpumask_setall(data->affinity);
+                       cpumask_setall(mask);
                }
-               irq_set_affinity(i, data->affinity);
+               irq_set_affinity(i, mask);
        }
 }
 #endif /* CONFIG_HOTPLUG_CPU */
index 527d291706e89220db44d4f4a0880990ef12fddf..6b2a84e7f2bece5643c2b68a17254067213b99ce 100644 (file)
@@ -22,6 +22,7 @@ obj-$(CONFIG_REGMAP)  += regmap/
 obj-$(CONFIG_SOC_BUS) += soc.o
 obj-$(CONFIG_PINCTRL) += pinctrl.o
 obj-$(CONFIG_DEV_COREDUMP) += devcoredump.o
+obj-$(CONFIG_GENERIC_MSI_IRQ_DOMAIN) += platform-msi.o
 
 ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
 
index fc5a558f62f974bbd769e3879ae11f6eb7297d9d..f6947d0abc2f470e56f6b4b72f894cacd050efd3 100644 (file)
@@ -708,6 +708,9 @@ void device_initialize(struct device *dev)
        INIT_LIST_HEAD(&dev->devres_head);
        device_pm_init(dev);
        set_dev_node(dev, -1);
+#ifdef CONFIG_GENERIC_MSI_IRQ
+       INIT_LIST_HEAD(&dev->msi_list);
+#endif
 }
 EXPORT_SYMBOL_GPL(device_initialize);
 
diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
new file mode 100644 (file)
index 0000000..1857a5d
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * MSI framework for platform devices
+ *
+ * Copyright (C) 2015 ARM Limited, All Rights Reserved.
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/device.h>
+#include <linux/idr.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/msi.h>
+#include <linux/slab.h>
+
+#define DEV_ID_SHIFT   24
+
+/*
+ * Internal data structure containing a (made up, but unique) devid
+ * and the callback to write the MSI message.
+ */
+struct platform_msi_priv_data {
+       irq_write_msi_msg_t     write_msg;
+       int                     devid;
+};
+
+/* The devid allocator */
+static DEFINE_IDA(platform_msi_devid_ida);
+
+#ifdef GENERIC_MSI_DOMAIN_OPS
+/*
+ * Convert an msi_desc to a globaly unique identifier (per-device
+ * devid + msi_desc position in the msi_list).
+ */
+static irq_hw_number_t platform_msi_calc_hwirq(struct msi_desc *desc)
+{
+       u32 devid;
+
+       devid = desc->platform.msi_priv_data->devid;
+
+       return (devid << (32 - DEV_ID_SHIFT)) | desc->platform.msi_index;
+}
+
+static void platform_msi_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc)
+{
+       arg->desc = desc;
+       arg->hwirq = platform_msi_calc_hwirq(desc);
+}
+
+static int platform_msi_init(struct irq_domain *domain,
+                            struct msi_domain_info *info,
+                            unsigned int virq, irq_hw_number_t hwirq,
+                            msi_alloc_info_t *arg)
+{
+       struct irq_data *data;
+
+       irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
+                                     info->chip, info->chip_data);
+
+       /*
+        * Save the MSI descriptor in handler_data so that the
+        * irq_write_msi_msg callback can retrieve it (and the
+        * associated device).
+        */
+       data = irq_domain_get_irq_data(domain, virq);
+       data->handler_data = arg->desc;
+
+       return 0;
+}
+#else
+#define platform_msi_set_desc          NULL
+#define platform_msi_init              NULL
+#endif
+
+static void platform_msi_update_dom_ops(struct msi_domain_info *info)
+{
+       struct msi_domain_ops *ops = info->ops;
+
+       BUG_ON(!ops);
+
+       if (ops->msi_init == NULL)
+               ops->msi_init = platform_msi_init;
+       if (ops->set_desc == NULL)
+               ops->set_desc = platform_msi_set_desc;
+}
+
+static void platform_msi_write_msg(struct irq_data *data, struct msi_msg *msg)
+{
+       struct msi_desc *desc = irq_data_get_irq_handler_data(data);
+       struct platform_msi_priv_data *priv_data;
+
+       priv_data = desc->platform.msi_priv_data;
+
+       priv_data->write_msg(desc, msg);
+}
+
+static void platform_msi_update_chip_ops(struct msi_domain_info *info)
+{
+       struct irq_chip *chip = info->chip;
+
+       BUG_ON(!chip);
+       if (!chip->irq_mask)
+               chip->irq_mask = irq_chip_mask_parent;
+       if (!chip->irq_unmask)
+               chip->irq_unmask = irq_chip_unmask_parent;
+       if (!chip->irq_eoi)
+               chip->irq_eoi = irq_chip_eoi_parent;
+       if (!chip->irq_set_affinity)
+               chip->irq_set_affinity = msi_domain_set_affinity;
+       if (!chip->irq_write_msi_msg)
+               chip->irq_write_msi_msg = platform_msi_write_msg;
+}
+
+static void platform_msi_free_descs(struct device *dev)
+{
+       struct msi_desc *desc, *tmp;
+
+       list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
+               list_del(&desc->list);
+               free_msi_entry(desc);
+       }
+}
+
+static int platform_msi_alloc_descs(struct device *dev, int nvec,
+                                   struct platform_msi_priv_data *data)
+
+{
+       int i;
+
+       for (i = 0; i < nvec; i++) {
+               struct msi_desc *desc;
+
+               desc = alloc_msi_entry(dev);
+               if (!desc)
+                       break;
+
+               desc->platform.msi_priv_data = data;
+               desc->platform.msi_index = i;
+               desc->nvec_used = 1;
+
+               list_add_tail(&desc->list, dev_to_msi_list(dev));
+       }
+
+       if (i != nvec) {
+               /* Clean up the mess */
+               platform_msi_free_descs(dev);
+
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+/**
+ * platform_msi_create_irq_domain - Create a platform MSI interrupt domain
+ * @np:                Optional device-tree node of the interrupt controller
+ * @info:      MSI domain info
+ * @parent:    Parent irq domain
+ *
+ * Updates the domain and chip ops and creates a platform MSI
+ * interrupt domain.
+ *
+ * Returns:
+ * A domain pointer or NULL in case of failure.
+ */
+struct irq_domain *platform_msi_create_irq_domain(struct device_node *np,
+                                                 struct msi_domain_info *info,
+                                                 struct irq_domain *parent)
+{
+       struct irq_domain *domain;
+
+       if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS)
+               platform_msi_update_dom_ops(info);
+       if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
+               platform_msi_update_chip_ops(info);
+
+       domain = msi_create_irq_domain(np, info, parent);
+       if (domain)
+               domain->bus_token = DOMAIN_BUS_PLATFORM_MSI;
+
+       return domain;
+}
+
+/**
+ * platform_msi_domain_alloc_irqs - Allocate MSI interrupts for @dev
+ * @dev:               The device for which to allocate interrupts
+ * @nvec:              The number of interrupts to allocate
+ * @write_msi_msg:     Callback to write an interrupt message for @dev
+ *
+ * Returns:
+ * Zero for success, or an error code in case of failure
+ */
+int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
+                                  irq_write_msi_msg_t write_msi_msg)
+{
+       struct platform_msi_priv_data *priv_data;
+       int err;
+
+       /*
+        * Limit the number of interrupts to 256 per device. Should we
+        * need to bump this up, DEV_ID_SHIFT should be adjusted
+        * accordingly (which would impact the max number of MSI
+        * capable devices).
+        */
+       if (!dev->msi_domain || !write_msi_msg || !nvec ||
+           nvec > (1 << (32 - DEV_ID_SHIFT)))
+               return -EINVAL;
+
+       if (dev->msi_domain->bus_token != DOMAIN_BUS_PLATFORM_MSI) {
+               dev_err(dev, "Incompatible msi_domain, giving up\n");
+               return -EINVAL;
+       }
+
+       /* Already had a helping of MSI? Greed... */
+       if (!list_empty(dev_to_msi_list(dev)))
+               return -EBUSY;
+
+       priv_data = kzalloc(sizeof(*priv_data), GFP_KERNEL);
+       if (!priv_data)
+               return -ENOMEM;
+
+       priv_data->devid = ida_simple_get(&platform_msi_devid_ida,
+                                         0, 1 << DEV_ID_SHIFT, GFP_KERNEL);
+       if (priv_data->devid < 0) {
+               err = priv_data->devid;
+               goto out_free_data;
+       }
+
+       priv_data->write_msg = write_msi_msg;
+
+       err = platform_msi_alloc_descs(dev, nvec, priv_data);
+       if (err)
+               goto out_free_id;
+
+       err = msi_domain_alloc_irqs(dev->msi_domain, dev, nvec);
+       if (err)
+               goto out_free_desc;
+
+       return 0;
+
+out_free_desc:
+       platform_msi_free_descs(dev);
+out_free_id:
+       ida_simple_remove(&platform_msi_devid_ida, priv_data->devid);
+out_free_data:
+       kfree(priv_data);
+
+       return err;
+}
+
+/**
+ * platform_msi_domain_free_irqs - Free MSI interrupts for @dev
+ * @dev:       The device for which to free interrupts
+ */
+void platform_msi_domain_free_irqs(struct device *dev)
+{
+       struct msi_desc *desc;
+
+       desc = first_msi_entry(dev);
+       if (desc) {
+               struct platform_msi_priv_data *data;
+
+               data = desc->platform.msi_priv_data;
+
+               ida_simple_remove(&platform_msi_devid_ida, data->devid);
+               kfree(data);
+       }
+
+       msi_domain_free_irqs(dev->msi_domain, dev);
+       platform_msi_free_descs(dev);
+}
index 120d81543e53254ea725ff845631edc667dbdb07..27b52c8729cd1e1a6f17e9945a14e894a78ee81f 100644 (file)
@@ -61,6 +61,10 @@ config ATMEL_AIC5_IRQ
        select MULTI_IRQ_HANDLER
        select SPARSE_IRQ
 
+config I8259
+       bool
+       select IRQ_DOMAIN
+
 config BCM7038_L1_IRQ
        bool
        select GENERIC_IRQ_CHIP
@@ -177,3 +181,9 @@ config RENESAS_H8300H_INTC
 config RENESAS_H8S_INTC
         bool
        select IRQ_DOMAIN
+
+config IMX_GPCV2
+       bool
+       select IRQ_DOMAIN
+       help
+         Enables the wakeup IRQs for IMX platforms with GPCv2 block
index b8d4e9691890eccf5e601b129e30169ddcc3140d..bb3048f00e647d5c8c0665a7fb31cedc593f4e46 100644 (file)
@@ -1,6 +1,7 @@
 obj-$(CONFIG_IRQCHIP)                  += irqchip.o
 
 obj-$(CONFIG_ARCH_BCM2835)             += irq-bcm2835.o
+obj-$(CONFIG_ARCH_BCM2835)             += irq-bcm2836.o
 obj-$(CONFIG_ARCH_EXYNOS)              += exynos-combiner.o
 obj-$(CONFIG_ARCH_HIP04)               += irq-hip04.o
 obj-$(CONFIG_ARCH_MMP)                 += irq-mmp.o
@@ -22,11 +23,12 @@ obj-$(CONFIG_ARCH_SPEAR3XX)         += spear-shirq.o
 obj-$(CONFIG_ARM_GIC)                  += irq-gic.o irq-gic-common.o
 obj-$(CONFIG_ARM_GIC_V2M)              += irq-gic-v2m.o
 obj-$(CONFIG_ARM_GIC_V3)               += irq-gic-v3.o irq-gic-common.o
-obj-$(CONFIG_ARM_GIC_V3_ITS)           += irq-gic-v3-its.o
+obj-$(CONFIG_ARM_GIC_V3_ITS)           += irq-gic-v3-its.o irq-gic-v3-its-pci-msi.o irq-gic-v3-its-platform-msi.o
 obj-$(CONFIG_ARM_NVIC)                 += irq-nvic.o
 obj-$(CONFIG_ARM_VIC)                  += irq-vic.o
 obj-$(CONFIG_ATMEL_AIC_IRQ)            += irq-atmel-aic-common.o irq-atmel-aic.o
 obj-$(CONFIG_ATMEL_AIC5_IRQ)   += irq-atmel-aic-common.o irq-atmel-aic5.o
+obj-$(CONFIG_I8259)                    += irq-i8259.o
 obj-$(CONFIG_IMGPDC_IRQ)               += irq-imgpdc.o
 obj-$(CONFIG_IRQ_MIPS_CPU)             += irq-mips-cpu.o
 obj-$(CONFIG_SIRF_IRQ)                 += irq-sirfsoc.o
@@ -52,3 +54,4 @@ obj-$(CONFIG_RENESAS_H8300H_INTC)     += irq-renesas-h8300h.o
 obj-$(CONFIG_RENESAS_H8S_INTC)         += irq-renesas-h8s.o
 obj-$(CONFIG_ARCH_SA1100)              += irq-sa11x0.o
 obj-$(CONFIG_INGENIC_IRQ)              += irq-ingenic.o
+obj-$(CONFIG_IMX_GPCV2)                        += irq-imx-gpcv2.o
index 5c82e3bdafdf0f61f054b7ea14144346a4390002..e9c6f2a5b52de0958ec334f0a011f3883edf6bf3 100644 (file)
 #include <linux/slab.h>
 #include <linux/syscore_ops.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/interrupt.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 
-#include "irqchip.h"
-
 #define COMBINER_ENABLE_SET    0x0
 #define COMBINER_ENABLE_CLEAR  0x4
 #define COMBINER_INT_STATUS    0xC
@@ -66,10 +65,12 @@ static void combiner_unmask_irq(struct irq_data *data)
        __raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
 }
 
-static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
+static void combiner_handle_cascade_irq(unsigned int __irq,
+                                       struct irq_desc *desc)
 {
-       struct combiner_chip_data *chip_data = irq_get_handler_data(irq);
-       struct irq_chip *chip = irq_get_chip(irq);
+       struct combiner_chip_data *chip_data = irq_desc_get_handler_data(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       unsigned int irq = irq_desc_get_irq(desc);
        unsigned int cascade_irq, combiner_irq;
        unsigned long status;
 
@@ -122,9 +123,8 @@ static struct irq_chip combiner_chip = {
 static void __init combiner_cascade_irq(struct combiner_chip_data *combiner_data,
                                        unsigned int irq)
 {
-       if (irq_set_handler_data(irq, combiner_data) != 0)
-               BUG();
-       irq_set_chained_handler(irq, combiner_handle_cascade_irq);
+       irq_set_chained_handler_and_data(irq, combiner_handle_cascade_irq,
+                                        combiner_data);
 }
 
 static void __init combiner_init_one(struct combiner_chip_data *combiner_data,
@@ -185,14 +185,14 @@ static void __init combiner_init(void __iomem *combiner_base,
 
        combiner_data = kcalloc(max_nr, sizeof (*combiner_data), GFP_KERNEL);
        if (!combiner_data) {
-               pr_warning("%s: could not allocate combiner data\n", __func__);
+               pr_warn("%s: could not allocate combiner data\n", __func__);
                return;
        }
 
        combiner_irq_domain = irq_domain_add_linear(np, nr_irq,
                                &combiner_irq_domain_ops, combiner_data);
        if (WARN_ON(!combiner_irq_domain)) {
-               pr_warning("%s: irq domain init failed\n", __func__);
+               pr_warn("%s: irq domain init failed\n", __func__);
                return;
        }
 
index 0d3b0fe2f175e89912db13bc38e6d7235d60d835..39b72da0c1437fc4caf658a85c0e2ba62dc70694 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/irqchip.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/cpu.h>
 #include <linux/io.h>
@@ -33,8 +34,6 @@
 #include <asm/smp_plat.h>
 #include <asm/mach/irq.h>
 
-#include "irqchip.h"
-
 /* Interrupt Controller Registers Map */
 #define ARMADA_370_XP_INT_SET_MASK_OFFS                (0x48)
 #define ARMADA_370_XP_INT_CLEAR_MASK_OFFS      (0x4C)
@@ -451,7 +450,7 @@ static void armada_370_xp_handle_msi_irq(struct pt_regs *r, bool b) {}
 static void armada_370_xp_mpic_handle_cascade_irq(unsigned int irq,
                                                  struct irq_desc *desc)
 {
-       struct irq_chip *chip = irq_get_chip(irq);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned long irqmap, irqn, irqsrc, cpuid;
        unsigned int cascade_irq;
 
index dae3604b32a900ab71c0d098eb4790a4ff4e4af7..8a0c7f28819841a83e1afb0e3eccf71d4aa287a7 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/bitmap.h>
 #include <linux/types.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -31,7 +32,6 @@
 #include <asm/mach/irq.h>
 
 #include "irq-atmel-aic-common.h"
-#include "irqchip.h"
 
 /* Number of irq lines managed by AIC */
 #define NR_AIC_IRQS    32
@@ -225,7 +225,7 @@ static void __init at91sam9g45_aic_irq_fixup(struct device_node *root)
        aic_common_rtt_irq_fixup(root);
 }
 
-static const struct of_device_id __initdata aic_irq_fixups[] = {
+static const struct of_device_id aic_irq_fixups[] __initconst = {
        { .compatible = "atmel,at91rm9200", .data = at91rm9200_aic_irq_fixup },
        { .compatible = "atmel,at91sam9g45", .data = at91sam9g45_aic_irq_fixup },
        { .compatible = "atmel,at91sam9n12", .data = at91rm9200_aic_irq_fixup },
index 459bf4429d365794d4f84c19116cb0d57755c646..9da9942ac83c9e4ce861e193061f0f29df8b5700 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/bitmap.h>
 #include <linux/types.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -31,7 +32,6 @@
 #include <asm/mach/irq.h>
 
 #include "irq-atmel-aic-common.h"
-#include "irqchip.h"
 
 /* Number of irq lines managed by AIC */
 #define NR_AIC5_IRQS   128
@@ -290,7 +290,7 @@ static void __init sama5d3_aic_irq_fixup(struct device_node *root)
        aic_common_rtc_irq_fixup(root);
 }
 
-static const struct of_device_id __initdata aic5_irq_fixups[] = {
+static const struct of_device_id aic5_irq_fixups[] __initconst = {
        { .compatible = "atmel,sama5d3", .data = sama5d3_aic_irq_fixup },
        { .compatible = "atmel,sama5d4", .data = sama5d3_aic_irq_fixup },
        { /* sentinel */ },
index e68c3b60a681ba460b24dd17499de544ea4a35fc..ed4ca9deca7030bf202b02a1034f71b229a3c2ff 100644 (file)
 #include <linux/slab.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 
 #include <asm/exception.h>
 #include <asm/mach/irq.h>
 
-#include "irqchip.h"
-
 /* Put the bank and irq (32 bits) into the hwirq */
 #define MAKE_HWIRQ(b, n)       ((b << 5) | (n))
 #define HWIRQ_BANK(i)          (i >> 5)
 #define NR_BANKS               3
 #define IRQS_PER_BANK          32
 
-static int reg_pending[] __initconst = { 0x00, 0x04, 0x08 };
-static int reg_enable[] __initconst = { 0x18, 0x10, 0x14 };
-static int reg_disable[] __initconst = { 0x24, 0x1c, 0x20 };
-static int bank_irqs[] __initconst = { 8, 32, 32 };
+static const int reg_pending[] __initconst = { 0x00, 0x04, 0x08 };
+static const int reg_enable[] __initconst = { 0x18, 0x10, 0x14 };
+static const int reg_disable[] __initconst = { 0x24, 0x1c, 0x20 };
+static const int bank_irqs[] __initconst = { 8, 32, 32 };
 
 static const int shortcuts[] = {
        7, 9, 10, 18, 19,               /* Bank 1 */
@@ -97,6 +96,7 @@ struct armctrl_ic {
 static struct armctrl_ic intc __read_mostly;
 static void __exception_irq_entry bcm2835_handle_irq(
        struct pt_regs *regs);
+static void bcm2836_chained_handle_irq(unsigned int irq, struct irq_desc *desc);
 
 static void armctrl_mask_irq(struct irq_data *d)
 {
@@ -140,7 +140,8 @@ static const struct irq_domain_ops armctrl_ops = {
 };
 
 static int __init armctrl_of_init(struct device_node *node,
-       struct device_node *parent)
+                                 struct device_node *parent,
+                                 bool is_2836)
 {
        void __iomem *base;
        int irq, b, i;
@@ -169,54 +170,90 @@ static int __init armctrl_of_init(struct device_node *node,
                }
        }
 
-       set_handle_irq(bcm2835_handle_irq);
+       if (is_2836) {
+               int parent_irq = irq_of_parse_and_map(node, 0);
+
+               if (!parent_irq) {
+                       panic("%s: unable to get parent interrupt.\n",
+                             node->full_name);
+               }
+               irq_set_chained_handler(parent_irq, bcm2836_chained_handle_irq);
+       } else {
+               set_handle_irq(bcm2835_handle_irq);
+       }
+
        return 0;
 }
 
+static int __init bcm2835_armctrl_of_init(struct device_node *node,
+                                         struct device_node *parent)
+{
+       return armctrl_of_init(node, parent, false);
+}
+
+static int __init bcm2836_armctrl_of_init(struct device_node *node,
+                                         struct device_node *parent)
+{
+       return armctrl_of_init(node, parent, true);
+}
+
+
 /*
  * Handle each interrupt across the entire interrupt controller.  This reads the
  * status register before handling each interrupt, which is necessary given that
  * handle_IRQ may briefly re-enable interrupts for soft IRQ handling.
  */
 
-static void armctrl_handle_bank(int bank, struct pt_regs *regs)
+static u32 armctrl_translate_bank(int bank)
 {
-       u32 stat, irq;
+       u32 stat = readl_relaxed(intc.pending[bank]);
 
-       while ((stat = readl_relaxed(intc.pending[bank]))) {
-               irq = MAKE_HWIRQ(bank, ffs(stat) - 1);
-               handle_IRQ(irq_linear_revmap(intc.domain, irq), regs);
-       }
+       return MAKE_HWIRQ(bank, ffs(stat) - 1);
+}
+
+static u32 armctrl_translate_shortcut(int bank, u32 stat)
+{
+       return MAKE_HWIRQ(bank, shortcuts[ffs(stat >> SHORTCUT_SHIFT) - 1]);
 }
 
-static void armctrl_handle_shortcut(int bank, struct pt_regs *regs,
-       u32 stat)
+static u32 get_next_armctrl_hwirq(void)
 {
-       u32 irq = MAKE_HWIRQ(bank, shortcuts[ffs(stat >> SHORTCUT_SHIFT) - 1]);
-       handle_IRQ(irq_linear_revmap(intc.domain, irq), regs);
+       u32 stat = readl_relaxed(intc.pending[0]) & BANK0_VALID_MASK;
+
+       if (stat == 0)
+               return ~0;
+       else if (stat & BANK0_HWIRQ_MASK)
+               return MAKE_HWIRQ(0, ffs(stat & BANK0_HWIRQ_MASK) - 1);
+       else if (stat & SHORTCUT1_MASK)
+               return armctrl_translate_shortcut(1, stat & SHORTCUT1_MASK);
+       else if (stat & SHORTCUT2_MASK)
+               return armctrl_translate_shortcut(2, stat & SHORTCUT2_MASK);
+       else if (stat & BANK1_HWIRQ)
+               return armctrl_translate_bank(1);
+       else if (stat & BANK2_HWIRQ)
+               return armctrl_translate_bank(2);
+       else
+               BUG();
 }
 
 static void __exception_irq_entry bcm2835_handle_irq(
        struct pt_regs *regs)
 {
-       u32 stat, irq;
-
-       while ((stat = readl_relaxed(intc.pending[0]) & BANK0_VALID_MASK)) {
-               if (stat & BANK0_HWIRQ_MASK) {
-                       irq = MAKE_HWIRQ(0, ffs(stat & BANK0_HWIRQ_MASK) - 1);
-                       handle_IRQ(irq_linear_revmap(intc.domain, irq), regs);
-               } else if (stat & SHORTCUT1_MASK) {
-                       armctrl_handle_shortcut(1, regs, stat & SHORTCUT1_MASK);
-               } else if (stat & SHORTCUT2_MASK) {
-                       armctrl_handle_shortcut(2, regs, stat & SHORTCUT2_MASK);
-               } else if (stat & BANK1_HWIRQ) {
-                       armctrl_handle_bank(1, regs);
-               } else if (stat & BANK2_HWIRQ) {
-                       armctrl_handle_bank(2, regs);
-               } else {
-                       BUG();
-               }
-       }
+       u32 hwirq;
+
+       while ((hwirq = get_next_armctrl_hwirq()) != ~0)
+               handle_IRQ(irq_linear_revmap(intc.domain, hwirq), regs);
+}
+
+static void bcm2836_chained_handle_irq(unsigned int irq, struct irq_desc *desc)
+{
+       u32 hwirq;
+
+       while ((hwirq = get_next_armctrl_hwirq()) != ~0)
+               generic_handle_irq(irq_linear_revmap(intc.domain, hwirq));
 }
 
-IRQCHIP_DECLARE(bcm2835_armctrl_ic, "brcm,bcm2835-armctrl-ic", armctrl_of_init);
+IRQCHIP_DECLARE(bcm2835_armctrl_ic, "brcm,bcm2835-armctrl-ic",
+               bcm2835_armctrl_of_init);
+IRQCHIP_DECLARE(bcm2836_armctrl_ic, "brcm,bcm2836-armctrl-ic",
+               bcm2836_armctrl_of_init);
diff --git a/drivers/irqchip/irq-bcm2836.c b/drivers/irqchip/irq-bcm2836.c
new file mode 100644 (file)
index 0000000..f687082
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Root interrupt controller for the BCM2836 (Raspberry Pi 2).
+ *
+ * Copyright 2015 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/cpu.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqdomain.h>
+#include <asm/exception.h>
+
+/*
+ * The low 2 bits identify the CPU that the GPU IRQ goes to, and the
+ * next 2 bits identify the CPU that the GPU FIQ goes to.
+ */
+#define LOCAL_GPU_ROUTING              0x00c
+/* When setting bits 0-3, enables PMU interrupts on that CPU. */
+#define LOCAL_PM_ROUTING_SET           0x010
+/* When setting bits 0-3, disables PMU interrupts on that CPU. */
+#define LOCAL_PM_ROUTING_CLR           0x014
+/*
+ * The low 4 bits of this are the CPU's timer IRQ enables, and the
+ * next 4 bits are the CPU's timer FIQ enables (which override the IRQ
+ * bits).
+ */
+#define LOCAL_TIMER_INT_CONTROL0       0x040
+/*
+ * The low 4 bits of this are the CPU's per-mailbox IRQ enables, and
+ * the next 4 bits are the CPU's per-mailbox FIQ enables (which
+ * override the IRQ bits).
+ */
+#define LOCAL_MAILBOX_INT_CONTROL0     0x050
+/*
+ * The CPU's interrupt status register.  Bits are defined by the the
+ * LOCAL_IRQ_* bits below.
+ */
+#define LOCAL_IRQ_PENDING0             0x060
+/* Same status bits as above, but for FIQ. */
+#define LOCAL_FIQ_PENDING0             0x070
+/*
+ * Mailbox0 write-to-set bits.  There are 16 mailboxes, 4 per CPU, and
+ * these bits are organized by mailbox number and then CPU number.  We
+ * use mailbox 0 for IPIs.  The mailbox's interrupt is raised while
+ * any bit is set.
+ */
+#define LOCAL_MAILBOX0_SET0            0x080
+/* Mailbox0 write-to-clear bits. */
+#define LOCAL_MAILBOX0_CLR0            0x0c0
+
+#define LOCAL_IRQ_CNTPSIRQ     0
+#define LOCAL_IRQ_CNTPNSIRQ    1
+#define LOCAL_IRQ_CNTHPIRQ     2
+#define LOCAL_IRQ_CNTVIRQ      3
+#define LOCAL_IRQ_MAILBOX0     4
+#define LOCAL_IRQ_MAILBOX1     5
+#define LOCAL_IRQ_MAILBOX2     6
+#define LOCAL_IRQ_MAILBOX3     7
+#define LOCAL_IRQ_GPU_FAST     8
+#define LOCAL_IRQ_PMU_FAST     9
+#define LAST_IRQ               LOCAL_IRQ_PMU_FAST
+
+struct bcm2836_arm_irqchip_intc {
+       struct irq_domain *domain;
+       void __iomem *base;
+};
+
+static struct bcm2836_arm_irqchip_intc intc  __read_mostly;
+
+static void bcm2836_arm_irqchip_mask_per_cpu_irq(unsigned int reg_offset,
+                                                unsigned int bit,
+                                                int cpu)
+{
+       void __iomem *reg = intc.base + reg_offset + 4 * cpu;
+
+       writel(readl(reg) & ~BIT(bit), reg);
+}
+
+static void bcm2836_arm_irqchip_unmask_per_cpu_irq(unsigned int reg_offset,
+                                                  unsigned int bit,
+                                                int cpu)
+{
+       void __iomem *reg = intc.base + reg_offset + 4 * cpu;
+
+       writel(readl(reg) | BIT(bit), reg);
+}
+
+static void bcm2836_arm_irqchip_mask_timer_irq(struct irq_data *d)
+{
+       bcm2836_arm_irqchip_mask_per_cpu_irq(LOCAL_TIMER_INT_CONTROL0,
+                                            d->hwirq - LOCAL_IRQ_CNTPSIRQ,
+                                            smp_processor_id());
+}
+
+static void bcm2836_arm_irqchip_unmask_timer_irq(struct irq_data *d)
+{
+       bcm2836_arm_irqchip_unmask_per_cpu_irq(LOCAL_TIMER_INT_CONTROL0,
+                                              d->hwirq - LOCAL_IRQ_CNTPSIRQ,
+                                              smp_processor_id());
+}
+
+static struct irq_chip bcm2836_arm_irqchip_timer = {
+       .name           = "bcm2836-timer",
+       .irq_mask       = bcm2836_arm_irqchip_mask_timer_irq,
+       .irq_unmask     = bcm2836_arm_irqchip_unmask_timer_irq,
+};
+
+static void bcm2836_arm_irqchip_mask_pmu_irq(struct irq_data *d)
+{
+       writel(1 << smp_processor_id(), intc.base + LOCAL_PM_ROUTING_CLR);
+}
+
+static void bcm2836_arm_irqchip_unmask_pmu_irq(struct irq_data *d)
+{
+       writel(1 << smp_processor_id(), intc.base + LOCAL_PM_ROUTING_SET);
+}
+
+static struct irq_chip bcm2836_arm_irqchip_pmu = {
+       .name           = "bcm2836-pmu",
+       .irq_mask       = bcm2836_arm_irqchip_mask_pmu_irq,
+       .irq_unmask     = bcm2836_arm_irqchip_unmask_pmu_irq,
+};
+
+static void bcm2836_arm_irqchip_mask_gpu_irq(struct irq_data *d)
+{
+}
+
+static void bcm2836_arm_irqchip_unmask_gpu_irq(struct irq_data *d)
+{
+}
+
+static struct irq_chip bcm2836_arm_irqchip_gpu = {
+       .name           = "bcm2836-gpu",
+       .irq_mask       = bcm2836_arm_irqchip_mask_gpu_irq,
+       .irq_unmask     = bcm2836_arm_irqchip_unmask_gpu_irq,
+};
+
+static void bcm2836_arm_irqchip_register_irq(int hwirq, struct irq_chip *chip)
+{
+       int irq = irq_create_mapping(intc.domain, hwirq);
+
+       irq_set_percpu_devid(irq);
+       irq_set_chip_and_handler(irq, chip, handle_percpu_devid_irq);
+       irq_set_status_flags(irq, IRQ_NOAUTOEN);
+}
+
+static void
+__exception_irq_entry bcm2836_arm_irqchip_handle_irq(struct pt_regs *regs)
+{
+       int cpu = smp_processor_id();
+       u32 stat;
+
+       stat = readl_relaxed(intc.base + LOCAL_IRQ_PENDING0 + 4 * cpu);
+       if (stat & 0x10) {
+#ifdef CONFIG_SMP
+               void __iomem *mailbox0 = (intc.base +
+                                         LOCAL_MAILBOX0_CLR0 + 16 * cpu);
+               u32 mbox_val = readl(mailbox0);
+               u32 ipi = ffs(mbox_val) - 1;
+
+               writel(1 << ipi, mailbox0);
+               handle_IPI(ipi, regs);
+#endif
+       } else {
+               u32 hwirq = ffs(stat) - 1;
+
+               handle_IRQ(irq_linear_revmap(intc.domain, hwirq), regs);
+       }
+}
+
+#ifdef CONFIG_SMP
+static void bcm2836_arm_irqchip_send_ipi(const struct cpumask *mask,
+                                        unsigned int ipi)
+{
+       int cpu;
+       void __iomem *mailbox0_base = intc.base + LOCAL_MAILBOX0_SET0;
+
+       /*
+        * Ensure that stores to normal memory are visible to the
+        * other CPUs before issuing the IPI.
+        */
+       dsb();
+
+       for_each_cpu(cpu, mask) {
+               writel(1 << ipi, mailbox0_base + 16 * cpu);
+       }
+}
+
+/* Unmasks the IPI on the CPU when it's online. */
+static int bcm2836_arm_irqchip_cpu_notify(struct notifier_block *nfb,
+                                         unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (unsigned long)hcpu;
+       unsigned int int_reg = LOCAL_MAILBOX_INT_CONTROL0;
+       unsigned int mailbox = 0;
+
+       if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
+               bcm2836_arm_irqchip_unmask_per_cpu_irq(int_reg, mailbox, cpu);
+       else if (action == CPU_DYING)
+               bcm2836_arm_irqchip_mask_per_cpu_irq(int_reg, mailbox, cpu);
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block bcm2836_arm_irqchip_cpu_notifier = {
+       .notifier_call = bcm2836_arm_irqchip_cpu_notify,
+       .priority = 100,
+};
+#endif
+
+static const struct irq_domain_ops bcm2836_arm_irqchip_intc_ops = {
+       .xlate = irq_domain_xlate_onecell
+};
+
+static void
+bcm2836_arm_irqchip_smp_init(void)
+{
+#ifdef CONFIG_SMP
+       /* Unmask IPIs to the boot CPU. */
+       bcm2836_arm_irqchip_cpu_notify(&bcm2836_arm_irqchip_cpu_notifier,
+                                      CPU_STARTING,
+                                      (void *)smp_processor_id());
+       register_cpu_notifier(&bcm2836_arm_irqchip_cpu_notifier);
+
+       set_smp_cross_call(bcm2836_arm_irqchip_send_ipi);
+#endif
+}
+
+static int __init bcm2836_arm_irqchip_l1_intc_of_init(struct device_node *node,
+                                                     struct device_node *parent)
+{
+       intc.base = of_iomap(node, 0);
+       if (!intc.base) {
+               panic("%s: unable to map local interrupt registers\n",
+                       node->full_name);
+       }
+
+       intc.domain = irq_domain_add_linear(node, LAST_IRQ + 1,
+                                           &bcm2836_arm_irqchip_intc_ops,
+                                           NULL);
+       if (!intc.domain)
+               panic("%s: unable to create IRQ domain\n", node->full_name);
+
+       bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTPSIRQ,
+                                        &bcm2836_arm_irqchip_timer);
+       bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTPNSIRQ,
+                                        &bcm2836_arm_irqchip_timer);
+       bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTHPIRQ,
+                                        &bcm2836_arm_irqchip_timer);
+       bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTVIRQ,
+                                        &bcm2836_arm_irqchip_timer);
+       bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_GPU_FAST,
+                                        &bcm2836_arm_irqchip_gpu);
+       bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_PMU_FAST,
+                                        &bcm2836_arm_irqchip_pmu);
+
+       bcm2836_arm_irqchip_smp_init();
+
+       set_handle_irq(bcm2836_arm_irqchip_handle_irq);
+       return 0;
+}
+
+IRQCHIP_DECLARE(bcm2836_arm_irqchip_l1_intc, "brcm,bcm2836-l1-intc",
+               bcm2836_arm_irqchip_l1_intc_of_init);
index d3b8c8be15f67460023b7483b69ced1050aa2a08..409bdc6366c20a3ba909aae5b770dfe71dac08d9 100644 (file)
 #include <linux/slab.h>
 #include <linux/smp.h>
 #include <linux/types.h>
+#include <linux/irqchip.h>
 #include <linux/irqchip/chained_irq.h>
 
-#include "irqchip.h"
-
 #define IRQS_PER_WORD          32
 #define REG_BYTES_PER_IRQ_WORD (sizeof(u32) * 4)
 #define MAX_WORDS              8
@@ -257,8 +256,8 @@ static int __init bcm7038_l1_init_one(struct device_node *dn,
                pr_err("failed to map parent interrupt %d\n", parent_irq);
                return -EINVAL;
        }
-       irq_set_handler_data(parent_irq, intc);
-       irq_set_chained_handler(parent_irq, bcm7038_l1_irq_handle);
+       irq_set_chained_handler_and_data(parent_irq, bcm7038_l1_irq_handle,
+                                        intc);
 
        return 0;
 }
index 3ba5cc780fcbbba4568db2557df8828b63d5d4d9..d3f976913a6fbd9bb2af3ff4c4b1e906f5bae61e 100644 (file)
 #include <linux/irqdomain.h>
 #include <linux/reboot.h>
 #include <linux/bitops.h>
+#include <linux/irqchip.h>
 #include <linux/irqchip/chained_irq.h>
 
-#include "irqchip.h"
-
 /* Register offset in the L2 interrupt controller */
 #define IRQEN          0x00
 #define IRQSTAT                0x04
 #define MAX_MAPPINGS   (MAX_WORDS * 2)
 #define IRQS_PER_WORD  32
 
+struct bcm7120_l1_intc_data {
+       struct bcm7120_l2_intc_data *b;
+       u32 irq_map_mask[MAX_WORDS];
+};
+
 struct bcm7120_l2_intc_data {
        unsigned int n_words;
        void __iomem *map_base[MAX_MAPPINGS];
@@ -47,14 +51,15 @@ struct bcm7120_l2_intc_data {
        struct irq_domain *domain;
        bool can_wake;
        u32 irq_fwd_mask[MAX_WORDS];
-       u32 irq_map_mask[MAX_WORDS];
+       struct bcm7120_l1_intc_data *l1_data;
        int num_parent_irqs;
        const __be32 *map_mask_prop;
 };
 
 static void bcm7120_l2_intc_irq_handle(unsigned int irq, struct irq_desc *desc)
 {
-       struct bcm7120_l2_intc_data *b = irq_desc_get_handler_data(desc);
+       struct bcm7120_l1_intc_data *data = irq_desc_get_handler_data(desc);
+       struct bcm7120_l2_intc_data *b = data->b;
        struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int idx;
 
@@ -69,7 +74,8 @@ static void bcm7120_l2_intc_irq_handle(unsigned int irq, struct irq_desc *desc)
 
                irq_gc_lock(gc);
                pending = irq_reg_readl(gc, b->stat_offset[idx]) &
-                                           gc->mask_cache;
+                                           gc->mask_cache &
+                                           data->irq_map_mask[idx];
                irq_gc_unlock(gc);
 
                for_each_set_bit(hwirq, &pending, IRQS_PER_WORD) {
@@ -81,11 +87,10 @@ static void bcm7120_l2_intc_irq_handle(unsigned int irq, struct irq_desc *desc)
        chained_irq_exit(chip, desc);
 }
 
-static void bcm7120_l2_intc_suspend(struct irq_data *d)
+static void bcm7120_l2_intc_suspend(struct irq_chip_generic *gc)
 {
-       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-       struct irq_chip_type *ct = irq_data_get_chip_type(d);
        struct bcm7120_l2_intc_data *b = gc->private;
+       struct irq_chip_type *ct = gc->chip_types;
 
        irq_gc_lock(gc);
        if (b->can_wake)
@@ -94,10 +99,9 @@ static void bcm7120_l2_intc_suspend(struct irq_data *d)
        irq_gc_unlock(gc);
 }
 
-static void bcm7120_l2_intc_resume(struct irq_data *d)
+static void bcm7120_l2_intc_resume(struct irq_chip_generic *gc)
 {
-       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-       struct irq_chip_type *ct = irq_data_get_chip_type(d);
+       struct irq_chip_type *ct = gc->chip_types;
 
        /* Restore the saved mask */
        irq_gc_lock(gc);
@@ -107,8 +111,9 @@ static void bcm7120_l2_intc_resume(struct irq_data *d)
 
 static int bcm7120_l2_intc_init_one(struct device_node *dn,
                                        struct bcm7120_l2_intc_data *data,
-                                       int irq)
+                                       int irq, u32 *valid_mask)
 {
+       struct bcm7120_l1_intc_data *l1_data = &data->l1_data[irq];
        int parent_irq;
        unsigned int idx;
 
@@ -120,20 +125,28 @@ static int bcm7120_l2_intc_init_one(struct device_node *dn,
 
        /* For multiple parent IRQs with multiple words, this looks like:
         * <irq0_w0 irq0_w1 irq1_w0 irq1_w1 ...>
+        *
+        * We need to associate a given parent interrupt with its corresponding
+        * map_mask in order to mask the status register with it because we
+        * have the same handler being called for multiple parent interrupts.
+        *
+        * This is typically something needed on BCM7xxx (STB chips).
         */
        for (idx = 0; idx < data->n_words; idx++) {
                if (data->map_mask_prop) {
-                       data->irq_map_mask[idx] |=
+                       l1_data->irq_map_mask[idx] |=
                                be32_to_cpup(data->map_mask_prop +
                                             irq * data->n_words + idx);
                } else {
-                       data->irq_map_mask[idx] = 0xffffffff;
+                       l1_data->irq_map_mask[idx] = 0xffffffff;
                }
+               valid_mask[idx] |= l1_data->irq_map_mask[idx];
        }
 
-       irq_set_handler_data(parent_irq, data);
-       irq_set_chained_handler(parent_irq, bcm7120_l2_intc_irq_handle);
+       l1_data->b = data;
 
+       irq_set_chained_handler_and_data(parent_irq,
+                                        bcm7120_l2_intc_irq_handle, l1_data);
        return 0;
 }
 
@@ -214,6 +227,7 @@ int __init bcm7120_l2_intc_probe(struct device_node *dn,
        struct irq_chip_type *ct;
        int ret = 0;
        unsigned int idx, irq, flags;
+       u32 valid_mask[MAX_WORDS] = { };
 
        data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
@@ -226,9 +240,16 @@ int __init bcm7120_l2_intc_probe(struct device_node *dn,
                goto out_unmap;
        }
 
+       data->l1_data = kcalloc(data->num_parent_irqs, sizeof(*data->l1_data),
+                               GFP_KERNEL);
+       if (!data->l1_data) {
+               ret = -ENOMEM;
+               goto out_free_l1_data;
+       }
+
        ret = iomap_regs_fn(dn, data);
        if (ret < 0)
-               goto out_unmap;
+               goto out_free_l1_data;
 
        for (idx = 0; idx < data->n_words; idx++) {
                __raw_writel(data->irq_fwd_mask[idx],
@@ -237,16 +258,16 @@ int __init bcm7120_l2_intc_probe(struct device_node *dn,
        }
 
        for (irq = 0; irq < data->num_parent_irqs; irq++) {
-               ret = bcm7120_l2_intc_init_one(dn, data, irq);
+               ret = bcm7120_l2_intc_init_one(dn, data, irq, valid_mask);
                if (ret)
-                       goto out_unmap;
+                       goto out_free_l1_data;
        }
 
        data->domain = irq_domain_add_linear(dn, IRQS_PER_WORD * data->n_words,
                                             &irq_generic_chip_ops, NULL);
        if (!data->domain) {
                ret = -ENOMEM;
-               goto out_unmap;
+               goto out_free_l1_data;
        }
 
        /* MIPS chips strapped for BE will automagically configure the
@@ -270,7 +291,7 @@ int __init bcm7120_l2_intc_probe(struct device_node *dn,
                irq = idx * IRQS_PER_WORD;
                gc = irq_get_domain_generic_chip(data->domain, irq);
 
-               gc->unused = 0xffffffff & ~data->irq_map_mask[idx];
+               gc->unused = 0xffffffff & ~valid_mask[idx];
                gc->private = data;
                ct = gc->chip_types;
 
@@ -280,8 +301,15 @@ int __init bcm7120_l2_intc_probe(struct device_node *dn,
                ct->chip.irq_mask = irq_gc_mask_clr_bit;
                ct->chip.irq_unmask = irq_gc_mask_set_bit;
                ct->chip.irq_ack = irq_gc_noop;
-               ct->chip.irq_suspend = bcm7120_l2_intc_suspend;
-               ct->chip.irq_resume = bcm7120_l2_intc_resume;
+               gc->suspend = bcm7120_l2_intc_suspend;
+               gc->resume = bcm7120_l2_intc_resume;
+
+               /*
+                * Initialize mask-cache, in case we need it for
+                * saving/restoring fwd mask even w/o any child interrupts
+                * installed
+                */
+               gc->mask_cache = irq_reg_readl(gc, ct->regs.mask);
 
                if (data->can_wake) {
                        /* This IRQ chip can wake the system, set all
@@ -300,6 +328,8 @@ int __init bcm7120_l2_intc_probe(struct device_node *dn,
 
 out_free_domain:
        irq_domain_remove(data->domain);
+out_free_l1_data:
+       kfree(data->l1_data);
 out_unmap:
        for (idx = 0; idx < MAX_MAPPINGS; idx++) {
                if (data->map_base[idx])
index d6bcc6be077777551bf5a970938d3703fdc477d0..aedda06191eb08cdf0a688a9a7fbe63959e021f1 100644 (file)
@@ -32,8 +32,6 @@
 #include <linux/irqchip.h>
 #include <linux/irqchip/chained_irq.h>
 
-#include "irqchip.h"
-
 /* Register offsets in the L2 interrupt controller */
 #define CPU_STATUS     0x00
 #define CPU_SET                0x04
@@ -51,11 +49,13 @@ struct brcmstb_l2_intc_data {
        u32 saved_mask; /* for suspend/resume */
 };
 
-static void brcmstb_l2_intc_irq_handle(unsigned int irq, struct irq_desc *desc)
+static void brcmstb_l2_intc_irq_handle(unsigned int __irq,
+                                      struct irq_desc *desc)
 {
        struct brcmstb_l2_intc_data *b = irq_desc_get_handler_data(desc);
        struct irq_chip_generic *gc = irq_get_domain_generic_chip(b->domain, 0);
        struct irq_chip *chip = irq_desc_get_chip(desc);
+       unsigned int irq = irq_desc_get_irq(desc);
        u32 status;
 
        chained_irq_enter(chip, desc);
@@ -172,8 +172,8 @@ int __init brcmstb_l2_intc_of_init(struct device_node *np,
        }
 
        /* Set the IRQ chaining logic */
-       irq_set_handler_data(data->parent_irq, data);
-       irq_set_chained_handler(data->parent_irq, brcmstb_l2_intc_irq_handle);
+       irq_set_chained_handler_and_data(data->parent_irq,
+                                        brcmstb_l2_intc_irq_handle, data);
 
        gc = irq_get_domain_generic_chip(data->domain, 0);
        gc->reg_base = data->base;
index 33127f131d7840b0c0ec4c8ca15b0aa46b9ab5ba..2dd929eed9e0516fca48845f83720578622609be 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -19,8 +20,6 @@
 #include <asm/exception.h>
 #include <asm/mach/irq.h>
 
-#include "irqchip.h"
-
 #define CLPS711X_INTSR1        (0x0240)
 #define CLPS711X_INTMR1        (0x0280)
 #define CLPS711X_BLEOI (0x0600)
index c12bb93334ff99e7a5ddc72d274b00c4eeb9c24c..a7f5626930f506289c6eaea34529c20b2051c750 100644 (file)
  */
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/slab.h>
 
-#include "irqchip.h"
-
 #define IRQ_FREE       -1
 #define IRQ_RESERVED   -2
 #define IRQ_SKIP       -3
index 3cbc658afe27a4f7d28875373a1816afad86ac8b..dad85e74c37c051c02ea1b859db6aa5e66047731 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -20,8 +21,6 @@
 
 #include <asm/exception.h>
 
-#include "irqchip.h"
-
 #define UC_IRQ_CONTROL         0x04
 
 #define IC_FLAG_CLEAR_LO       0x00
index 53bb7326a60a6a597c159032627daa7d46d8ffe9..efd95d9955e7e3b5a0be532f36fa64c8a7c4da47 100644 (file)
 
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 
-#include "irqchip.h"
-
 #define APB_INT_ENABLE_L       0x00
 #define APB_INT_ENABLE_H       0x04
 #define APB_INT_MASK_L         0x08
 #define APB_INT_MASK_H         0x0c
 #define APB_INT_FINALSTATUS_L  0x30
 #define APB_INT_FINALSTATUS_H  0x34
+#define APB_INT_BASE_OFFSET    0x04
 
 static void dw_apb_ictl_handler(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_chip *chip = irq_get_chip(irq);
-       struct irq_chip_generic *gc = irq_get_handler_data(irq);
-       struct irq_domain *d = gc->private;
-       u32 stat;
+       struct irq_domain *d = irq_desc_get_handler_data(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        int n;
 
        chained_irq_enter(chip, desc);
 
-       for (n = 0; n < gc->num_ct; n++) {
-               stat = readl_relaxed(gc->reg_base +
-                                    APB_INT_FINALSTATUS_L + 4 * n);
+       for (n = 0; n < d->revmap_size; n += 32) {
+               struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, n);
+               u32 stat = readl_relaxed(gc->reg_base + APB_INT_FINALSTATUS_L);
+
                while (stat) {
                        u32 hwirq = ffs(stat) - 1;
-                       generic_handle_irq(irq_find_mapping(d,
-                                           gc->irq_base + hwirq + 32 * n));
+                       u32 virq = irq_find_mapping(d, gc->irq_base + hwirq);
+
+                       generic_handle_irq(virq);
                        stat &= ~(1 << hwirq);
                }
        }
@@ -73,7 +73,7 @@ static int __init dw_apb_ictl_init(struct device_node *np,
        struct irq_domain *domain;
        struct irq_chip_generic *gc;
        void __iomem *iobase;
-       int ret, nrirqs, irq;
+       int ret, nrirqs, irq, i;
        u32 reg;
 
        /* Map the parent interrupt for the chained handler */
@@ -128,35 +128,25 @@ static int __init dw_apb_ictl_init(struct device_node *np,
                goto err_unmap;
        }
 
-       ret = irq_alloc_domain_generic_chips(domain, 32, (nrirqs > 32) ? 2 : 1,
-                                            np->name, handle_level_irq, clr, 0,
-                                            IRQ_GC_MASK_CACHE_PER_TYPE |
+       ret = irq_alloc_domain_generic_chips(domain, 32, 1, np->name,
+                                            handle_level_irq, clr, 0,
                                             IRQ_GC_INIT_MASK_CACHE);
        if (ret) {
                pr_err("%s: unable to alloc irq domain gc\n", np->full_name);
                goto err_unmap;
        }
 
-       gc = irq_get_domain_generic_chip(domain, 0);
-       gc->private = domain;
-       gc->reg_base = iobase;
-
-       gc->chip_types[0].regs.mask = APB_INT_MASK_L;
-       gc->chip_types[0].regs.enable = APB_INT_ENABLE_L;
-       gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit;
-       gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit;
-       gc->chip_types[0].chip.irq_resume = dw_apb_ictl_resume;
-
-       if (nrirqs > 32) {
-               gc->chip_types[1].regs.mask = APB_INT_MASK_H;
-               gc->chip_types[1].regs.enable = APB_INT_ENABLE_H;
-               gc->chip_types[1].chip.irq_mask = irq_gc_mask_set_bit;
-               gc->chip_types[1].chip.irq_unmask = irq_gc_mask_clr_bit;
-               gc->chip_types[1].chip.irq_resume = dw_apb_ictl_resume;
+       for (i = 0; i < DIV_ROUND_UP(nrirqs, 32); i++) {
+               gc = irq_get_domain_generic_chip(domain, i * 32);
+               gc->reg_base = iobase + i * APB_INT_BASE_OFFSET;
+               gc->chip_types[0].regs.mask = APB_INT_MASK_L;
+               gc->chip_types[0].regs.enable = APB_INT_ENABLE_L;
+               gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit;
+               gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit;
+               gc->chip_types[0].chip.irq_resume = dw_apb_ictl_resume;
        }
 
-       irq_set_handler_data(irq, gc);
-       irq_set_chained_handler(irq, dw_apb_ictl_handler);
+       irq_set_chained_handler_and_data(irq, dw_apb_ictl_handler, domain);
 
        return 0;
 
index fdf706555d72f3a84b76513262bb5ab6dc688526..db04fc1f56b2578203964a13c48548376af8a7fb 100644 (file)
 
 struct v2m_data {
        spinlock_t msi_cnt_lock;
-       struct msi_controller mchip;
        struct resource res;    /* GICv2m resource */
        void __iomem *base;     /* GICv2m virt address */
        u32 spi_start;          /* The SPI number that MSIs start */
        u32 nr_spis;            /* The number of SPIs for MSIs */
        unsigned long *bm;      /* MSI vector bitmap */
-       struct irq_domain *domain;
 };
 
 static void gicv2m_mask_msi_irq(struct irq_data *d)
@@ -213,11 +211,25 @@ static bool is_msi_spi_valid(u32 base, u32 num)
        return true;
 }
 
+static struct irq_chip gicv2m_pmsi_irq_chip = {
+       .name                   = "pMSI",
+};
+
+static struct msi_domain_ops gicv2m_pmsi_ops = {
+};
+
+static struct msi_domain_info gicv2m_pmsi_domain_info = {
+       .flags  = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
+       .ops    = &gicv2m_pmsi_ops,
+       .chip   = &gicv2m_pmsi_irq_chip,
+};
+
 static int __init gicv2m_init_one(struct device_node *node,
                                  struct irq_domain *parent)
 {
        int ret;
        struct v2m_data *v2m;
+       struct irq_domain *inner_domain, *pci_domain, *plat_domain;
 
        v2m = kzalloc(sizeof(struct v2m_data), GFP_KERNEL);
        if (!v2m) {
@@ -261,32 +273,28 @@ static int __init gicv2m_init_one(struct device_node *node,
                goto err_iounmap;
        }
 
-       v2m->domain = irq_domain_add_tree(NULL, &gicv2m_domain_ops, v2m);
-       if (!v2m->domain) {
+       inner_domain = irq_domain_add_tree(node, &gicv2m_domain_ops, v2m);
+       if (!inner_domain) {
                pr_err("Failed to create GICv2m domain\n");
                ret = -ENOMEM;
                goto err_free_bm;
        }
 
-       v2m->domain->parent = parent;
-       v2m->mchip.of_node = node;
-       v2m->mchip.domain = pci_msi_create_irq_domain(node,
-                                                     &gicv2m_msi_domain_info,
-                                                     v2m->domain);
-       if (!v2m->mchip.domain) {
-               pr_err("Failed to create MSI domain\n");
+       inner_domain->bus_token = DOMAIN_BUS_NEXUS;
+       inner_domain->parent = parent;
+       pci_domain = pci_msi_create_irq_domain(node, &gicv2m_msi_domain_info,
+                                              inner_domain);
+       plat_domain = platform_msi_create_irq_domain(node,
+                                                    &gicv2m_pmsi_domain_info,
+                                                    inner_domain);
+       if (!pci_domain || !plat_domain) {
+               pr_err("Failed to create MSI domains\n");
                ret = -ENOMEM;
                goto err_free_domains;
        }
 
        spin_lock_init(&v2m->msi_cnt_lock);
 
-       ret = of_pci_msi_chip_add(&v2m->mchip);
-       if (ret) {
-               pr_err("Failed to add msi_chip.\n");
-               goto err_free_domains;
-       }
-
        pr_info("Node %s: range[%#lx:%#lx], SPI[%d:%d]\n", node->name,
                (unsigned long)v2m->res.start, (unsigned long)v2m->res.end,
                v2m->spi_start, (v2m->spi_start + v2m->nr_spis));
@@ -294,10 +302,12 @@ static int __init gicv2m_init_one(struct device_node *node,
        return 0;
 
 err_free_domains:
-       if (v2m->mchip.domain)
-               irq_domain_remove(v2m->mchip.domain);
-       if (v2m->domain)
-               irq_domain_remove(v2m->domain);
+       if (plat_domain)
+               irq_domain_remove(plat_domain);
+       if (pci_domain)
+               irq_domain_remove(pci_domain);
+       if (inner_domain)
+               irq_domain_remove(inner_domain);
 err_free_bm:
        kfree(v2m->bm);
 err_iounmap:
diff --git a/drivers/irqchip/irq-gic-v3-its-pci-msi.c b/drivers/irqchip/irq-gic-v3-its-pci-msi.c
new file mode 100644 (file)
index 0000000..cf351c6
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2013-2015 ARM Limited, All Rights Reserved.
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/msi.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_pci.h>
+
+static void its_mask_msi_irq(struct irq_data *d)
+{
+       pci_msi_mask_irq(d);
+       irq_chip_mask_parent(d);
+}
+
+static void its_unmask_msi_irq(struct irq_data *d)
+{
+       pci_msi_unmask_irq(d);
+       irq_chip_unmask_parent(d);
+}
+
+static struct irq_chip its_msi_irq_chip = {
+       .name                   = "ITS-MSI",
+       .irq_unmask             = its_unmask_msi_irq,
+       .irq_mask               = its_mask_msi_irq,
+       .irq_eoi                = irq_chip_eoi_parent,
+       .irq_write_msi_msg      = pci_msi_domain_write_msg,
+};
+
+struct its_pci_alias {
+       struct pci_dev  *pdev;
+       u32             dev_id;
+       u32             count;
+};
+
+static int its_pci_msi_vec_count(struct pci_dev *pdev)
+{
+       int msi, msix;
+
+       msi = max(pci_msi_vec_count(pdev), 0);
+       msix = max(pci_msix_vec_count(pdev), 0);
+
+       return max(msi, msix);
+}
+
+static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data)
+{
+       struct its_pci_alias *dev_alias = data;
+
+       dev_alias->dev_id = alias;
+       if (pdev != dev_alias->pdev)
+               dev_alias->count += its_pci_msi_vec_count(dev_alias->pdev);
+
+       return 0;
+}
+
+static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev,
+                              int nvec, msi_alloc_info_t *info)
+{
+       struct pci_dev *pdev;
+       struct its_pci_alias dev_alias;
+       struct msi_domain_info *msi_info;
+
+       if (!dev_is_pci(dev))
+               return -EINVAL;
+
+       msi_info = msi_get_domain_info(domain->parent);
+
+       pdev = to_pci_dev(dev);
+       dev_alias.pdev = pdev;
+       dev_alias.count = nvec;
+
+       pci_for_each_dma_alias(pdev, its_get_pci_alias, &dev_alias);
+
+       /* ITS specific DeviceID, as the core ITS ignores dev. */
+       info->scratchpad[0].ul = dev_alias.dev_id;
+
+       return msi_info->ops->msi_prepare(domain->parent,
+                                         dev, dev_alias.count, info);
+}
+
+static struct msi_domain_ops its_pci_msi_ops = {
+       .msi_prepare    = its_pci_msi_prepare,
+};
+
+static struct msi_domain_info its_pci_msi_domain_info = {
+       .flags  = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+                  MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX),
+       .ops    = &its_pci_msi_ops,
+       .chip   = &its_msi_irq_chip,
+};
+
+static struct of_device_id its_device_id[] = {
+       {       .compatible     = "arm,gic-v3-its",     },
+       {},
+};
+
+static int __init its_pci_msi_init(void)
+{
+       struct device_node *np;
+       struct irq_domain *parent;
+
+       for (np = of_find_matching_node(NULL, its_device_id); np;
+            np = of_find_matching_node(np, its_device_id)) {
+               if (!of_property_read_bool(np, "msi-controller"))
+                       continue;
+
+               parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS);
+               if (!parent || !msi_get_domain_info(parent)) {
+                       pr_err("%s: unable to locate ITS domain\n",
+                              np->full_name);
+                       continue;
+               }
+
+               if (!pci_msi_create_irq_domain(np, &its_pci_msi_domain_info,
+                                              parent)) {
+                       pr_err("%s: unable to create PCI domain\n",
+                              np->full_name);
+                       continue;
+               }
+
+               pr_info("PCI/MSI: %s domain created\n", np->full_name);
+       }
+
+       return 0;
+}
+early_initcall(its_pci_msi_init);
diff --git a/drivers/irqchip/irq-gic-v3-its-platform-msi.c b/drivers/irqchip/irq-gic-v3-its-platform-msi.c
new file mode 100644 (file)
index 0000000..a865505
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2013-2015 ARM Limited, All Rights Reserved.
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/device.h>
+#include <linux/msi.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+
+static struct irq_chip its_pmsi_irq_chip = {
+       .name                   = "ITS-pMSI",
+};
+
+static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev,
+                           int nvec, msi_alloc_info_t *info)
+{
+       struct msi_domain_info *msi_info;
+       u32 dev_id;
+       int ret;
+
+       msi_info = msi_get_domain_info(domain->parent);
+
+       /* Suck the DeviceID out of the msi-parent property */
+       ret = of_property_read_u32_index(dev->of_node, "msi-parent",
+                                        1, &dev_id);
+       if (ret)
+               return ret;
+
+       /* ITS specific DeviceID, as the core ITS ignores dev. */
+       info->scratchpad[0].ul = dev_id;
+
+       return msi_info->ops->msi_prepare(domain->parent,
+                                         dev, nvec, info);
+}
+
+static struct msi_domain_ops its_pmsi_ops = {
+       .msi_prepare    = its_pmsi_prepare,
+};
+
+static struct msi_domain_info its_pmsi_domain_info = {
+       .flags  = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
+       .ops    = &its_pmsi_ops,
+       .chip   = &its_pmsi_irq_chip,
+};
+
+static struct of_device_id its_device_id[] = {
+       {       .compatible     = "arm,gic-v3-its",     },
+       {},
+};
+
+static int __init its_pmsi_init(void)
+{
+       struct device_node *np;
+       struct irq_domain *parent;
+
+       for (np = of_find_matching_node(NULL, its_device_id); np;
+            np = of_find_matching_node(np, its_device_id)) {
+               if (!of_property_read_bool(np, "msi-controller"))
+                       continue;
+
+               parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS);
+               if (!parent || !msi_get_domain_info(parent)) {
+                       pr_err("%s: unable to locate ITS domain\n",
+                              np->full_name);
+                       continue;
+               }
+
+               if (!platform_msi_create_irq_domain(np, &its_pmsi_domain_info,
+                                                   parent)) {
+                       pr_err("%s: unable to create platform domain\n",
+                              np->full_name);
+                       continue;
+               }
+
+               pr_info("Platform MSI: %s domain created\n", np->full_name);
+       }
+
+       return 0;
+}
+early_initcall(its_pmsi_init);
index c00e2db351ba5aec327ebb1e98085b25b9b4d056..26b55c53755f0db82c5b4cbcd1c16a9beb5c5109 100644 (file)
 #include <linux/percpu.h>
 #include <linux/slab.h>
 
+#include <linux/irqchip.h>
 #include <linux/irqchip/arm-gic-v3.h>
 
 #include <asm/cacheflush.h>
 #include <asm/cputype.h>
 #include <asm/exception.h>
 
-#include "irqchip.h"
-
 #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING          (1 << 0)
 
 #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING    (1 << 0)
@@ -54,14 +53,12 @@ struct its_collection {
 
 /*
  * The ITS structure - contains most of the infrastructure, with the
- * msi_controller, the command queue, the collections, and the list of
- * devices writing to it.
+ * top-level MSI domain, the command queue, the collections, and the
+ * list of devices writing to it.
  */
 struct its_node {
        raw_spinlock_t          lock;
        struct list_head        entry;
-       struct msi_controller   msi_chip;
-       struct irq_domain       *domain;
        void __iomem            *base;
        unsigned long           phys_base;
        struct its_cmd_block    *cmd_base;
@@ -643,26 +640,6 @@ static struct irq_chip its_irq_chip = {
        .irq_compose_msi_msg    = its_irq_compose_msi_msg,
 };
 
-static void its_mask_msi_irq(struct irq_data *d)
-{
-       pci_msi_mask_irq(d);
-       irq_chip_mask_parent(d);
-}
-
-static void its_unmask_msi_irq(struct irq_data *d)
-{
-       pci_msi_unmask_irq(d);
-       irq_chip_unmask_parent(d);
-}
-
-static struct irq_chip its_msi_irq_chip = {
-       .name                   = "ITS-MSI",
-       .irq_unmask             = its_unmask_msi_irq,
-       .irq_mask               = its_mask_msi_irq,
-       .irq_eoi                = irq_chip_eoi_parent,
-       .irq_write_msi_msg      = pci_msi_domain_write_msg,
-};
-
 /*
  * How we allocate LPIs:
  *
@@ -831,7 +808,7 @@ static void its_free_tables(struct its_node *its)
        }
 }
 
-static int its_alloc_tables(struct its_node *its)
+static int its_alloc_tables(const char *node_name, struct its_node *its)
 {
        int err;
        int i;
@@ -874,7 +851,7 @@ static int its_alloc_tables(struct its_node *its)
                        if (order >= MAX_ORDER) {
                                order = MAX_ORDER - 1;
                                pr_warn("%s: Device Table too large, reduce its page order to %u\n",
-                                       its->msi_chip.of_node->full_name, order);
+                                       node_name, order);
                        }
                }
 
@@ -944,7 +921,7 @@ retry_baser:
 
                if (val != tmp) {
                        pr_err("ITS: %s: GITS_BASER%d doesn't stick: %lx %lx\n",
-                              its->msi_chip.of_node->full_name, i,
+                              node_name, i,
                               (unsigned long) val, (unsigned long) tmp);
                        err = -ENXIO;
                        goto out_free;
@@ -1209,85 +1186,50 @@ static int its_alloc_device_irq(struct its_device *dev, irq_hw_number_t *hwirq)
        return 0;
 }
 
-struct its_pci_alias {
-       struct pci_dev  *pdev;
-       u32             dev_id;
-       u32             count;
-};
-
-static int its_pci_msi_vec_count(struct pci_dev *pdev)
-{
-       int msi, msix;
-
-       msi = max(pci_msi_vec_count(pdev), 0);
-       msix = max(pci_msix_vec_count(pdev), 0);
-
-       return max(msi, msix);
-}
-
-static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data)
-{
-       struct its_pci_alias *dev_alias = data;
-
-       dev_alias->dev_id = alias;
-       if (pdev != dev_alias->pdev)
-               dev_alias->count += its_pci_msi_vec_count(dev_alias->pdev);
-
-       return 0;
-}
-
 static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
                           int nvec, msi_alloc_info_t *info)
 {
-       struct pci_dev *pdev;
        struct its_node *its;
        struct its_device *its_dev;
-       struct its_pci_alias dev_alias;
-
-       if (!dev_is_pci(dev))
-               return -EINVAL;
+       struct msi_domain_info *msi_info;
+       u32 dev_id;
 
-       pdev = to_pci_dev(dev);
-       dev_alias.pdev = pdev;
-       dev_alias.count = nvec;
+       /*
+        * We ignore "dev" entierely, and rely on the dev_id that has
+        * been passed via the scratchpad. This limits this domain's
+        * usefulness to upper layers that definitely know that they
+        * are built on top of the ITS.
+        */
+       dev_id = info->scratchpad[0].ul;
 
-       pci_for_each_dma_alias(pdev, its_get_pci_alias, &dev_alias);
-       its = domain->parent->host_data;
+       msi_info = msi_get_domain_info(domain);
+       its = msi_info->data;
 
-       its_dev = its_find_device(its, dev_alias.dev_id);
+       its_dev = its_find_device(its, dev_id);
        if (its_dev) {
                /*
                 * We already have seen this ID, probably through
                 * another alias (PCI bridge of some sort). No need to
                 * create the device.
                 */
-               dev_dbg(dev, "Reusing ITT for devID %x\n", dev_alias.dev_id);
+               pr_debug("Reusing ITT for devID %x\n", dev_id);
                goto out;
        }
 
-       its_dev = its_create_device(its, dev_alias.dev_id, dev_alias.count);
+       its_dev = its_create_device(its, dev_id, nvec);
        if (!its_dev)
                return -ENOMEM;
 
-       dev_dbg(&pdev->dev, "ITT %d entries, %d bits\n",
-               dev_alias.count, ilog2(dev_alias.count));
+       pr_debug("ITT %d entries, %d bits\n", nvec, ilog2(nvec));
 out:
        info->scratchpad[0].ptr = its_dev;
-       info->scratchpad[1].ptr = dev;
        return 0;
 }
 
-static struct msi_domain_ops its_pci_msi_ops = {
+static struct msi_domain_ops its_msi_domain_ops = {
        .msi_prepare    = its_msi_prepare,
 };
 
-static struct msi_domain_info its_pci_msi_domain_info = {
-       .flags  = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
-                  MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX),
-       .ops    = &its_pci_msi_ops,
-       .chip   = &its_msi_irq_chip,
-};
-
 static int its_irq_gic_domain_alloc(struct irq_domain *domain,
                                    unsigned int virq,
                                    irq_hw_number_t hwirq)
@@ -1323,9 +1265,9 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 
                irq_domain_set_hwirq_and_chip(domain, virq + i,
                                              hwirq, &its_irq_chip, its_dev);
-               dev_dbg(info->scratchpad[1].ptr, "ID:%d pID:%d vID:%d\n",
-                       (int)(hwirq - its_dev->event_map.lpi_base),
-                       (int)hwirq, virq + i);
+               pr_debug("ID:%d pID:%d vID:%d\n",
+                        (int)(hwirq - its_dev->event_map.lpi_base),
+                        (int) hwirq, virq + i);
        }
 
        return 0;
@@ -1426,6 +1368,7 @@ static int its_probe(struct device_node *node, struct irq_domain *parent)
        struct resource res;
        struct its_node *its;
        void __iomem *its_base;
+       struct irq_domain *inner_domain;
        u32 val;
        u64 baser, tmp;
        int err;
@@ -1469,7 +1412,6 @@ static int its_probe(struct device_node *node, struct irq_domain *parent)
        INIT_LIST_HEAD(&its->its_device_list);
        its->base = its_base;
        its->phys_base = res.start;
-       its->msi_chip.of_node = node;
        its->ite_size = ((readl_relaxed(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
 
        its->cmd_base = kzalloc(ITS_CMD_QUEUE_SZ, GFP_KERNEL);
@@ -1479,7 +1421,7 @@ static int its_probe(struct device_node *node, struct irq_domain *parent)
        }
        its->cmd_write = its->cmd_base;
 
-       err = its_alloc_tables(its);
+       err = its_alloc_tables(node->full_name, its);
        if (err)
                goto out_free_cmd;
 
@@ -1515,26 +1457,27 @@ static int its_probe(struct device_node *node, struct irq_domain *parent)
        writeq_relaxed(0, its->base + GITS_CWRITER);
        writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR);
 
-       if (of_property_read_bool(its->msi_chip.of_node, "msi-controller")) {
-               its->domain = irq_domain_add_tree(NULL, &its_domain_ops, its);
-               if (!its->domain) {
+       if (of_property_read_bool(node, "msi-controller")) {
+               struct msi_domain_info *info;
+
+               info = kzalloc(sizeof(*info), GFP_KERNEL);
+               if (!info) {
                        err = -ENOMEM;
                        goto out_free_tables;
                }
 
-               its->domain->parent = parent;
-
-               its->msi_chip.domain = pci_msi_create_irq_domain(node,
-                                                                &its_pci_msi_domain_info,
-                                                                its->domain);
-               if (!its->msi_chip.domain) {
+               inner_domain = irq_domain_add_tree(node, &its_domain_ops, its);
+               if (!inner_domain) {
                        err = -ENOMEM;
-                       goto out_free_domains;
+                       kfree(info);
+                       goto out_free_tables;
                }
 
-               err = of_pci_msi_chip_add(&its->msi_chip);
-               if (err)
-                       goto out_free_domains;
+               inner_domain->parent = parent;
+               inner_domain->bus_token = DOMAIN_BUS_NEXUS;
+               info->ops = &its_msi_domain_ops;
+               info->data = its;
+               inner_domain->host_data = info;
        }
 
        spin_lock(&its_lock);
@@ -1543,11 +1486,6 @@ static int its_probe(struct device_node *node, struct irq_domain *parent)
 
        return 0;
 
-out_free_domains:
-       if (its->msi_chip.domain)
-               irq_domain_remove(its->msi_chip.domain);
-       if (its->domain)
-               irq_domain_remove(its->domain);
 out_free_tables:
        its_free_tables(its);
 out_free_cmd:
index c52f7ba205b4c872205323868ecf0349f8174b20..e406bc5f13e4f10083ff2d91aa9d81785a8cc2fe 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/percpu.h>
 #include <linux/slab.h>
 
+#include <linux/irqchip.h>
 #include <linux/irqchip/arm-gic-v3.h>
 
 #include <asm/cputype.h>
@@ -32,7 +33,6 @@
 #include <asm/smp_plat.h>
 
 #include "irq-gic-common.h"
-#include "irqchip.h"
 
 struct redist_region {
        void __iomem            *redist_base;
index 4dd88264dff55c0c95efd813c82fe762d7216263..aa3e7b8a69c4349bcd775c7c796062bda3b392f2 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
 #include <linux/slab.h>
+#include <linux/irqchip.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/irqchip/arm-gic.h>
 #include <linux/irqchip/arm-gic-acpi.h>
@@ -48,7 +49,6 @@
 #include <asm/smp_plat.h>
 
 #include "irq-gic-common.h"
-#include "irqchip.h"
 
 union gic_base {
        void __iomem *common_base;
@@ -288,8 +288,8 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
 
 static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
 {
-       struct gic_chip_data *chip_data = irq_get_handler_data(irq);
-       struct irq_chip *chip = irq_get_chip(irq);
+       struct gic_chip_data *chip_data = irq_desc_get_handler_data(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int cascade_irq, gic_irq;
        unsigned long status;
 
@@ -324,16 +324,17 @@ static struct irq_chip gic_chip = {
 #endif
        .irq_get_irqchip_state  = gic_irq_get_irqchip_state,
        .irq_set_irqchip_state  = gic_irq_set_irqchip_state,
-       .flags                  = IRQCHIP_SET_TYPE_MASKED,
+       .flags                  = IRQCHIP_SET_TYPE_MASKED |
+                                 IRQCHIP_SKIP_SET_WAKE |
+                                 IRQCHIP_MASK_ON_SUSPEND,
 };
 
 void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
 {
        if (gic_nr >= MAX_GIC_NR)
                BUG();
-       if (irq_set_handler_data(irq, &gic_data[gic_nr]) != 0)
-               BUG();
-       irq_set_chained_handler(irq, gic_handle_cascade_irq);
+       irq_set_chained_handler_and_data(irq, gic_handle_cascade_irq,
+                                        &gic_data[gic_nr]);
 }
 
 static u8 gic_get_cpumask(struct gic_chip_data *gic)
@@ -355,9 +356,9 @@ static u8 gic_get_cpumask(struct gic_chip_data *gic)
        return mask;
 }
 
-static void gic_cpu_if_up(void)
+static void gic_cpu_if_up(struct gic_chip_data *gic)
 {
-       void __iomem *cpu_base = gic_data_cpu_base(&gic_data[0]);
+       void __iomem *cpu_base = gic_data_cpu_base(gic);
        u32 bypass = 0;
 
        /*
@@ -401,34 +402,47 @@ static void gic_cpu_init(struct gic_chip_data *gic)
        int i;
 
        /*
-        * Get what the GIC says our CPU mask is.
+        * Setting up the CPU map is only relevant for the primary GIC
+        * because any nested/secondary GICs do not directly interface
+        * with the CPU(s).
         */
-       BUG_ON(cpu >= NR_GIC_CPU_IF);
-       cpu_mask = gic_get_cpumask(gic);
-       gic_cpu_map[cpu] = cpu_mask;
+       if (gic == &gic_data[0]) {
+               /*
+                * Get what the GIC says our CPU mask is.
+                */
+               BUG_ON(cpu >= NR_GIC_CPU_IF);
+               cpu_mask = gic_get_cpumask(gic);
+               gic_cpu_map[cpu] = cpu_mask;
 
-       /*
-        * Clear our mask from the other map entries in case they're
-        * still undefined.
-        */
-       for (i = 0; i < NR_GIC_CPU_IF; i++)
-               if (i != cpu)
-                       gic_cpu_map[i] &= ~cpu_mask;
+               /*
+                * Clear our mask from the other map entries in case they're
+                * still undefined.
+                */
+               for (i = 0; i < NR_GIC_CPU_IF; i++)
+                       if (i != cpu)
+                               gic_cpu_map[i] &= ~cpu_mask;
+       }
 
        gic_cpu_config(dist_base, NULL);
 
        writel_relaxed(GICC_INT_PRI_THRESHOLD, base + GIC_CPU_PRIMASK);
-       gic_cpu_if_up();
+       gic_cpu_if_up(gic);
 }
 
-void gic_cpu_if_down(void)
+int gic_cpu_if_down(unsigned int gic_nr)
 {
-       void __iomem *cpu_base = gic_data_cpu_base(&gic_data[0]);
+       void __iomem *cpu_base;
        u32 val = 0;
 
+       if (gic_nr >= MAX_GIC_NR)
+               return -EINVAL;
+
+       cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
        val = readl(cpu_base + GIC_CPU_CTRL);
        val &= ~GICC_ENABLE;
        writel_relaxed(val, cpu_base + GIC_CPU_CTRL);
+
+       return 0;
 }
 
 #ifdef CONFIG_CPU_PM
@@ -564,7 +578,7 @@ static void gic_cpu_restore(unsigned int gic_nr)
                                        dist_base + GIC_DIST_PRI + i * 4);
 
        writel_relaxed(GICC_INT_PRI_THRESHOLD, cpu_base + GIC_CPU_PRIMASK);
-       gic_cpu_if_up();
+       gic_cpu_if_up(&gic_data[gic_nr]);
 }
 
 static int gic_notifier(struct notifier_block *self, unsigned long cmd,        void *v)
@@ -880,11 +894,6 @@ static const struct irq_domain_ops gic_irq_domain_ops = {
        .xlate = gic_irq_domain_xlate,
 };
 
-void gic_set_irqchip_flags(unsigned long flags)
-{
-       gic_chip.flags |= flags;
-}
-
 void __init gic_init_bases(unsigned int gic_nr, int irq_start,
                           void __iomem *dist_base, void __iomem *cpu_base,
                           u32 percpu_offset, struct device_node *node)
@@ -929,13 +938,6 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
                gic_set_base_accessor(gic, gic_get_common_base);
        }
 
-       /*
-        * Initialize the CPU interface map to all CPUs.
-        * It will be refined as each CPU probes its ID.
-        */
-       for (i = 0; i < NR_GIC_CPU_IF; i++)
-               gic_cpu_map[i] = 0xff;
-
        /*
         * Find out how many interrupts are supported.
         * The GIC only supports up to 1020 interrupt sources.
@@ -981,6 +983,13 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
                return;
 
        if (gic_nr == 0) {
+               /*
+                * Initialize the CPU interface map to all CPUs.
+                * It will be refined as each CPU probes its ID.
+                * This is only necessary for the primary GIC.
+                */
+               for (i = 0; i < NR_GIC_CPU_IF; i++)
+                       gic_cpu_map[i] = 0xff;
 #ifdef CONFIG_SMP
                set_smp_cross_call(gic_raise_softirq);
                register_cpu_notifier(&gic_cpu_notifier);
index 0cae45d106950783108b60c31432a9149e75f638..a0128c7c98dd5d6e62335894b3369a2709856248 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/irqdomain.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/irqchip.h>
 #include <linux/irqchip/arm-gic.h>
 
 #include <asm/irq.h>
@@ -48,7 +49,6 @@
 #include <asm/smp_plat.h>
 
 #include "irq-gic-common.h"
-#include "irqchip.h"
 
 #define HIP04_MAX_IRQS         510
 
@@ -202,7 +202,9 @@ static struct irq_chip hip04_irq_chip = {
 #ifdef CONFIG_SMP
        .irq_set_affinity       = hip04_irq_set_affinity,
 #endif
-       .flags                  = IRQCHIP_SET_TYPE_MASKED,
+       .flags                  = IRQCHIP_SET_TYPE_MASKED |
+                                 IRQCHIP_SKIP_SET_WAKE |
+                                 IRQCHIP_MASK_ON_SUSPEND,
 };
 
 static u16 hip04_get_cpumask(struct hip04_irq_data *intc)
similarity index 98%
rename from arch/mips/kernel/i8259.c
rename to drivers/irqchip/irq-i8259.c
index 74f6752814d342387d1182e6d779fb15c1235691..4836102ba31205ddc5643e1bfacc24e4cd81eacb 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
 #include <linux/of_irq.h>
@@ -22,8 +23,6 @@
 #include <asm/i8259.h>
 #include <asm/io.h>
 
-#include "../../drivers/irqchip/irqchip.h"
-
 /*
  * This is the 'legacy' 8259A Programmable Interrupt Controller,
  * present in the majority of PC/AT boxes.
@@ -353,10 +352,11 @@ void __init init_i8259_irqs(void)
        __init_i8259_irqs(NULL);
 }
 
-static void i8259_irq_dispatch(unsigned int irq, struct irq_desc *desc)
+static void i8259_irq_dispatch(unsigned int __irq, struct irq_desc *desc)
 {
-       struct irq_domain *domain = irq_get_handler_data(irq);
+       struct irq_domain *domain = irq_desc_get_handler_data(desc);
        int hwirq = i8259_irq();
+       unsigned int irq;
 
        if (hwirq < 0)
                return;
index 8071c2eb02487f2f6a681f0ad2b62df01b418d58..841604b81004f415473a91f970ae74a02d3a8052 100644 (file)
@@ -218,8 +218,9 @@ static int pdc_irq_set_wake(struct irq_data *data, unsigned int on)
        return 0;
 }
 
-static void pdc_intc_perip_isr(unsigned int irq, struct irq_desc *desc)
+static void pdc_intc_perip_isr(unsigned int __irq, struct irq_desc *desc)
 {
+       unsigned int irq = irq_desc_get_irq(desc);
        struct pdc_intc_priv *priv;
        unsigned int i, irq_no;
 
@@ -451,13 +452,13 @@ static int pdc_intc_probe(struct platform_device *pdev)
        /* Setup chained handlers for the peripheral IRQs */
        for (i = 0; i < priv->nr_perips; ++i) {
                irq = priv->perip_irqs[i];
-               irq_set_handler_data(irq, priv);
-               irq_set_chained_handler(irq, pdc_intc_perip_isr);
+               irq_set_chained_handler_and_data(irq, pdc_intc_perip_isr,
+                                                priv);
        }
 
        /* Setup chained handler for the syswake IRQ */
-       irq_set_handler_data(priv->syswake_irq, priv);
-       irq_set_chained_handler(priv->syswake_irq, pdc_intc_syswake_isr);
+       irq_set_chained_handler_and_data(priv->syswake_irq,
+                                        pdc_intc_syswake_isr, priv);
 
        dev_info(&pdev->dev,
                 "PDC IRQ controller initialised (%u perip IRQs, %u syswake IRQs)\n",
diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c
new file mode 100644 (file)
index 0000000..e48d330
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/irqchip.h>
+#include <linux/syscore_ops.h>
+
+#define IMR_NUM                        4
+#define GPC_MAX_IRQS            (IMR_NUM * 32)
+
+#define GPC_IMR1_CORE0         0x30
+#define GPC_IMR1_CORE1         0x40
+
+struct gpcv2_irqchip_data {
+       struct raw_spinlock     rlock;
+       void __iomem            *gpc_base;
+       u32                     wakeup_sources[IMR_NUM];
+       u32                     saved_irq_mask[IMR_NUM];
+       u32                     cpu2wakeup;
+};
+
+static struct gpcv2_irqchip_data *imx_gpcv2_instance;
+
+/*
+ * Interface for the low level wakeup code.
+ */
+u32 imx_gpcv2_get_wakeup_source(u32 **sources)
+{
+       if (!imx_gpcv2_instance)
+               return 0;
+
+       if (sources)
+               *sources = imx_gpcv2_instance->wakeup_sources;
+
+       return IMR_NUM;
+}
+
+static int gpcv2_wakeup_source_save(void)
+{
+       struct gpcv2_irqchip_data *cd;
+       void __iomem *reg;
+       int i;
+
+       cd = imx_gpcv2_instance;
+       if (!cd)
+               return 0;
+
+       for (i = 0; i < IMR_NUM; i++) {
+               reg = cd->gpc_base + cd->cpu2wakeup + i * 4;
+               cd->saved_irq_mask[i] = readl_relaxed(reg);
+               writel_relaxed(cd->wakeup_sources[i], reg);
+       }
+
+       return 0;
+}
+
+static void gpcv2_wakeup_source_restore(void)
+{
+       struct gpcv2_irqchip_data *cd;
+       void __iomem *reg;
+       int i;
+
+       cd = imx_gpcv2_instance;
+       if (!cd)
+               return;
+
+       for (i = 0; i < IMR_NUM; i++) {
+               reg = cd->gpc_base + cd->cpu2wakeup + i * 4;
+               writel_relaxed(cd->saved_irq_mask[i], reg);
+       }
+}
+
+static struct syscore_ops imx_gpcv2_syscore_ops = {
+       .suspend        = gpcv2_wakeup_source_save,
+       .resume         = gpcv2_wakeup_source_restore,
+};
+
+static int imx_gpcv2_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+       struct gpcv2_irqchip_data *cd = d->chip_data;
+       unsigned int idx = d->hwirq / 32;
+       unsigned long flags;
+       void __iomem *reg;
+       u32 mask, val;
+
+       raw_spin_lock_irqsave(&cd->rlock, flags);
+       reg = cd->gpc_base + cd->cpu2wakeup + idx * 4;
+       mask = 1 << d->hwirq % 32;
+       val = cd->wakeup_sources[idx];
+
+       cd->wakeup_sources[idx] = on ? (val & ~mask) : (val | mask);
+       raw_spin_unlock_irqrestore(&cd->rlock, flags);
+
+       /*
+        * Do *not* call into the parent, as the GIC doesn't have any
+        * wake-up facility...
+        */
+
+       return 0;
+}
+
+static void imx_gpcv2_irq_unmask(struct irq_data *d)
+{
+       struct gpcv2_irqchip_data *cd = d->chip_data;
+       void __iomem *reg;
+       u32 val;
+
+       raw_spin_lock(&cd->rlock);
+       reg = cd->gpc_base + cd->cpu2wakeup + d->hwirq / 32 * 4;
+       val = readl_relaxed(reg);
+       val &= ~(1 << d->hwirq % 32);
+       writel_relaxed(val, reg);
+       raw_spin_unlock(&cd->rlock);
+
+       irq_chip_unmask_parent(d);
+}
+
+static void imx_gpcv2_irq_mask(struct irq_data *d)
+{
+       struct gpcv2_irqchip_data *cd = d->chip_data;
+       void __iomem *reg;
+       u32 val;
+
+       raw_spin_lock(&cd->rlock);
+       reg = cd->gpc_base + cd->cpu2wakeup + d->hwirq / 32 * 4;
+       val = readl_relaxed(reg);
+       val |= 1 << (d->hwirq % 32);
+       writel_relaxed(val, reg);
+       raw_spin_unlock(&cd->rlock);
+
+       irq_chip_mask_parent(d);
+}
+
+static struct irq_chip gpcv2_irqchip_data_chip = {
+       .name                   = "GPCv2",
+       .irq_eoi                = irq_chip_eoi_parent,
+       .irq_mask               = imx_gpcv2_irq_mask,
+       .irq_unmask             = imx_gpcv2_irq_unmask,
+       .irq_set_wake           = imx_gpcv2_irq_set_wake,
+       .irq_retrigger          = irq_chip_retrigger_hierarchy,
+#ifdef CONFIG_SMP
+       .irq_set_affinity       = irq_chip_set_affinity_parent,
+#endif
+};
+
+static int imx_gpcv2_domain_xlate(struct irq_domain *domain,
+                               struct device_node *controller,
+                               const u32 *intspec,
+                               unsigned int intsize,
+                               unsigned long *out_hwirq,
+                               unsigned int *out_type)
+{
+       /* Shouldn't happen, really... */
+       if (domain->of_node != controller)
+               return -EINVAL;
+
+       /* Not GIC compliant */
+       if (intsize != 3)
+               return -EINVAL;
+
+       /* No PPI should point to this domain */
+       if (intspec[0] != 0)
+               return -EINVAL;
+
+       *out_hwirq = intspec[1];
+       *out_type = intspec[2];
+       return 0;
+}
+
+static int imx_gpcv2_domain_alloc(struct irq_domain *domain,
+                                 unsigned int irq, unsigned int nr_irqs,
+                                 void *data)
+{
+       struct of_phandle_args *args = data;
+       struct of_phandle_args parent_args;
+       irq_hw_number_t hwirq;
+       int i;
+
+       /* Not GIC compliant */
+       if (args->args_count != 3)
+               return -EINVAL;
+
+       /* No PPI should point to this domain */
+       if (args->args[0] != 0)
+               return -EINVAL;
+
+       /* Can't deal with this */
+       hwirq = args->args[1];
+       if (hwirq >= GPC_MAX_IRQS)
+               return -EINVAL;
+
+       for (i = 0; i < nr_irqs; i++) {
+               irq_domain_set_hwirq_and_chip(domain, irq + i, hwirq + i,
+                               &gpcv2_irqchip_data_chip, domain->host_data);
+       }
+
+       parent_args = *args;
+       parent_args.np = domain->parent->of_node;
+       return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args);
+}
+
+static struct irq_domain_ops gpcv2_irqchip_data_domain_ops = {
+       .xlate  = imx_gpcv2_domain_xlate,
+       .alloc  = imx_gpcv2_domain_alloc,
+       .free   = irq_domain_free_irqs_common,
+};
+
+static int __init imx_gpcv2_irqchip_init(struct device_node *node,
+                              struct device_node *parent)
+{
+       struct irq_domain *parent_domain, *domain;
+       struct gpcv2_irqchip_data *cd;
+       int i;
+
+       if (!parent) {
+               pr_err("%s: no parent, giving up\n", node->full_name);
+               return -ENODEV;
+       }
+
+       parent_domain = irq_find_host(parent);
+       if (!parent_domain) {
+               pr_err("%s: unable to get parent domain\n", node->full_name);
+               return -ENXIO;
+       }
+
+       cd = kzalloc(sizeof(struct gpcv2_irqchip_data), GFP_KERNEL);
+       if (!cd) {
+               pr_err("kzalloc failed!\n");
+               return -ENOMEM;
+       }
+
+       cd->gpc_base = of_iomap(node, 0);
+       if (!cd->gpc_base) {
+               pr_err("fsl-gpcv2: unable to map gpc registers\n");
+               kfree(cd);
+               return -ENOMEM;
+       }
+
+       domain = irq_domain_add_hierarchy(parent_domain, 0, GPC_MAX_IRQS,
+                               node, &gpcv2_irqchip_data_domain_ops, cd);
+       if (!domain) {
+               iounmap(cd->gpc_base);
+               kfree(cd);
+               return -ENOMEM;
+       }
+       irq_set_default_host(domain);
+
+       /* Initially mask all interrupts */
+       for (i = 0; i < IMR_NUM; i++) {
+               writel_relaxed(~0, cd->gpc_base + GPC_IMR1_CORE0 + i * 4);
+               writel_relaxed(~0, cd->gpc_base + GPC_IMR1_CORE1 + i * 4);
+               cd->wakeup_sources[i] = ~0;
+       }
+
+       /* Let CORE0 as the default CPU to wake up by GPC */
+       cd->cpu2wakeup = GPC_IMR1_CORE0;
+
+       /*
+        * Due to hardware design failure, need to make sure GPR
+        * interrupt(#32) is unmasked during RUN mode to avoid entering
+        * DSM by mistake.
+        */
+       writel_relaxed(~0x1, cd->gpc_base + cd->cpu2wakeup);
+
+       imx_gpcv2_instance = cd;
+       register_syscore_ops(&imx_gpcv2_syscore_ops);
+
+       return 0;
+}
+
+IRQCHIP_DECLARE(imx_gpcv2, "fsl,imx7d-gpc", imx_gpcv2_irqchip_init);
index 005de3f932ae8807a2a7af66a40c2c421e425996..fc5953dea509af10b38abf783dac4fbd83efdaaa 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/irqchip.h>
 #include <linux/irqchip/ingenic.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -28,8 +29,6 @@
 #include <asm/io.h>
 #include <asm/mach-jz4740/irq.h>
 
-#include "irqchip.h"
-
 struct ingenic_intc_data {
        void __iomem *base;
        unsigned num_chips;
index 81e3cf5b9a1faa07ddbb1ab52b714aa08e0a4e09..c1517267b5dbcf48aac50c9930db4c54cec762ae 100644 (file)
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
-#include "irqchip.h"
-
 
 /* The source ID bits start from 4 to 31 (total 28 bits)*/
 #define BIT_OFS                        4
@@ -84,8 +83,9 @@ static void keystone_irq_ack(struct irq_data *d)
        /* nothing to do here */
 }
 
-static void keystone_irq_handler(unsigned irq, struct irq_desc *desc)
+static void keystone_irq_handler(unsigned __irq, struct irq_desc *desc)
 {
+       unsigned int irq = irq_desc_get_irq(desc);
        struct keystone_irq_device *kirq = irq_desc_get_handler_data(desc);
        unsigned long pending;
        int src, virq;
index 2cb474ad8809faa2fadaf5b08a7b06b087e73794..5f4c52928d1671b99cfc759552562bd5b8d09691 100644 (file)
@@ -404,7 +404,6 @@ static int meta_intc_irq_set_type(struct irq_data *data, unsigned int flow_type)
 #ifdef CONFIG_METAG_SUSPEND_MEM
        struct meta_intc_priv *priv = &meta_intc_priv;
 #endif
-       unsigned int irq = data->irq;
        irq_hw_number_t hw = data->hwirq;
        unsigned int bit = 1 << meta_intc_offset(hw);
        void __iomem *level_addr = meta_intc_level_addr(hw);
@@ -413,11 +412,11 @@ static int meta_intc_irq_set_type(struct irq_data *data, unsigned int flow_type)
 
        /* update the chip/handler */
        if (flow_type & IRQ_TYPE_LEVEL_MASK)
-               __irq_set_chip_handler_name_locked(irq, &meta_intc_level_chip,
-                                                  handle_level_irq, NULL);
+               irq_set_chip_handler_name_locked(data, &meta_intc_level_chip,
+                                                handle_level_irq, NULL);
        else
-               __irq_set_chip_handler_name_locked(irq, &meta_intc_edge_chip,
-                                                  handle_edge_irq, NULL);
+               irq_set_chip_handler_name_locked(data, &meta_intc_edge_chip,
+                                                handle_edge_irq, NULL);
 
        /* and clear/set the bit in HWLEVELEXT */
        __global_lock2(flags);
index c16c186d97d35f4246fa2acbd17942789922d6d7..3d23ce3edb5cccc8b50073af72633e0b3b3ed11f 100644 (file)
@@ -286,8 +286,7 @@ static void metag_internal_irq_init_cpu(struct metag_internal_irq_priv *priv,
        int irq = tbisig_map(signum);
 
        /* Register the multiplexed IRQ handler */
-       irq_set_handler_data(irq, priv);
-       irq_set_chained_handler(irq, metag_internal_irq_demux);
+       irq_set_chained_handler_and_data(irq, metag_internal_irq_demux, priv);
        irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);
 }
 
index a43c41988009c644400a164b7e893e2621d54568..8c504f562e9dcdb5c5fd2a9b88ab591dd763782c 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 
 #include <asm/irq_cpu.h>
@@ -38,8 +39,6 @@
 #include <asm/mipsmtregs.h>
 #include <asm/setup.h>
 
-#include "irqchip.h"
-
 static inline void unmask_mips_irq(struct irq_data *d)
 {
        set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
index ff4be0515a0dc7dbb206ae0a84968f922817101e..dae5914578834050751b3fe2283046add588ea09 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/irqchip/mips-gic.h>
 #include <linux/of_address.h>
 #include <linux/sched.h>
@@ -22,8 +23,6 @@
 
 #include <dt-bindings/interrupt-controller/mips-gic.h>
 
-#include "irqchip.h"
-
 unsigned int gic_present;
 
 struct gic_pcpu_mask {
@@ -358,15 +357,12 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
                break;
        }
 
-       if (is_edge) {
-               __irq_set_chip_handler_name_locked(d->irq,
-                                                  &gic_edge_irq_controller,
-                                                  handle_edge_irq, NULL);
-       } else {
-               __irq_set_chip_handler_name_locked(d->irq,
-                                                  &gic_level_irq_controller,
-                                                  handle_level_irq, NULL);
-       }
+       if (is_edge)
+               irq_set_chip_handler_name_locked(d, &gic_edge_irq_controller,
+                                                handle_edge_irq, NULL);
+       else
+               irq_set_chip_handler_name_locked(d, &gic_level_irq_controller,
+                                                handle_level_irq, NULL);
        spin_unlock_irqrestore(&gic_lock, flags);
 
        return 0;
@@ -396,7 +392,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
                clear_bit(irq, pcpu_masks[i].pcpu_mask);
        set_bit(irq, pcpu_masks[cpumask_first(&tmp)].pcpu_mask);
 
-       cpumask_copy(d->affinity, cpumask);
+       cpumask_copy(irq_data_get_affinity_mask(d), cpumask);
        spin_unlock_irqrestore(&gic_lock, flags);
 
        return IRQ_SET_MASK_OK_NOCOPY;
index c0da57bdb89dfcf0c0e2224180715989a88086a6..781ed6e71dbb3d1343440229b725db4e5eca3e1b 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
@@ -24,8 +25,6 @@
 #include <asm/exception.h>
 #include <asm/hardirq.h>
 
-#include "irqchip.h"
-
 #define MAX_ICU_NR             16
 
 #define PJ1_INT_SEL            0x10c
@@ -130,8 +129,9 @@ struct irq_chip icu_irq_chip = {
        .irq_unmask     = icu_unmask_irq,
 };
 
-static void icu_mux_irq_demux(unsigned int irq, struct irq_desc *desc)
+static void icu_mux_irq_demux(unsigned int __irq, struct irq_desc *desc)
 {
+       unsigned int irq = irq_desc_get_irq(desc);
        struct irq_domain *domain;
        struct icu_chip_data *data;
        int i;
index 00b3cc908f762d58fd92720d73fd2e3f1cb28e3f..a24b06a1718b6fd7e6bd90f4269d47d14722a225 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -19,8 +20,6 @@
 
 #include <asm/exception.h>
 
-#include "irqchip.h"
-
 #define IRQ_SOURCE_REG         0
 #define IRQ_MASK_REG           0x04
 #define IRQ_CLEAR_REG          0x08
index 15c13039bba211b53a309d05ba4fd0f333364065..c8753da4c156ee9e2fa1b3b5ddfde63561733d30 100644 (file)
@@ -13,6 +13,7 @@
  */
 
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
@@ -21,8 +22,6 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 
-#include "irqchip.h"
-
 struct mtk_sysirq_chip_data {
        spinlock_t lock;
        void __iomem *intpol_base;
index 04bf97b289cf4a10a6c4d4344247e6d26e4a22f5..1faf812f3dc8e4a8da4e8d9a2b4f214216705041 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -27,8 +28,6 @@
 #include <linux/stmp_device.h>
 #include <asm/exception.h>
 
-#include "irqchip.h"
-
 #define HW_ICOLL_VECTOR                                0x0000
 #define HW_ICOLL_LEVELACK                      0x0010
 #define HW_ICOLL_CTRL                          0x0020
index 5fac9100f6cbee9f7abf144eb4dcb9efeb3aaee0..a878b8d03868823a222af0ee4d0f296793673a7d 100644 (file)
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 
 #include <asm/v7m.h>
 #include <asm/exception.h>
 
-#include "irqchip.h"
-
 #define NVIC_ISER              0x000
 #define NVIC_ICER              0x080
 #define NVIC_IPR               0x300
index a569c6dbd1d16ee92bffabb6e45f9a6a2cbed4be..8587d0f8d8c03300e6ece2da0f252b767d31f781 100644 (file)
 #include <linux/io.h>
 
 #include <asm/exception.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 
-#include "irqchip.h"
-
 /* Define these here for now until we drop all board-files */
 #define OMAP24XX_IC_BASE       0x480fe000
 #define OMAP34XX_IC_BASE       0x48200000
@@ -331,37 +330,12 @@ static int __init omap_init_irq(u32 base, struct device_node *node)
 static asmlinkage void __exception_irq_entry
 omap_intc_handle_irq(struct pt_regs *regs)
 {
-       u32 irqnr = 0;
-       int handled_irq = 0;
-       int i;
-
-       do {
-               for (i = 0; i < omap_nr_pending; i++) {
-                       irqnr = intc_readl(INTC_PENDING_IRQ0 + (0x20 * i));
-                       if (irqnr)
-                               goto out;
-               }
-
-out:
-               if (!irqnr)
-                       break;
+       u32 irqnr;
 
-               irqnr = intc_readl(INTC_SIR);
-               irqnr &= ACTIVEIRQ_MASK;
-
-               if (irqnr) {
-                       handle_domain_irq(domain, irqnr, regs);
-                       handled_irq = 1;
-               }
-       } while (irqnr);
-
-       /*
-        * If an irq is masked or deasserted while active, we will
-        * keep ending up here with no irq handled. So remove it from
-        * the INTC with an ack.
-        */
-       if (!handled_irq)
-               omap_ack_irq(NULL);
+       irqnr = intc_readl(INTC_SIR);
+       irqnr &= ACTIVEIRQ_MASK;
+       WARN_ONCE(!irqnr, "Spurious IRQ ?\n");
+       handle_domain_irq(domain, irqnr, regs);
 }
 
 void __init omap3_init_irq(void)
index e93d079fe069eb11a55f6ff422063ec19620a826..6a9a3e79218b0fc623f99ad8f347362a92319300 100644 (file)
@@ -9,12 +9,11 @@
  */
 
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 
-#include "irqchip.h"
-
 /* OR1K PIC implementation */
 
 struct or1k_pic_dev {
index ad0c0f6f1d65ac6b4cf7d8db80f635cf698a9875..5ea999a724b5db93ade94d5a8daa57f7b19da55b 100644 (file)
 
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <asm/exception.h>
 #include <asm/mach/irq.h>
 
-#include "irqchip.h"
-
 /*
  * Orion SoC main interrupt controller
  */
@@ -109,7 +108,7 @@ IRQCHIP_DECLARE(orion_intc, "marvell,orion-intc", orion_irq_init);
 
 static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
-       struct irq_domain *d = irq_get_handler_data(irq);
+       struct irq_domain *d = irq_desc_get_handler_data(desc);
 
        struct irq_chip_generic *gc = irq_get_domain_generic_chip(d, 0);
        u32 stat = readl_relaxed(gc->reg_base + ORION_BRIDGE_IRQ_CAUSE) &
@@ -198,8 +197,8 @@ static int __init orion_bridge_irq_init(struct device_node *np,
        writel(0, gc->reg_base + ORION_BRIDGE_IRQ_MASK);
        writel(0, gc->reg_base + ORION_BRIDGE_IRQ_CAUSE);
 
-       irq_set_handler_data(irq, domain);
-       irq_set_chained_handler(irq, orion_bridge_irq_handler);
+       irq_set_chained_handler_and_data(irq, orion_bridge_irq_handler,
+                                        domain);
 
        return 0;
 }
index 1870e6bd3dd9ef3c21170bfc9ae0aa0fec541b12..6fd30d5ee14dddcd7a35169632a26d2156c2e34c 100644 (file)
@@ -11,8 +11,6 @@
 #include <linux/of_irq.h>
 #include <asm/io.h>
 
-#include "irqchip.h"
-
 static const char ipr_bit[] = {
         7,  6,  5,  5,
         4,  4,  4,  4,  3,  3,  3,  3,
index 64425f4de7d9542468708bd5bb7b5a2aef97dcfa..8098ead1eb22aa8600c8a6b25bf3c3eb8f0c486d 100644 (file)
@@ -5,10 +5,10 @@
  */
 
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <asm/io.h>
-#include "irqchip.h"
 
 static void *intc_baseaddr;
 #define IPRA ((unsigned long)intc_baseaddr)
index 778bd076aeea759a12fcfc49da0df952ffbc352a..2aa3add711a6612af6c1653c976a043e743d9058 100644 (file)
@@ -53,7 +53,6 @@
 struct irqc_irq {
        int hw_irq;
        int requested_irq;
-       int domain_irq;
        struct irqc_priv *p;
 };
 
@@ -70,8 +69,8 @@ struct irqc_priv {
 
 static void irqc_dbg(struct irqc_irq *i, char *str)
 {
-       dev_dbg(&i->p->pdev->dev, "%s (%d:%d:%d)\n",
-               str, i->requested_irq, i->hw_irq, i->domain_irq);
+       dev_dbg(&i->p->pdev->dev, "%s (%d:%d)\n",
+               str, i->requested_irq, i->hw_irq);
 }
 
 static void irqc_irq_enable(struct irq_data *d)
@@ -145,7 +144,7 @@ static irqreturn_t irqc_irq_handler(int irq, void *dev_id)
        if (ioread32(p->iomem + DETECT_STATUS) & bit) {
                iowrite32(bit, p->iomem + DETECT_STATUS);
                irqc_dbg(i, "demux2");
-               generic_handle_irq(i->domain_irq);
+               generic_handle_irq(irq_find_mapping(p->irq_domain, i->hw_irq));
                return IRQ_HANDLED;
        }
        return IRQ_NONE;
@@ -156,13 +155,9 @@ static int irqc_irq_domain_map(struct irq_domain *h, unsigned int virq,
 {
        struct irqc_priv *p = h->host_data;
 
-       p->irq[hw].domain_irq = virq;
-       p->irq[hw].hw_irq = hw;
-
        irqc_dbg(&p->irq[hw], "map");
        irq_set_chip_data(virq, h->host_data);
        irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
-       set_irq_flags(virq, IRQF_VALID); /* kill me now */
        return 0;
 }
 
@@ -215,6 +210,7 @@ static int irqc_probe(struct platform_device *pdev)
                        break;
 
                p->irq[k].p = p;
+               p->irq[k].hw_irq = k;
                p->irq[k].requested_irq = irq->start;
        }
 
@@ -243,8 +239,8 @@ static int irqc_probe(struct platform_device *pdev)
        irq_chip->irq_set_wake = irqc_irq_set_wake;
        irq_chip->flags = IRQCHIP_MASK_ON_SUSPEND;
 
-       p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
-                                             p->number_of_irqs, 0,
+       p->irq_domain = irq_domain_add_linear(pdev->dev.of_node,
+                                             p->number_of_irqs,
                                              &irqc_irq_domain_ops, p);
        if (!p->irq_domain) {
                ret = -ENXIO;
index e96717f45ea15148adb46aefe5f74428a46b97a9..506d9f20ca51950e481148c4b3d91c49e1766173 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/ioport.h>
 #include <linux/device.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
@@ -40,8 +41,6 @@
 #include <plat/regs-irqtype.h>
 #include <plat/pm.h>
 
-#include "irqchip.h"
-
 #define S3C_IRQTYPE_NONE       0
 #define S3C_IRQTYPE_EINT       1
 #define S3C_IRQTYPE_EDGE       2
@@ -299,16 +298,14 @@ static struct irq_chip s3c_irq_eint0t4 = {
        .irq_set_type   = s3c_irqext0_type,
 };
 
-static void s3c_irq_demux(unsigned int irq, struct irq_desc *desc)
+static void s3c_irq_demux(unsigned int __irq, struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct s3c_irq_data *irq_data = irq_desc_get_chip_data(desc);
        struct s3c_irq_intc *intc = irq_data->intc;
        struct s3c_irq_intc *sub_intc = irq_data->sub_intc;
-       unsigned long src;
-       unsigned long msk;
-       unsigned int n;
-       unsigned int offset;
+       unsigned int n, offset, irq;
+       unsigned long src, msk;
 
        /* we're using individual domains for the non-dt case
         * and one big domain for the dt case where the subintc
index a469355df352723cc415753c4e4ec7111c51d3ff..10cb21b9ba3d6779c1f0a593f3a715ef6857cc89 100644 (file)
 #include <linux/irq.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 #include <linux/syscore_ops.h>
 #include <asm/mach/irq.h>
 #include <asm/exception.h>
-#include "irqchip.h"
 
-#define SIRFSOC_INT_RISC_MASK0          0x0018
-#define SIRFSOC_INT_RISC_MASK1          0x001C
-#define SIRFSOC_INT_RISC_LEVEL0         0x0020
-#define SIRFSOC_INT_RISC_LEVEL1         0x0024
+#define SIRFSOC_INT_RISC_MASK0         0x0018
+#define SIRFSOC_INT_RISC_MASK1         0x001C
+#define SIRFSOC_INT_RISC_LEVEL0                0x0020
+#define SIRFSOC_INT_RISC_LEVEL1                0x0024
 #define SIRFSOC_INIT_IRQ_ID            0x0038
+#define SIRFSOC_INT_BASE_OFFSET                0x0004
 
 #define SIRFSOC_NUM_IRQS               64
+#define SIRFSOC_NUM_BANKS              (SIRFSOC_NUM_IRQS / 32)
 
 static struct irq_domain *sirfsoc_irqdomain;
 
-static __init void
-sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
+static __init void sirfsoc_alloc_gc(void __iomem *base)
 {
-       struct irq_chip_generic *gc;
-       struct irq_chip_type *ct;
-       int ret;
        unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
        unsigned int set = IRQ_LEVEL;
-
-       ret = irq_alloc_domain_generic_chips(sirfsoc_irqdomain, num, 1, "irq_sirfsoc",
-               handle_level_irq, clr, set, IRQ_GC_INIT_MASK_CACHE);
-
-       gc = irq_get_domain_generic_chip(sirfsoc_irqdomain, irq_start);
-       gc->reg_base = base;
-       ct = gc->chip_types;
-       ct->chip.irq_mask = irq_gc_mask_clr_bit;
-       ct->chip.irq_unmask = irq_gc_mask_set_bit;
-       ct->regs.mask = SIRFSOC_INT_RISC_MASK0;
+       struct irq_chip_generic *gc;
+       struct irq_chip_type *ct;
+       int i;
+
+       irq_alloc_domain_generic_chips(sirfsoc_irqdomain, 32, 1, "irq_sirfsoc",
+                                      handle_level_irq, clr, set,
+                                      IRQ_GC_INIT_MASK_CACHE);
+
+       for (i = 0; i < SIRFSOC_NUM_BANKS; i++) {
+               gc = irq_get_domain_generic_chip(sirfsoc_irqdomain, i * 32);
+               gc->reg_base = base + i * SIRFSOC_INT_BASE_OFFSET;
+               ct = gc->chip_types;
+               ct->chip.irq_mask = irq_gc_mask_clr_bit;
+               ct->chip.irq_unmask = irq_gc_mask_set_bit;
+               ct->regs.mask = SIRFSOC_INT_RISC_MASK0;
+       }
 }
 
 static void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs)
@@ -64,10 +68,8 @@ static int __init sirfsoc_irq_init(struct device_node *np,
                panic("unable to map intc cpu registers\n");
 
        sirfsoc_irqdomain = irq_domain_add_linear(np, SIRFSOC_NUM_IRQS,
-               &irq_generic_chip_ops, base);
-
-       sirfsoc_alloc_gc(base, 0, 32);
-       sirfsoc_alloc_gc(base + 4, 32, SIRFSOC_NUM_IRQS - 32);
+                                                 &irq_generic_chip_ops, base);
+       sirfsoc_alloc_gc(base);
 
        writel_relaxed(0, base + SIRFSOC_INT_RISC_LEVEL0);
        writel_relaxed(0, base + SIRFSOC_INT_RISC_LEVEL1);
index 83d6aa6464ee0b688c3b777c5eda519f0091af4e..4ad3e7c69aa779e2f53b039fb1138807ce9f1ae2 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -23,8 +24,6 @@
 #include <asm/exception.h>
 #include <asm/mach/irq.h>
 
-#include "irqchip.h"
-
 #define SUN4I_IRQ_VECTOR_REG           0x00
 #define SUN4I_IRQ_PROTECTION_REG       0x08
 #define SUN4I_IRQ_NMI_CTRL_REG         0x0c
index 6b2b582433bde95062e85d17403e4a505c5a4ef9..772a82cacbf7a7b2cbb37b263327f86848413d88 100644 (file)
@@ -17,8 +17,8 @@
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
+#include <linux/irqchip.h>
 #include <linux/irqchip/chained_irq.h>
-#include "irqchip.h"
 
 #define SUNXI_NMI_SRC_TYPE_MASK        0x00000003
 
@@ -61,7 +61,7 @@ static inline u32 sunxi_sc_nmi_read(struct irq_chip_generic *gc, u32 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);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int virq = irq_find_mapping(domain, 0);
 
        chained_irq_enter(chip, desc);
@@ -182,8 +182,7 @@ static int __init sunxi_sc_nmi_irq_init(struct device_node *node,
        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);
+       irq_set_chained_handler_and_data(irq, sunxi_sc_nmi_handle_irq, domain);
 
        return 0;
 
index accc20036a3c6580eb7320554f4603306c72b1ac..3318296613669c1c489f848ac36e399760a0d312 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/irqdomain.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/bitops.h>
-#include "irqchip.h"
 
 #define AB_IRQCTL_INT_ENABLE   0x00
 #define AB_IRQCTL_INT_STATUS   0x04
@@ -97,9 +97,10 @@ static int tb10x_irq_set_type(struct irq_data *data, unsigned int flow_type)
        return IRQ_SET_MASK_OK;
 }
 
-static void tb10x_irq_cascade(unsigned int irq, struct irq_desc *desc)
+static void tb10x_irq_cascade(unsigned int __irq, struct irq_desc *desc)
 {
        struct irq_domain *domain = irq_desc_get_handler_data(desc);
+       unsigned int irq = irq_desc_get_irq(desc);
 
        generic_handle_irq(irq_find_mapping(domain, irq));
 }
@@ -173,8 +174,8 @@ static int __init of_tb10x_init_irq(struct device_node *ictl,
        for (i = 0; i < nrirqs; i++) {
                unsigned int irq = irq_of_parse_and_map(ictl, i);
 
-               irq_set_handler_data(irq, domain);
-               irq_set_chained_handler(irq, tb10x_irq_cascade);
+               irq_set_chained_handler_and_data(irq, tb10x_irq_cascade,
+                                                domain);
        }
 
        ab_irqctl_writereg(gc, AB_IRQCTL_INT_ENABLE, 0);
index f67bbd80433e8c90527a9b911a2656987b800b96..2fd89eb88f3a29bc716ec1daf76ad4085e6a743d 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
@@ -31,8 +32,6 @@
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
-#include "irqchip.h"
-
 #define ICTLR_CPU_IEP_VFIQ     0x08
 #define ICTLR_CPU_IEP_FIR      0x14
 #define ICTLR_CPU_IEP_FIR_SET  0x18
index 888111b76ea0dd525c44ab46f68f96206be8e05d..16123f688768f24585653171b87de1785b764400 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/bitops.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/irqchip.h>
 #include <linux/irqchip/versatile-fpga.h>
 #include <linux/irqdomain.h>
 #include <linux/module.h>
@@ -14,8 +15,6 @@
 #include <asm/exception.h>
 #include <asm/mach/irq.h>
 
-#include "irqchip.h"
-
 #define IRQ_STATUS             0x00
 #define IRQ_RAW_STATUS         0x04
 #define IRQ_ENABLE_SET         0x08
@@ -66,9 +65,10 @@ static void fpga_irq_unmask(struct irq_data *d)
        writel(mask, f->base + IRQ_ENABLE_SET);
 }
 
-static void fpga_irq_handle(unsigned int irq, struct irq_desc *desc)
+static void fpga_irq_handle(unsigned int __irq, struct irq_desc *desc)
 {
        struct fpga_irq_data *f = irq_desc_get_handler_data(desc);
+       unsigned int irq = irq_desc_get_irq(desc);
        u32 status = readl(f->base + IRQ_STATUS);
 
        if (status == 0) {
@@ -156,8 +156,8 @@ void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start,
        f->valid = valid;
 
        if (parent_irq != -1) {
-               irq_set_handler_data(parent_irq, f);
-               irq_set_chained_handler(parent_irq, fpga_irq_handle);
+               irq_set_chained_handler_and_data(parent_irq, fpga_irq_handle,
+                                                f);
        }
 
        /* This will also allocate irq descriptors */
index f5c01cbcc73ac1376627cf31aa227a9cf5c25179..2c22558864012efe6425ab1f058ea0e07a9f0728 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/cpu_pm.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 #include <linux/mfd/syscon.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -34,8 +35,6 @@
 #include <linux/slab.h>
 #include <linux/regmap.h>
 
-#include "irqchip.h"
-
 #define MSCM_CPxNUM            0x4
 
 #define MSCM_IRSPRC(n)         (0x80 + 2 * (n))
index d4ce331ea4a08eadbd447e61486eff0d124d842c..03846dff42123c96079489f998ed18e7623ff576 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/list.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/irqdomain.h>
 #include <linux/of.h>
@@ -37,8 +38,6 @@
 #include <asm/exception.h>
 #include <asm/irq.h>
 
-#include "irqchip.h"
-
 #define VIC_IRQ_STATUS                 0x00
 #define VIC_FIQ_STATUS                 0x04
 #define VIC_INT_SELECT                 0x0c    /* 1 = FIQ, 0 = IRQ */
@@ -297,8 +296,8 @@ static void __init vic_register(void __iomem *base, unsigned int parent_irq,
        vic_id++;
 
        if (parent_irq) {
-               irq_set_handler_data(parent_irq, v);
-               irq_set_chained_handler(parent_irq, vic_handle_irq_cascaded);
+               irq_set_chained_handler_and_data(parent_irq,
+                                                vic_handle_irq_cascaded, v);
        }
 
        v->domain = irq_domain_add_simple(node, fls(valid_sources), irq,
index 0b297009b85662888fbe29af6dd18b5bd45b5151..8371d9978d31d9db5550ed1cdbf5cb28936b4fbd 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
@@ -39,8 +40,6 @@
 #include <asm/exception.h>
 #include <asm/mach/irq.h>
 
-#include "irqchip.h"
-
 #define VT8500_ICPC_IRQ                0x20
 #define VT8500_ICPC_FIQ                0x24
 #define VT8500_ICDC            0x40            /* Destination Control 64*u32 */
@@ -127,15 +126,15 @@ static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type)
                return -EINVAL;
        case IRQF_TRIGGER_HIGH:
                dctr |= VT8500_TRIGGER_HIGH;
-               __irq_set_handler_locked(d->irq, handle_level_irq);
+               irq_set_handler_locked(d, handle_level_irq);
                break;
        case IRQF_TRIGGER_FALLING:
                dctr |= VT8500_TRIGGER_FALLING;
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
+               irq_set_handler_locked(d, handle_edge_irq);
                break;
        case IRQF_TRIGGER_RISING:
                dctr |= VT8500_TRIGGER_RISING;
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
+               irq_set_handler_locked(d, handle_edge_irq);
                break;
        }
        writeb(dctr, base + VT8500_ICDC + d->hwirq);
index e1c2f963289374b38a3a7bce93c930cb6565b376..bb3ac5fe5846b9e2d27b71bea9bf0bff9bcb8e2d 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/irqdomain.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/of.h>
 
 #include <asm/mxregs.h>
 
-#include "irqchip.h"
-
 #define HW_IRQ_IPI_COUNT 2
 #define HW_IRQ_MX_BASE 2
 #define HW_IRQ_EXTERN_BASE 3
index 7d71126d1ce5596668176ea7b03b541292ded9d1..472ae17709647201606a10344fd741d77e81e988 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/irqdomain.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/of.h>
 
-#include "irqchip.h"
-
 unsigned int cached_irq_mask;
 
 /*
index e4ef74ed454a8d6826947924523498191efb474a..4c48fa88a03d9b54651276cfe95a8fc2d5e287af 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -18,8 +19,6 @@
 #include <asm/mach/irq.h>
 #include <asm/exception.h>
 
-#include "irqchip.h"
-
 #define IO_STATUS      0x000
 #define IO_RAW_STATUS  0x004
 #define IO_ENABLE      0x008
diff --git a/drivers/irqchip/irqchip.h b/drivers/irqchip/irqchip.h
deleted file mode 100644 (file)
index 0f67ae3..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright (C) 2012 Thomas Petazzoni
- *
- * Thomas Petazzoni <thomas.petazzoni@free-electrons.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/irqchip.h>
index acb721b31bcfc4972921ff4c7f6afe1e1c8026cc..4cbd9c5dc1e6fc1e65810c28c61c3a780942a8a1 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/spinlock.h>
 
-#include "irqchip.h"
-
 /*
  * struct spear_shirq: shared irq structure
  *
@@ -183,9 +182,9 @@ static struct spear_shirq *spear320_shirq_blocks[] = {
        &spear320_shirq_intrcomm_ras,
 };
 
-static void shirq_handler(unsigned irq, struct irq_desc *desc)
+static void shirq_handler(unsigned __irq, struct irq_desc *desc)
 {
-       struct spear_shirq *shirq = irq_get_handler_data(irq);
+       struct spear_shirq *shirq = irq_desc_get_handler_data(desc);
        u32 pend;
 
        pend = readl(shirq->base + shirq->status_reg) & shirq->mask;
index 3cf7a01f557f4fbe924479e379d599d03016f07f..2956d725649f25ffd7d115097a36a711867b052a 100644 (file)
@@ -18,6 +18,7 @@
  * driver.
  */
 
+#include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/list.h>
 #include <linux/module.h>
@@ -576,3 +577,23 @@ err:
                kfree(desc);
        }
 }
+
+/**
+ * of_msi_configure - Set the msi_domain field of a device
+ * @dev: device structure to associate with an MSI irq domain
+ * @np: device node for that device
+ */
+void of_msi_configure(struct device *dev, struct device_node *np)
+{
+       struct device_node *msi_np;
+       struct irq_domain *d;
+
+       msi_np = of_parse_phandle(np, "msi-parent", 0);
+       if (!msi_np)
+               return;
+
+       d = irq_find_matching_host(msi_np, DOMAIN_BUS_PLATFORM_MSI);
+       if (!d)
+               d = irq_find_host(msi_np);
+       dev_set_msi_domain(dev, d);
+}
index ddf8e42c9367d36132a2cd068fc441e9e29eea87..8a002d6151f2662851e22e240b5eb9957da974ee 100644 (file)
@@ -184,6 +184,7 @@ static struct platform_device *of_platform_device_create_pdata(
        dev->dev.bus = &platform_bus_type;
        dev->dev.platform_data = platform_data;
        of_dma_configure(&dev->dev, dev->dev.of_node);
+       of_msi_configure(&dev->dev, dev->dev.of_node);
 
        if (of_device_add(dev) != 0) {
                of_dma_deconfigure(&dev->dev);
index 9ee04b4b68bf39569acd6dd360c62a6cb4e4b76e..144c77dfe4b195864f37165cee0a71506e723b87 100644 (file)
@@ -691,7 +691,7 @@ static int iosapic_set_affinity_irq(struct irq_data *d,
        if (dest_cpu < 0)
                return -1;
 
-       cpumask_copy(d->affinity, cpumask_of(dest_cpu));
+       cpumask_copy(irq_data_get_affinity_mask(d), cpumask_of(dest_cpu));
        vi->txn_addr = txn_affinity_addr(d->irq, dest_cpu);
 
        spin_lock_irqsave(&iosapic_lock, flags);
index f1d0749ebbf066d99e02c73a8c609aaf55b4baa4..e71da991949b1d598444a81dd775b3117c1c4744 100644 (file)
@@ -104,14 +104,13 @@ static void ks_dw_pcie_msi_irq_ack(struct irq_data *d)
 {
        u32 offset, reg_offset, bit_pos;
        struct keystone_pcie *ks_pcie;
-       unsigned int irq = d->irq;
        struct msi_desc *msi;
        struct pcie_port *pp;
 
-       msi = irq_get_msi_desc(irq);
-       pp = sys_to_pcie(msi->dev->bus->sysdata);
+       msi = irq_data_get_msi_desc(d);
+       pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
        ks_pcie = to_keystone_pcie(pp);
-       offset = irq - irq_linear_revmap(pp->irq_domain, 0);
+       offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
        update_reg_offset_bit_pos(offset, &reg_offset, &bit_pos);
 
        writel(BIT(bit_pos),
@@ -142,15 +141,14 @@ void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
 static void ks_dw_pcie_msi_irq_mask(struct irq_data *d)
 {
        struct keystone_pcie *ks_pcie;
-       unsigned int irq = d->irq;
        struct msi_desc *msi;
        struct pcie_port *pp;
        u32 offset;
 
-       msi = irq_get_msi_desc(irq);
-       pp = sys_to_pcie(msi->dev->bus->sysdata);
+       msi = irq_data_get_msi_desc(d);
+       pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
        ks_pcie = to_keystone_pcie(pp);
-       offset = irq - irq_linear_revmap(pp->irq_domain, 0);
+       offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
 
        /* Mask the end point if PVM implemented */
        if (IS_ENABLED(CONFIG_PCI_MSI)) {
@@ -164,15 +162,14 @@ static void ks_dw_pcie_msi_irq_mask(struct irq_data *d)
 static void ks_dw_pcie_msi_irq_unmask(struct irq_data *d)
 {
        struct keystone_pcie *ks_pcie;
-       unsigned int irq = d->irq;
        struct msi_desc *msi;
        struct pcie_port *pp;
        u32 offset;
 
-       msi = irq_get_msi_desc(irq);
-       pp = sys_to_pcie(msi->dev->bus->sysdata);
+       msi = irq_data_get_msi_desc(d);
+       pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
        ks_pcie = to_keystone_pcie(pp);
-       offset = irq - irq_linear_revmap(pp->irq_domain, 0);
+       offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
 
        /* Mask the end point if PVM implemented */
        if (IS_ENABLED(CONFIG_PCI_MSI)) {
index 734da589cdfb94b4312c3a8cd13dbe06c9c5604c..81253e70b1c5441b41544a58f682caa73f84dbc8 100644 (file)
@@ -110,8 +110,9 @@ static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie)
        return -EINVAL;
 }
 
-static void ks_pcie_msi_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void ks_pcie_msi_irq_handler(unsigned int __irq, struct irq_desc *desc)
 {
+       unsigned int irq = irq_desc_get_irq(desc);
        struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
        u32 offset = irq - ks_pcie->msi_host_irqs[0];
        struct pcie_port *pp = &ks_pcie->pp;
@@ -137,8 +138,10 @@ static void ks_pcie_msi_irq_handler(unsigned int irq, struct irq_desc *desc)
  * Traverse through pending legacy interrupts and invoke handler for each. Also
  * takes care of interrupt controller level mask/ack operation.
  */
-static void ks_pcie_legacy_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void ks_pcie_legacy_irq_handler(unsigned int __irq,
+                                      struct irq_desc *desc)
 {
+       unsigned int irq = irq_desc_get_irq(desc);
        struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
        struct pcie_port *pp = &ks_pcie->pp;
        u32 irq_offset = irq - ks_pcie->legacy_host_irqs[0];
@@ -212,9 +215,9 @@ static void ks_pcie_setup_interrupts(struct keystone_pcie *ks_pcie)
 
        /* Legacy IRQ */
        for (i = 0; i < ks_pcie->num_legacy_host_irqs; i++) {
-               irq_set_handler_data(ks_pcie->legacy_host_irqs[i], ks_pcie);
-               irq_set_chained_handler(ks_pcie->legacy_host_irqs[i],
-                                       ks_pcie_legacy_irq_handler);
+               irq_set_chained_handler_and_data(ks_pcie->legacy_host_irqs[i],
+                                                ks_pcie_legacy_irq_handler,
+                                                ks_pcie);
        }
        ks_dw_pcie_enable_legacy_irqs(ks_pcie);
 
index 398c9bfe13a92166f747d67fcc676eb42eadeec3..996327cfa1e1945e47449f1a33dd941ef143b372 100644 (file)
@@ -40,8 +40,8 @@ struct xgene_msi_group {
 
 struct xgene_msi {
        struct device_node      *node;
-       struct msi_controller   mchip;
-       struct irq_domain       *domain;
+       struct irq_domain       *inner_domain;
+       struct irq_domain       *msi_domain;
        u64                     msi_addr;
        void __iomem            *msi_regs;
        unsigned long           *bitmap;
@@ -251,17 +251,17 @@ static const struct irq_domain_ops msi_domain_ops = {
 
 static int xgene_allocate_domains(struct xgene_msi *msi)
 {
-       msi->domain = irq_domain_add_linear(NULL, NR_MSI_VEC,
-                                           &msi_domain_ops, msi);
-       if (!msi->domain)
+       msi->inner_domain = irq_domain_add_linear(NULL, NR_MSI_VEC,
+                                                 &msi_domain_ops, msi);
+       if (!msi->inner_domain)
                return -ENOMEM;
 
-       msi->mchip.domain = pci_msi_create_irq_domain(msi->mchip.of_node,
-                                                     &xgene_msi_domain_info,
-                                                     msi->domain);
+       msi->msi_domain = pci_msi_create_irq_domain(msi->node,
+                                                   &xgene_msi_domain_info,
+                                                   msi->inner_domain);
 
-       if (!msi->mchip.domain) {
-               irq_domain_remove(msi->domain);
+       if (!msi->msi_domain) {
+               irq_domain_remove(msi->inner_domain);
                return -ENOMEM;
        }
 
@@ -270,10 +270,10 @@ static int xgene_allocate_domains(struct xgene_msi *msi)
 
 static void xgene_free_domains(struct xgene_msi *msi)
 {
-       if (msi->mchip.domain)
-               irq_domain_remove(msi->mchip.domain);
-       if (msi->domain)
-               irq_domain_remove(msi->domain);
+       if (msi->msi_domain)
+               irq_domain_remove(msi->msi_domain);
+       if (msi->inner_domain)
+               irq_domain_remove(msi->inner_domain);
 }
 
 static int xgene_msi_init_allocator(struct xgene_msi *xgene_msi)
@@ -339,7 +339,7 @@ static void xgene_msi_isr(unsigned int irq, struct irq_desc *desc)
                         * CPU0
                         */
                        hw_irq = hwirq_to_canonical_hwirq(hw_irq);
-                       virq = irq_find_mapping(xgene_msi->domain, hw_irq);
+                       virq = irq_find_mapping(xgene_msi->inner_domain, hw_irq);
                        WARN_ON(!virq);
                        if (virq != 0)
                                generic_handle_irq(virq);
@@ -367,10 +367,8 @@ static int xgene_msi_remove(struct platform_device *pdev)
 
        for (i = 0; i < NR_HW_IRQS; i++) {
                virq = msi->msi_groups[i].gic_irq;
-               if (virq != 0) {
-                       irq_set_chained_handler(virq, NULL);
-                       irq_set_handler_data(virq, NULL);
-               }
+               if (virq != 0)
+                       irq_set_chained_handler_and_data(virq, NULL, NULL);
        }
        kfree(msi->msi_groups);
 
@@ -420,8 +418,8 @@ static int xgene_msi_hwirq_alloc(unsigned int cpu)
                }
 
                if (err) {
-                       irq_set_chained_handler(msi_group->gic_irq, NULL);
-                       irq_set_handler_data(msi_group->gic_irq, NULL);
+                       irq_set_chained_handler_and_data(msi_group->gic_irq,
+                                                        NULL, NULL);
                        return err;
                }
        }
@@ -440,8 +438,8 @@ static void xgene_msi_hwirq_free(unsigned int cpu)
                if (!msi_group->gic_irq)
                        continue;
 
-               irq_set_chained_handler(msi_group->gic_irq, NULL);
-               irq_set_handler_data(msi_group->gic_irq, NULL);
+               irq_set_chained_handler_and_data(msi_group->gic_irq, NULL,
+                                                NULL);
        }
 }
 
@@ -496,7 +494,7 @@ static int xgene_msi_probe(struct platform_device *pdev)
                goto error;
        }
        xgene_msi->msi_addr = res->start;
-
+       xgene_msi->node = pdev->dev.of_node;
        xgene_msi->num_cpus = num_possible_cpus();
 
        rc = xgene_msi_init_allocator(xgene_msi);
@@ -560,19 +558,10 @@ static int xgene_msi_probe(struct platform_device *pdev)
 
        cpu_notifier_register_done();
 
-       xgene_msi->mchip.of_node = pdev->dev.of_node;
-       rc = of_pci_msi_chip_add(&xgene_msi->mchip);
-       if (rc) {
-               dev_err(&pdev->dev, "failed to add MSI controller chip\n");
-               goto error_notifier;
-       }
-
        dev_info(&pdev->dev, "APM X-Gene PCIe MSI driver loaded\n");
 
        return 0;
 
-error_notifier:
-       unregister_hotcpu_notifier(&xgene_msi_cpu_notifier);
 error:
        xgene_msi_remove(pdev);
        return rc;
index 8d52ce73f84262a4835557d952ddd709693fcef3..52aa6e34002bc2543f20b8607efdab9e2a5a669a 100644 (file)
@@ -255,7 +255,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
 static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
 {
        int irq, pos0, i;
-       struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
+       struct pcie_port *pp = sys_to_pcie(msi_desc_to_pci_sysdata(desc));
 
        pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
                                       order_base_2(no_irqs));
@@ -326,8 +326,8 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
 static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
 {
        struct irq_data *data = irq_get_irq_data(irq);
-       struct msi_desc *msi = irq_data_get_msi(data);
-       struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
+       struct msi_desc *msi = irq_data_get_msi_desc(data);
+       struct pcie_port *pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
 
        clear_irq_range(pp, irq, 1, data->hwirq);
 }
index 1aeaa914bd3034e0b42823b6ba593ad047b917fc..3c7a0d580b1ed990d9978efc5927c3a8d2abc8af 100644 (file)
@@ -227,18 +227,16 @@ static struct pci_ops xilinx_pcie_ops = {
  */
 static void xilinx_pcie_destroy_msi(unsigned int irq)
 {
-       struct irq_desc *desc;
        struct msi_desc *msi;
        struct xilinx_pcie_port *port;
 
-       desc = irq_to_desc(irq);
-       msi = irq_desc_get_msi_desc(desc);
-       port = sys_to_pcie(msi->dev->bus->sysdata);
-
-       if (!test_bit(irq, msi_irq_in_use))
+       if (!test_bit(irq, msi_irq_in_use)) {
+               msi = irq_get_msi_desc(irq);
+               port = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
                dev_err(port->dev, "Trying to free unused MSI#%d\n", irq);
-       else
+       } else {
                clear_bit(irq, msi_irq_in_use);
+       }
 }
 
 /**
index 2f9b1c0d1f961cb961d3320011a5b40afa1bb917..d4497141d083a71d5d5206496fee58fbddc5cb13 100644 (file)
@@ -39,14 +39,13 @@ struct irq_domain * __weak arch_get_pci_msi_domain(struct pci_dev *dev)
 
 static struct irq_domain *pci_msi_get_domain(struct pci_dev *dev)
 {
-       struct irq_domain *domain = NULL;
+       struct irq_domain *domain;
 
-       if (dev->bus->msi)
-               domain = dev->bus->msi->domain;
-       if (!domain)
-               domain = arch_get_pci_msi_domain(dev);
+       domain = dev_get_msi_domain(&dev->dev);
+       if (domain)
+               return domain;
 
-       return domain;
+       return arch_get_pci_msi_domain(dev);
 }
 
 static int pci_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
@@ -116,7 +115,7 @@ int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
        if (type == PCI_CAP_ID_MSI && nvec > 1)
                return 1;
 
-       list_for_each_entry(entry, &dev->msi_list, list) {
+       for_each_pci_msi_entry(entry, dev) {
                ret = arch_setup_msi_irq(dev, entry);
                if (ret < 0)
                        return ret;
@@ -136,7 +135,7 @@ void default_teardown_msi_irqs(struct pci_dev *dev)
        int i;
        struct msi_desc *entry;
 
-       list_for_each_entry(entry, &dev->msi_list, list)
+       for_each_pci_msi_entry(entry, dev)
                if (entry->irq)
                        for (i = 0; i < entry->nvec_used; i++)
                                arch_teardown_msi_irq(entry->irq + i);
@@ -153,7 +152,7 @@ static void default_restore_msi_irq(struct pci_dev *dev, int irq)
 
        entry = NULL;
        if (dev->msix_enabled) {
-               list_for_each_entry(entry, &dev->msi_list, list) {
+               for_each_pci_msi_entry(entry, dev) {
                        if (irq == entry->irq)
                                break;
                }
@@ -193,7 +192,8 @@ u32 __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
 
        mask_bits &= ~mask;
        mask_bits |= flag;
-       pci_write_config_dword(desc->dev, desc->mask_pos, mask_bits);
+       pci_write_config_dword(msi_desc_to_pci_dev(desc), desc->mask_pos,
+                              mask_bits);
 
        return mask_bits;
 }
@@ -234,7 +234,7 @@ static void msix_mask_irq(struct msi_desc *desc, u32 flag)
 
 static void msi_set_mask_bit(struct irq_data *data, u32 flag)
 {
-       struct msi_desc *desc = irq_data_get_msi(data);
+       struct msi_desc *desc = irq_data_get_msi_desc(data);
 
        if (desc->msi_attrib.is_msix) {
                msix_mask_irq(desc, flag);
@@ -267,13 +267,15 @@ void default_restore_msi_irqs(struct pci_dev *dev)
 {
        struct msi_desc *entry;
 
-       list_for_each_entry(entry, &dev->msi_list, list)
+       for_each_pci_msi_entry(entry, dev)
                default_restore_msi_irq(dev, entry->irq);
 }
 
 void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 {
-       BUG_ON(entry->dev->current_state != PCI_D0);
+       struct pci_dev *dev = msi_desc_to_pci_dev(entry);
+
+       BUG_ON(dev->current_state != PCI_D0);
 
        if (entry->msi_attrib.is_msix) {
                void __iomem *base = entry->mask_base +
@@ -283,7 +285,6 @@ void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
                msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR);
                msg->data = readl(base + PCI_MSIX_ENTRY_DATA);
        } else {
-               struct pci_dev *dev = entry->dev;
                int pos = dev->msi_cap;
                u16 data;
 
@@ -303,7 +304,9 @@ void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 
 void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 {
-       if (entry->dev->current_state != PCI_D0) {
+       struct pci_dev *dev = msi_desc_to_pci_dev(entry);
+
+       if (dev->current_state != PCI_D0) {
                /* Don't touch the hardware now */
        } else if (entry->msi_attrib.is_msix) {
                void __iomem *base;
@@ -314,7 +317,6 @@ void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
                writel(msg->address_hi, base + PCI_MSIX_ENTRY_UPPER_ADDR);
                writel(msg->data, base + PCI_MSIX_ENTRY_DATA);
        } else {
-               struct pci_dev *dev = entry->dev;
                int pos = dev->msi_cap;
                u16 msgctl;
 
@@ -348,21 +350,22 @@ EXPORT_SYMBOL_GPL(pci_write_msi_msg);
 
 static void free_msi_irqs(struct pci_dev *dev)
 {
+       struct list_head *msi_list = dev_to_msi_list(&dev->dev);
        struct msi_desc *entry, *tmp;
        struct attribute **msi_attrs;
        struct device_attribute *dev_attr;
        int i, count = 0;
 
-       list_for_each_entry(entry, &dev->msi_list, list)
+       for_each_pci_msi_entry(entry, dev)
                if (entry->irq)
                        for (i = 0; i < entry->nvec_used; i++)
                                BUG_ON(irq_has_action(entry->irq + i));
 
        pci_msi_teardown_msi_irqs(dev);
 
-       list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) {
+       list_for_each_entry_safe(entry, tmp, msi_list, list) {
                if (entry->msi_attrib.is_msix) {
-                       if (list_is_last(&entry->list, &dev->msi_list))
+                       if (list_is_last(&entry->list, msi_list))
                                iounmap(entry->mask_base);
                }
 
@@ -387,18 +390,6 @@ static void free_msi_irqs(struct pci_dev *dev)
        }
 }
 
-static struct msi_desc *alloc_msi_entry(struct pci_dev *dev)
-{
-       struct msi_desc *desc = kzalloc(sizeof(*desc), GFP_KERNEL);
-       if (!desc)
-               return NULL;
-
-       INIT_LIST_HEAD(&desc->list);
-       desc->dev = dev;
-
-       return desc;
-}
-
 static void pci_intx_for_msi(struct pci_dev *dev, int enable)
 {
        if (!(dev->dev_flags & PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG))
@@ -433,7 +424,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
 
        if (!dev->msix_enabled)
                return;
-       BUG_ON(list_empty(&dev->msi_list));
+       BUG_ON(list_empty(dev_to_msi_list(&dev->dev)));
 
        /* route the table */
        pci_intx_for_msi(dev, 0);
@@ -441,7 +432,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
                                PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL);
 
        arch_restore_msi_irqs(dev);
-       list_for_each_entry(entry, &dev->msi_list, list)
+       for_each_pci_msi_entry(entry, dev)
                msix_mask_irq(entry, entry->masked);
 
        pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);
@@ -486,7 +477,7 @@ static int populate_msi_sysfs(struct pci_dev *pdev)
        int count = 0;
 
        /* Determine how many msi entries we have */
-       list_for_each_entry(entry, &pdev->msi_list, list)
+       for_each_pci_msi_entry(entry, pdev)
                ++num_msi;
        if (!num_msi)
                return 0;
@@ -495,7 +486,7 @@ static int populate_msi_sysfs(struct pci_dev *pdev)
        msi_attrs = kzalloc(sizeof(void *) * (num_msi + 1), GFP_KERNEL);
        if (!msi_attrs)
                return -ENOMEM;
-       list_for_each_entry(entry, &pdev->msi_list, list) {
+       for_each_pci_msi_entry(entry, pdev) {
                msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL);
                if (!msi_dev_attr)
                        goto error_attrs;
@@ -553,7 +544,7 @@ static struct msi_desc *msi_setup_entry(struct pci_dev *dev, int nvec)
        struct msi_desc *entry;
 
        /* MSI Entry Initialization */
-       entry = alloc_msi_entry(dev);
+       entry = alloc_msi_entry(&dev->dev);
        if (!entry)
                return NULL;
 
@@ -584,7 +575,7 @@ static int msi_verify_entries(struct pci_dev *dev)
 {
        struct msi_desc *entry;
 
-       list_for_each_entry(entry, &dev->msi_list, list) {
+       for_each_pci_msi_entry(entry, dev) {
                if (!dev->no_64bit_msi || !entry->msg.address_hi)
                        continue;
                dev_err(&dev->dev, "Device has broken 64-bit MSI but arch"
@@ -621,7 +612,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
        mask = msi_mask(entry->msi_attrib.multi_cap);
        msi_mask_irq(entry, mask, mask);
 
-       list_add_tail(&entry->list, &dev->msi_list);
+       list_add_tail(&entry->list, dev_to_msi_list(&dev->dev));
 
        /* Configure MSI capability structure */
        ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI);
@@ -682,7 +673,7 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
        int i;
 
        for (i = 0; i < nvec; i++) {
-               entry = alloc_msi_entry(dev);
+               entry = alloc_msi_entry(&dev->dev);
                if (!entry) {
                        if (!i)
                                iounmap(base);
@@ -699,7 +690,7 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
                entry->mask_base                = base;
                entry->nvec_used                = 1;
 
-               list_add_tail(&entry->list, &dev->msi_list);
+               list_add_tail(&entry->list, dev_to_msi_list(&dev->dev));
        }
 
        return 0;
@@ -711,7 +702,7 @@ static void msix_program_entries(struct pci_dev *dev,
        struct msi_desc *entry;
        int i = 0;
 
-       list_for_each_entry(entry, &dev->msi_list, list) {
+       for_each_pci_msi_entry(entry, dev) {
                int offset = entries[i].entry * PCI_MSIX_ENTRY_SIZE +
                                                PCI_MSIX_ENTRY_VECTOR_CTRL;
 
@@ -792,7 +783,7 @@ out_avail:
                struct msi_desc *entry;
                int avail = 0;
 
-               list_for_each_entry(entry, &dev->msi_list, list) {
+               for_each_pci_msi_entry(entry, dev) {
                        if (entry->irq != 0)
                                avail++;
                }
@@ -881,8 +872,8 @@ void pci_msi_shutdown(struct pci_dev *dev)
        if (!pci_msi_enable || !dev || !dev->msi_enabled)
                return;
 
-       BUG_ON(list_empty(&dev->msi_list));
-       desc = list_first_entry(&dev->msi_list, struct msi_desc, list);
+       BUG_ON(list_empty(dev_to_msi_list(&dev->dev)));
+       desc = first_pci_msi_entry(dev);
 
        pci_msi_set_enable(dev, 0);
        pci_intx_for_msi(dev, 1);
@@ -988,7 +979,7 @@ void pci_msix_shutdown(struct pci_dev *dev)
                return;
 
        /* Return the device with MSI-X masked as initial states */
-       list_for_each_entry(entry, &dev->msi_list, list) {
+       for_each_pci_msi_entry(entry, dev) {
                /* Keep cached states to be restored */
                __pci_msix_desc_mask_irq(entry, 1);
        }
@@ -1028,7 +1019,6 @@ EXPORT_SYMBOL(pci_msi_enabled);
 
 void pci_msi_init_pci_dev(struct pci_dev *dev)
 {
-       INIT_LIST_HEAD(&dev->msi_list);
 }
 
 /**
@@ -1125,6 +1115,19 @@ int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,
 }
 EXPORT_SYMBOL(pci_enable_msix_range);
 
+struct pci_dev *msi_desc_to_pci_dev(struct msi_desc *desc)
+{
+       return to_pci_dev(desc->dev);
+}
+
+void *msi_desc_to_pci_sysdata(struct msi_desc *desc)
+{
+       struct pci_dev *dev = msi_desc_to_pci_dev(desc);
+
+       return dev->bus->sysdata;
+}
+EXPORT_SYMBOL_GPL(msi_desc_to_pci_sysdata);
+
 #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
 /**
  * pci_msi_domain_write_msg - Helper to write MSI message to PCI config space
@@ -1133,7 +1136,7 @@ EXPORT_SYMBOL(pci_enable_msix_range);
  */
 void pci_msi_domain_write_msg(struct irq_data *irq_data, struct msi_msg *msg)
 {
-       struct msi_desc *desc = irq_data->msi_desc;
+       struct msi_desc *desc = irq_data_get_msi_desc(irq_data);
 
        /*
         * For MSI-X desc->irq is always equal to irq_data->irq. For
@@ -1257,12 +1260,19 @@ struct irq_domain *pci_msi_create_irq_domain(struct device_node *node,
                                             struct msi_domain_info *info,
                                             struct irq_domain *parent)
 {
+       struct irq_domain *domain;
+
        if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS)
                pci_msi_domain_update_dom_ops(info);
        if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
                pci_msi_domain_update_chip_ops(info);
 
-       return msi_create_irq_domain(node, info, parent);
+       domain = msi_create_irq_domain(node, info, parent);
+       if (!domain)
+               return NULL;
+
+       domain->bus_token = DOMAIN_BUS_PCI_MSI;
+       return domain;
 }
 
 /**
index f0929934bb7ac0c8a5d0dca4dbb197fb4700b6d3..2e99a500cb83fe48ac065333fad036186935aa4f 100644 (file)
@@ -9,6 +9,7 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <linux/irqdomain.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/of.h>
@@ -59,3 +60,32 @@ struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus)
                return of_node_get(bus->bridge->parent->of_node);
        return NULL;
 }
+
+struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus)
+{
+#ifdef CONFIG_IRQ_DOMAIN
+       struct device_node *np;
+       struct irq_domain *d;
+
+       if (!bus->dev.of_node)
+               return NULL;
+
+       /* Start looking for a phandle to an MSI controller. */
+       np = of_parse_phandle(bus->dev.of_node, "msi-parent", 0);
+
+       /*
+        * If we don't have an msi-parent property, look for a domain
+        * directly attached to the host bridge.
+        */
+       if (!np)
+               np = bus->dev.of_node;
+
+       d = irq_find_matching_host(np, DOMAIN_BUS_PCI_MSI);
+       if (d)
+               return d;
+
+       return irq_find_host(np);
+#else
+       return NULL;
+#endif
+}
index 04cfc60f786070617e06dfdd692129cbac841ee3..8177f3b0449152a7c01136a1925f4bfcf885cf8a 100644 (file)
@@ -661,6 +661,35 @@ static void pci_set_bus_speed(struct pci_bus *bus)
        }
 }
 
+static struct irq_domain *pci_host_bridge_msi_domain(struct pci_bus *bus)
+{
+       struct irq_domain *d;
+
+       /*
+        * Any firmware interface that can resolve the msi_domain
+        * should be called from here.
+        */
+       d = pci_host_bridge_of_msi_domain(bus);
+
+       return d;
+}
+
+static void pci_set_bus_msi_domain(struct pci_bus *bus)
+{
+       struct irq_domain *d;
+
+       /*
+        * Either bus is the root, and we must obtain it from the
+        * firmware, or we inherit it from the bridge device.
+        */
+       if (pci_is_root_bus(bus))
+               d = pci_host_bridge_msi_domain(bus);
+       else
+               d = dev_get_msi_domain(&bus->self->dev);
+
+       dev_set_msi_domain(&bus->dev, d);
+}
+
 static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
                                           struct pci_dev *bridge, int busnr)
 {
@@ -714,6 +743,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
        bridge->subordinate = child;
 
 add_dev:
+       pci_set_bus_msi_domain(child);
        ret = device_register(&child->dev);
        WARN_ON(ret < 0);
 
@@ -1594,6 +1624,17 @@ static void pci_init_capabilities(struct pci_dev *dev)
        pci_enable_acs(dev);
 }
 
+static void pci_set_msi_domain(struct pci_dev *dev)
+{
+       /*
+        * If no domain has been set through the pcibios_add_device
+        * callback, inherit the default from the bus device.
+        */
+       if (!dev_get_msi_domain(&dev->dev))
+               dev_set_msi_domain(&dev->dev,
+                                  dev_get_msi_domain(&dev->bus->dev));
+}
+
 void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
 {
        int ret;
@@ -1635,6 +1676,9 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
        ret = pcibios_add_device(dev);
        WARN_ON(ret < 0);
 
+       /* Setup MSI irq domain */
+       pci_set_msi_domain(dev);
+
        /* Notifier could use PCI capabilities */
        dev->match_driver = false;
        ret = device_add(&dev->dev);
@@ -2008,6 +2052,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
        b->bridge = get_device(&bridge->dev);
        device_enable_async_suspend(b->bridge);
        pci_set_bus_of_node(b);
+       pci_set_bus_msi_domain(b);
 
        if (!parent)
                set_dev_node(b->bridge, pcibus_to_node(b));
index 8b7a900cd28b25e5a8d52a10357768df1d6513aa..c777b97207d5378936a8f25a54be603d76691ab9 100644 (file)
@@ -265,7 +265,7 @@ static int pci_frontend_enable_msix(struct pci_dev *dev,
        }
 
        i = 0;
-       list_for_each_entry(entry, &dev->msi_list, list) {
+       for_each_pci_msi_entry(entry, dev) {
                op.msix_entries[i].entry = entry->msi_attrib.entry_nr;
                /* Vector is useless at this point. */
                op.msix_entries[i].vector = -1;
index 46427b48e2f1767fcc1fa8732aff3536fb38ec66..358df75101860090808775a62661fce0313219d4 100644 (file)
@@ -22,7 +22,7 @@ void _intc_enable(struct irq_data *data, unsigned long handle)
 
        for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
 #ifdef CONFIG_SMP
-               if (!cpumask_test_cpu(cpu, data->affinity))
+               if (!cpumask_test_cpu(cpu, irq_data_get_affinity_mask(data)))
                        continue;
 #endif
                addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
@@ -50,7 +50,7 @@ static void intc_disable(struct irq_data *data)
 
        for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
 #ifdef CONFIG_SMP
-               if (!cpumask_test_cpu(cpu, data->affinity))
+               if (!cpumask_test_cpu(cpu, irq_data_get_affinity_mask(data)))
                        continue;
 #endif
                addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
@@ -72,7 +72,7 @@ static int intc_set_affinity(struct irq_data *data,
        if (!cpumask_intersects(cpumask, cpu_online_mask))
                return -1;
 
-       cpumask_copy(data->affinity, cpumask);
+       cpumask_copy(irq_data_get_affinity_mask(data), cpumask);
 
        return IRQ_SET_MASK_OK_NOCOPY;
 }
index 156b790072b47263f5c9aec874e02694e6bb1c9b..043419dcee92306eb93c52b6240df0a48071c272 100644 (file)
@@ -67,7 +67,7 @@ void intc_set_prio_level(unsigned int irq, unsigned int level)
 
 static void intc_redirect_irq(unsigned int irq, struct irq_desc *desc)
 {
-       generic_handle_irq((unsigned int)irq_get_handler_data(irq));
+       generic_handle_irq((unsigned int)irq_desc_get_handler_data(desc));
 }
 
 static void __init intc_register_irq(struct intc_desc *desc,
index f5f1b821241afc92e6854788262d13f665a0dd45..bafc51c6f0bacbe2fdb99e033d89a46dd07d37ea 100644 (file)
@@ -83,12 +83,11 @@ EXPORT_SYMBOL_GPL(intc_irq_lookup);
 
 static int add_virq_to_pirq(unsigned int irq, unsigned int virq)
 {
-       struct intc_virq_list **last, *entry;
-       struct irq_data *data = irq_get_irq_data(irq);
+       struct intc_virq_list *entry;
+       struct intc_virq_list **last = NULL;
 
        /* scan for duplicates */
-       last = (struct intc_virq_list **)&data->handler_data;
-       for_each_virq(entry, data->handler_data) {
+       for_each_virq(entry, irq_get_handler_data(irq)) {
                if (entry->irq == virq)
                        return 0;
                last = &entry->next;
@@ -102,14 +101,18 @@ static int add_virq_to_pirq(unsigned int irq, unsigned int virq)
 
        entry->irq = virq;
 
-       *last = entry;
+       if (last)
+               *last = entry;
+       else
+               irq_set_handler_data(irq, entry);
 
        return 0;
 }
 
-static void intc_virq_handler(unsigned int irq, struct irq_desc *desc)
+static void intc_virq_handler(unsigned int __irq, struct irq_desc *desc)
 {
-       struct irq_data *data = irq_get_irq_data(irq);
+       unsigned int irq = irq_desc_get_irq(desc);
+       struct irq_data *data = irq_desc_get_irq_data(desc);
        struct irq_chip *chip = irq_data_get_irq_chip(data);
        struct intc_virq_list *entry, *vlist = irq_data_get_irq_handler_data(data);
        struct intc_desc_int *d = get_intc_desc(irq);
@@ -118,12 +121,14 @@ static void intc_virq_handler(unsigned int irq, struct irq_desc *desc)
 
        for_each_virq(entry, vlist) {
                unsigned long addr, handle;
+               struct irq_desc *vdesc = irq_to_desc(entry->irq);
 
-               handle = (unsigned long)irq_get_handler_data(entry->irq);
-               addr = INTC_REG(d, _INTC_ADDR_E(handle), 0);
-
-               if (intc_reg_fns[_INTC_FN(handle)](addr, handle, 0))
-                       generic_handle_irq(entry->irq);
+               if (vdesc) {
+                       handle = (unsigned long)irq_desc_get_handler_data(vdesc);
+                       addr = INTC_REG(d, _INTC_ADDR_E(handle), 0);
+                       if (intc_reg_fns[_INTC_FN(handle)](addr, handle, 0))
+                               generic_handle_irq_desc(entry->irq, vdesc);
+               }
        }
 
        chip->irq_unmask(data);
index a4d8c043a7106907259c3deb78c36fbb9b631b47..bdfb3c84c3cb43a652dcb36fb449758807f58fa4 100644 (file)
@@ -453,8 +453,8 @@ static void periph_interrupt(struct spmi_pmic_arb_dev *pa, u8 apid)
 
 static void pmic_arb_chained_irq(unsigned int irq, struct irq_desc *desc)
 {
-       struct spmi_pmic_arb_dev *pa = irq_get_handler_data(irq);
-       struct irq_chip *chip = irq_get_chip(irq);
+       struct spmi_pmic_arb_dev *pa = irq_desc_get_handler_data(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        void __iomem *intr = pa->intr;
        int first = pa->min_apid >> 5;
        int last = pa->max_apid >> 5;
@@ -945,8 +945,7 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
                goto err_put_ctrl;
        }
 
-       irq_set_handler_data(pa->irq, pa);
-       irq_set_chained_handler(pa->irq, pmic_arb_chained_irq);
+       irq_set_chained_handler_and_data(pa->irq, pmic_arb_chained_irq, pa);
 
        err = spmi_controller_add(ctrl);
        if (err)
@@ -955,8 +954,7 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
        return 0;
 
 err_domain_remove:
-       irq_set_chained_handler(pa->irq, NULL);
-       irq_set_handler_data(pa->irq, NULL);
+       irq_set_chained_handler_and_data(pa->irq, NULL, NULL);
        irq_domain_remove(pa->domain);
 err_put_ctrl:
        spmi_controller_put(ctrl);
@@ -968,8 +966,7 @@ static int spmi_pmic_arb_remove(struct platform_device *pdev)
        struct spmi_controller *ctrl = platform_get_drvdata(pdev);
        struct spmi_pmic_arb_dev *pa = spmi_controller_get_drvdata(ctrl);
        spmi_controller_remove(ctrl);
-       irq_set_chained_handler(pa->irq, NULL);
-       irq_set_handler_data(pa->irq, NULL);
+       irq_set_chained_handler_and_data(pa->irq, NULL, NULL);
        irq_domain_remove(pa->domain);
        spmi_controller_put(ctrl);
        return 0;
index 1225f98e9240226ff7685190aef463b8d640a6e0..49fdcc4b8adff4e7482f243d459afed09c91b2d4 100644 (file)
@@ -714,6 +714,8 @@ struct device_dma_parameters {
  *             along with subsystem-level and driver-level callbacks.
  * @pins:      For device pin management.
  *             See Documentation/pinctrl.txt for details.
+ * @msi_list:  Hosts MSI descriptors
+ * @msi_domain: The generic MSI domain this device is using.
  * @numa_node: NUMA node this device is close to.
  * @dma_mask:  Dma mask (if dma'ble device).
  * @coherent_dma_mask: Like dma_mask, but for alloc_coherent mapping as not all
@@ -774,9 +776,15 @@ struct device {
        struct dev_pm_info      power;
        struct dev_pm_domain    *pm_domain;
 
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+       struct irq_domain       *msi_domain;
+#endif
 #ifdef CONFIG_PINCTRL
        struct dev_pin_info     *pins;
 #endif
+#ifdef CONFIG_GENERIC_MSI_IRQ
+       struct list_head        msi_list;
+#endif
 
 #ifdef CONFIG_NUMA
        int             numa_node;      /* NUMA node this device is close to */
@@ -861,6 +869,22 @@ static inline void set_dev_node(struct device *dev, int node)
 }
 #endif
 
+static inline struct irq_domain *dev_get_msi_domain(const struct device *dev)
+{
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+       return dev->msi_domain;
+#else
+       return NULL;
+#endif
+}
+
+static inline void dev_set_msi_domain(struct device *dev, struct irq_domain *d)
+{
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+       dev->msi_domain = d;
+#endif
+}
+
 static inline void *dev_get_drvdata(const struct device *dev)
 {
        return dev->driver_data;
index 51744bcf74eec7bee678b9e1f63c3a10f247350e..6f8b340664421bb797fd37488bbd2c97afb6d3d4 100644 (file)
@@ -324,8 +324,10 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
  * @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips
  * @irq_cpu_online:    configure an interrupt source for a secondary CPU
  * @irq_cpu_offline:   un-configure an interrupt source for a secondary CPU
- * @irq_suspend:       function called from core code on suspend once per chip
- * @irq_resume:                function called from core code on resume once per chip
+ * @irq_suspend:       function called from core code on suspend once per
+ *                     chip, when one or more interrupts are installed
+ * @irq_resume:                function called from core code on resume once per chip,
+ *                     when one ore more interrupts are installed
  * @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_print_chip:    optional to print special chip info in show_interrupts
@@ -488,8 +490,7 @@ extern int irq_chip_set_type_parent(struct irq_data *data, unsigned int type);
 #endif
 
 /* Handling of unhandled and spurious interrupts: */
-extern void note_interrupt(unsigned int irq, struct irq_desc *desc,
-                          irqreturn_t action_ret);
+extern void note_interrupt(struct irq_desc *desc, irqreturn_t action_ret);
 
 
 /* Enable/disable irq debugging output: */
@@ -640,7 +641,7 @@ static inline struct msi_desc *irq_get_msi_desc(unsigned int irq)
        return d ? d->msi_desc : NULL;
 }
 
-static inline struct msi_desc *irq_data_get_msi(struct irq_data *d)
+static inline struct msi_desc *irq_data_get_msi_desc(struct irq_data *d)
 {
        return d->msi_desc;
 }
@@ -762,6 +763,12 @@ struct irq_chip_type {
  * @reg_base:          Register base address (virtual)
  * @reg_readl:         Alternate I/O accessor (defaults to readl if NULL)
  * @reg_writel:                Alternate I/O accessor (defaults to writel if NULL)
+ * @suspend:           Function called from core code on suspend once per
+ *                     chip; can be useful instead of irq_chip::suspend to
+ *                     handle chip details even when no interrupts are in use
+ * @resume:            Function called from core code on resume once per chip;
+ *                     can be useful instead of irq_chip::suspend to handle
+ *                     chip details even when no interrupts are in use
  * @irq_base:          Interrupt base nr for this chip
  * @irq_cnt:           Number of interrupts handled by this chip
  * @mask_cache:                Cached mask register shared between all chip types
@@ -788,6 +795,8 @@ struct irq_chip_generic {
        void __iomem            *reg_base;
        u32                     (*reg_readl)(void __iomem *addr);
        void                    (*reg_writel)(u32 val, void __iomem *addr);
+       void                    (*suspend)(struct irq_chip_generic *gc);
+       void                    (*resume)(struct irq_chip_generic *gc);
        unsigned int            irq_base;
        unsigned int            irq_cnt;
        u32                     mask_cache;
index ffbc034c88104d251c3891f4513c12a62818c5dd..bf982e021fbd043f8fddf0903a6926f3558a679b 100644 (file)
 #ifndef __ASSEMBLY__
 
 #include <linux/stringify.h>
+#include <asm/msi.h>
 
 /*
  * We need a value to serve as a irq-type for LPIs. Choose one that will
index 9de976b4f9a79c8ef8bb43e7a150a2533e74f39a..65da435d01c10218741ccddc1f99d7107acaad4d 100644 (file)
 
 struct device_node;
 
-void gic_set_irqchip_flags(unsigned long flags);
 void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
                    u32 offset, struct device_node *);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
-void gic_cpu_if_down(void);
+int gic_cpu_if_down(unsigned int gic_nr);
 
 static inline void gic_init(unsigned int nr, int start,
                            void __iomem *dist , void __iomem *cpu)
index 744ac0ec98eb2c9e094f8ebdcfd71aebcdd32026..d3ca79236fb00ee5543e507ae9e69bc62b700e43 100644 (file)
@@ -45,6 +45,20 @@ struct irq_data;
 /* Number of irqs reserved for a legacy isa controller */
 #define NUM_ISA_INTERRUPTS     16
 
+/*
+ * Should several domains have the same device node, but serve
+ * different purposes (for example one domain is for PCI/MSI, and the
+ * other for wired IRQs), they can be distinguished using a
+ * bus-specific token. Most domains are expected to only carry
+ * DOMAIN_BUS_ANY.
+ */
+enum irq_domain_bus_token {
+       DOMAIN_BUS_ANY          = 0,
+       DOMAIN_BUS_PCI_MSI,
+       DOMAIN_BUS_PLATFORM_MSI,
+       DOMAIN_BUS_NEXUS,
+};
+
 /**
  * struct irq_domain_ops - Methods for irq_domain objects
  * @match: Match an interrupt controller device node to a host, returns
@@ -61,7 +75,8 @@ struct irq_data;
  * to setup the irq_desc when returning from map().
  */
 struct irq_domain_ops {
-       int (*match)(struct irq_domain *d, struct device_node *node);
+       int (*match)(struct irq_domain *d, struct device_node *node,
+                    enum irq_domain_bus_token bus_token);
        int (*map)(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw);
        void (*unmap)(struct irq_domain *d, unsigned int virq);
        int (*xlate)(struct irq_domain *d, struct device_node *node,
@@ -116,6 +131,7 @@ struct irq_domain {
 
        /* Optional data */
        struct device_node *of_node;
+       enum irq_domain_bus_token bus_token;
        struct irq_domain_chip_generic *gc;
 #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
        struct irq_domain *parent;
@@ -161,9 +177,15 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
                                         irq_hw_number_t first_hwirq,
                                         const struct irq_domain_ops *ops,
                                         void *host_data);
-extern struct irq_domain *irq_find_host(struct device_node *node);
+extern struct irq_domain *irq_find_matching_host(struct device_node *node,
+                                                enum irq_domain_bus_token bus_token);
 extern void irq_set_default_host(struct irq_domain *host);
 
+static inline struct irq_domain *irq_find_host(struct device_node *node)
+{
+       return irq_find_matching_host(node, DOMAIN_BUS_ANY);
+}
+
 /**
  * irq_domain_add_linear() - Allocate and register a linear revmap irq_domain.
  * @of_node: pointer to interrupt controller's device tree node.
index 8ac4a68ffae2d928f677e0a9535402eb8978636a..ad939d0ba816372b975d5c44d9582617b7b618e0 100644 (file)
@@ -14,38 +14,85 @@ extern int pci_msi_ignore_mask;
 /* Helper functions */
 struct irq_data;
 struct msi_desc;
+struct pci_dev;
+struct platform_msi_priv_data;
 void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
 void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg);
 
+typedef void (*irq_write_msi_msg_t)(struct msi_desc *desc,
+                                   struct msi_msg *msg);
+
+/**
+ * platform_msi_desc - Platform device specific msi descriptor data
+ * @msi_priv_data:     Pointer to platform private data
+ * @msi_index:         The index of the MSI descriptor for multi MSI
+ */
+struct platform_msi_desc {
+       struct platform_msi_priv_data   *msi_priv_data;
+       u16                             msi_index;
+};
+
+/**
+ * struct msi_desc - Descriptor structure for MSI based interrupts
+ * @list:      List head for management
+ * @irq:       The base interrupt number
+ * @nvec_used: The number of vectors used
+ * @dev:       Pointer to the device which uses this descriptor
+ * @msg:       The last set MSI message cached for reuse
+ *
+ * @masked:    [PCI MSI/X] Mask bits
+ * @is_msix:   [PCI MSI/X] True if MSI-X
+ * @multiple:  [PCI MSI/X] log2 num of messages allocated
+ * @multi_cap: [PCI MSI/X] log2 num of messages supported
+ * @maskbit:   [PCI MSI/X] Mask-Pending bit supported?
+ * @is_64:     [PCI MSI/X] Address size: 0=32bit 1=64bit
+ * @entry_nr:  [PCI MSI/X] Entry which is described by this descriptor
+ * @default_irq:[PCI MSI/X] The default pre-assigned non-MSI irq
+ * @mask_pos:  [PCI MSI]   Mask register position
+ * @mask_base: [PCI MSI-X] Mask register base address
+ * @platform:  [platform]  Platform device specific msi descriptor data
+ */
 struct msi_desc {
-       struct {
-               __u8    is_msix : 1;
-               __u8    multiple: 3;    /* log2 num of messages allocated */
-               __u8    multi_cap : 3;  /* log2 num of messages supported */
-               __u8    maskbit : 1;    /* mask-pending bit supported ? */
-               __u8    is_64   : 1;    /* Address size: 0=32bit 1=64bit */
-               __u16   entry_nr;       /* specific enabled entry */
-               unsigned default_irq;   /* default pre-assigned irq */
-       } msi_attrib;
-
-       u32 masked;                     /* mask bits */
-       unsigned int irq;
-       unsigned int nvec_used;         /* number of messages */
-       struct list_head list;
+       /* Shared device/bus type independent data */
+       struct list_head                list;
+       unsigned int                    irq;
+       unsigned int                    nvec_used;
+       struct device                   *dev;
+       struct msi_msg                  msg;
 
        union {
-               void __iomem *mask_base;
-               u8 mask_pos;
-       };
-       struct pci_dev *dev;
+               /* PCI MSI/X specific data */
+               struct {
+                       u32 masked;
+                       struct {
+                               __u8    is_msix         : 1;
+                               __u8    multiple        : 3;
+                               __u8    multi_cap       : 3;
+                               __u8    maskbit         : 1;
+                               __u8    is_64           : 1;
+                               __u16   entry_nr;
+                               unsigned default_irq;
+                       } msi_attrib;
+                       union {
+                               u8      mask_pos;
+                               void __iomem *mask_base;
+                       };
+               };
 
-       /* Last set MSI message */
-       struct msi_msg msg;
+               /*
+                * Non PCI variants add their data structure here. New
+                * entries need to use a named structure. We want
+                * proper name spaces for this. The PCI part is
+                * anonymous for now as it would require an immediate
+                * tree wide cleanup.
+                */
+               struct platform_msi_desc platform;
+       };
 };
 
 /* Helpers to hide struct msi_desc implementation details */
-#define msi_desc_to_dev(desc)          (&(desc)->dev.dev)
-#define dev_to_msi_list(dev)           (&to_pci_dev((dev))->msi_list)
+#define msi_desc_to_dev(desc)          ((desc)->dev)
+#define dev_to_msi_list(dev)           (&(dev)->msi_list)
 #define first_msi_entry(dev)           \
        list_first_entry(dev_to_msi_list((dev)), struct msi_desc, list)
 #define for_each_msi_entry(desc, dev)  \
@@ -56,12 +103,17 @@ struct msi_desc {
 #define for_each_pci_msi_entry(desc, pdev)     \
        for_each_msi_entry((desc), &(pdev)->dev)
 
-static inline struct pci_dev *msi_desc_to_pci_dev(struct msi_desc *desc)
+struct pci_dev *msi_desc_to_pci_dev(struct msi_desc *desc);
+void *msi_desc_to_pci_sysdata(struct msi_desc *desc);
+#else /* CONFIG_PCI_MSI */
+static inline void *msi_desc_to_pci_sysdata(struct msi_desc *desc)
 {
-       return desc->dev;
+       return NULL;
 }
 #endif /* CONFIG_PCI_MSI */
 
+struct msi_desc *alloc_msi_entry(struct device *dev);
+void free_msi_entry(struct msi_desc *entry);
 void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
 void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
 void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg);
@@ -108,9 +160,6 @@ struct msi_controller {
        struct device *dev;
        struct device_node *of_node;
        struct list_head list;
-#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
-       struct irq_domain *domain;
-#endif
 
        int (*setup_irq)(struct msi_controller *chip, struct pci_dev *dev,
                         struct msi_desc *desc);
@@ -221,6 +270,12 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
 void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev);
 struct msi_domain_info *msi_get_domain_info(struct irq_domain *domain);
 
+struct irq_domain *platform_msi_create_irq_domain(struct device_node *np,
+                                                 struct msi_domain_info *info,
+                                                 struct irq_domain *parent);
+int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
+                                  irq_write_msi_msg_t write_msi_msg);
+void platform_msi_domain_free_irqs(struct device *dev);
 #endif /* CONFIG_GENERIC_MSI_IRQ_DOMAIN */
 
 #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
index d884929a77479782f9486ac486d0bad444bfcef8..4bcbd586a67296081fadb219ee96f32d7fcb65b2 100644 (file)
@@ -74,6 +74,7 @@ static inline int of_irq_to_resource_table(struct device_node *dev,
  */
 extern unsigned int irq_of_parse_and_map(struct device_node *node, int index);
 extern struct device_node *of_irq_find_parent(struct device_node *child);
+extern void of_msi_configure(struct device *dev, struct device_node *np);
 
 #else /* !CONFIG_OF */
 static inline unsigned int irq_of_parse_and_map(struct device_node *dev,
index 4fee9cd7a7df948d59f29b89f18b24f6db4c14a6..1a64733c48c741dff6d8bdfc34588c8c8f72f7fd 100644 (file)
@@ -369,7 +369,6 @@ struct pci_dev {
        struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */
        struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */
 #ifdef CONFIG_PCI_MSI
-       struct list_head msi_list;
        const struct attribute_group **msi_irq_groups;
 #endif
        struct pci_vpd *vpd;
@@ -1892,10 +1891,12 @@ int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off,
 /* PCI <-> OF binding helpers */
 #ifdef CONFIG_OF
 struct device_node;
+struct irq_domain;
 void pci_set_of_node(struct pci_dev *dev);
 void pci_release_of_node(struct pci_dev *dev);
 void pci_set_bus_of_node(struct pci_bus *bus);
 void pci_release_bus_of_node(struct pci_bus *bus);
+struct irq_domain *pci_host_bridge_of_msi_domain(struct pci_bus *bus);
 
 /* Arch may override this (weak) */
 struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus);
@@ -1918,6 +1919,8 @@ static inline void pci_set_bus_of_node(struct pci_bus *bus) { }
 static inline void pci_release_bus_of_node(struct pci_bus *bus) { }
 static inline struct device_node *
 pci_device_to_OF_node(const struct pci_dev *pdev) { return NULL; }
+static inline struct irq_domain *
+pci_host_bridge_of_msi_domain(struct pci_bus *bus) { return NULL; }
 #endif  /* CONFIG_OF */
 
 #ifdef CONFIG_EEH
index ae216824e8ca9224c4b76f225ef58d664a3e1726..6e40a9539763f48efc695c2b780a29f61b760f9f 100644 (file)
@@ -63,7 +63,7 @@ int irq_set_irq_type(unsigned int irq, unsigned int type)
                return -EINVAL;
 
        type &= IRQ_TYPE_SENSE_MASK;
-       ret = __irq_set_trigger(desc, irq, type);
+       ret = __irq_set_trigger(desc, type);
        irq_put_desc_busunlock(desc, flags);
        return ret;
 }
@@ -187,7 +187,7 @@ int irq_startup(struct irq_desc *desc, bool resend)
                irq_enable(desc);
        }
        if (resend)
-               check_irq_resend(desc, desc->irq_data.irq);
+               check_irq_resend(desc);
        return ret;
 }
 
@@ -315,7 +315,7 @@ void handle_nested_irq(unsigned int irq)
        raw_spin_lock_irq(&desc->lock);
 
        desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
-       kstat_incr_irqs_this_cpu(irq, desc);
+       kstat_incr_irqs_this_cpu(desc);
 
        action = desc->action;
        if (unlikely(!action || irqd_irq_disabled(&desc->irq_data))) {
@@ -328,7 +328,7 @@ void handle_nested_irq(unsigned int irq)
 
        action_ret = action->thread_fn(action->irq, action->dev_id);
        if (!noirqdebug)
-               note_interrupt(irq, desc, action_ret);
+               note_interrupt(desc, action_ret);
 
        raw_spin_lock_irq(&desc->lock);
        irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);
@@ -391,7 +391,7 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc)
                goto out_unlock;
 
        desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
-       kstat_incr_irqs_this_cpu(irq, desc);
+       kstat_incr_irqs_this_cpu(desc);
 
        if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
                desc->istate |= IRQS_PENDING;
@@ -443,7 +443,7 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
                goto out_unlock;
 
        desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
-       kstat_incr_irqs_this_cpu(irq, desc);
+       kstat_incr_irqs_this_cpu(desc);
 
        /*
         * If its disabled or no action available
@@ -515,7 +515,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
                goto out;
 
        desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
-       kstat_incr_irqs_this_cpu(irq, desc);
+       kstat_incr_irqs_this_cpu(desc);
 
        /*
         * If its disabled or no action available
@@ -583,7 +583,7 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
                goto out_unlock;
        }
 
-       kstat_incr_irqs_this_cpu(irq, desc);
+       kstat_incr_irqs_this_cpu(desc);
 
        /* Start handling the irq */
        desc->irq_data.chip->irq_ack(&desc->irq_data);
@@ -646,7 +646,7 @@ void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc)
                goto out_eoi;
        }
 
-       kstat_incr_irqs_this_cpu(irq, desc);
+       kstat_incr_irqs_this_cpu(desc);
 
        do {
                if (unlikely(!desc->action))
@@ -675,7 +675,7 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
 
-       kstat_incr_irqs_this_cpu(irq, desc);
+       kstat_incr_irqs_this_cpu(desc);
 
        if (chip->irq_ack)
                chip->irq_ack(&desc->irq_data);
@@ -705,7 +705,7 @@ void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc)
        void *dev_id = raw_cpu_ptr(action->percpu_dev_id);
        irqreturn_t res;
 
-       kstat_incr_irqs_this_cpu(irq, desc);
+       kstat_incr_irqs_this_cpu(desc);
 
        if (chip->irq_ack)
                chip->irq_ack(&desc->irq_data);
@@ -1020,7 +1020,7 @@ int irq_chip_retrigger_hierarchy(struct irq_data *data)
 /**
  * irq_chip_set_vcpu_affinity_parent - Set vcpu affinity on the parent interrupt
  * @data:      Pointer to interrupt specific data
- * @dest:      The vcpu affinity information
+ * @vcpu_info: The vcpu affinity information
  */
 int irq_chip_set_vcpu_affinity_parent(struct irq_data *data, void *vcpu_info)
 {
index 15b370daf23446d3a6b5213cbeac4d9559fb095d..abd286afbd2732544e54a4653053a4d9ce785286 100644 (file)
@@ -553,6 +553,9 @@ static int irq_gc_suspend(void)
                        if (data)
                                ct->chip.irq_suspend(data);
                }
+
+               if (gc->suspend)
+                       gc->suspend(gc);
        }
        return 0;
 }
@@ -564,6 +567,9 @@ static void irq_gc_resume(void)
        list_for_each_entry(gc, &gc_list, list) {
                struct irq_chip_type *ct = gc->chip_types;
 
+               if (gc->resume)
+                       gc->resume(gc);
+
                if (ct->chip.irq_resume) {
                        struct irq_data *data = irq_gc_get_irq_data(gc);
 
index 635480270858448064b1afa54bf616f074744d60..b6eeea8a80c5bbb7143b41ebcaa6f1132eedc7b4 100644 (file)
@@ -30,7 +30,7 @@
 void handle_bad_irq(unsigned int irq, struct irq_desc *desc)
 {
        print_irq_desc(irq, desc);
-       kstat_incr_irqs_this_cpu(irq, desc);
+       kstat_incr_irqs_this_cpu(desc);
        ack_bad_irq(irq);
 }
 
@@ -176,7 +176,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
        add_interrupt_randomness(irq, flags);
 
        if (!noirqdebug)
-               note_interrupt(irq, desc, retval);
+               note_interrupt(desc, retval);
        return retval;
 }
 
index 61008b8433ab78f5364ac2512d956fd554614690..eee4b385cffb46f260db19bfd9f9f5fbf7044224 100644 (file)
@@ -59,10 +59,9 @@ enum {
 #include "debug.h"
 #include "settings.h"
 
-extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
-               unsigned long flags);
-extern void __disable_irq(struct irq_desc *desc, unsigned int irq);
-extern void __enable_irq(struct irq_desc *desc, unsigned int irq);
+extern int __irq_set_trigger(struct irq_desc *desc, unsigned long flags);
+extern void __disable_irq(struct irq_desc *desc);
+extern void __enable_irq(struct irq_desc *desc);
 
 extern int irq_startup(struct irq_desc *desc, bool resend);
 extern void irq_shutdown(struct irq_desc *desc);
@@ -86,7 +85,7 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *act
 irqreturn_t handle_irq_event(struct irq_desc *desc);
 
 /* Resending of interrupts :*/
-void check_irq_resend(struct irq_desc *desc, unsigned int irq);
+void check_irq_resend(struct irq_desc *desc);
 bool irq_wait_for_poll(struct irq_desc *desc);
 void __irq_wake_thread(struct irq_desc *desc, struct irqaction *action);
 
@@ -187,7 +186,7 @@ static inline bool irqd_has_set(struct irq_data *d, unsigned int mask)
        return __irqd_to_state(d) & mask;
 }
 
-static inline void kstat_incr_irqs_this_cpu(unsigned int irq, struct irq_desc *desc)
+static inline void kstat_incr_irqs_this_cpu(struct irq_desc *desc)
 {
        __this_cpu_inc(*desc->kstat_irqs);
        __this_cpu_inc(kstat.irqs_sum);
index 4afc457613ddf7da1bd845733e68ec22af099ec0..0a2a4b697bcbffcc219b024a04113e1358d109d9 100644 (file)
@@ -582,7 +582,7 @@ int irq_set_percpu_devid(unsigned int irq)
 
 void kstat_incr_irq_this_cpu(unsigned int irq)
 {
-       kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
+       kstat_incr_irqs_this_cpu(irq_to_desc(irq));
 }
 
 /**
index 8c3577fef78c4ee50cd6912d1cc87202e7d17cf2..79baaf8a7813a601659d1316becba1fe0fd9807c 100644 (file)
@@ -187,10 +187,12 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
 
 /**
- * irq_find_host() - Locates a domain for a given device node
+ * irq_find_matching_host() - Locates a domain for a given device node
  * @node: device-tree node of the interrupt controller
+ * @bus_token: domain-specific data
  */
-struct irq_domain *irq_find_host(struct device_node *node)
+struct irq_domain *irq_find_matching_host(struct device_node *node,
+                                         enum irq_domain_bus_token bus_token)
 {
        struct irq_domain *h, *found = NULL;
        int rc;
@@ -199,13 +201,19 @@ struct irq_domain *irq_find_host(struct device_node *node)
         * it might potentially be set to match all interrupts in
         * the absence of a device node. This isn't a problem so far
         * yet though...
+        *
+        * bus_token == DOMAIN_BUS_ANY matches any domain, any other
+        * values must generate an exact match for the domain to be
+        * selected.
         */
        mutex_lock(&irq_domain_mutex);
        list_for_each_entry(h, &irq_domain_list, link) {
                if (h->ops->match)
-                       rc = h->ops->match(h, node);
+                       rc = h->ops->match(h, node, bus_token);
                else
-                       rc = (h->of_node != NULL) && (h->of_node == node);
+                       rc = ((h->of_node != NULL) && (h->of_node == node) &&
+                             ((bus_token == DOMAIN_BUS_ANY) ||
+                              (h->bus_token == bus_token)));
 
                if (rc) {
                        found = h;
@@ -215,7 +223,7 @@ struct irq_domain *irq_find_host(struct device_node *node)
        mutex_unlock(&irq_domain_mutex);
        return found;
 }
-EXPORT_SYMBOL_GPL(irq_find_host);
+EXPORT_SYMBOL_GPL(irq_find_matching_host);
 
 /**
  * irq_set_default_host() - Set a "default" irq domain
index f9744853b656976bc4fdc49e006464a08a7d5395..ad1b064f94fee7cf19e1d6c5592832184fcda3ff 100644 (file)
@@ -115,6 +115,14 @@ EXPORT_SYMBOL(synchronize_irq);
 #ifdef CONFIG_SMP
 cpumask_var_t irq_default_affinity;
 
+static int __irq_can_set_affinity(struct irq_desc *desc)
+{
+       if (!desc || !irqd_can_balance(&desc->irq_data) ||
+           !desc->irq_data.chip || !desc->irq_data.chip->irq_set_affinity)
+               return 0;
+       return 1;
+}
+
 /**
  *     irq_can_set_affinity - Check if the affinity of a given irq can be set
  *     @irq:           Interrupt to check
@@ -122,13 +130,7 @@ cpumask_var_t irq_default_affinity;
  */
 int irq_can_set_affinity(unsigned int irq)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-
-       if (!desc || !irqd_can_balance(&desc->irq_data) ||
-           !desc->irq_data.chip || !desc->irq_data.chip->irq_set_affinity)
-               return 0;
-
-       return 1;
+       return __irq_can_set_affinity(irq_to_desc(irq));
 }
 
 /**
@@ -359,14 +361,13 @@ EXPORT_SYMBOL_GPL(irq_set_affinity_notifier);
 /*
  * Generic version of the affinity autoselector.
  */
-static int
-setup_affinity(unsigned int irq, struct irq_desc *desc, struct cpumask *mask)
+static int setup_affinity(struct irq_desc *desc, struct cpumask *mask)
 {
        struct cpumask *set = irq_default_affinity;
        int node = irq_desc_get_node(desc);
 
        /* Excludes PER_CPU and NO_BALANCE interrupts */
-       if (!irq_can_set_affinity(irq))
+       if (!__irq_can_set_affinity(desc))
                return 0;
 
        /*
@@ -393,10 +394,10 @@ setup_affinity(unsigned int irq, struct irq_desc *desc, struct cpumask *mask)
        return 0;
 }
 #else
-static inline int
-setup_affinity(unsigned int irq, struct irq_desc *d, struct cpumask *mask)
+/* Wrapper for ALPHA specific affinity selector magic */
+static inline int setup_affinity(struct irq_desc *d, struct cpumask *mask)
 {
-       return irq_select_affinity(irq);
+       return irq_select_affinity(irq_desc_get_irq(d));
 }
 #endif
 
@@ -410,20 +411,20 @@ int irq_select_affinity_usr(unsigned int irq, struct cpumask *mask)
        int ret;
 
        raw_spin_lock_irqsave(&desc->lock, flags);
-       ret = setup_affinity(irq, desc, mask);
+       ret = setup_affinity(desc, mask);
        raw_spin_unlock_irqrestore(&desc->lock, flags);
        return ret;
 }
 
 #else
 static inline int
-setup_affinity(unsigned int irq, struct irq_desc *desc, struct cpumask *mask)
+setup_affinity(struct irq_desc *desc, struct cpumask *mask)
 {
        return 0;
 }
 #endif
 
-void __disable_irq(struct irq_desc *desc, unsigned int irq)
+void __disable_irq(struct irq_desc *desc)
 {
        if (!desc->depth++)
                irq_disable(desc);
@@ -436,7 +437,7 @@ static int __disable_irq_nosync(unsigned int irq)
 
        if (!desc)
                return -EINVAL;
-       __disable_irq(desc, irq);
+       __disable_irq(desc);
        irq_put_desc_busunlock(desc, flags);
        return 0;
 }
@@ -503,12 +504,13 @@ bool disable_hardirq(unsigned int irq)
 }
 EXPORT_SYMBOL_GPL(disable_hardirq);
 
-void __enable_irq(struct irq_desc *desc, unsigned int irq)
+void __enable_irq(struct irq_desc *desc)
 {
        switch (desc->depth) {
        case 0:
  err_out:
-               WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);
+               WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n",
+                    irq_desc_get_irq(desc));
                break;
        case 1: {
                if (desc->istate & IRQS_SUSPENDED)
@@ -516,7 +518,7 @@ void __enable_irq(struct irq_desc *desc, unsigned int irq)
                /* Prevent probing on this irq: */
                irq_settings_set_noprobe(desc);
                irq_enable(desc);
-               check_irq_resend(desc, irq);
+               check_irq_resend(desc);
                /* fall-through */
        }
        default:
@@ -546,7 +548,7 @@ void enable_irq(unsigned int irq)
                 KERN_ERR "enable_irq before setup/request_irq: irq %u\n", irq))
                goto out;
 
-       __enable_irq(desc, irq);
+       __enable_irq(desc);
 out:
        irq_put_desc_busunlock(desc, flags);
 }
@@ -637,8 +639,7 @@ int can_request_irq(unsigned int irq, unsigned long irqflags)
        return canrequest;
 }
 
-int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
-                     unsigned long flags)
+int __irq_set_trigger(struct irq_desc *desc, unsigned long flags)
 {
        struct irq_chip *chip = desc->irq_data.chip;
        int ret, unmask = 0;
@@ -648,7 +649,8 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
                 * IRQF_TRIGGER_* but the PIC does not support multiple
                 * flow-types?
                 */
-               pr_debug("No set_type function for IRQ %d (%s)\n", irq,
+               pr_debug("No set_type function for IRQ %d (%s)\n",
+                        irq_desc_get_irq(desc),
                         chip ? (chip->name ? : "unknown") : "unknown");
                return 0;
        }
@@ -685,7 +687,7 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
                break;
        default:
                pr_err("Setting trigger mode %lu for irq %u failed (%pF)\n",
-                      flags, irq, chip->irq_set_type);
+                      flags, irq_desc_get_irq(desc), chip->irq_set_type);
        }
        if (unmask)
                unmask_irq(desc);
@@ -1221,8 +1223,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 
                /* Setup the type (level, edge polarity) if configured: */
                if (new->flags & IRQF_TRIGGER_MASK) {
-                       ret = __irq_set_trigger(desc, irq,
-                                       new->flags & IRQF_TRIGGER_MASK);
+                       ret = __irq_set_trigger(desc,
+                                               new->flags & IRQF_TRIGGER_MASK);
 
                        if (ret)
                                goto out_mask;
@@ -1253,7 +1255,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
                }
 
                /* Set default affinity mask once everything is setup */
-               setup_affinity(irq, desc, mask);
+               setup_affinity(desc, mask);
 
        } else if (new->flags & IRQF_TRIGGER_MASK) {
                unsigned int nmsk = new->flags & IRQF_TRIGGER_MASK;
@@ -1280,7 +1282,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
         */
        if (shared && (desc->istate & IRQS_SPURIOUS_DISABLED)) {
                desc->istate &= ~IRQS_SPURIOUS_DISABLED;
-               __enable_irq(desc, irq);
+               __enable_irq(desc);
        }
 
        raw_spin_unlock_irqrestore(&desc->lock, flags);
@@ -1650,7 +1652,7 @@ void enable_percpu_irq(unsigned int irq, unsigned int type)
        if (type != IRQ_TYPE_NONE) {
                int ret;
 
-               ret = __irq_set_trigger(desc, irq, type);
+               ret = __irq_set_trigger(desc, type);
 
                if (ret) {
                        WARN(1, "failed to set type for IRQ%d\n", irq);
@@ -1875,6 +1877,7 @@ int irq_get_irqchip_state(unsigned int irq, enum irqchip_irq_state which,
        irq_put_desc_busunlock(desc, flags);
        return err;
 }
+EXPORT_SYMBOL_GPL(irq_get_irqchip_state);
 
 /**
  *     irq_set_irqchip_state - set the state of a forwarded interrupt.
@@ -1920,3 +1923,4 @@ int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which,
        irq_put_desc_busunlock(desc, flags);
        return err;
 }
+EXPORT_SYMBOL_GPL(irq_set_irqchip_state);
index 7bf1f1bbb7fa5620a270ca1d42d9d54e54b61288..7e6512b9dc1ff2682394cdd0fea9a8c6d01cf6e9 100644 (file)
 /* Temparory solution for building, will be removed later */
 #include <linux/pci.h>
 
+struct msi_desc *alloc_msi_entry(struct device *dev)
+{
+       struct msi_desc *desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+       if (!desc)
+               return NULL;
+
+       INIT_LIST_HEAD(&desc->list);
+       desc->dev = dev;
+
+       return desc;
+}
+
+void free_msi_entry(struct msi_desc *entry)
+{
+       kfree(entry);
+}
+
 void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 {
        *msg = entry->msg;
index d22786a6dbde92eec5cc6b17a198cf309328b27a..21c62617a35a6dae316b22221b3b4896317faedd 100644 (file)
@@ -68,7 +68,7 @@ void irq_pm_remove_action(struct irq_desc *desc, struct irqaction *action)
                desc->cond_suspend_depth--;
 }
 
-static bool suspend_device_irq(struct irq_desc *desc, int irq)
+static bool suspend_device_irq(struct irq_desc *desc)
 {
        if (!desc->action || desc->no_suspend_depth)
                return false;
@@ -85,7 +85,7 @@ static bool suspend_device_irq(struct irq_desc *desc, int irq)
        }
 
        desc->istate |= IRQS_SUSPENDED;
-       __disable_irq(desc, irq);
+       __disable_irq(desc);
 
        /*
         * Hardware which has no wakeup source configuration facility
@@ -126,7 +126,7 @@ void suspend_device_irqs(void)
                if (irq_settings_is_nested_thread(desc))
                        continue;
                raw_spin_lock_irqsave(&desc->lock, flags);
-               sync = suspend_device_irq(desc, irq);
+               sync = suspend_device_irq(desc);
                raw_spin_unlock_irqrestore(&desc->lock, flags);
 
                if (sync)
@@ -135,7 +135,7 @@ void suspend_device_irqs(void)
 }
 EXPORT_SYMBOL_GPL(suspend_device_irqs);
 
-static void resume_irq(struct irq_desc *desc, int irq)
+static void resume_irq(struct irq_desc *desc)
 {
        irqd_clear(&desc->irq_data, IRQD_WAKEUP_ARMED);
 
@@ -150,7 +150,7 @@ static void resume_irq(struct irq_desc *desc, int irq)
        desc->depth++;
 resume:
        desc->istate &= ~IRQS_SUSPENDED;
-       __enable_irq(desc, irq);
+       __enable_irq(desc);
 }
 
 static void resume_irqs(bool want_early)
@@ -169,7 +169,7 @@ static void resume_irqs(bool want_early)
                        continue;
 
                raw_spin_lock_irqsave(&desc->lock, flags);
-               resume_irq(desc, irq);
+               resume_irq(desc);
                raw_spin_unlock_irqrestore(&desc->lock, flags);
        }
 }
index 7a5237a1bce5b5626d74cdb377f8e5a900d06f7a..dd95f44f99b226d8f44f3a2a3ba5284e2f6ecdf5 100644 (file)
@@ -53,7 +53,7 @@ static DECLARE_TASKLET(resend_tasklet, resend_irqs, 0);
  *
  * Is called with interrupts disabled and desc->lock held.
  */
-void check_irq_resend(struct irq_desc *desc, unsigned int irq)
+void check_irq_resend(struct irq_desc *desc)
 {
        /*
         * We do not resend level type interrupts. Level type
@@ -74,6 +74,8 @@ void check_irq_resend(struct irq_desc *desc, unsigned int irq)
                if (!desc->irq_data.chip->irq_retrigger ||
                    !desc->irq_data.chip->irq_retrigger(&desc->irq_data)) {
 #ifdef CONFIG_HARDIRQS_SW_RESEND
+                       unsigned int irq = irq_desc_get_irq(desc);
+
                        /*
                         * If the interrupt is running in the thread
                         * context of the parent irq we need to be
index e2514b0e439e942e19245558e0fad10918f84371..32144175458d77d39dc65353770aa187818dfe6f 100644 (file)
@@ -60,7 +60,7 @@ bool irq_wait_for_poll(struct irq_desc *desc)
 /*
  * Recovery handler for misrouted interrupts.
  */
-static int try_one_irq(int irq, struct irq_desc *desc, bool force)
+static int try_one_irq(struct irq_desc *desc, bool force)
 {
        irqreturn_t ret = IRQ_NONE;
        struct irqaction *action;
@@ -133,7 +133,7 @@ static int misrouted_irq(int irq)
                if (i == irq)   /* Already tried */
                        continue;
 
-               if (try_one_irq(i, desc, false))
+               if (try_one_irq(desc, false))
                        ok = 1;
        }
 out:
@@ -164,7 +164,7 @@ static void poll_spurious_irqs(unsigned long dummy)
                        continue;
 
                local_irq_disable();
-               try_one_irq(i, desc, true);
+               try_one_irq(desc, true);
                local_irq_enable();
        }
 out:
@@ -188,10 +188,9 @@ static inline int bad_action_ret(irqreturn_t action_ret)
  * (The other 100-of-100,000 interrupts may have been a correctly
  *  functioning device sharing an IRQ with the failing one)
  */
-static void
-__report_bad_irq(unsigned int irq, struct irq_desc *desc,
-                irqreturn_t action_ret)
+static void __report_bad_irq(struct irq_desc *desc, irqreturn_t action_ret)
 {
+       unsigned int irq = irq_desc_get_irq(desc);
        struct irqaction *action;
        unsigned long flags;
 
@@ -224,14 +223,13 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc,
        raw_spin_unlock_irqrestore(&desc->lock, flags);
 }
 
-static void
-report_bad_irq(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret)
+static void report_bad_irq(struct irq_desc *desc, irqreturn_t action_ret)
 {
        static int count = 100;
 
        if (count > 0) {
                count--;
-               __report_bad_irq(irq, desc, action_ret);
+               __report_bad_irq(desc, action_ret);
        }
 }
 
@@ -272,15 +270,16 @@ try_misrouted_irq(unsigned int irq, struct irq_desc *desc,
 
 #define SPURIOUS_DEFERRED      0x80000000
 
-void note_interrupt(unsigned int irq, struct irq_desc *desc,
-                   irqreturn_t action_ret)
+void note_interrupt(struct irq_desc *desc, irqreturn_t action_ret)
 {
+       unsigned int irq;
+
        if (desc->istate & IRQS_POLL_INPROGRESS ||
            irq_settings_is_polled(desc))
                return;
 
        if (bad_action_ret(action_ret)) {
-               report_bad_irq(irq, desc, action_ret);
+               report_bad_irq(desc, action_ret);
                return;
        }
 
@@ -398,6 +397,7 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
                desc->last_unhandled = jiffies;
        }
 
+       irq = irq_desc_get_irq(desc);
        if (unlikely(try_misrouted_irq(irq, desc, action_ret))) {
                int ok = misrouted_irq(irq);
                if (action_ret == IRQ_NONE)
@@ -413,7 +413,7 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
                /*
                 * The interrupt is stuck
                 */
-               __report_bad_irq(irq, desc, action_ret);
+               __report_bad_irq(desc, action_ret);
                /*
                 * Now kill the IRQ
                 */