aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/core.c')
-rw-r--r--net/wireless/core.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 086cddd03ba6..5a63c3cbda2e 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -260,6 +260,45 @@ static void cfg80211_event_work(struct work_struct *work)
260 rtnl_unlock(); 260 rtnl_unlock();
261} 261}
262 262
263void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev)
264{
265 struct cfg80211_iface_destroy *item;
266
267 ASSERT_RTNL();
268
269 spin_lock_irq(&rdev->destroy_list_lock);
270 while ((item = list_first_entry_or_null(&rdev->destroy_list,
271 struct cfg80211_iface_destroy,
272 list))) {
273 struct wireless_dev *wdev, *tmp;
274 u32 nlportid = item->nlportid;
275
276 list_del(&item->list);
277 kfree(item);
278 spin_unlock_irq(&rdev->destroy_list_lock);
279
280 list_for_each_entry_safe(wdev, tmp, &rdev->wdev_list, list) {
281 if (nlportid == wdev->owner_nlportid)
282 rdev_del_virtual_intf(rdev, wdev);
283 }
284
285 spin_lock_irq(&rdev->destroy_list_lock);
286 }
287 spin_unlock_irq(&rdev->destroy_list_lock);
288}
289
290static void cfg80211_destroy_iface_wk(struct work_struct *work)
291{
292 struct cfg80211_registered_device *rdev;
293
294 rdev = container_of(work, struct cfg80211_registered_device,
295 destroy_work);
296
297 rtnl_lock();
298 cfg80211_destroy_ifaces(rdev);
299 rtnl_unlock();
300}
301
263/* exported functions */ 302/* exported functions */
264 303
265struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) 304struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
@@ -318,6 +357,10 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
318 rdev->wiphy.dev.class = &ieee80211_class; 357 rdev->wiphy.dev.class = &ieee80211_class;
319 rdev->wiphy.dev.platform_data = rdev; 358 rdev->wiphy.dev.platform_data = rdev;
320 359
360 INIT_LIST_HEAD(&rdev->destroy_list);
361 spin_lock_init(&rdev->destroy_list_lock);
362 INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk);
363
321#ifdef CONFIG_CFG80211_DEFAULT_PS 364#ifdef CONFIG_CFG80211_DEFAULT_PS
322 rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; 365 rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
323#endif 366#endif
@@ -675,6 +718,7 @@ void wiphy_unregister(struct wiphy *wiphy)
675 cancel_work_sync(&rdev->conn_work); 718 cancel_work_sync(&rdev->conn_work);
676 flush_work(&rdev->event_work); 719 flush_work(&rdev->event_work);
677 cancel_delayed_work_sync(&rdev->dfs_update_channels_wk); 720 cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
721 flush_work(&rdev->destroy_work);
678 722
679#ifdef CONFIG_PM 723#ifdef CONFIG_PM
680 if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup) 724 if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup)