diff options
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r-- | net/mac80211/main.c | 88 |
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 | ||
37 | bool ieee80211_disable_40mhz_24ghz; | 37 | static bool ieee80211_disable_40mhz_24ghz; |
38 | module_param(ieee80211_disable_40mhz_24ghz, bool, 0644); | 38 | module_param(ieee80211_disable_40mhz_24ghz, bool, 0644); |
39 | MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz, | 39 | MODULE_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 | */ | ||
107 | bool 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 | |||
101 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | 142 | int 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; |