diff options
Diffstat (limited to 'net/wireless/core.c')
-rw-r--r-- | net/wireless/core.c | 44 |
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 | ||
263 | void 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 | |||
290 | static 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 | ||
265 | struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | 304 | struct 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) |