Linus,

please pull the latest irq-core-for-linus git tree from:

   git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq-core-for-linus

The irq department delivers:

    - A new core infrastructure to allow better management of multi-queue
      devices (interrupt spreading, node aware descriptor allocation ...).
    
    - A new interrupt flow handler to support the new fangled Intel VMD
      devices.

    - Yet another new interrupt controller driver.

    - A series of fixes which addresses sparse warnings, missing includes,
      missing static declarations etc. from Ben Dooks.

    - A fix for the error handling in the hierarchical domain allocation code.

    - The usual pile of small updates to core and driver code.

Thanks,

        tglx

------------------>
Alexander Popov (1):
      irqdomain: Fix irq_domain_alloc_irqs_recursive() error handling

Ben Dooks (11):
      irqchip/sirfsoc: Fix sparse warnings on __iomem
      irqchip/tegra: Fix sparse warnings on __iomem
      irqchip/armada-370-xp: Make syscore_ops static
      irqchip/bcm2836: Make bcm2836_smp_boot_secondary static
      irqchip/bcm7120-l2: Make probe functions static
      irqchip/brcmstb-l2: Make of probe function static
      irqchip/gic-v2m: Fix missing include of <linux/irqchip/arm-gic.h>
      irqchip/omap-intc: Fix missing <linux/irqchip/irq-omap-intc.h> include
      irqchip/vic: Make vic_syscore_ops and vic_of_init static
      irqchip/exynos-combiner: Fix usage of __raw IO
      irqchip/s3c24xx: Fixup IO accessors for big endian

Benjamin Herrenschmidt (1):
      irqchip/aspeed-vic: Add irq controller for Aspeed

Christoph Hellwig (1):
      genirq: Add a helper to spread an affinity mask for MSI/MSI-X vectors

Eric Anholt (1):
      irqchip: bcm2835: Avoid arch/arm-specific handle_IRQ

Harvey Hunt (1):
      irqchip/mips-gic: Populate irq_domain names

Jianyu Zhan (1):
      genirq: Remove redundant NULL check of irq_desc

Joel Stanley (1):
      doc/devicetree: Add Aspeed VIC bindings

John Kacur (1):
      irq/Documentation: Correct result of echnoing 5 to smp_affinity

Jon Hunter (10):
      irqdomain: Fix handling of type settings for existing mappings
      genirq: Look-up trigger type if not specified by caller
      irqdomain: Don't set type when mapping an IRQ
      genirq: Add runtime power management support for IRQ chips
      irqchip/gic: Isolate early GIC initialisation code
      irqchip/gic: Add helper function for chip initialisation
      irqchip/gic: Prepare for adding platform driver
      dt-bindings: arm-gic: Add documentation for Tegra210 AGIC
      irqchip/gic: Add platform driver for non-root GICs that require RPM
      irqdomain: Fix disposal of mappings for interrupt hierarchies

Keith Busch (2):
      genirq: Add untracked irq handler
      x86/PCI/VMD: Use untracked irq handler

Marc Zyngier (1):
      genirq: Look-up percpu trigger type if not specified by caller

Shanker Donthineni (5):
      irqchip/gicv3-its: Introduce two helper functions for accessing BASERn
      irqchip/gicv3-its: Add a new function for parsing device table BASERn
      irqchip/gicv3-its: Split its_alloc_tables() into two functions
      irqchip/gicv3-its: Remove an unused argument 'node_name'
      irqchip/gicv3-its: Implement two-level(indirect) device table support

Thomas Gleixner (7):
      genirq/msi: Remove unused MSI_FLAG_IDENTITY_MAP
      genirq: Introduce IRQD_AFFINITY_MANAGED flag
      genirq: Add affinity hint to irq allocation
      genirq: Use affinity hint in irqdesc allocation
      genirq/msi: Make use of affinity aware allocations
      genirq/msi: Fix broken debug output
      MAINTAINERS: Remove Jiang Liu from irq domains

Vincent Stehle (1):
      genirq: Fix missing irq allocation affinity hint

Weongyo Jeong (1):
      genirq: Remove unnecessary memset() calls


 .../bindings/interrupt-controller/arm,gic.txt      |   3 +-
 .../interrupt-controller/aspeed,ast2400-vic.txt    |  22 ++
 Documentation/filesystems/proc.txt                 |   2 +-
 MAINTAINERS                                        |   1 -
 arch/sparc/kernel/irq_64.c                         |   2 +-
 arch/x86/kernel/apic/io_apic.c                     |   5 +-
 arch/x86/pci/vmd.c                                 |   2 +-
 drivers/irqchip/Kconfig                            |   6 +
 drivers/irqchip/Makefile                           |   2 +
 drivers/irqchip/exynos-combiner.c                  |  14 +-
 drivers/irqchip/irq-armada-370-xp.c                |   2 +-
 drivers/irqchip/irq-aspeed-vic.c                   | 230 ++++++++++++
 drivers/irqchip/irq-bcm2835.c                      |   3 +-
 drivers/irqchip/irq-bcm2836.c                      |   6 +-
 drivers/irqchip/irq-bcm7120-l2.c                   |  10 +-
 drivers/irqchip/irq-brcmstb-l2.c                   |   4 +-
 drivers/irqchip/irq-gic-common.c                   |   4 +-
 drivers/irqchip/irq-gic-pm.c                       | 184 ++++++++++
 drivers/irqchip/irq-gic-v2m.c                      |   1 +
 drivers/irqchip/irq-gic-v3-its.c                   | 404 +++++++++++++--------
 drivers/irqchip/irq-gic.c                          | 134 +++++--
 drivers/irqchip/irq-mips-gic.c                     |   3 +
 drivers/irqchip/irq-omap-intc.c                    |   2 +
 drivers/irqchip/irq-s3c24xx.c                      |  36 +-
 drivers/irqchip/irq-sirfsoc.c                      |  11 +-
 drivers/irqchip/irq-tegra.c                        |   4 +-
 drivers/irqchip/irq-vic.c                          |   5 +-
 include/linux/interrupt.h                          |   8 +
 include/linux/irq.h                                |  16 +-
 include/linux/irqchip/arm-gic-v3.h                 |   4 +
 include/linux/irqchip/arm-gic.h                    |  11 +
 include/linux/irqdomain.h                          |  12 +-
 include/linux/msi.h                                |   8 +-
 kernel/irq/Makefile                                |   1 +
 kernel/irq/affinity.c                              |  61 ++++
 kernel/irq/chip.c                                  |  83 +++++
 kernel/irq/handle.c                                |  18 +-
 kernel/irq/internals.h                             |   4 +
 kernel/irq/ipi.c                                   |   4 +-
 kernel/irq/irqdesc.c                               |  63 +++-
 kernel/irq/irqdomain.c                             |  94 +++--
 kernel/irq/manage.c                                |  73 +++-
 kernel/irq/msi.c                                   |  12 +-
 kernel/irq/proc.c                                  |  11 +-
 44 files changed, 1265 insertions(+), 320 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt
 create mode 100644 drivers/irqchip/irq-aspeed-vic.c
 create mode 100644 drivers/irqchip/irq-gic-pm.c
 create mode 100644 kernel/irq/affinity.c

diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt 
b/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
index 793c20ff8fcc..5393e2a45a42 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
@@ -21,6 +21,7 @@ Main node required properties:
        "arm,pl390"
        "arm,tc11mp-gic"
        "brcm,brahma-b15-gic"
+       "nvidia,tegra210-agic"
        "qcom,msm-8660-qgic"
        "qcom,msm-qgic2"
 - interrupt-controller : Identifies the node as an interrupt controller
@@ -68,7 +69,7 @@ Optional
        "ic_clk" (for "arm,arm11mp-gic")
        "PERIPHCLKEN" (for "arm,cortex-a15-gic")
        "PERIPHCLK", "PERIPHCLKEN" (for "arm,cortex-a9-gic")
-       "clk" (for "arm,gic-400")
+       "clk" (for "arm,gic-400" and "nvidia,tegra210")
        "gclk" (for "arm,pl390")
 
 - power-domains : A phandle and PM domain specifier as defined by bindings of
diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt 
b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt
new file mode 100644
index 000000000000..6c6e85324b9d
--- /dev/null
+++ 
b/Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-vic.txt
@@ -0,0 +1,22 @@
+Aspeed Vectored Interrupt Controller
+
+These bindings are for the Aspeed AST2400 interrupt controller register layout.
+The SoC has an legacy register layout, but this driver does not support that
+mode of operation.
+
+Required properties:
+
+- compatible : should be "aspeed,ast2400-vic".
+
+- 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.
+
+Example:
+
+ vic: interrupt-controller@1e6c0080 {
+      compatible = "aspeed,ast2400-vic";
+      interrupt-controller;
+      #interrupt-cells = <1>;
+      reg = <0x1e6c0080 0x80>;
+ };
diff --git a/Documentation/filesystems/proc.txt 
b/Documentation/filesystems/proc.txt
index e8d00759bfa5..5b61eeae3f6e 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -725,7 +725,7 @@ IRQ, you can set it by doing:
   > echo 1 > /proc/irq/10/smp_affinity
 
 This means that only the first CPU will handle the IRQ, but you can also echo
-5 which means that only the first and fourth CPU can handle the IRQ.
+5 which means that only the first and third CPU can handle the IRQ.
 
 The contents of each smp_affinity file is the same by default:
 
diff --git a/MAINTAINERS b/MAINTAINERS
index 1209323b7e43..6ec72cff87b1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6235,7 +6235,6 @@ F:        
Documentation/devicetree/bindings/interrupt-controller/
 F:     drivers/irqchip/
 
 IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
-M:     Jiang Liu <[email protected]>
 M:     Marc Zyngier <[email protected]>
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index e22416ce56ea..34a7930b76ef 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -242,7 +242,7 @@ unsigned int irq_alloc(unsigned int dev_handle, unsigned 
int dev_ino)
 {
        int irq;
 
-       irq = __irq_alloc_descs(-1, 1, 1, numa_node_id(), NULL);
+       irq = __irq_alloc_descs(-1, 1, 1, numa_node_id(), NULL, NULL);
        if (irq <= 0)
                goto out;
 
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 446702ed99dc..7c4f90dd4c2a 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -981,7 +981,7 @@ static int alloc_irq_from_domain(struct irq_domain *domain, 
int ioapic, u32 gsi,
 
        return __irq_domain_alloc_irqs(domain, irq, 1,
                                       ioapic_alloc_attr_node(info),
-                                      info, legacy);
+                                      info, legacy, NULL);
 }
 
 /*
@@ -1014,7 +1014,8 @@ static int alloc_isa_irq_from_domain(struct irq_domain 
*domain,
                                          info->ioapic_pin))
                        return -ENOMEM;
        } else {
-               irq = __irq_domain_alloc_irqs(domain, irq, 1, node, info, true);
+               irq = __irq_domain_alloc_irqs(domain, irq, 1, node, info, true,
+                                             NULL);
                if (irq >= 0) {
                        irq_data = irq_domain_get_irq_data(domain, irq);
                        data = irq_data->chip_data;
diff --git a/arch/x86/pci/vmd.c b/arch/x86/pci/vmd.c
index 7792aba266df..613cac7395c4 100644
--- a/arch/x86/pci/vmd.c
+++ b/arch/x86/pci/vmd.c
@@ -195,7 +195,7 @@ static int vmd_msi_init(struct irq_domain *domain, struct 
msi_domain_info *info,
        vmdirq->virq = virq;
 
        irq_domain_set_info(domain, virq, vmdirq->irq->vmd_vector, info->chip,
-                           vmdirq, handle_simple_irq, vmd, NULL);
+                           vmdirq, handle_untracked_irq, vmd, NULL);
        return 0;
 }
 
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index fa33c50b0e5a..5495a5ba8039 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -8,6 +8,12 @@ config ARM_GIC
        select IRQ_DOMAIN_HIERARCHY
        select MULTI_IRQ_HANDLER
 
+config ARM_GIC_PM
+       bool
+       depends on PM
+       select ARM_GIC
+       select PM_CLK
+
 config ARM_GIC_MAX_NR
        int
        default 2 if ARCH_REALVIEW
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 38853a187607..4c203b6b8163 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_ARCH_SUNXI)              += irq-sun4i.o
 obj-$(CONFIG_ARCH_SUNXI)               += irq-sunxi-nmi.o
 obj-$(CONFIG_ARCH_SPEAR3XX)            += spear-shirq.o
 obj-$(CONFIG_ARM_GIC)                  += irq-gic.o irq-gic-common.o
+obj-$(CONFIG_ARM_GIC_PM)               += irq-gic-pm.o
 obj-$(CONFIG_REALVIEW_DT)              += irq-gic-realview.o
 obj-$(CONFIG_ARM_GIC_V2M)              += irq-gic-v2m.o
 obj-$(CONFIG_ARM_GIC_V3)               += irq-gic-v3.o irq-gic-common.o
@@ -69,3 +70,4 @@ obj-$(CONFIG_PIC32_EVIC)              += irq-pic32-evic.o
 obj-$(CONFIG_MVEBU_ODMI)               += irq-mvebu-odmi.o
 obj-$(CONFIG_LS_SCFG_MSI)              += irq-ls-scfg-msi.o
 obj-$(CONFIG_EZNPS_GIC)                        += irq-eznps.o
+obj-$(CONFIG_ARCH_ASPEED)              += irq-aspeed-vic.o
diff --git a/drivers/irqchip/exynos-combiner.c 
b/drivers/irqchip/exynos-combiner.c
index ead15be2d20a..b78a169c9c83 100644
--- a/drivers/irqchip/exynos-combiner.c
+++ b/drivers/irqchip/exynos-combiner.c
@@ -55,14 +55,14 @@ static void combiner_mask_irq(struct irq_data *data)
 {
        u32 mask = 1 << (data->hwirq % 32);
 
-       __raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
+       writel_relaxed(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
 }
 
 static void combiner_unmask_irq(struct irq_data *data)
 {
        u32 mask = 1 << (data->hwirq % 32);
 
-       __raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
+       writel_relaxed(mask, combiner_base(data) + COMBINER_ENABLE_SET);
 }
 
 static void combiner_handle_cascade_irq(struct irq_desc *desc)
@@ -75,7 +75,7 @@ static void combiner_handle_cascade_irq(struct irq_desc *desc)
        chained_irq_enter(chip, desc);
 
        spin_lock(&irq_controller_lock);
-       status = __raw_readl(chip_data->base + COMBINER_INT_STATUS);
+       status = readl_relaxed(chip_data->base + COMBINER_INT_STATUS);
        spin_unlock(&irq_controller_lock);
        status &= chip_data->irq_mask;
 
@@ -135,7 +135,7 @@ static void __init combiner_init_one(struct 
combiner_chip_data *combiner_data,
        combiner_data->parent_irq = irq;
 
        /* Disable all interrupts */
-       __raw_writel(combiner_data->irq_mask, base + COMBINER_ENABLE_CLEAR);
+       writel_relaxed(combiner_data->irq_mask, base + COMBINER_ENABLE_CLEAR);
 }
 
 static int combiner_irq_domain_xlate(struct irq_domain *d,
@@ -218,7 +218,7 @@ static int combiner_suspend(void)
 
        for (i = 0; i < max_nr; i++)
                combiner_data[i].pm_save =
-                       __raw_readl(combiner_data[i].base + 
COMBINER_ENABLE_SET);
+                       readl_relaxed(combiner_data[i].base + 
COMBINER_ENABLE_SET);
 
        return 0;
 }
@@ -235,9 +235,9 @@ static void combiner_resume(void)
        int i;
 
        for (i = 0; i < max_nr; i++) {
-               __raw_writel(combiner_data[i].irq_mask,
+               writel_relaxed(combiner_data[i].irq_mask,
                             combiner_data[i].base + COMBINER_ENABLE_CLEAR);
-               __raw_writel(combiner_data[i].pm_save,
+               writel_relaxed(combiner_data[i].pm_save,
                             combiner_data[i].base + COMBINER_ENABLE_SET);
        }
 }
diff --git a/drivers/irqchip/irq-armada-370-xp.c 
b/drivers/irqchip/irq-armada-370-xp.c
index e7dc6cbda2a1..7c42b1d13faf 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -541,7 +541,7 @@ static void armada_370_xp_mpic_resume(void)
                writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
 }
 
-struct syscore_ops armada_370_xp_mpic_syscore_ops = {
+static struct syscore_ops armada_370_xp_mpic_syscore_ops = {
        .suspend        = armada_370_xp_mpic_suspend,
        .resume         = armada_370_xp_mpic_resume,
 };
diff --git a/drivers/irqchip/irq-aspeed-vic.c b/drivers/irqchip/irq-aspeed-vic.c
new file mode 100644
index 000000000000..d24451d5bf8a
--- /dev/null
+++ b/drivers/irqchip/irq-aspeed-vic.c
@@ -0,0 +1,230 @@
+/*
+ *  Copyright (C) 2015 - Ben Herrenschmidt, IBM Corp.
+ *
+ *  Driver for Aspeed "new" VIC as found in SoC generation 3 and later
+ *
+ *  Based on irq-vic.c:
+ *
+ *  Copyright (C) 1999 - 2003 ARM Limited
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * 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/export.h>
+#include <linux/init.h>
+#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>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/syscore_ops.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+
+#include <asm/exception.h>
+#include <asm/irq.h>
+
+/* These definitions correspond to the "new mapping" of the
+ * register set that interleaves "high" and "low". The offsets
+ * below are for the "low" register, add 4 to get to the high one
+ */
+#define AVIC_IRQ_STATUS                0x00
+#define AVIC_FIQ_STATUS                0x08
+#define AVIC_RAW_STATUS                0x10
+#define AVIC_INT_SELECT                0x18
+#define AVIC_INT_ENABLE                0x20
+#define AVIC_INT_ENABLE_CLR    0x28
+#define AVIC_INT_TRIGGER       0x30
+#define AVIC_INT_TRIGGER_CLR   0x38
+#define AVIC_INT_SENSE         0x40
+#define AVIC_INT_DUAL_EDGE     0x48
+#define AVIC_INT_EVENT         0x50
+#define AVIC_EDGE_CLR          0x58
+#define AVIC_EDGE_STATUS       0x60
+
+#define NUM_IRQS               64
+
+struct aspeed_vic {
+       void __iomem            *base;
+       u32                     edge_sources[2];
+       struct irq_domain       *dom;
+};
+static struct aspeed_vic *system_avic;
+
+static void vic_init_hw(struct aspeed_vic *vic)
+{
+       u32 sense;
+
+       /* Disable all interrupts */
+       writel(0xffffffff, vic->base + AVIC_INT_ENABLE_CLR);
+       writel(0xffffffff, vic->base + AVIC_INT_ENABLE_CLR + 4);
+
+       /* Make sure no soft trigger is on */
+       writel(0xffffffff, vic->base + AVIC_INT_TRIGGER_CLR);
+       writel(0xffffffff, vic->base + AVIC_INT_TRIGGER_CLR + 4);
+
+       /* Set everything to be IRQ */
+       writel(0, vic->base + AVIC_INT_SELECT);
+       writel(0, vic->base + AVIC_INT_SELECT + 4);
+
+       /* Some interrupts have a programable high/low level trigger
+        * (4 GPIO direct inputs), for now we assume this was configured
+        * by firmware. We read which ones are edge now.
+        */
+       sense = readl(vic->base + AVIC_INT_SENSE);
+       vic->edge_sources[0] = ~sense;
+       sense = readl(vic->base + AVIC_INT_SENSE + 4);
+       vic->edge_sources[1] = ~sense;
+
+       /* Clear edge detection latches */
+       writel(0xffffffff, vic->base + AVIC_EDGE_CLR);
+       writel(0xffffffff, vic->base + AVIC_EDGE_CLR + 4);
+}
+
+static void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
+{
+       struct aspeed_vic *vic = system_avic;
+       u32 stat, irq;
+
+       for (;;) {
+               irq = 0;
+               stat = readl_relaxed(vic->base + AVIC_IRQ_STATUS);
+               if (!stat) {
+                       stat = readl_relaxed(vic->base + AVIC_IRQ_STATUS + 4);
+                       irq = 32;
+               }
+               if (stat == 0)
+                       break;
+               irq += ffs(stat) - 1;
+               handle_domain_irq(vic->dom, irq, regs);
+       }
+}
+
+static void avic_ack_irq(struct irq_data *d)
+{
+       struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
+       unsigned int sidx = d->hwirq >> 5;
+       unsigned int sbit = 1u << (d->hwirq & 0x1f);
+
+       /* Clear edge latch for edge interrupts, nop for level */
+       if (vic->edge_sources[sidx] & sbit)
+               writel(sbit, vic->base + AVIC_EDGE_CLR + sidx * 4);
+}
+
+static void avic_mask_irq(struct irq_data *d)
+{
+       struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
+       unsigned int sidx = d->hwirq >> 5;
+       unsigned int sbit = 1u << (d->hwirq & 0x1f);
+
+       writel(sbit, vic->base + AVIC_INT_ENABLE_CLR + sidx * 4);
+}
+
+static void avic_unmask_irq(struct irq_data *d)
+{
+       struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
+       unsigned int sidx = d->hwirq >> 5;
+       unsigned int sbit = 1u << (d->hwirq & 0x1f);
+
+       writel(sbit, vic->base + AVIC_INT_ENABLE + sidx * 4);
+}
+
+/* For level irq, faster than going through a nop "ack" and mask */
+static void avic_mask_ack_irq(struct irq_data *d)
+{
+       struct aspeed_vic *vic = irq_data_get_irq_chip_data(d);
+       unsigned int sidx = d->hwirq >> 5;
+       unsigned int sbit = 1u << (d->hwirq & 0x1f);
+
+       /* First mask */
+       writel(sbit, vic->base + AVIC_INT_ENABLE_CLR + sidx * 4);
+
+       /* Then clear edge latch for edge interrupts */
+       if (vic->edge_sources[sidx] & sbit)
+               writel(sbit, vic->base + AVIC_EDGE_CLR + sidx * 4);
+}
+
+static struct irq_chip avic_chip = {
+       .name           = "AVIC",
+       .irq_ack        = avic_ack_irq,
+       .irq_mask       = avic_mask_irq,
+       .irq_unmask     = avic_unmask_irq,
+       .irq_mask_ack   = avic_mask_ack_irq,
+};
+
+static int avic_map(struct irq_domain *d, unsigned int irq,
+                   irq_hw_number_t hwirq)
+{
+       struct aspeed_vic *vic = d->host_data;
+       unsigned int sidx = hwirq >> 5;
+       unsigned int sbit = 1u << (hwirq & 0x1f);
+
+       /* Check if interrupt exists */
+       if (sidx > 1)
+               return -EPERM;
+
+       if (vic->edge_sources[sidx] & sbit)
+               irq_set_chip_and_handler(irq, &avic_chip, handle_edge_irq);
+       else
+               irq_set_chip_and_handler(irq, &avic_chip, handle_level_irq);
+       irq_set_chip_data(irq, vic);
+       irq_set_probe(irq);
+       return 0;
+}
+
+static struct irq_domain_ops avic_dom_ops = {
+       .map = avic_map,
+       .xlate = irq_domain_xlate_onetwocell,
+};
+
+static int __init avic_of_init(struct device_node *node,
+                              struct device_node *parent)
+{
+       void __iomem *regs;
+       struct aspeed_vic *vic;
+
+       if (WARN(parent, "non-root Aspeed VIC not supported"))
+               return -EINVAL;
+       if (WARN(system_avic, "duplicate Aspeed VIC not supported"))
+               return -EINVAL;
+
+       regs = of_iomap(node, 0);
+       if (WARN_ON(!regs))
+               return -EIO;
+
+       vic = kzalloc(sizeof(struct aspeed_vic), GFP_KERNEL);
+       if (WARN_ON(!vic)) {
+               iounmap(regs);
+               return -ENOMEM;
+       }
+       vic->base = regs;
+
+       /* Initialize soures, all masked */
+       vic_init_hw(vic);
+
+       /* Ready to receive interrupts */
+       system_avic = vic;
+       set_handle_irq(avic_handle_irq);
+
+       /* Register our domain */
+       vic->dom = irq_domain_add_simple(node, NUM_IRQS, 0,
+                                        &avic_dom_ops, vic);
+
+       return 0;
+}
+
+IRQCHIP_DECLARE(aspeed_new_vic, "aspeed,ast2400-vic", avic_of_init);
diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c
index bf9cc5f2e839..44d7c38dde47 100644
--- a/drivers/irqchip/irq-bcm2835.c
+++ b/drivers/irqchip/irq-bcm2835.c
@@ -52,7 +52,6 @@
 #include <linux/irqdomain.h>
 
 #include <asm/exception.h>
-#include <asm/mach/irq.h>
 
 /* Put the bank and irq (32 bits) into the hwirq */
 #define MAKE_HWIRQ(b, n)       ((b << 5) | (n))
@@ -242,7 +241,7 @@ static void __exception_irq_entry bcm2835_handle_irq(
        u32 hwirq;
 
        while ((hwirq = get_next_armctrl_hwirq()) != ~0)
-               handle_IRQ(irq_linear_revmap(intc.domain, hwirq), regs);
+               handle_domain_irq(intc.domain, hwirq, regs);
 }
 
 static void bcm2836_chained_handle_irq(struct irq_desc *desc)
diff --git a/drivers/irqchip/irq-bcm2836.c b/drivers/irqchip/irq-bcm2836.c
index 72ff1d5c5de6..df1949c0aa23 100644
--- a/drivers/irqchip/irq-bcm2836.c
+++ b/drivers/irqchip/irq-bcm2836.c
@@ -180,7 +180,7 @@ __exception_irq_entry bcm2836_arm_irqchip_handle_irq(struct 
pt_regs *regs)
        } else if (stat) {
                u32 hwirq = ffs(stat) - 1;
 
-               handle_IRQ(irq_linear_revmap(intc.domain, hwirq), regs);
+               handle_domain_irq(intc.domain, hwirq, regs);
        }
 }
 
@@ -224,8 +224,8 @@ static struct notifier_block 
bcm2836_arm_irqchip_cpu_notifier = {
 };
 
 #ifdef CONFIG_ARM
-int __init bcm2836_smp_boot_secondary(unsigned int cpu,
-                                     struct task_struct *idle)
+static int __init bcm2836_smp_boot_secondary(unsigned int cpu,
+                                            struct task_struct *idle)
 {
        unsigned long secondary_startup_phys =
                (unsigned long)virt_to_phys((void *)secondary_startup);
diff --git a/drivers/irqchip/irq-bcm7120-l2.c b/drivers/irqchip/irq-bcm7120-l2.c
index 61b18ab33ad9..0ec92631e23c 100644
--- a/drivers/irqchip/irq-bcm7120-l2.c
+++ b/drivers/irqchip/irq-bcm7120-l2.c
@@ -215,7 +215,7 @@ static int __init bcm7120_l2_intc_iomap_3380(struct 
device_node *dn,
        return 0;
 }
 
-int __init bcm7120_l2_intc_probe(struct device_node *dn,
+static int __init bcm7120_l2_intc_probe(struct device_node *dn,
                                 struct device_node *parent,
                                 int (*iomap_regs_fn)(struct device_node *,
                                        struct bcm7120_l2_intc_data *),
@@ -339,15 +339,15 @@ out_unmap:
        return ret;
 }
 
-int __init bcm7120_l2_intc_probe_7120(struct device_node *dn,
-                                     struct device_node *parent)
+static int __init bcm7120_l2_intc_probe_7120(struct device_node *dn,
+                                            struct device_node *parent)
 {
        return bcm7120_l2_intc_probe(dn, parent, bcm7120_l2_intc_iomap_7120,
                                     "BCM7120 L2");
 }
 
-int __init bcm7120_l2_intc_probe_3380(struct device_node *dn,
-                                     struct device_node *parent)
+static int __init bcm7120_l2_intc_probe_3380(struct device_node *dn,
+                                            struct device_node *parent)
 {
        return bcm7120_l2_intc_probe(dn, parent, bcm7120_l2_intc_iomap_3380,
                                     "BCM3380 L2");
diff --git a/drivers/irqchip/irq-brcmstb-l2.c b/drivers/irqchip/irq-brcmstb-l2.c
index 65cd341f331a..1d4a5b46d9ae 100644
--- a/drivers/irqchip/irq-brcmstb-l2.c
+++ b/drivers/irqchip/irq-brcmstb-l2.c
@@ -112,8 +112,8 @@ static void brcmstb_l2_intc_resume(struct irq_data *d)
        irq_gc_unlock(gc);
 }
 
-int __init brcmstb_l2_intc_of_init(struct device_node *np,
-                                       struct device_node *parent)
+static int __init brcmstb_l2_intc_of_init(struct device_node *np,
+                                         struct device_node *parent)
 {
        unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
        struct brcmstb_l2_intc_data *data;
diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
index 89e7423f0ebb..9ae71804b5dd 100644
--- a/drivers/irqchip/irq-gic-common.c
+++ b/drivers/irqchip/irq-gic-common.c
@@ -90,8 +90,8 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
        return ret;
 }
 
-void __init gic_dist_config(void __iomem *base, int gic_irqs,
-                           void (*sync_access)(void))
+void gic_dist_config(void __iomem *base, int gic_irqs,
+                    void (*sync_access)(void))
 {
        unsigned int i;
 
diff --git a/drivers/irqchip/irq-gic-pm.c b/drivers/irqchip/irq-gic-pm.c
new file mode 100644
index 000000000000..4cbffba3ff13
--- /dev/null
+++ b/drivers/irqchip/irq-gic-pm.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2016 NVIDIA CORPORATION, All Rights Reserved.
+ *
+ * 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/module.h>
+#include <linux/clk.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/irqchip/arm-gic.h>
+#include <linux/platform_device.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+
+struct gic_clk_data {
+       unsigned int num_clocks;
+       const char *const *clocks;
+};
+
+static int gic_runtime_resume(struct device *dev)
+{
+       struct gic_chip_data *gic = dev_get_drvdata(dev);
+       int ret;
+
+       ret = pm_clk_resume(dev);
+       if (ret)
+               return ret;
+
+       /*
+        * On the very first resume, the pointer to the driver data
+        * will be NULL and this is intentional, because we do not
+        * want to restore the GIC on the very first resume. So if
+        * the pointer is not valid just return.
+        */
+       if (!gic)
+               return 0;
+
+       gic_dist_restore(gic);
+       gic_cpu_restore(gic);
+
+       return 0;
+}
+
+static int gic_runtime_suspend(struct device *dev)
+{
+       struct gic_chip_data *gic = dev_get_drvdata(dev);
+
+       gic_dist_save(gic);
+       gic_cpu_save(gic);
+
+       return pm_clk_suspend(dev);
+}
+
+static int gic_get_clocks(struct device *dev, const struct gic_clk_data *data)
+{
+       struct clk *clk;
+       unsigned int i;
+       int ret;
+
+       if (!dev || !data)
+               return -EINVAL;
+
+       ret = pm_clk_create(dev);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < data->num_clocks; i++) {
+               clk = of_clk_get_by_name(dev->of_node, data->clocks[i]);
+               if (IS_ERR(clk)) {
+                       dev_err(dev, "failed to get clock %s\n",
+                               data->clocks[i]);
+                       ret = PTR_ERR(clk);
+                       goto error;
+               }
+
+               ret = pm_clk_add_clk(dev, clk);
+               if (ret) {
+                       dev_err(dev, "failed to add clock at index %d\n", i);
+                       clk_put(clk);
+                       goto error;
+               }
+       }
+
+       return 0;
+
+error:
+       pm_clk_destroy(dev);
+
+       return ret;
+}
+
+static int gic_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       const struct gic_clk_data *data;
+       struct gic_chip_data *gic;
+       int ret, irq;
+
+       data = of_device_get_match_data(&pdev->dev);
+       if (!data) {
+               dev_err(&pdev->dev, "no device match found\n");
+               return -ENODEV;
+       }
+
+       irq = irq_of_parse_and_map(dev->of_node, 0);
+       if (!irq) {
+               dev_err(dev, "no parent interrupt found!\n");
+               return -EINVAL;
+       }
+
+       ret = gic_get_clocks(dev, data);
+       if (ret)
+               goto irq_dispose;
+
+       pm_runtime_enable(dev);
+
+       ret = pm_runtime_get_sync(dev);
+       if (ret < 0)
+               goto rpm_disable;
+
+       ret = gic_of_init_child(dev, &gic, irq);
+       if (ret)
+               goto rpm_put;
+
+       platform_set_drvdata(pdev, gic);
+
+       pm_runtime_put(dev);
+
+       dev_info(dev, "GIC IRQ controller registered\n");
+
+       return 0;
+
+rpm_put:
+       pm_runtime_put_sync(dev);
+rpm_disable:
+       pm_runtime_disable(dev);
+       pm_clk_destroy(dev);
+irq_dispose:
+       irq_dispose_mapping(irq);
+
+       return ret;
+}
+
+static const struct dev_pm_ops gic_pm_ops = {
+       SET_RUNTIME_PM_OPS(gic_runtime_suspend,
+                          gic_runtime_resume, NULL)
+};
+
+static const char * const gic400_clocks[] = {
+       "clk",
+};
+
+static const struct gic_clk_data gic400_data = {
+       .num_clocks = ARRAY_SIZE(gic400_clocks),
+       .clocks = gic400_clocks,
+};
+
+static const struct of_device_id gic_match[] = {
+       { .compatible = "nvidia,tegra210-agic", .data = &gic400_data },
+       {},
+};
+MODULE_DEVICE_TABLE(of, gic_match);
+
+static struct platform_driver gic_driver = {
+       .probe          = gic_probe,
+       .driver         = {
+               .name   = "gic",
+               .of_match_table = gic_match,
+               .pm     = &gic_pm_ops,
+       }
+};
+
+builtin_platform_driver(gic_driver);
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index ad0d2960b664..35eb7ac5d21f 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -24,6 +24,7 @@
 #include <linux/of_pci.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/irqchip/arm-gic.h>
 
 /*
 * MSI_TYPER:
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 5eb1f9e17a98..7ceaba81efb4 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -56,13 +56,14 @@ struct its_collection {
 };
 
 /*
- * The ITS_BASER structure - contains memory information and cached
- * value of BASER register configuration.
+ * The ITS_BASER structure - contains memory information, cached
+ * value of BASER register configuration and ITS page size.
  */
 struct its_baser {
        void            *base;
        u64             val;
        u32             order;
+       u32             psz;
 };
 
 /*
@@ -824,180 +825,241 @@ static const char *its_base_type_string[] = {
        [GITS_BASER_TYPE_RESERVED7]     = "Reserved (7)",
 };
 
-static void its_free_tables(struct its_node *its)
+static u64 its_read_baser(struct its_node *its, struct its_baser *baser)
 {
-       int i;
+       u32 idx = baser - its->tables;
 
-       for (i = 0; i < GITS_BASER_NR_REGS; i++) {
-               if (its->tables[i].base) {
-                       free_pages((unsigned long)its->tables[i].base,
-                                  its->tables[i].order);
-                       its->tables[i].base = NULL;
-               }
-       }
+       return readq_relaxed(its->base + GITS_BASER + (idx << 3));
 }
 
-static int its_alloc_tables(const char *node_name, struct its_node *its)
+static void its_write_baser(struct its_node *its, struct its_baser *baser,
+                           u64 val)
 {
-       int err;
-       int i;
-       int psz = SZ_64K;
-       u64 shr = GITS_BASER_InnerShareable;
-       u64 cache;
-       u64 typer;
-       u32 ids;
+       u32 idx = baser - its->tables;
 
-       if (its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_22375) {
-               /*
-                * erratum 22375: only alloc 8MB table size
-                * erratum 24313: ignore memory access type
-                */
-               cache   = 0;
-               ids     = 0x14;                 /* 20 bits, 8MB */
-       } else {
-               cache   = GITS_BASER_WaWb;
-               typer   = readq_relaxed(its->base + GITS_TYPER);
-               ids     = GITS_TYPER_DEVBITS(typer);
+       writeq_relaxed(val, its->base + GITS_BASER + (idx << 3));
+       baser->val = its_read_baser(its, baser);
+}
+
+static int its_setup_baser(struct its_node *its, struct its_baser *baser,
+                          u64 cache, u64 shr, u32 psz, u32 order,
+                          bool indirect)
+{
+       u64 val = its_read_baser(its, baser);
+       u64 esz = GITS_BASER_ENTRY_SIZE(val);
+       u64 type = GITS_BASER_TYPE(val);
+       u32 alloc_pages;
+       void *base;
+       u64 tmp;
+
+retry_alloc_baser:
+       alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz);
+       if (alloc_pages > GITS_BASER_PAGES_MAX) {
+               pr_warn("ITS@%pa: %s too large, reduce ITS pages %u->%u\n",
+                       &its->phys_base, its_base_type_string[type],
+                       alloc_pages, GITS_BASER_PAGES_MAX);
+               alloc_pages = GITS_BASER_PAGES_MAX;
+               order = get_order(GITS_BASER_PAGES_MAX * psz);
        }
 
-       its->device_ids = ids;
+       base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
+       if (!base)
+               return -ENOMEM;
 
-       for (i = 0; i < GITS_BASER_NR_REGS; i++) {
-               u64 val = readq_relaxed(its->base + GITS_BASER + i * 8);
-               u64 type = GITS_BASER_TYPE(val);
-               u64 entry_size = GITS_BASER_ENTRY_SIZE(val);
-               int order = get_order(psz);
-               int alloc_pages;
-               u64 tmp;
-               void *base;
+retry_baser:
+       val = (virt_to_phys(base)                                |
+               (type << GITS_BASER_TYPE_SHIFT)                  |
+               ((esz - 1) << GITS_BASER_ENTRY_SIZE_SHIFT)       |
+               ((alloc_pages - 1) << GITS_BASER_PAGES_SHIFT)    |
+               cache                                            |
+               shr                                              |
+               GITS_BASER_VALID);
+
+       val |=  indirect ? GITS_BASER_INDIRECT : 0x0;
+
+       switch (psz) {
+       case SZ_4K:
+               val |= GITS_BASER_PAGE_SIZE_4K;
+               break;
+       case SZ_16K:
+               val |= GITS_BASER_PAGE_SIZE_16K;
+               break;
+       case SZ_64K:
+               val |= GITS_BASER_PAGE_SIZE_64K;
+               break;
+       }
 
-               if (type == GITS_BASER_TYPE_NONE)
-                       continue;
+       its_write_baser(its, baser, val);
+       tmp = baser->val;
 
+       if ((val ^ tmp) & GITS_BASER_SHAREABILITY_MASK) {
                /*
-                * Allocate as many entries as required to fit the
-                * range of device IDs that the ITS can grok... The ID
-                * space being incredibly sparse, this results in a
-                * massive waste of memory.
-                *
-                * For other tables, only allocate a single page.
+                * Shareability didn't stick. Just use
+                * whatever the read reported, which is likely
+                * to be the only thing this redistributor
+                * supports. If that's zero, make it
+                * non-cacheable as well.
                 */
-               if (type == GITS_BASER_TYPE_DEVICE) {
-                       /*
-                        * 'order' was initialized earlier to the default page
-                        * granule of the the ITS.  We can't have an allocation
-                        * smaller than that.  If the requested allocation
-                        * is smaller, round up to the default page granule.
-                        */
-                       order = max(get_order((1UL << ids) * entry_size),
-                                   order);
-                       if (order >= MAX_ORDER) {
-                               order = MAX_ORDER - 1;
-                               pr_warn("%s: Device Table too large, reduce its 
page order to %u\n",
-                                       node_name, order);
-                       }
-               }
-
-retry_alloc_baser:
-               alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz);
-               if (alloc_pages > GITS_BASER_PAGES_MAX) {
-                       alloc_pages = GITS_BASER_PAGES_MAX;
-                       order = get_order(GITS_BASER_PAGES_MAX * psz);
-                       pr_warn("%s: Device Table too large, reduce its page 
order to %u (%u pages)\n",
-                               node_name, order, alloc_pages);
+               shr = tmp & GITS_BASER_SHAREABILITY_MASK;
+               if (!shr) {
+                       cache = GITS_BASER_nC;
+                       __flush_dcache_area(base, PAGE_ORDER_TO_SIZE(order));
                }
+               goto retry_baser;
+       }
 
-               base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
-               if (!base) {
-                       err = -ENOMEM;
-                       goto out_free;
-               }
-
-               its->tables[i].base = base;
-               its->tables[i].order = order;
-
-retry_baser:
-               val = (virt_to_phys(base)                                |
-                      (type << GITS_BASER_TYPE_SHIFT)                   |
-                      ((entry_size - 1) << GITS_BASER_ENTRY_SIZE_SHIFT) |
-                      cache                                             |
-                      shr                                               |
-                      GITS_BASER_VALID);
+       if ((val ^ tmp) & GITS_BASER_PAGE_SIZE_MASK) {
+               /*
+                * Page size didn't stick. Let's try a smaller
+                * size and retry. If we reach 4K, then
+                * something is horribly wrong...
+                */
+               free_pages((unsigned long)base, order);
+               baser->base = NULL;
 
                switch (psz) {
-               case SZ_4K:
-                       val |= GITS_BASER_PAGE_SIZE_4K;
-                       break;
                case SZ_16K:
-                       val |= GITS_BASER_PAGE_SIZE_16K;
-                       break;
+                       psz = SZ_4K;
+                       goto retry_alloc_baser;
                case SZ_64K:
-                       val |= GITS_BASER_PAGE_SIZE_64K;
-                       break;
+                       psz = SZ_16K;
+                       goto retry_alloc_baser;
                }
+       }
+
+       if (val != tmp) {
+               pr_err("ITS@%pa: %s doesn't stick: %lx %lx\n",
+                      &its->phys_base, its_base_type_string[type],
+                      (unsigned long) val, (unsigned long) tmp);
+               free_pages((unsigned long)base, order);
+               return -ENXIO;
+       }
 
-               val |= alloc_pages - 1;
-               its->tables[i].val = val;
+       baser->order = order;
+       baser->base = base;
+       baser->psz = psz;
+       tmp = indirect ? GITS_LVL1_ENTRY_SIZE : esz;
 
-               writeq_relaxed(val, its->base + GITS_BASER + i * 8);
-               tmp = readq_relaxed(its->base + GITS_BASER + i * 8);
+       pr_info("ITS@%pa: allocated %d %s @%lx (%s, esz %d, psz %dK, shr %d)\n",
+               &its->phys_base, (int)(PAGE_ORDER_TO_SIZE(order) / tmp),
+               its_base_type_string[type],
+               (unsigned long)virt_to_phys(base),
+               indirect ? "indirect" : "flat", (int)esz,
+               psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
 
-               if ((val ^ tmp) & GITS_BASER_SHAREABILITY_MASK) {
+       return 0;
+}
+
+static bool its_parse_baser_device(struct its_node *its, struct its_baser 
*baser,
+                                  u32 psz, u32 *order)
+{
+       u64 esz = GITS_BASER_ENTRY_SIZE(its_read_baser(its, baser));
+       u64 val = GITS_BASER_InnerShareable | GITS_BASER_WaWb;
+       u32 ids = its->device_ids;
+       u32 new_order = *order;
+       bool indirect = false;
+
+       /* No need to enable Indirection if memory requirement < (psz*2)bytes */
+       if ((esz << ids) > (psz * 2)) {
+               /*
+                * Find out whether hw supports a single or two-level table by
+                * table by reading bit at offset '62' after writing '1' to it.
+                */
+               its_write_baser(its, baser, val | GITS_BASER_INDIRECT);
+               indirect = !!(baser->val & GITS_BASER_INDIRECT);
+
+               if (indirect) {
                        /*
-                        * Shareability didn't stick. Just use
-                        * whatever the read reported, which is likely
-                        * to be the only thing this redistributor
-                        * supports. If that's zero, make it
-                        * non-cacheable as well.
+                        * The size of the lvl2 table is equal to ITS page size
+                        * which is 'psz'. For computing lvl1 table size,
+                        * subtract ID bits that sparse lvl2 table from 'ids'
+                        * which is reported by ITS hardware times lvl1 table
+                        * entry size.
                         */
-                       shr = tmp & GITS_BASER_SHAREABILITY_MASK;
-                       if (!shr) {
-                               cache = GITS_BASER_nC;
-                               __flush_dcache_area(base, 
PAGE_ORDER_TO_SIZE(order));
-                       }
-                       goto retry_baser;
+                       ids -= ilog2(psz / esz);
+                       esz = GITS_LVL1_ENTRY_SIZE;
                }
+       }
 
-               if ((val ^ tmp) & GITS_BASER_PAGE_SIZE_MASK) {
-                       /*
-                        * Page size didn't stick. Let's try a smaller
-                        * size and retry. If we reach 4K, then
-                        * something is horribly wrong...
-                        */
-                       free_pages((unsigned long)base, order);
-                       its->tables[i].base = NULL;
+       /*
+        * Allocate as many entries as required to fit the
+        * range of device IDs that the ITS can grok... The ID
+        * space being incredibly sparse, this results in a
+        * massive waste of memory if two-level device table
+        * feature is not supported by hardware.
+        */
+       new_order = max_t(u32, get_order(esz << ids), new_order);
+       if (new_order >= MAX_ORDER) {
+               new_order = MAX_ORDER - 1;
+               ids = ilog2(PAGE_ORDER_TO_SIZE(new_order) / esz);
+               pr_warn("ITS@%pa: Device Table too large, reduce ids %u->%u\n",
+                       &its->phys_base, its->device_ids, ids);
+       }
 
-                       switch (psz) {
-                       case SZ_16K:
-                               psz = SZ_4K;
-                               goto retry_alloc_baser;
-                       case SZ_64K:
-                               psz = SZ_16K;
-                               goto retry_alloc_baser;
-                       }
-               }
+       *order = new_order;
+
+       return indirect;
+}
 
-               if (val != tmp) {
-                       pr_err("ITS: %s: GITS_BASER%d doesn't stick: %lx %lx\n",
-                              node_name, i,
-                              (unsigned long) val, (unsigned long) tmp);
-                       err = -ENXIO;
-                       goto out_free;
+static void its_free_tables(struct its_node *its)
+{
+       int i;
+
+       for (i = 0; i < GITS_BASER_NR_REGS; i++) {
+               if (its->tables[i].base) {
+                       free_pages((unsigned long)its->tables[i].base,
+                                  its->tables[i].order);
+                       its->tables[i].base = NULL;
                }
+       }
+}
+
+static int its_alloc_tables(struct its_node *its)
+{
+       u64 typer = readq_relaxed(its->base + GITS_TYPER);
+       u32 ids = GITS_TYPER_DEVBITS(typer);
+       u64 shr = GITS_BASER_InnerShareable;
+       u64 cache = GITS_BASER_WaWb;
+       u32 psz = SZ_64K;
+       int err, i;
 
-               pr_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n",
-                       (int)(PAGE_ORDER_TO_SIZE(order) / entry_size),
-                       its_base_type_string[type],
-                       (unsigned long)virt_to_phys(base),
-                       psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
+       if (its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_22375) {
+               /*
+               * erratum 22375: only alloc 8MB table size
+               * erratum 24313: ignore memory access type
+               */
+               cache   = GITS_BASER_nCnB;
+               ids     = 0x14;                 /* 20 bits, 8MB */
        }
 
-       return 0;
+       its->device_ids = ids;
 
-out_free:
-       its_free_tables(its);
+       for (i = 0; i < GITS_BASER_NR_REGS; i++) {
+               struct its_baser *baser = its->tables + i;
+               u64 val = its_read_baser(its, baser);
+               u64 type = GITS_BASER_TYPE(val);
+               u32 order = get_order(psz);
+               bool indirect = false;
 
-       return err;
+               if (type == GITS_BASER_TYPE_NONE)
+                       continue;
+
+               if (type == GITS_BASER_TYPE_DEVICE)
+                       indirect = its_parse_baser_device(its, baser, psz, 
&order);
+
+               err = its_setup_baser(its, baser, cache, shr, psz, order, 
indirect);
+               if (err < 0) {
+                       its_free_tables(its);
+                       return err;
+               }
+
+               /* Update settings which will be used for next BASERn */
+               psz = baser->psz;
+               cache = baser->val & GITS_BASER_CACHEABILITY_MASK;
+               shr = baser->val & GITS_BASER_SHAREABILITY_MASK;
+       }
+
+       return 0;
 }
 
 static int its_alloc_collections(struct its_node *its)
@@ -1185,10 +1247,57 @@ static struct its_baser *its_get_baser(struct its_node 
*its, u32 type)
        return NULL;
 }
 
+static bool its_alloc_device_table(struct its_node *its, u32 dev_id)
+{
+       struct its_baser *baser;
+       struct page *page;
+       u32 esz, idx;
+       __le64 *table;
+
+       baser = its_get_baser(its, GITS_BASER_TYPE_DEVICE);
+
+       /* Don't allow device id that exceeds ITS hardware limit */
+       if (!baser)
+               return (ilog2(dev_id) < its->device_ids);
+
+       /* Don't allow device id that exceeds single, flat table limit */
+       esz = GITS_BASER_ENTRY_SIZE(baser->val);
+       if (!(baser->val & GITS_BASER_INDIRECT))
+               return (dev_id < (PAGE_ORDER_TO_SIZE(baser->order) / esz));
+
+       /* Compute 1st level table index & check if that exceeds table limit */
+       idx = dev_id >> ilog2(baser->psz / esz);
+       if (idx >= (PAGE_ORDER_TO_SIZE(baser->order) / GITS_LVL1_ENTRY_SIZE))
+               return false;
+
+       table = baser->base;
+
+       /* Allocate memory for 2nd level table */
+       if (!table[idx]) {
+               page = alloc_pages(GFP_KERNEL | __GFP_ZERO, 
get_order(baser->psz));
+               if (!page)
+                       return false;
+
+               /* Flush Lvl2 table to PoC if hw doesn't support coherency */
+               if (!(baser->val & GITS_BASER_SHAREABILITY_MASK))
+                       __flush_dcache_area(page_address(page), baser->psz);
+
+               table[idx] = cpu_to_le64(page_to_phys(page) | GITS_BASER_VALID);
+
+               /* Flush Lvl1 entry to PoC if hw doesn't support coherency */
+               if (!(baser->val & GITS_BASER_SHAREABILITY_MASK))
+                       __flush_dcache_area(table + idx, GITS_LVL1_ENTRY_SIZE);
+
+               /* Ensure updated table contents are visible to ITS hardware */
+               dsb(sy);
+       }
+
+       return true;
+}
+
 static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
                                            int nvecs)
 {
-       struct its_baser *baser;
        struct its_device *dev;
        unsigned long *lpi_map;
        unsigned long flags;
@@ -1199,14 +1308,7 @@ static struct its_device *its_create_device(struct 
its_node *its, u32 dev_id,
        int nr_ites;
        int sz;
 
-       baser = its_get_baser(its, GITS_BASER_TYPE_DEVICE);
-
-       /* Don't allow 'dev_id' that exceeds single, flat table limit */
-       if (baser) {
-               if (dev_id >= (PAGE_ORDER_TO_SIZE(baser->order) /
-                             GITS_BASER_ENTRY_SIZE(baser->val)))
-                       return NULL;
-       } else if (ilog2(dev_id) >= its->device_ids)
+       if (!its_alloc_device_table(its, dev_id))
                return NULL;
 
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
@@ -1569,7 +1671,7 @@ static int __init its_probe(struct device_node *node,
 
        its_enable_quirks(its);
 
-       err = its_alloc_tables(node->full_name, its);
+       err = its_alloc_tables(its);
        if (err)
                goto out_free_cmd;
 
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index fbc4ae2afd29..1de07eb5839c 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -75,7 +75,7 @@ struct gic_chip_data {
        void __iomem *raw_dist_base;
        void __iomem *raw_cpu_base;
        u32 percpu_offset;
-#ifdef CONFIG_CPU_PM
+#if defined(CONFIG_CPU_PM) || defined(CONFIG_ARM_GIC_PM)
        u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
        u32 saved_spi_active[DIV_ROUND_UP(1020, 32)];
        u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
@@ -449,7 +449,7 @@ static void gic_cpu_if_up(struct gic_chip_data *gic)
 }
 
 
-static void __init gic_dist_init(struct gic_chip_data *gic)
+static void gic_dist_init(struct gic_chip_data *gic)
 {
        unsigned int i;
        u32 cpumask;
@@ -528,14 +528,14 @@ int gic_cpu_if_down(unsigned int gic_nr)
        return 0;
 }
 
-#ifdef CONFIG_CPU_PM
+#if defined(CONFIG_CPU_PM) || defined(CONFIG_ARM_GIC_PM)
 /*
  * Saves the GIC distributor registers during suspend or idle.  Must be called
  * with interrupts disabled but before powering down the GIC.  After calling
  * this function, no interrupts will be delivered by the GIC, and another
  * platform-specific wakeup source must be enabled.
  */
-static void gic_dist_save(struct gic_chip_data *gic)
+void gic_dist_save(struct gic_chip_data *gic)
 {
        unsigned int gic_irqs;
        void __iomem *dist_base;
@@ -574,7 +574,7 @@ static void gic_dist_save(struct gic_chip_data *gic)
  * handled normally, but any edge interrupts that occured will not be seen by
  * the GIC and need to be handled by the platform-specific wakeup source.
  */
-static void gic_dist_restore(struct gic_chip_data *gic)
+void gic_dist_restore(struct gic_chip_data *gic)
 {
        unsigned int gic_irqs;
        unsigned int i;
@@ -620,7 +620,7 @@ static void gic_dist_restore(struct gic_chip_data *gic)
        writel_relaxed(GICD_ENABLE, dist_base + GIC_DIST_CTRL);
 }
 
-static void gic_cpu_save(struct gic_chip_data *gic)
+void gic_cpu_save(struct gic_chip_data *gic)
 {
        int i;
        u32 *ptr;
@@ -650,7 +650,7 @@ static void gic_cpu_save(struct gic_chip_data *gic)
 
 }
 
-static void gic_cpu_restore(struct gic_chip_data *gic)
+void gic_cpu_restore(struct gic_chip_data *gic)
 {
        int i;
        u32 *ptr;
@@ -727,7 +727,7 @@ static struct notifier_block gic_notifier_block = {
        .notifier_call = gic_notifier,
 };
 
-static int __init gic_pm_init(struct gic_chip_data *gic)
+static int gic_pm_init(struct gic_chip_data *gic)
 {
        gic->saved_ppi_enable = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4,
                sizeof(u32));
@@ -757,7 +757,7 @@ free_ppi_enable:
        return -ENOMEM;
 }
 #else
-static int __init gic_pm_init(struct gic_chip_data *gic)
+static int gic_pm_init(struct gic_chip_data *gic)
 {
        return 0;
 }
@@ -1032,32 +1032,31 @@ static const struct irq_domain_ops gic_irq_domain_ops = 
{
        .unmap = gic_irq_domain_unmap,
 };
 
-static int __init __gic_init_bases(struct gic_chip_data *gic, int irq_start,
-                                  struct fwnode_handle *handle)
+static void gic_init_chip(struct gic_chip_data *gic, struct device *dev,
+                         const char *name, bool use_eoimode1)
 {
-       irq_hw_number_t hwirq_base;
-       int gic_irqs, irq_base, i, ret;
-
-       if (WARN_ON(!gic || gic->domain))
-               return -EINVAL;
-
        /* Initialize irq_chip */
        gic->chip = gic_chip;
+       gic->chip.name = name;
+       gic->chip.parent_device = dev;
 
-       if (static_key_true(&supports_deactivate) && gic == &gic_data[0]) {
+       if (use_eoimode1) {
                gic->chip.irq_mask = gic_eoimode1_mask_irq;
                gic->chip.irq_eoi = gic_eoimode1_eoi_irq;
                gic->chip.irq_set_vcpu_affinity = gic_irq_set_vcpu_affinity;
-               gic->chip.name = kasprintf(GFP_KERNEL, "GICv2");
-       } else {
-               gic->chip.name = kasprintf(GFP_KERNEL, "GIC-%d",
-                                          (int)(gic - &gic_data[0]));
        }
 
 #ifdef CONFIG_SMP
        if (gic == &gic_data[0])
                gic->chip.irq_set_affinity = gic_set_affinity;
 #endif
+}
+
+static int gic_init_bases(struct gic_chip_data *gic, int irq_start,
+                         struct fwnode_handle *handle)
+{
+       irq_hw_number_t hwirq_base;
+       int gic_irqs, irq_base, ret;
 
        if (IS_ENABLED(CONFIG_GIC_NON_BANKED) && gic->percpu_offset) {
                /* Frankein-GIC without banked registers... */
@@ -1138,6 +1137,36 @@ static int __init __gic_init_bases(struct gic_chip_data 
*gic, int irq_start,
                goto error;
        }
 
+       gic_dist_init(gic);
+       ret = gic_cpu_init(gic);
+       if (ret)
+               goto error;
+
+       ret = gic_pm_init(gic);
+       if (ret)
+               goto error;
+
+       return 0;
+
+error:
+       if (IS_ENABLED(CONFIG_GIC_NON_BANKED) && gic->percpu_offset) {
+               free_percpu(gic->dist_base.percpu_base);
+               free_percpu(gic->cpu_base.percpu_base);
+       }
+
+       return ret;
+}
+
+static int __init __gic_init_bases(struct gic_chip_data *gic,
+                                  int irq_start,
+                                  struct fwnode_handle *handle)
+{
+       char *name;
+       int i, ret;
+
+       if (WARN_ON(!gic || gic->domain))
+               return -EINVAL;
+
        if (gic == &gic_data[0]) {
                /*
                 * Initialize the CPU interface map to all CPUs.
@@ -1155,24 +1184,17 @@ static int __init __gic_init_bases(struct gic_chip_data 
*gic, int irq_start,
                        pr_info("GIC: Using split EOI/Deactivate mode\n");
        }
 
-       gic_dist_init(gic);
-       ret = gic_cpu_init(gic);
-       if (ret)
-               goto error;
-
-       ret = gic_pm_init(gic);
-       if (ret)
-               goto error;
-
-       return 0;
-
-error:
-       if (IS_ENABLED(CONFIG_GIC_NON_BANKED) && gic->percpu_offset) {
-               free_percpu(gic->dist_base.percpu_base);
-               free_percpu(gic->cpu_base.percpu_base);
+       if (static_key_true(&supports_deactivate) && gic == &gic_data[0]) {
+               name = kasprintf(GFP_KERNEL, "GICv2");
+               gic_init_chip(gic, NULL, name, true);
+       } else {
+               name = kasprintf(GFP_KERNEL, "GIC-%d", (int)(gic-&gic_data[0]));
+               gic_init_chip(gic, NULL, name, false);
        }
 
-       kfree(gic->chip.name);
+       ret = gic_init_bases(gic, irq_start, handle);
+       if (ret)
+               kfree(name);
 
        return ret;
 }
@@ -1250,7 +1272,7 @@ static bool gic_check_eoimode(struct device_node *node, 
void __iomem **base)
        return true;
 }
 
-static int __init gic_of_setup(struct gic_chip_data *gic, struct device_node 
*node)
+static int gic_of_setup(struct gic_chip_data *gic, struct device_node *node)
 {
        if (!gic || !node)
                return -EINVAL;
@@ -1274,6 +1296,34 @@ error:
        return -ENOMEM;
 }
 
+int gic_of_init_child(struct device *dev, struct gic_chip_data **gic, int irq)
+{
+       int ret;
+
+       if (!dev || !dev->of_node || !gic || !irq)
+               return -EINVAL;
+
+       *gic = devm_kzalloc(dev, sizeof(**gic), GFP_KERNEL);
+       if (!*gic)
+               return -ENOMEM;
+
+       gic_init_chip(*gic, dev, dev->of_node->name, false);
+
+       ret = gic_of_setup(*gic, dev->of_node);
+       if (ret)
+               return ret;
+
+       ret = gic_init_bases(*gic, -1, &dev->of_node->fwnode);
+       if (ret) {
+               gic_teardown(*gic);
+               return ret;
+       }
+
+       irq_set_chained_handler_and_data(irq, gic_handle_cascade_irq, *gic);
+
+       return 0;
+}
+
 static void __init gic_of_setup_kvm_info(struct device_node *node)
 {
        int ret;
@@ -1353,7 +1403,11 @@ IRQCHIP_DECLARE(cortex_a7_gic, "arm,cortex-a7-gic", 
gic_of_init);
 IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init);
 IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
 IRQCHIP_DECLARE(pl390, "arm,pl390", gic_of_init);
-
+#else
+int gic_of_init_child(struct device *dev, struct gic_chip_data **gic, int irq)
+{
+       return -ENOTSUPP;
+}
 #endif
 
 #ifdef CONFIG_ACPI
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 8a4adbeb2b8c..f4dff5665e4e 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -1042,12 +1042,14 @@ static void __init __gic_init(unsigned long 
gic_base_addr,
                                               &gic_irq_domain_ops, NULL);
        if (!gic_irq_domain)
                panic("Failed to add GIC IRQ domain");
+       gic_irq_domain->name = "mips-gic-irq";
 
        gic_dev_domain = irq_domain_add_hierarchy(gic_irq_domain, 0,
                                                  GIC_NUM_LOCAL_INTRS + 
gic_shared_intrs,
                                                  node, &gic_dev_domain_ops, 
NULL);
        if (!gic_dev_domain)
                panic("Failed to add GIC DEV domain");
+       gic_dev_domain->name = "mips-gic-dev";
 
        gic_ipi_domain = irq_domain_add_hierarchy(gic_irq_domain,
                                                  IRQ_DOMAIN_FLAG_IPI_PER_CPU,
@@ -1056,6 +1058,7 @@ static void __init __gic_init(unsigned long gic_base_addr,
        if (!gic_ipi_domain)
                panic("Failed to add GIC IPI domain");
 
+       gic_ipi_domain->name = "mips-gic-ipi";
        gic_ipi_domain->bus_token = DOMAIN_BUS_IPI;
 
        if (node &&
diff --git a/drivers/irqchip/irq-omap-intc.c b/drivers/irqchip/irq-omap-intc.c
index 9d1bcfc33e4c..b04a8ac6e744 100644
--- a/drivers/irqchip/irq-omap-intc.c
+++ b/drivers/irqchip/irq-omap-intc.c
@@ -23,6 +23,8 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 
+#include <linux/irqchip/irq-omap-intc.h>
+
 /* Define these here for now until we drop all board-files */
 #define OMAP24XX_IC_BASE       0x480fe000
 #define OMAP34XX_IC_BASE       0x48200000
diff --git a/drivers/irqchip/irq-s3c24xx.c b/drivers/irqchip/irq-s3c24xx.c
index 5dc5a760c723..c25ce5af091a 100644
--- a/drivers/irqchip/irq-s3c24xx.c
+++ b/drivers/irqchip/irq-s3c24xx.c
@@ -92,9 +92,9 @@ static void s3c_irq_mask(struct irq_data *data)
        unsigned long mask;
        unsigned int irqno;
 
-       mask = __raw_readl(intc->reg_mask);
+       mask = readl_relaxed(intc->reg_mask);
        mask |= (1UL << irq_data->offset);
-       __raw_writel(mask, intc->reg_mask);
+       writel_relaxed(mask, intc->reg_mask);
 
        if (parent_intc) {
                parent_data = &parent_intc->irqs[irq_data->parent_irq];
@@ -119,9 +119,9 @@ static void s3c_irq_unmask(struct irq_data *data)
        unsigned long mask;
        unsigned int irqno;
 
-       mask = __raw_readl(intc->reg_mask);
+       mask = readl_relaxed(intc->reg_mask);
        mask &= ~(1UL << irq_data->offset);
-       __raw_writel(mask, intc->reg_mask);
+       writel_relaxed(mask, intc->reg_mask);
 
        if (parent_intc) {
                irqno = irq_find_mapping(parent_intc->domain,
@@ -136,9 +136,9 @@ static inline void s3c_irq_ack(struct irq_data *data)
        struct s3c_irq_intc *intc = irq_data->intc;
        unsigned long bitval = 1UL << irq_data->offset;
 
-       __raw_writel(bitval, intc->reg_pending);
+       writel_relaxed(bitval, intc->reg_pending);
        if (intc->reg_intpnd)
-               __raw_writel(bitval, intc->reg_intpnd);
+               writel_relaxed(bitval, intc->reg_intpnd);
 }
 
 static int s3c_irq_type(struct irq_data *data, unsigned int type)
@@ -172,9 +172,9 @@ static int s3c_irqext_type_set(void __iomem *gpcon_reg,
        unsigned long newvalue = 0, value;
 
        /* Set the GPIO to external interrupt mode */
-       value = __raw_readl(gpcon_reg);
+       value = readl_relaxed(gpcon_reg);
        value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
-       __raw_writel(value, gpcon_reg);
+       writel_relaxed(value, gpcon_reg);
 
        /* Set the external interrupt to pointed trigger type */
        switch (type)
@@ -208,9 +208,9 @@ static int s3c_irqext_type_set(void __iomem *gpcon_reg,
                        return -EINVAL;
        }
 
-       value = __raw_readl(extint_reg);
+       value = readl_relaxed(extint_reg);
        value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
-       __raw_writel(value, extint_reg);
+       writel_relaxed(value, extint_reg);
 
        return 0;
 }
@@ -315,8 +315,8 @@ static void s3c_irq_demux(struct irq_desc *desc)
 
        chained_irq_enter(chip, desc);
 
-       src = __raw_readl(sub_intc->reg_pending);
-       msk = __raw_readl(sub_intc->reg_mask);
+       src = readl_relaxed(sub_intc->reg_pending);
+       msk = readl_relaxed(sub_intc->reg_mask);
 
        src &= ~msk;
        src &= irq_data->sub_bits;
@@ -337,7 +337,7 @@ static inline int s3c24xx_handle_intc(struct s3c_irq_intc 
*intc,
        int pnd;
        int offset;
 
-       pnd = __raw_readl(intc->reg_intpnd);
+       pnd = readl_relaxed(intc->reg_intpnd);
        if (!pnd)
                return false;
 
@@ -352,7 +352,7 @@ static inline int s3c24xx_handle_intc(struct s3c_irq_intc 
*intc,
         *
         * Thanks to Klaus, Shannon, et al for helping to debug this problem
         */
-       offset = __raw_readl(intc->reg_intpnd + 4);
+       offset = readl_relaxed(intc->reg_intpnd + 4);
 
        /* Find the bit manually, when the offset is wrong.
         * The pending register only ever contains the one bit of the next
@@ -406,7 +406,7 @@ int s3c24xx_set_fiq(unsigned int irq, bool on)
                intmod = 0;
        }
 
-       __raw_writel(intmod, S3C2410_INTMOD);
+       writel_relaxed(intmod, S3C2410_INTMOD);
        return 0;
 }
 
@@ -508,14 +508,14 @@ static void s3c24xx_clear_intc(struct s3c_irq_intc *intc)
 
        last = 0;
        for (i = 0; i < 4; i++) {
-               pend = __raw_readl(reg_source);
+               pend = readl_relaxed(reg_source);
 
                if (pend == 0 || pend == last)
                        break;
 
-               __raw_writel(pend, intc->reg_pending);
+               writel_relaxed(pend, intc->reg_pending);
                if (intc->reg_intpnd)
-                       __raw_writel(pend, intc->reg_intpnd);
+                       writel_relaxed(pend, intc->reg_intpnd);
 
                pr_info("irq: clearing pending status %08x\n", (int)pend);
                last = pend;
diff --git a/drivers/irqchip/irq-sirfsoc.c b/drivers/irqchip/irq-sirfsoc.c
index 10cb21b9ba3d..e1336848affa 100644
--- a/drivers/irqchip/irq-sirfsoc.c
+++ b/drivers/irqchip/irq-sirfsoc.c
@@ -29,6 +29,11 @@
 
 static struct irq_domain *sirfsoc_irqdomain;
 
+static void __iomem *sirfsoc_irq_get_regbase(void)
+{
+       return (void __iomem __force *)sirfsoc_irqdomain->host_data;
+}
+
 static __init void sirfsoc_alloc_gc(void __iomem *base)
 {
        unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
@@ -53,7 +58,7 @@ static __init void sirfsoc_alloc_gc(void __iomem *base)
 
 static void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs)
 {
-       void __iomem *base = sirfsoc_irqdomain->host_data;
+       void __iomem *base = sirfsoc_irq_get_regbase();
        u32 irqstat;
 
        irqstat = readl_relaxed(base + SIRFSOC_INIT_IRQ_ID);
@@ -94,7 +99,7 @@ static struct sirfsoc_irq_status sirfsoc_irq_st;
 
 static int sirfsoc_irq_suspend(void)
 {
-       void __iomem *base = sirfsoc_irqdomain->host_data;
+       void __iomem *base = sirfsoc_irq_get_regbase();
 
        sirfsoc_irq_st.mask0 = readl_relaxed(base + SIRFSOC_INT_RISC_MASK0);
        sirfsoc_irq_st.mask1 = readl_relaxed(base + SIRFSOC_INT_RISC_MASK1);
@@ -106,7 +111,7 @@ static int sirfsoc_irq_suspend(void)
 
 static void sirfsoc_irq_resume(void)
 {
-       void __iomem *base = sirfsoc_irqdomain->host_data;
+       void __iomem *base = sirfsoc_irq_get_regbase();
 
        writel_relaxed(sirfsoc_irq_st.mask0, base + SIRFSOC_INT_RISC_MASK0);
        writel_relaxed(sirfsoc_irq_st.mask1, base + SIRFSOC_INT_RISC_MASK1);
diff --git a/drivers/irqchip/irq-tegra.c b/drivers/irqchip/irq-tegra.c
index e902f081e16c..3973a14bb15b 100644
--- a/drivers/irqchip/irq-tegra.c
+++ b/drivers/irqchip/irq-tegra.c
@@ -90,7 +90,7 @@ static struct tegra_ictlr_info *lic;
 
 static inline void tegra_ictlr_write_mask(struct irq_data *d, unsigned long 
reg)
 {
-       void __iomem *base = d->chip_data;
+       void __iomem *base = (void __iomem __force *)d->chip_data;
        u32 mask;
 
        mask = BIT(d->hwirq % 32);
@@ -266,7 +266,7 @@ static int tegra_ictlr_domain_alloc(struct irq_domain 
*domain,
 
                irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
                                              &tegra_ictlr_chip,
-                                             info->base[ictlr]);
+                                             (void __force 
*)info->base[ictlr]);
        }
 
        parent_fwspec = *fwspec;
diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c
index b956dfffe78c..f811a7de5857 100644
--- a/drivers/irqchip/irq-vic.c
+++ b/drivers/irqchip/irq-vic.c
@@ -167,7 +167,7 @@ static int vic_suspend(void)
        return 0;
 }
 
-struct syscore_ops vic_syscore_ops = {
+static struct syscore_ops vic_syscore_ops = {
        .suspend        = vic_suspend,
        .resume         = vic_resume,
 };
@@ -517,7 +517,8 @@ int __init vic_init_cascaded(void __iomem *base, unsigned 
int parent_irq,
 EXPORT_SYMBOL_GPL(vic_init_cascaded);
 
 #ifdef CONFIG_OF
-int __init vic_of_init(struct device_node *node, struct device_node *parent)
+static int __init vic_of_init(struct device_node *node,
+                             struct device_node *parent)
 {
        void __iomem *regs;
        u32 interrupt_mask = ~0;
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 9fcabeb07787..b6683f0ffc9f 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -278,6 +278,8 @@ extern int irq_set_affinity_hint(unsigned int irq, const 
struct cpumask *m);
 extern int
 irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify 
*notify);
 
+struct cpumask *irq_create_affinity_mask(unsigned int *nr_vecs);
+
 #else /* CONFIG_SMP */
 
 static inline int irq_set_affinity(unsigned int irq, const struct cpumask *m)
@@ -308,6 +310,12 @@ irq_set_affinity_notifier(unsigned int irq, struct 
irq_affinity_notify *notify)
 {
        return 0;
 }
+
+static inline struct cpumask *irq_create_affinity_mask(unsigned int *nr_vecs)
+{
+       *nr_vecs = 1;
+       return NULL;
+}
 #endif /* CONFIG_SMP */
 
 /*
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 4d758a7c604a..b52424eaa0ed 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -197,6 +197,7 @@ struct irq_data {
  * IRQD_IRQ_INPROGRESS         - In progress state of the interrupt
  * IRQD_WAKEUP_ARMED           - Wakeup mode armed
  * IRQD_FORWARDED_TO_VCPU      - The interrupt is forwarded to a VCPU
+ * IRQD_AFFINITY_MANAGED       - Affinity is auto-managed by the kernel
  */
 enum {
        IRQD_TRIGGER_MASK               = 0xf,
@@ -212,6 +213,7 @@ enum {
        IRQD_IRQ_INPROGRESS             = (1 << 18),
        IRQD_WAKEUP_ARMED               = (1 << 19),
        IRQD_FORWARDED_TO_VCPU          = (1 << 20),
+       IRQD_AFFINITY_MANAGED           = (1 << 21),
 };
 
 #define __irqd_to_state(d) ACCESS_PRIVATE((d)->common, state_use_accessors)
@@ -305,6 +307,11 @@ static inline void irqd_clr_forwarded_to_vcpu(struct 
irq_data *d)
        __irqd_to_state(d) &= ~IRQD_FORWARDED_TO_VCPU;
 }
 
+static inline bool irqd_affinity_is_managed(struct irq_data *d)
+{
+       return __irqd_to_state(d) & IRQD_AFFINITY_MANAGED;
+}
+
 #undef __irqd_to_state
 
 static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
@@ -315,6 +322,7 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data 
*d)
 /**
  * struct irq_chip - hardware interrupt chip descriptor
  *
+ * @parent_device:     pointer to parent device for irqchip
  * @name:              name for /proc/interrupts
  * @irq_startup:       start up the interrupt (defaults to ->enable if NULL)
  * @irq_shutdown:      shut down the interrupt (defaults to ->disable if NULL)
@@ -354,6 +362,7 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data 
*d)
  * @flags:             chip specific flags
  */
 struct irq_chip {
+       struct device   *parent_device;
        const char      *name;
        unsigned int    (*irq_startup)(struct irq_data *data);
        void            (*irq_shutdown)(struct irq_data *data);
@@ -482,12 +491,15 @@ extern void handle_fasteoi_irq(struct irq_desc *desc);
 extern void handle_edge_irq(struct irq_desc *desc);
 extern void handle_edge_eoi_irq(struct irq_desc *desc);
 extern void handle_simple_irq(struct irq_desc *desc);
+extern void handle_untracked_irq(struct irq_desc *desc);
 extern void handle_percpu_irq(struct irq_desc *desc);
 extern void handle_percpu_devid_irq(struct irq_desc *desc);
 extern void handle_bad_irq(struct irq_desc *desc);
 extern void handle_nested_irq(unsigned int irq);
 
 extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg 
*msg);
+extern int irq_chip_pm_get(struct irq_data *data);
+extern int irq_chip_pm_put(struct irq_data *data);
 #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
 extern void irq_chip_enable_parent(struct irq_data *data);
 extern void irq_chip_disable_parent(struct irq_data *data);
@@ -701,11 +713,11 @@ static inline struct cpumask 
*irq_data_get_affinity_mask(struct irq_data *d)
 unsigned int arch_dynirq_lower_bound(unsigned int from);
 
 int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
-               struct module *owner);
+                     struct module *owner, const struct cpumask *affinity);
 
 /* use macros to avoid needing export.h for THIS_MODULE */
 #define irq_alloc_descs(irq, from, cnt, node)  \
-       __irq_alloc_descs(irq, from, cnt, node, THIS_MODULE)
+       __irq_alloc_descs(irq, from, cnt, node, THIS_MODULE, NULL)
 
 #define irq_alloc_desc(node)                   \
        irq_alloc_descs(-1, 0, 1, node)
diff --git a/include/linux/irqchip/arm-gic-v3.h 
b/include/linux/irqchip/arm-gic-v3.h
index dc493e0f0ff7..107eed475b94 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -204,6 +204,7 @@
 #define GITS_BASER_NR_REGS             8
 
 #define GITS_BASER_VALID               (1UL << 63)
+#define GITS_BASER_INDIRECT            (1UL << 62)
 #define GITS_BASER_nCnB                        (0UL << 59)
 #define GITS_BASER_nC                  (1UL << 59)
 #define GITS_BASER_RaWt                        (2UL << 59)
@@ -228,6 +229,7 @@
 #define GITS_BASER_PAGE_SIZE_64K       (2UL << GITS_BASER_PAGE_SIZE_SHIFT)
 #define GITS_BASER_PAGE_SIZE_MASK      (3UL << GITS_BASER_PAGE_SIZE_SHIFT)
 #define GITS_BASER_PAGES_MAX           256
+#define GITS_BASER_PAGES_SHIFT         (0)
 
 #define GITS_BASER_TYPE_NONE           0
 #define GITS_BASER_TYPE_DEVICE         1
@@ -238,6 +240,8 @@
 #define GITS_BASER_TYPE_RESERVED6      6
 #define GITS_BASER_TYPE_RESERVED7      7
 
+#define GITS_LVL1_ENTRY_SIZE           (8UL)
+
 /*
  * ITS commands
  */
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index fd051855539b..eafc965b3eb8 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -101,9 +101,14 @@
 #include <linux/irqdomain.h>
 
 struct device_node;
+struct gic_chip_data;
 
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 int gic_cpu_if_down(unsigned int gic_nr);
+void gic_cpu_save(struct gic_chip_data *gic);
+void gic_cpu_restore(struct gic_chip_data *gic);
+void gic_dist_save(struct gic_chip_data *gic);
+void gic_dist_restore(struct gic_chip_data *gic);
 
 /*
  * Subdrivers that need some preparatory work can initialize their
@@ -112,6 +117,12 @@ int gic_cpu_if_down(unsigned int gic_nr);
 int gic_of_init(struct device_node *node, struct device_node *parent);
 
 /*
+ * Initialises and registers a non-root or child GIC chip. Memory for
+ * the gic_chip_data structure is dynamically allocated.
+ */
+int gic_of_init_child(struct device *dev, struct gic_chip_data **gic, int irq);
+
+/*
  * Legacy platforms not converted to DT yet must use this to init
  * their GIC
  */
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index f1f36e04d885..ffb84604c1de 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -39,6 +39,7 @@ struct irq_domain;
 struct of_device_id;
 struct irq_chip;
 struct irq_data;
+struct cpumask;
 
 /* Number of irqs reserved for a legacy isa controller */
 #define NUM_ISA_INTERRUPTS     16
@@ -217,7 +218,8 @@ extern struct irq_domain *irq_find_matching_fwspec(struct 
irq_fwspec *fwspec,
                                                   enum irq_domain_bus_token 
bus_token);
 extern void irq_set_default_host(struct irq_domain *host);
 extern int irq_domain_alloc_descs(int virq, unsigned int nr_irqs,
-                                 irq_hw_number_t hwirq, int node);
+                                 irq_hw_number_t hwirq, int node,
+                                 const struct cpumask *affinity);
 
 static inline struct fwnode_handle *of_node_to_fwnode(struct device_node *node)
 {
@@ -389,7 +391,7 @@ static inline struct irq_domain 
*irq_domain_add_hierarchy(struct irq_domain *par
 
 extern int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
                                   unsigned int nr_irqs, int node, void *arg,
-                                  bool realloc);
+                                  bool realloc, const struct cpumask 
*affinity);
 extern void irq_domain_free_irqs(unsigned int virq, unsigned int nr_irqs);
 extern void irq_domain_activate_irq(struct irq_data *irq_data);
 extern void irq_domain_deactivate_irq(struct irq_data *irq_data);
@@ -397,7 +399,8 @@ extern void irq_domain_deactivate_irq(struct irq_data 
*irq_data);
 static inline int irq_domain_alloc_irqs(struct irq_domain *domain,
                        unsigned int nr_irqs, int node, void *arg)
 {
-       return __irq_domain_alloc_irqs(domain, -1, nr_irqs, node, arg, false);
+       return __irq_domain_alloc_irqs(domain, -1, nr_irqs, node, arg, false,
+                                      NULL);
 }
 
 extern int irq_domain_alloc_irqs_recursive(struct irq_domain *domain,
@@ -452,6 +455,9 @@ static inline int irq_domain_alloc_irqs(struct irq_domain 
*domain,
        return -1;
 }
 
+static inline void irq_domain_free_irqs(unsigned int virq,
+                                       unsigned int nr_irqs) { }
+
 static inline bool irq_domain_is_hierarchy(struct irq_domain *domain)
 {
        return false;
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 8b425c66305a..4f0bfe5912b2 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -47,6 +47,7 @@ struct fsl_mc_msi_desc {
  * @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
+ * @affinity:  Optional pointer to a cpu affinity mask for this descriptor
  *
  * @masked:    [PCI MSI/X] Mask bits
  * @is_msix:   [PCI MSI/X] True if MSI-X
@@ -67,6 +68,7 @@ struct msi_desc {
        unsigned int                    nvec_used;
        struct device                   *dev;
        struct msi_msg                  msg;
+       const struct cpumask            *affinity;
 
        union {
                /* PCI MSI/X specific data */
@@ -264,12 +266,10 @@ enum {
         * callbacks.
         */
        MSI_FLAG_USE_DEF_CHIP_OPS       = (1 << 1),
-       /* Build identity map between hwirq and irq */
-       MSI_FLAG_IDENTITY_MAP           = (1 << 2),
        /* Support multiple PCI MSI interrupts */
-       MSI_FLAG_MULTI_PCI_MSI          = (1 << 3),
+       MSI_FLAG_MULTI_PCI_MSI          = (1 << 2),
        /* Support PCI MSIX interrupts */
-       MSI_FLAG_PCI_MSIX               = (1 << 4),
+       MSI_FLAG_PCI_MSIX               = (1 << 3),
 };
 
 int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask,
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
index 2ee42e95a3ce..1d3ee3169202 100644
--- a/kernel/irq/Makefile
+++ b/kernel/irq/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_GENERIC_IRQ_MIGRATION) += cpuhotplug.o
 obj-$(CONFIG_PM_SLEEP) += pm.o
 obj-$(CONFIG_GENERIC_MSI_IRQ) += msi.o
 obj-$(CONFIG_GENERIC_IRQ_IPI) += ipi.o
+obj-$(CONFIG_SMP) += affinity.o
diff --git a/kernel/irq/affinity.c b/kernel/irq/affinity.c
new file mode 100644
index 000000000000..f68959341c0f
--- /dev/null
+++ b/kernel/irq/affinity.c
@@ -0,0 +1,61 @@
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/cpu.h>
+
+static int get_first_sibling(unsigned int cpu)
+{
+       unsigned int ret;
+
+       ret = cpumask_first(topology_sibling_cpumask(cpu));
+       if (ret < nr_cpu_ids)
+               return ret;
+       return cpu;
+}
+
+/*
+ * Take a map of online CPUs and the number of available interrupt vectors
+ * and generate an output cpumask suitable for spreading MSI/MSI-X vectors
+ * so that they are distributed as good as possible around the CPUs.  If
+ * more vectors than CPUs are available we'll map one to each CPU,
+ * otherwise we map one to the first sibling of each socket.
+ *
+ * If there are more vectors than CPUs we will still only have one bit
+ * set per CPU, but interrupt code will keep on assigning the vectors from
+ * the start of the bitmap until we run out of vectors.
+ */
+struct cpumask *irq_create_affinity_mask(unsigned int *nr_vecs)
+{
+       struct cpumask *affinity_mask;
+       unsigned int max_vecs = *nr_vecs;
+
+       if (max_vecs == 1)
+               return NULL;
+
+       affinity_mask = kzalloc(cpumask_size(), GFP_KERNEL);
+       if (!affinity_mask) {
+               *nr_vecs = 1;
+               return NULL;
+       }
+
+       if (max_vecs >= num_online_cpus()) {
+               cpumask_copy(affinity_mask, cpu_online_mask);
+               *nr_vecs = num_online_cpus();
+       } else {
+               unsigned int vecs = 0, cpu;
+
+               for_each_online_cpu(cpu) {
+                       if (cpu == get_first_sibling(cpu)) {
+                               cpumask_set_cpu(cpu, affinity_mask);
+                               vecs++;
+                       }
+
+                       if (--max_vecs == 0)
+                               break;
+               }
+               *nr_vecs = vecs;
+       }
+
+       return affinity_mask;
+}
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 2f9f2b0e79f2..b4c1bc7c9ca2 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -426,6 +426,49 @@ out_unlock:
 }
 EXPORT_SYMBOL_GPL(handle_simple_irq);
 
+/**
+ *     handle_untracked_irq - Simple and software-decoded IRQs.
+ *     @desc:  the interrupt description structure for this irq
+ *
+ *     Untracked interrupts are sent from a demultiplexing interrupt
+ *     handler when the demultiplexer does not know which device it its
+ *     multiplexed irq domain generated the interrupt. IRQ's handled
+ *     through here are not subjected to stats tracking, randomness, or
+ *     spurious interrupt detection.
+ *
+ *     Note: Like handle_simple_irq, the caller is expected to handle
+ *     the ack, clear, mask and unmask issues if necessary.
+ */
+void handle_untracked_irq(struct irq_desc *desc)
+{
+       unsigned int flags = 0;
+
+       raw_spin_lock(&desc->lock);
+
+       if (!irq_may_run(desc))
+               goto out_unlock;
+
+       desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
+
+       if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
+               desc->istate |= IRQS_PENDING;
+               goto out_unlock;
+       }
+
+       desc->istate &= ~IRQS_PENDING;
+       irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS);
+       raw_spin_unlock(&desc->lock);
+
+       __handle_irq_event_percpu(desc, &flags);
+
+       raw_spin_lock(&desc->lock);
+       irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);
+
+out_unlock:
+       raw_spin_unlock(&desc->lock);
+}
+EXPORT_SYMBOL_GPL(handle_untracked_irq);
+
 /*
  * Called unconditionally from handle_level_irq() and only for oneshot
  * interrupts from handle_fasteoi_irq()
@@ -1093,3 +1136,43 @@ int irq_chip_compose_msi_msg(struct irq_data *data, 
struct msi_msg *msg)
 
        return 0;
 }
+
+/**
+ * irq_chip_pm_get - Enable power for an IRQ chip
+ * @data:      Pointer to interrupt specific data
+ *
+ * Enable the power to the IRQ chip referenced by the interrupt data
+ * structure.
+ */
+int irq_chip_pm_get(struct irq_data *data)
+{
+       int retval;
+
+       if (IS_ENABLED(CONFIG_PM) && data->chip->parent_device) {
+               retval = pm_runtime_get_sync(data->chip->parent_device);
+               if (retval < 0) {
+                       pm_runtime_put_noidle(data->chip->parent_device);
+                       return retval;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * irq_chip_pm_put - Disable power for an IRQ chip
+ * @data:      Pointer to interrupt specific data
+ *
+ * Disable the power to the IRQ chip referenced by the interrupt data
+ * structure, belongs. Note that power will only be disabled, once this
+ * function has been called for all IRQs that have called irq_chip_pm_get().
+ */
+int irq_chip_pm_put(struct irq_data *data)
+{
+       int retval = 0;
+
+       if (IS_ENABLED(CONFIG_PM) && data->chip->parent_device)
+               retval = pm_runtime_put(data->chip->parent_device);
+
+       return (retval < 0) ? retval : 0;
+}
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index a15b5485b446..d3f24905852c 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -132,10 +132,10 @@ void __irq_wake_thread(struct irq_desc *desc, struct 
irqaction *action)
        wake_up_process(action->thread);
 }
 
-irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
+irqreturn_t __handle_irq_event_percpu(struct irq_desc *desc, unsigned int 
*flags)
 {
        irqreturn_t retval = IRQ_NONE;
-       unsigned int flags = 0, irq = desc->irq_data.irq;
+       unsigned int irq = desc->irq_data.irq;
        struct irqaction *action;
 
        for_each_action_of_desc(desc, action) {
@@ -164,7 +164,7 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
 
                        /* Fall through to add to randomness */
                case IRQ_HANDLED:
-                       flags |= action->flags;
+                       *flags |= action->flags;
                        break;
 
                default:
@@ -174,7 +174,17 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
                retval |= res;
        }
 
-       add_interrupt_randomness(irq, flags);
+       return retval;
+}
+
+irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
+{
+       irqreturn_t retval;
+       unsigned int flags = 0;
+
+       retval = __handle_irq_event_percpu(desc, &flags);
+
+       add_interrupt_randomness(desc->irq_data.irq, flags);
 
        if (!noirqdebug)
                note_interrupt(desc, retval);
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 09be2c903c6d..bc226e783bd2 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -7,6 +7,7 @@
  */
 #include <linux/irqdesc.h>
 #include <linux/kernel_stat.h>
+#include <linux/pm_runtime.h>
 
 #ifdef CONFIG_SPARSE_IRQ
 # define IRQ_BITMAP_BITS       (NR_IRQS + 8196)
@@ -83,6 +84,7 @@ extern void irq_mark_irq(unsigned int irq);
 
 extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr);
 
+irqreturn_t __handle_irq_event_percpu(struct irq_desc *desc, unsigned int 
*flags);
 irqreturn_t handle_irq_event_percpu(struct irq_desc *desc);
 irqreturn_t handle_irq_event(struct irq_desc *desc);
 
@@ -105,6 +107,8 @@ static inline void unregister_handler_proc(unsigned int irq,
                                           struct irqaction *action) { }
 #endif
 
+extern bool irq_can_set_affinity_usr(unsigned int irq);
+
 extern int irq_select_affinity_usr(unsigned int irq, struct cpumask *mask);
 
 extern void irq_set_thread_affinity(struct irq_desc *desc);
diff --git a/kernel/irq/ipi.c b/kernel/irq/ipi.c
index 89b49f6773f0..1a9abc1c8ea0 100644
--- a/kernel/irq/ipi.c
+++ b/kernel/irq/ipi.c
@@ -76,14 +76,14 @@ int irq_reserve_ipi(struct irq_domain *domain,
                }
        }
 
-       virq = irq_domain_alloc_descs(-1, nr_irqs, 0, NUMA_NO_NODE);
+       virq = irq_domain_alloc_descs(-1, nr_irqs, 0, NUMA_NO_NODE, NULL);
        if (virq <= 0) {
                pr_warn("Can't reserve IPI, failed to alloc descs\n");
                return -ENOMEM;
        }
 
        virq = __irq_domain_alloc_irqs(domain, virq, nr_irqs, NUMA_NO_NODE,
-                                      (void *) dest, true);
+                                      (void *) dest, true, NULL);
 
        if (virq <= 0) {
                pr_warn("Can't reserve IPI, failed to alloc hw irqs\n");
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 8731e1c5d1e7..a623b44f2d4b 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -68,9 +68,13 @@ static int alloc_masks(struct irq_desc *desc, gfp_t gfp, int 
node)
        return 0;
 }
 
-static void desc_smp_init(struct irq_desc *desc, int node)
+static void desc_smp_init(struct irq_desc *desc, int node,
+                         const struct cpumask *affinity)
 {
-       cpumask_copy(desc->irq_common_data.affinity, irq_default_affinity);
+       if (!affinity)
+               affinity = irq_default_affinity;
+       cpumask_copy(desc->irq_common_data.affinity, affinity);
+
 #ifdef CONFIG_GENERIC_PENDING_IRQ
        cpumask_clear(desc->pending_mask);
 #endif
@@ -82,11 +86,12 @@ static void desc_smp_init(struct irq_desc *desc, int node)
 #else
 static inline int
 alloc_masks(struct irq_desc *desc, gfp_t gfp, int node) { return 0; }
-static inline void desc_smp_init(struct irq_desc *desc, int node) { }
+static inline void
+desc_smp_init(struct irq_desc *desc, int node, const struct cpumask *affinity) 
{ }
 #endif
 
 static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int 
node,
-               struct module *owner)
+                             const struct cpumask *affinity, struct module 
*owner)
 {
        int cpu;
 
@@ -107,7 +112,7 @@ static void desc_set_defaults(unsigned int irq, struct 
irq_desc *desc, int node,
        desc->owner = owner;
        for_each_possible_cpu(cpu)
                *per_cpu_ptr(desc->kstat_irqs, cpu) = 0;
-       desc_smp_init(desc, node);
+       desc_smp_init(desc, node, affinity);
 }
 
 int nr_irqs = NR_IRQS;
@@ -158,7 +163,9 @@ void irq_unlock_sparse(void)
        mutex_unlock(&sparse_irq_lock);
 }
 
-static struct irq_desc *alloc_desc(int irq, int node, struct module *owner)
+static struct irq_desc *alloc_desc(int irq, int node, unsigned int flags,
+                                  const struct cpumask *affinity,
+                                  struct module *owner)
 {
        struct irq_desc *desc;
        gfp_t gfp = GFP_KERNEL;
@@ -178,7 +185,8 @@ static struct irq_desc *alloc_desc(int irq, int node, 
struct module *owner)
        lockdep_set_class(&desc->lock, &irq_desc_lock_class);
        init_rcu_head(&desc->rcu);
 
-       desc_set_defaults(irq, desc, node, owner);
+       desc_set_defaults(irq, desc, node, affinity, owner);
+       irqd_set(&desc->irq_data, flags);
 
        return desc;
 
@@ -223,13 +231,32 @@ static void free_desc(unsigned int irq)
 }
 
 static int alloc_descs(unsigned int start, unsigned int cnt, int node,
-                      struct module *owner)
+                      const struct cpumask *affinity, struct module *owner)
 {
+       const struct cpumask *mask = NULL;
        struct irq_desc *desc;
-       int i;
+       unsigned int flags;
+       int i, cpu = -1;
+
+       if (affinity && cpumask_empty(affinity))
+               return -EINVAL;
+
+       flags = affinity ? IRQD_AFFINITY_MANAGED : 0;
 
        for (i = 0; i < cnt; i++) {
-               desc = alloc_desc(start + i, node, owner);
+               if (affinity) {
+                       cpu = cpumask_next(cpu, affinity);
+                       if (cpu >= nr_cpu_ids)
+                               cpu = cpumask_first(affinity);
+                       node = cpu_to_node(cpu);
+
+                       /*
+                        * For single allocations we use the caller provided
+                        * mask otherwise we use the mask of the target cpu
+                        */
+                       mask = cnt == 1 ? affinity : cpumask_of(cpu);
+               }
+               desc = alloc_desc(start + i, node, flags, mask, owner);
                if (!desc)
                        goto err;
                mutex_lock(&sparse_irq_lock);
@@ -277,7 +304,7 @@ int __init early_irq_init(void)
                nr_irqs = initcnt;
 
        for (i = 0; i < initcnt; i++) {
-               desc = alloc_desc(i, node, NULL);
+               desc = alloc_desc(i, node, 0, NULL, NULL);
                set_bit(i, allocated_irqs);
                irq_insert_desc(i, desc);
        }
@@ -311,7 +338,7 @@ int __init early_irq_init(void)
                alloc_masks(&desc[i], GFP_KERNEL, node);
                raw_spin_lock_init(&desc[i].lock);
                lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
-               desc_set_defaults(i, &desc[i], node, NULL);
+               desc_set_defaults(i, &desc[i], node, NULL, NULL);
        }
        return arch_early_irq_init();
 }
@@ -328,11 +355,12 @@ static void free_desc(unsigned int irq)
        unsigned long flags;
 
        raw_spin_lock_irqsave(&desc->lock, flags);
-       desc_set_defaults(irq, desc, irq_desc_get_node(desc), NULL);
+       desc_set_defaults(irq, desc, irq_desc_get_node(desc), NULL, NULL);
        raw_spin_unlock_irqrestore(&desc->lock, flags);
 }
 
 static inline int alloc_descs(unsigned int start, unsigned int cnt, int node,
+                             const struct cpumask *affinity,
                              struct module *owner)
 {
        u32 i;
@@ -453,12 +481,15 @@ EXPORT_SYMBOL_GPL(irq_free_descs);
  * @cnt:       Number of consecutive irqs to allocate.
  * @node:      Preferred node on which the irq descriptor should be allocated
  * @owner:     Owning module (can be NULL)
+ * @affinity:  Optional pointer to an affinity mask which hints where the
+ *             irq descriptors should be allocated and which default
+ *             affinities to use
  *
  * Returns the first irq number or error code
  */
 int __ref
 __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
-                 struct module *owner)
+                 struct module *owner, const struct cpumask *affinity)
 {
        int start, ret;
 
@@ -494,7 +525,7 @@ __irq_alloc_descs(int irq, unsigned int from, unsigned int 
cnt, int node,
 
        bitmap_set(allocated_irqs, start, cnt);
        mutex_unlock(&sparse_irq_lock);
-       return alloc_descs(start, cnt, node, owner);
+       return alloc_descs(start, cnt, node, affinity, owner);
 
 err:
        mutex_unlock(&sparse_irq_lock);
@@ -512,7 +543,7 @@ EXPORT_SYMBOL_GPL(__irq_alloc_descs);
  */
 unsigned int irq_alloc_hwirqs(int cnt, int node)
 {
-       int i, irq = __irq_alloc_descs(-1, 0, cnt, node, NULL);
+       int i, irq = __irq_alloc_descs(-1, 0, cnt, node, NULL, NULL);
 
        if (irq < 0)
                return 0;
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 8798b6c9e945..4752b43662e0 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -481,7 +481,7 @@ unsigned int irq_create_mapping(struct irq_domain *domain,
        }
 
        /* Allocate a virtual interrupt number */
-       virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node));
+       virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node), 
NULL);
        if (virq <= 0) {
                pr_debug("-> virq allocation failed\n");
                return 0;
@@ -567,6 +567,7 @@ static void of_phandle_args_to_fwspec(struct 
of_phandle_args *irq_data,
 unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
 {
        struct irq_domain *domain;
+       struct irq_data *irq_data;
        irq_hw_number_t hwirq;
        unsigned int type = IRQ_TYPE_NONE;
        int virq;
@@ -588,15 +589,46 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec 
*fwspec)
        if (irq_domain_translate(domain, fwspec, &hwirq, &type))
                return 0;
 
-       if (irq_domain_is_hierarchy(domain)) {
+       /*
+        * WARN if the irqchip returns a type with bits
+        * outside the sense mask set and clear these bits.
+        */
+       if (WARN_ON(type & ~IRQ_TYPE_SENSE_MASK))
+               type &= IRQ_TYPE_SENSE_MASK;
+
+       /*
+        * If we've already configured this interrupt,
+        * don't do it again, or hell will break loose.
+        */
+       virq = irq_find_mapping(domain, hwirq);
+       if (virq) {
+               /*
+                * If the trigger type is not specified or matches the
+                * current trigger type then we are done so return the
+                * interrupt number.
+                */
+               if (type == IRQ_TYPE_NONE || type == irq_get_trigger_type(virq))
+                       return virq;
+
                /*
-                * If we've already configured this interrupt,
-                * don't do it again, or hell will break loose.
+                * If the trigger type has not been set yet, then set
+                * it now and return the interrupt number.
                 */
-               virq = irq_find_mapping(domain, hwirq);
-               if (virq)
+               if (irq_get_trigger_type(virq) == IRQ_TYPE_NONE) {
+                       irq_data = irq_get_irq_data(virq);
+                       if (!irq_data)
+                               return 0;
+
+                       irqd_set_trigger_type(irq_data, type);
                        return virq;
+               }
 
+               pr_warn("type mismatch, failed to map hwirq-%lu for %s!\n",
+                       hwirq, of_node_full_name(to_of_node(fwspec->fwnode)));
+               return 0;
+       }
+
+       if (irq_domain_is_hierarchy(domain)) {
                virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec);
                if (virq <= 0)
                        return 0;
@@ -607,10 +639,18 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec 
*fwspec)
                        return virq;
        }
 
-       /* Set type if specified and different than the current one */
-       if (type != IRQ_TYPE_NONE &&
-           type != irq_get_trigger_type(virq))
-               irq_set_irq_type(virq, type);
+       irq_data = irq_get_irq_data(virq);
+       if (!irq_data) {
+               if (irq_domain_is_hierarchy(domain))
+                       irq_domain_free_irqs(virq, 1);
+               else
+                       irq_dispose_mapping(virq);
+               return 0;
+       }
+
+       /* Store trigger type */
+       irqd_set_trigger_type(irq_data, type);
+
        return virq;
 }
 EXPORT_SYMBOL_GPL(irq_create_fwspec_mapping);
@@ -640,8 +680,12 @@ void irq_dispose_mapping(unsigned int virq)
        if (WARN_ON(domain == NULL))
                return;
 
-       irq_domain_disassociate(domain, virq);
-       irq_free_desc(virq);
+       if (irq_domain_is_hierarchy(domain)) {
+               irq_domain_free_irqs(virq, 1);
+       } else {
+               irq_domain_disassociate(domain, virq);
+               irq_free_desc(virq);
+       }
 }
 EXPORT_SYMBOL_GPL(irq_dispose_mapping);
 
@@ -835,19 +879,23 @@ const struct irq_domain_ops irq_domain_simple_ops = {
 EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
 
 int irq_domain_alloc_descs(int virq, unsigned int cnt, irq_hw_number_t hwirq,
-                          int node)
+                          int node, const struct cpumask *affinity)
 {
        unsigned int hint;
 
        if (virq >= 0) {
-               virq = irq_alloc_descs(virq, virq, cnt, node);
+               virq = __irq_alloc_descs(virq, virq, cnt, node, THIS_MODULE,
+                                        affinity);
        } else {
                hint = hwirq % nr_irqs;
                if (hint == 0)
                        hint++;
-               virq = irq_alloc_descs_from(hint, cnt, node);
-               if (virq <= 0 && hint > 1)
-                       virq = irq_alloc_descs_from(1, cnt, node);
+               virq = __irq_alloc_descs(-1, hint, cnt, node, THIS_MODULE,
+                                        affinity);
+               if (virq <= 0 && hint > 1) {
+                       virq = __irq_alloc_descs(-1, 1, cnt, node, THIS_MODULE,
+                                                affinity);
+               }
        }
 
        return virq;
@@ -1144,8 +1192,10 @@ int irq_domain_alloc_irqs_recursive(struct irq_domain 
*domain,
        if (recursive)
                ret = irq_domain_alloc_irqs_recursive(parent, irq_base,
                                                      nr_irqs, arg);
-       if (ret >= 0)
-               ret = domain->ops->alloc(domain, irq_base, nr_irqs, arg);
+       if (ret < 0)
+               return ret;
+
+       ret = domain->ops->alloc(domain, irq_base, nr_irqs, arg);
        if (ret < 0 && recursive)
                irq_domain_free_irqs_recursive(parent, irq_base, nr_irqs);
 
@@ -1160,6 +1210,7 @@ int irq_domain_alloc_irqs_recursive(struct irq_domain 
*domain,
  * @node:      NUMA node id for memory allocation
  * @arg:       domain specific argument
  * @realloc:   IRQ descriptors have already been allocated if true
+ * @affinity:  Optional irq affinity mask for multiqueue devices
  *
  * Allocate IRQ numbers and initialized all data structures to support
  * hierarchy IRQ domains.
@@ -1175,7 +1226,7 @@ int irq_domain_alloc_irqs_recursive(struct irq_domain 
*domain,
  */
 int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
                            unsigned int nr_irqs, int node, void *arg,
-                           bool realloc)
+                           bool realloc, const struct cpumask *affinity)
 {
        int i, ret, virq;
 
@@ -1193,7 +1244,8 @@ int __irq_domain_alloc_irqs(struct irq_domain *domain, 
int irq_base,
        if (realloc && irq_base >= 0) {
                virq = irq_base;
        } else {
-               virq = irq_domain_alloc_descs(irq_base, nr_irqs, 0, node);
+               virq = irq_domain_alloc_descs(irq_base, nr_irqs, 0, node,
+                                             affinity);
                if (virq < 0) {
                        pr_debug("cannot allocate IRQ(base %d, count %d)\n",
                                 irq_base, nr_irqs);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index ef0bc02c3a70..73a2b786b5e9 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -115,12 +115,12 @@ EXPORT_SYMBOL(synchronize_irq);
 #ifdef CONFIG_SMP
 cpumask_var_t irq_default_affinity;
 
-static int __irq_can_set_affinity(struct irq_desc *desc)
+static bool __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;
+               return false;
+       return true;
 }
 
 /**
@@ -134,6 +134,21 @@ int irq_can_set_affinity(unsigned int irq)
 }
 
 /**
+ * irq_can_set_affinity_usr - Check if affinity of a irq can be set from user 
space
+ * @irq:       Interrupt to check
+ *
+ * Like irq_can_set_affinity() above, but additionally checks for the
+ * AFFINITY_MANAGED flag.
+ */
+bool irq_can_set_affinity_usr(unsigned int irq)
+{
+       struct irq_desc *desc = irq_to_desc(irq);
+
+       return __irq_can_set_affinity(desc) &&
+               !irqd_affinity_is_managed(&desc->irq_data);
+}
+
+/**
  *     irq_set_thread_affinity - Notify irq threads to adjust affinity
  *     @desc:          irq descriptor which has affitnity changed
  *
@@ -338,10 +353,11 @@ static int setup_affinity(struct irq_desc *desc, struct 
cpumask *mask)
                return 0;
 
        /*
-        * Preserve an userspace affinity setup, but make sure that
-        * one of the targets is online.
+        * Preserve the managed affinity setting and an userspace affinity
+        * setup, but make sure that one of the targets is online.
         */
-       if (irqd_has_set(&desc->irq_data, IRQD_AFFINITY_SET)) {
+       if (irqd_affinity_is_managed(&desc->irq_data) ||
+           irqd_has_set(&desc->irq_data, IRQD_AFFINITY_SET)) {
                if (cpumask_intersects(desc->irq_common_data.affinity,
                                       cpu_online_mask))
                        set = desc->irq_common_data.affinity;
@@ -1117,6 +1133,13 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, 
struct irqaction *new)
        new->irq = irq;
 
        /*
+        * If the trigger type is not specified by the caller,
+        * then use the default for this interrupt.
+        */
+       if (!(new->flags & IRQF_TRIGGER_MASK))
+               new->flags |= irqd_get_trigger_type(&desc->irq_data);
+
+       /*
         * Check whether the interrupt nests into another interrupt
         * thread.
         */
@@ -1409,10 +1432,18 @@ int setup_irq(unsigned int irq, struct irqaction *act)
 
        if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc)))
                return -EINVAL;
+
+       retval = irq_chip_pm_get(&desc->irq_data);
+       if (retval < 0)
+               return retval;
+
        chip_bus_lock(desc);
        retval = __setup_irq(irq, desc, act);
        chip_bus_sync_unlock(desc);
 
+       if (retval)
+               irq_chip_pm_put(&desc->irq_data);
+
        return retval;
 }
 EXPORT_SYMBOL_GPL(setup_irq);
@@ -1506,6 +1537,7 @@ static struct irqaction *__free_irq(unsigned int irq, 
void *dev_id)
                }
        }
 
+       irq_chip_pm_put(&desc->irq_data);
        module_put(desc->owner);
        kfree(action->secondary);
        return action;
@@ -1648,11 +1680,16 @@ int request_threaded_irq(unsigned int irq, 
irq_handler_t handler,
        action->name = devname;
        action->dev_id = dev_id;
 
+       retval = irq_chip_pm_get(&desc->irq_data);
+       if (retval < 0)
+               return retval;
+
        chip_bus_lock(desc);
        retval = __setup_irq(irq, desc, action);
        chip_bus_sync_unlock(desc);
 
        if (retval) {
+               irq_chip_pm_put(&desc->irq_data);
                kfree(action->secondary);
                kfree(action);
        }
@@ -1730,7 +1767,14 @@ void enable_percpu_irq(unsigned int irq, unsigned int 
type)
        if (!desc)
                return;
 
+       /*
+        * If the trigger type is not specified by the caller, then
+        * use the default for this interrupt.
+        */
        type &= IRQ_TYPE_SENSE_MASK;
+       if (type == IRQ_TYPE_NONE)
+               type = irqd_get_trigger_type(&desc->irq_data);
+
        if (type != IRQ_TYPE_NONE) {
                int ret;
 
@@ -1822,6 +1866,7 @@ static struct irqaction *__free_percpu_irq(unsigned int 
irq, void __percpu *dev_
 
        unregister_handler_proc(irq, action);
 
+       irq_chip_pm_put(&desc->irq_data);
        module_put(desc->owner);
        return action;
 
@@ -1884,10 +1929,18 @@ int setup_percpu_irq(unsigned int irq, struct irqaction 
*act)
 
        if (!desc || !irq_settings_is_per_cpu_devid(desc))
                return -EINVAL;
+
+       retval = irq_chip_pm_get(&desc->irq_data);
+       if (retval < 0)
+               return retval;
+
        chip_bus_lock(desc);
        retval = __setup_irq(irq, desc, act);
        chip_bus_sync_unlock(desc);
 
+       if (retval)
+               irq_chip_pm_put(&desc->irq_data);
+
        return retval;
 }
 
@@ -1931,12 +1984,18 @@ int request_percpu_irq(unsigned int irq, irq_handler_t 
handler,
        action->name = devname;
        action->percpu_dev_id = dev_id;
 
+       retval = irq_chip_pm_get(&desc->irq_data);
+       if (retval < 0)
+               return retval;
+
        chip_bus_lock(desc);
        retval = __setup_irq(irq, desc, action);
        chip_bus_sync_unlock(desc);
 
-       if (retval)
+       if (retval) {
+               irq_chip_pm_put(&desc->irq_data);
                kfree(action);
+       }
 
        return retval;
 }
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 38e89ce7b071..54999350162c 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -324,7 +324,7 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct 
device *dev,
        struct msi_domain_ops *ops = info->ops;
        msi_alloc_info_t arg;
        struct msi_desc *desc;
-       int i, ret, virq = -1;
+       int i, ret, virq;
 
        ret = msi_domain_prepare_irqs(domain, dev, nvec, &arg);
        if (ret)
@@ -332,13 +332,10 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, 
struct device *dev,
 
        for_each_msi_entry(desc, dev) {
                ops->set_desc(&arg, desc);
-               if (info->flags & MSI_FLAG_IDENTITY_MAP)
-                       virq = (int)ops->get_hwirq(info, &arg);
-               else
-                       virq = -1;
 
-               virq = __irq_domain_alloc_irqs(domain, virq, desc->nvec_used,
-                                              dev_to_node(dev), &arg, false);
+               virq = __irq_domain_alloc_irqs(domain, -1, desc->nvec_used,
+                                              dev_to_node(dev), &arg, false,
+                                              desc->affinity);
                if (virq < 0) {
                        ret = -ENOSPC;
                        if (ops->handle_error)
@@ -356,6 +353,7 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct 
device *dev,
                ops->msi_finish(&arg, 0);
 
        for_each_msi_entry(desc, dev) {
+               virq = desc->irq;
                if (desc->nvec_used == 1)
                        dev_dbg(dev, "irq %d for MSI\n", virq);
                else
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index 4e1b94726818..feaa813b84a9 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -96,7 +96,7 @@ static ssize_t write_irq_affinity(int type, struct file *file,
        cpumask_var_t new_value;
        int err;
 
-       if (!irq_can_set_affinity(irq) || no_irq_affinity)
+       if (!irq_can_set_affinity_usr(irq) || no_irq_affinity)
                return -EIO;
 
        if (!alloc_cpumask_var(&new_value, GFP_KERNEL))
@@ -311,7 +311,6 @@ void register_handler_proc(unsigned int irq, struct 
irqaction *action)
                                        !name_unique(irq, action))
                return;
 
-       memset(name, 0, MAX_NAMELEN);
        snprintf(name, MAX_NAMELEN, "%s", action->name);
 
        /* create /proc/irq/1234/handler/ */
@@ -340,7 +339,6 @@ void register_irq_proc(unsigned int irq, struct irq_desc 
*desc)
        if (desc->dir)
                goto out_unlock;
 
-       memset(name, 0, MAX_NAMELEN);
        sprintf(name, "%d", irq);
 
        /* create /proc/irq/1234 */
@@ -386,7 +384,6 @@ void unregister_irq_proc(unsigned int irq, struct irq_desc 
*desc)
 #endif
        remove_proc_entry("spurious", desc->dir);
 
-       memset(name, 0, MAX_NAMELEN);
        sprintf(name, "%u", irq);
        remove_proc_entry(name, root_irq_dir);
 }
@@ -421,12 +418,8 @@ void init_irq_proc(void)
        /*
         * Create entries for all existing IRQs.
         */
-       for_each_irq_desc(irq, desc) {
-               if (!desc)
-                       continue;
-
+       for_each_irq_desc(irq, desc)
                register_irq_proc(irq, desc);
-       }
 }
 
 #ifdef CONFIG_GENERIC_IRQ_SHOW

Reply via email to