Re: [PATCH net-next v1 06/11] page_pool: Coordinate refill with memory providers

From: Stanislav Fomichev

Date: Tue Nov 10 2026 - 18:57:49 EST


On 11/10, Björn Töpel wrote:
> A UMEM has a fixed number of chunks. When a refill finds none, and the
> chunks come back later, nothing schedules the queue again: RX stalls.
> Kicks after each queue operation are easy to miss.
>
> Drivers report the end of each refill with page_pool_refill_done().
> The provider then asks for another poll, or wakes the queue later
> through the NAPI that the core publishes while the queue runs. Socket
> wakeups use that NAPI too, so such drivers need no ndo_xsk_wakeup.
>
> With XDP_USE_NEED_WAKEUP, the FILL flag stays set: a flag set only
> when starved can miss an entry posted at the same time.
>
> Signed-off-by: Björn Töpel <bjorn@xxxxxxxxxx>
> ---
> Documentation/networking/netmem.rst | 10 +++
> include/net/netdev_rx_queue.h | 6 ++
> include/net/page_pool/helpers.h | 24 ++++++
> include/net/page_pool/memory_provider.h | 2 +
> include/net/page_pool/types.h | 6 ++
> net/core/dev.c | 4 +
> net/core/dev.h | 4 +
> net/core/netdev_rx_queue.c | 97 ++++++++++++++++++++++++-
> net/xdp/xsk.c | 4 +
> net/xdp/xsk.h | 1 +
> net/xdp/xsk_pp.c | 73 ++++++++++++++++++-
> 11 files changed, 226 insertions(+), 5 deletions(-)
>
> diff --git a/Documentation/networking/netmem.rst b/Documentation/networking/netmem.rst
> index 39cb75339704..74c73d7d126e 100644
> --- a/Documentation/networking/netmem.rst
> +++ b/Documentation/networking/netmem.rst
> @@ -136,6 +136,16 @@ Driver RX Requirements
> circulation times, such as when userspace holds a reference in zerocopy
> scenarios.
>
> +8. After each RX ring refill, call page_pool_refill_done() once per page
> + pool, with PP_REFILL_FULL only if all rings that use the pool are full.
> + Rings of a queue that take buffers from one such provider share one
> + page pool. Keep buffers in each of them, first in a ring that every
> + packet needs, like a header ring, so that a provider with few buffers
> + does not leave them all in one ring. If the call returns false, poll
> + again soon, for example by returning the full NAPI budget. Register the
> + NAPI of each RX queue with netif_queue_set_napi(); the core schedules
> + it when provider buffers become available.
> +
> Driver TX Requirements
> ======================
>
> diff --git a/include/net/netdev_rx_queue.h b/include/net/netdev_rx_queue.h
> index 989120cbf452..ca12cbf7b825 100644
> --- a/include/net/netdev_rx_queue.h
> +++ b/include/net/netdev_rx_queue.h
> @@ -33,6 +33,12 @@ struct netdev_rx_queue {
> struct pp_memory_provider_params mp_params;
> /* stamps the page pools of each queue allocation */
> u32 mp_gen;
> + /* NAPI of the running queue, for memory provider wakeups. Set while
> + * mp_armed, and if the provider has a refill_done op. Written under
> + * the ops lock, read under RCU, see netif_mp_wake().
> + */
> + struct napi_struct __rcu *mp_napi;
> + bool mp_armed;

The comment should explain why mp_napi != napi? (I do not understand why)