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: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Eric Dumazet 2024-02-13 06:32:36 +00:00 committed by David S. Miller
parent a6473fe9b6
commit 4d42b37def
2 changed files with 18 additions and 13 deletions

View file

@ -1815,6 +1815,15 @@ enum netdev_stat_type {
NETDEV_PCPU_STAT_DSTATS, /* struct pcpu_dstats */ 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. * struct net_device - The DEVICE structure.
* *
@ -2372,13 +2381,7 @@ struct net_device {
struct list_head link_watch_list; struct list_head link_watch_list;
enum { NETREG_UNINITIALIZED=0, u8 reg_state;
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;
bool dismantle; 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) 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_UNINITIALIZED: return " (uninitialized)";
case NETREG_REGISTERED: return ""; case NETREG_REGISTERED: return "";
case NETREG_UNREGISTERING: return " (unregistering)"; 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)"; 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)"; return " (unknown)";
} }

View file

@ -10339,7 +10339,7 @@ int register_netdevice(struct net_device *dev)
ret = netdev_register_kobject(dev); ret = netdev_register_kobject(dev);
write_lock(&dev_base_lock); 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); write_unlock(&dev_base_lock);
if (ret) if (ret)
goto err_uninit_notify; goto err_uninit_notify;
@ -10630,7 +10630,7 @@ void netdev_run_todo(void)
} }
write_lock(&dev_base_lock); write_lock(&dev_base_lock);
dev->reg_state = NETREG_UNREGISTERED; WRITE_ONCE(dev->reg_state, NETREG_UNREGISTERED);
write_unlock(&dev_base_lock); write_unlock(&dev_base_lock);
linkwatch_sync_dev(dev); linkwatch_sync_dev(dev);
} }
@ -11050,7 +11050,7 @@ void free_netdev(struct net_device *dev)
} }
BUG_ON(dev->reg_state != NETREG_UNREGISTERED); BUG_ON(dev->reg_state != NETREG_UNREGISTERED);
dev->reg_state = NETREG_RELEASED; WRITE_ONCE(dev->reg_state, NETREG_RELEASED);
/* will free via device release */ /* will free via device release */
put_device(&dev->dev); put_device(&dev->dev);
@ -11140,7 +11140,7 @@ void unregister_netdevice_many_notify(struct list_head *head,
/* And unlink it from device chain. */ /* And unlink it from device chain. */
write_lock(&dev_base_lock); write_lock(&dev_base_lock);
unlist_netdevice(dev, false); unlist_netdevice(dev, false);
dev->reg_state = NETREG_UNREGISTERING; WRITE_ONCE(dev->reg_state, NETREG_UNREGISTERING);
write_unlock(&dev_base_lock); write_unlock(&dev_base_lock);
} }
flush_all_backlogs(); flush_all_backlogs();