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_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 <[email protected]>
---
 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..ab5a1e20a37ce 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(&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 885df6294ad94..0da095738d8d8 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
@@ -599,6 +599,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)
@@ -617,7 +620,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(&fq, buf_id, GFP_KERNEL);
                if (addr == DMA_MAPPING_ERROR)
                        return false;
 
@@ -628,7 +631,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(&fq, buf_id, GFP_KERNEL);
        if (addr == DMA_MAPPING_ERROR)
                return false;
 
@@ -674,7 +677,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 fe0c913f9bb95..82f0a63f23c34 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.h
+++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.h
@@ -1129,7 +1129,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.385.gac671c819a-goog

Reply via email to