diff mbox series

[v2,1/2] RDMA/rxe: Treat physical addresses right

Message ID 20230329142341.863175-1-linus.walleij@linaro.org (mailing list archive)
State Changes Requested
Delegated to: Jason Gunthorpe
Headers show
Series [v2,1/2] RDMA/rxe: Treat physical addresses right | expand

Commit Message

Linus Walleij March 29, 2023, 2:23 p.m. UTC
Whenever the IB_MR_TYPE_DMA flag is set in imbr.type, the "iova"
(I/O virtual address) is not really a virtual address but a physical
address.

This means that the use of virt_to_page() on these addresses is also
incorrect, this needs to be treated and converted to a page using
the page frame number and pfn_to_page().

Fix up all users in this file.

Fixes: 592627ccbdff ("RDMA/rxe: Replace rxe_map and rxe_phys_buf by xarray")
Cc: Bob Pearson <rpearsonhpe@gmail.com>
Reported-by: Jason Gunthorpe <jgg@nvidia.com>
Link: https://lore.kernel.org/linux-rdma/ZB2s3GeaN%2FFBpR5K@nvidia.com/
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v1->v2:
- New patch prepended to patch set.
---
 drivers/infiniband/sw/rxe/rxe_mr.c | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

Comments

Zhu Yanjun April 2, 2023, 1:51 p.m. UTC | #1
在 2023/3/29 22:23, Linus Walleij 写道:
> Whenever the IB_MR_TYPE_DMA flag is set in imbr.type, the "iova"
> (I/O virtual address) is not really a virtual address but a physical
> address.
> 
> This means that the use of virt_to_page() on these addresses is also
> incorrect, this needs to be treated and converted to a page using
> the page frame number and pfn_to_page().
> 
> Fix up all users in this file.

It is better to have a summary to these 2 commits.
Anyway, thanks.

Acked-by: Zhu Yanjun <zyjzyj2000@gmail.com>

Zhu Yanjun

> 
> Fixes: 592627ccbdff ("RDMA/rxe: Replace rxe_map and rxe_phys_buf by xarray")
> Cc: Bob Pearson <rpearsonhpe@gmail.com>
> Reported-by: Jason Gunthorpe <jgg@nvidia.com>
> Link: https://lore.kernel.org/linux-rdma/ZB2s3GeaN%2FFBpR5K@nvidia.com/
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> ChangeLog v1->v2:
> - New patch prepended to patch set.
> ---
>   drivers/infiniband/sw/rxe/rxe_mr.c | 26 ++++++++++++++++++--------
>   1 file changed, 18 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c
> index b10aa1580a64..8e8250652f9d 100644
> --- a/drivers/infiniband/sw/rxe/rxe_mr.c
> +++ b/drivers/infiniband/sw/rxe/rxe_mr.c
> @@ -279,16 +279,20 @@ static int rxe_mr_copy_xarray(struct rxe_mr *mr, u64 iova, void *addr,
>   	return 0;
>   }
>   
> -static void rxe_mr_copy_dma(struct rxe_mr *mr, u64 iova, void *addr,
> +/*
> + * This function is always called with a physical address as parameter,
> + * since DMA only operates on physical addresses.
> + */
> +static void rxe_mr_copy_dma(struct rxe_mr *mr, u64 phys, void *addr,
>   			    unsigned int length, enum rxe_mr_copy_dir dir)
>   {
> -	unsigned int page_offset = iova & (PAGE_SIZE - 1);
> +	unsigned int page_offset = phys & (PAGE_SIZE - 1);
>   	unsigned int bytes;
>   	struct page *page;
>   	u8 *va;
>   
>   	while (length) {
> -		page = virt_to_page(iova & mr->page_mask);
> +		page = pfn_to_page(phys >> PAGE_SHIFT);
>   		bytes = min_t(unsigned int, length,
>   				PAGE_SIZE - page_offset);
>   		va = kmap_local_page(page);
> @@ -300,7 +304,7 @@ static void rxe_mr_copy_dma(struct rxe_mr *mr, u64 iova, void *addr,
>   
>   		kunmap_local(va);
>   		page_offset = 0;
> -		iova += bytes;
> +		phys += bytes;
>   		addr += bytes;
>   		length -= bytes;
>   	}
> @@ -487,8 +491,11 @@ int rxe_mr_do_atomic_op(struct rxe_mr *mr, u64 iova, int opcode,
>   	}
>   
>   	if (mr->ibmr.type == IB_MR_TYPE_DMA) {
> -		page_offset = iova & (PAGE_SIZE - 1);
> -		page = virt_to_page(iova & PAGE_MASK);
> +		/* In this case iova is a physical address */
> +		u64 phys = iova;
> +
> +		page_offset = phys & (PAGE_SIZE - 1);
> +		page = pfn_to_page(phys >> PAGE_SHIFT);
>   	} else {
>   		unsigned long index;
>   		int err;
> @@ -544,8 +551,11 @@ int rxe_mr_do_atomic_write(struct rxe_mr *mr, u64 iova, u64 value)
>   	}
>   
>   	if (mr->ibmr.type == IB_MR_TYPE_DMA) {
> -		page_offset = iova & (PAGE_SIZE - 1);
> -		page = virt_to_page(iova & PAGE_MASK);
> +		/* In this case iova is a physical address */
> +		u64 phys = iova;
> +
> +		page_offset = phys & (PAGE_SIZE - 1);
> +		page = pfn_to_page(phys >> PAGE_SHIFT);
>   	} else {
>   		unsigned long index;
>   		int err;
diff mbox series

Patch

diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c
index b10aa1580a64..8e8250652f9d 100644
--- a/drivers/infiniband/sw/rxe/rxe_mr.c
+++ b/drivers/infiniband/sw/rxe/rxe_mr.c
@@ -279,16 +279,20 @@  static int rxe_mr_copy_xarray(struct rxe_mr *mr, u64 iova, void *addr,
 	return 0;
 }
 
-static void rxe_mr_copy_dma(struct rxe_mr *mr, u64 iova, void *addr,
+/*
+ * This function is always called with a physical address as parameter,
+ * since DMA only operates on physical addresses.
+ */
+static void rxe_mr_copy_dma(struct rxe_mr *mr, u64 phys, void *addr,
 			    unsigned int length, enum rxe_mr_copy_dir dir)
 {
-	unsigned int page_offset = iova & (PAGE_SIZE - 1);
+	unsigned int page_offset = phys & (PAGE_SIZE - 1);
 	unsigned int bytes;
 	struct page *page;
 	u8 *va;
 
 	while (length) {
-		page = virt_to_page(iova & mr->page_mask);
+		page = pfn_to_page(phys >> PAGE_SHIFT);
 		bytes = min_t(unsigned int, length,
 				PAGE_SIZE - page_offset);
 		va = kmap_local_page(page);
@@ -300,7 +304,7 @@  static void rxe_mr_copy_dma(struct rxe_mr *mr, u64 iova, void *addr,
 
 		kunmap_local(va);
 		page_offset = 0;
-		iova += bytes;
+		phys += bytes;
 		addr += bytes;
 		length -= bytes;
 	}
@@ -487,8 +491,11 @@  int rxe_mr_do_atomic_op(struct rxe_mr *mr, u64 iova, int opcode,
 	}
 
 	if (mr->ibmr.type == IB_MR_TYPE_DMA) {
-		page_offset = iova & (PAGE_SIZE - 1);
-		page = virt_to_page(iova & PAGE_MASK);
+		/* In this case iova is a physical address */
+		u64 phys = iova;
+
+		page_offset = phys & (PAGE_SIZE - 1);
+		page = pfn_to_page(phys >> PAGE_SHIFT);
 	} else {
 		unsigned long index;
 		int err;
@@ -544,8 +551,11 @@  int rxe_mr_do_atomic_write(struct rxe_mr *mr, u64 iova, u64 value)
 	}
 
 	if (mr->ibmr.type == IB_MR_TYPE_DMA) {
-		page_offset = iova & (PAGE_SIZE - 1);
-		page = virt_to_page(iova & PAGE_MASK);
+		/* In this case iova is a physical address */
+		u64 phys = iova;
+
+		page_offset = phys & (PAGE_SIZE - 1);
+		page = pfn_to_page(phys >> PAGE_SHIFT);
 	} else {
 		unsigned long index;
 		int err;