|
@@ -1584,6 +1584,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_
|
|
|
*/
|
|
|
#define AMD_813X_MISC 0x40
|
|
|
#define AMD_813X_NOIOAMODE (1<<0)
|
|
|
+#define AMD_813X_REV_B2 0x13
|
|
|
|
|
|
static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev)
|
|
|
{
|
|
@@ -1591,6 +1592,8 @@ static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev)
|
|
|
|
|
|
if (noioapicquirk)
|
|
|
return;
|
|
|
+ if (dev->revision == AMD_813X_REV_B2)
|
|
|
+ return;
|
|
|
|
|
|
pci_read_config_dword(dev, AMD_813X_MISC, &pci_config_dword);
|
|
|
pci_config_dword &= ~AMD_813X_NOIOAMODE;
|
|
@@ -1981,7 +1984,6 @@ static void __devinit quirk_msi_ht_cap(struct pci_dev *dev)
|
|
|
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE,
|
|
|
quirk_msi_ht_cap);
|
|
|
|
|
|
-
|
|
|
/* The nVidia CK804 chipset may have 2 HT MSI mappings.
|
|
|
* MSI are supported if the MSI capability set in any of these mappings.
|
|
|
*/
|
|
@@ -2032,6 +2034,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS,
|
|
|
PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB,
|
|
|
ht_enable_msi_mapping);
|
|
|
|
|
|
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE,
|
|
|
+ ht_enable_msi_mapping);
|
|
|
+
|
|
|
/* The P5N32-SLI Premium motherboard from Asus has a problem with msi
|
|
|
* for the MCP55 NIC. It is not yet determined whether the msi problem
|
|
|
* also affects other devices. As for now, turn off msi for this device.
|
|
@@ -2048,10 +2053,100 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
|
|
|
PCI_DEVICE_ID_NVIDIA_NVENET_15,
|
|
|
nvenet_msi_disable);
|
|
|
|
|
|
-static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev)
|
|
|
+static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev)
|
|
|
{
|
|
|
struct pci_dev *host_bridge;
|
|
|
+ int pos;
|
|
|
+ int i, dev_no;
|
|
|
+ int found = 0;
|
|
|
+
|
|
|
+ dev_no = dev->devfn >> 3;
|
|
|
+ for (i = dev_no; i >= 0; i--) {
|
|
|
+ host_bridge = pci_get_slot(dev->bus, PCI_DEVFN(i, 0));
|
|
|
+ if (!host_bridge)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ pos = pci_find_ht_capability(host_bridge, HT_CAPTYPE_SLAVE);
|
|
|
+ if (pos != 0) {
|
|
|
+ found = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ pci_dev_put(host_bridge);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!found)
|
|
|
+ return;
|
|
|
+
|
|
|
+ /* root did that ! */
|
|
|
+ if (msi_ht_cap_enabled(host_bridge))
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ ht_enable_msi_mapping(dev);
|
|
|
+
|
|
|
+out:
|
|
|
+ pci_dev_put(host_bridge);
|
|
|
+}
|
|
|
+
|
|
|
+static void __devinit ht_disable_msi_mapping(struct pci_dev *dev)
|
|
|
+{
|
|
|
+ int pos, ttl = 48;
|
|
|
+
|
|
|
+ pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
|
|
|
+ while (pos && ttl--) {
|
|
|
+ u8 flags;
|
|
|
+
|
|
|
+ if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
|
|
|
+ &flags) == 0) {
|
|
|
+ dev_info(&dev->dev, "Enabling HT MSI Mapping\n");
|
|
|
+
|
|
|
+ pci_write_config_byte(dev, pos + HT_MSI_FLAGS,
|
|
|
+ flags & ~HT_MSI_FLAGS_ENABLE);
|
|
|
+ }
|
|
|
+ pos = pci_find_next_ht_capability(dev, pos,
|
|
|
+ HT_CAPTYPE_MSI_MAPPING);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static int __devinit ht_check_msi_mapping(struct pci_dev *dev)
|
|
|
+{
|
|
|
int pos, ttl = 48;
|
|
|
+ int found = 0;
|
|
|
+
|
|
|
+ /* check if there is HT MSI cap or enabled on this device */
|
|
|
+ pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
|
|
|
+ while (pos && ttl--) {
|
|
|
+ u8 flags;
|
|
|
+
|
|
|
+ if (found < 1)
|
|
|
+ found = 1;
|
|
|
+ if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
|
|
|
+ &flags) == 0) {
|
|
|
+ if (flags & HT_MSI_FLAGS_ENABLE) {
|
|
|
+ if (found < 2) {
|
|
|
+ found = 2;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ pos = pci_find_next_ht_capability(dev, pos,
|
|
|
+ HT_CAPTYPE_MSI_MAPPING);
|
|
|
+ }
|
|
|
+
|
|
|
+ return found;
|
|
|
+}
|
|
|
+
|
|
|
+static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev)
|
|
|
+{
|
|
|
+ struct pci_dev *host_bridge;
|
|
|
+ int pos;
|
|
|
+ int found;
|
|
|
+
|
|
|
+ /* check if there is HT MSI cap or enabled on this device */
|
|
|
+ found = ht_check_msi_mapping(dev);
|
|
|
+
|
|
|
+ /* no HT MSI CAP */
|
|
|
+ if (found == 0)
|
|
|
+ return;
|
|
|
|
|
|
/*
|
|
|
* HT MSI mapping should be disabled on devices that are below
|
|
@@ -2067,24 +2162,19 @@ static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev)
|
|
|
pos = pci_find_ht_capability(host_bridge, HT_CAPTYPE_SLAVE);
|
|
|
if (pos != 0) {
|
|
|
/* Host bridge is to HT */
|
|
|
- ht_enable_msi_mapping(dev);
|
|
|
+ if (found == 1) {
|
|
|
+ /* it is not enabled, try to enable it */
|
|
|
+ nv_ht_enable_msi_mapping(dev);
|
|
|
+ }
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- /* Host bridge is not to HT, disable HT MSI mapping on this device */
|
|
|
- pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
|
|
|
- while (pos && ttl--) {
|
|
|
- u8 flags;
|
|
|
+ /* HT MSI is not enabled */
|
|
|
+ if (found == 1)
|
|
|
+ return;
|
|
|
|
|
|
- if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
|
|
|
- &flags) == 0) {
|
|
|
- dev_info(&dev->dev, "Disabling HT MSI mapping");
|
|
|
- pci_write_config_byte(dev, pos + HT_MSI_FLAGS,
|
|
|
- flags & ~HT_MSI_FLAGS_ENABLE);
|
|
|
- }
|
|
|
- pos = pci_find_next_ht_capability(dev, pos,
|
|
|
- HT_CAPTYPE_MSI_MAPPING);
|
|
|
- }
|
|
|
+ /* Host bridge is not to HT, disable HT MSI mapping on this device */
|
|
|
+ ht_disable_msi_mapping(dev);
|
|
|
}
|
|
|
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk);
|
|
|
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk);
|