Skip to content

Commit 2b0cfa6

Browse files
LorenzoBianconikuba-moo
authored andcommitted
net: add generic percpu page_pool allocator
Introduce generic percpu page_pools allocator. Moreover add page_pool_create_percpu() and cpuid filed in page_pool struct in order to recycle the page in the page_pool "hot" cache if napi_pp_put_page() is running on the same cpu. This is a preliminary patch to add xdp multi-buff support for xdp running in generic mode. Acked-by: Jesper Dangaard Brouer <[email protected]> Reviewed-by: Toke Hoiland-Jorgensen <[email protected]> Signed-off-by: Lorenzo Bianconi <[email protected]> Link: https://lore.kernel.org/r/80bc4285228b6f4220cd03de1999d86e46e3fcbd.1707729884.git.lorenzo@kernel.org Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 32e4a54 commit 2b0cfa6

File tree

4 files changed

+70
-6
lines changed

4 files changed

+70
-6
lines changed

include/net/page_pool/types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ struct page_pool_stats {
128128
struct page_pool {
129129
struct page_pool_params_fast p;
130130

131+
int cpuid;
131132
bool has_init_callback;
132133

133134
long frag_users;
@@ -203,6 +204,8 @@ struct page *page_pool_alloc_pages(struct page_pool *pool, gfp_t gfp);
203204
struct page *page_pool_alloc_frag(struct page_pool *pool, unsigned int *offset,
204205
unsigned int size, gfp_t gfp);
205206
struct page_pool *page_pool_create(const struct page_pool_params *params);
207+
struct page_pool *page_pool_create_percpu(const struct page_pool_params *params,
208+
int cpuid);
206209

207210
struct xdp_mem_info;
208211

net/core/dev.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@
153153
#include <linux/prandom.h>
154154
#include <linux/once_lite.h>
155155
#include <net/netdev_rx_queue.h>
156+
#include <net/page_pool/types.h>
157+
#include <net/page_pool/helpers.h>
156158

157159
#include "dev.h"
158160
#include "net-sysfs.h"
@@ -450,6 +452,12 @@ static RAW_NOTIFIER_HEAD(netdev_chain);
450452
DEFINE_PER_CPU_ALIGNED(struct softnet_data, softnet_data);
451453
EXPORT_PER_CPU_SYMBOL(softnet_data);
452454

455+
/* Page_pool has a lockless array/stack to alloc/recycle pages.
456+
* PP consumers must pay attention to run APIs in the appropriate context
457+
* (e.g. NAPI context).
458+
*/
459+
static DEFINE_PER_CPU_ALIGNED(struct page_pool *, system_page_pool);
460+
453461
#ifdef CONFIG_LOCKDEP
454462
/*
455463
* register_netdevice() inits txq->_xmit_lock and sets lockdep class
@@ -11724,6 +11732,27 @@ static void __init net_dev_struct_check(void)
1172411732
*
1172511733
*/
1172611734

11735+
/* We allocate 256 pages for each CPU if PAGE_SHIFT is 12 */
11736+
#define SYSTEM_PERCPU_PAGE_POOL_SIZE ((1 << 20) / PAGE_SIZE)
11737+
11738+
static int net_page_pool_create(int cpuid)
11739+
{
11740+
#if IS_ENABLED(CONFIG_PAGE_POOL)
11741+
struct page_pool_params page_pool_params = {
11742+
.pool_size = SYSTEM_PERCPU_PAGE_POOL_SIZE,
11743+
.nid = NUMA_NO_NODE,
11744+
};
11745+
struct page_pool *pp_ptr;
11746+
11747+
pp_ptr = page_pool_create_percpu(&page_pool_params, cpuid);
11748+
if (IS_ERR(pp_ptr))
11749+
return -ENOMEM;
11750+
11751+
per_cpu(system_page_pool, cpuid) = pp_ptr;
11752+
#endif
11753+
return 0;
11754+
}
11755+
1172711756
/*
1172811757
* This is called single threaded during boot, so no need
1172911758
* to take the rtnl semaphore.
@@ -11776,6 +11805,9 @@ static int __init net_dev_init(void)
1177611805
init_gro_hash(&sd->backlog);
1177711806
sd->backlog.poll = process_backlog;
1177811807
sd->backlog.weight = weight_p;
11808+
11809+
if (net_page_pool_create(i))
11810+
goto out;
1177911811
}
1178011812

1178111813
dev_boot_phase = 0;
@@ -11803,6 +11835,19 @@ static int __init net_dev_init(void)
1180311835
WARN_ON(rc < 0);
1180411836
rc = 0;
1180511837
out:
11838+
if (rc < 0) {
11839+
for_each_possible_cpu(i) {
11840+
struct page_pool *pp_ptr;
11841+
11842+
pp_ptr = per_cpu(system_page_pool, i);
11843+
if (!pp_ptr)
11844+
continue;
11845+
11846+
page_pool_destroy(pp_ptr);
11847+
per_cpu(system_page_pool, i) = NULL;
11848+
}
11849+
}
11850+
1180611851
return rc;
1180711852
}
1180811853

net/core/page_pool.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,13 +171,16 @@ static void page_pool_producer_unlock(struct page_pool *pool,
171171
}
172172

173173
static int page_pool_init(struct page_pool *pool,
174-
const struct page_pool_params *params)
174+
const struct page_pool_params *params,
175+
int cpuid)
175176
{
176177
unsigned int ring_qsize = 1024; /* Default */
177178

178179
memcpy(&pool->p, &params->fast, sizeof(pool->p));
179180
memcpy(&pool->slow, &params->slow, sizeof(pool->slow));
180181

182+
pool->cpuid = cpuid;
183+
181184
/* Validate only known flags were used */
182185
if (pool->p.flags & ~(PP_FLAG_ALL))
183186
return -EINVAL;
@@ -253,10 +256,12 @@ static void page_pool_uninit(struct page_pool *pool)
253256
}
254257

255258
/**
256-
* page_pool_create() - create a page pool.
259+
* page_pool_create_percpu() - create a page pool for a given cpu.
257260
* @params: parameters, see struct page_pool_params
261+
* @cpuid: cpu identifier
258262
*/
259-
struct page_pool *page_pool_create(const struct page_pool_params *params)
263+
struct page_pool *
264+
page_pool_create_percpu(const struct page_pool_params *params, int cpuid)
260265
{
261266
struct page_pool *pool;
262267
int err;
@@ -265,7 +270,7 @@ struct page_pool *page_pool_create(const struct page_pool_params *params)
265270
if (!pool)
266271
return ERR_PTR(-ENOMEM);
267272

268-
err = page_pool_init(pool, params);
273+
err = page_pool_init(pool, params, cpuid);
269274
if (err < 0)
270275
goto err_free;
271276

@@ -282,6 +287,16 @@ struct page_pool *page_pool_create(const struct page_pool_params *params)
282287
kfree(pool);
283288
return ERR_PTR(err);
284289
}
290+
EXPORT_SYMBOL(page_pool_create_percpu);
291+
292+
/**
293+
* page_pool_create() - create a page pool
294+
* @params: parameters, see struct page_pool_params
295+
*/
296+
struct page_pool *page_pool_create(const struct page_pool_params *params)
297+
{
298+
return page_pool_create_percpu(params, -1);
299+
}
285300
EXPORT_SYMBOL(page_pool_create);
286301

287302
static void page_pool_return_page(struct page_pool *pool, struct page *page);

net/core/skbuff.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -923,9 +923,10 @@ bool napi_pp_put_page(struct page *page, bool napi_safe)
923923
*/
924924
if (napi_safe || in_softirq()) {
925925
const struct napi_struct *napi = READ_ONCE(pp->p.napi);
926+
unsigned int cpuid = smp_processor_id();
926927

927-
allow_direct = napi &&
928-
READ_ONCE(napi->list_owner) == smp_processor_id();
928+
allow_direct = napi && READ_ONCE(napi->list_owner) == cpuid;
929+
allow_direct |= (pp->cpuid == cpuid);
929930
}
930931

931932
/* Driver set this to memory recycling info. Reset it on recycle.

0 commit comments

Comments
 (0)