* @event_list: (private) list for internal event processing
* @event_lock: (private) lock for event list
* @owner_nlportid: (private) owner socket port ID
+ * @nl_owner_dead: (private) owner socket went away
* @cqm_config: (private) nl80211 RSSI monitor state
*/
struct wireless_dev {
u32 ap_unexpected_nlportid;
+ u32 owner_nlportid;
+ bool nl_owner_dead;
+
bool cac_started;
unsigned long cac_start_time;
unsigned int cac_time_ms;
- u32 owner_nlportid;
-
#ifdef CONFIG_CFG80211_WEXT
/* wext data */
struct {
void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev)
{
- struct cfg80211_iface_destroy *item;
+ struct wireless_dev *wdev, *tmp;
ASSERT_RTNL();
- spin_lock_irq(&rdev->destroy_list_lock);
- while ((item = list_first_entry_or_null(&rdev->destroy_list,
- struct cfg80211_iface_destroy,
- list))) {
- struct wireless_dev *wdev, *tmp;
- u32 nlportid = item->nlportid;
-
- list_del(&item->list);
- kfree(item);
- spin_unlock_irq(&rdev->destroy_list_lock);
-
- list_for_each_entry_safe(wdev, tmp,
- &rdev->wiphy.wdev_list, list) {
- if (nlportid == wdev->owner_nlportid)
- rdev_del_virtual_intf(rdev, wdev);
- }
-
- spin_lock_irq(&rdev->destroy_list_lock);
+ list_for_each_entry_safe(wdev, tmp, &rdev->wiphy.wdev_list, list) {
+ if (wdev->nl_owner_dead)
+ rdev_del_virtual_intf(rdev, wdev);
}
- spin_unlock_irq(&rdev->destroy_list_lock);
}
static void cfg80211_destroy_iface_wk(struct work_struct *work)
rdev->wiphy.dev.platform_data = rdev;
device_enable_async_suspend(&rdev->wiphy.dev);
- INIT_LIST_HEAD(&rdev->destroy_list);
- spin_lock_init(&rdev->destroy_list_lock);
INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk);
INIT_WORK(&rdev->sched_scan_stop_wk, cfg80211_sched_scan_stop_wk);
INIT_WORK(&rdev->propagate_radar_detect_wk,
struct cfg80211_coalesce *coalesce;
- spinlock_t destroy_list_lock;
- struct list_head destroy_list;
struct work_struct destroy_work;
-
struct work_struct sched_scan_stop_wk;
struct cfg80211_chan_def radar_chandef;
u32 nlportid;
};
-struct cfg80211_iface_destroy {
- struct list_head list;
- u32 nlportid;
-};
-
struct cfg80211_cqm_config {
u32 rssi_hyst;
s32 last_rssi_event_value;
rcu_read_lock();
list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
- bool schedule_destroy_work = false;
struct cfg80211_sched_scan_request *sched_scan_req =
rcu_dereference(rdev->sched_scan_req);
list_for_each_entry_rcu(wdev, &rdev->wiphy.wdev_list, list) {
cfg80211_mlme_unregister_socket(wdev, notify->portid);
- if (wdev->owner_nlportid == notify->portid)
- schedule_destroy_work = true;
- else if (wdev->conn_owner_nlportid == notify->portid)
+ if (wdev->owner_nlportid == notify->portid) {
+ wdev->nl_owner_dead = true;
+ schedule_work(&rdev->destroy_work);
+ } else if (wdev->conn_owner_nlportid == notify->portid) {
schedule_work(&wdev->disconnect_wk);
+ }
}
spin_lock_bh(&rdev->beacon_registrations_lock);
}
}
spin_unlock_bh(&rdev->beacon_registrations_lock);
-
- if (schedule_destroy_work) {
- struct cfg80211_iface_destroy *destroy;
-
- destroy = kzalloc(sizeof(*destroy), GFP_ATOMIC);
- if (destroy) {
- destroy->nlportid = notify->portid;
- spin_lock(&rdev->destroy_list_lock);
- list_add(&destroy->list, &rdev->destroy_list);
- spin_unlock(&rdev->destroy_list_lock);
- schedule_work(&rdev->destroy_work);
- }
- }
}
rcu_read_unlock();