瀏覽代碼

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>
Zhao, Yu 16 年之前
父節點
當前提交
8113587c2d
共有 1 個文件被更改,包括 13 次插入8 次删除
  1. 13 8
      drivers/pci/pci.c

+ 13 - 8
drivers/pci/pci.c

@@ -1309,27 +1309,32 @@ void pci_enable_ari(struct pci_dev *dev)
 	int pos;
 	int pos;
 	u32 cap;
 	u32 cap;
 	u16 ctrl;
 	u16 ctrl;
+	struct pci_dev *bridge;
 
 
-	if (!dev->is_pcie)
+	if (!dev->is_pcie || dev->devfn)
 		return;
 		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;
 		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)
 	if (!pos)
 		return;
 		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))
 	if (!(cap & PCI_EXP_DEVCAP2_ARI))
 		return;
 		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;
 	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
 int