All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv2 0/2] NVMe: Enable SQes on the CMB
@ 2015-06-23 22:33 Jon Derrick
  2015-06-23 22:33 ` [PATCHv2 1/2] NVMe: Unify SQ entry writing and doorbell ringing Jon Derrick
  2015-06-23 22:33 ` [PATCHv2 2/2] NVMe: Use CMB for the SQ if available Jon Derrick
  0 siblings, 2 replies; 7+ messages in thread
From: Jon Derrick @ 2015-06-23 22:33 UTC (permalink / raw)


This set unifies the command submission path, enables the cmb, and  maps
submission queues onto the controller memory buffer.

Jon Derrick (2):
  NVMe: Unify SQ entry writing and doorbell ringing
  NVMe: Use CMB for the SQ if available

 drivers/block/nvme-core.c | 197 ++++++++++++++++++++++++++++++++++------------
 include/linux/nvme.h      |  17 ++++
 2 files changed, 164 insertions(+), 50 deletions(-)

-- 
2.1.4

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

* [PATCHv2 1/2] NVMe: Unify SQ entry writing and doorbell ringing
  2015-06-23 22:33 [PATCHv2 0/2] NVMe: Enable SQes on the CMB Jon Derrick
@ 2015-06-23 22:33 ` Jon Derrick
  2015-06-23 22:33 ` [PATCHv2 2/2] NVMe: Use CMB for the SQ if available Jon Derrick
  1 sibling, 0 replies; 7+ messages in thread
From: Jon Derrick @ 2015-06-23 22:33 UTC (permalink / raw)


This patch changes sq_cmd writers to instead create their command on
the stack. __nvme_submit_cmd copies the sq entry to the queue and writes
the doorbell.

Signed-off-by: Jon Derrick <jonathan.derrick at intel.com>
---
 drivers/block/nvme-core.c | 80 +++++++++++++++++++++--------------------------
 1 file changed, 35 insertions(+), 45 deletions(-)

diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index a501d3e..62b71d6 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -720,18 +720,16 @@ static int nvme_setup_prps(struct nvme_dev *dev, struct nvme_iod *iod,
 static void nvme_submit_priv(struct nvme_queue *nvmeq, struct request *req,
 		struct nvme_iod *iod)
 {
-	struct nvme_command *cmnd = &nvmeq->sq_cmds[nvmeq->sq_tail];
+	struct nvme_command cmnd;
 
-	memcpy(cmnd, req->cmd, sizeof(struct nvme_command));
-	cmnd->rw.command_id = req->tag;
+	memcpy(&cmnd, req->cmd, sizeof(cmnd));
+	cmnd.rw.command_id = req->tag;
 	if (req->nr_phys_segments) {
-		cmnd->rw.prp1 = cpu_to_le64(sg_dma_address(iod->sg));
-		cmnd->rw.prp2 = cpu_to_le64(iod->first_dma);
+		cmnd.rw.prp1 = cpu_to_le64(sg_dma_address(iod->sg));
+		cmnd.rw.prp2 = cpu_to_le64(iod->first_dma);
 	}
 
-	if (++nvmeq->sq_tail == nvmeq->q_depth)
-		nvmeq->sq_tail = 0;
-	writel(nvmeq->sq_tail, nvmeq->q_db);
+	__nvme_submit_cmd(nvmeq, &cmnd);
 }
 
 /*
@@ -744,45 +742,41 @@ static void nvme_submit_discard(struct nvme_queue *nvmeq, struct nvme_ns *ns,
 {
 	struct nvme_dsm_range *range =
 				(struct nvme_dsm_range *)iod_list(iod)[0];
-	struct nvme_command *cmnd = &nvmeq->sq_cmds[nvmeq->sq_tail];
+	struct nvme_command cmnd;
 
 	range->cattr = cpu_to_le32(0);
 	range->nlb = cpu_to_le32(blk_rq_bytes(req) >> ns->lba_shift);
 	range->slba = cpu_to_le64(nvme_block_nr(ns, blk_rq_pos(req)));
 
-	memset(cmnd, 0, sizeof(*cmnd));
-	cmnd->dsm.opcode = nvme_cmd_dsm;
-	cmnd->dsm.command_id = req->tag;
-	cmnd->dsm.nsid = cpu_to_le32(ns->ns_id);
-	cmnd->dsm.prp1 = cpu_to_le64(iod->first_dma);
-	cmnd->dsm.nr = 0;
-	cmnd->dsm.attributes = cpu_to_le32(NVME_DSMGMT_AD);
+	memset(&cmnd, 0, sizeof(cmnd));
+	cmnd.dsm.opcode = nvme_cmd_dsm;
+	cmnd.dsm.command_id = req->tag;
+	cmnd.dsm.nsid = cpu_to_le32(ns->ns_id);
+	cmnd.dsm.prp1 = cpu_to_le64(iod->first_dma);
+	cmnd.dsm.nr = 0;
+	cmnd.dsm.attributes = cpu_to_le32(NVME_DSMGMT_AD);
 
-	if (++nvmeq->sq_tail == nvmeq->q_depth)
-		nvmeq->sq_tail = 0;
-	writel(nvmeq->sq_tail, nvmeq->q_db);
+	__nvme_submit_cmd(nvmeq, &cmnd);
 }
 
 static void nvme_submit_flush(struct nvme_queue *nvmeq, struct nvme_ns *ns,
 								int cmdid)
 {
-	struct nvme_command *cmnd = &nvmeq->sq_cmds[nvmeq->sq_tail];
+	struct nvme_command cmnd;
 
-	memset(cmnd, 0, sizeof(*cmnd));
-	cmnd->common.opcode = nvme_cmd_flush;
-	cmnd->common.command_id = cmdid;
-	cmnd->common.nsid = cpu_to_le32(ns->ns_id);
+	memset(&cmnd, 0, sizeof(cmnd));
+	cmnd.common.opcode = nvme_cmd_flush;
+	cmnd.common.command_id = cmdid;
+	cmnd.common.nsid = cpu_to_le32(ns->ns_id);
 
-	if (++nvmeq->sq_tail == nvmeq->q_depth)
-		nvmeq->sq_tail = 0;
-	writel(nvmeq->sq_tail, nvmeq->q_db);
+	__nvme_submit_cmd(nvmeq, &cmnd);
 }
 
 static int nvme_submit_iod(struct nvme_queue *nvmeq, struct nvme_iod *iod,
 							struct nvme_ns *ns)
 {
 	struct request *req = iod_get_private(iod);
-	struct nvme_command *cmnd;
+	struct nvme_command cmnd;
 	u16 control = 0;
 	u32 dsmgmt = 0;
 
@@ -794,19 +788,17 @@ static int nvme_submit_iod(struct nvme_queue *nvmeq, struct nvme_iod *iod,
 	if (req->cmd_flags & REQ_RAHEAD)
 		dsmgmt |= NVME_RW_DSM_FREQ_PREFETCH;
 
-	cmnd = &nvmeq->sq_cmds[nvmeq->sq_tail];
-	memset(cmnd, 0, sizeof(*cmnd));
-
-	cmnd->rw.opcode = (rq_data_dir(req) ? nvme_cmd_write : nvme_cmd_read);
-	cmnd->rw.command_id = req->tag;
-	cmnd->rw.nsid = cpu_to_le32(ns->ns_id);
-	cmnd->rw.prp1 = cpu_to_le64(sg_dma_address(iod->sg));
-	cmnd->rw.prp2 = cpu_to_le64(iod->first_dma);
-	cmnd->rw.slba = cpu_to_le64(nvme_block_nr(ns, blk_rq_pos(req)));
-	cmnd->rw.length = cpu_to_le16((blk_rq_bytes(req) >> ns->lba_shift) - 1);
+	memset(&cmnd, 0, sizeof(cmnd));
+	cmnd.rw.opcode = (rq_data_dir(req) ? nvme_cmd_write : nvme_cmd_read);
+	cmnd.rw.command_id = req->tag;
+	cmnd.rw.nsid = cpu_to_le32(ns->ns_id);
+	cmnd.rw.prp1 = cpu_to_le64(sg_dma_address(iod->sg));
+	cmnd.rw.prp2 = cpu_to_le64(iod->first_dma);
+	cmnd.rw.slba = cpu_to_le64(nvme_block_nr(ns, blk_rq_pos(req)));
+	cmnd.rw.length = cpu_to_le16((blk_rq_bytes(req) >> ns->lba_shift) - 1);
 
 	if (blk_integrity_rq(req)) {
-		cmnd->rw.metadata = cpu_to_le64(sg_dma_address(iod->meta_sg));
+		cmnd.rw.metadata = cpu_to_le64(sg_dma_address(iod->meta_sg));
 		switch (ns->pi_type) {
 		case NVME_NS_DPS_PI_TYPE3:
 			control |= NVME_RW_PRINFO_PRCHK_GUARD;
@@ -815,19 +807,17 @@ static int nvme_submit_iod(struct nvme_queue *nvmeq, struct nvme_iod *iod,
 		case NVME_NS_DPS_PI_TYPE2:
 			control |= NVME_RW_PRINFO_PRCHK_GUARD |
 					NVME_RW_PRINFO_PRCHK_REF;
-			cmnd->rw.reftag = cpu_to_le32(
+			cmnd.rw.reftag = cpu_to_le32(
 					nvme_block_nr(ns, blk_rq_pos(req)));
 			break;
 		}
 	} else if (ns->ms)
 		control |= NVME_RW_PRINFO_PRACT;
 
-	cmnd->rw.control = cpu_to_le16(control);
-	cmnd->rw.dsmgmt = cpu_to_le32(dsmgmt);
+	cmnd.rw.control = cpu_to_le16(control);
+	cmnd.rw.dsmgmt = cpu_to_le32(dsmgmt);
 
-	if (++nvmeq->sq_tail == nvmeq->q_depth)
-		nvmeq->sq_tail = 0;
-	writel(nvmeq->sq_tail, nvmeq->q_db);
+	__nvme_submit_cmd(nvmeq, &cmnd);
 
 	return 0;
 }
-- 
2.1.4

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

* [PATCHv2 2/2] NVMe: Use CMB for the SQ if available
  2015-06-23 22:33 [PATCHv2 0/2] NVMe: Enable SQes on the CMB Jon Derrick
  2015-06-23 22:33 ` [PATCHv2 1/2] NVMe: Unify SQ entry writing and doorbell ringing Jon Derrick
@ 2015-06-23 22:33 ` Jon Derrick
  2015-06-24 12:21   ` Christoph Hellwig
  2015-07-01  8:10   ` Stephen Bates
  1 sibling, 2 replies; 7+ messages in thread
From: Jon Derrick @ 2015-06-23 22:33 UTC (permalink / raw)


Some controllers have a controller-side memory buffer available for use
for submissions, completions, lists, or data.

If a CMB is available, the entire CMB will be ioremapped and it will
attempt to map the SQs onto the CMB. The queues will be shrunk as needed.
The CMB will not be used if the queue depth is shrunk below some
threshold where it may have reduced performance over a larger queue
in system memory.

Signed-off-by: Jon Derrick <jonathan.derrick at intel.com>
---
This is the 'bulk' of the patchset. The main differences between v1 and
v2 is that nvme_{get,put}_cmd has been removed and an __iomem version of
sq_cmds is available.

 drivers/block/nvme-core.c | 117 ++++++++++++++++++++++++++++++++++++++++++++--
 include/linux/nvme.h      |  17 +++++++
 2 files changed, 129 insertions(+), 5 deletions(-)

diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index 62b71d6..a8f1fa1 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -102,12 +102,16 @@ struct nvme_queue {
 	struct nvme_dev *dev;
 	char irqname[24];	/* nvme4294967295-65535\0 */
 	spinlock_t q_lock;
-	struct nvme_command *sq_cmds;
+	union {
+		struct nvme_command *sq_cmds;
+		struct nvme_command __iomem *sq_cmds_io;
+	};
 	volatile struct nvme_completion *cqes;
 	struct blk_mq_tags **tags;
 	dma_addr_t sq_dma_addr;
 	dma_addr_t cq_dma_addr;
 	u32 __iomem *q_db;
+	bool cmb_mapped;
 	u16 q_depth;
 	s16 cq_vector;
 	u16 sq_head;
@@ -376,7 +380,11 @@ static int __nvme_submit_cmd(struct nvme_queue *nvmeq, struct nvme_command *cmd)
 {
 	u16 tail = nvmeq->sq_tail;
 
-	memcpy(&nvmeq->sq_cmds[tail], cmd, sizeof(*cmd));
+	if (nvmeq->cmb_mapped)
+		memcpy_toio(&nvmeq->sq_cmds_io[tail], cmd, sizeof(*cmd));
+	else
+		memcpy(&nvmeq->sq_cmds[tail], cmd, sizeof(*cmd));
+
 	if (++tail == nvmeq->q_depth)
 		tail = 0;
 	writel(tail, nvmeq->q_db);
@@ -1352,7 +1360,8 @@ static void nvme_free_queue(struct nvme_queue *nvmeq)
 {
 	dma_free_coherent(nvmeq->q_dmadev, CQ_SIZE(nvmeq->q_depth),
 				(void *)nvmeq->cqes, nvmeq->cq_dma_addr);
-	dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth),
+	if (!nvmeq->cmb_mapped)
+		dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth),
 					nvmeq->sq_cmds, nvmeq->sq_dma_addr);
 	kfree(nvmeq);
 }
@@ -1425,6 +1434,44 @@ static void nvme_disable_queue(struct nvme_dev *dev, int qid)
 	spin_unlock_irq(&nvmeq->q_lock);
 }
 
+static int nvme_cmb_qdepth(struct nvme_dev *dev, int nr_io_queues,
+				int entry_size)
+{
+	int q_depth = dev->q_depth;
+	unsigned q_size_aligned = roundup(q_depth * entry_size, dev->page_size);
+
+	if (q_size_aligned * nr_io_queues > dev->cmb_size) {
+		q_depth = rounddown(dev->cmb_size / nr_io_queues,
+					dev->page_size) / entry_size;
+
+		/*
+		 * Ensure the reduced q_depth is above some threshold where it
+		 * would be better to map queues in system memory with the
+		 * original depth
+		 */
+		if (q_depth < 64)
+			return -ENOMEM;
+	}
+
+	return q_depth;
+}
+
+static void nvme_alloc_sq_cmds(struct nvme_dev *dev, struct nvme_queue *nvmeq,
+				int qid, int depth)
+{
+	if (qid && NVME_CMB_SQS(dev->cmbsz) && dev->cmb) {
+		unsigned offset = (qid - 1) *
+					roundup(SQ_SIZE(depth), dev->page_size);
+		nvmeq->cmb_mapped = true;
+		nvmeq->sq_dma_addr = dev->cmb_dma_addr + offset;
+		nvmeq->sq_cmds_io = dev->cmb + offset;
+	} else {
+		nvmeq->cmb_mapped = false;
+		nvmeq->sq_cmds = dma_alloc_coherent(dev->dev, SQ_SIZE(depth),
+					&nvmeq->sq_dma_addr, GFP_KERNEL);
+	}
+}
+
 static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid,
 							int depth)
 {
@@ -1437,8 +1484,7 @@ static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid,
 	if (!nvmeq->cqes)
 		goto free_nvmeq;
 
-	nvmeq->sq_cmds = dma_alloc_coherent(dev->dev, SQ_SIZE(depth),
-					&nvmeq->sq_dma_addr, GFP_KERNEL);
+	nvme_alloc_sq_cmds(dev, nvmeq, qid, depth);
 	if (!nvmeq->sq_cmds)
 		goto free_cqdma;
 
@@ -2122,6 +2168,55 @@ static int set_queue_count(struct nvme_dev *dev, int count)
 	return min(result & 0xffff, result >> 16) + 1;
 }
 
+static void __iomem *nvme_map_cmb(struct nvme_dev *dev)
+{
+	u64 szu, size, offset;
+	u32 cmbloc;
+	resource_size_t bar_size;
+	struct pci_dev *pdev = to_pci_dev(dev->dev);
+	void __iomem *cmb;
+	dma_addr_t dma_addr;
+
+	dev->cmbsz = readl(&dev->bar->cmbsz);
+	if (!(NVME_CMB_SZ(dev->cmbsz)))
+		return NULL;
+
+	cmbloc = readl(&dev->bar->cmbloc);
+
+	szu = 1 << (12 + 4 * NVME_CMB_SZU(dev->cmbsz));
+	size = szu * NVME_CMB_SZ(dev->cmbsz);
+	offset = szu * NVME_CMB_OFST(cmbloc);
+	bar_size = pci_resource_len(pdev, NVME_CMB_BIR(cmbloc));
+
+	if (offset > bar_size)
+		return NULL;
+
+	/*
+	 * Controllers may support a CMB size larger than their BAR,
+	 * for example, due to being behind a bridge. Reduce the CMB to
+	 * the reported size of the BAR
+	 */
+	if (size > bar_size - offset)
+		size = bar_size - offset;
+
+	dma_addr = pci_resource_start(pdev, NVME_CMB_BIR(cmbloc)) + offset;
+	cmb = ioremap_wc(dma_addr, size);
+	if (!cmb)
+		return NULL;
+
+	dev->cmb_dma_addr = dma_addr;
+	dev->cmb_size = size;
+	return cmb;
+}
+
+static inline void nvme_release_cmb(struct nvme_dev *dev)
+{
+	if (dev->cmb) {
+		iounmap(dev->cmb);
+		dev->cmb = NULL;
+	}
+}
+
 static size_t db_bar_size(struct nvme_dev *dev, unsigned nr_io_queues)
 {
 	return 4096 + ((nr_io_queues + 1) * 8 * dev->db_stride);
@@ -2140,6 +2235,15 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
 	if (result < nr_io_queues)
 		nr_io_queues = result;
 
+	if (NVME_CMB_SQS(dev->cmbsz) && dev->cmb) {
+		result = nvme_cmb_qdepth(dev, nr_io_queues,
+				sizeof(struct nvme_command));
+		if (result > 0)
+			dev->q_depth = result;
+		else
+			nvme_release_cmb(dev);
+	}
+
 	size = db_bar_size(dev, nr_io_queues);
 	if (size > 8192) {
 		iounmap(dev->bar);
@@ -2400,6 +2504,8 @@ static int nvme_dev_map(struct nvme_dev *dev)
 	dev->q_depth = min_t(int, NVME_CAP_MQES(cap) + 1, NVME_Q_DEPTH);
 	dev->db_stride = 1 << NVME_CAP_STRIDE(cap);
 	dev->dbs = ((void __iomem *)dev->bar) + 4096;
+	if (readl(&dev->bar->vs) >= NVME_VS(1, 2))
+		dev->cmb = nvme_map_cmb(dev);
 
 	return 0;
 
@@ -3098,6 +3204,7 @@ static void nvme_remove(struct pci_dev *pdev)
 	nvme_dev_remove_admin(dev);
 	device_destroy(nvme_class, MKDEV(nvme_char_major, dev->instance));
 	nvme_free_queues(dev, 0);
+	nvme_release_cmb(dev);
 	nvme_release_prp_pools(dev);
 	kref_put(&dev->kref, nvme_free_dev);
 }
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index c0d94ed..fa3fe16 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -32,6 +32,8 @@ struct nvme_bar {
 	__u32			aqa;	/* Admin Queue Attributes */
 	__u64			asq;	/* Admin SQ Base Address */
 	__u64			acq;	/* Admin CQ Base Address */
+	__u32			cmbloc; /* Controller Memory Buffer Location */
+	__u32			cmbsz;  /* Controller Memory Buffer Size */
 };
 
 #define NVME_CAP_MQES(cap)	((cap) & 0xffff)
@@ -40,6 +42,17 @@ struct nvme_bar {
 #define NVME_CAP_MPSMIN(cap)	(((cap) >> 48) & 0xf)
 #define NVME_CAP_MPSMAX(cap)	(((cap) >> 52) & 0xf)
 
+#define NVME_CMB_BIR(cmbloc)	((cmbloc) & 0x7)
+#define NVME_CMB_OFST(cmbloc)	(((cmbloc) >> 12) & 0xfffff)
+#define NVME_CMB_SZ(cmbsz)	(((cmbsz) >> 12) & 0xfffff)
+#define NVME_CMB_SZU(cmbsz)	(((cmbsz) >> 8) & 0xf)
+
+#define NVME_CMB_WDS(cmbsz)	((cmbsz) & 0x10)
+#define NVME_CMB_RDS(cmbsz)	((cmbsz) & 0x8)
+#define NVME_CMB_LISTS(cmbsz)	((cmbsz) & 0x4)
+#define NVME_CMB_CQS(cmbsz)	((cmbsz) & 0x2)
+#define NVME_CMB_SQS(cmbsz)	((cmbsz) & 0x1)
+
 enum {
 	NVME_CC_ENABLE		= 1 << 0,
 	NVME_CC_CSS_NVM		= 0 << 4,
@@ -100,6 +113,10 @@ struct nvme_dev {
 	u32 max_hw_sectors;
 	u32 stripe_size;
 	u32 page_size;
+	void __iomem *cmb;
+	dma_addr_t cmb_dma_addr;
+	u64 cmb_size;
+	u32 cmbsz;
 	u16 oncs;
 	u16 abort_limit;
 	u8 event_limit;
-- 
2.1.4

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

* [PATCHv2 2/2] NVMe: Use CMB for the SQ if available
  2015-06-23 22:33 ` [PATCHv2 2/2] NVMe: Use CMB for the SQ if available Jon Derrick
@ 2015-06-24 12:21   ` Christoph Hellwig
  2015-07-01  8:10   ` Stephen Bates
  1 sibling, 0 replies; 7+ messages in thread
From: Christoph Hellwig @ 2015-06-24 12:21 UTC (permalink / raw)


> +++ b/drivers/block/nvme-core.c
> @@ -102,12 +102,16 @@ struct nvme_queue {
>  	struct nvme_dev *dev;
>  	char irqname[24];	/* nvme4294967295-65535\0 */
>  	spinlock_t q_lock;
> -	struct nvme_command *sq_cmds;
> +	union {
> +		struct nvme_command *sq_cmds;
> +		struct nvme_command __iomem *sq_cmds_io;
> +	};
>  	volatile struct nvme_completion *cqes;
>  	struct blk_mq_tags **tags;
>  	dma_addr_t sq_dma_addr;
>  	dma_addr_t cq_dma_addr;
>  	u32 __iomem *q_db;
> +	bool cmb_mapped;

If you remove the union you'll get better error checking because
using the wrong member won't work, and you can remove the cmb_mapped
flag and instead check for a non-NULL sq_cmds_io.

Otherwise this looks reasonable to me.

Note that I have a WIP patch to make all command submissions go through
nvme_queue_rq, in which case we might be able to get rid of the on-stack
cmds again.  But until that happens I think the refactoring in the first
patch is preferable to the earlier version.

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

* [PATCHv2 2/2] NVMe: Use CMB for the SQ if available
  2015-06-23 22:33 ` [PATCHv2 2/2] NVMe: Use CMB for the SQ if available Jon Derrick
  2015-06-24 12:21   ` Christoph Hellwig
@ 2015-07-01  8:10   ` Stephen Bates
  2015-07-01 16:54     ` Jon Derrick
  1 sibling, 1 reply; 7+ messages in thread
From: Stephen Bates @ 2015-07-01  8:10 UTC (permalink / raw)


Hi Jon

Thanks for starting the work on this.

> +static void nvme_alloc_sq_cmds(struct nvme_dev *dev, struct
> nvme_queue *nvmeq,
> +				int qid, int depth)
> +{
> +	if (qid && NVME_CMB_SQS(dev->cmbsz) && dev->cmb) {
> +		unsigned offset = (qid - 1) *
> +					roundup(SQ_SIZE(depth), dev-
> >page_size);
> +		nvmeq->cmb_mapped = true;

This seems a little backwards to me in the sense that if the drive advertises CMB with SQ support the host is forced into using the CMB for SQs. Surely the host should have some ability to over-ride what the drive says? At the very least an argument into the  module to ignore CMB capabilities seems appropriate. Ultimately it would be good to have the host have the ability to use its preference when a device is reset. Or am I missing something?

Aside from this the patch looks good to me.

Stephen

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

* [PATCHv2 2/2] NVMe: Use CMB for the SQ if available
  2015-07-01  8:10   ` Stephen Bates
@ 2015-07-01 16:54     ` Jon Derrick
  2015-07-01 19:14       ` Stephen Bates
  0 siblings, 1 reply; 7+ messages in thread
From: Jon Derrick @ 2015-07-01 16:54 UTC (permalink / raw)


Hi Stephen,

Thanks for reviewing

> This seems a little backwards to me in the sense that if the drive advertises CMB with SQ support the host is forced into using the CMB for SQs. Surely the host should have some ability to over-ride what the drive says? At the very least an argument into the  module to ignore CMB capabilities seems appropriate.

That seems like a good idea to allow it to be disabled as a module param

>Ultimately it would be good to have the host have the ability to use its preference when a device is reset. Or am I missing something?

Would using a module param cover your concerns here?

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

* [PATCHv2 2/2] NVMe: Use CMB for the SQ if available
  2015-07-01 16:54     ` Jon Derrick
@ 2015-07-01 19:14       ` Stephen Bates
  0 siblings, 0 replies; 7+ messages in thread
From: Stephen Bates @ 2015-07-01 19:14 UTC (permalink / raw)


Jon

> > This seems a little backwards to me in the sense that if the drive advertises
> CMB with SQ support the host is forced into using the CMB for SQs. Surely
> the host should have some ability to over-ride what the drive says? At the
> very least an argument into the  module to ignore CMB capabilities seems
> appropriate.
> 
> That seems like a good idea to allow it to be disabled as a module param

Great.

> 
> >Ultimately it would be good to have the host have the ability to use its
> preference when a device is reset. Or am I missing something?
> 
> Would using a module param cover your concerns here?

I would find that acceptable to get the CMB support started and sufficient for your patchset. As we add support for other CMB areas I think we need something a bit more flexible for two reasons:

1. To allocate the CMB space up for SQs, CQ, WDS, RDS zones. The host should have a way of controlling how the CMB is split  up when we have support for more than one CMB  data type.

2. As noted in my earlier email we might want to change the allocation in a semi-dynamic fashion (via a device reset perhaps).

But I think we can add this functionality over time. Happy to hear what others think though.

Cheers

Stephen Bates

> -----Original Message-----
> From: Jon Derrick [mailto:jonathan.derrick at intel.com]
> Sent: Wednesday, July 1, 2015 5:55 PM
> To: Stephen Bates
> Cc: linux-nvme at lists.infradead.org; keith.busch at intel.com
> Subject: Re: [PATCHv2 2/2] NVMe: Use CMB for the SQ if available
> 
> Hi Stephen,
> 
> Thanks for reviewing
> 
> > This seems a little backwards to me in the sense that if the drive advertises
> CMB with SQ support the host is forced into using the CMB for SQs. Surely
> the host should have some ability to over-ride what the drive says? At the
> very least an argument into the  module to ignore CMB capabilities seems
> appropriate.
> 
> That seems like a good idea to allow it to be disabled as a module param
> 
> >Ultimately it would be good to have the host have the ability to use its
> preference when a device is reset. Or am I missing something?
> 
> Would using a module param cover your concerns here?

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

end of thread, other threads:[~2015-07-01 19:14 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-23 22:33 [PATCHv2 0/2] NVMe: Enable SQes on the CMB Jon Derrick
2015-06-23 22:33 ` [PATCHv2 1/2] NVMe: Unify SQ entry writing and doorbell ringing Jon Derrick
2015-06-23 22:33 ` [PATCHv2 2/2] NVMe: Use CMB for the SQ if available Jon Derrick
2015-06-24 12:21   ` Christoph Hellwig
2015-07-01  8:10   ` Stephen Bates
2015-07-01 16:54     ` Jon Derrick
2015-07-01 19:14       ` Stephen Bates

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.