127
126
/* determine capability flags */
129
if (ieee80211_disable_40mhz_24ghz &&
130
sband->band == IEEE80211_BAND_2GHZ) {
131
cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
132
cap &= ~IEEE80211_HT_CAP_SGI_40;
135
128
switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
136
129
case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
137
130
if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
870
static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct,
871
enum nl80211_channel_type oper_ct)
874
case NL80211_CHAN_NO_HT:
876
case NL80211_CHAN_HT20:
877
if (oper_ct != NL80211_CHAN_NO_HT)
880
case NL80211_CHAN_HT40MINUS:
881
case NL80211_CHAN_HT40PLUS:
882
return (wk_ct == oper_ct);
884
WARN_ON(1); /* shouldn't get here */
888
static enum nl80211_channel_type
889
ieee80211_calc_ct(enum nl80211_channel_type wk_ct,
890
enum nl80211_channel_type oper_ct)
893
case NL80211_CHAN_NO_HT:
895
case NL80211_CHAN_HT20:
896
if (oper_ct != NL80211_CHAN_NO_HT)
899
case NL80211_CHAN_HT40MINUS:
900
case NL80211_CHAN_HT40PLUS:
903
WARN_ON(1); /* shouldn't get here */
877
908
static void ieee80211_work_timer(unsigned long data)
879
910
struct ieee80211_local *local = (void *) data;
926
957
if (!started && !local->tmp_channel) {
928
* TODO: could optimize this by leaving the
929
* station vifs in awake mode if they
930
* happen to be on the same channel as
931
* the requested channel
933
ieee80211_offchannel_stop_beaconing(local);
934
ieee80211_offchannel_stop_station(local);
959
bool tmp_chan_changed = false;
961
enum nl80211_channel_type wk_ct;
962
on_oper_chan = ieee80211_cfg_on_oper_channel(local);
964
/* Work with existing channel type if possible. */
965
wk_ct = wk->chan_type;
966
if (wk->chan == local->hw.conf.channel)
967
wk_ct = ieee80211_calc_ct(wk->chan_type,
968
local->hw.conf.channel_type);
970
if (local->tmp_channel)
971
if ((local->tmp_channel != wk->chan) ||
972
(local->tmp_channel_type != wk_ct))
973
tmp_chan_changed = true;
936
975
local->tmp_channel = wk->chan;
937
local->tmp_channel_type = wk->chan_type;
938
ieee80211_hw_config(local, 0);
976
local->tmp_channel_type = wk_ct;
978
* Leave the station vifs in awake mode if they
979
* happen to be on the same channel as
980
* the requested channel.
982
on_oper_chan2 = ieee80211_cfg_on_oper_channel(local);
983
if (on_oper_chan != on_oper_chan2) {
985
/* going off oper channel, PS too */
986
ieee80211_offchannel_stop_vifs(local,
988
ieee80211_hw_config(local, 0);
990
/* going on channel, but leave PS
992
ieee80211_hw_config(local, 0);
993
ieee80211_offchannel_return(local,
997
} else if (tmp_chan_changed)
998
/* Still off-channel, but on some other
999
* channel, so update hardware.
1000
* PS should already be off-channel.
1002
ieee80211_hw_config(local, 0);
940
1005
wk->timeout = jiffies;
1006
1071
if (wk->chan != local->tmp_channel)
1008
if (wk->chan_type != local->tmp_channel_type)
1073
if (ieee80211_work_ct_coexists(wk->chan_type,
1074
local->tmp_channel_type))
1010
1076
remain_off_channel = true;
1013
1079
if (!remain_off_channel && local->tmp_channel) {
1080
bool on_oper_chan = ieee80211_cfg_on_oper_channel(local);
1014
1081
local->tmp_channel = NULL;
1015
ieee80211_hw_config(local, 0);
1016
ieee80211_offchannel_return(local, true);
1082
/* If tmp_channel wasn't operating channel, then
1083
* we need to go back on-channel.
1084
* NOTE: If we can ever be here while scannning,
1085
* or if the hw_config() channel config logic changes,
1086
* then we may need to do a more thorough check to see if
1087
* we still need to do a hardware config. Currently,
1088
* we cannot be here while scanning, however.
1090
if (ieee80211_cfg_on_oper_channel(local) && !on_oper_chan)
1091
ieee80211_hw_config(local, 0);
1093
/* At the least, we need to disable offchannel_ps,
1094
* so just go ahead and run the entire offchannel
1095
* return logic here. We *could* skip enabling
1096
* beaconing if we were already on-oper-channel
1097
* as a future optimization.
1099
ieee80211_offchannel_return(local, true, true);
1017
1101
/* give connection some time to breathe */
1018
1102
run_again(local, jiffies + HZ/2);