]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
net: provide pending ring configuration in net_device
authorJakub Kicinski <kuba@kernel.org>
Sun, 19 Jan 2025 02:05:13 +0000 (18:05 -0800)
committerJakub Kicinski <kuba@kernel.org>
Mon, 20 Jan 2025 19:44:57 +0000 (11:44 -0800)
Record the pending configuration in net_device struct.
ethtool core duplicates the current config and the specific
handlers (for now just ringparam) can modify it.

Reviewed-by: Michael Chan <michael.chan@broadcom.com>
Link: https://patch.msgid.link/20250119020518.1962249-4-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/linux/netdevice.h
net/core/dev.c
net/ethtool/netlink.c
net/ethtool/rings.c

index 173a8b3a9eb2e3c386f0c5fc3b7accdd76554c7b..8da4c61f97b970a0f552e9cbdf1a42b4ff8b5f51 100644 (file)
@@ -2413,6 +2413,12 @@ struct net_device {
 
        /** @cfg: net_device queue-related configuration */
        struct netdev_config    *cfg;
+       /**
+        * @cfg_pending: same as @cfg but when device is being actively
+        *      reconfigured includes any changes to the configuration
+        *      requested by the user, but which may or may not be rejected.
+        */
+       struct netdev_config    *cfg_pending;
        struct ethtool_netdev_state *ethtool;
 
        /* protected by rtnl_lock */
index e37d47cf476b8b31df958d9d8112b1fd4d07a110..afa2282f2604353ad65f78c12da9902e9de0931e 100644 (file)
@@ -11546,6 +11546,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
        dev->cfg = kzalloc(sizeof(*dev->cfg), GFP_KERNEL_ACCOUNT);
        if (!dev->cfg)
                goto free_all;
+       dev->cfg_pending = dev->cfg;
 
        napi_config_sz = array_size(maxqs, sizeof(*dev->napi_config));
        dev->napi_config = kvzalloc(napi_config_sz, GFP_KERNEL_ACCOUNT);
@@ -11615,6 +11616,7 @@ void free_netdev(struct net_device *dev)
                return;
        }
 
+       WARN_ON(dev->cfg != dev->cfg_pending);
        kfree(dev->cfg);
        kfree(dev->ethtool);
        netif_free_tx_queues(dev);
index c17d8513d4c1f08961634878afaf5480fa2a65ad..1d2f62ef61306ba8626f29ba9d3c12463eae773e 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
+#include <net/netdev_queues.h>
 #include <net/sock.h>
 #include <linux/ethtool_netlink.h>
 #include <linux/phy_link_topology.h>
@@ -692,19 +693,33 @@ static int ethnl_default_set_doit(struct sk_buff *skb, struct genl_info *info)
        dev = req_info.dev;
 
        rtnl_lock();
+       dev->cfg_pending = kmemdup(dev->cfg, sizeof(*dev->cfg),
+                                  GFP_KERNEL_ACCOUNT);
+       if (!dev->cfg_pending) {
+               ret = -ENOMEM;
+               goto out_tie_cfg;
+       }
+
        ret = ethnl_ops_begin(dev);
        if (ret < 0)
-               goto out_rtnl;
+               goto out_free_cfg;
 
        ret = ops->set(&req_info, info);
-       if (ret <= 0)
+       if (ret < 0)
+               goto out_ops;
+
+       swap(dev->cfg, dev->cfg_pending);
+       if (!ret)
                goto out_ops;
        ethtool_notify(dev, ops->set_ntf_cmd, NULL);
 
        ret = 0;
 out_ops:
        ethnl_ops_complete(dev);
-out_rtnl:
+out_free_cfg:
+       kfree(dev->cfg_pending);
+out_tie_cfg:
+       dev->cfg_pending = dev->cfg;
        rtnl_unlock();
 out_dev:
        ethnl_parse_header_dev_put(&req_info);
index 7a3c2a2dff12c38c123158cafae53b8d018efcc2..5e8ba81fbb3e469275b740240b1ea9ddda7bb0c0 100644 (file)
@@ -294,13 +294,11 @@ ethnl_set_rings(struct ethnl_req_info *req_info, struct genl_info *info)
                return -EINVAL;
        }
 
+       dev->cfg_pending->hds_config = kernel_ringparam.tcp_data_split;
+       dev->cfg_pending->hds_thresh = kernel_ringparam.hds_thresh;
+
        ret = dev->ethtool_ops->set_ringparam(dev, &ringparam,
                                              &kernel_ringparam, info->extack);
-       if (!ret) {
-               dev->cfg->hds_config = kernel_ringparam.tcp_data_split;
-               dev->cfg->hds_thresh = kernel_ringparam.hds_thresh;
-       }
-
        return ret < 0 ? ret : 1;
 }