aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2009-03-20 22:29:41 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-03-26 19:09:14 -0400
commitde7453065d5d5243686467998f1fcc58d20e0a7c (patch)
treea010aa2eb04f824a6fac08be2e60b99ac4bcb303 /drivers
parente42d1fe804408c57506a5326252b4db29958a7fb (diff)
PCI: don't enable too much HT MSI mapping
Impact: fix bug Prakash reported that his c51-mcp51 system ondie sound card doesn't work MSI but if he hack out the HT-MSI on mcp51, the MSI will work well with sound card. This patch reworks nv_msi_ht_cap_quirk() and will only avoid enabling ht_msi on devices following that root device. Reported-by: Prakash Punnoor <prakash@punnoor.de> Signed-off-by: Yinghai Lu <yinghai@kernel.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/quirks.c118
1 files changed, 82 insertions, 36 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 7ddcfc65e790..faf02dd00015 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2147,6 +2147,65 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
2147 PCI_DEVICE_ID_NVIDIA_NVENET_15, 2147 PCI_DEVICE_ID_NVIDIA_NVENET_15,
2148 nvenet_msi_disable); 2148 nvenet_msi_disable);
2149 2149
2150static int __devinit ht_check_msi_mapping(struct pci_dev *dev)
2151{
2152 int pos, ttl = 48;
2153 int found = 0;
2154
2155 /* check if there is HT MSI cap or enabled on this device */
2156 pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
2157 while (pos && ttl--) {
2158 u8 flags;
2159
2160 if (found < 1)
2161 found = 1;
2162 if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
2163 &flags) == 0) {
2164 if (flags & HT_MSI_FLAGS_ENABLE) {
2165 if (found < 2) {
2166 found = 2;
2167 break;
2168 }
2169 }
2170 }
2171 pos = pci_find_next_ht_capability(dev, pos,
2172 HT_CAPTYPE_MSI_MAPPING);
2173 }
2174
2175 return found;
2176}
2177
2178static int __devinit host_bridge_with_leaf(struct pci_dev *host_bridge)
2179{
2180 struct pci_dev *dev;
2181 int pos;
2182 int i, dev_no;
2183 int found = 0;
2184
2185 dev_no = host_bridge->devfn >> 3;
2186 for (i = dev_no + 1; i < 0x20; i++) {
2187 dev = pci_get_slot(host_bridge->bus, PCI_DEVFN(i, 0));
2188 if (!dev)
2189 continue;
2190
2191 /* found next host bridge ?*/
2192 pos = pci_find_ht_capability(dev, HT_CAPTYPE_SLAVE);
2193 if (pos != 0) {
2194 pci_dev_put(dev);
2195 break;
2196 }
2197
2198 if (ht_check_msi_mapping(dev)) {
2199 found = 1;
2200 pci_dev_put(dev);
2201 break;
2202 }
2203 pci_dev_put(dev);
2204 }
2205
2206 return found;
2207}
2208
2150static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev) 2209static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev)
2151{ 2210{
2152 struct pci_dev *host_bridge; 2211 struct pci_dev *host_bridge;
@@ -2171,6 +2230,10 @@ static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev)
2171 if (!found) 2230 if (!found)
2172 return; 2231 return;
2173 2232
2233 /* don't enable host_bridge with leaf directly here */
2234 if (host_bridge == dev && host_bridge_with_leaf(host_bridge))
2235 goto out;
2236
2174 /* root did that ! */ 2237 /* root did that ! */
2175 if (msi_ht_cap_enabled(host_bridge)) 2238 if (msi_ht_cap_enabled(host_bridge))
2176 goto out; 2239 goto out;
@@ -2201,44 +2264,12 @@ static void __devinit ht_disable_msi_mapping(struct pci_dev *dev)
2201 } 2264 }
2202} 2265}
2203 2266
2204static int __devinit ht_check_msi_mapping(struct pci_dev *dev) 2267static void __devinit __nv_msi_ht_cap_quirk(struct pci_dev *dev, int all)
2205{
2206 int pos, ttl = 48;
2207 int found = 0;
2208
2209 /* check if there is HT MSI cap or enabled on this device */
2210 pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
2211 while (pos && ttl--) {
2212 u8 flags;
2213
2214 if (found < 1)
2215 found = 1;
2216 if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
2217 &flags) == 0) {
2218 if (flags & HT_MSI_FLAGS_ENABLE) {
2219 if (found < 2) {
2220 found = 2;
2221 break;
2222 }
2223 }
2224 }
2225 pos = pci_find_next_ht_capability(dev, pos,
2226 HT_CAPTYPE_MSI_MAPPING);
2227 }
2228
2229 return found;
2230}
2231
2232static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev)
2233{ 2268{
2234 struct pci_dev *host_bridge; 2269 struct pci_dev *host_bridge;
2235 int pos; 2270 int pos;
2236 int found; 2271 int found;
2237 2272
2238 /* Enabling HT MSI mapping on this device breaks MCP51 */
2239 if (dev->device == 0x270)
2240 return;
2241
2242 /* check if there is HT MSI cap or enabled on this device */ 2273 /* check if there is HT MSI cap or enabled on this device */
2243 found = ht_check_msi_mapping(dev); 2274 found = ht_check_msi_mapping(dev);
2244 2275
@@ -2262,7 +2293,10 @@ static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev)
2262 /* Host bridge is to HT */ 2293 /* Host bridge is to HT */
2263 if (found == 1) { 2294 if (found == 1) {
2264 /* it is not enabled, try to enable it */ 2295 /* it is not enabled, try to enable it */
2265 nv_ht_enable_msi_mapping(dev); 2296 if (all)
2297 ht_enable_msi_mapping(dev);
2298 else
2299 nv_ht_enable_msi_mapping(dev);
2266 } 2300 }
2267 return; 2301 return;
2268 } 2302 }
@@ -2274,8 +2308,20 @@ static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev)
2274 /* Host bridge is not to HT, disable HT MSI mapping on this device */ 2308 /* Host bridge is not to HT, disable HT MSI mapping on this device */
2275 ht_disable_msi_mapping(dev); 2309 ht_disable_msi_mapping(dev);
2276} 2310}
2277DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk); 2311
2278DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk); 2312static void __devinit nv_msi_ht_cap_quirk_all(struct pci_dev *dev)
2313{
2314 return __nv_msi_ht_cap_quirk(dev, 1);
2315}
2316
2317static void __devinit nv_msi_ht_cap_quirk_leaf(struct pci_dev *dev)
2318{
2319 return __nv_msi_ht_cap_quirk(dev, 0);
2320}
2321
2322DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk_leaf);
2323
2324DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk_all);
2279 2325
2280static void __devinit quirk_msi_intx_disable_bug(struct pci_dev *dev) 2326static void __devinit quirk_msi_intx_disable_bug(struct pci_dev *dev)
2281{ 2327{