]> Git Repo - linux.git/commitdiff
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <[email protected]>
Tue, 17 May 2016 17:27:29 +0000 (10:27 -0700)
committerLinus Torvalds <[email protected]>
Tue, 17 May 2016 17:27:29 +0000 (10:27 -0700)
Pull irq updates from Thomas Gleixner:
 "This update delivers:

   - Yet another interrupt chip diver (LPC32xx)
   - Core functions to handle partitioned per-cpu interrupts
   - Enhancements to the IPI core
   - Proper handling of irq type configuration
   - A large set of ARM GIC enhancements
   - The usual pile of small fixes, cleanups and enhancements"

* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (31 commits)
  irqchip/bcm2836: Use a more generic memory barrier call
  irqchip/bcm2836: Fix compiler warning on 64-bit build
  irqchip/bcm2836: Drop smp_set_ops on arm64 builds
  irqchip/gic: Add helper functions for GIC setup and teardown
  irqchip/gic: Store GIC configuration parameters
  irqchip/gic: Pass GIC pointer to save/restore functions
  irqchip/gic: Return an error if GIC initialisation fails
  irqchip/gic: Remove static irq_chip definition for eoimode1
  irqchip/gic: Don't initialise chip if mapping IO space fails
  irqchip/gic: WARN if setting the interrupt type for a PPI fails
  irqchip/gic: Don't unnecessarily write the IRQ configuration
  irqchip: Mask the non-type/sense bits when translating an IRQ
  genirq: Ensure IRQ descriptor is valid when setting-up the IRQ
  irqchip/gic-v3: Configure all interrupts as non-secure Group-1
  irqchip/gic-v2m: Add workaround for Broadcom NS2 GICv2m erratum
  irqchip/irq-alpine-msi: Don't use <asm-generic/msi.h>
  irqchip/mbigen: Checking for IS_ERR() instead of NULL
  irqchip/gic-v3: Remove inexistant register definition
  irqchip/gicv3-its: Don't allow devices whose ID is outside range
  irqchip: Add LPC32xx interrupt controller driver
  ...

1  2 
drivers/irqchip/irq-gic.c

index 095bb5b5c3f2bee0c45a7a763fb33dbb1b023112,113e2d02c81246e1836361f3f16798c654ae7dfb..1de20e14a721111737bdab39c575ab7a45ddc63b
@@@ -55,7 -55,7 +55,7 @@@
  
  static void gic_check_cpu_features(void)
  {
 -      WARN_TAINT_ONCE(cpus_have_cap(ARM64_HAS_SYSREG_GIC_CPUIF),
 +      WARN_TAINT_ONCE(this_cpu_has_cap(ARM64_HAS_SYSREG_GIC_CPUIF),
                        TAINT_CPU_OUT_OF_SPEC,
                        "GICv3 system registers enabled, broken firmware!\n");
  }
@@@ -72,6 -72,9 +72,9 @@@ struct gic_chip_data 
        struct irq_chip chip;
        union gic_base dist_base;
        union gic_base cpu_base;
+       void __iomem *raw_dist_base;
+       void __iomem *raw_cpu_base;
+       u32 percpu_offset;
  #ifdef CONFIG_CPU_PM
        u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
        u32 saved_spi_active[DIV_ROUND_UP(1020, 32)];
@@@ -344,6 -347,14 +347,14 @@@ static void __exception_irq_entry gic_h
                        if (static_key_true(&supports_deactivate))
                                writel_relaxed(irqstat, cpu_base + GIC_CPU_DEACTIVATE);
  #ifdef CONFIG_SMP
+                       /*
+                        * Ensure any shared data written by the CPU sending
+                        * the IPI is read after we've read the ACK register
+                        * on the GIC.
+                        *
+                        * Pairs with the write barrier in gic_raise_softirq
+                        */
+                       smp_rmb();
                        handle_IPI(irqnr, regs);
  #endif
                        continue;
@@@ -391,20 -402,6 +402,6 @@@ static struct irq_chip gic_chip = 
                                  IRQCHIP_MASK_ON_SUSPEND,
  };
  
- static struct irq_chip gic_eoimode1_chip = {
-       .name                   = "GICv2",
-       .irq_mask               = gic_eoimode1_mask_irq,
-       .irq_unmask             = gic_unmask_irq,
-       .irq_eoi                = gic_eoimode1_eoi_irq,
-       .irq_set_type           = gic_set_type,
-       .irq_get_irqchip_state  = gic_irq_get_irqchip_state,
-       .irq_set_irqchip_state  = gic_irq_set_irqchip_state,
-       .irq_set_vcpu_affinity  = gic_irq_set_vcpu_affinity,
-       .flags                  = IRQCHIP_SET_TYPE_MASKED |
-                                 IRQCHIP_SKIP_SET_WAKE |
-                                 IRQCHIP_MASK_ON_SUSPEND,
- };
  void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
  {
        BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
@@@ -473,7 -470,7 +470,7 @@@ static void __init gic_dist_init(struc
        writel_relaxed(GICD_ENABLE, base + GIC_DIST_CTRL);
  }
  
- static void gic_cpu_init(struct gic_chip_data *gic)
+ static int gic_cpu_init(struct gic_chip_data *gic)
  {
        void __iomem *dist_base = gic_data_dist_base(gic);
        void __iomem *base = gic_data_cpu_base(gic);
                /*
                 * Get what the GIC says our CPU mask is.
                 */
-               BUG_ON(cpu >= NR_GIC_CPU_IF);
+               if (WARN_ON(cpu >= NR_GIC_CPU_IF))
+                       return -EINVAL;
 +              gic_check_cpu_features();
                cpu_mask = gic_get_cpumask(gic);
                gic_cpu_map[cpu] = cpu_mask;
  
  
        writel_relaxed(GICC_INT_PRI_THRESHOLD, base + GIC_CPU_PRIMASK);
        gic_cpu_if_up(gic);
+       return 0;
  }
  
  int gic_cpu_if_down(unsigned int gic_nr)
   * this function, no interrupts will be delivered by the GIC, and another
   * platform-specific wakeup source must be enabled.
   */
- static void gic_dist_save(unsigned int gic_nr)
+ static void gic_dist_save(struct gic_chip_data *gic)
  {
        unsigned int gic_irqs;
        void __iomem *dist_base;
        int i;
  
-       BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
+       if (WARN_ON(!gic))
+               return;
  
-       gic_irqs = gic_data[gic_nr].gic_irqs;
-       dist_base = gic_data_dist_base(&gic_data[gic_nr]);
+       gic_irqs = gic->gic_irqs;
+       dist_base = gic_data_dist_base(gic);
  
        if (!dist_base)
                return;
  
        for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
-               gic_data[gic_nr].saved_spi_conf[i] =
+               gic->saved_spi_conf[i] =
                        readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
  
        for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
-               gic_data[gic_nr].saved_spi_target[i] =
+               gic->saved_spi_target[i] =
                        readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
  
        for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
-               gic_data[gic_nr].saved_spi_enable[i] =
+               gic->saved_spi_enable[i] =
                        readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
  
        for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
-               gic_data[gic_nr].saved_spi_active[i] =
+               gic->saved_spi_active[i] =
                        readl_relaxed(dist_base + GIC_DIST_ACTIVE_SET + i * 4);
  }
  
   * 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(unsigned int gic_nr)
+ static void gic_dist_restore(struct gic_chip_data *gic)
  {
        unsigned int gic_irqs;
        unsigned int i;
        void __iomem *dist_base;
  
-       BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
+       if (WARN_ON(!gic))
+               return;
  
-       gic_irqs = gic_data[gic_nr].gic_irqs;
-       dist_base = gic_data_dist_base(&gic_data[gic_nr]);
+       gic_irqs = gic->gic_irqs;
+       dist_base = gic_data_dist_base(gic);
  
        if (!dist_base)
                return;
        writel_relaxed(GICD_DISABLE, dist_base + GIC_DIST_CTRL);
  
        for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
-               writel_relaxed(gic_data[gic_nr].saved_spi_conf[i],
+               writel_relaxed(gic->saved_spi_conf[i],
                        dist_base + GIC_DIST_CONFIG + i * 4);
  
        for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
                        dist_base + GIC_DIST_PRI + i * 4);
  
        for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
-               writel_relaxed(gic_data[gic_nr].saved_spi_target[i],
+               writel_relaxed(gic->saved_spi_target[i],
                        dist_base + GIC_DIST_TARGET + i * 4);
  
        for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) {
                writel_relaxed(GICD_INT_EN_CLR_X32,
                        dist_base + GIC_DIST_ENABLE_CLEAR + i * 4);
-               writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
+               writel_relaxed(gic->saved_spi_enable[i],
                        dist_base + GIC_DIST_ENABLE_SET + i * 4);
        }
  
        for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) {
                writel_relaxed(GICD_INT_EN_CLR_X32,
                        dist_base + GIC_DIST_ACTIVE_CLEAR + i * 4);
-               writel_relaxed(gic_data[gic_nr].saved_spi_active[i],
+               writel_relaxed(gic->saved_spi_active[i],
                        dist_base + GIC_DIST_ACTIVE_SET + i * 4);
        }
  
        writel_relaxed(GICD_ENABLE, dist_base + GIC_DIST_CTRL);
  }
  
- static void gic_cpu_save(unsigned int gic_nr)
+ static void gic_cpu_save(struct gic_chip_data *gic)
  {
        int i;
        u32 *ptr;
        void __iomem *dist_base;
        void __iomem *cpu_base;
  
-       BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
+       if (WARN_ON(!gic))
+               return;
  
-       dist_base = gic_data_dist_base(&gic_data[gic_nr]);
-       cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
+       dist_base = gic_data_dist_base(gic);
+       cpu_base = gic_data_cpu_base(gic);
  
        if (!dist_base || !cpu_base)
                return;
  
-       ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
+       ptr = raw_cpu_ptr(gic->saved_ppi_enable);
        for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
                ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
  
-       ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_active);
+       ptr = raw_cpu_ptr(gic->saved_ppi_active);
        for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
                ptr[i] = readl_relaxed(dist_base + GIC_DIST_ACTIVE_SET + i * 4);
  
-       ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
+       ptr = raw_cpu_ptr(gic->saved_ppi_conf);
        for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
                ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
  
  }
  
- static void gic_cpu_restore(unsigned int gic_nr)
+ static void gic_cpu_restore(struct gic_chip_data *gic)
  {
        int i;
        u32 *ptr;
        void __iomem *dist_base;
        void __iomem *cpu_base;
  
-       BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
+       if (WARN_ON(!gic))
+               return;
  
-       dist_base = gic_data_dist_base(&gic_data[gic_nr]);
-       cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
+       dist_base = gic_data_dist_base(gic);
+       cpu_base = gic_data_cpu_base(gic);
  
        if (!dist_base || !cpu_base)
                return;
  
-       ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
+       ptr = raw_cpu_ptr(gic->saved_ppi_enable);
        for (i = 0; i < DIV_ROUND_UP(32, 32); i++) {
                writel_relaxed(GICD_INT_EN_CLR_X32,
                               dist_base + GIC_DIST_ENABLE_CLEAR + i * 4);
                writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4);
        }
  
-       ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_active);
+       ptr = raw_cpu_ptr(gic->saved_ppi_active);
        for (i = 0; i < DIV_ROUND_UP(32, 32); i++) {
                writel_relaxed(GICD_INT_EN_CLR_X32,
                               dist_base + GIC_DIST_ACTIVE_CLEAR + i * 4);
                writel_relaxed(ptr[i], dist_base + GIC_DIST_ACTIVE_SET + i * 4);
        }
  
-       ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
+       ptr = raw_cpu_ptr(gic->saved_ppi_conf);
        for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
                writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4);
  
                                        dist_base + GIC_DIST_PRI + i * 4);
  
        writel_relaxed(GICC_INT_PRI_THRESHOLD, cpu_base + GIC_CPU_PRIMASK);
-       gic_cpu_if_up(&gic_data[gic_nr]);
+       gic_cpu_if_up(gic);
  }
  
  static int gic_notifier(struct notifier_block *self, unsigned long cmd,       void *v)
  #endif
                switch (cmd) {
                case CPU_PM_ENTER:
-                       gic_cpu_save(i);
+                       gic_cpu_save(&gic_data[i]);
                        break;
                case CPU_PM_ENTER_FAILED:
                case CPU_PM_EXIT:
-                       gic_cpu_restore(i);
+                       gic_cpu_restore(&gic_data[i]);
                        break;
                case CPU_CLUSTER_PM_ENTER:
-                       gic_dist_save(i);
+                       gic_dist_save(&gic_data[i]);
                        break;
                case CPU_CLUSTER_PM_ENTER_FAILED:
                case CPU_CLUSTER_PM_EXIT:
-                       gic_dist_restore(i);
+                       gic_dist_restore(&gic_data[i]);
                        break;
                }
        }
@@@ -720,26 -724,39 +725,39 @@@ static struct notifier_block gic_notifi
        .notifier_call = gic_notifier,
  };
  
- static void __init gic_pm_init(struct gic_chip_data *gic)
+ static int __init gic_pm_init(struct gic_chip_data *gic)
  {
        gic->saved_ppi_enable = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4,
                sizeof(u32));
-       BUG_ON(!gic->saved_ppi_enable);
+       if (WARN_ON(!gic->saved_ppi_enable))
+               return -ENOMEM;
  
        gic->saved_ppi_active = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4,
                sizeof(u32));
-       BUG_ON(!gic->saved_ppi_active);
+       if (WARN_ON(!gic->saved_ppi_active))
+               goto free_ppi_enable;
  
        gic->saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4,
                sizeof(u32));
-       BUG_ON(!gic->saved_ppi_conf);
+       if (WARN_ON(!gic->saved_ppi_conf))
+               goto free_ppi_active;
  
        if (gic == &gic_data[0])
                cpu_pm_register_notifier(&gic_notifier_block);
+       return 0;
+ free_ppi_active:
+       free_percpu(gic->saved_ppi_active);
+ free_ppi_enable:
+       free_percpu(gic->saved_ppi_enable);
+       return -ENOMEM;
  }
  #else
- static void __init gic_pm_init(struct gic_chip_data *gic)
+ static int __init gic_pm_init(struct gic_chip_data *gic)
  {
+       return 0;
  }
  #endif
  
@@@ -1012,61 -1029,65 +1030,63 @@@ static const struct irq_domain_ops gic_
        .unmap = gic_irq_domain_unmap,
  };
  
- static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
-                          void __iomem *dist_base, void __iomem *cpu_base,
-                          u32 percpu_offset, struct fwnode_handle *handle)
+ static int __init __gic_init_bases(struct gic_chip_data *gic, int irq_start,
+                                  struct fwnode_handle *handle)
  {
        irq_hw_number_t hwirq_base;
-       struct gic_chip_data *gic;
-       int gic_irqs, irq_base, i;
-       BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
+       int gic_irqs, irq_base, i, ret;
  
-       gic = &gic_data[gic_nr];
+       if (WARN_ON(!gic || gic->domain))
+               return -EINVAL;
  
 -      gic_check_cpu_features();
 -
        /* Initialize irq_chip */
-       if (static_key_true(&supports_deactivate) && gic_nr == 0) {
-               gic->chip = gic_eoimode1_chip;
+       gic->chip = gic_chip;
+       if (static_key_true(&supports_deactivate) && gic == &gic_data[0]) {
+               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 = gic_chip;
-               gic->chip.name = kasprintf(GFP_KERNEL, "GIC-%d", gic_nr);
+               gic->chip.name = kasprintf(GFP_KERNEL, "GIC-%d",
+                                          (int)(gic - &gic_data[0]));
        }
  
  #ifdef CONFIG_SMP
-       if (gic_nr == 0)
+       if (gic == &gic_data[0])
                gic->chip.irq_set_affinity = gic_set_affinity;
  #endif
  
- #ifdef CONFIG_GIC_NON_BANKED
-       if (percpu_offset) { /* Frankein-GIC without banked registers... */
+       if (IS_ENABLED(CONFIG_GIC_NON_BANKED) && gic->percpu_offset) {
+               /* Frankein-GIC without banked registers... */
                unsigned int cpu;
  
                gic->dist_base.percpu_base = alloc_percpu(void __iomem *);
                gic->cpu_base.percpu_base = alloc_percpu(void __iomem *);
                if (WARN_ON(!gic->dist_base.percpu_base ||
                            !gic->cpu_base.percpu_base)) {
-                       free_percpu(gic->dist_base.percpu_base);
-                       free_percpu(gic->cpu_base.percpu_base);
-                       return;
+                       ret = -ENOMEM;
+                       goto error;
                }
  
                for_each_possible_cpu(cpu) {
                        u32 mpidr = cpu_logical_map(cpu);
                        u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
-                       unsigned long offset = percpu_offset * core_id;
-                       *per_cpu_ptr(gic->dist_base.percpu_base, cpu) = dist_base + offset;
-                       *per_cpu_ptr(gic->cpu_base.percpu_base, cpu) = cpu_base + offset;
+                       unsigned long offset = gic->percpu_offset * core_id;
+                       *per_cpu_ptr(gic->dist_base.percpu_base, cpu) =
+                               gic->raw_dist_base + offset;
+                       *per_cpu_ptr(gic->cpu_base.percpu_base, cpu) =
+                               gic->raw_cpu_base + offset;
                }
  
                gic_set_base_accessor(gic, gic_get_percpu_base);
-       } else
- #endif
-       {                       /* Normal, sane GIC... */
-               WARN(percpu_offset,
+       } else {
+               /* Normal, sane GIC... */
+               WARN(gic->percpu_offset,
                     "GIC_NON_BANKED not enabled, ignoring %08x offset!",
-                    percpu_offset);
-               gic->dist_base.common_base = dist_base;
-               gic->cpu_base.common_base = cpu_base;
+                    gic->percpu_offset);
+               gic->dist_base.common_base = gic->raw_dist_base;
+               gic->cpu_base.common_base = gic->raw_cpu_base;
                gic_set_base_accessor(gic, gic_get_common_base);
        }
  
                 * For primary GICs, skip over SGIs.
                 * For secondary GICs, skip over PPIs, too.
                 */
-               if (gic_nr == 0 && (irq_start & 31) > 0) {
+               if (gic == &gic_data[0] && (irq_start & 31) > 0) {
                        hwirq_base = 16;
                        if (irq_start != -1)
                                irq_start = (irq_start & ~31) + 16;
                                        hwirq_base, &gic_irq_domain_ops, gic);
        }
  
-       if (WARN_ON(!gic->domain))
-               return;
+       if (WARN_ON(!gic->domain)) {
+               ret = -ENODEV;
+               goto error;
+       }
  
-       if (gic_nr == 0) {
+       if (gic == &gic_data[0]) {
                /*
                 * Initialize the CPU interface map to all CPUs.
                 * It will be refined as each CPU probes its ID.
        }
  
        gic_dist_init(gic);
-       gic_cpu_init(gic);
-       gic_pm_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);
+       }
+       kfree(gic->chip.name);
+       return ret;
  }
  
  void __init gic_init(unsigned int gic_nr, int irq_start,
                     void __iomem *dist_base, void __iomem *cpu_base)
  {
+       struct gic_chip_data *gic;
+       if (WARN_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR))
+               return;
        /*
         * Non-DT/ACPI systems won't run a hypervisor, so let's not
         * bother with these...
         */
        static_key_slow_dec(&supports_deactivate);
-       __gic_init_bases(gic_nr, irq_start, dist_base, cpu_base, 0, NULL);
+       gic = &gic_data[gic_nr];
+       gic->raw_dist_base = dist_base;
+       gic->raw_cpu_base = cpu_base;
+       __gic_init_bases(gic, irq_start, NULL);
+ }
+ static void gic_teardown(struct gic_chip_data *gic)
+ {
+       if (WARN_ON(!gic))
+               return;
+       if (gic->raw_dist_base)
+               iounmap(gic->raw_dist_base);
+       if (gic->raw_cpu_base)
+               iounmap(gic->raw_cpu_base);
  }
  
  #ifdef CONFIG_OF
@@@ -1188,35 -1249,61 +1248,61 @@@ static bool gic_check_eoimode(struct de
        return true;
  }
  
+ static int gic_of_setup(struct gic_chip_data *gic, struct device_node *node)
+ {
+       if (!gic || !node)
+               return -EINVAL;
+       gic->raw_dist_base = of_iomap(node, 0);
+       if (WARN(!gic->raw_dist_base, "unable to map gic dist registers\n"))
+               goto error;
+       gic->raw_cpu_base = of_iomap(node, 1);
+       if (WARN(!gic->raw_cpu_base, "unable to map gic cpu registers\n"))
+               goto error;
+       if (of_property_read_u32(node, "cpu-offset", &gic->percpu_offset))
+               gic->percpu_offset = 0;
+       return 0;
+ error:
+       gic_teardown(gic);
+       return -ENOMEM;
+ }
  int __init
  gic_of_init(struct device_node *node, struct device_node *parent)
  {
-       void __iomem *cpu_base;
-       void __iomem *dist_base;
-       u32 percpu_offset;
-       int irq;
+       struct gic_chip_data *gic;
+       int irq, ret;
  
        if (WARN_ON(!node))
                return -ENODEV;
  
-       dist_base = of_iomap(node, 0);
-       WARN(!dist_base, "unable to map gic dist registers\n");
+       if (WARN_ON(gic_cnt >= CONFIG_ARM_GIC_MAX_NR))
+               return -EINVAL;
+       gic = &gic_data[gic_cnt];
  
-       cpu_base = of_iomap(node, 1);
-       WARN(!cpu_base, "unable to map gic cpu registers\n");
+       ret = gic_of_setup(gic, node);
+       if (ret)
+               return ret;
  
        /*
         * Disable split EOI/Deactivate if either HYP is not available
         * or the CPU interface is too small.
         */
-       if (gic_cnt == 0 && !gic_check_eoimode(node, &cpu_base))
+       if (gic_cnt == 0 && !gic_check_eoimode(node, &gic->raw_cpu_base))
                static_key_slow_dec(&supports_deactivate);
  
-       if (of_property_read_u32(node, "cpu-offset", &percpu_offset))
-               percpu_offset = 0;
+       ret = __gic_init_bases(gic, -1, &node->fwnode);
+       if (ret) {
+               gic_teardown(gic);
+               return ret;
+       }
  
-       __gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset,
-                        &node->fwnode);
        if (!gic_cnt)
                gic_init_physaddr(node);
  
@@@ -1303,9 -1390,9 +1389,9 @@@ static int __init gic_v2_acpi_init(stru
                                   const unsigned long end)
  {
        struct acpi_madt_generic_distributor *dist;
-       void __iomem *cpu_base, *dist_base;
        struct fwnode_handle *domain_handle;
-       int count;
+       struct gic_chip_data *gic = &gic_data[0];
+       int count, ret;
  
        /* Collect CPU base addresses */
        count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
                return -EINVAL;
        }
  
-       cpu_base = ioremap(cpu_phy_base, ACPI_GIC_CPU_IF_MEM_SIZE);
-       if (!cpu_base) {
+       gic->raw_cpu_base = ioremap(cpu_phy_base, ACPI_GIC_CPU_IF_MEM_SIZE);
+       if (!gic->raw_cpu_base) {
                pr_err("Unable to map GICC registers\n");
                return -ENOMEM;
        }
  
        dist = (struct acpi_madt_generic_distributor *)header;
-       dist_base = ioremap(dist->base_address, ACPI_GICV2_DIST_MEM_SIZE);
-       if (!dist_base) {
+       gic->raw_dist_base = ioremap(dist->base_address,
+                                    ACPI_GICV2_DIST_MEM_SIZE);
+       if (!gic->raw_dist_base) {
                pr_err("Unable to map GICD registers\n");
-               iounmap(cpu_base);
+               gic_teardown(gic);
                return -ENOMEM;
        }
  
        /*
         * Initialize GIC instance zero (no multi-GIC support).
         */
-       domain_handle = irq_domain_alloc_fwnode(dist_base);
+       domain_handle = irq_domain_alloc_fwnode(gic->raw_dist_base);
        if (!domain_handle) {
                pr_err("Unable to allocate domain handle\n");
-               iounmap(cpu_base);
-               iounmap(dist_base);
+               gic_teardown(gic);
                return -ENOMEM;
        }
  
-       __gic_init_bases(0, -1, dist_base, cpu_base, 0, domain_handle);
+       ret = __gic_init_bases(gic, -1, domain_handle);
+       if (ret) {
+               pr_err("Failed to initialise GIC\n");
+               irq_domain_free_fwnode(domain_handle);
+               gic_teardown(gic);
+               return ret;
+       }
  
        acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle);
  
This page took 0.140296 seconds and 4 git commands to generate.