All of lore.kernel.org
 help / color / mirror / Atom feed
* RFC: handle completions outside the queue lock and split the queue lock
@ 2018-05-17 16:31 Christoph Hellwig
  2018-05-17 16:31 ` [PATCH 1/7] nvme: mark the result argument to nvme_complete_async_event volatile Christoph Hellwig
                   ` (8 more replies)
  0 siblings, 9 replies; 15+ messages in thread
From: Christoph Hellwig @ 2018-05-17 16:31 UTC (permalink / raw)


Mostly the previous work from Jens, just with random cleanups from me
thrown in.  Based on nvme/nvme-4.18 minus the two top-most commits,
very lightly tested.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/7] nvme: mark the result argument to nvme_complete_async_event volatile
  2018-05-17 16:31 RFC: handle completions outside the queue lock and split the queue lock Christoph Hellwig
@ 2018-05-17 16:31 ` Christoph Hellwig
  2018-05-17 16:31 ` [PATCH 2/7] nvme-pci: simplify nvme_cqe_valid Christoph Hellwig
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Christoph Hellwig @ 2018-05-17 16:31 UTC (permalink / raw)


We'll need that in the PCIe driver soon as we'll read it straight off the
CQ.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 drivers/nvme/host/core.c | 2 +-
 drivers/nvme/host/nvme.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 62262fac7a5d..b070c659391f 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -3344,7 +3344,7 @@ static void nvme_fw_act_work(struct work_struct *work)
 }
 
 void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
-		union nvme_result *res)
+		volatile union nvme_result *res)
 {
 	u32 result = le32_to_cpu(res->u32);
 
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 061fecfd44f5..7a872b0d53a7 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -400,7 +400,7 @@ int nvme_sec_submit(void *data, u16 spsp, u8 secp, void *buffer, size_t len,
 		bool send);
 
 void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
-		union nvme_result *res);
+		volatile union nvme_result *res);
 
 void nvme_stop_queues(struct nvme_ctrl *ctrl);
 void nvme_start_queues(struct nvme_ctrl *ctrl);
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/7] nvme-pci: simplify nvme_cqe_valid
  2018-05-17 16:31 RFC: handle completions outside the queue lock and split the queue lock Christoph Hellwig
  2018-05-17 16:31 ` [PATCH 1/7] nvme: mark the result argument to nvme_complete_async_event volatile Christoph Hellwig
@ 2018-05-17 16:31 ` Christoph Hellwig
  2018-05-17 16:31 ` [PATCH 3/7] nvme-pci: remove cq check after submission Christoph Hellwig
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Christoph Hellwig @ 2018-05-17 16:31 UTC (permalink / raw)


We always look at the current CQ head and phase, so don't pass these
as separate arguments, and rename the function to nvme_cqe_pending.

Also micro-optimize by byte swapping the constant 1 instead of the status.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 drivers/nvme/host/pci.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index b58aebb347a0..4b8c3420ace6 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -915,10 +915,10 @@ static void nvme_pci_complete_rq(struct request *req)
 }
 
 /* We read the CQE phase first to check if the rest of the entry is valid */
-static inline bool nvme_cqe_valid(struct nvme_queue *nvmeq, u16 head,
-		u16 phase)
+static inline bool nvme_cqe_pending(struct nvme_queue *nvmeq)
 {
-	return (le16_to_cpu(nvmeq->cqes[head].status) & 1) == phase;
+	return ((nvmeq->cqes[nvmeq->cq_head].status) & cpu_to_le16(1)) ==
+			nvmeq->cq_phase;
 }
 
 static inline void nvme_ring_cq_doorbell(struct nvme_queue *nvmeq)
@@ -965,7 +965,7 @@ static inline void nvme_handle_cqe(struct nvme_queue *nvmeq,
 static inline bool nvme_read_cqe(struct nvme_queue *nvmeq,
 		struct nvme_completion *cqe)
 {
-	if (nvme_cqe_valid(nvmeq, nvmeq->cq_head, nvmeq->cq_phase)) {
+	if (nvme_cqe_pending(nvmeq)) {
 		*cqe = nvmeq->cqes[nvmeq->cq_head];
 
 		if (++nvmeq->cq_head == nvmeq->q_depth) {
@@ -1006,7 +1006,7 @@ static irqreturn_t nvme_irq(int irq, void *data)
 static irqreturn_t nvme_irq_check(int irq, void *data)
 {
 	struct nvme_queue *nvmeq = data;
-	if (nvme_cqe_valid(nvmeq, nvmeq->cq_head, nvmeq->cq_phase))
+	if (nvme_cqe_pending(nvmeq))
 		return IRQ_WAKE_THREAD;
 	return IRQ_NONE;
 }
@@ -1016,7 +1016,7 @@ static int __nvme_poll(struct nvme_queue *nvmeq, unsigned int tag)
 	struct nvme_completion cqe;
 	int found = 0, consumed = 0;
 
-	if (!nvme_cqe_valid(nvmeq, nvmeq->cq_head, nvmeq->cq_phase))
+	if (!nvme_cqe_pending(nvmeq))
 		return 0;
 
 	spin_lock_irq(&nvmeq->q_lock);
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/7] nvme-pci: remove cq check after submission
  2018-05-17 16:31 RFC: handle completions outside the queue lock and split the queue lock Christoph Hellwig
  2018-05-17 16:31 ` [PATCH 1/7] nvme: mark the result argument to nvme_complete_async_event volatile Christoph Hellwig
  2018-05-17 16:31 ` [PATCH 2/7] nvme-pci: simplify nvme_cqe_valid Christoph Hellwig
@ 2018-05-17 16:31 ` Christoph Hellwig
  2018-05-17 16:31 ` [PATCH 4/7] nvme-pci: move ->cq_vector == -1 check outside of ->q_lock Christoph Hellwig
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Christoph Hellwig @ 2018-05-17 16:31 UTC (permalink / raw)


From: Jens Axboe <axboe@kernel.dk>

We always check the completion queue after submitting, but in my testing
this isn't a win even on DRAM/xpoint devices. In some cases it's
actually worse. Kill it.

Signed-off-by: Jens Axboe <axboe at kernel.dk>
Signed-off-by: Keith Busch <keith.busch at intel.com>
Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 drivers/nvme/host/pci.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 4b8c3420ace6..16eacae3b69d 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -69,7 +69,6 @@ MODULE_PARM_DESC(io_queue_depth, "set io queue depth, should >= 2");
 struct nvme_dev;
 struct nvme_queue;
 
-static void nvme_process_cq(struct nvme_queue *nvmeq);
 static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown);
 
 /*
@@ -896,7 +895,6 @@ static blk_status_t nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
 		goto out_cleanup_iod;
 	}
 	__nvme_submit_cmd(nvmeq, &cmnd);
-	nvme_process_cq(nvmeq);
 	spin_unlock_irq(&nvmeq->q_lock);
 	return BLK_STS_OK;
 out_cleanup_iod:
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/7] nvme-pci: move ->cq_vector == -1 check outside of ->q_lock
  2018-05-17 16:31 RFC: handle completions outside the queue lock and split the queue lock Christoph Hellwig
                   ` (2 preceding siblings ...)
  2018-05-17 16:31 ` [PATCH 3/7] nvme-pci: remove cq check after submission Christoph Hellwig
@ 2018-05-17 16:31 ` Christoph Hellwig
  2018-05-17 16:31 ` [PATCH 5/7] nvme-pci: handle completions outside of the queue lock Christoph Hellwig
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Christoph Hellwig @ 2018-05-17 16:31 UTC (permalink / raw)


From: Jens Axboe <axboe@kernel.dk>

We only clear it dynamically in nvme_suspend_queue(). When we do, ensure
to do a full flush so that any nvme_queue_rq() invocation will see it.

Ideally we'd kill this check completely, but we're using it to flush
requests on a dying queue.

Signed-off-by: Jens Axboe <axboe at kernel.dk>
Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 drivers/nvme/host/pci.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 16eacae3b69d..258f097fddbc 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -872,6 +872,13 @@ static blk_status_t nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
 	struct nvme_command cmnd;
 	blk_status_t ret;
 
+	/*
+	 * We should not need to do this, but we're still using this to
+	 * ensure we can drain requests on a dying queue.
+	 */
+	if (unlikely(nvmeq->cq_vector < 0))
+		return BLK_STS_IOERR;
+
 	ret = nvme_setup_cmd(ns, req, &cmnd);
 	if (ret)
 		return ret;
@@ -889,11 +896,6 @@ static blk_status_t nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
 	blk_mq_start_request(req);
 
 	spin_lock_irq(&nvmeq->q_lock);
-	if (unlikely(nvmeq->cq_vector < 0)) {
-		ret = BLK_STS_IOERR;
-		spin_unlock_irq(&nvmeq->q_lock);
-		goto out_cleanup_iod;
-	}
 	__nvme_submit_cmd(nvmeq, &cmnd);
 	spin_unlock_irq(&nvmeq->q_lock);
 	return BLK_STS_OK;
@@ -1321,6 +1323,12 @@ static int nvme_suspend_queue(struct nvme_queue *nvmeq)
 	nvmeq->cq_vector = -1;
 	spin_unlock_irq(&nvmeq->q_lock);
 
+	/*
+	 * Ensure that nvme_queue_rq() sees it ->cq_vector == -1 without
+	 * having to grab the lock.
+	 */
+	mb();
+
 	if (!nvmeq->qid && nvmeq->dev->ctrl.admin_q)
 		blk_mq_quiesce_queue(nvmeq->dev->ctrl.admin_q);
 
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/7] nvme-pci: handle completions outside of the queue lock
  2018-05-17 16:31 RFC: handle completions outside the queue lock and split the queue lock Christoph Hellwig
                   ` (3 preceding siblings ...)
  2018-05-17 16:31 ` [PATCH 4/7] nvme-pci: move ->cq_vector == -1 check outside of ->q_lock Christoph Hellwig
@ 2018-05-17 16:31 ` Christoph Hellwig
  2018-05-17 16:31 ` [PATCH 6/7] nvme-pci: split the nvme queue lock into submission and completion locks Christoph Hellwig
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Christoph Hellwig @ 2018-05-17 16:31 UTC (permalink / raw)


Split the completion of events into a two part process:

1) Reap the events inside the queue lock
2) Complete the events outside the queue lock

Since we never wrap the queue, we can access it locklessly after we've
updated the completion queue head. This patch started off with batching
events on the stack, but with this trick we don't have to. Keith Busch
<keith.busch at intel.com> came up with that idea.

Note that this kills the ->cqe_seen as well. I haven't been able to
trigger any ill effects of this. If we do race with polling every so
often, it should be rare enough NOT to trigger any issues.

Signed-off-by: Jens Axboe <axboe at kernel.dk>
Signed-off-by: Keith Busch <keith.busch at intel.com>
[hch: refactored, restored poll early exit optimization]
Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 drivers/nvme/host/pci.c | 87 +++++++++++++++++++++--------------------
 1 file changed, 45 insertions(+), 42 deletions(-)

diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 258f097fddbc..246882bdef54 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -161,7 +161,6 @@ struct nvme_queue {
 	u16 cq_head;
 	u16 qid;
 	u8 cq_phase;
-	u8 cqe_seen;
 	u32 *dbbuf_sq_db;
 	u32 *dbbuf_cq_db;
 	u32 *dbbuf_sq_ei;
@@ -932,9 +931,9 @@ static inline void nvme_ring_cq_doorbell(struct nvme_queue *nvmeq)
 	}
 }
 
-static inline void nvme_handle_cqe(struct nvme_queue *nvmeq,
-		struct nvme_completion *cqe)
+static inline void nvme_handle_cqe(struct nvme_queue *nvmeq, u16 idx)
 {
+	volatile struct nvme_completion *cqe = &nvmeq->cqes[idx];
 	struct request *req;
 
 	if (unlikely(cqe->command_id >= nvmeq->q_depth)) {
@@ -957,50 +956,58 @@ static inline void nvme_handle_cqe(struct nvme_queue *nvmeq,
 		return;
 	}
 
-	nvmeq->cqe_seen = 1;
 	req = blk_mq_tag_to_rq(*nvmeq->tags, cqe->command_id);
 	nvme_end_request(req, cqe->status, cqe->result);
 }
 
-static inline bool nvme_read_cqe(struct nvme_queue *nvmeq,
-		struct nvme_completion *cqe)
+static void nvme_complete_cqes(struct nvme_queue *nvmeq, u16 start, u16 end)
 {
-	if (nvme_cqe_pending(nvmeq)) {
-		*cqe = nvmeq->cqes[nvmeq->cq_head];
+	while (start != end) {
+		nvme_handle_cqe(nvmeq, start);
+		if (++start == nvmeq->q_depth)
+			start = 0;
+	}
+}
 
-		if (++nvmeq->cq_head == nvmeq->q_depth) {
-			nvmeq->cq_head = 0;
-			nvmeq->cq_phase = !nvmeq->cq_phase;
-		}
-		return true;
+static inline void nvme_update_cq_head(struct nvme_queue *nvmeq)
+{
+	if (++nvmeq->cq_head == nvmeq->q_depth) {
+		nvmeq->cq_head = 0;
+		nvmeq->cq_phase = !nvmeq->cq_phase;
 	}
-	return false;
 }
 
-static void nvme_process_cq(struct nvme_queue *nvmeq)
+static inline bool nvme_process_cq(struct nvme_queue *nvmeq, u16 *start,
+		u16 *end, int tag)
 {
-	struct nvme_completion cqe;
-	int consumed = 0;
+	bool found = false;
 
-	while (nvme_read_cqe(nvmeq, &cqe)) {
-		nvme_handle_cqe(nvmeq, &cqe);
-		consumed++;
+	*start = nvmeq->cq_head;
+	while (!found && nvme_cqe_pending(nvmeq)) {
+		if (nvmeq->cqes[nvmeq->cq_head].command_id == tag)
+			found = true;
+		nvme_update_cq_head(nvmeq);
 	}
+	*end = nvmeq->cq_head;
 
-	if (consumed)
+	if (*start != *end)
 		nvme_ring_cq_doorbell(nvmeq);
+	return found;
 }
 
 static irqreturn_t nvme_irq(int irq, void *data)
 {
-	irqreturn_t result;
 	struct nvme_queue *nvmeq = data;
+	u16 start, end;
+
 	spin_lock(&nvmeq->q_lock);
-	nvme_process_cq(nvmeq);
-	result = nvmeq->cqe_seen ? IRQ_HANDLED : IRQ_NONE;
-	nvmeq->cqe_seen = 0;
+	nvme_process_cq(nvmeq, &start, &end, -1);
 	spin_unlock(&nvmeq->q_lock);
-	return result;
+
+	if (start == end)
+		return IRQ_NONE;
+	nvme_complete_cqes(nvmeq, start, end);
+	return IRQ_HANDLED;
 }
 
 static irqreturn_t nvme_irq_check(int irq, void *data)
@@ -1013,27 +1020,17 @@ static irqreturn_t nvme_irq_check(int irq, void *data)
 
 static int __nvme_poll(struct nvme_queue *nvmeq, unsigned int tag)
 {
-	struct nvme_completion cqe;
-	int found = 0, consumed = 0;
+	u16 start, end;
+	bool found;
 
 	if (!nvme_cqe_pending(nvmeq))
 		return 0;
 
 	spin_lock_irq(&nvmeq->q_lock);
-	while (nvme_read_cqe(nvmeq, &cqe)) {
-		nvme_handle_cqe(nvmeq, &cqe);
-		consumed++;
-
-		if (tag == cqe.command_id) {
-			found = 1;
-			break;
-		}
-       }
-
-	if (consumed)
-		nvme_ring_cq_doorbell(nvmeq);
+	found = nvme_process_cq(nvmeq, &start, &end, tag);
 	spin_unlock_irq(&nvmeq->q_lock);
 
+	nvme_complete_cqes(nvmeq, start, end);
 	return found;
 }
 
@@ -1340,6 +1337,7 @@ static int nvme_suspend_queue(struct nvme_queue *nvmeq)
 static void nvme_disable_admin_queue(struct nvme_dev *dev, bool shutdown)
 {
 	struct nvme_queue *nvmeq = &dev->queues[0];
+	u16 start, end;
 
 	if (shutdown)
 		nvme_shutdown_ctrl(&dev->ctrl);
@@ -1347,8 +1345,10 @@ static void nvme_disable_admin_queue(struct nvme_dev *dev, bool shutdown)
 		nvme_disable_ctrl(&dev->ctrl, dev->ctrl.cap);
 
 	spin_lock_irq(&nvmeq->q_lock);
-	nvme_process_cq(nvmeq);
+	nvme_process_cq(nvmeq, &start, &end, -1);
 	spin_unlock_irq(&nvmeq->q_lock);
+
+	nvme_complete_cqes(nvmeq, start, end);
 }
 
 static int nvme_cmb_qdepth(struct nvme_dev *dev, int nr_io_queues,
@@ -1995,6 +1995,7 @@ static void nvme_del_queue_end(struct request *req, blk_status_t error)
 static void nvme_del_cq_end(struct request *req, blk_status_t error)
 {
 	struct nvme_queue *nvmeq = req->end_io_data;
+	u16 start, end;
 
 	if (!error) {
 		unsigned long flags;
@@ -2006,8 +2007,10 @@ static void nvme_del_cq_end(struct request *req, blk_status_t error)
 		 */
 		spin_lock_irqsave_nested(&nvmeq->q_lock, flags,
 					SINGLE_DEPTH_NESTING);
-		nvme_process_cq(nvmeq);
+		nvme_process_cq(nvmeq, &start, &end, -1);
 		spin_unlock_irqrestore(&nvmeq->q_lock, flags);
+
+		nvme_complete_cqes(nvmeq, start, end);
 	}
 
 	nvme_del_queue_end(req, error);
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 6/7] nvme-pci: split the nvme queue lock into submission and completion locks
  2018-05-17 16:31 RFC: handle completions outside the queue lock and split the queue lock Christoph Hellwig
                   ` (4 preceding siblings ...)
  2018-05-17 16:31 ` [PATCH 5/7] nvme-pci: handle completions outside of the queue lock Christoph Hellwig
@ 2018-05-17 16:31 ` Christoph Hellwig
  2018-05-17 16:31 ` [PATCH 7/7] nvme-pci: drop IRQ disabling on submission queue lock Christoph Hellwig
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Christoph Hellwig @ 2018-05-17 16:31 UTC (permalink / raw)


This is now feasible. We protect the submission queue ring with
->sq_lock, and the completion side with ->cq_lock.

Reviewed-by: Christoph Hellwig <hch at lst.de>
Signed-off-by: Jens Axboe <axboe at kernel.dk>
Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 drivers/nvme/host/pci.c | 44 +++++++++++++++++++++--------------------
 1 file changed, 23 insertions(+), 21 deletions(-)

diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 246882bdef54..49c783801fd4 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -147,9 +147,10 @@ static inline struct nvme_dev *to_nvme_dev(struct nvme_ctrl *ctrl)
 struct nvme_queue {
 	struct device *q_dmadev;
 	struct nvme_dev *dev;
-	spinlock_t q_lock;
+	spinlock_t sq_lock;
 	struct nvme_command *sq_cmds;
 	struct nvme_command __iomem *sq_cmds_io;
+	spinlock_t cq_lock ____cacheline_aligned_in_smp;
 	volatile struct nvme_completion *cqes;
 	struct blk_mq_tags **tags;
 	dma_addr_t sq_dma_addr;
@@ -894,9 +895,9 @@ static blk_status_t nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
 
 	blk_mq_start_request(req);
 
-	spin_lock_irq(&nvmeq->q_lock);
+	spin_lock_irq(&nvmeq->sq_lock);
 	__nvme_submit_cmd(nvmeq, &cmnd);
-	spin_unlock_irq(&nvmeq->q_lock);
+	spin_unlock_irq(&nvmeq->sq_lock);
 	return BLK_STS_OK;
 out_cleanup_iod:
 	nvme_free_iod(dev, req);
@@ -1000,9 +1001,9 @@ static irqreturn_t nvme_irq(int irq, void *data)
 	struct nvme_queue *nvmeq = data;
 	u16 start, end;
 
-	spin_lock(&nvmeq->q_lock);
+	spin_lock(&nvmeq->cq_lock);
 	nvme_process_cq(nvmeq, &start, &end, -1);
-	spin_unlock(&nvmeq->q_lock);
+	spin_unlock(&nvmeq->cq_lock);
 
 	if (start == end)
 		return IRQ_NONE;
@@ -1026,9 +1027,9 @@ static int __nvme_poll(struct nvme_queue *nvmeq, unsigned int tag)
 	if (!nvme_cqe_pending(nvmeq))
 		return 0;
 
-	spin_lock_irq(&nvmeq->q_lock);
+	spin_lock_irq(&nvmeq->cq_lock);
 	found = nvme_process_cq(nvmeq, &start, &end, tag);
-	spin_unlock_irq(&nvmeq->q_lock);
+	spin_unlock_irq(&nvmeq->cq_lock);
 
 	nvme_complete_cqes(nvmeq, start, end);
 	return found;
@@ -1051,9 +1052,9 @@ static void nvme_pci_submit_async_event(struct nvme_ctrl *ctrl)
 	c.common.opcode = nvme_admin_async_event;
 	c.common.command_id = NVME_AQ_BLK_MQ_DEPTH;
 
-	spin_lock_irq(&nvmeq->q_lock);
+	spin_lock_irq(&nvmeq->sq_lock);
 	__nvme_submit_cmd(nvmeq, &c);
-	spin_unlock_irq(&nvmeq->q_lock);
+	spin_unlock_irq(&nvmeq->sq_lock);
 }
 
 static int adapter_delete_queue(struct nvme_dev *dev, u8 opcode, u16 id)
@@ -1310,15 +1311,15 @@ static int nvme_suspend_queue(struct nvme_queue *nvmeq)
 {
 	int vector;
 
-	spin_lock_irq(&nvmeq->q_lock);
+	spin_lock_irq(&nvmeq->cq_lock);
 	if (nvmeq->cq_vector == -1) {
-		spin_unlock_irq(&nvmeq->q_lock);
+		spin_unlock_irq(&nvmeq->cq_lock);
 		return 1;
 	}
 	vector = nvmeq->cq_vector;
 	nvmeq->dev->online_queues--;
 	nvmeq->cq_vector = -1;
-	spin_unlock_irq(&nvmeq->q_lock);
+	spin_unlock_irq(&nvmeq->cq_lock);
 
 	/*
 	 * Ensure that nvme_queue_rq() sees it ->cq_vector == -1 without
@@ -1344,9 +1345,9 @@ static void nvme_disable_admin_queue(struct nvme_dev *dev, bool shutdown)
 	else
 		nvme_disable_ctrl(&dev->ctrl, dev->ctrl.cap);
 
-	spin_lock_irq(&nvmeq->q_lock);
+	spin_lock_irq(&nvmeq->cq_lock);
 	nvme_process_cq(nvmeq, &start, &end, -1);
-	spin_unlock_irq(&nvmeq->q_lock);
+	spin_unlock_irq(&nvmeq->cq_lock);
 
 	nvme_complete_cqes(nvmeq, start, end);
 }
@@ -1406,7 +1407,8 @@ static int nvme_alloc_queue(struct nvme_dev *dev, int qid, int depth)
 
 	nvmeq->q_dmadev = dev->dev;
 	nvmeq->dev = dev;
-	spin_lock_init(&nvmeq->q_lock);
+	spin_lock_init(&nvmeq->sq_lock);
+	spin_lock_init(&nvmeq->cq_lock);
 	nvmeq->cq_head = 0;
 	nvmeq->cq_phase = 1;
 	nvmeq->q_db = &dev->dbs[qid * 2 * dev->db_stride];
@@ -1442,7 +1444,7 @@ static void nvme_init_queue(struct nvme_queue *nvmeq, u16 qid)
 {
 	struct nvme_dev *dev = nvmeq->dev;
 
-	spin_lock_irq(&nvmeq->q_lock);
+	spin_lock_irq(&nvmeq->cq_lock);
 	nvmeq->sq_tail = 0;
 	nvmeq->cq_head = 0;
 	nvmeq->cq_phase = 1;
@@ -1450,7 +1452,7 @@ static void nvme_init_queue(struct nvme_queue *nvmeq, u16 qid)
 	memset((void *)nvmeq->cqes, 0, CQ_SIZE(nvmeq->q_depth));
 	nvme_dbbuf_init(dev, nvmeq, qid);
 	dev->online_queues++;
-	spin_unlock_irq(&nvmeq->q_lock);
+	spin_unlock_irq(&nvmeq->cq_lock);
 }
 
 static int nvme_create_queue(struct nvme_queue *nvmeq, int qid)
@@ -2001,14 +2003,14 @@ static void nvme_del_cq_end(struct request *req, blk_status_t error)
 		unsigned long flags;
 
 		/*
-		 * We might be called with the AQ q_lock held
-		 * and the I/O queue q_lock should always
+		 * We might be called with the AQ cq_lock held
+		 * and the I/O queue cq_lock should always
 		 * nest inside the AQ one.
 		 */
-		spin_lock_irqsave_nested(&nvmeq->q_lock, flags,
+		spin_lock_irqsave_nested(&nvmeq->cq_lock, flags,
 					SINGLE_DEPTH_NESTING);
 		nvme_process_cq(nvmeq, &start, &end, -1);
-		spin_unlock_irqrestore(&nvmeq->q_lock, flags);
+		spin_unlock_irqrestore(&nvmeq->cq_lock, flags);
 
 		nvme_complete_cqes(nvmeq, start, end);
 	}
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 7/7] nvme-pci: drop IRQ disabling on submission queue lock
  2018-05-17 16:31 RFC: handle completions outside the queue lock and split the queue lock Christoph Hellwig
                   ` (5 preceding siblings ...)
  2018-05-17 16:31 ` [PATCH 6/7] nvme-pci: split the nvme queue lock into submission and completion locks Christoph Hellwig
@ 2018-05-17 16:31 ` Christoph Hellwig
  2018-05-17 16:36 ` RFC: handle completions outside the queue lock and split the " Jens Axboe
  2018-05-17 16:55 ` Keith Busch
  8 siblings, 0 replies; 15+ messages in thread
From: Christoph Hellwig @ 2018-05-17 16:31 UTC (permalink / raw)


From: Jens Axboe <axboe@kernel.dk>

Since we aren't sharing the lock for completions now, we don't
have to make it IRQ safe.

Reviewed-by: Christoph Hellwig <hch at lst.de>
Signed-off-by: Jens Axboe <axboe at kernel.dk>
Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 drivers/nvme/host/pci.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 49c783801fd4..96cf91256fc8 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -895,9 +895,9 @@ static blk_status_t nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
 
 	blk_mq_start_request(req);
 
-	spin_lock_irq(&nvmeq->sq_lock);
+	spin_lock(&nvmeq->sq_lock);
 	__nvme_submit_cmd(nvmeq, &cmnd);
-	spin_unlock_irq(&nvmeq->sq_lock);
+	spin_unlock(&nvmeq->sq_lock);
 	return BLK_STS_OK;
 out_cleanup_iod:
 	nvme_free_iod(dev, req);
@@ -1052,9 +1052,9 @@ static void nvme_pci_submit_async_event(struct nvme_ctrl *ctrl)
 	c.common.opcode = nvme_admin_async_event;
 	c.common.command_id = NVME_AQ_BLK_MQ_DEPTH;
 
-	spin_lock_irq(&nvmeq->sq_lock);
+	spin_lock(&nvmeq->sq_lock);
 	__nvme_submit_cmd(nvmeq, &c);
-	spin_unlock_irq(&nvmeq->sq_lock);
+	spin_unlock(&nvmeq->sq_lock);
 }
 
 static int adapter_delete_queue(struct nvme_dev *dev, u8 opcode, u16 id)
-- 
2.17.0

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* RFC: handle completions outside the queue lock and split the queue lock
  2018-05-17 16:31 RFC: handle completions outside the queue lock and split the queue lock Christoph Hellwig
                   ` (6 preceding siblings ...)
  2018-05-17 16:31 ` [PATCH 7/7] nvme-pci: drop IRQ disabling on submission queue lock Christoph Hellwig
@ 2018-05-17 16:36 ` Jens Axboe
  2018-05-17 16:44   ` Christoph Hellwig
  2018-05-17 16:55 ` Keith Busch
  8 siblings, 1 reply; 15+ messages in thread
From: Jens Axboe @ 2018-05-17 16:36 UTC (permalink / raw)


On 5/17/18 10:31 AM, Christoph Hellwig wrote:
> Mostly the previous work from Jens, just with random cleanups from me
> thrown in.  Based on nvme/nvme-4.18 minus the two top-most commits,
> very lightly tested.

Looks good to me, 1+2 are fine as prep patches. You can add my
Reviewed-by to those.

You messed up the attributions on 5+6 though.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RFC: handle completions outside the queue lock and split the queue lock
  2018-05-17 16:36 ` RFC: handle completions outside the queue lock and split the " Jens Axboe
@ 2018-05-17 16:44   ` Christoph Hellwig
  0 siblings, 0 replies; 15+ messages in thread
From: Christoph Hellwig @ 2018-05-17 16:44 UTC (permalink / raw)


On Thu, May 17, 2018@10:36:23AM -0600, Jens Axboe wrote:
> On 5/17/18 10:31 AM, Christoph Hellwig wrote:
> > Mostly the previous work from Jens, just with random cleanups from me
> > thrown in.  Based on nvme/nvme-4.18 minus the two top-most commits,
> > very lightly tested.
> 
> Looks good to me, 1+2 are fine as prep patches. You can add my
> Reviewed-by to those.
> 
> You messed up the attributions on 5+6 though.

Sigh.  I don't know why, but everytime git sees a conflict during
rebase I get these messed up.  I blame it on Linus..

> 
> -- 
> Jens Axboe
---end quoted text---

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RFC: handle completions outside the queue lock and split the queue lock
  2018-05-17 16:31 RFC: handle completions outside the queue lock and split the queue lock Christoph Hellwig
                   ` (7 preceding siblings ...)
  2018-05-17 16:36 ` RFC: handle completions outside the queue lock and split the " Jens Axboe
@ 2018-05-17 16:55 ` Keith Busch
  2018-05-17 17:00   ` Christoph Hellwig
  8 siblings, 1 reply; 15+ messages in thread
From: Keith Busch @ 2018-05-17 16:55 UTC (permalink / raw)


On Thu, May 17, 2018@06:31:45PM +0200, Christoph Hellwig wrote:
> Mostly the previous work from Jens, just with random cleanups from me
> thrown in.  Based on nvme/nvme-4.18 minus the two top-most commits,
> very lightly tested.

Looking good. I can force push a rebase removing the current top-two
commits. Sound okay?

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RFC: handle completions outside the queue lock and split the queue lock
  2018-05-17 16:55 ` Keith Busch
@ 2018-05-17 17:00   ` Christoph Hellwig
  2018-05-17 17:05     ` Keith Busch
  0 siblings, 1 reply; 15+ messages in thread
From: Christoph Hellwig @ 2018-05-17 17:00 UTC (permalink / raw)


On Thu, May 17, 2018@10:55:46AM -0600, Keith Busch wrote:
> On Thu, May 17, 2018@06:31:45PM +0200, Christoph Hellwig wrote:
> > Mostly the previous work from Jens, just with random cleanups from me
> > thrown in.  Based on nvme/nvme-4.18 minus the two top-most commits,
> > very lightly tested.
> 
> Looking good. I can force push a rebase removing the current top-two
> commits. Sound okay?

Yes, let's do that for now, and let pending series settle for another
day or two.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RFC: handle completions outside the queue lock and split the queue lock
  2018-05-17 17:00   ` Christoph Hellwig
@ 2018-05-17 17:05     ` Keith Busch
  2018-05-17 17:08       ` Jens Axboe
  0 siblings, 1 reply; 15+ messages in thread
From: Keith Busch @ 2018-05-17 17:05 UTC (permalink / raw)


On Thu, May 17, 2018@07:00:45PM +0200, Christoph Hellwig wrote:
> On Thu, May 17, 2018@10:55:46AM -0600, Keith Busch wrote:
> > On Thu, May 17, 2018@06:31:45PM +0200, Christoph Hellwig wrote:
> > > Mostly the previous work from Jens, just with random cleanups from me
> > > thrown in.  Based on nvme/nvme-4.18 minus the two top-most commits,
> > > very lightly tested.
> > 
> > Looking good. I can force push a rebase removing the current top-two
> > commits. Sound okay?
> 
> Yes, let's do that for now, and let pending series settle for another
> day or two.

Done. That's enough excitement for one day. :)

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RFC: handle completions outside the queue lock and split the queue lock
  2018-05-17 17:05     ` Keith Busch
@ 2018-05-17 17:08       ` Jens Axboe
  0 siblings, 0 replies; 15+ messages in thread
From: Jens Axboe @ 2018-05-17 17:08 UTC (permalink / raw)


On 5/17/18 11:05 AM, Keith Busch wrote:
> On Thu, May 17, 2018@07:00:45PM +0200, Christoph Hellwig wrote:
>> On Thu, May 17, 2018@10:55:46AM -0600, Keith Busch wrote:
>>> On Thu, May 17, 2018@06:31:45PM +0200, Christoph Hellwig wrote:
>>>> Mostly the previous work from Jens, just with random cleanups from me
>>>> thrown in.  Based on nvme/nvme-4.18 minus the two top-most commits,
>>>> very lightly tested.
>>>
>>> Looking good. I can force push a rebase removing the current top-two
>>> commits. Sound okay?
>>
>> Yes, let's do that for now, and let pending series settle for another
>> day or two.
> 
> Done. That's enough excitement for one day. :)

Bah, where's your sense of adventure!

FWIW, I'm testing this series, committed here:

http://git.kernel.dk/cgit/linux-block/log/?h=nvme-4.18

I'll report back end-of-day when the full cycle is done.

-- 
Jens Axboe

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/7] nvme: mark the result argument to nvme_complete_async_event volatile
  2018-05-18 14:52 [PATCHSET v2 0/7] Improve nvme completion handling Jens Axboe
@ 2018-05-18 14:52 ` Jens Axboe
  0 siblings, 0 replies; 15+ messages in thread
From: Jens Axboe @ 2018-05-18 14:52 UTC (permalink / raw)


From: Christoph Hellwig <hch@lst.de>

We'll need that in the PCIe driver soon as we'll read it straight off the
CQ.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 drivers/nvme/host/core.c | 2 +-
 drivers/nvme/host/nvme.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 99b857e5a7a9..c7c1298c6dc5 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -3323,7 +3323,7 @@ static void nvme_fw_act_work(struct work_struct *work)
 }
 
 void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
-		union nvme_result *res)
+		volatile union nvme_result *res)
 {
 	u32 result = le32_to_cpu(res->u32);
 
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 17d2f7cf3fed..de78eae52673 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -405,7 +405,7 @@ int nvme_sec_submit(void *data, u16 spsp, u8 secp, void *buffer, size_t len,
 		bool send);
 
 void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
-		union nvme_result *res);
+		volatile union nvme_result *res);
 
 void nvme_stop_queues(struct nvme_ctrl *ctrl);
 void nvme_start_queues(struct nvme_ctrl *ctrl);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2018-05-18 14:52 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-17 16:31 RFC: handle completions outside the queue lock and split the queue lock Christoph Hellwig
2018-05-17 16:31 ` [PATCH 1/7] nvme: mark the result argument to nvme_complete_async_event volatile Christoph Hellwig
2018-05-17 16:31 ` [PATCH 2/7] nvme-pci: simplify nvme_cqe_valid Christoph Hellwig
2018-05-17 16:31 ` [PATCH 3/7] nvme-pci: remove cq check after submission Christoph Hellwig
2018-05-17 16:31 ` [PATCH 4/7] nvme-pci: move ->cq_vector == -1 check outside of ->q_lock Christoph Hellwig
2018-05-17 16:31 ` [PATCH 5/7] nvme-pci: handle completions outside of the queue lock Christoph Hellwig
2018-05-17 16:31 ` [PATCH 6/7] nvme-pci: split the nvme queue lock into submission and completion locks Christoph Hellwig
2018-05-17 16:31 ` [PATCH 7/7] nvme-pci: drop IRQ disabling on submission queue lock Christoph Hellwig
2018-05-17 16:36 ` RFC: handle completions outside the queue lock and split the " Jens Axboe
2018-05-17 16:44   ` Christoph Hellwig
2018-05-17 16:55 ` Keith Busch
2018-05-17 17:00   ` Christoph Hellwig
2018-05-17 17:05     ` Keith Busch
2018-05-17 17:08       ` Jens Axboe
2018-05-18 14:52 [PATCHSET v2 0/7] Improve nvme completion handling Jens Axboe
2018-05-18 14:52 ` [PATCH 1/7] nvme: mark the result argument to nvme_complete_async_event volatile Jens Axboe

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.