From: Jakub Kicinski <[email protected]>

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 <[email protected]>
Signed-off-by: Björn Töpel <[email protected]>
---
 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 290e0f099e6b..4a7c5a5e48e5 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -12195,10 +12195,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));
@@ -12270,8 +12268,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 b757faead4d1..4b52ff779cba 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


Reply via email to