Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / drivers / irqchip / irq-gic.c
index 095bb5b..1de20e1 100644 (file)
@@ -72,6 +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 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
                        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 @@ 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 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
        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);
@@ -489,7 +486,9 @@ static void gic_cpu_init(struct gic_chip_data *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;
@@ -507,6 +506,8 @@ static void gic_cpu_init(struct gic_chip_data *gic)
 
        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)
@@ -532,34 +533,35 @@ 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);
 }
 
@@ -570,16 +572,17 @@ static void gic_dist_save(unsigned int gic_nr)
  * 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;
@@ -587,7 +590,7 @@ static void gic_dist_restore(unsigned int gic_nr)
        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++)
@@ -595,85 +598,87 @@ static void gic_dist_restore(unsigned int gic_nr)
                        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);
 
@@ -682,7 +687,7 @@ static void gic_cpu_restore(unsigned int gic_nr)
                                        dist_base + GIC_DIST_PRI + i * 4);
 
        writel_relaxed(GICC_INT_PRI_THRESHOLD, cpu_base + GIC_CPU_PRIMASK);
-       gic_cpu_if_up(&gic_data[gic_nr]);
+       gic_cpu_if_up(gic);
 }
 
 static int gic_notifier(struct notifier_block *self, unsigned long cmd,        void *v)
@@ -697,18 +702,18 @@ 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 +725,39 @@ static struct notifier_block gic_notifier_block = {
        .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 +1030,63 @@ static const struct irq_domain_ops gic_irq_domain_ops = {
        .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;
 
        /* 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);
        }
 
@@ -1089,7 +1109,7 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
                 * 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;
@@ -1111,10 +1131,12 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
                                        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.
@@ -1132,19 +1154,57 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
        }
 
        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 +1248,61 @@ static bool gic_check_eoimode(struct device_node *node, void __iomem **base)
        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 +1389,9 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
                                   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,
@@ -1315,17 +1401,18 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
                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;
        }
 
@@ -1340,15 +1427,20 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
        /*
         * 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);