diff options
author | Rajat Jain <rajatxjain@gmail.com> | 2014-09-08 23:19:49 +0200 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2014-09-09 07:05:00 +0200 |
commit | 89665a6a71408796565bfd29cfa6a7877b17a667 (patch) | |
tree | 95fa4fcde378e302264775083c3234866956f0c9 | |
parent | Linux 3.17-rc2 (diff) | |
download | linux-89665a6a71408796565bfd29cfa6a7877b17a667.tar.xz linux-89665a6a71408796565bfd29cfa6a7877b17a667.zip |
PCI: Check only the Vendor ID to identify Configuration Request Retry
Per PCIe r3.0, sec 2.3.2, if a Root Complex
- has Configuration Request Retry Status Software Visibility enabled,
- issues a Configuration Read of both bytes of the Vendor ID, and
- receives a Completion with Configuration Request Retry Status (CRS),
it must complete the request to the host by fabricating data of 0x0001 for
the Vendor ID and 0xff for any additional bytes in the request.
Linux issues a single config read for the four bytes containing the Vendor
ID and the Device ID. Previously we checked all four bytes for 0xffff0001
to identify CRS.
However, it is only the Vendor ID that really indicates CRS, because it's
sufficient to read only those two bytes. Checking the Device ID verifies
spec compliance but doesn't add any information.
Some Root Complexes appear to indicate CRS by returning 0x0001 for the
Vendor ID along with the actual the Device ID. Previously we interpreted
that as a valid Vendor/Device ID pair, although 0x0001 is reserved and
cannot be a valid Vendor ID.
[bhelgaas: changelog]
Link: http://lkml.kernel.org/r/4729FC36.3040000@gmail.com
Signed-off-by: Rajat Jain <rajatxjain@gmail.com>
Signed-off-by: Rajat Jain <rajatjain@juniper.net>
Signed-off-by: Guenter Roeck <groeck@juniper.net>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r-- | drivers/pci/probe.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index e3cf8a2e6292..9c26663c91d2 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1292,8 +1292,13 @@ bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *l, *l == 0x0000ffff || *l == 0xffff0000) return false; - /* Configuration request Retry Status */ - while (*l == 0xffff0001) { + /* + * Configuration Request Retry Status. Some root ports return the + * actual device ID instead of the synthetic ID (0xFFFF) required + * by the PCIe spec. Ignore the device ID and only check for + * (vendor id == 1). + */ + while ((*l & 0xffff) == 0x0001) { if (!crs_timeout) return false; |