irqchip/gic: Isolate early GIC initialisation code
authorJon Hunter <jonathanh@nvidia.com>
Tue, 7 Jun 2016 15:12:30 +0000 (16:12 +0100)
committerMarc Zyngier <marc.zyngier@arm.com>
Mon, 13 Jun 2016 10:53:51 +0000 (11:53 +0100)
To re-use the code that initialises the GIC (found in
__gic_init_bases()), from within a platform driver, it is necessary to
move the code from the __init section so that it is always present and
not removed. Unfortunately, it is not possible to simply drop the __init
from the function declaration for __gic_init_bases() because it contains
calls to set_smp_cross_call() and set_handle_irq() which are both
located in the __init section. Fortunately, these calls are only
required for the root controller and because the initial platform driver
will only support non-root controllers that can be initialised later in
the boot process, we can move these calls to another function.

Move the bulk of the code from __gic_init_bases() to a new function
called gic_init_bases() which is not located in the __init section and
can be used by the platform driver. Update __gic_init_bases() to call
gic_init_bases() and if necessary, set_smp_cross_call() and
set_handle_irq().

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
drivers/irqchip/irq-gic.c

index fbc4ae2..fa0dd98 100644 (file)
@@ -1032,14 +1032,11 @@ 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 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, i, ret;
-
-       if (WARN_ON(!gic || gic->domain))
-               return -EINVAL;
+       int gic_irqs, irq_base, ret;
 
        /* Initialize irq_chip */
        gic->chip = gic_chip;
@@ -1138,23 +1135,6 @@ static int __init __gic_init_bases(struct gic_chip_data *gic, int irq_start,
                goto error;
        }
 
-       if (gic == &gic_data[0]) {
-               /*
-                * Initialize the CPU interface map to all CPUs.
-                * It will be refined as each CPU probes its ID.
-                * This is only necessary for the primary GIC.
-                */
-               for (i = 0; i < NR_GIC_CPU_IF; i++)
-                       gic_cpu_map[i] = 0xff;
-#ifdef CONFIG_SMP
-               set_smp_cross_call(gic_raise_softirq);
-               register_cpu_notifier(&gic_cpu_notifier);
-#endif
-               set_handle_irq(gic_handle_irq);
-               if (static_key_true(&supports_deactivate))
-                       pr_info("GIC: Using split EOI/Deactivate mode\n");
-       }
-
        gic_dist_init(gic);
        ret = gic_cpu_init(gic);
        if (ret)
@@ -1177,6 +1157,35 @@ error:
        return ret;
 }
 
+static int __init __gic_init_bases(struct gic_chip_data *gic,
+                                  int irq_start,
+                                  struct fwnode_handle *handle)
+{
+       int i;
+
+       if (WARN_ON(!gic || gic->domain))
+               return -EINVAL;
+
+       if (gic == &gic_data[0]) {
+               /*
+                * Initialize the CPU interface map to all CPUs.
+                * It will be refined as each CPU probes its ID.
+                * This is only necessary for the primary GIC.
+                */
+               for (i = 0; i < NR_GIC_CPU_IF; i++)
+                       gic_cpu_map[i] = 0xff;
+#ifdef CONFIG_SMP
+               set_smp_cross_call(gic_raise_softirq);
+               register_cpu_notifier(&gic_cpu_notifier);
+#endif
+               set_handle_irq(gic_handle_irq);
+               if (static_key_true(&supports_deactivate))
+                       pr_info("GIC: Using split EOI/Deactivate mode\n");
+       }
+
+       return gic_init_bases(gic, irq_start, handle);
+}
+
 void __init gic_init(unsigned int gic_nr, int irq_start,
                     void __iomem *dist_base, void __iomem *cpu_base)
 {