diff options
| author | Stanislav Fomichev <sdf.kernel@gmail.com> | 2026-09-25 13:15:22 -0700 |
|---|---|---|
| committer | Paolo Abeni <pabeni@redhat.com> | 2026-09-29 15:41:31 +0200 |
| commit | 5c729e6c71f1be48b5afb99326a6b687e3600c67 (patch) | |
| tree | 834c0e57399a3a4fe6783314d87324f7800b2f51 /net/core | |
| parent | 5bdeb89ec5b07c751c490af7cac9b1e20a1426ac (diff) | |
| download | linux-next-5c729e6c71f1be48b5afb99326a6b687e3600c67.tar.gz linux-next-5c729e6c71f1be48b5afb99326a6b687e3600c67.zip | |
net: devmem: decode DMA addresses for TX
On 32-bit architectures where dma_addr_t is wider than unsigned long,
page_pool_set_dma_addr_netmem() stores page-aligned DMA addresses shifted
by PAGE_SHIFT. The net_iov branch of __skb_frag_dma_map() adds byte offsets
to the encoded value, so the NIC is programmed with an invalid DMA address.
This can trigger an IOMMU fault or DMA from unintended memory.
Consolidate DMA address encoding, decoding, and representability checks in
netmem helpers. Use the common decoder from the page pool and net_iov TX
paths so both interpret stored addresses consistently.
Reviewed-by: Mina Almasry <almasrymina@google.com>
Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
Link: https://patch.msgid.link/20260925201522.254717-4-sdf@fomichev.me
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Diffstat (limited to 'net/core')
| -rw-r--r-- | net/core/page_pool_priv.h | 14 |
1 files changed, 2 insertions, 12 deletions
diff --git a/net/core/page_pool_priv.h b/net/core/page_pool_priv.h index 2fb06d5f6d55..430b97cd88da 100644 --- a/net/core/page_pool_priv.h +++ b/net/core/page_pool_priv.h @@ -18,18 +18,8 @@ void page_pool_unlist(struct page_pool *pool); static inline bool page_pool_set_dma_addr_netmem(netmem_ref netmem, dma_addr_t addr) { - if (PAGE_POOL_32BIT_ARCH_WITH_64BIT_DMA) { - netmem_set_dma_addr(netmem, addr >> PAGE_SHIFT); - - /* We assume page alignment to shave off bottom bits, - * if this "compression" doesn't work we need to drop. - */ - return addr != (dma_addr_t)netmem_get_dma_addr(netmem) - << PAGE_SHIFT; - } - - netmem_set_dma_addr(netmem, addr); - return false; + netmem_set_dma_addr(netmem, netmem_dma_addr_encode(addr)); + return !netmem_dma_addr_fits(addr); } static inline bool page_pool_set_dma_addr(struct page *page, dma_addr_t addr) |
