]> xenbits.xensource.com Git - legacy/linux-2.6.18-xen.git/commitdiff
Backport: PCI: fix ARI code to be compatible with mixed ARI/non-ARI
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 13 Mar 2009 07:41:23 +0000 (07:41 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 13 Mar 2009 07:41:23 +0000 (07:41 +0000)
systems

    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: Yu Zhao <yu.zhao@intel.com>
drivers/pci/pci.c

index 3cd615dd7fc629738f06ad47ac49ae0c4a8f8f19..62e0d1e7dabf20ab5afd0bf265dcf590445ae7de 100644 (file)
@@ -638,27 +638,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