]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: add bare bone queue configs
authorPavel Begunkov <asml.silence@gmail.com>
Tue, 6 Jan 2026 13:25:40 +0000 (13:25 +0000)
committerPavel Begunkov <asml.silence@gmail.com>
Wed, 14 Jan 2026 02:13:36 +0000 (02:13 +0000)
We'll need to pass extra parameters when allocating a queue for memory
providers. Define a new structure for queue configurations, and pass it
to qapi callbacks. It's empty for now, actual parameters will be added
in following patches.

Configurations should persist across resets, and for that they're
default-initialised on device registration and stored in struct
netdev_rx_queue. We also add a new qapi callback for defaulting a given
config. It must be implemented if a driver wants to use queue configs
and is optional otherwise.

Suggested-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/google/gve/gve_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
drivers/net/netdevsim/netdev.c
include/net/netdev_queues.h
include/net/netdev_rx_queue.h
net/core/dev.c
net/core/netdev_rx_queue.c

index 8419d1eb4035dc1faef32f7fec6e7d440016adaf..a0abe991f79a6dd7898d3b881ae966ac4bfe4412 100644 (file)
@@ -15911,7 +15911,9 @@ static const struct netdev_stat_ops bnxt_stat_ops = {
        .get_base_stats         = bnxt_get_base_stats,
 };
 
-static int bnxt_queue_mem_alloc(struct net_device *dev, void *qmem, int idx)
+static int bnxt_queue_mem_alloc(struct net_device *dev,
+                               struct netdev_queue_config *qcfg,
+                               void *qmem, int idx)
 {
        struct bnxt_rx_ring_info *rxr, *clone;
        struct bnxt *bp = netdev_priv(dev);
@@ -16077,7 +16079,9 @@ static void bnxt_copy_rx_ring(struct bnxt *bp,
        dst->rx_agg_bmap = src->rx_agg_bmap;
 }
 
-static int bnxt_queue_start(struct net_device *dev, void *qmem, int idx)
+static int bnxt_queue_start(struct net_device *dev,
+                           struct netdev_queue_config *qcfg,
+                           void *qmem, int idx)
 {
        struct bnxt *bp = netdev_priv(dev);
        struct bnxt_rx_ring_info *rxr, *clone;
index 7eb64e1e4d858bb9cff0431703d8b4fd97104db5..c42640da15a5a918cb4e802c23a4fd6818cdb526 100644 (file)
@@ -2616,8 +2616,9 @@ static void gve_rx_queue_mem_free(struct net_device *dev, void *per_q_mem)
                gve_rx_free_ring_dqo(priv, gve_per_q_mem, &cfg);
 }
 
-static int gve_rx_queue_mem_alloc(struct net_device *dev, void *per_q_mem,
-                                 int idx)
+static int gve_rx_queue_mem_alloc(struct net_device *dev,
+                                 struct netdev_queue_config *qcfg,
+                                 void *per_q_mem, int idx)
 {
        struct gve_priv *priv = netdev_priv(dev);
        struct gve_rx_alloc_rings_cfg cfg = {0};
@@ -2638,7 +2639,9 @@ static int gve_rx_queue_mem_alloc(struct net_device *dev, void *per_q_mem,
        return err;
 }
 
-static int gve_rx_queue_start(struct net_device *dev, void *per_q_mem, int idx)
+static int gve_rx_queue_start(struct net_device *dev,
+                             struct netdev_queue_config *qcfg,
+                             void *per_q_mem, int idx)
 {
        struct gve_priv *priv = netdev_priv(dev);
        struct gve_rx_ring *gve_per_q_mem;
index 07fc4d2c8fadd420d4646eba8a1a730a974cca52..0e2132b5825778b46b2abd6bb5b4ff4f901763ab 100644 (file)
@@ -5596,8 +5596,9 @@ struct mlx5_qmgmt_data {
        struct mlx5e_channel_param cparam;
 };
 
-static int mlx5e_queue_mem_alloc(struct net_device *dev, void *newq,
-                                int queue_index)
+static int mlx5e_queue_mem_alloc(struct net_device *dev,
+                                struct netdev_queue_config *qcfg,
+                                void *newq, int queue_index)
 {
        struct mlx5_qmgmt_data *new = (struct mlx5_qmgmt_data *)newq;
        struct mlx5e_priv *priv = netdev_priv(dev);
@@ -5658,8 +5659,9 @@ static int mlx5e_queue_stop(struct net_device *dev, void *oldq, int queue_index)
        return 0;
 }
 
-static int mlx5e_queue_start(struct net_device *dev, void *newq,
-                            int queue_index)
+static int mlx5e_queue_start(struct net_device *dev,
+                            struct netdev_queue_config *qcfg,
+                            void *newq, int queue_index)
 {
        struct mlx5_qmgmt_data *new = (struct mlx5_qmgmt_data *)newq;
        struct mlx5e_priv *priv = netdev_priv(dev);
index 13d508ce637f10dff44f436fa92e839aaf75d24e..e36ed25462b481f56dc49ce87f8165369911fe34 100644 (file)
@@ -2809,7 +2809,9 @@ void fbnic_napi_depletion_check(struct net_device *netdev)
        fbnic_wrfl(fbd);
 }
 
-static int fbnic_queue_mem_alloc(struct net_device *dev, void *qmem, int idx)
+static int fbnic_queue_mem_alloc(struct net_device *dev,
+                                struct netdev_queue_config *qcfg,
+                                void *qmem, int idx)
 {
        struct fbnic_net *fbn = netdev_priv(dev);
        const struct fbnic_q_triad *real;
@@ -2861,7 +2863,9 @@ static void __fbnic_nv_restart(struct fbnic_net *fbn,
                netif_wake_subqueue(fbn->netdev, nv->qt[i].sub0.q_idx);
 }
 
-static int fbnic_queue_start(struct net_device *dev, void *qmem, int idx)
+static int fbnic_queue_start(struct net_device *dev,
+                            struct netdev_queue_config *qcfg,
+                            void *qmem, int idx)
 {
        struct fbnic_net *fbn = netdev_priv(dev);
        struct fbnic_napi_vector *nv;
index 6927c1962277aa916ae646f4235f8ab58ec40e21..6285fbefe38af369666bcbc14c7f309ab3653887 100644 (file)
@@ -758,7 +758,9 @@ struct nsim_queue_mem {
 };
 
 static int
-nsim_queue_mem_alloc(struct net_device *dev, void *per_queue_mem, int idx)
+nsim_queue_mem_alloc(struct net_device *dev,
+                    struct netdev_queue_config *qcfg,
+                    void *per_queue_mem, int idx)
 {
        struct nsim_queue_mem *qmem = per_queue_mem;
        struct netdevsim *ns = netdev_priv(dev);
@@ -807,7 +809,8 @@ static void nsim_queue_mem_free(struct net_device *dev, void *per_queue_mem)
 }
 
 static int
-nsim_queue_start(struct net_device *dev, void *per_queue_mem, int idx)
+nsim_queue_start(struct net_device *dev, struct netdev_queue_config *qcfg,
+                void *per_queue_mem, int idx)
 {
        struct nsim_queue_mem *qmem = per_queue_mem;
        struct netdevsim *ns = netdev_priv(dev);
index 541e7d9853b1bc6710e9708a4b84cc8eb2914d22..f6f1f71a24e157400dd4c0609a8f055e0d1c912a 100644 (file)
@@ -14,6 +14,9 @@ struct netdev_config {
        u8      hds_config;
 };
 
+struct netdev_queue_config {
+};
+
 /* See the netdev.yaml spec for definition of each statistic */
 struct netdev_queue_stats_rx {
        u64 bytes;
@@ -130,6 +133,8 @@ void netdev_stat_queue_sum(struct net_device *netdev,
  * @ndo_queue_get_dma_dev: Get dma device for zero-copy operations to be used
  *                        for this queue. Return NULL on error.
  *
+ * @ndo_default_qcfg:  Populate queue config struct with defaults. Optional.
+ *
  * Note that @ndo_queue_mem_alloc and @ndo_queue_mem_free may be called while
  * the interface is closed. @ndo_queue_start and @ndo_queue_stop will only
  * be called for an interface which is open.
@@ -137,16 +142,20 @@ void netdev_stat_queue_sum(struct net_device *netdev,
 struct netdev_queue_mgmt_ops {
        size_t  ndo_queue_mem_size;
        int     (*ndo_queue_mem_alloc)(struct net_device *dev,
+                                      struct netdev_queue_config *qcfg,
                                       void *per_queue_mem,
                                       int idx);
        void    (*ndo_queue_mem_free)(struct net_device *dev,
                                      void *per_queue_mem);
        int     (*ndo_queue_start)(struct net_device *dev,
+                                  struct netdev_queue_config *qcfg,
                                   void *per_queue_mem,
                                   int idx);
        int     (*ndo_queue_stop)(struct net_device *dev,
                                  void *per_queue_mem,
                                  int idx);
+       void    (*ndo_default_qcfg)(struct net_device *dev,
+                                   struct netdev_queue_config *qcfg);
        struct device * (*ndo_queue_get_dma_dev)(struct net_device *dev,
                                                 int idx);
 };
index 8cdcd138b33f2d713a34c2886eae388da42be22e..cfa72c4853876c6fcb84b5c551580d9205f7b29d 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/sysfs.h>
 #include <net/xdp.h>
 #include <net/page_pool/types.h>
+#include <net/netdev_queues.h>
 
 /* This structure contains an instance of an RX queue. */
 struct netdev_rx_queue {
@@ -27,6 +28,7 @@ struct netdev_rx_queue {
        struct xsk_buff_pool            *pool;
 #endif
        struct napi_struct              *napi;
+       struct netdev_queue_config      qcfg;
        struct pp_memory_provider_params mp_params;
 } ____cacheline_aligned_in_smp;
 
index 36dc5199037edb1506e67f6ab5e977ff41efef59..a1d394addaeffc59fe48a2efc32023ec005fdf26 100644 (file)
@@ -11270,6 +11270,21 @@ static void netdev_free_phy_link_topology(struct net_device *dev)
        }
 }
 
+static void init_rx_queue_cfgs(struct net_device *dev)
+{
+       const struct netdev_queue_mgmt_ops *qops = dev->queue_mgmt_ops;
+       struct netdev_rx_queue *rxq;
+       int i;
+
+       if (!qops || !qops->ndo_default_qcfg)
+               return;
+
+       for (i = 0; i < dev->num_rx_queues; i++) {
+               rxq = __netif_get_rx_queue(dev, i);
+               qops->ndo_default_qcfg(dev, &rxq->qcfg);
+       }
+}
+
 /**
  * register_netdevice() - register a network device
  * @dev: device to register
@@ -11315,6 +11330,8 @@ int register_netdevice(struct net_device *dev)
        if (!dev->name_node)
                goto out;
 
+       init_rx_queue_cfgs(dev);
+
        /* Init, if this function is available */
        if (dev->netdev_ops->ndo_init) {
                ret = dev->netdev_ops->ndo_init(dev);
index a0083f176a9cc5cec7964766a05878bfff77dff9..86d1c0a925e3751861d7b261a7296ed7d24698e0 100644 (file)
@@ -22,6 +22,7 @@ int netdev_rx_queue_restart(struct net_device *dev, unsigned int rxq_idx)
 {
        struct netdev_rx_queue *rxq = __netif_get_rx_queue(dev, rxq_idx);
        const struct netdev_queue_mgmt_ops *qops = dev->queue_mgmt_ops;
+       struct netdev_queue_config qcfg;
        void *new_mem, *old_mem;
        int err;
 
@@ -31,6 +32,10 @@ int netdev_rx_queue_restart(struct net_device *dev, unsigned int rxq_idx)
 
        netdev_assert_locked(dev);
 
+       memset(&qcfg, 0, sizeof(qcfg));
+       if (qops->ndo_default_qcfg)
+               qops->ndo_default_qcfg(dev, &qcfg);
+
        new_mem = kvzalloc(qops->ndo_queue_mem_size, GFP_KERNEL);
        if (!new_mem)
                return -ENOMEM;
@@ -41,7 +46,7 @@ int netdev_rx_queue_restart(struct net_device *dev, unsigned int rxq_idx)
                goto err_free_new_mem;
        }
 
-       err = qops->ndo_queue_mem_alloc(dev, new_mem, rxq_idx);
+       err = qops->ndo_queue_mem_alloc(dev, &qcfg, new_mem, rxq_idx);
        if (err)
                goto err_free_old_mem;
 
@@ -54,7 +59,7 @@ int netdev_rx_queue_restart(struct net_device *dev, unsigned int rxq_idx)
                if (err)
                        goto err_free_new_queue_mem;
 
-               err = qops->ndo_queue_start(dev, new_mem, rxq_idx);
+               err = qops->ndo_queue_start(dev, &qcfg, new_mem, rxq_idx);
                if (err)
                        goto err_start_queue;
        } else {
@@ -66,6 +71,7 @@ int netdev_rx_queue_restart(struct net_device *dev, unsigned int rxq_idx)
        kvfree(old_mem);
        kvfree(new_mem);
 
+       rxq->qcfg = qcfg;
        return 0;
 
 err_start_queue:
@@ -76,7 +82,7 @@ err_start_queue:
         * WARN if we fail to recover the old rx queue, and at least free
         * old_mem so we don't also leak that.
         */
-       if (qops->ndo_queue_start(dev, old_mem, rxq_idx)) {
+       if (qops->ndo_queue_start(dev, &rxq->qcfg, old_mem, rxq_idx)) {
                WARN(1,
                     "Failed to restart old queue in error path. RX queue %d may be unhealthy.",
                     rxq_idx);