aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorZhao, Yu <yu.zhao@intel.com>2008-10-23 01:15:39 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2008-10-23 17:42:13 -0400
commit8113587c2d14d3be2414190845b2e2617c0aa33b (patch)
tree8fd7355ae2d677342a6dd2c2f7afb6e0e9db98f8 /drivers/pci/pci.c
parentd2174c3c07adad88dd9ba37a731e0b00b746822a (diff)
PCI: fix ARI code to be compatible with mixed ARI/non-ARI systems
The original ARI support code has a compatibility problem with non-ARI devices. If a device doesn't support ARI, turning on ARI forwarding on its upper level bridge will cause undefined behavior. This fix turns on ARI forwarding only when the subordinate devices support it. Tested-by: Suresh Siddha <suresh.b.siddha@intel.com> Signed-off-by: Yu Zhao <yu.zhao@intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 533aeb5fcbe..21f2ac639ca 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1309,27 +1309,32 @@ void pci_enable_ari(struct pci_dev *dev)
1309 int pos; 1309 int pos;
1310 u32 cap; 1310 u32 cap;
1311 u16 ctrl; 1311 u16 ctrl;
1312 struct pci_dev *bridge;
1312 1313
1313 if (!dev->is_pcie) 1314 if (!dev->is_pcie || dev->devfn)
1314 return; 1315 return;
1315 1316
1316 if (dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && 1317 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
1317 dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) 1318 if (!pos)
1318 return; 1319 return;
1319 1320
1320 pos = pci_find_capability(dev, PCI_CAP_ID_EXP); 1321 bridge = dev->bus->self;
1322 if (!bridge || !bridge->is_pcie)
1323 return;
1324
1325 pos = pci_find_capability(bridge, PCI_CAP_ID_EXP);
1321 if (!pos) 1326 if (!pos)
1322 return; 1327 return;
1323 1328
1324 pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP2, &cap); 1329 pci_read_config_dword(bridge, pos + PCI_EXP_DEVCAP2, &cap);
1325 if (!(cap & PCI_EXP_DEVCAP2_ARI)) 1330 if (!(cap & PCI_EXP_DEVCAP2_ARI))
1326 return; 1331 return;
1327 1332
1328 pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl); 1333 pci_read_config_word(bridge, pos + PCI_EXP_DEVCTL2, &ctrl);
1329 ctrl |= PCI_EXP_DEVCTL2_ARI; 1334 ctrl |= PCI_EXP_DEVCTL2_ARI;
1330 pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl); 1335 pci_write_config_word(bridge, pos + PCI_EXP_DEVCTL2, ctrl);
1331 1336
1332 dev->ari_enabled = 1; 1337 bridge->ari_enabled = 1;
1333} 1338}
1334 1339
1335int 1340int