aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2011-02-22 15:10:22 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-02-22 15:10:22 -0500
commit5db5e44cdcdc5ee9cc821bd4d63445af0bb34bce (patch)
treeb5e5787a6d5c15e589d275c7434ebbf341257234 /net/mac80211
parentdb62983a1e4b2af9e79c97af768f0c8b80bd93f0 (diff)
parent320d6c1b56de5f461c6062625b9664095f90ee95 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/Kconfig2
-rw-r--r--net/mac80211/cfg.c1
-rw-r--r--net/mac80211/debugfs.c6
-rw-r--r--net/mac80211/ibss.c11
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/main.c33
-rw-r--r--net/mac80211/mlme.c8
-rw-r--r--net/mac80211/rx.c12
-rw-r--r--net/mac80211/scan.c15
-rw-r--r--net/mac80211/tx.c1
-rw-r--r--net/mac80211/util.c6
-rw-r--r--net/mac80211/work.c59
12 files changed, 113 insertions, 43 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index c766056d0488..dbf5e4006bc1 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -17,7 +17,7 @@ comment "CFG80211 needs to be enabled for MAC80211"
17if MAC80211 != n 17if MAC80211 != n
18 18
19config MAC80211_HAS_RC 19config MAC80211_HAS_RC
20 def_bool n 20 bool
21 21
22config MAC80211_RC_PID 22config MAC80211_RC_PID
23 bool "PID controller based rate control algorithm" if EXPERT 23 bool "PID controller based rate control algorithm" if EXPERT
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 2ba3af850dda..140503d4c97a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1863,6 +1863,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
1863 1863
1864 wk->type = IEEE80211_WORK_OFFCHANNEL_TX; 1864 wk->type = IEEE80211_WORK_OFFCHANNEL_TX;
1865 wk->chan = chan; 1865 wk->chan = chan;
1866 wk->chan_type = channel_type;
1866 wk->sdata = sdata; 1867 wk->sdata = sdata;
1867 wk->done = ieee80211_offchan_tx_done; 1868 wk->done = ieee80211_offchan_tx_done;
1868 wk->offchan_tx.frame = skb; 1869 wk->offchan_tx.frame = skb;
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 1f02e599a318..51f0d780dafa 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -60,6 +60,10 @@ static const struct file_operations name## _ops = { \
60 debugfs_create_file(#name, mode, phyd, local, &name## _ops); 60 debugfs_create_file(#name, mode, phyd, local, &name## _ops);
61 61
62 62
63DEBUGFS_READONLY_FILE(user_power, "%d",
64 local->user_power_level);
65DEBUGFS_READONLY_FILE(power, "%d",
66 local->hw.conf.power_level);
63DEBUGFS_READONLY_FILE(frequency, "%d", 67DEBUGFS_READONLY_FILE(frequency, "%d",
64 local->hw.conf.channel->center_freq); 68 local->hw.conf.channel->center_freq);
65DEBUGFS_READONLY_FILE(total_ps_buffered, "%d", 69DEBUGFS_READONLY_FILE(total_ps_buffered, "%d",
@@ -391,6 +395,8 @@ void debugfs_hw_add(struct ieee80211_local *local)
391 DEBUGFS_ADD(uapsd_queues); 395 DEBUGFS_ADD(uapsd_queues);
392 DEBUGFS_ADD(uapsd_max_sp_len); 396 DEBUGFS_ADD(uapsd_max_sp_len);
393 DEBUGFS_ADD(channel_type); 397 DEBUGFS_ADD(channel_type);
398 DEBUGFS_ADD(user_power);
399 DEBUGFS_ADD(power);
394 400
395 statsd = debugfs_create_dir("statistics", phyd); 401 statsd = debugfs_create_dir("statistics", phyd);
396 402
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 775fb63471c4..a42aa61269ea 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -664,12 +664,13 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
664} 664}
665 665
666static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, 666static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
667 struct ieee80211_mgmt *mgmt, 667 struct sk_buff *req)
668 size_t len)
669{ 668{
669 struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(req);
670 struct ieee80211_mgmt *mgmt = (void *)req->data;
670 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 671 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
671 struct ieee80211_local *local = sdata->local; 672 struct ieee80211_local *local = sdata->local;
672 int tx_last_beacon; 673 int tx_last_beacon, len = req->len;
673 struct sk_buff *skb; 674 struct sk_buff *skb;
674 struct ieee80211_mgmt *resp; 675 struct ieee80211_mgmt *resp;
675 u8 *pos, *end; 676 u8 *pos, *end;
@@ -689,7 +690,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
689 mgmt->bssid, tx_last_beacon); 690 mgmt->bssid, tx_last_beacon);
690#endif /* CONFIG_MAC80211_IBSS_DEBUG */ 691#endif /* CONFIG_MAC80211_IBSS_DEBUG */
691 692
692 if (!tx_last_beacon) 693 if (!tx_last_beacon && !(rx_status->rx_flags & IEEE80211_RX_RA_MATCH))
693 return; 694 return;
694 695
695 if (memcmp(mgmt->bssid, ifibss->bssid, ETH_ALEN) != 0 && 696 if (memcmp(mgmt->bssid, ifibss->bssid, ETH_ALEN) != 0 &&
@@ -786,7 +787,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
786 787
787 switch (fc & IEEE80211_FCTL_STYPE) { 788 switch (fc & IEEE80211_FCTL_STYPE) {
788 case IEEE80211_STYPE_PROBE_REQ: 789 case IEEE80211_STYPE_PROBE_REQ:
789 ieee80211_rx_mgmt_probe_req(sdata, mgmt, skb->len); 790 ieee80211_rx_mgmt_probe_req(sdata, skb);
790 break; 791 break;
791 case IEEE80211_STYPE_PROBE_RESP: 792 case IEEE80211_STYPE_PROBE_RESP:
792 ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, 793 ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f2ef15d910a5..0a570a111a84 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1066,8 +1066,6 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
1066void ieee80211_configure_filter(struct ieee80211_local *local); 1066void ieee80211_configure_filter(struct ieee80211_local *local);
1067u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); 1067u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata);
1068 1068
1069extern bool ieee80211_disable_40mhz_24ghz;
1070
1071/* STA code */ 1069/* STA code */
1072void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); 1070void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata);
1073int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, 1071int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index c155c0b69426..2543e48bd813 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -34,7 +34,7 @@
34#include "debugfs.h" 34#include "debugfs.h"
35 35
36 36
37bool ieee80211_disable_40mhz_24ghz; 37static bool ieee80211_disable_40mhz_24ghz;
38module_param(ieee80211_disable_40mhz_24ghz, bool, 0644); 38module_param(ieee80211_disable_40mhz_24ghz, bool, 0644);
39MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz, 39MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz,
40 "Disable 40MHz support in the 2.4GHz band"); 40 "Disable 40MHz support in the 2.4GHz band");
@@ -112,7 +112,13 @@ bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local)
112 /* This logic needs to match logic in ieee80211_hw_config */ 112 /* This logic needs to match logic in ieee80211_hw_config */
113 if (local->scan_channel) { 113 if (local->scan_channel) {
114 chan = local->scan_channel; 114 chan = local->scan_channel;
115 channel_type = NL80211_CHAN_NO_HT; 115 /* If scanning on oper channel, use whatever channel-type
116 * is currently in use.
117 */
118 if (chan == local->oper_channel)
119 channel_type = local->_oper_channel_type;
120 else
121 channel_type = NL80211_CHAN_NO_HT;
116 } else if (local->tmp_channel) { 122 } else if (local->tmp_channel) {
117 chan = scan_chan = local->tmp_channel; 123 chan = scan_chan = local->tmp_channel;
118 channel_type = local->tmp_channel_type; 124 channel_type = local->tmp_channel_type;
@@ -151,7 +157,13 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
151 offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; 157 offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
152 if (scan_chan) { 158 if (scan_chan) {
153 chan = scan_chan; 159 chan = scan_chan;
154 channel_type = NL80211_CHAN_NO_HT; 160 /* If scanning on oper channel, use whatever channel-type
161 * is currently in use.
162 */
163 if (chan == local->oper_channel)
164 channel_type = local->_oper_channel_type;
165 else
166 channel_type = NL80211_CHAN_NO_HT;
155 } else if (local->tmp_channel) { 167 } else if (local->tmp_channel) {
156 chan = scan_chan = local->tmp_channel; 168 chan = scan_chan = local->tmp_channel;
157 channel_type = local->tmp_channel_type; 169 channel_type = local->tmp_channel_type;
@@ -187,7 +199,8 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
187 changed |= IEEE80211_CONF_CHANGE_SMPS; 199 changed |= IEEE80211_CONF_CHANGE_SMPS;
188 } 200 }
189 201
190 if (scan_chan) 202 if ((local->scanning & SCAN_SW_SCANNING) ||
203 (local->scanning & SCAN_HW_SCANNING))
191 power = chan->max_power; 204 power = chan->max_power;
192 else 205 else
193 power = local->power_constr_level ? 206 power = local->power_constr_level ?
@@ -710,6 +723,18 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
710 } 723 }
711 channels += sband->n_channels; 724 channels += sband->n_channels;
712 725
726 /*
727 * Since ieee80211_disable_40mhz_24ghz is global, we can
728 * modify the sband's ht data even if the driver uses a
729 * global structure for that.
730 */
731 if (ieee80211_disable_40mhz_24ghz &&
732 band == IEEE80211_BAND_2GHZ &&
733 sband->ht_cap.ht_supported) {
734 sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
735 sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
736 }
737
713 if (max_bitrates < sband->n_bitrates) 738 if (max_bitrates < sband->n_bitrates)
714 max_bitrates = sband->n_bitrates; 739 max_bitrates = sband->n_bitrates;
715 supp_ht = supp_ht || sband->ht_cap.ht_supported; 740 supp_ht = supp_ht || sband->ht_cap.ht_supported;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index f77adf1a520e..7b3f9df725bd 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1071,6 +1071,12 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
1071 if (is_multicast_ether_addr(hdr->addr1)) 1071 if (is_multicast_ether_addr(hdr->addr1))
1072 return; 1072 return;
1073 1073
1074 /*
1075 * In case we receive frames after disassociation.
1076 */
1077 if (!sdata->u.mgd.associated)
1078 return;
1079
1074 ieee80211_sta_reset_conn_monitor(sdata); 1080 ieee80211_sta_reset_conn_monitor(sdata);
1075} 1081}
1076 1082
@@ -2294,6 +2300,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
2294 else 2300 else
2295 wk->type = IEEE80211_WORK_DIRECT_PROBE; 2301 wk->type = IEEE80211_WORK_DIRECT_PROBE;
2296 wk->chan = req->bss->channel; 2302 wk->chan = req->bss->channel;
2303 wk->chan_type = NL80211_CHAN_NO_HT;
2297 wk->sdata = sdata; 2304 wk->sdata = sdata;
2298 wk->done = ieee80211_probe_auth_done; 2305 wk->done = ieee80211_probe_auth_done;
2299 2306
@@ -2443,6 +2450,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
2443 memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN); 2450 memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN);
2444 2451
2445 wk->chan = req->bss->channel; 2452 wk->chan = req->bss->channel;
2453 wk->chan_type = NL80211_CHAN_NO_HT;
2446 wk->sdata = sdata; 2454 wk->sdata = sdata;
2447 wk->done = ieee80211_assoc_done; 2455 wk->done = ieee80211_assoc_done;
2448 if (!bss->dtim_period && 2456 if (!bss->dtim_period &&
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 045b2fe4a414..f502634d43af 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -832,18 +832,8 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
832 ieee80211_is_pspoll(hdr->frame_control)) && 832 ieee80211_is_pspoll(hdr->frame_control)) &&
833 rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && 833 rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
834 rx->sdata->vif.type != NL80211_IFTYPE_WDS && 834 rx->sdata->vif.type != NL80211_IFTYPE_WDS &&
835 (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { 835 (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC))))
836 if ((!ieee80211_has_fromds(hdr->frame_control) &&
837 !ieee80211_has_tods(hdr->frame_control) &&
838 ieee80211_is_data(hdr->frame_control)) ||
839 !(status->rx_flags & IEEE80211_RX_RA_MATCH)) {
840 /* Drop IBSS frames and frames for other hosts
841 * silently. */
842 return RX_DROP_MONITOR;
843 }
844
845 return RX_DROP_MONITOR; 836 return RX_DROP_MONITOR;
846 }
847 837
848 return RX_CONTINUE; 838 return RX_CONTINUE;
849} 839}
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 0ea6adae3e06..842954509925 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -307,11 +307,15 @@ static void __ieee80211_scan_completed_finish(struct ieee80211_hw *hw,
307 mutex_lock(&local->mtx); 307 mutex_lock(&local->mtx);
308 on_oper_chan = ieee80211_cfg_on_oper_channel(local); 308 on_oper_chan = ieee80211_cfg_on_oper_channel(local);
309 309
310 WARN_ON(local->scanning & (SCAN_SW_SCANNING | SCAN_HW_SCANNING));
311
310 if (was_hw_scan || !on_oper_chan) { 312 if (was_hw_scan || !on_oper_chan) {
311 if (WARN_ON(local->scan_channel)) 313 if (WARN_ON(local->scan_channel))
312 local->scan_channel = NULL; 314 local->scan_channel = NULL;
313 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); 315 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
314 } 316 } else
317 /* Set power back to normal operating levels. */
318 ieee80211_hw_config(local, 0);
315 319
316 if (!was_hw_scan) { 320 if (!was_hw_scan) {
317 bool on_oper_chan2; 321 bool on_oper_chan2;
@@ -377,6 +381,9 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
377 381
378 ieee80211_configure_filter(local); 382 ieee80211_configure_filter(local);
379 383
384 /* We need to set power level at maximum rate for scanning. */
385 ieee80211_hw_config(local, 0);
386
380 ieee80211_queue_delayed_work(&local->hw, 387 ieee80211_queue_delayed_work(&local->hw,
381 &local->scan_work, 388 &local->scan_work,
382 IEEE80211_CHANNEL_TIME); 389 IEEE80211_CHANNEL_TIME);
@@ -517,8 +524,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
517 524
518 if (ieee80211_cfg_on_oper_channel(local)) { 525 if (ieee80211_cfg_on_oper_channel(local)) {
519 /* We're currently on operating channel. */ 526 /* We're currently on operating channel. */
520 if ((next_chan == local->oper_channel) && 527 if (next_chan == local->oper_channel)
521 (local->_oper_channel_type == NL80211_CHAN_NO_HT))
522 /* We don't need to move off of operating channel. */ 528 /* We don't need to move off of operating channel. */
523 local->next_scan_state = SCAN_SET_CHANNEL; 529 local->next_scan_state = SCAN_SET_CHANNEL;
524 else 530 else
@@ -620,8 +626,7 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
620 local->scan_channel = chan; 626 local->scan_channel = chan;
621 627
622 /* Only call hw-config if we really need to change channels. */ 628 /* Only call hw-config if we really need to change channels. */
623 if ((chan != local->hw.conf.channel) || 629 if (chan != local->hw.conf.channel)
624 (local->hw.conf.channel_type != NL80211_CHAN_NO_HT))
625 if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL)) 630 if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL))
626 skip = 1; 631 skip = 1;
627 632
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 17ef4f4e8602..34edf7f22b0e 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -236,6 +236,7 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
236 if (local->hw.conf.flags & IEEE80211_CONF_PS) { 236 if (local->hw.conf.flags & IEEE80211_CONF_PS) {
237 ieee80211_stop_queues_by_reason(&local->hw, 237 ieee80211_stop_queues_by_reason(&local->hw,
238 IEEE80211_QUEUE_STOP_REASON_PS); 238 IEEE80211_QUEUE_STOP_REASON_PS);
239 ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
239 ieee80211_queue_work(&local->hw, 240 ieee80211_queue_work(&local->hw,
240 &local->dynamic_ps_disable_work); 241 &local->dynamic_ps_disable_work);
241 } 242 }
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index d036597aabbe..556647a910ac 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -986,12 +986,6 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
986 u16 cap = sband->ht_cap.cap; 986 u16 cap = sband->ht_cap.cap;
987 __le16 tmp; 987 __le16 tmp;
988 988
989 if (ieee80211_disable_40mhz_24ghz &&
990 sband->band == IEEE80211_BAND_2GHZ) {
991 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
992 cap &= ~IEEE80211_HT_CAP_SGI_40;
993 }
994
995 *pos++ = WLAN_EID_HT_CAPABILITY; 989 *pos++ = WLAN_EID_HT_CAPABILITY;
996 *pos++ = sizeof(struct ieee80211_ht_cap); 990 *pos++ = sizeof(struct ieee80211_ht_cap);
997 memset(pos, 0, sizeof(struct ieee80211_ht_cap)); 991 memset(pos, 0, sizeof(struct ieee80211_ht_cap));
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 }