diff mbox series

[v2,2/2] RDMA/rxe: Pass a pointer to virt_to_page()

Message ID 20230329142341.863175-2-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
Like the other calls in this function virt_to_page() expects
a pointer, not an integer.

However since many architectures implement virt_to_pfn() as
a macro, this function becomes polymorphic and accepts both a
(unsigned long) and a (void *).

Fix this up with an explicit cast.

Then we need a second cast to (uintptr_t). This is because
the kernel robot builds this driver also for the PARISC,
yielding the following build error on PARISC when casting
(void *) to virt_to_page():

drivers/infiniband/sw/rxe/rxe_mr.c: In function 'rxe_set_page':
>> drivers/infiniband/sw/rxe/rxe_mr.c:216:42: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
     216 |         struct page *page = virt_to_page((void *)(iova & mr->page_mask));
         |                                          ^
   include/asm-generic/memory_model.h:18:46: note: in definition of macro '__pfn_to_page'
      18 | #define __pfn_to_page(pfn)      (mem_map + ((pfn) - ARCH_PFN_OFFSET))
         |                                              ^~~
   arch/parisc/include/asm/page.h:179:45: note: in expansion of macro '__pa'
     179 | #define virt_to_page(kaddr)     pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
         |                                             ^~~~
   drivers/infiniband/sw/rxe/rxe_mr.c:216:29: note: in expansion of macro 'virt_to_page'
     216 |         struct page *page = virt_to_page((void *)(iova & mr->page_mask));
         |                             ^~~~~~~~~~~~

First: I think this happens because iova is u64 by design and
(void *) on PARISC is sometimes 32 bit.

Second: compilation of the SW RXE driver on PARISC is made possible
because it fulfills depends on INFINIBAND_VIRT_DMA since that is just
def_bool !HIGHMEM and PARISC does not have HIGHMEM.

By first casting iova to (uintptr_t) it is turned into a u32 on PARISC
or any other 32bit system and u64 on any 64BIT system.

Link: https://lore.kernel.org/linux-rdma/202303242000.HmTaa6yB-lkp@intel.com/
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v1->v2:
- Fix up confusion between virtual and physical addresses found
  by Jason in a separate patch.
- Fix up compilation on PARISC by additional cast.
  I don't know if this is the right solution, perhaps RDMA should
  rather depend on 64BIT if the subsystem is only for 64BIT
  systems?
---
 drivers/infiniband/sw/rxe/rxe_mr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Bob Pearson March 29, 2023, 8:14 p.m. UTC | #1
On 3/29/23 09:23, Linus Walleij wrote:
> Like the other calls in this function virt_to_page() expects
> a pointer, not an integer.
> 
> However since many architectures implement virt_to_pfn() as
> a macro, this function becomes polymorphic and accepts both a
> (unsigned long) and a (void *).
> 
> Fix this up with an explicit cast.
> 
> Then we need a second cast to (uintptr_t). This is because
> the kernel robot builds this driver also for the PARISC,
> yielding the following build error on PARISC when casting
> (void *) to virt_to_page():
> 
> drivers/infiniband/sw/rxe/rxe_mr.c: In function 'rxe_set_page':
>>> drivers/infiniband/sw/rxe/rxe_mr.c:216:42: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
>      216 |         struct page *page = virt_to_page((void *)(iova & mr->page_mask));
>          |                                          ^
>    include/asm-generic/memory_model.h:18:46: note: in definition of macro '__pfn_to_page'
>       18 | #define __pfn_to_page(pfn)      (mem_map + ((pfn) - ARCH_PFN_OFFSET))
>          |                                              ^~~
>    arch/parisc/include/asm/page.h:179:45: note: in expansion of macro '__pa'
>      179 | #define virt_to_page(kaddr)     pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
>          |                                             ^~~~
>    drivers/infiniband/sw/rxe/rxe_mr.c:216:29: note: in expansion of macro 'virt_to_page'
>      216 |         struct page *page = virt_to_page((void *)(iova & mr->page_mask));
>          |                             ^~~~~~~~~~~~
> 
> First: I think this happens because iova is u64 by design and
> (void *) on PARISC is sometimes 32 bit.
> 
> Second: compilation of the SW RXE driver on PARISC is made possible
> because it fulfills depends on INFINIBAND_VIRT_DMA since that is just
> def_bool !HIGHMEM and PARISC does not have HIGHMEM.
> 
> By first casting iova to (uintptr_t) it is turned into a u32 on PARISC
> or any other 32bit system and u64 on any 64BIT system.
> 
> Link: https://lore.kernel.org/linux-rdma/202303242000.HmTaa6yB-lkp@intel.com/
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> ChangeLog v1->v2:
> - Fix up confusion between virtual and physical addresses found
>   by Jason in a separate patch.
> - Fix up compilation on PARISC by additional cast.
>   I don't know if this is the right solution, perhaps RDMA should
>   rather depend on 64BIT if the subsystem is only for 64BIT
>   systems?
> ---
>  drivers/infiniband/sw/rxe/rxe_mr.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c
> index 8e8250652f9d..a5efb0575956 100644
> --- a/drivers/infiniband/sw/rxe/rxe_mr.c
> +++ b/drivers/infiniband/sw/rxe/rxe_mr.c
> @@ -213,7 +213,7 @@ int rxe_mr_init_fast(int max_pages, struct rxe_mr *mr)
>  static int rxe_set_page(struct ib_mr *ibmr, u64 iova)
>  {
>  	struct rxe_mr *mr = to_rmr(ibmr);
> -	struct page *page = virt_to_page(iova & mr->page_mask);
> +	struct page *page = virt_to_page((void *)(uintptr_t)(iova & mr->page_mask));
>  	bool persistent = !!(mr->access & IB_ACCESS_FLUSH_PERSISTENT);
>  	int err;
>  

Linus, Thanks for these. AFAIK these are just fine. I am not aware of any interest in 32 bit
support for the rxe driver. My testing has been limited to IA64 architectures but I would be interested
in going further with emulated hardware.

Reviewed-by: Bob Pearson <rpearsonhpe@gmail.com>
diff mbox series

Patch

diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c
index 8e8250652f9d..a5efb0575956 100644
--- a/drivers/infiniband/sw/rxe/rxe_mr.c
+++ b/drivers/infiniband/sw/rxe/rxe_mr.c
@@ -213,7 +213,7 @@  int rxe_mr_init_fast(int max_pages, struct rxe_mr *mr)
 static int rxe_set_page(struct ib_mr *ibmr, u64 iova)
 {
 	struct rxe_mr *mr = to_rmr(ibmr);
-	struct page *page = virt_to_page(iova & mr->page_mask);
+	struct page *page = virt_to_page((void *)(uintptr_t)(iova & mr->page_mask));
 	bool persistent = !!(mr->access & IB_ACCESS_FLUSH_PERSISTENT);
 	int err;