aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/quirks.c
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2009-02-23 14:51:59 -0500
committerJesse Barnes <jbarnes@hobbes.lan>2009-02-24 12:34:31 -0500
commit1dec6b054dd1fc780e18b815068bf5677409eb2d (patch)
treece73d3c8fb909c1ccc4bf3a9c75df2fc883b93e1 /drivers/pci/quirks.c
parentd22157b3d7a24d953ef5cce4515436be65b2e121 (diff)
PCI: don't enable too many HT MSI mappings
Prakash reported that his c51-mcp51 ondie sound card doesn't work with MSI. But if he hacks out the HT-MSI quirk, MSI works fine. So this patch reworks the nv_msi_ht_cap_quirk(). It will now only enable ht_msi on own its root device, avoiding enabling it on devices following that root dev. Reported-by: Prakash Punnoor <prakash@punnoor.de> Tested-by: Prakash Punnoor <prakash@punnoor.de> Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Jesse Barnes <jbarnes@hobbes.lan>
Diffstat (limited to 'drivers/pci/quirks.c')
-rw-r--r--drivers/pci/quirks.c115
1 files changed, 100 insertions, 15 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index a21e1c292ee4..a8523294e4ae 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2050,10 +2050,100 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
2050 PCI_DEVICE_ID_NVIDIA_NVENET_15, 2050 PCI_DEVICE_ID_NVIDIA_NVENET_15,
2051 nvenet_msi_disable); 2051 nvenet_msi_disable);
2052 2052
2053static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) 2053static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev)
2054{ 2054{
2055 struct pci_dev *host_bridge; 2055 struct pci_dev *host_bridge;
2056 int pos;
2057 int i, dev_no;
2058 int found = 0;
2059
2060 dev_no = dev->devfn >> 3;
2061 for (i = dev_no; i >= 0; i--) {
2062 host_bridge = pci_get_slot(dev->bus, PCI_DEVFN(i, 0));
2063 if (!host_bridge)
2064 continue;
2065
2066 pos = pci_find_ht_capability(host_bridge, HT_CAPTYPE_SLAVE);
2067 if (pos != 0) {
2068 found = 1;
2069 break;
2070 }
2071 pci_dev_put(host_bridge);
2072 }
2073
2074 if (!found)
2075 return;
2076
2077 /* root did that ! */
2078 if (msi_ht_cap_enabled(host_bridge))
2079 goto out;
2080
2081 ht_enable_msi_mapping(dev);
2082
2083out:
2084 pci_dev_put(host_bridge);
2085}
2086
2087static void __devinit ht_disable_msi_mapping(struct pci_dev *dev)
2088{
2089 int pos, ttl = 48;
2090
2091 pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
2092 while (pos && ttl--) {
2093 u8 flags;
2094
2095 if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
2096 &flags) == 0) {
2097 dev_info(&dev->dev, "Enabling HT MSI Mapping\n");
2098
2099 pci_write_config_byte(dev, pos + HT_MSI_FLAGS,
2100 flags & ~HT_MSI_FLAGS_ENABLE);
2101 }
2102 pos = pci_find_next_ht_capability(dev, pos,
2103 HT_CAPTYPE_MSI_MAPPING);
2104 }
2105}
2106
2107static int __devinit ht_check_msi_mapping(struct pci_dev *dev)
2108{
2056 int pos, ttl = 48; 2109 int pos, ttl = 48;
2110 int found = 0;
2111
2112 /* check if there is HT MSI cap or enabled on this device */
2113 pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
2114 while (pos && ttl--) {
2115 u8 flags;
2116
2117 if (found < 1)
2118 found = 1;
2119 if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
2120 &flags) == 0) {
2121 if (flags & HT_MSI_FLAGS_ENABLE) {
2122 if (found < 2) {
2123 found = 2;
2124 break;
2125 }
2126 }
2127 }
2128 pos = pci_find_next_ht_capability(dev, pos,
2129 HT_CAPTYPE_MSI_MAPPING);
2130 }
2131
2132 return found;
2133}
2134
2135static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev)
2136{
2137 struct pci_dev *host_bridge;
2138 int pos;
2139 int found;
2140
2141 /* check if there is HT MSI cap or enabled on this device */
2142 found = ht_check_msi_mapping(dev);
2143
2144 /* no HT MSI CAP */
2145 if (found == 0)
2146 return;
2057 2147
2058 /* 2148 /*
2059 * HT MSI mapping should be disabled on devices that are below 2149 * HT MSI mapping should be disabled on devices that are below
@@ -2069,24 +2159,19 @@ static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev)
2069 pos = pci_find_ht_capability(host_bridge, HT_CAPTYPE_SLAVE); 2159 pos = pci_find_ht_capability(host_bridge, HT_CAPTYPE_SLAVE);
2070 if (pos != 0) { 2160 if (pos != 0) {
2071 /* Host bridge is to HT */ 2161 /* Host bridge is to HT */
2072 ht_enable_msi_mapping(dev); 2162 if (found == 1) {
2163 /* it is not enabled, try to enable it */
2164 nv_ht_enable_msi_mapping(dev);
2165 }
2073 return; 2166 return;
2074 } 2167 }
2075 2168
2076 /* Host bridge is not to HT, disable HT MSI mapping on this device */ 2169 /* HT MSI is not enabled */
2077 pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING); 2170 if (found == 1)
2078 while (pos && ttl--) { 2171 return;
2079 u8 flags;
2080 2172
2081 if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, 2173 /* Host bridge is not to HT, disable HT MSI mapping on this device */
2082 &flags) == 0) { 2174 ht_disable_msi_mapping(dev);
2083 dev_info(&dev->dev, "Disabling HT MSI mapping");
2084 pci_write_config_byte(dev, pos + HT_MSI_FLAGS,
2085 flags & ~HT_MSI_FLAGS_ENABLE);
2086 }
2087 pos = pci_find_next_ht_capability(dev, pos,
2088 HT_CAPTYPE_MSI_MAPPING);
2089 }
2090} 2175}
2091DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk); 2176DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk);
2092DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk); 2177DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk);