Commit 6a2968ee authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

net: add netdev_set_operstate() helper

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: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 328771de
...@@ -2258,7 +2258,7 @@ struct net_device { ...@@ -2258,7 +2258,7 @@ struct net_device {
const struct tlsdev_ops *tlsdev_ops; const struct tlsdev_ops *tlsdev_ops;
#endif #endif
unsigned char operstate; unsigned int operstate;
unsigned char link_mode; unsigned char link_mode;
unsigned char if_port; unsigned char if_port;
......
...@@ -172,4 +172,6 @@ rtnl_notify_needed(const struct net *net, u16 nlflags, u32 group) ...@@ -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); return (nlflags & NLM_F_ECHO) || rtnl_has_listeners(net, group);
} }
void netdev_set_operstate(struct net_device *dev, int newstate);
#endif /* __LINUX_RTNETLINK_H */ #endif /* __LINUX_RTNETLINK_H */
...@@ -33,7 +33,7 @@ static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event); ...@@ -33,7 +33,7 @@ static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event);
static LIST_HEAD(lweventlist); static LIST_HEAD(lweventlist);
static DEFINE_SPINLOCK(lweventlist_lock); 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)) if (netif_testing(dev))
return IF_OPER_TESTING; return IF_OPER_TESTING;
...@@ -62,16 +62,13 @@ static unsigned char default_operstate(const struct net_device *dev) ...@@ -62,16 +62,13 @@ static unsigned char default_operstate(const struct net_device *dev)
return IF_OPER_UP; return IF_OPER_UP;
} }
static void rfc2863_policy(struct net_device *dev) 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)) if (operstate == READ_ONCE(dev->operstate))
return; return;
write_lock(&dev_base_lock);
switch(dev->link_mode) { switch(dev->link_mode) {
case IF_LINK_MODE_TESTING: case IF_LINK_MODE_TESTING:
if (operstate == IF_OPER_UP) if (operstate == IF_OPER_UP)
...@@ -88,8 +85,6 @@ static void rfc2863_policy(struct net_device *dev) ...@@ -88,8 +85,6 @@ static void rfc2863_policy(struct net_device *dev)
} }
WRITE_ONCE(dev->operstate, operstate); WRITE_ONCE(dev->operstate, operstate);
write_unlock(&dev_base_lock);
} }
......
...@@ -842,9 +842,22 @@ int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id, ...@@ -842,9 +842,22 @@ int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id,
} }
EXPORT_SYMBOL_GPL(rtnl_put_cacheinfo); 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) 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) { switch (transition) {
case IF_OPER_UP: case IF_OPER_UP:
...@@ -866,12 +879,7 @@ static void set_operstate(struct net_device *dev, unsigned char transition) ...@@ -866,12 +879,7 @@ static void set_operstate(struct net_device *dev, unsigned char transition)
break; break;
} }
if (READ_ONCE(dev->operstate) != operstate) { netdev_set_operstate(dev, operstate);
write_lock(&dev_base_lock);
WRITE_ONCE(dev->operstate, operstate);
write_unlock(&dev_base_lock);
netdev_state_change(dev);
}
} }
static unsigned int rtnl_dev_get_flags(const struct net_device *dev) static unsigned int rtnl_dev_get_flags(const struct net_device *dev)
......
...@@ -28,29 +28,19 @@ static bool is_slave_up(struct net_device *dev) ...@@ -28,29 +28,19 @@ static bool is_slave_up(struct net_device *dev)
return dev && is_admin_up(dev) && netif_oper_up(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) static void hsr_set_operstate(struct hsr_port *master, bool has_carrier)
{ {
if (!is_admin_up(master->dev)) { struct net_device *dev = master->dev;
__hsr_set_operstate(master->dev, IF_OPER_DOWN);
if (!is_admin_up(dev)) {
netdev_set_operstate(dev, IF_OPER_DOWN);
return; return;
} }
if (has_carrier) if (has_carrier)
__hsr_set_operstate(master->dev, IF_OPER_UP); netdev_set_operstate(dev, IF_OPER_UP);
else 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) static bool hsr_check_carrier(struct hsr_port *master)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment