From: Andy Gospodarek <gospo@redhat.com> Date: Tue, 27 Jan 2009 16:38:41 -0500 Subject: [pci] msi: set 'En' bit for devices on HT-based platform Message-id: 20090127213841.GI22333@gospo.rdu.redhat.com O-Subject: Re: [RHEL5.4 PATCH] pci: set 'En' bit of MSI Mapping for devices on HT-based nvidia/Ali platforms Bugzilla: 290701 RH-Acked-by: Neil Horman <nhorman@redhat.com> RH-Acked-by: Prarit Bhargava <prarit@redhat.com> RH-Acked-by: Brian Maly <bmaly@redhat.com> There were some reports that interrupts were just not working correctly with e1000e on a platform with nvidia bridge chips. There were some recent patches to e1000/e1000e to address issues where MSI was detected but not completely functional. I also got reports that Fedora was working find on these systems, so I looked around and discovered that we needed to backport the following upstream commit: commit 9dc625e72309e1c919ea3e7f51d0ffca96123787 Author: Peer Chen <pchen@nvidia.com> Date: Mon Feb 4 23:50:13 2008 -0800 PCI: quirks: set 'En' bit of MSI Mapping for devices onHT-based nvidia platform According to HT spec, to get message interrupt from devices mapped to HT interrupt message, the 'En' bit of MSI Mapping capability need to be set. The patch do this setting in quirks code for the devices on HT-based nvidia platform. Later the same fix was proposed Ali chipsets as well, so I added this commit: commit 439a7733e8fcbaee39979c10246101565834d6b2 Author: Björn Krombholz <fox.box@gmail.com> Date: Mon May 12 00:24:27 2008 +0200 PCI: enable nv_msi_ht_cap_quirk for ALi bridges This applies the NVidia MSI enabled flag for HT capable devices quirk to ALi bridges as well. The nvidia portion of this patch has been tested by several customers and will resolve RHBZ 290701. I have gotten no reports that the Ali chipset is an issue, but this is a one-liner we should take since we are adding this fix. diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index ca70481..da65176 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -27,6 +27,69 @@ * Mark this device with a broken_parity_status, to allow * PCI scanning code to "skip" this now blacklisted device. */ +/* + * Force enable MSI mapping capability on HT bridges */ +static inline void ht_enable_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 void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) +{ + struct pci_dev *host_bridge; + int pos, ttl = 48; + + /* + * HT MSI mapping should be disabled on devices that are below + * a non-Hypertransport host bridge. Locate the host bridge... + */ + host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)); + if (host_bridge == NULL) { + dev_warn(&dev->dev, + "nv_msi_ht_cap_quirk didn't locate host bridge\n"); + return; + } + + pos = pci_find_ht_capability(host_bridge, HT_CAPTYPE_SLAVE); + if (pos != 0) { + /* Host bridge is to HT */ + 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; + + if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, + &flags) == 0) { + dev_info(&dev->dev, "Quirk 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); + } +} +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); + static void __devinit quirk_mellanox_tavor(struct pci_dev *dev) { dev->broken_parity_status = 1; /* This device gives false positives */