Skip to content

Commit ea7789c

Browse files
damien-lemoalkeithbusch
authored andcommitted
nvmet: pci-epf: Keep completion queues mapped
Instead of mapping and unmapping the completion queues memory to the host PCI address space whenever nvmet_pci_epf_cq_work() is called, map a completion queue to the host PCI address space when the completion queue is created with nvmet_pci_epf_create_cq() and unmap it when the completion queue is deleted with nvmet_pci_epf_delete_cq(). This removes the completion queue mapping/unmapping from nvmet_pci_epf_cq_work() and significantly increases performance. For a single job 4K random read QD=1 workload, the IOPS is increased from 23 KIOPS to 25 KIOPS. Some significant throughput increasde for high queue depth and large IOs workloads can also be seen. Since the functions nvmet_pci_epf_map_queue() and nvmet_pci_epf_unmap_queue() are called respectively only from nvmet_pci_epf_create_cq() and nvmet_pci_epf_delete_cq(), these functions are removed and open-coded in their respective call sites. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Keith Busch <kbusch@kernel.org>
1 parent e3e6831 commit ea7789c

File tree

1 file changed

+25
-38
lines changed

1 file changed

+25
-38
lines changed

drivers/nvme/target/pci-epf.c

Lines changed: 25 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,6 +1264,7 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl,
12641264
struct nvmet_pci_epf_ctrl *ctrl = tctrl->drvdata;
12651265
struct nvmet_pci_epf_queue *cq = &ctrl->cq[cqid];
12661266
u16 status;
1267+
int ret;
12671268

12681269
if (test_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags))
12691270
return NVME_SC_QID_INVALID | NVME_STATUS_DNR;
@@ -1298,13 +1299,35 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl,
12981299
if (status != NVME_SC_SUCCESS)
12991300
goto err;
13001301

1302+
/*
1303+
* Map the CQ PCI address space and since PCI endpoint controllers may
1304+
* return a partial mapping, check that the mapping is large enough.
1305+
*/
1306+
ret = nvmet_pci_epf_mem_map(ctrl->nvme_epf, cq->pci_addr, cq->pci_size,
1307+
&cq->pci_map);
1308+
if (ret) {
1309+
dev_err(ctrl->dev, "Failed to map CQ %u (err=%d)\n",
1310+
cq->qid, ret);
1311+
goto err_internal;
1312+
}
1313+
1314+
if (cq->pci_map.pci_size < cq->pci_size) {
1315+
dev_err(ctrl->dev, "Invalid partial mapping of queue %u\n",
1316+
cq->qid);
1317+
goto err_unmap_queue;
1318+
}
1319+
13011320
set_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags);
13021321

13031322
dev_dbg(ctrl->dev, "CQ[%u]: %u entries of %zu B, IRQ vector %u\n",
13041323
cqid, qsize, cq->qes, cq->vector);
13051324

13061325
return NVME_SC_SUCCESS;
13071326

1327+
err_unmap_queue:
1328+
nvmet_pci_epf_mem_unmap(ctrl->nvme_epf, &cq->pci_map);
1329+
err_internal:
1330+
status = NVME_SC_INTERNAL | NVME_STATUS_DNR;
13081331
err:
13091332
if (test_and_clear_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags))
13101333
nvmet_pci_epf_remove_irq_vector(ctrl, cq->vector);
@@ -1322,6 +1345,7 @@ static u16 nvmet_pci_epf_delete_cq(struct nvmet_ctrl *tctrl, u16 cqid)
13221345
cancel_delayed_work_sync(&cq->work);
13231346
nvmet_pci_epf_drain_queue(cq);
13241347
nvmet_pci_epf_remove_irq_vector(ctrl, cq->vector);
1348+
nvmet_pci_epf_mem_unmap(ctrl->nvme_epf, &cq->pci_map);
13251349

13261350
return NVME_SC_SUCCESS;
13271351
}
@@ -1553,36 +1577,6 @@ static void nvmet_pci_epf_free_queues(struct nvmet_pci_epf_ctrl *ctrl)
15531577
ctrl->cq = NULL;
15541578
}
15551579

1556-
static int nvmet_pci_epf_map_queue(struct nvmet_pci_epf_ctrl *ctrl,
1557-
struct nvmet_pci_epf_queue *queue)
1558-
{
1559-
struct nvmet_pci_epf *nvme_epf = ctrl->nvme_epf;
1560-
int ret;
1561-
1562-
ret = nvmet_pci_epf_mem_map(nvme_epf, queue->pci_addr,
1563-
queue->pci_size, &queue->pci_map);
1564-
if (ret) {
1565-
dev_err(ctrl->dev, "Failed to map queue %u (err=%d)\n",
1566-
queue->qid, ret);
1567-
return ret;
1568-
}
1569-
1570-
if (queue->pci_map.pci_size < queue->pci_size) {
1571-
dev_err(ctrl->dev, "Invalid partial mapping of queue %u\n",
1572-
queue->qid);
1573-
nvmet_pci_epf_mem_unmap(nvme_epf, &queue->pci_map);
1574-
return -ENOMEM;
1575-
}
1576-
1577-
return 0;
1578-
}
1579-
1580-
static inline void nvmet_pci_epf_unmap_queue(struct nvmet_pci_epf_ctrl *ctrl,
1581-
struct nvmet_pci_epf_queue *queue)
1582-
{
1583-
nvmet_pci_epf_mem_unmap(ctrl->nvme_epf, &queue->pci_map);
1584-
}
1585-
15861580
static void nvmet_pci_epf_exec_iod_work(struct work_struct *work)
15871581
{
15881582
struct nvmet_pci_epf_iod *iod =
@@ -1746,11 +1740,7 @@ static void nvmet_pci_epf_cq_work(struct work_struct *work)
17461740
struct nvme_completion *cqe;
17471741
struct nvmet_pci_epf_iod *iod;
17481742
unsigned long flags;
1749-
int ret, n = 0;
1750-
1751-
ret = nvmet_pci_epf_map_queue(ctrl, cq);
1752-
if (ret)
1753-
goto again;
1743+
int ret = 0, n = 0;
17541744

17551745
while (test_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags) && ctrl->link_up) {
17561746

@@ -1797,8 +1787,6 @@ static void nvmet_pci_epf_cq_work(struct work_struct *work)
17971787
n++;
17981788
}
17991789

1800-
nvmet_pci_epf_unmap_queue(ctrl, cq);
1801-
18021790
/*
18031791
* We do not support precise IRQ coalescing time (100ns units as per
18041792
* NVMe specifications). So if we have posted completion entries without
@@ -1807,7 +1795,6 @@ static void nvmet_pci_epf_cq_work(struct work_struct *work)
18071795
if (n)
18081796
nvmet_pci_epf_raise_irq(ctrl, cq, true);
18091797

1810-
again:
18111798
if (ret < 0)
18121799
queue_delayed_work(system_highpri_wq, &cq->work,
18131800
NVMET_PCI_EPF_CQ_RETRY_INTERVAL);

0 commit comments

Comments
 (0)