aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorMyron Stowe <myron.stowe@redhat.com>2012-06-01 17:16:37 -0400
committerBjorn Helgaas <bhelgaas@google.com>2012-06-11 22:41:23 -0400
commitc463b8cb9350cf1230cefe467a1cf279140a5437 (patch)
tree396a615ecee1763411ba5c5f61b13315aab0a219 /drivers/pci/pci.c
parentcb97ae3485955401d637bd269b0d24d3cd3fd3ec (diff)
PCI: add pci_pcie_cap2() check for PCIe feature capabilities >= v2
This patch resolves potential issues when accessing PCI Express Capability structures. The makeup of the capability varies substantially between v1 and v2: Version 1 of the PCI Express Capability (defined by PCI Express 1.0 and 1.1 base) neither requires the endpoint to implement the entire PCIe capability structure nor specifies default values of registers that are not implemented by the device. Version 2 of the PCI Express Capability (defined by PCIe 1.1 Capability Structure Expansion ECN, PCIe 2.0, 2.1, and 3.0) added additional registers to the structure and requires all registers to be either implemented or hardwired to 0. Due to the differences in the capability structures, code dealing with capability features must be careful not to access the additional registers introduced with v2 unless the device is specifically known to be a v2 capable device. Otherwise, attempts to access non-existant registers will occur. This is a subtle issue that is hard to track down when it occurs (and it has - see commit 864d296cf94). To try and help mitigate such occurrences, this patch introduces pci_pcie_cap2() which is similar to pci_pcie_cap() but also checks that the PCIe capability version is >= 2. pci_pcie_cap2() should be used for qualifying PCIe capability features introduced after v1. Suggested by Don Dutile. Acked-by: Donald Dutile <ddutile@redhat.com> Signed-off-by: Myron Stowe <myron.stowe@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c65
1 files changed, 50 insertions, 15 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 766bb13bb0a3..985df63aa59f 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -278,6 +278,38 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
278} 278}
279 279
280/** 280/**
281 * pci_pcie_cap2 - query for devices' PCI_CAP_ID_EXP v2 capability structure
282 * @dev: PCI device to check
283 *
284 * Like pci_pcie_cap() but also checks that the PCIe capability version is
285 * >= 2. Note that v1 capability structures could be sparse in that not
286 * all register fields were required. v2 requires the entire structure to
287 * be present size wise, while still allowing for non-implemented registers
288 * to exist but they must be hardwired to 0.
289 *
290 * Due to the differences in the versions of capability structures, one
291 * must be careful not to try and access non-existant registers that may
292 * exist in early versions - v1 - of Express devices.
293 *
294 * Returns the offset of the PCIe capability structure as long as the
295 * capability version is >= 2; otherwise 0 is returned.
296 */
297static int pci_pcie_cap2(struct pci_dev *dev)
298{
299 u16 flags;
300 int pos;
301
302 pos = pci_pcie_cap(dev);
303 if (pos) {
304 pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags);
305 if ((flags & PCI_EXP_FLAGS_VERS) < 2)
306 pos = 0;
307 }
308
309 return pos;
310}
311
312/**
281 * pci_find_ext_capability - Find an extended capability 313 * pci_find_ext_capability - Find an extended capability
282 * @dev: PCI device to query 314 * @dev: PCI device to query
283 * @cap: capability code 315 * @cap: capability code
@@ -1983,7 +2015,7 @@ void pci_enable_ari(struct pci_dev *dev)
1983{ 2015{
1984 int pos; 2016 int pos;
1985 u32 cap; 2017 u32 cap;
1986 u16 flags, ctrl; 2018 u16 ctrl;
1987 struct pci_dev *bridge; 2019 struct pci_dev *bridge;
1988 2020
1989 if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn) 2021 if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn)
@@ -1997,15 +2029,11 @@ void pci_enable_ari(struct pci_dev *dev)
1997 if (!bridge) 2029 if (!bridge)
1998 return; 2030 return;
1999 2031
2000 pos = pci_pcie_cap(bridge); 2032 /* ARI is a PCIe cap v2 feature */
2033 pos = pci_pcie_cap2(bridge);
2001 if (!pos) 2034 if (!pos)
2002 return; 2035 return;
2003 2036
2004 /* ARI is a PCIe v2 feature */
2005 pci_read_config_word(bridge, pos + PCI_EXP_FLAGS, &flags);
2006 if ((flags & PCI_EXP_FLAGS_VERS) < 2)
2007 return;
2008
2009 pci_read_config_dword(bridge, pos + PCI_EXP_DEVCAP2, &cap); 2037 pci_read_config_dword(bridge, pos + PCI_EXP_DEVCAP2, &cap);
2010 if (!(cap & PCI_EXP_DEVCAP2_ARI)) 2038 if (!(cap & PCI_EXP_DEVCAP2_ARI))
2011 return; 2039 return;
@@ -2018,7 +2046,7 @@ void pci_enable_ari(struct pci_dev *dev)
2018} 2046}
2019 2047
2020/** 2048/**
2021 * pci_enable_ido - enable ID-based ordering on a device 2049 * pci_enable_ido - enable ID-based Ordering on a device
2022 * @dev: the PCI device 2050 * @dev: the PCI device
2023 * @type: which types of IDO to enable 2051 * @type: which types of IDO to enable
2024 * 2052 *
@@ -2031,7 +2059,8 @@ void pci_enable_ido(struct pci_dev *dev, unsigned long type)
2031 int pos; 2059 int pos;
2032 u16 ctrl; 2060 u16 ctrl;
2033 2061
2034 pos = pci_pcie_cap(dev); 2062 /* ID-based Ordering is a PCIe cap v2 feature */
2063 pos = pci_pcie_cap2(dev);
2035 if (!pos) 2064 if (!pos)
2036 return; 2065 return;
2037 2066
@@ -2054,7 +2083,8 @@ void pci_disable_ido(struct pci_dev *dev, unsigned long type)
2054 int pos; 2083 int pos;
2055 u16 ctrl; 2084 u16 ctrl;
2056 2085
2057 pos = pci_pcie_cap(dev); 2086 /* ID-based Ordering is a PCIe cap v2 feature */
2087 pos = pci_pcie_cap2(dev);
2058 if (!pos) 2088 if (!pos)
2059 return; 2089 return;
2060 2090
@@ -2093,7 +2123,8 @@ int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type)
2093 u16 ctrl; 2123 u16 ctrl;
2094 int ret; 2124 int ret;
2095 2125
2096 pos = pci_pcie_cap(dev); 2126 /* OBFF is a PCIe cap v2 feature */
2127 pos = pci_pcie_cap2(dev);
2097 if (!pos) 2128 if (!pos)
2098 return -ENOTSUPP; 2129 return -ENOTSUPP;
2099 2130
@@ -2143,7 +2174,8 @@ void pci_disable_obff(struct pci_dev *dev)
2143 int pos; 2174 int pos;
2144 u16 ctrl; 2175 u16 ctrl;
2145 2176
2146 pos = pci_pcie_cap(dev); 2177 /* OBFF is a PCIe cap v2 feature */
2178 pos = pci_pcie_cap2(dev);
2147 if (!pos) 2179 if (!pos)
2148 return; 2180 return;
2149 2181
@@ -2165,7 +2197,8 @@ static bool pci_ltr_supported(struct pci_dev *dev)
2165 int pos; 2197 int pos;
2166 u32 cap; 2198 u32 cap;
2167 2199
2168 pos = pci_pcie_cap(dev); 2200 /* LTR is a PCIe cap v2 feature */
2201 pos = pci_pcie_cap2(dev);
2169 if (!pos) 2202 if (!pos)
2170 return false; 2203 return false;
2171 2204
@@ -2193,7 +2226,8 @@ int pci_enable_ltr(struct pci_dev *dev)
2193 if (!pci_ltr_supported(dev)) 2226 if (!pci_ltr_supported(dev))
2194 return -ENOTSUPP; 2227 return -ENOTSUPP;
2195 2228
2196 pos = pci_pcie_cap(dev); 2229 /* LTR is a PCIe cap v2 feature */
2230 pos = pci_pcie_cap2(dev);
2197 if (!pos) 2231 if (!pos)
2198 return -ENOTSUPP; 2232 return -ENOTSUPP;
2199 2233
@@ -2228,7 +2262,8 @@ void pci_disable_ltr(struct pci_dev *dev)
2228 if (!pci_ltr_supported(dev)) 2262 if (!pci_ltr_supported(dev))
2229 return; 2263 return;
2230 2264
2231 pos = pci_pcie_cap(dev); 2265 /* LTR is a PCIe cap v2 feature */
2266 pos = pci_pcie_cap2(dev);
2232 if (!pos) 2267 if (!pos)
2233 return; 2268 return;
2234 2269