]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
gve: keep registry of zc xsk pools in netdev_priv
authorJoshua Washington <joshwash@google.com>
Thu, 17 Jul 2025 15:28:37 +0000 (08:28 -0700)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 22 Jul 2025 09:35:49 +0000 (11:35 +0200)
Relying on xsk_get_pool_from_qid for getting whether zero copy is
enabled on a queue is erroneous, as an XSK pool is registered in
xp_assign_dev whether AF_XDP zero-copy is enabled or not. This becomes
problematic when queues are restarted in copy mode, as all RX queues
with XSKs will register a pool, causing the driver to exercise the
zero-copy codepath.

This patch adds a bitmap to keep track of which queues have zero-copy
enabled.

Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Joshua Washington <joshwash@google.com>
Signed-off-by: Jeroen de Borst <jeroendb@google.com>
Link: https://patch.msgid.link/20250717152839.973004-4-jeroendb@google.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/google/gve/gve.h
drivers/net/ethernet/google/gve/gve_main.c

index b2be3fca41253f6d8215e3fa38f35f12325aebf6..9925c08e595eaf61870f330f17b3d12915b91af7 100644 (file)
@@ -802,6 +802,7 @@ struct gve_priv {
 
        struct gve_tx_queue_config tx_cfg;
        struct gve_rx_queue_config rx_cfg;
+       unsigned long *xsk_pools; /* bitmap of RX queues with XSK pools */
        u32 num_ntfy_blks; /* split between TX and RX so must be even */
        int numa_node;
 
index cf8e1abdfa8ef4be3f240d39b9cda88c3497ce48..d5953f5d1895bf33569437fde4b56caa353825a3 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) 2015-2024 Google LLC
  */
 
+#include <linux/bitmap.h>
 #include <linux/bpf.h>
 #include <linux/cpumask.h>
 #include <linux/etherdevice.h>
@@ -1215,6 +1216,14 @@ static void gve_unreg_xdp_info(struct gve_priv *priv)
        }
 }
 
+static struct xsk_buff_pool *gve_get_xsk_pool(struct gve_priv *priv, int qid)
+{
+       if (!test_bit(qid, priv->xsk_pools))
+               return NULL;
+
+       return xsk_get_pool_from_qid(priv->dev, qid);
+}
+
 static int gve_reg_xdp_info(struct gve_priv *priv, struct net_device *dev)
 {
        struct napi_struct *napi;
@@ -1236,7 +1245,7 @@ static int gve_reg_xdp_info(struct gve_priv *priv, struct net_device *dev)
                if (err)
                        goto err;
 
-               xsk_pool = xsk_get_pool_from_qid(dev, i);
+               xsk_pool = gve_get_xsk_pool(priv, i);
                if (xsk_pool)
                        err = gve_reg_xsk_pool(priv, dev, xsk_pool, i);
                else if (gve_is_qpl(priv))
@@ -1588,15 +1597,19 @@ static int gve_xsk_pool_enable(struct net_device *dev,
        if (err)
                return err;
 
+       set_bit(qid, priv->xsk_pools);
+
        /* If XDP prog is not installed or interface is down, return. */
        if (!priv->xdp_prog || !netif_running(dev))
                return 0;
 
        err = gve_reg_xsk_pool(priv, dev, pool, qid);
-       if (err)
+       if (err) {
+               clear_bit(qid, priv->xsk_pools);
                xsk_pool_dma_unmap(pool,
                                   DMA_ATTR_SKIP_CPU_SYNC |
                                   DMA_ATTR_WEAK_ORDERING);
+       }
 
        return err;
 }
@@ -1613,6 +1626,8 @@ static int gve_xsk_pool_disable(struct net_device *dev,
        if (qid >= priv->rx_cfg.num_queues)
                return -EINVAL;
 
+       clear_bit(qid, priv->xsk_pools);
+
        pool = xsk_get_pool_from_qid(dev, qid);
        if (pool)
                xsk_pool_dma_unmap(pool,
@@ -2360,10 +2375,22 @@ static int gve_init_priv(struct gve_priv *priv, bool skip_describe_device)
        priv->ts_config.rx_filter = HWTSTAMP_FILTER_NONE;
 
 setup_device:
+       priv->xsk_pools = bitmap_zalloc(priv->rx_cfg.max_queues, GFP_KERNEL);
+       if (!priv->xsk_pools) {
+               err = -ENOMEM;
+               goto err;
+       }
+
        gve_set_netdev_xdp_features(priv);
        err = gve_setup_device_resources(priv);
-       if (!err)
-               return 0;
+       if (err)
+               goto err_free_xsk_bitmap;
+
+       return 0;
+
+err_free_xsk_bitmap:
+       bitmap_free(priv->xsk_pools);
+       priv->xsk_pools = NULL;
 err:
        gve_adminq_free(&priv->pdev->dev, priv);
        return err;
@@ -2373,6 +2400,8 @@ static void gve_teardown_priv_resources(struct gve_priv *priv)
 {
        gve_teardown_device_resources(priv);
        gve_adminq_free(&priv->pdev->dev, priv);
+       bitmap_free(priv->xsk_pools);
+       priv->xsk_pools = NULL;
 }
 
 static void gve_trigger_reset(struct gve_priv *priv)