net: Add netdev_config helpers

netdev_config manipulation will become slightly more complicated
soon and will be used by both ethtool and the queue API.
Encapsulate the logic in helper functions.

Signed-off-by: Björn Töpel <bjorn@kernel.org>
Reviewed-by: Breno Leitao <leitao@debian.org>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Joe Damato <joe@dama.to>
Link: https://patch.msgid.link/20260925104417.2325213-2-bjorn@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-09-25 12:44:08 +02:00
parent aa65d37326
commit c978ff0f1e
4 changed files with 51 additions and 13 deletions

View File

@ -12243,10 +12243,8 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
if (!dev->ethtool)
goto free_all;
dev->cfg = kzalloc_obj(*dev->cfg, GFP_KERNEL_ACCOUNT);
if (!dev->cfg)
if (netdev_alloc_config(dev))
goto free_all;
dev->cfg_pending = dev->cfg;
dev->num_napi_configs = maxqs;
napi_config_sz = array_size(maxqs, sizeof(*dev->napi_config));
@ -12318,8 +12316,7 @@ void free_netdev(struct net_device *dev)
return;
}
WARN_ON(dev->cfg != dev->cfg_pending);
kfree(dev->cfg);
netdev_free_config(dev);
kfree(dev->ethtool);
netif_free_tx_queues(dev);
netif_free_rx_queues(dev);

View File

@ -104,6 +104,11 @@ extern struct rw_semaphore dev_addr_sem;
extern struct list_head net_todo_list;
void netdev_run_todo(void);
int netdev_alloc_config(struct net_device *dev);
void __netdev_free_config(struct netdev_config *cfg);
void netdev_free_config(struct net_device *dev);
int netdev_reconfig_start(struct net_device *dev);
int netdev_queue_config_validate(struct net_device *dev, int rxq_idx,
struct netdev_queue_config *qcfg,
struct netlink_ext_ack *extack);

View File

@ -6,6 +6,43 @@
#include "dev.h"
int netdev_alloc_config(struct net_device *dev)
{
struct netdev_config *cfg;
cfg = kzalloc_obj(*dev->cfg, GFP_KERNEL_ACCOUNT);
if (!cfg)
return -ENOMEM;
dev->cfg = cfg;
dev->cfg_pending = cfg;
return 0;
}
void __netdev_free_config(struct netdev_config *cfg)
{
kfree(cfg);
}
void netdev_free_config(struct net_device *dev)
{
WARN_ON(dev->cfg != dev->cfg_pending);
__netdev_free_config(dev->cfg);
}
int netdev_reconfig_start(struct net_device *dev)
{
struct netdev_config *cfg;
WARN_ON(dev->cfg != dev->cfg_pending);
cfg = kmemdup(dev->cfg, sizeof(*dev->cfg), GFP_KERNEL_ACCOUNT);
if (!cfg)
return -ENOMEM;
dev->cfg_pending = cfg;
return 0;
}
static int netdev_nop_validate_qcfg(struct net_device *dev,
struct netdev_queue_config *qcfg,
struct netlink_ext_ack *extack)

View File

@ -11,6 +11,8 @@
#include "module_fw.h"
#include "netlink.h"
#include "../core/dev.h"
static struct genl_family ethtool_genl_family;
static bool ethnl_ok __read_mostly;
@ -934,12 +936,9 @@ static int ethnl_default_set_doit(struct sk_buff *skb, struct genl_info *info)
if (need_rtnl)
rtnl_lock();
netdev_lock_ops(dev);
dev->cfg_pending = kmemdup(dev->cfg, sizeof(*dev->cfg),
GFP_KERNEL_ACCOUNT);
if (!dev->cfg_pending) {
ret = -ENOMEM;
goto out_tie_cfg;
}
ret = netdev_reconfig_start(dev);
if (ret)
goto out_unlock;
ret = ethnl_ops_begin(dev);
if (ret < 0)
@ -958,9 +957,9 @@ static int ethnl_default_set_doit(struct sk_buff *skb, struct genl_info *info)
out_ops:
ethnl_ops_complete(dev);
out_free_cfg:
kfree(dev->cfg_pending);
out_tie_cfg:
__netdev_free_config(dev->cfg_pending);
dev->cfg_pending = dev->cfg;
out_unlock:
netdev_unlock_ops(dev);
if (need_rtnl)
rtnl_unlock();