]> git.baikalelectronics.ru Git - kernel.git/commitdiff
nvme: ensure subsystem reset is single threaded
authorKeith Busch <kbusch@kernel.org>
Thu, 22 Sep 2022 15:13:47 +0000 (08:13 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 8 Dec 2022 10:23:05 +0000 (11:23 +0100)
commit 7a1ebcdac9d52bb7416bc410ed60d4aee92f9a5b upstream.

The subsystem reset writes to a register, so we have to ensure the
device state is capable of handling that otherwise the driver may access
unmapped registers. Use the state machine to ensure the subsystem reset
doesn't try to write registers on a device already undergoing this type
of reset.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=214771
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/nvme/host/nvme.h

index 81a5b968253ff2032374d3dde82bf7b8318d9f3a..17c0d6ae3eeeb123b586490e237d2f041b8ccd30 100644 (file)
@@ -422,11 +422,23 @@ static inline void nvme_fault_inject_fini(struct nvme_fault_inject *fault_inj)
 static inline void nvme_should_fail(struct request *req) {}
 #endif
 
+bool nvme_wait_reset(struct nvme_ctrl *ctrl);
+int nvme_try_sched_reset(struct nvme_ctrl *ctrl);
+
 static inline int nvme_reset_subsystem(struct nvme_ctrl *ctrl)
 {
+       int ret;
+
        if (!ctrl->subsystem)
                return -ENOTTY;
-       return ctrl->ops->reg_write32(ctrl, NVME_REG_NSSR, 0x4E564D65);
+       if (!nvme_wait_reset(ctrl))
+               return -EBUSY;
+
+       ret = ctrl->ops->reg_write32(ctrl, NVME_REG_NSSR, 0x4E564D65);
+       if (ret)
+               return ret;
+
+       return nvme_try_sched_reset(ctrl);
 }
 
 /*
@@ -473,7 +485,6 @@ void nvme_cancel_tagset(struct nvme_ctrl *ctrl);
 void nvme_cancel_admin_tagset(struct nvme_ctrl *ctrl);
 bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
                enum nvme_ctrl_state new_state);
-bool nvme_wait_reset(struct nvme_ctrl *ctrl);
 int nvme_disable_ctrl(struct nvme_ctrl *ctrl);
 int nvme_enable_ctrl(struct nvme_ctrl *ctrl);
 int nvme_shutdown_ctrl(struct nvme_ctrl *ctrl);
@@ -525,7 +536,6 @@ int nvme_set_queue_count(struct nvme_ctrl *ctrl, int *count);
 void nvme_stop_keep_alive(struct nvme_ctrl *ctrl);
 int nvme_reset_ctrl(struct nvme_ctrl *ctrl);
 int nvme_reset_ctrl_sync(struct nvme_ctrl *ctrl);
-int nvme_try_sched_reset(struct nvme_ctrl *ctrl);
 int nvme_delete_ctrl(struct nvme_ctrl *ctrl);
 
 int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp,