Skip to content

Commit 5b41315

Browse files
keithbuschkawasaki
authored andcommitted
nvme: 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 c7c4005 commit 5b41315

1 file changed

Lines changed: 62 additions & 64 deletions

File tree

drivers/nvme/host/pci.c

Lines changed: 62 additions & 64 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,9 @@ 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,
267268
};
268269

269270
struct nvme_dma_vec {
@@ -279,15 +280,17 @@ struct nvme_iod {
279280
struct nvme_command cmd;
280281
u8 flags;
281282
u8 nr_descriptors;
283+
u8 nr_meta_descriptors;
282284

283285
unsigned int total_len;
286+
unsigned int meta_total_len;
284287
struct dma_iova_state dma_state;
288+
struct dma_iova_state meta_dma_state;
285289
void *descriptors[NVME_MAX_NR_DESCRIPTORS];
286290
struct nvme_dma_vec *dma_vecs;
287291
unsigned int nr_dma_vecs;
288292

289293
dma_addr_t meta_dma;
290-
struct sg_table meta_sgt;
291294
struct nvme_sgl_desc *meta_descriptor;
292295
};
293296

@@ -644,6 +647,11 @@ static inline struct dma_pool *nvme_dma_pool(struct nvme_queue *nvmeq,
644647
return nvmeq->descriptor_pools.large;
645648
}
646649

650+
static inline bool nvme_pci_cmd_use_meta_sgl(struct nvme_command *cmd)
651+
{
652+
return (cmd->common.flags & NVME_CMD_SGL_ALL) == NVME_CMD_SGL_METASEG;
653+
}
654+
647655
static inline bool nvme_pci_cmd_use_sgl(struct nvme_command *cmd)
648656
{
649657
return cmd->common.flags &
@@ -1014,70 +1022,53 @@ static blk_status_t nvme_map_data(struct request *req)
10141022
return nvme_pci_setup_data_prp(req, &iter);
10151023
}
10161024

1017-
static void nvme_pci_sgl_set_data_sg(struct nvme_sgl_desc *sge,
1018-
struct scatterlist *sg)
1019-
{
1020-
sge->addr = cpu_to_le64(sg_dma_address(sg));
1021-
sge->length = cpu_to_le32(sg_dma_len(sg));
1022-
sge->type = NVME_SGL_FMT_DATA_DESC << 4;
1023-
}
1024-
10251025
static blk_status_t nvme_pci_setup_meta_sgls(struct request *req)
10261026
{
10271027
struct nvme_queue *nvmeq = req->mq_hctx->driver_data;
1028-
struct nvme_dev *dev = nvmeq->dev;
1028+
unsigned int entries = req->nr_integrity_segments;
10291029
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
1030+
struct nvme_dev *dev = nvmeq->dev;
10301031
struct nvme_sgl_desc *sg_list;
1031-
struct scatterlist *sgl, *sg;
1032-
unsigned int entries;
1032+
struct blk_dma_iter iter;
10331033
dma_addr_t sgl_dma;
1034-
int rc, i;
1035-
1036-
iod->meta_sgt.sgl = mempool_alloc(dev->iod_meta_mempool, GFP_ATOMIC);
1037-
if (!iod->meta_sgt.sgl)
1038-
return BLK_STS_RESOURCE;
1034+
int i = 0;
10391035

1040-
sg_init_table(iod->meta_sgt.sgl, req->nr_integrity_segments);
1041-
iod->meta_sgt.orig_nents = blk_rq_map_integrity_sg(req,
1042-
iod->meta_sgt.sgl);
1043-
if (!iod->meta_sgt.orig_nents)
1044-
goto out_free_sg;
1036+
if (!blk_rq_integrity_dma_map_iter_start(req, dev->dev,
1037+
&iod->meta_dma_state, &iter))
1038+
return iter.status;
10451039

1046-
rc = dma_map_sgtable(dev->dev, &iod->meta_sgt, rq_dma_dir(req),
1047-
DMA_ATTR_NO_WARN);
1048-
if (rc)
1049-
goto out_free_sg;
1040+
if (iter.p2pdma.map == PCI_P2PDMA_MAP_BUS_ADDR)
1041+
iod->flags |= IOD_META_P2P_BUS_ADDR;
1042+
else if (blk_rq_dma_map_coalesce(&iod->meta_dma_state))
1043+
entries = 1;
10501044

10511045
sg_list = dma_pool_alloc(nvmeq->descriptor_pools.small, GFP_ATOMIC,
10521046
&sgl_dma);
10531047
if (!sg_list)
1054-
goto out_unmap_sg;
1048+
return BLK_STS_RESOURCE;
10551049

1056-
entries = iod->meta_sgt.nents;
10571050
iod->meta_descriptor = sg_list;
10581051
iod->meta_dma = sgl_dma;
10591052

10601053
iod->cmd.common.flags = NVME_CMD_SGL_METASEG;
10611054
iod->cmd.common.metadata = cpu_to_le64(sgl_dma);
10621055

1063-
sgl = iod->meta_sgt.sgl;
10641056
if (entries == 1) {
1065-
nvme_pci_sgl_set_data_sg(sg_list, sgl);
1057+
iod->meta_total_len = iter.len;
1058+
nvme_pci_sgl_set_data(sg_list, &iter);
1059+
iod->nr_meta_descriptors = 0;
10661060
return BLK_STS_OK;
10671061
}
10681062

10691063
sgl_dma += sizeof(*sg_list);
1070-
nvme_pci_sgl_set_seg(sg_list, sgl_dma, entries);
1071-
for_each_sg(sgl, sg, entries, i)
1072-
nvme_pci_sgl_set_data_sg(&sg_list[i + 1], sg);
1073-
1074-
return BLK_STS_OK;
1064+
do {
1065+
nvme_pci_sgl_set_data(&sg_list[++i], &iter);
1066+
iod->meta_total_len += iter.len;
1067+
} while (blk_rq_integrity_dma_map_iter_next(req, dev->dev, &iter));
10751068

1076-
out_unmap_sg:
1077-
dma_unmap_sgtable(dev->dev, &iod->meta_sgt, rq_dma_dir(req), 0);
1078-
out_free_sg:
1079-
mempool_free(iod->meta_sgt.sgl, dev->iod_meta_mempool);
1080-
return BLK_STS_RESOURCE;
1069+
nvme_pci_sgl_set_seg(sg_list, sgl_dma, i);
1070+
iod->nr_meta_descriptors = i;
1071+
return iter.status;
10811072
}
10821073

10831074
static blk_status_t nvme_pci_setup_meta_mptr(struct request *req)
@@ -1090,6 +1081,7 @@ static blk_status_t nvme_pci_setup_meta_mptr(struct request *req)
10901081
if (dma_mapping_error(nvmeq->dev->dev, iod->meta_dma))
10911082
return BLK_STS_IOERR;
10921083
iod->cmd.common.metadata = cpu_to_le64(iod->meta_dma);
1084+
iod->nr_meta_descriptors = 0;
10931085
return BLK_STS_OK;
10941086
}
10951087

@@ -1111,7 +1103,6 @@ static blk_status_t nvme_prep_rq(struct request *req)
11111103
iod->flags = 0;
11121104
iod->nr_descriptors = 0;
11131105
iod->total_len = 0;
1114-
iod->meta_sgt.nents = 0;
11151106

11161107
ret = nvme_setup_cmd(req->q->queuedata, req);
11171108
if (ret)
@@ -1222,23 +1213,43 @@ static void nvme_queue_rqs(struct rq_list *rqlist)
12221213
*rqlist = requeue_list;
12231214
}
12241215

1216+
static void nvme_free_meta_sgls(struct nvme_iod *iod, struct device *dma_dev,
1217+
enum dma_data_direction dir)
1218+
{
1219+
struct nvme_sgl_desc *sg_list = iod->meta_descriptor;
1220+
int i;
1221+
1222+
if (!iod->nr_meta_descriptors) {
1223+
dma_unmap_page(dma_dev, le64_to_cpu(sg_list->addr),
1224+
le32_to_cpu(sg_list->length), dir);
1225+
return;
1226+
}
1227+
1228+
for (i = 1; i <= iod->nr_meta_descriptors; i++)
1229+
dma_unmap_page(dma_dev, le64_to_cpu(sg_list[i].addr),
1230+
le32_to_cpu(sg_list[i].length), dir);
1231+
}
1232+
12251233
static __always_inline void nvme_unmap_metadata(struct request *req)
12261234
{
1227-
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
12281235
struct nvme_queue *nvmeq = req->mq_hctx->driver_data;
1229-
struct nvme_dev *dev = nvmeq->dev;
1236+
enum dma_data_direction dir = rq_dma_dir(req);
1237+
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
1238+
struct device *dma_dev = nvmeq->dev->dev;
12301239

1231-
if (!iod->meta_sgt.nents) {
1232-
dma_unmap_page(dev->dev, iod->meta_dma,
1233-
rq_integrity_vec(req).bv_len,
1234-
rq_dma_dir(req));
1240+
if (!nvme_pci_cmd_use_meta_sgl(&iod->cmd)) {
1241+
dma_unmap_page(dma_dev, iod->meta_dma,
1242+
rq_integrity_vec(req).bv_len, dir);
12351243
return;
12361244
}
12371245

1246+
if (!blk_rq_dma_unmap(req, dma_dev, &iod->meta_dma_state,
1247+
iod->meta_total_len,
1248+
iod->flags & IOD_META_P2P_BUS_ADDR))
1249+
nvme_free_meta_sgls(iod, dma_dev, dir);
1250+
12381251
dma_pool_free(nvmeq->descriptor_pools.small, iod->meta_descriptor,
12391252
iod->meta_dma);
1240-
dma_unmap_sgtable(dev->dev, &iod->meta_sgt, rq_dma_dir(req), 0);
1241-
mempool_free(iod->meta_sgt.sgl, dev->iod_meta_mempool);
12421253
}
12431254

12441255
static __always_inline void nvme_pci_unmap_rq(struct request *req)
@@ -3046,7 +3057,6 @@ static int nvme_disable_prepare_reset(struct nvme_dev *dev, bool shutdown)
30463057

30473058
static int nvme_pci_alloc_iod_mempool(struct nvme_dev *dev)
30483059
{
3049-
size_t meta_size = sizeof(struct scatterlist) * (NVME_MAX_META_SEGS + 1);
30503060
size_t alloc_size = sizeof(struct nvme_dma_vec) * NVME_MAX_SEGS;
30513061

30523062
dev->dmavec_mempool = mempool_create_node(1,
@@ -3055,17 +3065,7 @@ static int nvme_pci_alloc_iod_mempool(struct nvme_dev *dev)
30553065
dev_to_node(dev->dev));
30563066
if (!dev->dmavec_mempool)
30573067
return -ENOMEM;
3058-
3059-
dev->iod_meta_mempool = mempool_create_node(1,
3060-
mempool_kmalloc, mempool_kfree,
3061-
(void *)meta_size, GFP_KERNEL,
3062-
dev_to_node(dev->dev));
3063-
if (!dev->iod_meta_mempool)
3064-
goto free;
30653068
return 0;
3066-
free:
3067-
mempool_destroy(dev->dmavec_mempool);
3068-
return -ENOMEM;
30693069
}
30703070

30713071
static void nvme_free_tagset(struct nvme_dev *dev)
@@ -3515,7 +3515,6 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
35153515
nvme_free_queues(dev, 0);
35163516
out_release_iod_mempool:
35173517
mempool_destroy(dev->dmavec_mempool);
3518-
mempool_destroy(dev->iod_meta_mempool);
35193518
out_dev_unmap:
35203519
nvme_dev_unmap(dev);
35213520
out_uninit_ctrl:
@@ -3579,7 +3578,6 @@ static void nvme_remove(struct pci_dev *pdev)
35793578
nvme_dbbuf_dma_free(dev);
35803579
nvme_free_queues(dev, 0);
35813580
mempool_destroy(dev->dmavec_mempool);
3582-
mempool_destroy(dev->iod_meta_mempool);
35833581
nvme_release_descriptor_pools(dev);
35843582
nvme_dev_unmap(dev);
35853583
nvme_uninit_ctrl(&dev->ctrl);

0 commit comments

Comments
 (0)