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 --- net/dsa/dsa.c | 20 +++++++++++++++++--- net/dsa/user.c | 19 +++++++++++++++++-- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 9cb732f6b1e3..da53a666d4b8 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #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, false); - netif_close_many(&close_list, true); + 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); diff --git a/net/dsa/user.c b/net/dsa/user.c index 8704c1a3a5b7..8ea47444d6d5 100644 --- a/net/dsa/user.c +++ b/net/dsa/user.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -3600,10 +3601,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; } -- 2.53.0-Meta