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

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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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;
+2 −0
Original line number Diff line number Diff line
@@ -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 */
+2 −7
Original line number Diff line number Diff line
@@ -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);
}


+15 −7
Original line number Diff line number Diff line
@@ -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)
+6 −16
Original line number Diff line number Diff line
@@ -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)