mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-21 13:29:39 -04:00
net: dsa: hold instance lock on close-on-shutdown paths
netif_close_many will soon assert ops lock (for locked DOWN/GOING_DOWN). Update dsa_switch_shutdown to manually grab and release the ops lock. Signed-off-by: Stanislav Fomichev <sdf@fomichev.me> Link: https://patch.msgid.link/20260702224150.3730033-3-sdf@fomichev.me Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
committed by
Paolo Abeni
parent
5326fefb9f
commit
cefa18fab2
@@ -18,6 +18,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <net/dsa_stubs.h>
|
||||
#include <net/netdev_lock.h>
|
||||
#include <net/sch_generic.h>
|
||||
|
||||
#include "conduit.h"
|
||||
@@ -1620,10 +1621,23 @@ void dsa_switch_shutdown(struct dsa_switch *ds)
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
dsa_switch_for_each_cpu_port(dp, ds)
|
||||
list_add(&dp->conduit->close_list, &close_list);
|
||||
dsa_switch_for_each_cpu_port(dp, ds) {
|
||||
if (!(dp->conduit->flags & IFF_UP))
|
||||
continue;
|
||||
list_add_tail(&dp->conduit->close_list, &close_list);
|
||||
netdev_lock_ops(dp->conduit);
|
||||
}
|
||||
|
||||
netif_close_many(&close_list, true);
|
||||
netif_close_many(&close_list, false);
|
||||
|
||||
while (!list_empty(&close_list)) {
|
||||
struct net_device *conduit;
|
||||
|
||||
conduit = list_first_entry(&close_list, struct net_device,
|
||||
close_list);
|
||||
netdev_unlock_ops(conduit);
|
||||
list_del_init(&conduit->close_list);
|
||||
}
|
||||
|
||||
dsa_switch_for_each_user_port(dp, ds) {
|
||||
conduit = dsa_port_to_conduit(dp);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/mdio.h>
|
||||
#include <net/netdev_lock.h>
|
||||
#include <net/rtnetlink.h>
|
||||
#include <net/pkt_cls.h>
|
||||
#include <net/selftests.h>
|
||||
@@ -3599,10 +3600,24 @@ static int dsa_user_netdevice_event(struct notifier_block *nb,
|
||||
if (dp->cpu_dp != cpu_dp)
|
||||
continue;
|
||||
|
||||
list_add(&dp->user->close_list, &close_list);
|
||||
if (!(dp->user->flags & IFF_UP))
|
||||
continue;
|
||||
|
||||
list_add_tail(&dp->user->close_list, &close_list);
|
||||
netdev_lock_ops(dp->user);
|
||||
}
|
||||
|
||||
netif_close_many(&close_list, true);
|
||||
netif_close_many(&close_list, false);
|
||||
|
||||
while (!list_empty(&close_list)) {
|
||||
struct net_device *user_dev;
|
||||
|
||||
user_dev = list_first_entry(&close_list,
|
||||
struct net_device,
|
||||
close_list);
|
||||
netdev_unlock_ops(user_dev);
|
||||
list_del_init(&user_dev->close_list);
|
||||
}
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user