diff options
Diffstat (limited to 'drivers/pci/quirks.c')
-rw-r--r-- | drivers/pci/quirks.c | 182 |
1 files changed, 90 insertions, 92 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index f722c5f6951a..4bf71028556b 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -26,73 +26,12 @@ #include <linux/dmi.h> #include <linux/pci-aspm.h> #include <linux/ioport.h> +#include <linux/sched.h> +#include <linux/ktime.h> #include <asm/dma.h> /* isa_dma_bridge_buggy */ #include "pci.h" /* - * This quirk function disables memory decoding and releases memory resources - * of the device specified by kernel's boot parameter 'pci=resource_alignment='. - * It also rounds up size to specified alignment. - * Later on, the kernel will assign page-aligned memory resource back - * to the device. - */ -static void __devinit quirk_resource_alignment(struct pci_dev *dev) -{ - int i; - struct resource *r; - resource_size_t align, size; - u16 command; - - if (!pci_is_reassigndev(dev)) - return; - - if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL && - (dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) { - dev_warn(&dev->dev, - "Can't reassign resources to host bridge.\n"); - return; - } - - dev_info(&dev->dev, - "Disabling memory decoding and releasing memory resources.\n"); - pci_read_config_word(dev, PCI_COMMAND, &command); - command &= ~PCI_COMMAND_MEMORY; - pci_write_config_word(dev, PCI_COMMAND, command); - - align = pci_specified_resource_alignment(dev); - for (i=0; i < PCI_BRIDGE_RESOURCES; i++) { - r = &dev->resource[i]; - if (!(r->flags & IORESOURCE_MEM)) - continue; - size = resource_size(r); - if (size < align) { - size = align; - dev_info(&dev->dev, - "Rounding up size of resource #%d to %#llx.\n", - i, (unsigned long long)size); - } - r->end = size - 1; - r->start = 0; - } - /* Need to disable bridge's resource window, - * to enable the kernel to reassign new resource - * window later on. - */ - if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && - (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { - for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) { - r = &dev->resource[i]; - if (!(r->flags & IORESOURCE_MEM)) - continue; - r->end = resource_size(r) - 1; - r->start = 0; - } - pci_disable_bridge_window(dev); - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_resource_alignment); - -/* * Decoding should be disabled for a PCI device during BAR sizing to avoid * conflict. But doing so may cause problems on host bridge and perhaps other * key system devices. For devices that need to have mmio decoding always-on, @@ -100,10 +39,10 @@ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_resource_alignment); */ static void __devinit quirk_mmio_always_on(struct pci_dev *dev) { - if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) - dev->mmio_always_on = 1; + dev->mmio_always_on = 1; } -DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, quirk_mmio_always_on); +DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_BRIDGE_HOST, 8, quirk_mmio_always_on); /* The Mellanox Tavor device gives false positive parity errors * Mark this device with a broken_parity_status, to allow @@ -1002,12 +941,12 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt */ static void quirk_cardbus_legacy(struct pci_dev *dev) { - if ((PCI_CLASS_BRIDGE_CARDBUS << 8) ^ dev->class) - return; pci_write_config_dword(dev, PCI_CB_LEGACY_MODE_BASE, 0); } -DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy); -DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy); +DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_BRIDGE_CARDBUS, 8, quirk_cardbus_legacy); +DECLARE_PCI_FIXUP_CLASS_RESUME_EARLY(PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_BRIDGE_CARDBUS, 8, quirk_cardbus_legacy); /* * Following the PCI ordering rules is optional on the AMD762. I'm not @@ -1164,17 +1103,20 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, qui static void __devinit quirk_no_ata_d3(struct pci_dev *pdev) { - /* Quirk the legacy ATA devices only. The AHCI ones are ok */ - if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) - pdev->dev_flags |= PCI_DEV_FLAGS_NO_D3; + pdev->dev_flags |= PCI_DEV_FLAGS_NO_D3; } -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_ANY_ID, quirk_no_ata_d3); -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, PCI_ANY_ID, quirk_no_ata_d3); +/* Quirk the legacy ATA devices only. The AHCI ones are ok */ +DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_ANY_ID, + PCI_CLASS_STORAGE_IDE, 8, quirk_no_ata_d3); +DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_ATI, PCI_ANY_ID, + PCI_CLASS_STORAGE_IDE, 8, quirk_no_ata_d3); /* ALi loses some register settings that we cannot then restore */ -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, PCI_ANY_ID, quirk_no_ata_d3); +DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_AL, PCI_ANY_ID, + PCI_CLASS_STORAGE_IDE, 8, quirk_no_ata_d3); /* VIA comes back fine but we need to keep it alive or ACPI GTM failures occur when mode detecting */ -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_no_ata_d3); +DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_VIA, PCI_ANY_ID, + PCI_CLASS_STORAGE_IDE, 8, quirk_no_ata_d3); /* This was originally an Alpha specific thing, but it really fits here. * The i82375 PCI/EISA bridge appears as non-classified. Fix that. @@ -1873,8 +1815,7 @@ static void __devinit quirk_netmos(struct pci_dev *dev) case PCI_DEVICE_ID_NETMOS_9745: case PCI_DEVICE_ID_NETMOS_9845: case PCI_DEVICE_ID_NETMOS_9855: - if ((dev->class >> 8) == PCI_CLASS_COMMUNICATION_SERIAL && - num_parallel) { + if (num_parallel) { dev_info(&dev->dev, "Netmos %04x (%u parallel, " "%u serial); changing class SERIAL to OTHER " "(use parport_serial)\n", @@ -1884,7 +1825,8 @@ static void __devinit quirk_netmos(struct pci_dev *dev) } } } -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos); +DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, + PCI_CLASS_COMMUNICATION_SERIAL, 8, quirk_netmos); static void __devinit quirk_e100_interrupt(struct pci_dev *dev) { @@ -1952,7 +1894,8 @@ static void __devinit quirk_e100_interrupt(struct pci_dev *dev) iounmap(csr); } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_e100_interrupt); +DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, + PCI_CLASS_NETWORK_ETHERNET, 8, quirk_e100_interrupt); /* * The 82575 and 82598 may experience data corruption issues when transitioning @@ -2834,12 +2777,11 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors); static void __devinit fixup_ti816x_class(struct pci_dev* dev) { /* TI 816x devices do not have class code set when in PCIe boot mode */ - if (dev->class == PCI_CLASS_NOT_DEFINED) { - dev_info(&dev->dev, "Setting PCI class for 816x PCIe device\n"); - dev->class = PCI_CLASS_MULTIMEDIA_VIDEO; - } + dev_info(&dev->dev, "Setting PCI class for 816x PCIe device\n"); + dev->class = PCI_CLASS_MULTIMEDIA_VIDEO; } -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_TI, 0xb800, fixup_ti816x_class); +DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_TI, 0xb800, + PCI_CLASS_NOT_DEFINED, 0, fixup_ti816x_class); /* Some PCIe devices do not work reliably with the claimed maximum * payload size supported. @@ -2924,17 +2866,73 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f8, quirk_intel_mc_errata); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata); + +static void do_one_fixup_debug(void (*fn)(struct pci_dev *dev), struct pci_dev *dev) +{ + ktime_t calltime, delta, rettime; + unsigned long long duration; + + printk(KERN_DEBUG "calling %pF @ %i for %s\n", + fn, task_pid_nr(current), dev_name(&dev->dev)); + calltime = ktime_get(); + fn(dev); + rettime = ktime_get(); + delta = ktime_sub(rettime, calltime); + duration = (unsigned long long) ktime_to_ns(delta) >> 10; + printk(KERN_DEBUG "pci fixup %pF returned after %lld usecs for %s\n", + fn, duration, dev_name(&dev->dev)); +} + +/* + * Some BIOS implementations leave the Intel GPU interrupts enabled, + * even though no one is handling them (f.e. i915 driver is never loaded). + * Additionally the interrupt destination is not set up properly + * and the interrupt ends up -somewhere-. + * + * These spurious interrupts are "sticky" and the kernel disables + * the (shared) interrupt line after 100.000+ generated interrupts. + * + * Fix it by disabling the still enabled interrupts. + * This resolves crashes often seen on monitor unplug. + */ +#define I915_DEIER_REG 0x4400c +static void __devinit disable_igfx_irq(struct pci_dev *dev) +{ + void __iomem *regs = pci_iomap(dev, 0, 0); + if (regs == NULL) { + dev_warn(&dev->dev, "igfx quirk: Can't iomap PCI device\n"); + return; + } + + /* Check if any interrupt line is still enabled */ + if (readl(regs + I915_DEIER_REG) != 0) { + dev_warn(&dev->dev, "BIOS left Intel GPU interrupts enabled; " + "disabling\n"); + + writel(0, regs + I915_DEIER_REG); + } + + pci_iounmap(dev, regs); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); + static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) { - while (f < end) { - if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) && - (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) { + for (; f < end; f++) + if ((f->class == (u32) (dev->class >> f->class_shift) || + f->class == (u32) PCI_ANY_ID) && + (f->vendor == dev->vendor || + f->vendor == (u16) PCI_ANY_ID) && + (f->device == dev->device || + f->device == (u16) PCI_ANY_ID)) { dev_dbg(&dev->dev, "calling %pF\n", f->hook); - f->hook(dev); + if (initcall_debug) + do_one_fixup_debug(f->hook, dev); + else + f->hook(dev); } - f++; - } } extern struct pci_fixup __start_pci_fixups_early[]; |