# HG changeset patch # User Yu Zhao # Date 1236909504 14400 # Node ID 16659f5d8bb0d9d4b47cdb4a8c086c89deba793d # Parent 313310b824c81e803a698ee3a1a8a94075096060 Backport: PCI: fix ARI code to be compatible with mixed ARI/non-ARI systems commit 8113587c2d14d3be2414190845b2e2617c0aa33b Author: Zhao, Yu 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 Signed-off-by: Yu Zhao Signed-off-by: Jesse Barnes Signed-off-by: Yu Zhao diff -r 313310b824c8 -r 16659f5d8bb0 drivers/pci/pci.c --- a/drivers/pci/pci.c Thu Mar 12 21:57:23 2009 -0400 +++ b/drivers/pci/pci.c Thu Mar 12 21:58:24 2009 -0400 @@ -638,27 +638,32 @@ 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) - return; - - pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); if (!pos) return; - pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP2, &cap); + bridge = dev->bus->self; + if (!bridge) + return; + + pos = pci_find_capability(bridge, PCI_CAP_ID_EXP); + if (!pos) + return; + + 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