]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: use netdev_queue_config() for mp restart
authorJakub Kicinski <kuba@kernel.org>
Thu, 22 Jan 2026 00:51:11 +0000 (16:51 -0800)
committerJakub Kicinski <kuba@kernel.org>
Fri, 23 Jan 2026 19:49:02 +0000 (11:49 -0800)
We should follow the prepare/commit approach for queue configuration.
The qcfg struct should be added to dev->cfg rather than directly to
queue objects so that we can clone and discard the pending config
easily.

Remove the qcfg in struct netdev_rx_queue, and switch remaining callers
to netdev_queue_config(). netdev_queue_config() will construct the qcfg
on the fly based on device defaults and state of the queue.

ndo_default_qcfg becomes optional because having the callback itself
does not have any meaningful semantics to us.

Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Link: https://patch.msgid.link/20260122005113.2476634-5-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/net/netdev_queues.h
net/core/dev.c
net/core/netdev_config.c
net/core/netdev_rx_queue.c

index 725bf69ef86c140075df2a69a275cab25bacaba0..4b23c3697cc942bae3a5f46e5af46839706c423b 100644 (file)
@@ -139,7 +139,9 @@ enum {
  * @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.
+ * @ndo_default_qcfg:  (Optional) Populate queue config struct with defaults.
+ *                     Queue config structs are passed to this helper before
+ *                     the user-requested settings are applied.
  *
  * @supported_params:  Bitmask of supported parameters, see QCFG_*.
  *
index ec0d0cdfc07870baacbc96919e3c401a977a4bce..43de5af0d6ecd6473e3ceff0e1db99d1aaf5ce5f 100644 (file)
@@ -11282,21 +11282,6 @@ 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
@@ -11342,8 +11327,6 @@ 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 562087bd30c8467a4ea9264cf46d9e32739099d6..48f7634465065049db5994fa4662be8518bf4ca8 100644 (file)
 void netdev_queue_config(struct net_device *dev, int rxq_idx,
                         struct netdev_queue_config *qcfg)
 {
-       struct netdev_queue_config *stored;
+       struct pp_memory_provider_params *mpp;
 
        memset(qcfg, 0, sizeof(*qcfg));
 
-       stored = &__netif_get_rx_queue(dev, rxq_idx)->qcfg;
-       qcfg->rx_page_size = stored->rx_page_size;
+       /* Get defaults from the driver, in case user config not set */
+       if (dev->queue_mgmt_ops->ndo_default_qcfg)
+               dev->queue_mgmt_ops->ndo_default_qcfg(dev, qcfg);
+
+       /* Apply MP overrides */
+       mpp = &__netif_get_rx_queue(dev, rxq_idx)->mp_params;
+       if (mpp->rx_page_size)
+               qcfg->rx_page_size = mpp->rx_page_size;
 }
 EXPORT_SYMBOL(netdev_queue_config);
index 03d7531abb3a8c325a2a81c516207fd7fa182c0c..72374930699a9f3fa9a035ca73ed3b3903cffbd5 100644 (file)
@@ -18,11 +18,13 @@ bool netif_rxq_has_unreadable_mp(struct net_device *dev, int idx)
 }
 EXPORT_SYMBOL(netif_rxq_has_unreadable_mp);
 
-int netdev_rx_queue_restart(struct net_device *dev, unsigned int rxq_idx)
+static int netdev_rx_queue_reconfig(struct net_device *dev,
+                                   unsigned int rxq_idx,
+                                   struct netdev_queue_config *qcfg_old,
+                                   struct netdev_queue_config *qcfg_new)
 {
        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;
 
@@ -30,18 +32,8 @@ int netdev_rx_queue_restart(struct net_device *dev, unsigned int rxq_idx)
            !qops->ndo_queue_mem_alloc || !qops->ndo_queue_start)
                return -EOPNOTSUPP;
 
-       if (WARN_ON_ONCE(qops->supported_params && !qops->ndo_default_qcfg))
-               return -EINVAL;
-
        netdev_assert_locked(dev);
 
-       memset(&qcfg, 0, sizeof(qcfg));
-       if (qops->ndo_default_qcfg)
-               qops->ndo_default_qcfg(dev, &qcfg);
-
-       if (rxq->mp_params.rx_page_size)
-               qcfg.rx_page_size = rxq->mp_params.rx_page_size;
-
        new_mem = kvzalloc(qops->ndo_queue_mem_size, GFP_KERNEL);
        if (!new_mem)
                return -ENOMEM;
@@ -52,7 +44,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, &qcfg, new_mem, rxq_idx);
+       err = qops->ndo_queue_mem_alloc(dev, qcfg_new, new_mem, rxq_idx);
        if (err)
                goto err_free_old_mem;
 
@@ -65,7 +57,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, &qcfg, new_mem, rxq_idx);
+               err = qops->ndo_queue_start(dev, qcfg_new, new_mem, rxq_idx);
                if (err)
                        goto err_start_queue;
        } else {
@@ -77,7 +69,6 @@ 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:
@@ -88,7 +79,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, &rxq->qcfg, old_mem, rxq_idx)) {
+       if (qops->ndo_queue_start(dev, qcfg_old, old_mem, rxq_idx)) {
                WARN(1,
                     "Failed to restart old queue in error path. RX queue %d may be unhealthy.",
                     rxq_idx);
@@ -106,6 +97,14 @@ err_free_new_mem:
 
        return err;
 }
+
+int netdev_rx_queue_restart(struct net_device *dev, unsigned int rxq_idx)
+{
+       struct netdev_queue_config qcfg;
+
+       netdev_queue_config(dev, rxq_idx, &qcfg);
+       return netdev_rx_queue_reconfig(dev, rxq_idx, &qcfg, &qcfg);
+}
 EXPORT_SYMBOL_NS_GPL(netdev_rx_queue_restart, "NETDEV_INTERNAL");
 
 int __net_mp_open_rxq(struct net_device *dev, unsigned int rxq_idx,
@@ -113,6 +112,7 @@ int __net_mp_open_rxq(struct net_device *dev, unsigned int rxq_idx,
                      struct netlink_ext_ack *extack)
 {
        const struct netdev_queue_mgmt_ops *qops = dev->queue_mgmt_ops;
+       struct netdev_queue_config qcfg[2];
        struct netdev_rx_queue *rxq;
        int ret;
 
@@ -154,8 +154,11 @@ int __net_mp_open_rxq(struct net_device *dev, unsigned int rxq_idx,
        }
 #endif
 
+       netdev_queue_config(dev, rxq_idx, &qcfg[0]);
        rxq->mp_params = *p;
-       ret = netdev_rx_queue_restart(dev, rxq_idx);
+       netdev_queue_config(dev, rxq_idx, &qcfg[1]);
+
+       ret = netdev_rx_queue_reconfig(dev, rxq_idx, &qcfg[0], &qcfg[1]);
        if (ret)
                memset(&rxq->mp_params, 0, sizeof(rxq->mp_params));
 
@@ -176,6 +179,7 @@ int net_mp_open_rxq(struct net_device *dev, unsigned int rxq_idx,
 void __net_mp_close_rxq(struct net_device *dev, unsigned int ifq_idx,
                        const struct pp_memory_provider_params *old_p)
 {
+       struct netdev_queue_config qcfg[2];
        struct netdev_rx_queue *rxq;
        int err;
 
@@ -195,8 +199,11 @@ void __net_mp_close_rxq(struct net_device *dev, unsigned int ifq_idx,
                         rxq->mp_params.mp_priv != old_p->mp_priv))
                return;
 
+       netdev_queue_config(dev, ifq_idx, &qcfg[0]);
        memset(&rxq->mp_params, 0, sizeof(rxq->mp_params));
-       err = netdev_rx_queue_restart(dev, ifq_idx);
+       netdev_queue_config(dev, ifq_idx, &qcfg[1]);
+
+       err = netdev_rx_queue_reconfig(dev, ifq_idx, &qcfg[0], &qcfg[1]);
        WARN_ON(err && err != -ENETDOWN);
 }