From: scott.bauer@intel.com (Scott Bauer)
Subject: [RCF PATCH 2/2] nvme-pci: Bounce data from Host memory to CMB Memory
Date: Thu, 19 Jul 2018 17:06:28 -0600 [thread overview]
Message-ID: <20180719230628.31494-3-scott.bauer@intel.com> (raw)
In-Reply-To: <20180719230628.31494-1-scott.bauer@intel.com>
Signed-off-by: Scott Bauer <scott.bauer at intel.com>
---
drivers/nvme/host/pci.c | 91 ++++++++++++++++++++++++++++++++++++++---
1 file changed, 85 insertions(+), 6 deletions(-)
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index b8c81be4a985..2f1dd7e582ac 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -53,6 +53,10 @@ static bool use_cmb_sqes = true;
module_param(use_cmb_sqes, bool, 0444);
MODULE_PARM_DESC(use_cmb_sqes, "use controller's memory buffer for I/O SQes");
+static bool use_cmb_wds = false;
+module_param(use_cmb_wds, bool, 0444);
+MODULE_PARM_DESC(use_cmb_wds, "use controller's memory buffer for I/O data");
+
static unsigned int max_host_mem_size_mb = 128;
module_param(max_host_mem_size_mb, uint, 0444);
MODULE_PARM_DESC(max_host_mem_size_mb,
@@ -193,6 +197,7 @@ struct nvme_iod {
int npages; /* In the PRP list. 0 means small pool in use */
int nents; /* Used in scatterlist */
int length; /* Of data, in bytes */
+ int cmb_data; /* Data was copied into CMB for WDS */
dma_addr_t first_dma;
struct scatterlist meta_sg; /* metadata requires single contiguous buffer */
struct scatterlist *sg;
@@ -504,6 +509,30 @@ static blk_status_t nvme_init_iod(struct request *rq, struct nvme_dev *dev)
return BLK_STS_OK;
}
+static void nvme_unmap_sg_cmb(struct nvme_dev *dev, struct nvme_iod *iod,
+ int num_mapped)
+{
+ struct scatterlist *s;
+ int j;
+
+ for_each_sg(iod->sg, s, iod->nents, j) {
+ if (j == num_mapped)
+ break;
+ gen_pool_free(dev->cmb_pool, s->page_link, s->length);
+ s->dma_address = 0;
+ s->page_link = 0;
+ sg_dma_len(s) = 0;
+ }
+ iod->cmb_data = 0;
+}
+
+static void nvme_clean_cmb_iod(struct nvme_dev *dev, struct nvme_iod *iod)
+{
+ if (iod->cmb_data)
+ nvme_unmap_sg_cmb(dev, iod, iod->nents);
+ return;
+}
+
static void nvme_free_iod(struct nvme_dev *dev, struct request *req)
{
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
@@ -534,8 +563,10 @@ static void nvme_free_iod(struct nvme_dev *dev, struct request *req)
dma_addr = next_dma_addr;
}
- if (iod->sg != iod->inline_sg)
+ if (iod->sg != iod->inline_sg) {
+ nvme_clean_cmb_iod(dev, iod);
mempool_free(iod->sg, dev->iod_mempool);
+ }
}
#ifdef CONFIG_BLK_DEV_INTEGRITY
@@ -641,6 +672,12 @@ static blk_status_t nvme_pci_setup_prps(struct nvme_dev *dev,
goto done;
}
+ if (iod->cmb_data)
+ dma_addr = gen_pool_virt_to_phys(dev->cmb_pool,
+ sg_dma_address(sg));
+ else
+ dma_addr = sg_dma_address(sg);
+
dma_len -= (page_size - offset);
if (dma_len) {
dma_addr += (page_size - offset);
@@ -792,8 +829,37 @@ static blk_status_t nvme_pci_setup_sgls(struct nvme_dev *dev,
return BLK_STS_OK;
}
+static int nvme_copy_to_cmb(struct nvme_dev *dev, struct nvme_iod *iod)
+{
+ struct scatterlist *s;
+ void *data_cmb;
+ int i;
+
+ iod->cmb_data = 1;
+ for_each_sg(iod->sg, s, iod->nents, i) {
+ data_cmb = (void *) gen_pool_alloc(dev->cmb_pool, s->length);
+ if (!data_cmb) {
+ pr_err("%s: failed to alloc from pool\n", __func__);
+ goto unwind;
+ }
+
+ memcpy_toio(data_cmb, page_address(sg_page(s)), s->length);
+
+ s->dma_address = gen_pool_virt_to_phys(dev->cmb_pool,
+ (unsigned long) data_cmb);
+ sg_dma_len(s) = s->length;
+ /* We do not need the sg_page page link anymore so we'll steal it. */
+ s->page_link = (unsigned long) data_cmb;
+ }
+ return i;
+
+ unwind:
+ nvme_unmap_sg_cmb(dev, iod, i);
+ return 0;
+}
+
static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req,
- struct nvme_command *cmnd)
+ struct nvme_command *cmnd)
{
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
struct request_queue *q = req->q;
@@ -808,8 +874,15 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req,
goto out;
ret = BLK_STS_RESOURCE;
- nr_mapped = dma_map_sg_attrs(dev->dev, iod->sg, iod->nents, dma_dir,
- DMA_ATTR_NO_WARN);
+
+ if (dma_dir == DMA_TO_DEVICE && use_cmb_wds
+ && dev->cmb_pool && dev->cmbsz & NVME_CMBSZ_WDS &&
+ iod->nvmeq->qid)
+ nr_mapped = nvme_copy_to_cmb(dev, iod);
+ else
+ nr_mapped = dma_map_sg_attrs(dev->dev, iod->sg, iod->nents,
+ dma_dir, DMA_ATTR_NO_WARN);
+
if (!nr_mapped)
goto out;
@@ -842,7 +915,10 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req,
return BLK_STS_OK;
out_unmap:
- dma_unmap_sg(dev->dev, iod->sg, iod->nents, dma_dir);
+ if (iod->cmb_data)
+ nvme_unmap_sg_cmb(dev, iod, iod->nents);
+ else
+ dma_unmap_sg(dev->dev, iod->sg, iod->nents, dma_dir);
out:
return ret;
}
@@ -853,7 +929,7 @@ static void nvme_unmap_data(struct nvme_dev *dev, struct request *req)
enum dma_data_direction dma_dir = rq_data_dir(req) ?
DMA_TO_DEVICE : DMA_FROM_DEVICE;
- if (iod->nents) {
+ if (iod->nents && !iod->cmb_data) {
dma_unmap_sg(dev->dev, iod->sg, iod->nents, dma_dir);
if (blk_integrity_rq(req)) {
if (req_op(req) == REQ_OP_READ)
@@ -1210,6 +1286,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved)
*/
if (nvme_should_reset(dev, csts)) {
nvme_warn_reset(dev, csts);
+ nvme_clean_cmb_iod(dev, iod);
nvme_dev_disable(dev, false);
nvme_reset_ctrl(&dev->ctrl);
return BLK_EH_DONE;
@@ -1237,6 +1314,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved)
dev_warn_ratelimited(dev->ctrl.device,
"I/O %d QID %d timeout, disable controller\n",
req->tag, nvmeq->qid);
+ nvme_clean_cmb_iod(dev, iod);
nvme_dev_disable(dev, false);
nvme_req(req)->flags |= NVME_REQ_CANCELLED;
return BLK_EH_DONE;
@@ -1253,6 +1331,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved)
dev_warn(dev->ctrl.device,
"I/O %d QID %d timeout, reset controller\n",
req->tag, nvmeq->qid);
+ nvme_clean_cmb_iod(dev, iod);
nvme_dev_disable(dev, false);
nvme_reset_ctrl(&dev->ctrl);
--
2.17.1
next prev parent reply other threads:[~2018-07-19 23:06 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-07-19 23:06 [RFC PATCH 0/2] Re-work CMB and add WDS support Scott Bauer
2018-07-19 23:06 ` [RCF PATCH 1/2] nvme: pci: Move CMB allocation into a pool Scott Bauer
2018-07-20 14:49 ` Christoph Hellwig
2018-07-19 23:06 ` Scott Bauer [this message]
2018-07-20 14:23 ` [RCF PATCH 2/2] nvme-pci: Bounce data from Host memory to CMB Memory Keith Busch
2018-07-20 14:49 ` Christoph Hellwig
2018-07-20 14:53 ` Scott Bauer
2018-07-20 14:46 ` [RFC PATCH 0/2] Re-work CMB and add WDS support Christoph Hellwig
2018-07-20 14:50 ` Scott Bauer
2018-07-20 16:01 ` Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180719230628.31494-3-scott.bauer@intel.com \
--to=scott.bauer@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.