Skip to content

Commit a41ce5c

Browse files
isilencegregkh
authored andcommitted
net: page_pool: create hooks for custom memory providers
[ Upstream commit 57afb48 ] A spin off from the original page pool memory providers patch by Jakub, which allows extending page pools with custom allocators. One of such providers is devmem TCP, and the other is io_uring zerocopy added in following patches. Link: https://lore.kernel.org/netdev/20230707183935.997267-7-kuba@kernel.org/ Co-developed-by: Jakub Kicinski <kuba@kernel.org> # initial mp proposal Signed-off-by: Pavel Begunkov <asml.silence@gmail.com> Signed-off-by: David Wei <dw@davidwei.uk> Link: https://patch.msgid.link/20250204215622.695511-5-dw@davidwei.uk Signed-off-by: Jakub Kicinski <kuba@kernel.org> Stable-dep-of: 5ef3436 ("page_pool: fix memory-provider leak in page_pool_create_percpu() error path") Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent ab964dd commit a41ce5c

4 files changed

Lines changed: 48 additions & 9 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef _NET_PAGE_POOL_MEMORY_PROVIDER_H
3+
#define _NET_PAGE_POOL_MEMORY_PROVIDER_H
4+
5+
#include <net/netmem.h>
6+
#include <net/page_pool/types.h>
7+
8+
struct memory_provider_ops {
9+
netmem_ref (*alloc_netmems)(struct page_pool *pool, gfp_t gfp);
10+
bool (*release_netmem)(struct page_pool *pool, netmem_ref netmem);
11+
int (*init)(struct page_pool *pool);
12+
void (*destroy)(struct page_pool *pool);
13+
};
14+
15+
#endif

include/net/page_pool/types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,11 @@ struct page_pool_stats {
156156
*/
157157
#define PAGE_POOL_FRAG_GROUP_ALIGN (4 * sizeof(long))
158158

159+
struct memory_provider_ops;
160+
159161
struct pp_memory_provider_params {
160162
void *mp_priv;
163+
const struct memory_provider_ops *mp_ops;
161164
};
162165

163166
struct page_pool {
@@ -219,6 +222,7 @@ struct page_pool {
219222
struct ptr_ring ring;
220223

221224
void *mp_priv;
225+
const struct memory_provider_ops *mp_ops;
222226

223227
struct xarray dma_mapped;
224228

net/core/devmem.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <net/netdev_queues.h>
1616
#include <net/netdev_rx_queue.h>
1717
#include <net/page_pool/helpers.h>
18+
#include <net/page_pool/memory_provider.h>
1819
#include <trace/events/page_pool.h>
1920

2021
#include "devmem.h"
@@ -26,6 +27,8 @@
2627
/* Protected by rtnl_lock() */
2728
static DEFINE_XARRAY_FLAGS(net_devmem_dmabuf_bindings, XA_FLAGS_ALLOC1);
2829

30+
static const struct memory_provider_ops dmabuf_devmem_ops;
31+
2932
static void net_devmem_dmabuf_free_chunk_owner(struct gen_pool *genpool,
3033
struct gen_pool_chunk *chunk,
3134
void *not_used)
@@ -117,6 +120,7 @@ void net_devmem_unbind_dmabuf(struct net_devmem_dmabuf_binding *binding)
117120
WARN_ON(rxq->mp_params.mp_priv != binding);
118121

119122
rxq->mp_params.mp_priv = NULL;
123+
rxq->mp_params.mp_ops = NULL;
120124

121125
rxq_idx = get_netdev_rx_queue_index(rxq);
122126

@@ -143,7 +147,7 @@ int net_devmem_bind_dmabuf_to_queue(struct net_device *dev, u32 rxq_idx,
143147
}
144148

145149
rxq = __netif_get_rx_queue(dev, rxq_idx);
146-
if (rxq->mp_params.mp_priv) {
150+
if (rxq->mp_params.mp_ops) {
147151
NL_SET_ERR_MSG(extack, "designated queue already memory provider bound");
148152
return -EEXIST;
149153
}
@@ -161,6 +165,7 @@ int net_devmem_bind_dmabuf_to_queue(struct net_device *dev, u32 rxq_idx,
161165
return err;
162166

163167
rxq->mp_params.mp_priv = binding;
168+
rxq->mp_params.mp_ops = &dmabuf_devmem_ops;
164169

165170
err = netdev_rx_queue_restart(dev, rxq_idx);
166171
if (err)
@@ -170,6 +175,7 @@ int net_devmem_bind_dmabuf_to_queue(struct net_device *dev, u32 rxq_idx,
170175

171176
err_xa_erase:
172177
rxq->mp_params.mp_priv = NULL;
178+
rxq->mp_params.mp_ops = NULL;
173179
xa_erase(&binding->bound_rxqs, xa_idx);
174180

175181
return err;
@@ -388,3 +394,10 @@ bool mp_dmabuf_devmem_release_page(struct page_pool *pool, netmem_ref netmem)
388394
/* We don't want the page pool put_page()ing our net_iovs. */
389395
return false;
390396
}
397+
398+
static const struct memory_provider_ops dmabuf_devmem_ops = {
399+
.init = mp_dmabuf_devmem_init,
400+
.destroy = mp_dmabuf_devmem_destroy,
401+
.alloc_netmems = mp_dmabuf_devmem_alloc_netmems,
402+
.release_netmem = mp_dmabuf_devmem_release_page,
403+
};

net/core/page_pool.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include <net/netdev_rx_queue.h>
1515
#include <net/page_pool/helpers.h>
16+
#include <net/page_pool/memory_provider.h>
1617
#include <net/xdp.h>
1718

1819
#include <linux/dma-direction.h>
@@ -280,13 +281,19 @@ static int page_pool_init(struct page_pool *pool,
280281
rxq = __netif_get_rx_queue(pool->slow.netdev,
281282
pool->slow.queue_idx);
282283
pool->mp_priv = rxq->mp_params.mp_priv;
284+
pool->mp_ops = rxq->mp_params.mp_ops;
283285
}
284286

285-
if (pool->mp_priv) {
287+
if (pool->mp_ops) {
286288
if (!pool->dma_map || !pool->dma_sync)
287289
return -EOPNOTSUPP;
288290

289-
err = mp_dmabuf_devmem_init(pool);
291+
if (WARN_ON(!is_kernel_rodata((unsigned long)pool->mp_ops))) {
292+
err = -EFAULT;
293+
goto free_ptr_ring;
294+
}
295+
296+
err = pool->mp_ops->init(pool);
290297
if (err) {
291298
pr_warn("%s() mem-provider init failed %d\n", __func__,
292299
err);
@@ -651,8 +658,8 @@ netmem_ref page_pool_alloc_netmem(struct page_pool *pool, gfp_t gfp)
651658
return netmem;
652659

653660
/* Slow-path: cache empty, do real allocation */
654-
if (static_branch_unlikely(&page_pool_mem_providers) && pool->mp_priv)
655-
netmem = mp_dmabuf_devmem_alloc_netmems(pool, gfp);
661+
if (static_branch_unlikely(&page_pool_mem_providers) && pool->mp_ops)
662+
netmem = pool->mp_ops->alloc_netmems(pool, gfp);
656663
else
657664
netmem = __page_pool_alloc_pages_slow(pool, gfp);
658665
return netmem;
@@ -746,8 +753,8 @@ void page_pool_return_page(struct page_pool *pool, netmem_ref netmem)
746753
bool put;
747754

748755
put = true;
749-
if (static_branch_unlikely(&page_pool_mem_providers) && pool->mp_priv)
750-
put = mp_dmabuf_devmem_release_page(pool, netmem);
756+
if (static_branch_unlikely(&page_pool_mem_providers) && pool->mp_ops)
757+
put = pool->mp_ops->release_netmem(pool, netmem);
751758
else
752759
__page_pool_release_page_dma(pool, netmem);
753760

@@ -1081,8 +1088,8 @@ static void __page_pool_destroy(struct page_pool *pool)
10811088
page_pool_unlist(pool);
10821089
page_pool_uninit(pool);
10831090

1084-
if (pool->mp_priv) {
1085-
mp_dmabuf_devmem_destroy(pool);
1091+
if (pool->mp_ops) {
1092+
pool->mp_ops->destroy(pool);
10861093
static_branch_dec(&page_pool_mem_providers);
10871094
}
10881095

0 commit comments

Comments
 (0)