aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/work.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/work.c')
-rw-r--r--net/mac80211/work.c59
1 files changed, 50 insertions, 9 deletions
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index 6bf787a5b38a..204f0a4db969 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -126,12 +126,6 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
126 126
127 /* determine capability flags */ 127 /* determine capability flags */
128 128
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;
133 }
134
135 switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { 129 switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
136 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: 130 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
137 if (flags & IEEE80211_CHAN_NO_HT40PLUS) { 131 if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
@@ -874,6 +868,44 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
874 kfree_skb(skb); 868 kfree_skb(skb);
875} 869}
876 870
871static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct,
872 enum nl80211_channel_type oper_ct)
873{
874 switch (wk_ct) {
875 case NL80211_CHAN_NO_HT:
876 return true;
877 case NL80211_CHAN_HT20:
878 if (oper_ct != NL80211_CHAN_NO_HT)
879 return true;
880 return false;
881 case NL80211_CHAN_HT40MINUS:
882 case NL80211_CHAN_HT40PLUS:
883 return (wk_ct == oper_ct);
884 }
885 WARN_ON(1); /* shouldn't get here */
886 return false;
887}
888
889static enum nl80211_channel_type
890ieee80211_calc_ct(enum nl80211_channel_type wk_ct,
891 enum nl80211_channel_type oper_ct)
892{
893 switch (wk_ct) {
894 case NL80211_CHAN_NO_HT:
895 return oper_ct;
896 case NL80211_CHAN_HT20:
897 if (oper_ct != NL80211_CHAN_NO_HT)
898 return oper_ct;
899 return wk_ct;
900 case NL80211_CHAN_HT40MINUS:
901 case NL80211_CHAN_HT40PLUS:
902 return wk_ct;
903 }
904 WARN_ON(1); /* shouldn't get here */
905 return wk_ct;
906}
907
908
877static void ieee80211_work_timer(unsigned long data) 909static void ieee80211_work_timer(unsigned long data)
878{ 910{
879 struct ieee80211_local *local = (void *) data; 911 struct ieee80211_local *local = (void *) data;
@@ -927,14 +959,22 @@ static void ieee80211_work_work(struct work_struct *work)
927 bool on_oper_chan; 959 bool on_oper_chan;
928 bool tmp_chan_changed = false; 960 bool tmp_chan_changed = false;
929 bool on_oper_chan2; 961 bool on_oper_chan2;
962 enum nl80211_channel_type wk_ct;
930 on_oper_chan = ieee80211_cfg_on_oper_channel(local); 963 on_oper_chan = ieee80211_cfg_on_oper_channel(local);
964
965 /* Work with existing channel type if possible. */
966 wk_ct = wk->chan_type;
967 if (wk->chan == local->hw.conf.channel)
968 wk_ct = ieee80211_calc_ct(wk->chan_type,
969 local->hw.conf.channel_type);
970
931 if (local->tmp_channel) 971 if (local->tmp_channel)
932 if ((local->tmp_channel != wk->chan) || 972 if ((local->tmp_channel != wk->chan) ||
933 (local->tmp_channel_type != wk->chan_type)) 973 (local->tmp_channel_type != wk_ct))
934 tmp_chan_changed = true; 974 tmp_chan_changed = true;
935 975
936 local->tmp_channel = wk->chan; 976 local->tmp_channel = wk->chan;
937 local->tmp_channel_type = wk->chan_type; 977 local->tmp_channel_type = wk_ct;
938 /* 978 /*
939 * Leave the station vifs in awake mode if they 979 * Leave the station vifs in awake mode if they
940 * happen to be on the same channel as 980 * happen to be on the same channel as
@@ -1031,7 +1071,8 @@ static void ieee80211_work_work(struct work_struct *work)
1031 continue; 1071 continue;
1032 if (wk->chan != local->tmp_channel) 1072 if (wk->chan != local->tmp_channel)
1033 continue; 1073 continue;
1034 if (wk->chan_type != local->tmp_channel_type) 1074 if (ieee80211_work_ct_coexists(wk->chan_type,
1075 local->tmp_channel_type))
1035 continue; 1076 continue;
1036 remain_off_channel = true; 1077 remain_off_channel = true;
1037 } 1078 }