Skip to content

Commit d591f68

Browse files
committed
PCI: Wait for device readiness with Configuration RRS
After a device reset, delays are required before the device can successfully complete config accesses. PCIe r6.0, sec 6.6, specifies some delays required before software can perform config accesses. Devices that require more time after those delays may respond to config accesses with Configuration Request Retry Status (RRS) completions. Callers of pci_dev_wait() are responsible for delays until the device can respond to config accesses. pci_dev_wait() waits any additional time until the device can successfully complete config accesses. Reading config space of devices that are not present or not ready typically returns ~0 (PCI_ERROR_RESPONSE). Previously we polled the Command register until we got a value other than ~0. This is sometimes a problem because Root Complex handling of RRS completions may include several retries and implementation-specific behavior that is invisible to software (see sec 2.3.2), so the exponential backoff in pci_dev_wait() may not work as intended. Linux enables Configuration RRS Software Visibility on all Root Ports that support it. If it is enabled, read the Vendor ID instead of the Command register. RRS completions cause immediate return of the 0x0001 reserved Vendor ID value, so the pci_dev_wait() backoff works correctly. When a read of Vendor ID eventually completes successfully by returning a non-0x0001 value (the Vendor ID or 0xffff for VFs), the device should be initialized and ready to respond to config requests. For conventional PCI devices or devices below Root Ports that don't support Configuration RRS Software Visibility, poll the Command register as before. This was developed independently, but is very similar to Stanislav Spassov's previous work at https://lore.kernel.org/linux-pci/[email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Bjorn Helgaas <[email protected]> Tested-by: Duc Dang <[email protected]>
1 parent 8400291 commit d591f68

File tree

4 files changed

+37
-19
lines changed

4 files changed

+37
-19
lines changed

drivers/pci/pci.c

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,7 +1283,9 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
12831283
{
12841284
int delay = 1;
12851285
bool retrain = false;
1286-
struct pci_dev *bridge;
1286+
struct pci_dev *root, *bridge;
1287+
1288+
root = pcie_find_root_port(dev);
12871289

12881290
if (pci_is_pcie(dev)) {
12891291
bridge = pci_upstream_bridge(dev);
@@ -1292,16 +1294,23 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
12921294
}
12931295

12941296
/*
1295-
* After reset, the device should not silently discard config
1296-
* requests, but it may still indicate that it needs more time by
1297-
* responding to them with CRS completions. The Root Port will
1298-
* generally synthesize ~0 (PCI_ERROR_RESPONSE) data to complete
1299-
* the read (except when CRS SV is enabled and the read was for the
1300-
* Vendor ID; in that case it synthesizes 0x0001 data).
1297+
* The caller has already waited long enough after a reset that the
1298+
* device should respond to config requests, but it may respond
1299+
* with Request Retry Status (RRS) if it needs more time to
1300+
* initialize.
1301+
*
1302+
* If the device is below a Root Port with Configuration RRS
1303+
* Software Visibility enabled, reading the Vendor ID returns a
1304+
* special data value if the device responded with RRS. Read the
1305+
* Vendor ID until we get non-RRS status.
13011306
*
1302-
* Wait for the device to return a non-CRS completion. Read the
1303-
* Command register instead of Vendor ID so we don't have to
1304-
* contend with the CRS SV value.
1307+
* If there's no Root Port or Configuration RRS Software Visibility
1308+
* is not enabled, the device may still respond with RRS, but
1309+
* hardware may retry the config request. If no retries receive
1310+
* Successful Completion, hardware generally synthesizes ~0
1311+
* (PCI_ERROR_RESPONSE) data to complete the read. Reading Vendor
1312+
* ID for VFs and non-existent devices also returns ~0, so read the
1313+
* Command register until it returns something other than ~0.
13051314
*/
13061315
for (;;) {
13071316
u32 id;
@@ -1311,9 +1320,15 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
13111320
return -ENOTTY;
13121321
}
13131322

1314-
pci_read_config_dword(dev, PCI_COMMAND, &id);
1315-
if (!PCI_POSSIBLE_ERROR(id))
1316-
break;
1323+
if (root && root->config_crs_sv) {
1324+
pci_read_config_dword(dev, PCI_VENDOR_ID, &id);
1325+
if (!pci_bus_crs_vendor_id(id))
1326+
break;
1327+
} else {
1328+
pci_read_config_dword(dev, PCI_COMMAND, &id);
1329+
if (!PCI_POSSIBLE_ERROR(id))
1330+
break;
1331+
}
13171332

13181333
if (delay > timeout) {
13191334
pci_warn(dev, "not ready %dms after %s; giving up\n",

drivers/pci/pci.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ bool pci_bridge_d3_possible(struct pci_dev *dev);
139139
void pci_bridge_d3_update(struct pci_dev *dev);
140140
int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type);
141141

142+
static inline bool pci_bus_crs_vendor_id(u32 l)
143+
{
144+
return (l & 0xffff) == PCI_VENDOR_ID_PCI_SIG;
145+
}
146+
142147
static inline void pci_wakeup_event(struct pci_dev *dev)
143148
{
144149
/* Wait 100 ms before the system can be put into a sleep state. */

drivers/pci/probe.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,9 +1209,11 @@ static void pci_enable_crs(struct pci_dev *pdev)
12091209

12101210
/* Enable CRS Software Visibility if supported */
12111211
pcie_capability_read_word(pdev, PCI_EXP_RTCAP, &root_cap);
1212-
if (root_cap & PCI_EXP_RTCAP_CRSVIS)
1212+
if (root_cap & PCI_EXP_RTCAP_CRSVIS) {
12131213
pcie_capability_set_word(pdev, PCI_EXP_RTCTL,
12141214
PCI_EXP_RTCTL_CRSSVE);
1215+
pdev->config_crs_sv = 1;
1216+
}
12151217
}
12161218

12171219
static unsigned int pci_scan_child_bus_extend(struct pci_bus *bus,
@@ -2343,11 +2345,6 @@ struct pci_dev *pci_alloc_dev(struct pci_bus *bus)
23432345
}
23442346
EXPORT_SYMBOL(pci_alloc_dev);
23452347

2346-
static bool pci_bus_crs_vendor_id(u32 l)
2347-
{
2348-
return (l & 0xffff) == PCI_VENDOR_ID_PCI_SIG;
2349-
}
2350-
23512348
static bool pci_bus_wait_crs(struct pci_bus *bus, int devfn, u32 *l,
23522349
int timeout)
23532350
{

include/linux/pci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ struct pci_dev {
371371
can be generated */
372372
unsigned int pme_poll:1; /* Poll device's PME status bit */
373373
unsigned int pinned:1; /* Whether this dev is pinned */
374+
unsigned int config_crs_sv:1; /* Config CRS software visibility */
374375
unsigned int imm_ready:1; /* Supports Immediate Readiness */
375376
unsigned int d1_support:1; /* Low power state D1 is supported */
376377
unsigned int d2_support:1; /* Low power state D2 is supported */

0 commit comments

Comments
 (0)