Skip to content

Commit 3f674e7

Browse files
committed
nvme-pci: fix stuck reset on concurrent DPC and HP
The PCIe error handling has the nvme driver quiesce the device, attempt to restart it, then wait for that restart to complete. A PCIe DPC event also toggles the PCIe link. If the slot doesn't have out-of-band presence detection, this will trigger a pciehp re-enumeration. The error handling that calls nvme_error_resume is holding the device lock while this happens. This lock blocks pciehp's request to disconnect the driver from proceeding. Meanwhile the nvme's reset can't make forward progress because its device isn't there anymore with outstanding IO, and the timeout handler won't do anything to fix it because the device is undergoing error handling. End result: deadlocked. Fix this by having the timeout handler short cut the disabling for a disconnected PCIe device. The downside is that we're relying on an IO timeout to clean up this mess, which could be a minute by default. Tested-by: Nilay Shroff <nilay@linux.ibm.com> Reviewed-by: Nilay Shroff <nilay@linux.ibm.com> Signed-off-by: Keith Busch <kbusch@kernel.org>
1 parent e711252 commit 3f674e7

File tree

1 file changed

+12
-1
lines changed

1 file changed

+12
-1
lines changed

drivers/nvme/host/pci.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1411,17 +1411,28 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req)
14111411
struct nvme_dev *dev = nvmeq->dev;
14121412
struct request *abort_req;
14131413
struct nvme_command cmd = { };
1414+
struct pci_dev *pdev = to_pci_dev(dev->dev);
14141415
u32 csts = readl(dev->bar + NVME_REG_CSTS);
14151416
u8 opcode;
14161417

1418+
/*
1419+
* Shutdown the device immediately if we see it is disconnected. This
1420+
* unblocks PCIe error handling if the nvme driver is waiting in
1421+
* error_resume for a device that has been removed. We can't unbind the
1422+
* driver while the driver's error callback is waiting to complete, so
1423+
* we're relying on a timeout to break that deadlock if a removal
1424+
* occurs while reset work is running.
1425+
*/
1426+
if (pci_dev_is_disconnected(pdev))
1427+
nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DELETING);
14171428
if (nvme_state_terminal(&dev->ctrl))
14181429
goto disable;
14191430

14201431
/* If PCI error recovery process is happening, we cannot reset or
14211432
* the recovery mechanism will surely fail.
14221433
*/
14231434
mb();
1424-
if (pci_channel_offline(to_pci_dev(dev->dev)))
1435+
if (pci_channel_offline(pdev))
14251436
return BLK_EH_RESET_TIMER;
14261437

14271438
/*

0 commit comments

Comments
 (0)