x86: unify mp_register_gsi
authorAlexey Starikovskiy <astarikovskiy@suse.de>
Fri, 4 Apr 2008 19:43:12 +0000 (23:43 +0400)
committerIngo Molnar <mingo@elte.hu>
Thu, 17 Apr 2008 15:41:36 +0000 (17:41 +0200)
Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/kernel/mpparse_32.c
arch/x86/kernel/mpparse_64.c

index 1ad8a5d4e3ee8e4d1d5d877769b688fd31f8e79d..6376791cffe557df60019dc82f17c64443620810 100644 (file)
@@ -994,14 +994,15 @@ void __init mp_config_acpi_legacy_irqs(void)
        }
 }
 
-#define MAX_GSI_NUM    4096
-#define IRQ_COMPRESSION_START  64
-
 int mp_register_gsi(u32 gsi, int triggering, int polarity)
 {
        int ioapic = -1;
        int ioapic_pin = 0;
        int idx, bit = 0;
+#ifdef CONFIG_X86_32
+#define MAX_GSI_NUM    4096
+#define IRQ_COMPRESSION_START  64
+
        static int pci_irq = IRQ_COMPRESSION_START;
        /*
         * Mapping between Global System Interrupts, which
@@ -1009,6 +1010,11 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
         * assigned to actual devices.
         */
        static int gsi_to_irq[MAX_GSI_NUM];
+#else
+
+       if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
+               return gsi;
+#endif
 
        /* Don't set up the ACPI SCI because it's already set up */
        if (acpi_gbl_FADT.sci_interrupt == gsi)
@@ -1022,8 +1028,10 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
 
        ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
 
+#ifdef CONFIG_X86_32
        if (ioapic_renumber_irq)
                gsi = ioapic_renumber_irq(ioapic, gsi);
+#endif
 
        /*
         * Avoid pin reprogramming.  PRTs typically include entries
@@ -1041,11 +1049,15 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
        if ((1 << bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
                Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
                        mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+#ifdef CONFIG_X86_32
                return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
+#else
+               return gsi;
+#endif
        }
 
        mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1 << bit);
-
+#ifdef CONFIG_X86_32
        /*
         * For GSI >= 64, use IRQ compression
         */
@@ -1079,7 +1091,7 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
                        return gsi;
                }
        }
-
+#endif
        io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
                                triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
                                polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
index 8ad365136a6b8ed938c1de8a3ed9a3601055be41..7d742577d68aaae2448f9b52a2ac45868dcd1591 100644 (file)
@@ -685,6 +685,8 @@ void __init find_smp_config(void)
 
 #ifdef CONFIG_ACPI
 
+#ifdef CONFIG_X86_IO_APIC
+
 #define MP_ISA_BUS             0
 #define MP_MAX_IOAPIC_PIN      127
 
@@ -770,7 +772,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
        int ioapic = -1;
        int pin = -1;
 
-       /* 
+       /*
         * Convert 'gsi' to 'ioapic.pin'.
         */
        ioapic = mp_find_ioapic(gsi);
@@ -780,7 +782,7 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
 
        /*
         * TBD: This check is for faulty timer entries, where the override
-        *      erroneously sets the trigger to level, resulting in a HUGE 
+        *      erroneously sets the trigger to level, resulting in a HUGE
         *      increase of timer interrupts!
         */
        if ((bus_irq == 0) && (trigger == 3))
@@ -886,9 +888,22 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
        int ioapic = -1;
        int ioapic_pin = 0;
        int idx, bit = 0;
+#ifdef CONFIG_X86_32
+#define MAX_GSI_NUM    4096
+#define IRQ_COMPRESSION_START  64
+
+       static int pci_irq = IRQ_COMPRESSION_START;
+       /*
+        * Mapping between Global System Interrupts, which
+        * represent all possible interrupts, and IRQs
+        * assigned to actual devices.
+        */
+       static int gsi_to_irq[MAX_GSI_NUM];
+#else
 
        if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
                return gsi;
+#endif
 
        /* Don't set up the ACPI SCI because it's already set up */
        if (acpi_gbl_FADT.sci_interrupt == gsi)
@@ -902,8 +917,13 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
 
        ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base;
 
-       /* 
-        * Avoid pin reprogramming.  PRTs typically include entries  
+#ifdef CONFIG_X86_32
+       if (ioapic_renumber_irq)
+               gsi = ioapic_renumber_irq(ioapic, gsi);
+#endif
+
+       /*
+        * Avoid pin reprogramming.  PRTs typically include entries
         * with redundant pin->gsi mappings (but unique PCI devices);
         * we only program the IOAPIC on the first.
         */
@@ -918,14 +938,54 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
        if ((1 << bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
                Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
                        mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
+#ifdef CONFIG_X86_32
+               return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
+#else
                return gsi;
+#endif
        }
 
        mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1 << bit);
-
+#ifdef CONFIG_X86_32
+       /*
+        * For GSI >= 64, use IRQ compression
+        */
+       if ((gsi >= IRQ_COMPRESSION_START)
+           && (triggering == ACPI_LEVEL_SENSITIVE)) {
+               /*
+                * For PCI devices assign IRQs in order, avoiding gaps
+                * due to unused I/O APIC pins.
+                */
+               int irq = gsi;
+               if (gsi < MAX_GSI_NUM) {
+                       /*
+                        * Retain the VIA chipset work-around (gsi > 15), but
+                        * avoid a problem where the 8254 timer (IRQ0) is setup
+                        * via an override (so it's not on pin 0 of the ioapic),
+                        * and at the same time, the pin 0 interrupt is a PCI
+                        * type.  The gsi > 15 test could cause these two pins
+                        * to be shared as IRQ0, and they are not shareable.
+                        * So test for this condition, and if necessary, avoid
+                        * the pin collision.
+                        */
+                       gsi = pci_irq++;
+                       /*
+                        * Don't assign IRQ used by ACPI SCI
+                        */
+                       if (gsi == acpi_gbl_FADT.sci_interrupt)
+                               gsi = pci_irq++;
+                       gsi_to_irq[irq] = gsi;
+               } else {
+                       printk(KERN_ERR "GSI %u is too high\n", gsi);
+                       return gsi;
+               }
+       }
+#endif
        io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
                                triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
                                polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
        return gsi;
 }
+
+#endif /* CONFIG_X86_IO_APIC */
 #endif /* CONFIG_ACPI */