Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI: VIA IRQ quirk behaviour change

The most recent VIA IRQ quirk changes have broken various VIA devices for
some users. We are not able to add these devices to the blacklist as they
are also available in PCI-card form, and running the quirk on these devices
brings us back to square one (running the VIA quirk on non-VIA boards where
the quirk is not needed).

This patch, based on suggestions from Sergey Vlasov, implements a scheme
similar to but more restrictive than the scheme we had in 2.6.16 and
earlier. It runs the quirk on all VIA hardware, but *only* if a VIA
southbridge was detected on the system.

To further reduce the amount of quirked devices, this patch includes a
change suggested by Linus at http://lkml.org/lkml/2005/9/27/113 This
ensures that devices bound to non-legacy IO-APIC interrupt lines are not
quirked. We have made one change to Linus' suggestion: we do a comparison
of ">15" rather than ">=15", as 15 is still in the legacy interrupt range.

There is still a downside to this patch: if the user inserts a VIA PCI card
into a VIA-based motherboard, in some circumstances the quirk will also run
on the VIA PCI card. This corner case is hard to avoid.

Signed-off-by: Daniel Drake <dsd@gentoo.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Daniel Drake and committed by
Greg Kroah-Hartman
09d6029f 9ef9977c

+34 -9
+34 -9
drivers/pci/quirks.c
··· 648 648 * Some of the on-chip devices are actually '586 devices' so they are 649 649 * listed here. 650 650 */ 651 + 652 + static int via_irq_fixup_needed = -1; 653 + 654 + /* 655 + * As some VIA hardware is available in PCI-card form, we need to restrict 656 + * this quirk to VIA PCI hardware built onto VIA-based motherboards only. 657 + * We try to locate a VIA southbridge before deciding whether the quirk 658 + * should be applied. 659 + */ 660 + static const struct pci_device_id via_irq_fixup_tbl[] = { 661 + { 662 + .vendor = PCI_VENDOR_ID_VIA, 663 + .device = PCI_ANY_ID, 664 + .subvendor = PCI_ANY_ID, 665 + .subdevice = PCI_ANY_ID, 666 + .class = PCI_CLASS_BRIDGE_ISA << 8, 667 + .class_mask = 0xffff00, 668 + }, 669 + { 0, }, 670 + }; 671 + 651 672 static void quirk_via_irq(struct pci_dev *dev) 652 673 { 653 674 u8 irq, new_irq; 654 675 655 - new_irq = dev->irq & 0xf; 676 + if (via_irq_fixup_needed == -1) 677 + via_irq_fixup_needed = pci_dev_present(via_irq_fixup_tbl); 678 + 679 + if (!via_irq_fixup_needed) 680 + return; 681 + 682 + new_irq = dev->irq; 683 + 684 + /* Don't quirk interrupts outside the legacy IRQ range */ 685 + if (!new_irq || new_irq > 15) 686 + return; 687 + 656 688 pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); 657 689 if (new_irq != irq) { 658 690 printk(KERN_INFO "PCI: VIA IRQ fixup for %s, from %d to %d\n", ··· 693 661 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); 694 662 } 695 663 } 696 - DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_via_irq); 697 - DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, quirk_via_irq); 698 - DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irq); 699 - DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_irq); 700 - DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235_USB_2, quirk_via_irq); 701 - DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_irq); 702 - DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_irq); 703 - DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irq); 664 + DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq); 704 665 705 666 /* 706 667 * VIA VT82C598 has its device ID settable and many BIOSes