net: provide pending ring configuration in net_device

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>
This commit is contained in:
Jakub Kicinski 2025-01-18 18:05:13 -08:00
parent 743dea746e
commit 32ad1f7a05
4 changed files with 29 additions and 8 deletions

View 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 */

View 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);

View 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);

View 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;
}