net: add netdev_set_operstate() helper
authorEric Dumazet <edumazet@google.com>
Tue, 13 Feb 2024 06:32:42 +0000 (06:32 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 14 Feb 2024 11:20:13 +0000 (11:20 +0000)
dev_base_lock is going away, add netdev_set_operstate() helper
so that hsr does not have to know core internals.

Remove dev_base_lock acquisition from rfc2863_policy()

v3: use an "unsigned int" for dev->operstate,
    so that try_cmpxchg() can work on all arches.
        ( https://lore.kernel.org/oe-kbuild-all/202402081918.OLyGaea3-lkp@intel.com/ )

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/netdevice.h
include/linux/rtnetlink.h
net/core/link_watch.c
net/core/rtnetlink.c
net/hsr/hsr_device.c

index 6311246551072ba08f1f7f2f5afd79d34d3d7b8e..697370706a82d3501b3586d92ac2a4ab0f18e82f 100644 (file)
@@ -2258,7 +2258,7 @@ struct net_device {
        const struct tlsdev_ops *tlsdev_ops;
 #endif
 
-       unsigned char           operstate;
+       unsigned int            operstate;
        unsigned char           link_mode;
 
        unsigned char           if_port;
index 21780608cf47ca0687dbaaf0d07b561e8631412c..cdfc897f1e3c683940a0958bc8a790c07ae819b0 100644 (file)
@@ -172,4 +172,6 @@ rtnl_notify_needed(const struct net *net, u16 nlflags, u32 group)
        return (nlflags & NLM_F_ECHO) || rtnl_has_listeners(net, group);
 }
 
+void netdev_set_operstate(struct net_device *dev, int newstate);
+
 #endif /* __LINUX_RTNETLINK_H */
index 1b93e054c9a3cfcdd5d1251a9982d88a071abbaa..8ec35194bfcb8574f53a9fd28f0cb2ebfe9a3f2e 100644 (file)
@@ -33,7 +33,7 @@ static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event);
 static LIST_HEAD(lweventlist);
 static DEFINE_SPINLOCK(lweventlist_lock);
 
-static unsigned char default_operstate(const struct net_device *dev)
+static unsigned int default_operstate(const struct net_device *dev)
 {
        if (netif_testing(dev))
                return IF_OPER_TESTING;
@@ -62,16 +62,13 @@ static unsigned char default_operstate(const struct net_device *dev)
        return IF_OPER_UP;
 }
 
-
 static void rfc2863_policy(struct net_device *dev)
 {
-       unsigned char operstate = default_operstate(dev);
+       unsigned int operstate = default_operstate(dev);
 
        if (operstate == READ_ONCE(dev->operstate))
                return;
 
-       write_lock(&dev_base_lock);
-
        switch(dev->link_mode) {
        case IF_LINK_MODE_TESTING:
                if (operstate == IF_OPER_UP)
@@ -88,8 +85,6 @@ static void rfc2863_policy(struct net_device *dev)
        }
 
        WRITE_ONCE(dev->operstate, operstate);
-
-       write_unlock(&dev_base_lock);
 }
 
 
index 43d92de8601cb8cecd5391de88ccf114744603e6..e484ba44f23b2571b774d0f4389500735d4360fd 100644 (file)
@@ -842,9 +842,22 @@ int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id,
 }
 EXPORT_SYMBOL_GPL(rtnl_put_cacheinfo);
 
+void netdev_set_operstate(struct net_device *dev, int newstate)
+{
+       unsigned int old = READ_ONCE(dev->operstate);
+
+       do {
+               if (old == newstate)
+                       return;
+       } while (!try_cmpxchg(&dev->operstate, &old, newstate));
+
+       netdev_state_change(dev);
+}
+EXPORT_SYMBOL(netdev_set_operstate);
+
 static void set_operstate(struct net_device *dev, unsigned char transition)
 {
-       unsigned char operstate = dev->operstate;
+       unsigned char operstate = READ_ONCE(dev->operstate);
 
        switch (transition) {
        case IF_OPER_UP:
@@ -866,12 +879,7 @@ static void set_operstate(struct net_device *dev, unsigned char transition)
                break;
        }
 
-       if (READ_ONCE(dev->operstate) != operstate) {
-               write_lock(&dev_base_lock);
-               WRITE_ONCE(dev->operstate, operstate);
-               write_unlock(&dev_base_lock);
-               netdev_state_change(dev);
-       }
+       netdev_set_operstate(dev, operstate);
 }
 
 static unsigned int rtnl_dev_get_flags(const struct net_device *dev)
index be0e43f46556e028e675147e63c6b787aa72e894..5ef6d437db727e60bfd8cf68f010f0151d0db98b 100644 (file)
@@ -28,29 +28,19 @@ static bool is_slave_up(struct net_device *dev)
        return dev && is_admin_up(dev) && netif_oper_up(dev);
 }
 
-static void __hsr_set_operstate(struct net_device *dev, int transition)
-{
-       write_lock(&dev_base_lock);
-       if (READ_ONCE(dev->operstate) != transition) {
-               WRITE_ONCE(dev->operstate, transition);
-               write_unlock(&dev_base_lock);
-               netdev_state_change(dev);
-       } else {
-               write_unlock(&dev_base_lock);
-       }
-}
-
 static void hsr_set_operstate(struct hsr_port *master, bool has_carrier)
 {
-       if (!is_admin_up(master->dev)) {
-               __hsr_set_operstate(master->dev, IF_OPER_DOWN);
+       struct net_device *dev = master->dev;
+
+       if (!is_admin_up(dev)) {
+               netdev_set_operstate(dev, IF_OPER_DOWN);
                return;
        }
 
        if (has_carrier)
-               __hsr_set_operstate(master->dev, IF_OPER_UP);
+               netdev_set_operstate(dev, IF_OPER_UP);
        else
-               __hsr_set_operstate(master->dev, IF_OPER_LOWERLAYERDOWN);
+               netdev_set_operstate(dev, IF_OPER_LOWERLAYERDOWN);
 }
 
 static bool hsr_check_carrier(struct hsr_port *master)