From: ddugger@redhat.com <ddugger@redhat.com> Date: Thu, 2 Apr 2009 08:46:09 -0600 Subject: [pci] fix ARI code to be compatible with mixed systems Message-id: 200904021446.n32Ek9dg017122@sobek.n0ano.com O-Subject: [RHEL5.4 PATCH 6/17] BZ493152: Backport: PCI: fix ARI code to be compatible with mixed ARI/non-ARI systems Bugzilla: 493152 RH-Acked-by: Rik van Riel <riel@redhat.com> RH-Acked-by: Chris Wright <chrisw@redhat.com> Upstream status: commit 8113587c2d14d3be2414190845b2e2617c0aa33b Author: Zhao, Yu <yu.zhao@intel.com> Date: Thu Oct 23 13:15:39 2008 +0800 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> Signed-off-by: Gerd Hoffman <kraxel@redhat.com> Signed-off-by: Don Dugger <donald.d.dugger@intel.com> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 86a1429..a2bf736 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -937,27 +937,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->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; + + bridge = dev->bus->self; + if (!bridge) return; - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + 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