On 11/10, Björn Töpel wrote:
quoted hunk ↗ jump to hunk
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@kernel.org>
---
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)