Skip to content

Commit c1ac9a4

Browse files
committed
nvme: Wait for reset state when required
Prevent simultaneous controller disabling/enabling tasks from interfering with each other through a function to wait until the task successfully transitioned the controller to the RESETTING state. This ensures disabling the controller will not be interrupted by another reset path, otherwise a concurrent reset may leave the controller in the wrong state. Tested-by: Edmund Nadolski <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Keith Busch <[email protected]>
1 parent 4c75f87 commit c1ac9a4

File tree

3 files changed

+74
-17
lines changed

3 files changed

+74
-17
lines changed

drivers/nvme/host/core.c

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,15 @@ static void nvme_queue_scan(struct nvme_ctrl *ctrl)
126126
* code paths that can't be interrupted by other reset attempts. A hot removal
127127
* may prevent this from succeeding.
128128
*/
129-
static int nvme_try_sched_reset(struct nvme_ctrl *ctrl)
129+
int nvme_try_sched_reset(struct nvme_ctrl *ctrl)
130130
{
131131
if (ctrl->state != NVME_CTRL_RESETTING)
132132
return -EBUSY;
133133
if (!queue_work(nvme_reset_wq, &ctrl->reset_work))
134134
return -EBUSY;
135135
return 0;
136136
}
137+
EXPORT_SYMBOL_GPL(nvme_try_sched_reset);
137138

138139
int nvme_reset_ctrl(struct nvme_ctrl *ctrl)
139140
{
@@ -384,8 +385,10 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
384385
break;
385386
}
386387

387-
if (changed)
388+
if (changed) {
388389
ctrl->state = new_state;
390+
wake_up_all(&ctrl->state_wq);
391+
}
389392

390393
spin_unlock_irqrestore(&ctrl->lock, flags);
391394
if (changed && ctrl->state == NVME_CTRL_LIVE)
@@ -394,6 +397,39 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
394397
}
395398
EXPORT_SYMBOL_GPL(nvme_change_ctrl_state);
396399

400+
/*
401+
* Returns true for sink states that can't ever transition back to live.
402+
*/
403+
static bool nvme_state_terminal(struct nvme_ctrl *ctrl)
404+
{
405+
switch (ctrl->state) {
406+
case NVME_CTRL_NEW:
407+
case NVME_CTRL_LIVE:
408+
case NVME_CTRL_RESETTING:
409+
case NVME_CTRL_CONNECTING:
410+
return false;
411+
case NVME_CTRL_DELETING:
412+
case NVME_CTRL_DEAD:
413+
return true;
414+
default:
415+
WARN_ONCE(1, "Unhandled ctrl state:%d", ctrl->state);
416+
return true;
417+
}
418+
}
419+
420+
/*
421+
* Waits for the controller state to be resetting, or returns false if it is
422+
* not possible to ever transition to that state.
423+
*/
424+
bool nvme_wait_reset(struct nvme_ctrl *ctrl)
425+
{
426+
wait_event(ctrl->state_wq,
427+
nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING) ||
428+
nvme_state_terminal(ctrl));
429+
return ctrl->state == NVME_CTRL_RESETTING;
430+
}
431+
EXPORT_SYMBOL_GPL(nvme_wait_reset);
432+
397433
static void nvme_free_ns_head(struct kref *ref)
398434
{
399435
struct nvme_ns_head *head =
@@ -3998,6 +4034,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
39984034
INIT_WORK(&ctrl->async_event_work, nvme_async_event_work);
39994035
INIT_WORK(&ctrl->fw_act_work, nvme_fw_act_work);
40004036
INIT_WORK(&ctrl->delete_work, nvme_delete_ctrl_work);
4037+
init_waitqueue_head(&ctrl->state_wq);
40014038

40024039
INIT_DELAYED_WORK(&ctrl->ka_work, nvme_keep_alive_work);
40034040
memset(&ctrl->ka_cmd, 0, sizeof(ctrl->ka_cmd));

drivers/nvme/host/nvme.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/sed-opal.h>
1616
#include <linux/fault-inject.h>
1717
#include <linux/rcupdate.h>
18+
#include <linux/wait.h>
1819

1920
#include <trace/events/block.h>
2021

@@ -198,6 +199,7 @@ struct nvme_ctrl {
198199
struct cdev cdev;
199200
struct work_struct reset_work;
200201
struct work_struct delete_work;
202+
wait_queue_head_t state_wq;
201203

202204
struct nvme_subsystem *subsys;
203205
struct list_head subsys_entry;
@@ -448,6 +450,7 @@ void nvme_complete_rq(struct request *req);
448450
bool nvme_cancel_request(struct request *req, void *data, bool reserved);
449451
bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
450452
enum nvme_ctrl_state new_state);
453+
bool nvme_wait_reset(struct nvme_ctrl *ctrl);
451454
int nvme_disable_ctrl(struct nvme_ctrl *ctrl);
452455
int nvme_enable_ctrl(struct nvme_ctrl *ctrl);
453456
int nvme_shutdown_ctrl(struct nvme_ctrl *ctrl);
@@ -498,6 +501,7 @@ int nvme_set_queue_count(struct nvme_ctrl *ctrl, int *count);
498501
void nvme_stop_keep_alive(struct nvme_ctrl *ctrl);
499502
int nvme_reset_ctrl(struct nvme_ctrl *ctrl);
500503
int nvme_reset_ctrl_sync(struct nvme_ctrl *ctrl);
504+
int nvme_try_sched_reset(struct nvme_ctrl *ctrl);
501505
int nvme_delete_ctrl(struct nvme_ctrl *ctrl);
502506

503507
int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp,

drivers/nvme/host/pci.c

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2463,6 +2463,14 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
24632463
mutex_unlock(&dev->shutdown_lock);
24642464
}
24652465

2466+
static int nvme_disable_prepare_reset(struct nvme_dev *dev, bool shutdown)
2467+
{
2468+
if (!nvme_wait_reset(&dev->ctrl))
2469+
return -EBUSY;
2470+
nvme_dev_disable(dev, shutdown);
2471+
return 0;
2472+
}
2473+
24662474
static int nvme_setup_prp_pools(struct nvme_dev *dev)
24672475
{
24682476
dev->prp_page_pool = dma_pool_create("prp list page", dev->dev,
@@ -2510,6 +2518,11 @@ static void nvme_pci_free_ctrl(struct nvme_ctrl *ctrl)
25102518

25112519
static void nvme_remove_dead_ctrl(struct nvme_dev *dev)
25122520
{
2521+
/*
2522+
* Set state to deleting now to avoid blocking nvme_wait_reset(), which
2523+
* may be holding this pci_dev's device lock.
2524+
*/
2525+
nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DELETING);
25132526
nvme_get_ctrl(&dev->ctrl);
25142527
nvme_dev_disable(dev, false);
25152528
nvme_kill_queues(&dev->ctrl);
@@ -2835,19 +2848,28 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
28352848
static void nvme_reset_prepare(struct pci_dev *pdev)
28362849
{
28372850
struct nvme_dev *dev = pci_get_drvdata(pdev);
2838-
nvme_dev_disable(dev, false);
2851+
2852+
/*
2853+
* We don't need to check the return value from waiting for the reset
2854+
* state as pci_dev device lock is held, making it impossible to race
2855+
* with ->remove().
2856+
*/
2857+
nvme_disable_prepare_reset(dev, false);
2858+
nvme_sync_queues(&dev->ctrl);
28392859
}
28402860

28412861
static void nvme_reset_done(struct pci_dev *pdev)
28422862
{
28432863
struct nvme_dev *dev = pci_get_drvdata(pdev);
2844-
nvme_reset_ctrl_sync(&dev->ctrl);
2864+
2865+
if (!nvme_try_sched_reset(&dev->ctrl))
2866+
flush_work(&dev->ctrl.reset_work);
28452867
}
28462868

28472869
static void nvme_shutdown(struct pci_dev *pdev)
28482870
{
28492871
struct nvme_dev *dev = pci_get_drvdata(pdev);
2850-
nvme_dev_disable(dev, true);
2872+
nvme_disable_prepare_reset(dev, true);
28512873
}
28522874

28532875
/*
@@ -2900,7 +2922,7 @@ static int nvme_resume(struct device *dev)
29002922

29012923
if (ndev->last_ps == U32_MAX ||
29022924
nvme_set_power_state(ctrl, ndev->last_ps) != 0)
2903-
nvme_reset_ctrl(ctrl);
2925+
return nvme_try_sched_reset(&ndev->ctrl);
29042926
return 0;
29052927
}
29062928

@@ -2928,10 +2950,8 @@ static int nvme_suspend(struct device *dev)
29282950
*/
29292951
if (pm_suspend_via_firmware() || !ctrl->npss ||
29302952
!pcie_aspm_enabled(pdev) ||
2931-
(ndev->ctrl.quirks & NVME_QUIRK_SIMPLE_SUSPEND)) {
2932-
nvme_dev_disable(ndev, true);
2933-
return 0;
2934-
}
2953+
(ndev->ctrl.quirks & NVME_QUIRK_SIMPLE_SUSPEND))
2954+
return nvme_disable_prepare_reset(ndev, true);
29352955

29362956
nvme_start_freeze(ctrl);
29372957
nvme_wait_freeze(ctrl);
@@ -2963,9 +2983,8 @@ static int nvme_suspend(struct device *dev)
29632983
* Clearing npss forces a controller reset on resume. The
29642984
* correct value will be resdicovered then.
29652985
*/
2966-
nvme_dev_disable(ndev, true);
2986+
ret = nvme_disable_prepare_reset(ndev, true);
29672987
ctrl->npss = 0;
2968-
ret = 0;
29692988
}
29702989
unfreeze:
29712990
nvme_unfreeze(ctrl);
@@ -2975,18 +2994,15 @@ static int nvme_suspend(struct device *dev)
29752994
static int nvme_simple_suspend(struct device *dev)
29762995
{
29772996
struct nvme_dev *ndev = pci_get_drvdata(to_pci_dev(dev));
2978-
2979-
nvme_dev_disable(ndev, true);
2980-
return 0;
2997+
return nvme_disable_prepare_reset(ndev, true);
29812998
}
29822999

29833000
static int nvme_simple_resume(struct device *dev)
29843001
{
29853002
struct pci_dev *pdev = to_pci_dev(dev);
29863003
struct nvme_dev *ndev = pci_get_drvdata(pdev);
29873004

2988-
nvme_reset_ctrl(&ndev->ctrl);
2989-
return 0;
3005+
return nvme_try_sched_reset(&ndev->ctrl);
29903006
}
29913007

29923008
static const struct dev_pm_ops nvme_dev_pm_ops = {

0 commit comments

Comments
 (0)