x86/pci: update pirq_enable_irq() to setup io apic routing
[safe/jmp/linux-2.6] / arch / x86 / pci / irq.c
index a2f6bde..2f3e192 100644 (file)
@@ -889,6 +889,9 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
                return 0;
        }
 
+       if (io_apic_assign_pci_irqs)
+               return 0;
+
        /* Find IRQ routing entry */
 
        if (!pirq_table)
@@ -1039,63 +1042,15 @@ static void __init pcibios_fixup_irqs(void)
                pirq_penalty[dev->irq]++;
        }
 
+       if (io_apic_assign_pci_irqs)
+               return;
+
        dev = NULL;
        while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
                pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
                if (!pin)
                        continue;
 
-#ifdef CONFIG_X86_IO_APIC
-               /*
-                * Recalculate IRQ numbers if we use the I/O APIC.
-                */
-               if (io_apic_assign_pci_irqs) {
-                       int irq;
-                       int ioapic = -1, ioapic_pin = -1;
-                       int triggering, polarity;
-
-                       /*
-                        * interrupt pins are numbered starting from 1
-                        */
-                       irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
-                                               PCI_SLOT(dev->devfn), pin - 1,
-                                               &ioapic, &ioapic_pin,
-                                               &triggering, &polarity);
-                       /*
-                        * Busses behind bridges are typically not listed in the
-                        * MP-table.  In this case we have to look up the IRQ
-                        * based on the parent bus, parent slot, and pin number.
-                        * The SMP code detects such bridged busses itself so we
-                        * should get into this branch reliably.
-                        */
-                       if (irq < 0 && dev->bus->parent) {
-                               /* go back to the bridge */
-                               struct pci_dev *bridge = dev->bus->self;
-                               int bus;
-
-                               pin = pci_swizzle_interrupt_pin(dev, pin);
-                               bus = bridge->bus->number;
-                               irq = IO_APIC_get_PCI_irq_vector(bus,
-                                               PCI_SLOT(bridge->devfn),
-                                               pin - 1,
-                                               &ioapic, &ioapic_pin,
-                                               &triggering, &polarity);
-                               if (irq >= 0)
-                                       dev_warn(&dev->dev,
-                                               "using bridge %s INT %c to "
-                                                       "get IRQ %d\n",
-                                                pci_name(bridge),
-                                                'A' + pin - 1, irq);
-                       }
-                       if (irq >= 0) {
-                               dev_info(&dev->dev,
-                                       "PCI->APIC IRQ transform: INT %c "
-                                               "-> IRQ %d\n",
-                                       'A' + pin - 1, irq);
-                               dev->irq = irq;
-                       }
-               }
-#endif
                /*
                 * Still no IRQ? Try to lookup one...
                 */
@@ -1190,6 +1145,19 @@ int __init pcibios_irq_init(void)
        pcibios_enable_irq = pirq_enable_irq;
 
        pcibios_fixup_irqs();
+
+       if (io_apic_assign_pci_irqs && pci_routeirq) {
+               struct pci_dev *dev = NULL;
+               /*
+                * PCI IRQ routing is set up by pci_enable_device(), but we
+                * also do it here in case there are still broken drivers that
+                * don't use pci_enable_device().
+                */
+               printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n");
+               for_each_pci_dev(dev)
+                       pirq_enable_irq(dev);
+       }
+
        return 0;
 }
 
@@ -1220,13 +1188,17 @@ void pcibios_penalize_isa_irq(int irq, int active)
 static int pirq_enable_irq(struct pci_dev *dev)
 {
        u8 pin;
-       struct pci_dev *temp_dev;
 
        pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-       if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
+       if (pin && !pcibios_lookup_irq(dev, 1)) {
                char *msg = "";
 
+               if (!io_apic_assign_pci_irqs && dev->irq)
+                       return 0;
+
                if (io_apic_assign_pci_irqs) {
+#ifdef CONFIG_X86_IO_APIC
+                       struct pci_dev *temp_dev;
                        int irq;
                        int ioapic = -1, ioapic_pin = -1;
                        int triggering, polarity;
@@ -1261,12 +1233,16 @@ static int pirq_enable_irq(struct pci_dev *dev)
                        }
                        dev = temp_dev;
                        if (irq >= 0) {
+                               io_apic_set_pci_routing(&dev->dev, ioapic,
+                                                       ioapic_pin, irq,
+                                                       triggering, polarity);
+                               dev->irq = irq;
                                dev_info(&dev->dev, "PCI->APIC IRQ transform: "
                                         "INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
-                               dev->irq = irq;
                                return 0;
                        } else
                                msg = "; probably buggy MP table";
+#endif
                } else if (pci_probe & PCI_BIOS_IRQ_SCAN)
                        msg = "";
                else