From: "Bjorn Helgaas" In PIC mode, some Via devices update IRQ routing when PCI_INTERRUPT_LINE is written. So if we've updated the device's IRQ, we also need to update PCI_INTERRUPT_LINE. Signed-off-by: Bjorn Helgaas Signed-off-by: Andrew Morton --- 25-akpm/arch/i386/pci/irq.c | 5 ----- 25-akpm/drivers/acpi/pci_irq.c | 4 ---- 25-akpm/drivers/pci/quirks.c | 40 +++++++++++++++++++++++++++++++--------- 3 files changed, 31 insertions(+), 18 deletions(-) diff -puN arch/i386/pci/irq.c~x86-via-workaround arch/i386/pci/irq.c --- 25/arch/i386/pci/irq.c~x86-via-workaround Thu Mar 24 16:01:57 2005 +++ 25-akpm/arch/i386/pci/irq.c Thu Mar 24 16:01:57 2005 @@ -1026,7 +1026,6 @@ void pcibios_penalize_isa_irq(int irq) static int pirq_enable_irq(struct pci_dev *dev) { u8 pin; - extern int via_interrupt_line_quirk; struct pci_dev *temp_dev; pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); @@ -1081,10 +1080,6 @@ static int pirq_enable_irq(struct pci_de printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n", 'A' + pin, pci_name(dev), msg); } - /* VIA bridges use interrupt line for apic/pci steering across - the V-Link */ - else if (via_interrupt_line_quirk) - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq & 15); return 0; } diff -puN drivers/acpi/pci_irq.c~x86-via-workaround drivers/acpi/pci_irq.c --- 25/drivers/acpi/pci_irq.c~x86-via-workaround Thu Mar 24 16:01:57 2005 +++ 25-akpm/drivers/acpi/pci_irq.c Thu Mar 24 16:02:50 2005 @@ -391,7 +391,6 @@ acpi_pci_irq_enable ( u8 pin = 0; int edge_level = ACPI_LEVEL_SENSITIVE; int active_high_low = ACPI_ACTIVE_LOW; - extern int via_interrupt_line_quirk; char *link = NULL; ACPI_FUNCTION_TRACE("acpi_pci_irq_enable"); @@ -444,9 +443,6 @@ acpi_pci_irq_enable ( } } - if (via_interrupt_line_quirk) - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq & 15); - dev->irq = acpi_register_gsi(irq, edge_level, active_high_low); printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ", diff -puN drivers/pci/quirks.c~x86-via-workaround drivers/pci/quirks.c --- 25/drivers/pci/quirks.c~x86-via-workaround Thu Mar 24 16:01:57 2005 +++ 25-akpm/drivers/pci/quirks.c Thu Mar 24 16:01:59 2005 @@ -683,19 +683,41 @@ static void __init quirk_disable_pxb(str } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb ); -/* - * VIA northbridges care about PCI_INTERRUPT_LINE - */ -int via_interrupt_line_quirk; +#ifdef CONFIG_ACPI +#include +#endif -static void __devinit quirk_via_bridge(struct pci_dev *pdev) +static void __devinit quirk_via_irqpic(struct pci_dev *dev) { - if(pdev->devfn == 0) { - printk(KERN_INFO "PCI: Via IRQ fixup\n"); - via_interrupt_line_quirk = 1; + u8 irq, new_irq; + +#ifdef CONFIG_X86_IO_APIC + if (nr_ioapics && !skip_ioapic_setup) + return; +#endif +#ifdef CONFIG_ACPI + if (acpi_irq_model != ACPI_IRQ_MODEL_PIC) + return; +#endif + /* + * Some Via devices make an internal connection to the PIC when the + * PCI_INTERRUPT_LINE register is written. If we've changed the + * device's IRQ, we need to update this routing. + * + * I suspect this only happens for devices on the same chip as the + * PIC, but I don't know how to identify those without listing them + * all individually, which is a maintenance problem. + */ + new_irq = dev->irq & 0xf; + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + if (new_irq != irq) { + printk(KERN_INFO "PCI: Via PIC IRQ fixup for %s, from %d to %d\n", + pci_name(dev), irq, new_irq); + udelay(15); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); } } -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_bridge ); +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irqpic); /* * Serverworks CSB5 IDE does not fully support native mode _