[RFC net-next 07/15] xsk: Keep the DMA mapping in the buffer pool

From: Björn Töpel

Date: Fri Oct 02 2026 - 15:04:12 EST


At unmap, an XSK buffer pool looks up its DMA mapping again. It
searches the UMEM's mapping list for the pool's netdev. A memory
provider, added later in this series, can keep the mapping after the
queue is gone. By then the netdev may be cleared, so the search is
not reliable.

Store the mapping that xp_dma_map() picked in the pool, and unmap
that mapping. Hold a reference on the DMA device while the mapping
exists, so a late final unmap does not use a freed device.

The reference counting of shared mappings does not change.

Signed-off-by: Björn Töpel <bjorn@xxxxxxxxxx>
---
include/net/xsk_buff_pool.h | 1 +
net/xdp/xsk_buff_pool.c | 8 +++++---
2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/include/net/xsk_buff_pool.h b/include/net/xsk_buff_pool.h
index a7df573784fd..77264c4902c0 100644
--- a/include/net/xsk_buff_pool.h
+++ b/include/net/xsk_buff_pool.h
@@ -67,6 +67,7 @@ struct xsk_buff_pool {
* even when they are identical.
*/
dma_addr_t *dma_pages;
+ struct xsk_dma_map *dma_map;
struct xdp_buff_xsk *heads;
struct xdp_desc *tx_descs;
u64 chunk_mask;
diff --git a/net/xdp/xsk_buff_pool.c b/net/xdp/xsk_buff_pool.c
index f01e1de7360e..244776a72961 100644
--- a/net/xdp/xsk_buff_pool.c
+++ b/net/xdp/xsk_buff_pool.c
@@ -373,7 +373,7 @@ static struct xsk_dma_map *xp_create_dma_map(struct device *dev, struct net_devi
}

dma_map->netdev = netdev;
- dma_map->dev = dev;
+ dma_map->dev = get_device(dev);
dma_map->dma_pages_cnt = nr_pages;
refcount_set(&dma_map->users, 1);
list_add(&dma_map->list, &umem->xsk_dma_list);
@@ -384,6 +384,7 @@ static void xp_destroy_dma_map(struct xsk_dma_map *dma_map)
{
list_del(&dma_map->list);
kvfree(dma_map->dma_pages);
+ put_device(dma_map->dev);
kfree(dma_map);
}

@@ -407,12 +408,11 @@ static void __xp_dma_unmap(struct xsk_dma_map *dma_map, unsigned long attrs)

void xp_dma_unmap(struct xsk_buff_pool *pool, unsigned long attrs)
{
- struct xsk_dma_map *dma_map;
+ struct xsk_dma_map *dma_map = pool->dma_map;

if (!pool->dma_pages)
return;

- dma_map = xp_find_dma_map(pool);
if (!dma_map) {
WARN(1, "Could not find dma_map for device");
return;
@@ -424,6 +424,7 @@ void xp_dma_unmap(struct xsk_buff_pool *pool, unsigned long attrs)
kvfree(pool->dma_pages);
pool->dma_pages = NULL;
pool->dma_pages_cnt = 0;
+ pool->dma_map = NULL;
pool->dev = NULL;
}
EXPORT_SYMBOL(xp_dma_unmap);
@@ -460,6 +461,7 @@ static int xp_init_dma_info(struct xsk_buff_pool *pool, struct xsk_dma_map *dma_
return -ENOMEM;

pool->dev = dma_map->dev;
+ pool->dma_map = dma_map;
pool->dma_pages_cnt = dma_map->dma_pages_cnt;
memcpy(pool->dma_pages, dma_map->dma_pages,
pool->dma_pages_cnt * sizeof(*pool->dma_pages));
--
2.55.0