Commit 4d42b37d authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

net: convert dev->reg_state to u8



Prepares things so that dev->reg_state reads can be lockless,
by adding WRITE_ONCE() on write side.

READ_ONCE()/WRITE_ONCE() do not support bitfields.

Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a6473fe9
Loading
Loading
Loading
Loading
+14 −9
Original line number Diff line number Diff line
@@ -1815,6 +1815,15 @@ enum netdev_stat_type {
	NETDEV_PCPU_STAT_DSTATS, /* struct pcpu_dstats */
};

enum netdev_reg_state {
	NETREG_UNINITIALIZED = 0,
	NETREG_REGISTERED,	/* completed register_netdevice */
	NETREG_UNREGISTERING,	/* called unregister_netdevice */
	NETREG_UNREGISTERED,	/* completed unregister todo */
	NETREG_RELEASED,	/* called free_netdev */
	NETREG_DUMMY,		/* dummy device for NAPI poll */
};

/**
 *	struct net_device - The DEVICE structure.
 *
@@ -2372,13 +2381,7 @@ struct net_device {

	struct list_head	link_watch_list;

	enum { NETREG_UNINITIALIZED=0,
	       NETREG_REGISTERED,	/* completed register_netdevice */
	       NETREG_UNREGISTERING,	/* called unregister_netdevice */
	       NETREG_UNREGISTERED,	/* completed unregister todo */
	       NETREG_RELEASED,		/* called free_netdev */
	       NETREG_DUMMY,		/* dummy device for NAPI poll */
	} reg_state:8;
	u8 reg_state;

	bool dismantle;

@@ -5254,7 +5257,9 @@ static inline const char *netdev_name(const struct net_device *dev)

static inline const char *netdev_reg_state(const struct net_device *dev)
{
	switch (dev->reg_state) {
	u8 reg_state = READ_ONCE(dev->reg_state);

	switch (reg_state) {
	case NETREG_UNINITIALIZED: return " (uninitialized)";
	case NETREG_REGISTERED: return "";
	case NETREG_UNREGISTERING: return " (unregistering)";
@@ -5263,7 +5268,7 @@ static inline const char *netdev_reg_state(const struct net_device *dev)
	case NETREG_DUMMY: return " (dummy)";
	}

	WARN_ONCE(1, "%s: unknown reg_state %d\n", dev->name, dev->reg_state);
	WARN_ONCE(1, "%s: unknown reg_state %d\n", dev->name, reg_state);
	return " (unknown)";
}

+4 −4
Original line number Diff line number Diff line
@@ -10339,7 +10339,7 @@ int register_netdevice(struct net_device *dev)

	ret = netdev_register_kobject(dev);
	write_lock(&dev_base_lock);
	dev->reg_state = ret ? NETREG_UNREGISTERED : NETREG_REGISTERED;
	WRITE_ONCE(dev->reg_state, ret ? NETREG_UNREGISTERED : NETREG_REGISTERED);
	write_unlock(&dev_base_lock);
	if (ret)
		goto err_uninit_notify;
@@ -10630,7 +10630,7 @@ void netdev_run_todo(void)
		}

		write_lock(&dev_base_lock);
		dev->reg_state = NETREG_UNREGISTERED;
		WRITE_ONCE(dev->reg_state, NETREG_UNREGISTERED);
		write_unlock(&dev_base_lock);
		linkwatch_sync_dev(dev);
	}
@@ -11050,7 +11050,7 @@ void free_netdev(struct net_device *dev)
	}

	BUG_ON(dev->reg_state != NETREG_UNREGISTERED);
	dev->reg_state = NETREG_RELEASED;
	WRITE_ONCE(dev->reg_state, NETREG_RELEASED);

	/* will free via device release */
	put_device(&dev->dev);
@@ -11140,7 +11140,7 @@ void unregister_netdevice_many_notify(struct list_head *head,
		/* And unlink it from device chain. */
		write_lock(&dev_base_lock);
		unlist_netdevice(dev, false);
		dev->reg_state = NETREG_UNREGISTERING;
		WRITE_ONCE(dev->reg_state, NETREG_UNREGISTERING);
		write_unlock(&dev_base_lock);
	}
	flush_all_backlogs();