aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r--net/mac80211/main.c88
1 files changed, 79 insertions, 9 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index a46ff06d7cb8..562d2984c482 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");
@@ -98,6 +98,47 @@ static void ieee80211_reconfig_filter(struct work_struct *work)
98 ieee80211_configure_filter(local); 98 ieee80211_configure_filter(local);
99} 99}
100 100
101/*
102 * Returns true if we are logically configured to be on
103 * the operating channel AND the hardware-conf is currently
104 * configured on the operating channel. Compares channel-type
105 * as well.
106 */
107bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local)
108{
109 struct ieee80211_channel *chan, *scan_chan;
110 enum nl80211_channel_type channel_type;
111
112 /* This logic needs to match logic in ieee80211_hw_config */
113 if (local->scan_channel) {
114 chan = local->scan_channel;
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;
122 } else if (local->tmp_channel) {
123 chan = scan_chan = local->tmp_channel;
124 channel_type = local->tmp_channel_type;
125 } else {
126 chan = local->oper_channel;
127 channel_type = local->_oper_channel_type;
128 }
129
130 if (chan != local->oper_channel ||
131 channel_type != local->_oper_channel_type)
132 return false;
133
134 /* Check current hardware-config against oper_channel. */
135 if ((local->oper_channel != local->hw.conf.channel) ||
136 (local->_oper_channel_type != local->hw.conf.channel_type))
137 return false;
138
139 return true;
140}
141
101int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) 142int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
102{ 143{
103 struct ieee80211_channel *chan, *scan_chan; 144 struct ieee80211_channel *chan, *scan_chan;
@@ -110,21 +151,33 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
110 151
111 scan_chan = local->scan_channel; 152 scan_chan = local->scan_channel;
112 153
154 /* If this off-channel logic ever changes, ieee80211_on_oper_channel
155 * may need to change as well.
156 */
113 offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; 157 offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
114 if (scan_chan) { 158 if (scan_chan) {
115 chan = scan_chan; 159 chan = scan_chan;
116 channel_type = NL80211_CHAN_NO_HT; 160 /* If scanning on oper channel, use whatever channel-type
117 local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; 161 * is currently in use.
118 } else if (local->tmp_channel && 162 */
119 local->oper_channel != local->tmp_channel) { 163 if (chan == local->oper_channel)
164 channel_type = local->_oper_channel_type;
165 else
166 channel_type = NL80211_CHAN_NO_HT;
167 } else if (local->tmp_channel) {
120 chan = scan_chan = local->tmp_channel; 168 chan = scan_chan = local->tmp_channel;
121 channel_type = local->tmp_channel_type; 169 channel_type = local->tmp_channel_type;
122 local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
123 } else { 170 } else {
124 chan = local->oper_channel; 171 chan = local->oper_channel;
125 channel_type = local->_oper_channel_type; 172 channel_type = local->_oper_channel_type;
126 local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
127 } 173 }
174
175 if (chan != local->oper_channel ||
176 channel_type != local->_oper_channel_type)
177 local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
178 else
179 local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
180
128 offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; 181 offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
129 182
130 if (offchannel_flag || chan != local->hw.conf.channel || 183 if (offchannel_flag || chan != local->hw.conf.channel ||
@@ -146,7 +199,8 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
146 changed |= IEEE80211_CONF_CHANGE_SMPS; 199 changed |= IEEE80211_CONF_CHANGE_SMPS;
147 } 200 }
148 201
149 if (scan_chan) 202 if ((local->scanning & SCAN_SW_SCANNING) ||
203 (local->scanning & SCAN_HW_SCANNING))
150 power = chan->max_power; 204 power = chan->max_power;
151 else 205 else
152 power = local->power_constr_level ? 206 power = local->power_constr_level ?
@@ -231,7 +285,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
231 285
232 if (changed & BSS_CHANGED_BEACON_ENABLED) { 286 if (changed & BSS_CHANGED_BEACON_ENABLED) {
233 if (local->quiescing || !ieee80211_sdata_running(sdata) || 287 if (local->quiescing || !ieee80211_sdata_running(sdata) ||
234 test_bit(SCAN_SW_SCANNING, &local->scanning)) { 288 test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) {
235 sdata->vif.bss_conf.enable_beacon = false; 289 sdata->vif.bss_conf.enable_beacon = false;
236 } else { 290 } else {
237 /* 291 /*
@@ -326,6 +380,9 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
326 380
327 trace_api_restart_hw(local); 381 trace_api_restart_hw(local);
328 382
383 wiphy_info(hw->wiphy,
384 "Hardware restart was requested\n");
385
329 /* use this reason, ieee80211_reconfig will unblock it */ 386 /* use this reason, ieee80211_reconfig will unblock it */
330 ieee80211_stop_queues_by_reason(hw, 387 ieee80211_stop_queues_by_reason(hw,
331 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 388 IEEE80211_QUEUE_STOP_REASON_SUSPEND);
@@ -554,6 +611,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
554 local->hw.queues = 1; 611 local->hw.queues = 1;
555 local->hw.max_rates = 1; 612 local->hw.max_rates = 1;
556 local->hw.max_report_rates = 0; 613 local->hw.max_report_rates = 0;
614 local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
557 local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; 615 local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
558 local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; 616 local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
559 local->user_power_level = -1; 617 local->user_power_level = -1;
@@ -668,6 +726,18 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
668 } 726 }
669 channels += sband->n_channels; 727 channels += sband->n_channels;
670 728
729 /*
730 * Since ieee80211_disable_40mhz_24ghz is global, we can
731 * modify the sband's ht data even if the driver uses a
732 * global structure for that.
733 */
734 if (ieee80211_disable_40mhz_24ghz &&
735 band == IEEE80211_BAND_2GHZ &&
736 sband->ht_cap.ht_supported) {
737 sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
738 sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
739 }
740
671 if (max_bitrates < sband->n_bitrates) 741 if (max_bitrates < sband->n_bitrates)
672 max_bitrates = sband->n_bitrates; 742 max_bitrates = sband->n_bitrates;
673 supp_ht = supp_ht || sband->ht_cap.ht_supported; 743 supp_ht = supp_ht || sband->ht_cap.ht_supported;