diff --git a/net/wireless/core.c b/net/wireless/core.c index dcce326fdb8c..ad812d4be773 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -1236,6 +1236,21 @@ void wiphy_rfkill_set_hw_state_reason(struct wiphy *wiphy, bool blocked, } EXPORT_SYMBOL(wiphy_rfkill_set_hw_state_reason); +struct netdev_unregister_work { + struct work_struct work; + struct net_device *netdev; +}; + +static void cfg80211_unregister_netdevice_work(struct work_struct *work) +{ + struct netdev_unregister_work *w = container_of(work, struct netdev_unregister_work, work); + + rtnl_lock(); + unregister_netdevice(w->netdev); + rtnl_unlock(); + kfree(w); +} + static void _cfg80211_unregister_wdev(struct wireless_dev *wdev, bool unregister_netdev) { @@ -1252,8 +1267,14 @@ static void _cfg80211_unregister_wdev(struct wireless_dev *wdev, if (wdev->netdev) { sysfs_remove_link(&wdev->netdev->dev.kobj, "phy80211"); - if (unregister_netdev) - unregister_netdevice(wdev->netdev); + if (unregister_netdev) { + struct netdev_unregister_work *w + = kmalloc(sizeof(*w), GFP_KERNEL | __GFP_NOFAIL); + + INIT_WORK(&w->work, cfg80211_unregister_netdevice_work); + w->netdev = wdev->netdev; + schedule_work(&w->work); + } } list_del_rcu(&wdev->list);