diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/ibss.c | 1 | ||||
-rw-r--r-- | net/mac80211/main.c | 6 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 11 | ||||
-rw-r--r-- | net/mac80211/mesh.h | 4 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 2 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 16 | ||||
-rw-r--r-- | net/mac80211/scan.c | 20 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 2 | ||||
-rw-r--r-- | net/mac80211/status.c | 5 | ||||
-rw-r--r-- | net/mac80211/util.c | 16 |
10 files changed, 53 insertions, 30 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index f7fc0e00497f..978d3bc31df7 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -1733,7 +1733,6 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) if (sdata->vif.type != NL80211_IFTYPE_ADHOC) continue; sdata->u.ibss.last_scan_completed = jiffies; - ieee80211_queue_work(&local->hw, &sdata->work); } mutex_unlock(&local->iflist_mtx); } diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 6bcf0faa4a89..8190bf27ebff 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -248,6 +248,7 @@ static void ieee80211_restart_work(struct work_struct *work) /* wait for scan work complete */ flush_workqueue(local->workqueue); + flush_work(&local->sched_scan_stopped_work); WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), "%s called with hardware scan in progress\n", __func__); @@ -256,6 +257,11 @@ static void ieee80211_restart_work(struct work_struct *work) list_for_each_entry(sdata, &local->interfaces, list) flush_delayed_work(&sdata->dec_tailroom_needed_wk); ieee80211_scan_cancel(local); + + /* make sure any new ROC will consider local->in_reconfig */ + flush_delayed_work(&local->roc_work); + flush_work(&local->hw_roc_done); + ieee80211_reconfig(local); rtnl_unlock(); } diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index fa28500f28fd..6f85b6ab8e51 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -1370,17 +1370,6 @@ out: sdata_unlock(sdata); } -void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) -{ - struct ieee80211_sub_if_data *sdata; - - rcu_read_lock(); - list_for_each_entry_rcu(sdata, &local->interfaces, list) - if (ieee80211_vif_is_mesh(&sdata->vif) && - ieee80211_sdata_running(sdata)) - ieee80211_queue_work(&local->hw, &sdata->work); - rcu_read_unlock(); -} void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) { diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index a1596344c3ba..4a8019f79fb2 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -362,14 +362,10 @@ static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) return sdata->u.mesh.mesh_pp_id == IEEE80211_PATH_PROTOCOL_HWMP; } -void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local); - void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata); void ieee80211s_stop(void); #else -static inline void -ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) { return false; } static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1c342e2592c4..bfbb1acafdd1 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -4005,8 +4005,6 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) if (!ieee80211_hw_check(&sdata->local->hw, CONNECTION_MONITOR)) ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.monitor_work); - /* and do all the other regular work too */ - ieee80211_queue_work(&sdata->local->hw, &sdata->work); } } diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 8b2f4eaac2ba..55a9c5b94ce1 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -252,14 +252,11 @@ static bool ieee80211_recalc_sw_work(struct ieee80211_local *local, static void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc, unsigned long start_time) { - struct ieee80211_local *local = roc->sdata->local; - if (WARN_ON(roc->notified)) return; roc->start_time = start_time; roc->started = true; - roc->hw_begun = true; if (roc->mgmt_tx_cookie) { if (!WARN_ON(!roc->frame)) { @@ -274,9 +271,6 @@ static void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc, } roc->notified = true; - - if (!local->ops->remain_on_channel) - ieee80211_recalc_sw_work(local, start_time); } static void ieee80211_hw_roc_start(struct work_struct *work) @@ -291,6 +285,7 @@ static void ieee80211_hw_roc_start(struct work_struct *work) if (!roc->started) break; + roc->hw_begun = true; ieee80211_handle_roc_started(roc, local->hw_roc_start_time); } @@ -413,6 +408,10 @@ void ieee80211_start_next_roc(struct ieee80211_local *local) return; } + /* defer roc if driver is not started (i.e. during reconfig) */ + if (local->in_reconfig) + return; + roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work, list); @@ -534,8 +533,10 @@ ieee80211_coalesce_hw_started_roc(struct ieee80211_local *local, * begin, otherwise they'll both be marked properly by the work * struct that runs once the driver notifies us of the beginning */ - if (cur_roc->hw_begun) + if (cur_roc->hw_begun) { + new_roc->hw_begun = true; ieee80211_handle_roc_started(new_roc, now); + } return true; } @@ -658,6 +659,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, queued = true; roc->on_channel = tmp->on_channel; ieee80211_handle_roc_started(roc, now); + ieee80211_recalc_sw_work(local, now); break; } diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index a413e52f7691..ae980ce8daff 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -314,6 +314,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) bool was_scanning = local->scanning; struct cfg80211_scan_request *scan_req; struct ieee80211_sub_if_data *scan_sdata; + struct ieee80211_sub_if_data *sdata; lockdep_assert_held(&local->mtx); @@ -373,7 +374,16 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) ieee80211_mlme_notify_scan_completed(local); ieee80211_ibss_notify_scan_completed(local); - ieee80211_mesh_notify_scan_completed(local); + + /* Requeue all the work that might have been ignored while + * the scan was in progress; if there was none this will + * just be a no-op for the particular interface. + */ + list_for_each_entry_rcu(sdata, &local->interfaces, list) { + if (ieee80211_sdata_running(sdata)) + ieee80211_queue_work(&sdata->local->hw, &sdata->work); + } + if (was_scanning) ieee80211_start_next_roc(local); } @@ -1213,6 +1223,14 @@ void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw) trace_api_sched_scan_stopped(local); + /* + * this shouldn't really happen, so for simplicity + * simply ignore it, and let mac80211 reconfigure + * the sched scan later on. + */ + if (local->in_reconfig) + return; + schedule_work(&local->sched_scan_stopped_work); } EXPORT_SYMBOL(ieee80211_sched_scan_stopped); diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 4402ad5b27d1..a4a4f89d3ba0 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -1453,7 +1453,7 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta, more_data = ieee80211_sta_ps_more_data(sta, ignored_acs, reason, driver_release_tids); - if (reason == IEEE80211_FRAME_RELEASE_PSPOLL) + if (driver_release_tids && reason == IEEE80211_FRAME_RELEASE_PSPOLL) driver_release_tids = BIT(find_highest_prio_tid(driver_release_tids)); diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 5bad05e9af90..6101deb805a8 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -51,6 +51,11 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, struct ieee80211_hdr *hdr = (void *)skb->data; int ac; + if (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER) { + ieee80211_free_txskb(&local->hw, skb); + return; + } + /* * This skb 'survived' a round-trip through the driver, and * hopefully the driver didn't mangle it too badly. However, diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 3943d4bf289c..58f58bd5202f 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -2043,16 +2043,26 @@ int ieee80211_reconfig(struct ieee80211_local *local) */ if (sched_scan_req->n_scan_plans > 1 || __ieee80211_request_sched_scan_start(sched_scan_sdata, - sched_scan_req)) + sched_scan_req)) { + RCU_INIT_POINTER(local->sched_scan_sdata, NULL); + RCU_INIT_POINTER(local->sched_scan_req, NULL); sched_scan_stopped = true; + } mutex_unlock(&local->mtx); if (sched_scan_stopped) cfg80211_sched_scan_stopped_rtnl(local->hw.wiphy); wake_up: - local->in_reconfig = false; - barrier(); + if (local->in_reconfig) { + local->in_reconfig = false; + barrier(); + + /* Restart deferred ROCs */ + mutex_lock(&local->mtx); + ieee80211_start_next_roc(local); + mutex_unlock(&local->mtx); + } if (local->monitors == local->open_count && local->monitors > 0) ieee80211_add_virtual_monitor(local); |