Commit 196ac1c1 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

mac80211: do remain-on-channel while idle

The IDLE handling in HW off-channel is broken right
now since we turn off IDLE only when the off-channel
period already started. Therefore, all drivers that
use it today (only iwlwifi!) must support off-channel
while idle, so playing with idle isn't needed at all.

Off-channel in general, since it's no longer used for
authentication/association, shouldn't affect PS, so
also remove that logic.

Also document a small caveat for reporting TX status
from off-channel frames in HW remain-on-channel.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 491b26b4
...@@ -2183,7 +2183,13 @@ enum ieee80211_rate_control_changed { ...@@ -2183,7 +2183,13 @@ enum ieee80211_rate_control_changed {
* offload. Frames to transmit on the off-channel channel are transmitted * offload. Frames to transmit on the off-channel channel are transmitted
* normally except for the %IEEE80211_TX_CTL_TX_OFFCHAN flag. When the * normally except for the %IEEE80211_TX_CTL_TX_OFFCHAN flag. When the
* duration (which will always be non-zero) expires, the driver must call * duration (which will always be non-zero) expires, the driver must call
* ieee80211_remain_on_channel_expired(). This callback may sleep. * ieee80211_remain_on_channel_expired().
* The driver must not call ieee80211_remain_on_channel_expired() before
* the TX status for a frame that was sent off-channel, otherwise the TX
* status is reported to userspace in an invalid way.
* Note that this callback may be called while the device is in IDLE and
* must be accepted in this case.
* This callback may sleep.
* @cancel_remain_on_channel: Requests that an ongoing off-channel period is * @cancel_remain_on_channel: Requests that an ongoing off-channel period is
* aborted before it expires. This callback may sleep. * aborted before it expires. This callback may sleep.
* *
......
...@@ -2187,8 +2187,6 @@ static int ieee80211_cancel_remain_on_channel_hw(struct ieee80211_local *local, ...@@ -2187,8 +2187,6 @@ static int ieee80211_cancel_remain_on_channel_hw(struct ieee80211_local *local,
local->hw_roc_cookie = 0; local->hw_roc_cookie = 0;
local->hw_roc_channel = NULL; local->hw_roc_channel = NULL;
ieee80211_recalc_idle(local);
return 0; return 0;
} }
...@@ -2248,7 +2246,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, ...@@ -2248,7 +2246,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_work *wk; struct ieee80211_work *wk;
const struct ieee80211_mgmt *mgmt = (void *)buf; const struct ieee80211_mgmt *mgmt = (void *)buf;
u32 flags; u32 flags;
bool is_offchan = false; bool is_offchan = false, in_hw_roc = false;
if (dont_wait_for_ack) if (dont_wait_for_ack)
flags = IEEE80211_TX_CTL_NO_ACK; flags = IEEE80211_TX_CTL_NO_ACK;
...@@ -2268,6 +2266,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, ...@@ -2268,6 +2266,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
if (chan == local->hw_roc_channel) { if (chan == local->hw_roc_channel) {
/* TODO: check channel type? */ /* TODO: check channel type? */
is_offchan = false; is_offchan = false;
in_hw_roc = true;
flags |= IEEE80211_TX_CTL_TX_OFFCHAN; flags |= IEEE80211_TX_CTL_TX_OFFCHAN;
} }
...@@ -2370,7 +2369,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, ...@@ -2370,7 +2369,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
* wait is involved, we might otherwise not be on * wait is involved, we might otherwise not be on
* the right channel for long enough! * the right channel for long enough!
*/ */
if (!is_offchan && !wait && !sdata->vif.bss_conf.idle) { if (!is_offchan && !wait && (in_hw_roc || !sdata->vif.bss_conf.idle)) {
ieee80211_tx_skb(sdata, skb); ieee80211_tx_skb(sdata, skb);
return 0; return 0;
} }
......
...@@ -1456,7 +1456,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) ...@@ -1456,7 +1456,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
{ {
struct ieee80211_sub_if_data *sdata; struct ieee80211_sub_if_data *sdata;
int count = 0; int count = 0;
bool working = false, scanning = false, hw_roc = false; bool working = false, scanning = false;
struct ieee80211_work *wk; struct ieee80211_work *wk;
unsigned int led_trig_start = 0, led_trig_stop = 0; unsigned int led_trig_start = 0, led_trig_stop = 0;
...@@ -1493,9 +1493,11 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) ...@@ -1493,9 +1493,11 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
count++; count++;
} }
list_for_each_entry(wk, &local->work_list, list) { if (!local->ops->remain_on_channel) {
working = true; list_for_each_entry(wk, &local->work_list, list) {
wk->sdata->vif.bss_conf.idle = false; working = true;
wk->sdata->vif.bss_conf.idle = false;
}
} }
if (local->scan_sdata && if (local->scan_sdata &&
...@@ -1504,9 +1506,6 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) ...@@ -1504,9 +1506,6 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
local->scan_sdata->vif.bss_conf.idle = false; local->scan_sdata->vif.bss_conf.idle = false;
} }
if (local->hw_roc_channel)
hw_roc = true;
list_for_each_entry(sdata, &local->interfaces, list) { list_for_each_entry(sdata, &local->interfaces, list) {
if (sdata->vif.type == NL80211_IFTYPE_MONITOR || if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN) sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
...@@ -1518,7 +1517,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) ...@@ -1518,7 +1517,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
} }
if (working || scanning || hw_roc) if (working || scanning)
led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK;
else else
led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK;
...@@ -1530,8 +1529,6 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) ...@@ -1530,8 +1529,6 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop);
if (hw_roc)
return ieee80211_idle_off(local, "hw remain-on-channel");
if (working) if (working)
return ieee80211_idle_off(local, "working"); return ieee80211_idle_off(local, "working");
if (scanning) if (scanning)
......
...@@ -930,11 +930,6 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) ...@@ -930,11 +930,6 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
return; return;
} }
if (!list_empty(&local->work_list)) {
local->ps_sdata = NULL;
goto change;
}
list_for_each_entry(sdata, &local->interfaces, list) { list_for_each_entry(sdata, &local->interfaces, list) {
if (!ieee80211_sdata_running(sdata)) if (!ieee80211_sdata_running(sdata))
continue; continue;
...@@ -1007,7 +1002,6 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) ...@@ -1007,7 +1002,6 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
local->ps_sdata = NULL; local->ps_sdata = NULL;
} }
change:
ieee80211_change_ps(local); ieee80211_change_ps(local);
} }
......
...@@ -207,8 +207,6 @@ static void ieee80211_hw_roc_start(struct work_struct *work) ...@@ -207,8 +207,6 @@ static void ieee80211_hw_roc_start(struct work_struct *work)
GFP_KERNEL); GFP_KERNEL);
} }
ieee80211_recalc_idle(local);
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
} }
...@@ -260,8 +258,6 @@ static void ieee80211_hw_roc_done(struct work_struct *work) ...@@ -260,8 +258,6 @@ static void ieee80211_hw_roc_done(struct work_struct *work)
local->hw_roc_channel = NULL; local->hw_roc_channel = NULL;
local->hw_roc_cookie = 0; local->hw_roc_cookie = 0;
ieee80211_recalc_idle(local);
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment