On 03/08, Jakub Kicinski wrote: > On Sun, 9 Mar 2025 05:37:18 +0900 Kohei Enju wrote: > > Both netdev_lock() and netdev_lock_ops() are called before > > list_netdevice() in register_netdevice(). > > No other context can access the struct net_device, so we don't need these > > locks in this context. That's technically true, but it will set off a bunch of lockdep warnings :-( > Doesn't sysfs get registered earlier? > I'm afraid not being able to take the lock from the registration > path ties our hands too much. Maybe we need to make a more serious > attempt at letting the caller take the lock? This looks like another case of upper/lower :-( So maybe we need to solve it for real? With an extra upper_lock pointer in the netdev? Untested patch to convey the general idea: diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index d3c549f73909..9c85179431e6 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2520,6 +2520,7 @@ struct net_device { * Ordering: take after rtnl_lock. */ struct mutex lock; + struct mutex *upper_lock; #if IS_ENABLED(CONFIG_NET_SHAPER) /** diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 90597bf84e3d..3d0fda6e9bca 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3022,6 +3022,9 @@ static int do_setlink(const struct sk_buff *skb, struct net_device *dev, char ifname[IFNAMSIZ]; int err; + /* TODO: add another wrapper for this */ + if (dev->upper_lock) + mutex_lock(dev->upper_lock); netdev_lock_ops(dev); err = validate_linkmsg(dev, tb, extack); @@ -3394,6 +3397,8 @@ static int do_setlink(const struct sk_buff *skb, struct net_device *dev, } netdev_unlock_ops(dev); + if (dev->upper_lock) + mutex_unlock(dev->upper_lock); return err; } diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index b0423046028c..818ff487b363 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -304,7 +304,7 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr) if (!dev->ieee80211_ptr->registered) return 0; - guard(wiphy)(local->hw.wiphy); + /* TODO: remove guard from other places */ return _ieee80211_change_mac(sdata, addr); } @@ -2227,6 +2227,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, free_netdev(ndev); return ret; } + + ndev->upper_lock = &local->hw.wiphy.mtx; } mutex_lock(&local->iflist_mtx);