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>
This commit is contained in:
parent
9ef9977cab
commit
09d6029f43
1 changed files with 34 additions and 9 deletions
|
@ -648,11 +648,43 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vi
|
|||
* Some of the on-chip devices are actually '586 devices' so they are
|
||||
* listed here.
|
||||
*/
|
||||
|
||||
static int via_irq_fixup_needed = -1;
|
||||
|
||||
/*
|
||||
* As some VIA hardware is available in PCI-card form, we need to restrict
|
||||
* this quirk to VIA PCI hardware built onto VIA-based motherboards only.
|
||||
* We try to locate a VIA southbridge before deciding whether the quirk
|
||||
* should be applied.
|
||||
*/
|
||||
static const struct pci_device_id via_irq_fixup_tbl[] = {
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_VIA,
|
||||
.device = PCI_ANY_ID,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.class = PCI_CLASS_BRIDGE_ISA << 8,
|
||||
.class_mask = 0xffff00,
|
||||
},
|
||||
{ 0, },
|
||||
};
|
||||
|
||||
static void quirk_via_irq(struct pci_dev *dev)
|
||||
{
|
||||
u8 irq, new_irq;
|
||||
|
||||
new_irq = dev->irq & 0xf;
|
||||
if (via_irq_fixup_needed == -1)
|
||||
via_irq_fixup_needed = pci_dev_present(via_irq_fixup_tbl);
|
||||
|
||||
if (!via_irq_fixup_needed)
|
||||
return;
|
||||
|
||||
new_irq = dev->irq;
|
||||
|
||||
/* Don't quirk interrupts outside the legacy IRQ range */
|
||||
if (!new_irq || new_irq > 15)
|
||||
return;
|
||||
|
||||
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
|
||||
if (new_irq != irq) {
|
||||
printk(KERN_INFO "PCI: VIA IRQ fixup for %s, from %d to %d\n",
|
||||
|
@ -661,14 +693,7 @@ static void quirk_via_irq(struct pci_dev *dev)
|
|||
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_via_irq);
|
||||
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, quirk_via_irq);
|
||||
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irq);
|
||||
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_irq);
|
||||
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235_USB_2, quirk_via_irq);
|
||||
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_irq);
|
||||
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_irq);
|
||||
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irq);
|
||||
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq);
|
||||
|
||||
/*
|
||||
* VIA VT82C598 has its device ID settable and many BIOSes
|
||||
|
|
Loading…
Reference in a new issue