diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/msi.c | 5 | ||||
-rw-r--r-- | drivers/pci/pci.h | 2 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 21 |
3 files changed, 26 insertions, 2 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index b5ab9aa6ff7c..2b85aa39f954 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -453,7 +453,7 @@ static void enable_msi_mode(struct pci_dev *dev, int pos, int type) } } -static void disable_msi_mode(struct pci_dev *dev, int pos, int type) +void disable_msi_mode(struct pci_dev *dev, int pos, int type) { u16 control; @@ -699,6 +699,9 @@ int pci_enable_msi(struct pci_dev* dev) if (!pci_msi_enable || !dev) return status; + if (dev->no_msi) + return status; + temp = dev->irq; if ((status = msi_init()) < 0) diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index d94d7af4f7a0..fa36094aa0f9 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -46,7 +46,7 @@ extern int pci_msi_quirk; #else #define pci_msi_quirk 0 #endif - +void disable_msi_mode(struct pci_dev *dev, int pos, int type); extern int pcie_mch_quirk; extern struct device_attribute pci_dev_attrs[]; extern struct class_device_attribute class_device_attr_cpuaffinity; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index a9160ad16581..bb36bb69803f 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1291,6 +1291,27 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quir DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_pcie_mch ); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_pcie_mch ); + +/* + * It's possible for the MSI to get corrupted if shpc and acpi + * are used together on certain PXH-based systems. + */ +static void __devinit quirk_pcie_pxh(struct pci_dev *dev) +{ + disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), + PCI_CAP_ID_MSI); + dev->no_msi = 1; + + printk(KERN_WARNING "PCI: PXH quirk detected, " + "disabling MSI for SHPC device\n"); +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHD_0, quirk_pcie_pxh); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHD_1, quirk_pcie_pxh); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_0, quirk_pcie_pxh); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXH_1, quirk_pcie_pxh); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHV, quirk_pcie_pxh); + + static void __devinit quirk_netmos(struct pci_dev *dev) { unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4; |