summaryrefslogtreecommitdiff
path: root/net/core
diff options
context:
space:
mode:
authorStanislav Fomichev <sdf.kernel@gmail.com>2026-09-25 13:15:22 -0700
committerPaolo Abeni <pabeni@redhat.com>2026-09-29 15:41:31 +0200
commit5c729e6c71f1be48b5afb99326a6b687e3600c67 (patch)
tree834c0e57399a3a4fe6783314d87324f7800b2f51 /net/core
parent5bdeb89ec5b07c751c490af7cac9b1e20a1426ac (diff)
downloadlinux-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.h14
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)