summaryrefslogtreecommitdiff
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorZhao, Yu <yu.zhao@intel.com>2008-10-23 05:15:39 (GMT)
committerJesse Barnes <jbarnes@virtuousgeek.org>2008-10-23 21:42:13 (GMT)
commit8113587c2d14d3be2414190845b2e2617c0aa33b (patch)
tree8fd7355ae2d677342a6dd2c2f7afb6e0e9db98f8 /drivers/pci/pci.c
parentd2174c3c07adad88dd9ba37a731e0b00b746822a (diff)
downloadlinux-fsl-qoriq-8113587c2d14d3be2414190845b2e2617c0aa33b.tar.xz
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 533aeb5..21f2ac6 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1309,27 +1309,32 @@ void pci_enable_ari(struct pci_dev *dev)
int pos;
u32 cap;
u16 ctrl;
+ struct pci_dev *bridge;
- if (!dev->is_pcie)
+ if (!dev->is_pcie || dev->devfn)
return;
- if (dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
- dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
+ if (!pos)
return;
- pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ bridge = dev->bus->self;
+ if (!bridge || !bridge->is_pcie)
+ return;
+
+ pos = pci_find_capability(bridge, PCI_CAP_ID_EXP);
if (!pos)
return;
- pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP2, &cap);
+ pci_read_config_dword(bridge, pos + PCI_EXP_DEVCAP2, &cap);
if (!(cap & PCI_EXP_DEVCAP2_ARI))
return;
- pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &ctrl);
+ pci_read_config_word(bridge, pos + PCI_EXP_DEVCTL2, &ctrl);
ctrl |= PCI_EXP_DEVCTL2_ARI;
- pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, ctrl);
+ pci_write_config_word(bridge, pos + PCI_EXP_DEVCTL2, ctrl);
- dev->ari_enabled = 1;
+ bridge->ari_enabled = 1;
}
int