RE: [PATCH iwl-next v2 2/2] idpf: use GFP_KERNEL for the initial Rx ring fill

From: Loktionov, Aleksandr

Date: Wed Oct 21 2026 - 06:48:25 EST




> -----Original Message-----
> From: Luigi Rizzo <lrizzo@xxxxxxxxxx>
> Sent: Monday, October 19, 2026 11:06 PM
> To: intel-wired-lan@xxxxxxxxxxxxxxxx
> Cc: netdev@xxxxxxxxxxxxxxx; Nguyen, Anthony L
> <anthony.l.nguyen@xxxxxxxxx>; Kitszel, Przemyslaw
> <przemyslaw.kitszel@xxxxxxxxx>; Lobakin, Aleksander
> <aleksander.lobakin@xxxxxxxxx>; Andrew Lunn <andrew+netdev@xxxxxxx>;
> David S . Miller <davem@xxxxxxxxxxxxx>; Eric Dumazet
> <edumazet@xxxxxxxxxx>; Luigi Rizzo <rizzo.unipi@xxxxxxxxx>; Brian
> Vazquez <brianvv@xxxxxxxxxx>; Hay, Joshua A <joshua.a.hay@xxxxxxxxx>;
> Zaremba, Larysa <larysa.zaremba@xxxxxxxxx>; Jakub Kicinski
> <kuba@xxxxxxxxxx>; Paolo Abeni <pabeni@xxxxxxxxxx>; Simon Horman
> <horms@xxxxxxxxxx>; linux-kernel@xxxxxxxxxxxxxxx; Luigi Rizzo
> <lrizzo@xxxxxxxxxx>
> Subject: [PATCH iwl-next v2 2/2] idpf: use GFP_KERNEL for the initial Rx
> ring fill
>
> When idpf fills its Rx rings at open or on queue reconfiguration, the
> allocation runs in process context, right after page_pool_create() and
> before the queues' NAPI is enabled. Allocating tens of thousands of
> buffers across all queues with GFP_ATOMIC is needlessly restrictive when
> the caller may sleep.
>
> In splitq mode, idpf_rx_post_buf_desc() is only used for this initial
> fill, so switch its header and payload allocations to
> libeth_rx_alloc_gfp(..., GFP_KERNEL).
>
> In singleq mode, add a gfp_t parameter to
> idpf_rx_singleq_buf_hw_alloc_all() and pass GFP_KERNEL from
> idpf_rx_buf_alloc_singleq() and GFP_ATOMIC from idpf_rx_singleq_clean().
>
> Signed-off-by: Luigi Rizzo <lrizzo@xxxxxxxxxx>
> ---
> drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c | 7 ++++---
> drivers/net/ethernet/intel/idpf/idpf_txrx.c | 9 ++++++---
> drivers/net/ethernet/intel/idpf/idpf_txrx.h | 2 +-
> 3 files changed, 11 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c
> b/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c
> index e3ddf18dcbf51..d623e4ab8511f 100644
> --- a/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c
> +++ b/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c
> @@ -885,11 +885,12 @@ static void idpf_rx_buf_hw_update(struct
> idpf_rx_queue *rxq, u32 val)
> * idpf_rx_singleq_buf_hw_alloc_all - Replace used receive buffers
> * @rx_q: queue for which the hw buffers are allocated
> * @cleaned_count: number of buffers to replace
> + * @gfp: GFP_KERNEL for the initial fill, GFP_ATOMIC from NAPI
> *
> * Returns false if all allocations were successful, true if any fail
> */
> bool idpf_rx_singleq_buf_hw_alloc_all(struct idpf_rx_queue *rx_q,
> - u16 cleaned_count)
> + u16 cleaned_count, gfp_t gfp)
> {
> struct virtchnl2_singleq_rx_buf_desc *desc;
> const struct libeth_fq_fp fq = {
> @@ -908,7 +909,7 @@ bool idpf_rx_singleq_buf_hw_alloc_all(struct
> idpf_rx_queue *rx_q,
> do {
> dma_addr_t addr;
>
> - addr = libeth_rx_alloc(&fq, nta);
> + addr = libeth_rx_alloc_gfp(&fq, nta, gfp);
> if (addr == DMA_MAPPING_ERROR)
> break;
>
> @@ -1095,7 +1096,7 @@ static int idpf_rx_singleq_clean(struct
> idpf_rx_queue *rx_q, int budget)
>
> page_pool_nid_changed(rx_q->pp, numa_mem_id());
> if (cleaned_count)
> - idpf_rx_singleq_buf_hw_alloc_all(rx_q, cleaned_count);
> + idpf_rx_singleq_buf_hw_alloc_all(rx_q, cleaned_count,
> GFP_ATOMIC);
>
> u64_stats_update_begin(&rx_q->stats_sync);
> u64_stats_add(&rx_q->q_stats.packets, rs.packets); diff --git
> a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
> b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
> index 4311ffa30bb18..b1127ab48ef3f 100644
> --- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
> +++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
> @@ -600,6 +600,9 @@ static void idpf_post_buf_refill(struct
> idpf_sw_queue *refillq, u16 buf_id)
> * @bufq: buffer queue to post to
> * @buf_id: buffer id to post
> *
> + * Only used for the initial fill, from process context, so it
> + allocates
> + * with GFP_KERNEL.
> + *
> * Return: %false if buffer could not be allocated, %true otherwise.
> */
> static bool idpf_rx_post_buf_desc(struct idpf_buf_queue *bufq, u16
> buf_id) @@ -618,7 +621,7 @@ static bool idpf_rx_post_buf_desc(struct
> idpf_buf_queue *bufq, u16 buf_id)
> fq.fqes = bufq->hdr_buf;
> fq.truesize = bufq->hdr_truesize;
>
> - addr = libeth_rx_alloc(&fq, buf_id);
> + addr = libeth_rx_alloc_gfp(&fq, buf_id, GFP_KERNEL);
> if (addr == DMA_MAPPING_ERROR)
> return false;
>
> @@ -629,7 +632,7 @@ static bool idpf_rx_post_buf_desc(struct
> idpf_buf_queue *bufq, u16 buf_id)
> fq.fqes = bufq->buf;
> fq.truesize = bufq->truesize;
>
> - addr = libeth_rx_alloc(&fq, buf_id);
> + addr = libeth_rx_alloc_gfp(&fq, buf_id, GFP_KERNEL);
> if (addr == DMA_MAPPING_ERROR)
> return false;
>
> @@ -675,7 +678,7 @@ static bool idpf_rx_post_init_bufs(struct
> idpf_buf_queue *bufq,
> */
> static int idpf_rx_buf_alloc_singleq(struct idpf_rx_queue *rxq) {
> - if (idpf_rx_singleq_buf_hw_alloc_all(rxq, rxq->desc_count - 1))
> + if (idpf_rx_singleq_buf_hw_alloc_all(rxq, rxq->desc_count - 1,
> +GFP_KERNEL))
> goto err;
>
> return 0;
> diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.h
> b/drivers/net/ethernet/intel/idpf/idpf_txrx.h
> index 93547597efd2a..e27438c78ec79 100644
> --- a/drivers/net/ethernet/intel/idpf/idpf_txrx.h
> +++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.h
> @@ -1123,7 +1123,7 @@ netdev_tx_t idpf_tx_singleq_frame(struct sk_buff
> *skb,
> struct idpf_tx_queue *tx_q);
> netdev_tx_t idpf_tx_start(struct sk_buff *skb, struct net_device
> *netdev); bool idpf_rx_singleq_buf_hw_alloc_all(struct idpf_rx_queue
> *rxq,
> - u16 cleaned_count);
> + u16 cleaned_count, gfp_t gfp);
> bool idpf_rx_process_skb_fields(struct sk_buff *skb,
> const struct libeth_xdp_buff *xdp,
> struct libeth_rq_napi_stats *rs);
> --
> 2.56.0.212.g129ede20d9-goog

Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@xxxxxxxxx>