[PATCH V4 5/7] nvme: core: introduce 'reset_lock' for sync reset state and reset activities

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



NVMe PCI may start a new reset context to run nested reset for recovering
from reset context, and we may not change the rule of state machine until
other kinds of NVMe controller support that, so use the 'reset_lock' to sync
the state change here.

Cc: Jianchao Wang <jianchao.w.wang@xxxxxxxxxx>
Cc: Christoph Hellwig <hch@xxxxxx>
Cc: Sagi Grimberg <sagi@xxxxxxxxxxx>
Cc: linux-nvme@xxxxxxxxxxxxxxxxxxx
Cc: Laurence Oberman <loberman@xxxxxxxxxx>
Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxx>
---
 drivers/nvme/host/core.c | 20 +++++++++++++++++---
 drivers/nvme/host/nvme.h |  3 +++
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 9df4f71e58ca..3aaee4dbf58e 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -100,13 +100,25 @@ static struct class *nvme_subsys_class;
 static void nvme_ns_remove(struct nvme_ns *ns);
 static int nvme_revalidate_disk(struct gendisk *disk);
 
+/*
+ * NVMe PCI may support nested reset for recovering from reset context,
+ * and we may not change the rule of state machine until other kinds of
+ * NVMe controller support that, so use the 'reset_lock' to sync the
+ * state change here.
+ */
 int nvme_reset_ctrl(struct nvme_ctrl *ctrl)
 {
+	int ret = -EBUSY;
+
+	mutex_lock(&ctrl->reset_lock);
 	if (!nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING))
-		return -EBUSY;
+		goto fail;
 	if (!queue_work(nvme_reset_wq, &ctrl->reset_work))
-		return -EBUSY;
-	return 0;
+		goto fail;
+	ret = 0;
+ fail:
+	mutex_unlock(&ctrl->reset_lock);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(nvme_reset_ctrl);
 
@@ -3447,6 +3459,8 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
 	INIT_WORK(&ctrl->fw_act_work, nvme_fw_act_work);
 	INIT_WORK(&ctrl->delete_work, nvme_delete_ctrl_work);
 
+	mutex_init(&ctrl->reset_lock);
+
 	ret = ida_simple_get(&nvme_instance_ida, 0, 0, GFP_KERNEL);
 	if (ret < 0)
 		goto out;
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 061fecfd44f5..99f55c6f69f8 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -146,6 +146,9 @@ struct nvme_ctrl {
 	struct device ctrl_device;
 	struct device *device;	/* char device */
 	struct cdev cdev;
+
+	/* sync reset state update and related reset activities */
+	struct mutex reset_lock;
 	struct work_struct reset_work;
 	struct work_struct delete_work;
 
-- 
2.9.5




[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux