x86/irq: Refine the way to allocate irq_cfg for legacy IRQs
authorJiang Liu <jiang.liu@linux.intel.com>
Mon, 13 Apr 2015 06:11:56 +0000 (14:11 +0800)
committerThomas Gleixner <tglx@linutronix.de>
Fri, 24 Apr 2015 13:36:51 +0000 (15:36 +0200)
To support legacy ISA IRQs, we need to preallocate irq_cfg structures
for legacy ISA IRQs. Refine the way to allocate irq_cfg for legacy ISA
IRQs, so it's more friendly for the hierarchical irqdomain
implementation.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Tested-by: Joerg Roedel <jroedel@suse.de>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: David Cohen <david.a.cohen@linux.intel.com>
Cc: Sander Eikelenboom <linux@eikelenboom.it>
Cc: David Vrabel <david.vrabel@citrix.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dimitri Sivanich <sivanich@sgi.com>
Cc: Grant Likely <grant.likely@linaro.org>
Link: http://lkml.kernel.org/r/1428905519-23704-35-git-send-email-jiang.liu@linux.intel.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/vector.c

index 3406dbec15706b3e4d2fdbfde9ac60b06b1474fd..16d4ba3ac844d44a0eac2692f79650a14657bcec 100644 (file)
@@ -254,8 +254,7 @@ static void free_ioapic_saved_registers(int idx)
 
 int __init arch_early_ioapic_init(void)
 {
-       struct irq_cfg *cfg;
-       int i, node = cpu_to_node(0);
+       int i;
 
        if (!nr_legacy_irqs())
                io_apic_irqs = ~0UL;
@@ -263,16 +262,6 @@ int __init arch_early_ioapic_init(void)
        for_each_ioapic(i)
                alloc_ioapic_saved_registers(i);
 
-       /*
-        * For legacy IRQ's, start with assigning irq0 to irq15 to
-        * IRQ0_VECTOR to IRQ15_VECTOR for all cpu's.
-        */
-       for (i = 0; i < nr_legacy_irqs(); i++) {
-               cfg = alloc_irq_and_cfg_at(i, node);
-               cfg->vector = IRQ0_VECTOR + i;
-               cpumask_setall(cfg->domain);
-       }
-
        return 0;
 }
 
index b4b6b5a134403eba95b375e48285a9a1262168ec..633f03268d481c10788ecb55222cdf375e5bcdfa 100644 (file)
@@ -24,6 +24,9 @@
 struct irq_domain *x86_vector_domain;
 static DEFINE_RAW_SPINLOCK(vector_lock);
 static struct irq_chip lapic_controller;
+#ifdef CONFIG_X86_IO_APIC
+static struct irq_cfg *legacy_irq_cfgs[NR_IRQS_LEGACY];
+#endif
 
 void lock_vector_lock(void)
 {
@@ -283,6 +286,10 @@ static void x86_vector_free_irqs(struct irq_domain *domain,
                        free_remapped_irq(virq);
                        clear_irq_vector(virq + i, irq_data->chip_data);
                        free_irq_cfg(irq_data->chip_data);
+#ifdef CONFIG_X86_IO_APIC
+                       if (virq + i < nr_legacy_irqs())
+                               legacy_irq_cfgs[virq + i] = NULL;
+#endif
                        irq_domain_reset_irq_data(irq_data);
                }
        }
@@ -308,7 +315,12 @@ static int x86_vector_alloc_irqs(struct irq_domain *domain, unsigned int virq,
        for (i = 0; i < nr_irqs; i++) {
                irq_data = irq_domain_get_irq_data(domain, virq + i);
                BUG_ON(!irq_data);
-               cfg = alloc_irq_cfg(irq_data->node);
+#ifdef CONFIG_X86_IO_APIC
+               if (virq + i < nr_legacy_irqs() && legacy_irq_cfgs[virq + i])
+                       cfg = legacy_irq_cfgs[virq + i];
+               else
+#endif
+                       cfg = alloc_irq_cfg(irq_data->node);
                if (!cfg) {
                        err = -ENOMEM;
                        goto error;
@@ -357,8 +369,36 @@ int __init arch_probe_nr_irqs(void)
        return nr_legacy_irqs();
 }
 
+#ifdef CONFIG_X86_IO_APIC
+static void init_legacy_irqs(void)
+{
+       int i, node = cpu_to_node(0);
+       struct irq_cfg *cfg;
+
+       /*
+        * For legacy IRQ's, start with assigning irq0 to irq15 to
+        * IRQ0_VECTOR to IRQ15_VECTOR for all cpu's.
+        */
+       for (i = 0; i < nr_legacy_irqs(); i++) {
+               cfg = legacy_irq_cfgs[i] = alloc_irq_cfg(node);
+               BUG_ON(!cfg);
+               /*
+                * For legacy IRQ's, start with assigning irq0 to irq15 to
+                * IRQ0_VECTOR to IRQ15_VECTOR for all cpu's.
+                */
+               cfg->vector = IRQ0_VECTOR + i;
+               cpumask_setall(cfg->domain);
+               irq_set_chip_data(i, cfg);
+       }
+}
+#else
+static void init_legacy_irqs(void) { }
+#endif
+
 int __init arch_early_irq_init(void)
 {
+       init_legacy_irqs();
+
        x86_vector_domain = irq_domain_add_tree(NULL, &x86_vector_domain_ops,
                                                NULL);
        BUG_ON(x86_vector_domain == NULL);