nvme-pci: refactor nvme_unmap_data
PATCH 1/2 nvme-pci: refactor nvme_unmap_data
From: Christoph Hellwig <[email protected]>
commit 9275c206f88e5c49cb3e71932c81c8561083db9e upstream.
Split out three helpers from nvme_unmap_data that will allow finer grained unwinding from nvme_map_data.
--- drivers/nvme/host/pci.c | 77 ++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 28 deletions(-)
drivers/nvme/host/pci.c +49 -28
@@ -528,50 +528,71 @@ static inline bool nvme_pci_use_sgls(struct nvme_dev *dev, struct request *req)return true; } -static void nvme_unmap_data (struct nvme_dev *dev,struct request *req) +static void nvme_free_prps (struct nvme_dev *dev,struct request *req) { -struct nvme_iod *iod =blk_mq_rq_to_pdu (req);const int last_prp = dev->ctrl.page_size /sizeof (__le64) -1 ; -dma_addr_t dma_addr = iod->first_dma, next_dma_addr; +struct nvme_iod *iod =blk_mq_rq_to_pdu (req); +dma_addr_t dma_addr = iod->first_dma;int i; -if (iod->dma_len) { -dma_unmap_page (dev->dev, dma_addr, iod->dma_len, -rq_dma_dir (req)); -return ; +for (i =0 ; i < iod->npages; i++) { +__le64 *prp_list =nvme_pci_iod_list (req)[i]; +dma_addr_t next_dma_addr =le64_to_cpu (prp_list[last_prp]); + +dma_pool_free (dev->prp_page_pool, prp_list, dma_addr); + dma_addr = next_dma_addr; } -WARN_ON_ONCE (!iod->nents); +} -if (is_pci_p2pdma_page (sg_page (iod->sg))) -pci_p2pdma_unmap_sg (dev->dev, iod->sg, iod->nents, -rq_dma_dir (req)); -else -dma_unmap_sg (dev->dev, iod->sg, iod->nents,rq_dma_dir (req)); +static void nvme_free_sgls (struct nvme_dev *dev,struct request *req) +{ +const int last_sg =SGES_PER_PAGE -1 ; +struct nvme_iod *iod =blk_mq_rq_to_pdu (req); +dma_addr_t dma_addr = iod->first_dma; +int i; +for (i =0 ; i < iod->npages; i++) { +struct nvme_sgl_desc *sg_list =nvme_pci_iod_list (req)[i]; +dma_addr_t next_dma_addr =le64_to_cpu ((sg_list[last_sg]).addr); -if (iod->npages ==0 ) -dma_pool_free (dev->prp_small_pool,nvme_pci_iod_list (req)[0 ], - dma_addr); +dma_pool_free (dev->prp_page_pool, sg_list, dma_addr); + dma_addr = next_dma_addr; + } -for (i =0 ; i < iod->npages; i++) { -void *addr =nvme_pci_iod_list (req)[i]; +} -if (iod->use_sgl) { -struct nvme_sgl_desc *sg_list = addr; +static void nvme_unmap_sg (struct nvme_dev *dev,struct request *req) +{ +struct nvme_iod *iod =blk_mq_rq_to_pdu (req); - next_dma_addr = -le64_to_cpu ((sg_list[SGES_PER_PAGE -1 ]).addr); - }else { -__le64 *prp_list = addr; +if (is_pci_p2pdma_page (sg_page (iod->sg))) +pci_p2pdma_unmap_sg (dev->dev, iod->sg, iod->nents, +rq_dma_dir (req)); +else +dma_unmap_sg (dev->dev, iod->sg, iod->nents,rq_dma_dir (req)); +} - next_dma_addr =le64_to_cpu (prp_list[last_prp]); - } +static void nvme_unmap_data (struct nvme_dev *dev,struct request *req) +{ +struct nvme_iod *iod =blk_mq_rq_to_pdu (req); -dma_pool_free (dev->prp_page_pool, addr, dma_addr); - dma_addr = next_dma_addr; +if (iod->dma_len) { +dma_unmap_page (dev->dev, iod->first_dma, iod->dma_len, +rq_dma_dir (req)); +return ; } +WARN_ON_ONCE (!iod->nents); + +nvme_unmap_sg (dev, req); +if (iod->npages ==0 ) +dma_pool_free (dev->prp_small_pool,nvme_pci_iod_list (req)[0 ], + iod->first_dma); +else if (iod->use_sgl) +nvme_free_sgls (dev, req); +else +nvme_free_prps (dev, req);mempool_free (iod->sg, dev->iod_mempool); }
Signature · 1 line
2.30.1.766.gb4fecdf3b7-goog
PATCH 2/2 nvme-pci: fix error unwind in nvme_map_data
From: Christoph Hellwig <[email protected]>
commit fa0732168fa1369dd089e5b06d6158a68229f7b7 upstream.
Properly unwind step by step using refactored helpers from nvme_unmap_data to avoid a potential double dma_unmap on a mapping failure.
--- drivers/nvme/host/pci.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-)
drivers/nvme/host/pci.c +18 -10
@@ -669,7 +669,7 @@ static blk_status_t nvme_pci_setup_prps(struct nvme_dev *dev,__le64 *old_prp_list = prp_list; prp_list =dma_pool_alloc (pool,GFP_ATOMIC , &prp_dma);if (!prp_list) -return BLK_STS_RESOURCE ; + goto free_prps; list[iod->npages++] = prp_list; prp_list[0 ] = old_prp_list[i -1 ]; old_prp_list[i -1 ] =cpu_to_le64 (prp_dma);
@@ -689,14 +689,14 @@ static blk_status_t nvme_pci_setup_prps(struct nvme_dev *dev, dma_addr =sg_dma_address (sg); dma_len =sg_dma_len (sg); } - done: cmnd->dptr.prp1 =cpu_to_le64 (sg_dma_address (iod->sg)); cmnd->dptr.prp2 =cpu_to_le64 (iod->first_dma); -return BLK_STS_OK ; - - bad_sgl: +free_prps: +nvme_free_prps (dev, req); +return BLK_STS_RESOURCE ; +bad_sgl:WARN (DO_ONCE (nvme_print_sgl, iod->sg, iod->nents),"Invalid SGL for payload:%d nents:%d\n" ,blk_rq_payload_bytes (req), iod->nents);
@@ -768,7 +768,7 @@ static blk_status_t nvme_pci_setup_sgls(struct nvme_dev *dev, sg_list =dma_pool_alloc (pool,GFP_ATOMIC , &sgl_dma);if (!sg_list) -return BLK_STS_RESOURCE ; + goto free_sgls; i =0 ;nvme_pci_iod_list (req)[iod->npages++] = sg_list;
@@ -781,6 +781,9 @@ static blk_status_t nvme_pci_setup_sgls(struct nvme_dev *dev, }while (--entries >0 );return BLK_STS_OK ; +free_sgls: +nvme_free_sgls (dev, req); +return BLK_STS_RESOURCE ; } static blk_status_t nvme_setup_prp_simple(struct nvme_dev *dev,
@@ -849,7 +852,7 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req,sg_init_table (iod->sg,blk_rq_nr_phys_segments (req)); iod->nents =blk_rq_map_sg (req->q, req, iod->sg);if (!iod->nents) - goto out; + goto out_free_sg;if (is_pci_p2pdma_page (sg_page (iod->sg))) nr_mapped = pci_p2pdma_map_sg_attrs(dev->dev, iod->sg,
@@ -858,16 +861,21 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req, nr_mapped =dma_map_sg_attrs (dev->dev, iod->sg, iod->nents,rq_dma_dir (req),DMA_ATTR_NO_WARN );if (!nr_mapped) - goto out; + goto out_free_sg; iod->use_sgl =nvme_pci_use_sgls (dev, req);if (iod->use_sgl) ret =nvme_pci_setup_sgls (dev, req, &cmnd->rw, nr_mapped);else ret =nvme_pci_setup_prps (dev, req, &cmnd->rw); -out:if (ret !=BLK_STS_OK ) -nvme_unmap_data (dev, req); + goto out_unmap_sg; +return BLK_STS_OK ; + +out_unmap_sg: +nvme_unmap_sg (dev, req); +out_free_sg: +mempool_free (iod->sg, dev->iod_mempool);return ret; }
Signature · 1 line
2.30.1.766.gb4fecdf3b7-goog
Quoted 7 lines · Marc Orr
From: Christoph Hellwig <[email protected]>
commit
9275c206f88e5c49cb3e71932c81c8561083db9eupstream.Split out three helpers from
nvme_unmap_datathat will allow finer grained unwinding fromnvme_map_data.
Quoted 7 lines
Signed-off-by Christoph Hellwig <[email protected]>Reviewed-by Keith Busch <[email protected]>Reviewed-by Marc Orr <[email protected]>Signed-off-by Marc Orr <[email protected]>--- drivers/nvme/host/pci.c | 77 ++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 28 deletions(-)
Both now queued up, thanks.
greg k-h