| From 6affca140cbea01f497c4f4e16f1e2be7f74bd04 Mon Sep 17 00:00:00 2001 |
| From: Max Gurtovoy <maxg@mellanox.com> |
| Date: Thu, 20 Feb 2020 12:08:18 +0200 |
| Subject: RDMA/rw: Fix error flow during RDMA context initialization |
| |
| From: Max Gurtovoy <maxg@mellanox.com> |
| |
| commit 6affca140cbea01f497c4f4e16f1e2be7f74bd04 upstream. |
| |
| In case the SGL was mapped for P2P DMA operation, we must unmap it using |
| pci_p2pdma_unmap_sg during the error unwind of rdma_rw_ctx_init() |
| |
| Fixes: 7f73eac3a713 ("PCI/P2PDMA: Introduce pci_p2pdma_unmap_sg()") |
| Link: https://lore.kernel.org/r/20200220100819.41860-1-maxg@mellanox.com |
| Signed-off-by: Max Gurtovoy <maxg@mellanox.com> |
| Reviewed-by: Leon Romanovsky <leonro@mellanox.com> |
| Reviewed-by: Logan Gunthorpe <logang@deltatee.com> |
| Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/infiniband/core/rw.c | 31 ++++++++++++++++++++----------- |
| 1 file changed, 20 insertions(+), 11 deletions(-) |
| |
| --- a/drivers/infiniband/core/rw.c |
| +++ b/drivers/infiniband/core/rw.c |
| @@ -273,6 +273,23 @@ static int rdma_rw_init_single_wr(struct |
| return 1; |
| } |
| |
| +static void rdma_rw_unmap_sg(struct ib_device *dev, struct scatterlist *sg, |
| + u32 sg_cnt, enum dma_data_direction dir) |
| +{ |
| + if (is_pci_p2pdma_page(sg_page(sg))) |
| + pci_p2pdma_unmap_sg(dev->dma_device, sg, sg_cnt, dir); |
| + else |
| + ib_dma_unmap_sg(dev, sg, sg_cnt, dir); |
| +} |
| + |
| +static int rdma_rw_map_sg(struct ib_device *dev, struct scatterlist *sg, |
| + u32 sg_cnt, enum dma_data_direction dir) |
| +{ |
| + if (is_pci_p2pdma_page(sg_page(sg))) |
| + return pci_p2pdma_map_sg(dev->dma_device, sg, sg_cnt, dir); |
| + return ib_dma_map_sg(dev, sg, sg_cnt, dir); |
| +} |
| + |
| /** |
| * rdma_rw_ctx_init - initialize a RDMA READ/WRITE context |
| * @ctx: context to initialize |
| @@ -295,11 +312,7 @@ int rdma_rw_ctx_init(struct rdma_rw_ctx |
| struct ib_device *dev = qp->pd->device; |
| int ret; |
| |
| - if (is_pci_p2pdma_page(sg_page(sg))) |
| - ret = pci_p2pdma_map_sg(dev->dma_device, sg, sg_cnt, dir); |
| - else |
| - ret = ib_dma_map_sg(dev, sg, sg_cnt, dir); |
| - |
| + ret = rdma_rw_map_sg(dev, sg, sg_cnt, dir); |
| if (!ret) |
| return -ENOMEM; |
| sg_cnt = ret; |
| @@ -338,7 +351,7 @@ int rdma_rw_ctx_init(struct rdma_rw_ctx |
| return ret; |
| |
| out_unmap_sg: |
| - ib_dma_unmap_sg(dev, sg, sg_cnt, dir); |
| + rdma_rw_unmap_sg(dev, sg, sg_cnt, dir); |
| return ret; |
| } |
| EXPORT_SYMBOL(rdma_rw_ctx_init); |
| @@ -588,11 +601,7 @@ void rdma_rw_ctx_destroy(struct rdma_rw_ |
| break; |
| } |
| |
| - if (is_pci_p2pdma_page(sg_page(sg))) |
| - pci_p2pdma_unmap_sg(qp->pd->device->dma_device, sg, |
| - sg_cnt, dir); |
| - else |
| - ib_dma_unmap_sg(qp->pd->device, sg, sg_cnt, dir); |
| + rdma_rw_unmap_sg(qp->pd->device, sg, sg_cnt, dir); |
| } |
| EXPORT_SYMBOL(rdma_rw_ctx_destroy); |
| |