Skip to content

Commit 9ac2253

Browse files
keithbuschkawasaki
authored andcommitted
nvme-pci: convert metadata mapping to dma iter
Aligns data and metadata to the similar dma mapping scheme and removes one more user of the scatter-gather dma mapping. Signed-off-by: Keith Busch <[email protected]>
1 parent b5be164 commit 9ac2253

1 file changed

Lines changed: 78 additions & 74 deletions

File tree

drivers/nvme/host/pci.c

Lines changed: 78 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,7 @@ struct nvme_dev {
172172
u32 last_ps;
173173
bool hmb;
174174
struct sg_table *hmb_sgt;
175-
176175
mempool_t *dmavec_mempool;
177-
mempool_t *iod_meta_mempool;
178176

179177
/* shadow doorbell buffer support: */
180178
__le32 *dbbuf_dbs;
@@ -264,6 +262,12 @@ enum nvme_iod_flags {
264262

265263
/* DMA mapped with PCI_P2PDMA_MAP_BUS_ADDR */
266264
IOD_P2P_BUS_ADDR = 1U << 3,
265+
266+
/* Metadata DMA mapped with PCI_P2PDMA_MAP_BUS_ADDR */
267+
IOD_META_P2P_BUS_ADDR = 1U << 4,
268+
269+
/* Metadata using non-coalesced MPTR */
270+
IOD_META_MPTR = 1U << 5,
267271
};
268272

269273
struct nvme_dma_vec {
@@ -281,13 +285,14 @@ struct nvme_iod {
281285
u8 nr_descriptors;
282286

283287
unsigned int total_len;
288+
unsigned int meta_total_len;
284289
struct dma_iova_state dma_state;
290+
struct dma_iova_state meta_dma_state;
285291
void *descriptors[NVME_MAX_NR_DESCRIPTORS];
286292
struct nvme_dma_vec *dma_vecs;
287293
unsigned int nr_dma_vecs;
288294

289295
dma_addr_t meta_dma;
290-
struct sg_table meta_sgt;
291296
struct nvme_sgl_desc *meta_descriptor;
292297
};
293298

@@ -644,6 +649,11 @@ static inline struct dma_pool *nvme_dma_pool(struct nvme_queue *nvmeq,
644649
return nvmeq->descriptor_pools.large;
645650
}
646651

652+
static inline bool nvme_pci_cmd_use_meta_sgl(struct nvme_command *cmd)
653+
{
654+
return (cmd->common.flags & NVME_CMD_SGL_ALL) == NVME_CMD_SGL_METASEG;
655+
}
656+
647657
static inline bool nvme_pci_cmd_use_sgl(struct nvme_command *cmd)
648658
{
649659
return cmd->common.flags &
@@ -1023,70 +1033,96 @@ static blk_status_t nvme_map_data(struct request *req)
10231033
return nvme_pci_setup_data_prp(req, &iter);
10241034
}
10251035

1026-
static void nvme_pci_sgl_set_data_sg(struct nvme_sgl_desc *sge,
1027-
struct scatterlist *sg)
1036+
static void nvme_free_meta_sgls(struct nvme_iod *iod, struct device *dma_dev,
1037+
enum dma_data_direction dir)
10281038
{
1029-
sge->addr = cpu_to_le64(sg_dma_address(sg));
1030-
sge->length = cpu_to_le32(sg_dma_len(sg));
1031-
sge->type = NVME_SGL_FMT_DATA_DESC << 4;
1039+
struct nvme_sgl_desc *sge = iod->meta_descriptor;
1040+
1041+
__nvme_free_sgls(dma_dev, sge, &sge[1], dir);
1042+
}
1043+
1044+
static void nvme_unmap_metadata(struct request *req)
1045+
{
1046+
struct nvme_queue *nvmeq = req->mq_hctx->driver_data;
1047+
enum dma_data_direction dir = rq_dma_dir(req);
1048+
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
1049+
struct device *dma_dev = nvmeq->dev->dev;
1050+
1051+
if (iod->flags & IOD_META_MPTR) {
1052+
dma_unmap_page(dma_dev, iod->meta_dma,
1053+
rq_integrity_vec(req).bv_len,
1054+
rq_dma_dir(req));
1055+
return;
1056+
}
1057+
1058+
if (!blk_rq_dma_unmap(req, dma_dev, &iod->meta_dma_state,
1059+
iod->meta_total_len,
1060+
iod->flags & IOD_META_P2P_BUS_ADDR)) {
1061+
if (nvme_pci_cmd_use_meta_sgl(&iod->cmd))
1062+
nvme_free_meta_sgls(iod, dma_dev, dir);
1063+
else
1064+
dma_unmap_page(dma_dev, iod->meta_dma,
1065+
iod->meta_total_len, dir);
1066+
}
1067+
1068+
if (iod->meta_descriptor)
1069+
dma_pool_free(nvmeq->descriptor_pools.small,
1070+
iod->meta_descriptor, iod->meta_dma);
10321071
}
10331072

10341073
static blk_status_t nvme_pci_setup_meta_sgls(struct request *req)
10351074
{
10361075
struct nvme_queue *nvmeq = req->mq_hctx->driver_data;
1037-
struct nvme_dev *dev = nvmeq->dev;
1076+
unsigned int entries = req->nr_integrity_segments;
10381077
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
1078+
struct nvme_dev *dev = nvmeq->dev;
10391079
struct nvme_sgl_desc *sg_list;
1040-
struct scatterlist *sgl, *sg;
1041-
unsigned int entries;
1080+
struct blk_dma_iter iter;
10421081
dma_addr_t sgl_dma;
1043-
int rc, i;
1044-
1045-
iod->meta_sgt.sgl = mempool_alloc(dev->iod_meta_mempool, GFP_ATOMIC);
1046-
if (!iod->meta_sgt.sgl)
1047-
return BLK_STS_RESOURCE;
1082+
int i = 0;
10481083

1049-
sg_init_table(iod->meta_sgt.sgl, req->nr_integrity_segments);
1050-
iod->meta_sgt.orig_nents = blk_rq_map_integrity_sg(req,
1051-
iod->meta_sgt.sgl);
1052-
if (!iod->meta_sgt.orig_nents)
1053-
goto out_free_sg;
1084+
if (!blk_rq_integrity_dma_map_iter_start(req, dev->dev,
1085+
&iod->meta_dma_state, &iter))
1086+
return iter.status;
10541087

1055-
rc = dma_map_sgtable(dev->dev, &iod->meta_sgt, rq_dma_dir(req),
1056-
DMA_ATTR_NO_WARN);
1057-
if (rc)
1058-
goto out_free_sg;
1088+
if (iter.p2pdma.map == PCI_P2PDMA_MAP_BUS_ADDR)
1089+
iod->flags |= IOD_META_P2P_BUS_ADDR;
1090+
else if (blk_rq_dma_map_coalesce(&iod->meta_dma_state))
1091+
entries = 1;
1092+
1093+
if (entries == 1 && !(nvme_req(req)->flags & NVME_REQ_USERCMD)) {
1094+
iod->cmd.common.metadata = cpu_to_le64(iter.addr);
1095+
iod->meta_total_len = iter.len;
1096+
iod->meta_dma = iter.addr;
1097+
iod->meta_descriptor = NULL;
1098+
return BLK_STS_OK;
1099+
}
10591100

10601101
sg_list = dma_pool_alloc(nvmeq->descriptor_pools.small, GFP_ATOMIC,
10611102
&sgl_dma);
10621103
if (!sg_list)
1063-
goto out_unmap_sg;
1104+
return BLK_STS_RESOURCE;
10641105

1065-
entries = iod->meta_sgt.nents;
10661106
iod->meta_descriptor = sg_list;
10671107
iod->meta_dma = sgl_dma;
1068-
10691108
iod->cmd.common.flags = NVME_CMD_SGL_METASEG;
10701109
iod->cmd.common.metadata = cpu_to_le64(sgl_dma);
1071-
1072-
sgl = iod->meta_sgt.sgl;
10731110
if (entries == 1) {
1074-
nvme_pci_sgl_set_data_sg(sg_list, sgl);
1111+
iod->meta_total_len = iter.len;
1112+
nvme_pci_sgl_set_data(sg_list, &iter);
10751113
return BLK_STS_OK;
10761114
}
10771115

10781116
sgl_dma += sizeof(*sg_list);
1079-
nvme_pci_sgl_set_seg(sg_list, sgl_dma, entries);
1080-
for_each_sg(sgl, sg, entries, i)
1081-
nvme_pci_sgl_set_data_sg(&sg_list[i + 1], sg);
1082-
1083-
return BLK_STS_OK;
1117+
do {
1118+
nvme_pci_sgl_set_data(&sg_list[++i], &iter);
1119+
iod->meta_total_len += iter.len;
1120+
} while (blk_rq_integrity_dma_map_iter_next(req, dev->dev, &iter));
10841121

1085-
out_unmap_sg:
1086-
dma_unmap_sgtable(dev->dev, &iod->meta_sgt, rq_dma_dir(req), 0);
1087-
out_free_sg:
1088-
mempool_free(iod->meta_sgt.sgl, dev->iod_meta_mempool);
1089-
return BLK_STS_RESOURCE;
1122+
nvme_pci_sgl_set_seg(sg_list, sgl_dma, i);
1123+
if (unlikely(iter.status))
1124+
nvme_unmap_metadata(req);
1125+
return iter.status;
10901126
}
10911127

10921128
static blk_status_t nvme_pci_setup_meta_mptr(struct request *req)
@@ -1099,6 +1135,7 @@ static blk_status_t nvme_pci_setup_meta_mptr(struct request *req)
10991135
if (dma_mapping_error(nvmeq->dev->dev, iod->meta_dma))
11001136
return BLK_STS_IOERR;
11011137
iod->cmd.common.metadata = cpu_to_le64(iod->meta_dma);
1138+
iod->flags |= IOD_META_MPTR;
11021139
return BLK_STS_OK;
11031140
}
11041141

@@ -1120,7 +1157,6 @@ static blk_status_t nvme_prep_rq(struct request *req)
11201157
iod->flags = 0;
11211158
iod->nr_descriptors = 0;
11221159
iod->total_len = 0;
1123-
iod->meta_sgt.nents = 0;
11241160

11251161
ret = nvme_setup_cmd(req->q->queuedata, req);
11261162
if (ret)
@@ -1231,25 +1267,6 @@ static void nvme_queue_rqs(struct rq_list *rqlist)
12311267
*rqlist = requeue_list;
12321268
}
12331269

1234-
static __always_inline void nvme_unmap_metadata(struct request *req)
1235-
{
1236-
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
1237-
struct nvme_queue *nvmeq = req->mq_hctx->driver_data;
1238-
struct nvme_dev *dev = nvmeq->dev;
1239-
1240-
if (!iod->meta_sgt.nents) {
1241-
dma_unmap_page(dev->dev, iod->meta_dma,
1242-
rq_integrity_vec(req).bv_len,
1243-
rq_dma_dir(req));
1244-
return;
1245-
}
1246-
1247-
dma_pool_free(nvmeq->descriptor_pools.small, iod->meta_descriptor,
1248-
iod->meta_dma);
1249-
dma_unmap_sgtable(dev->dev, &iod->meta_sgt, rq_dma_dir(req), 0);
1250-
mempool_free(iod->meta_sgt.sgl, dev->iod_meta_mempool);
1251-
}
1252-
12531270
static __always_inline void nvme_pci_unmap_rq(struct request *req)
12541271
{
12551272
if (blk_integrity_rq(req))
@@ -3055,7 +3072,6 @@ static int nvme_disable_prepare_reset(struct nvme_dev *dev, bool shutdown)
30553072

30563073
static int nvme_pci_alloc_iod_mempool(struct nvme_dev *dev)
30573074
{
3058-
size_t meta_size = sizeof(struct scatterlist) * (NVME_MAX_META_SEGS + 1);
30593075
size_t alloc_size = sizeof(struct nvme_dma_vec) * NVME_MAX_SEGS;
30603076

30613077
dev->dmavec_mempool = mempool_create_node(1,
@@ -3064,17 +3080,7 @@ static int nvme_pci_alloc_iod_mempool(struct nvme_dev *dev)
30643080
dev_to_node(dev->dev));
30653081
if (!dev->dmavec_mempool)
30663082
return -ENOMEM;
3067-
3068-
dev->iod_meta_mempool = mempool_create_node(1,
3069-
mempool_kmalloc, mempool_kfree,
3070-
(void *)meta_size, GFP_KERNEL,
3071-
dev_to_node(dev->dev));
3072-
if (!dev->iod_meta_mempool)
3073-
goto free;
30743083
return 0;
3075-
free:
3076-
mempool_destroy(dev->dmavec_mempool);
3077-
return -ENOMEM;
30783084
}
30793085

30803086
static void nvme_free_tagset(struct nvme_dev *dev)
@@ -3524,7 +3530,6 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
35243530
nvme_free_queues(dev, 0);
35253531
out_release_iod_mempool:
35263532
mempool_destroy(dev->dmavec_mempool);
3527-
mempool_destroy(dev->iod_meta_mempool);
35283533
out_dev_unmap:
35293534
nvme_dev_unmap(dev);
35303535
out_uninit_ctrl:
@@ -3588,7 +3593,6 @@ static void nvme_remove(struct pci_dev *pdev)
35883593
nvme_dbbuf_dma_free(dev);
35893594
nvme_free_queues(dev, 0);
35903595
mempool_destroy(dev->dmavec_mempool);
3591-
mempool_destroy(dev->iod_meta_mempool);
35923596
nvme_release_descriptor_pools(dev);
35933597
nvme_dev_unmap(dev);
35943598
nvme_uninit_ctrl(&dev->ctrl);

0 commit comments

Comments
 (0)