mac80211: synchronize scan off/on-channel and PS states
Since:
commit b23b025fe2
Author: Ben Greear <greearb@candelatech.com>
Date: Fri Feb 4 11:54:17 2011 -0800
mac80211: Optimize scans on current operating channel.
we do not disable PS while going back to operational channel (on
ieee80211_scan_state_suspend) and deffer that until scan finish.
But since we are allowed to send frames, we can send a frame to AP
without PM bit set, so disable PS on AP side. Then when we switch
to off-channel (in ieee80211_scan_state_resume) we do not enable PS.
Hence we are off-channel with PS disabled, frames are not buffered
by AP.
To fix remove offchannel_ps_disable argument and always enable PS when
going off-channel and disable it when going on-channel, like it was
before.
Cc: stable@vger.kernel.org # 2.6.39+
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Tested-by: Seth Forshee <seth.forshee@canonical.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Родитель
1626e0fa74
Коммит
aacde9ee45
|
@ -1358,10 +1358,8 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata);
|
|||
void ieee80211_sched_scan_stopped_work(struct work_struct *work);
|
||||
|
||||
/* off-channel helpers */
|
||||
void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
|
||||
bool offchannel_ps_enable);
|
||||
void ieee80211_offchannel_return(struct ieee80211_local *local,
|
||||
bool offchannel_ps_disable);
|
||||
void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local);
|
||||
void ieee80211_offchannel_return(struct ieee80211_local *local);
|
||||
void ieee80211_roc_setup(struct ieee80211_local *local);
|
||||
void ieee80211_start_next_roc(struct ieee80211_local *local);
|
||||
void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata);
|
||||
|
|
|
@ -102,8 +102,7 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata)
|
|||
ieee80211_sta_reset_conn_monitor(sdata);
|
||||
}
|
||||
|
||||
void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
|
||||
bool offchannel_ps_enable)
|
||||
void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
|
@ -134,8 +133,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
|
|||
|
||||
if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
|
||||
netif_tx_stop_all_queues(sdata->dev);
|
||||
if (offchannel_ps_enable &&
|
||||
(sdata->vif.type == NL80211_IFTYPE_STATION) &&
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
|
||||
sdata->u.mgd.associated)
|
||||
ieee80211_offchannel_ps_enable(sdata);
|
||||
}
|
||||
|
@ -143,8 +141,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
|
|||
mutex_unlock(&local->iflist_mtx);
|
||||
}
|
||||
|
||||
void ieee80211_offchannel_return(struct ieee80211_local *local,
|
||||
bool offchannel_ps_disable)
|
||||
void ieee80211_offchannel_return(struct ieee80211_local *local)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
|
||||
|
@ -163,11 +160,9 @@ void ieee80211_offchannel_return(struct ieee80211_local *local,
|
|||
continue;
|
||||
|
||||
/* Tell AP we're back */
|
||||
if (offchannel_ps_disable &&
|
||||
sdata->vif.type == NL80211_IFTYPE_STATION) {
|
||||
if (sdata->u.mgd.associated)
|
||||
ieee80211_offchannel_ps_disable(sdata);
|
||||
}
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
|
||||
sdata->u.mgd.associated)
|
||||
ieee80211_offchannel_ps_disable(sdata);
|
||||
|
||||
if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
|
||||
/*
|
||||
|
@ -385,7 +380,7 @@ void ieee80211_sw_roc_work(struct work_struct *work)
|
|||
local->tmp_channel = NULL;
|
||||
ieee80211_hw_config(local, 0);
|
||||
|
||||
ieee80211_offchannel_return(local, true);
|
||||
ieee80211_offchannel_return(local);
|
||||
}
|
||||
|
||||
ieee80211_recalc_idle(local);
|
||||
|
|
|
@ -292,7 +292,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
|
|||
if (!was_hw_scan) {
|
||||
ieee80211_configure_filter(local);
|
||||
drv_sw_scan_complete(local);
|
||||
ieee80211_offchannel_return(local, true);
|
||||
ieee80211_offchannel_return(local);
|
||||
}
|
||||
|
||||
ieee80211_recalc_idle(local);
|
||||
|
@ -341,7 +341,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
|
|||
local->next_scan_state = SCAN_DECISION;
|
||||
local->scan_channel_idx = 0;
|
||||
|
||||
ieee80211_offchannel_stop_vifs(local, true);
|
||||
ieee80211_offchannel_stop_vifs(local);
|
||||
|
||||
ieee80211_configure_filter(local);
|
||||
|
||||
|
@ -678,12 +678,8 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local,
|
|||
local->scan_channel = NULL;
|
||||
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
|
||||
|
||||
/*
|
||||
* Re-enable vifs and beaconing. Leave PS
|
||||
* in off-channel state..will put that back
|
||||
* on-channel at the end of scanning.
|
||||
*/
|
||||
ieee80211_offchannel_return(local, false);
|
||||
/* disable PS */
|
||||
ieee80211_offchannel_return(local);
|
||||
|
||||
*next_delay = HZ / 5;
|
||||
/* afterwards, resume scan & go to next channel */
|
||||
|
@ -693,8 +689,7 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local,
|
|||
static void ieee80211_scan_state_resume(struct ieee80211_local *local,
|
||||
unsigned long *next_delay)
|
||||
{
|
||||
/* PS already is in off-channel mode */
|
||||
ieee80211_offchannel_stop_vifs(local, false);
|
||||
ieee80211_offchannel_stop_vifs(local);
|
||||
|
||||
if (local->ops->flush) {
|
||||
drv_flush(local, false);
|
||||
|
|
Загрузка…
Ссылка в новой задаче