[PATCH net-next v4 1/5] net: Add netdev_config helpers
From: Björn Töpel <bjorn@kernel.org>
Date: 2026-09-25 10:44:32
Also in:
linux-kselftest, lkml
Subsystem:
networking [ethtool], networking [general], the rest · Maintainers:
Andrew Lunn, Jakub Kicinski, "David S. Miller", Eric Dumazet, Paolo Abeni, Linus Torvalds
From: Jakub Kicinski <kuba@kernel.org> 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: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Björn Töpel <bjorn@kernel.org> Reviewed-by: Breno Leitao <leitao@debian.org> --- net/core/dev.c | 7 ++----- net/core/dev.h | 5 +++++ net/core/netdev_config.c | 37 +++++++++++++++++++++++++++++++++++++ net/ethtool/netlink.c | 15 +++++++-------- 4 files changed, 51 insertions(+), 13 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index f660fccfc0db..9f4441624350 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c@@ -12206,10 +12206,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));
@@ -12281,8 +12279,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);
diff --git a/net/core/dev.h b/net/core/dev.h
index 04fb0e9a571e..6d8dbf556269 100644
--- a/net/core/dev.h
+++ b/net/core/dev.h@@ -102,6 +102,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);
diff --git a/net/core/netdev_config.c b/net/core/netdev_config.c
index f14af365d5cd..b101341e3251 100644
--- a/net/core/netdev_config.c
+++ b/net/core/netdev_config.c@@ -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)
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 1af395b54330..383e911f50f7 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c@@ -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();
--
2.55.0