diff options
author | Stanislaw Gruszka <sgruszka@redhat.com> | 2011-11-15 07:18:51 -0500 |
---|---|---|
committer | Stanislaw Gruszka <sgruszka@redhat.com> | 2011-11-15 07:18:51 -0500 |
commit | 4ed47911a2e0f9a425d22253433452ffa59d533e (patch) | |
tree | f8b3c1a2a1f5c6300dd736047c5495ccd9115894 /drivers/net/wireless/iwlegacy/common.c | |
parent | d2dfb33ec9a8da257bb0e6ed2872af2fdf85260c (diff) |
iwlegacy: rename iwl-core.c to common.c
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Diffstat (limited to 'drivers/net/wireless/iwlegacy/common.c')
-rw-r--r-- | drivers/net/wireless/iwlegacy/common.c | 2608 |
1 files changed, 2608 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c new file mode 100644 index 000000000000..856a321ed1ea --- /dev/null +++ b/drivers/net/wireless/iwlegacy/common.c | |||
@@ -0,0 +1,2608 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | *****************************************************************************/ | ||
28 | |||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/etherdevice.h> | ||
32 | #include <linux/sched.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <net/mac80211.h> | ||
35 | |||
36 | #include "iwl-eeprom.h" | ||
37 | #include "iwl-dev.h" | ||
38 | #include "iwl-debug.h" | ||
39 | #include "iwl-core.h" | ||
40 | #include "iwl-io.h" | ||
41 | #include "iwl-power.h" | ||
42 | #include "iwl-sta.h" | ||
43 | #include "iwl-helpers.h" | ||
44 | |||
45 | |||
46 | MODULE_DESCRIPTION("iwl-legacy: common functions for 3945 and 4965"); | ||
47 | MODULE_VERSION(IWLWIFI_VERSION); | ||
48 | MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); | ||
49 | MODULE_LICENSE("GPL"); | ||
50 | |||
51 | /* | ||
52 | * set bt_coex_active to true, uCode will do kill/defer | ||
53 | * every time the priority line is asserted (BT is sending signals on the | ||
54 | * priority line in the PCIx). | ||
55 | * set bt_coex_active to false, uCode will ignore the BT activity and | ||
56 | * perform the normal operation | ||
57 | * | ||
58 | * User might experience transmit issue on some platform due to WiFi/BT | ||
59 | * co-exist problem. The possible behaviors are: | ||
60 | * Able to scan and finding all the available AP | ||
61 | * Not able to associate with any AP | ||
62 | * On those platforms, WiFi communication can be restored by set | ||
63 | * "bt_coex_active" module parameter to "false" | ||
64 | * | ||
65 | * default: bt_coex_active = true (BT_COEX_ENABLE) | ||
66 | */ | ||
67 | static bool bt_coex_active = true; | ||
68 | module_param(bt_coex_active, bool, S_IRUGO); | ||
69 | MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist"); | ||
70 | |||
71 | u32 il_debug_level; | ||
72 | EXPORT_SYMBOL(il_debug_level); | ||
73 | |||
74 | const u8 il_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | ||
75 | EXPORT_SYMBOL(il_bcast_addr); | ||
76 | |||
77 | |||
78 | /* This function both allocates and initializes hw and il. */ | ||
79 | struct ieee80211_hw *il_alloc_all(struct il_cfg *cfg) | ||
80 | { | ||
81 | struct il_priv *il; | ||
82 | /* mac80211 allocates memory for this device instance, including | ||
83 | * space for this driver's ilate structure */ | ||
84 | struct ieee80211_hw *hw; | ||
85 | |||
86 | hw = ieee80211_alloc_hw(sizeof(struct il_priv), | ||
87 | cfg->ops->ieee80211_ops); | ||
88 | if (hw == NULL) { | ||
89 | pr_err("%s: Can not allocate network device\n", | ||
90 | cfg->name); | ||
91 | goto out; | ||
92 | } | ||
93 | |||
94 | il = hw->priv; | ||
95 | il->hw = hw; | ||
96 | |||
97 | out: | ||
98 | return hw; | ||
99 | } | ||
100 | EXPORT_SYMBOL(il_alloc_all); | ||
101 | |||
102 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ | ||
103 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ | ||
104 | static void il_init_ht_hw_capab(const struct il_priv *il, | ||
105 | struct ieee80211_sta_ht_cap *ht_info, | ||
106 | enum ieee80211_band band) | ||
107 | { | ||
108 | u16 max_bit_rate = 0; | ||
109 | u8 rx_chains_num = il->hw_params.rx_chains_num; | ||
110 | u8 tx_chains_num = il->hw_params.tx_chains_num; | ||
111 | |||
112 | ht_info->cap = 0; | ||
113 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); | ||
114 | |||
115 | ht_info->ht_supported = true; | ||
116 | |||
117 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | ||
118 | max_bit_rate = MAX_BIT_RATE_20_MHZ; | ||
119 | if (il->hw_params.ht40_channel & BIT(band)) { | ||
120 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
121 | ht_info->cap |= IEEE80211_HT_CAP_SGI_40; | ||
122 | ht_info->mcs.rx_mask[4] = 0x01; | ||
123 | max_bit_rate = MAX_BIT_RATE_40_MHZ; | ||
124 | } | ||
125 | |||
126 | if (il->cfg->mod_params->amsdu_size_8K) | ||
127 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; | ||
128 | |||
129 | ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; | ||
130 | ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF; | ||
131 | |||
132 | ht_info->mcs.rx_mask[0] = 0xFF; | ||
133 | if (rx_chains_num >= 2) | ||
134 | ht_info->mcs.rx_mask[1] = 0xFF; | ||
135 | if (rx_chains_num >= 3) | ||
136 | ht_info->mcs.rx_mask[2] = 0xFF; | ||
137 | |||
138 | /* Highest supported Rx data rate */ | ||
139 | max_bit_rate *= rx_chains_num; | ||
140 | WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK); | ||
141 | ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate); | ||
142 | |||
143 | /* Tx MCS capabilities */ | ||
144 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
145 | if (tx_chains_num != rx_chains_num) { | ||
146 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | ||
147 | ht_info->mcs.tx_params |= ((tx_chains_num - 1) << | ||
148 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); | ||
149 | } | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * il_init_geos - Initialize mac80211's geo/channel info based from eeprom | ||
154 | */ | ||
155 | int il_init_geos(struct il_priv *il) | ||
156 | { | ||
157 | struct il_channel_info *ch; | ||
158 | struct ieee80211_supported_band *sband; | ||
159 | struct ieee80211_channel *channels; | ||
160 | struct ieee80211_channel *geo_ch; | ||
161 | struct ieee80211_rate *rates; | ||
162 | int i = 0; | ||
163 | s8 max_tx_power = 0; | ||
164 | |||
165 | if (il->bands[IEEE80211_BAND_2GHZ].n_bitrates || | ||
166 | il->bands[IEEE80211_BAND_5GHZ].n_bitrates) { | ||
167 | D_INFO("Geography modes already initialized.\n"); | ||
168 | set_bit(S_GEO_CONFIGURED, &il->status); | ||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | channels = kzalloc(sizeof(struct ieee80211_channel) * | ||
173 | il->channel_count, GFP_KERNEL); | ||
174 | if (!channels) | ||
175 | return -ENOMEM; | ||
176 | |||
177 | rates = kzalloc((sizeof(struct ieee80211_rate) * RATE_COUNT_LEGACY), | ||
178 | GFP_KERNEL); | ||
179 | if (!rates) { | ||
180 | kfree(channels); | ||
181 | return -ENOMEM; | ||
182 | } | ||
183 | |||
184 | /* 5.2GHz channels start after the 2.4GHz channels */ | ||
185 | sband = &il->bands[IEEE80211_BAND_5GHZ]; | ||
186 | sband->channels = &channels[ARRAY_SIZE(il_eeprom_band_1)]; | ||
187 | /* just OFDM */ | ||
188 | sband->bitrates = &rates[IL_FIRST_OFDM_RATE]; | ||
189 | sband->n_bitrates = RATE_COUNT_LEGACY - IL_FIRST_OFDM_RATE; | ||
190 | |||
191 | if (il->cfg->sku & IL_SKU_N) | ||
192 | il_init_ht_hw_capab(il, &sband->ht_cap, | ||
193 | IEEE80211_BAND_5GHZ); | ||
194 | |||
195 | sband = &il->bands[IEEE80211_BAND_2GHZ]; | ||
196 | sband->channels = channels; | ||
197 | /* OFDM & CCK */ | ||
198 | sband->bitrates = rates; | ||
199 | sband->n_bitrates = RATE_COUNT_LEGACY; | ||
200 | |||
201 | if (il->cfg->sku & IL_SKU_N) | ||
202 | il_init_ht_hw_capab(il, &sband->ht_cap, | ||
203 | IEEE80211_BAND_2GHZ); | ||
204 | |||
205 | il->ieee_channels = channels; | ||
206 | il->ieee_rates = rates; | ||
207 | |||
208 | for (i = 0; i < il->channel_count; i++) { | ||
209 | ch = &il->channel_info[i]; | ||
210 | |||
211 | if (!il_is_channel_valid(ch)) | ||
212 | continue; | ||
213 | |||
214 | sband = &il->bands[ch->band]; | ||
215 | |||
216 | geo_ch = &sband->channels[sband->n_channels++]; | ||
217 | |||
218 | geo_ch->center_freq = | ||
219 | ieee80211_channel_to_frequency(ch->channel, ch->band); | ||
220 | geo_ch->max_power = ch->max_power_avg; | ||
221 | geo_ch->max_antenna_gain = 0xff; | ||
222 | geo_ch->hw_value = ch->channel; | ||
223 | |||
224 | if (il_is_channel_valid(ch)) { | ||
225 | if (!(ch->flags & EEPROM_CHANNEL_IBSS)) | ||
226 | geo_ch->flags |= IEEE80211_CHAN_NO_IBSS; | ||
227 | |||
228 | if (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) | ||
229 | geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN; | ||
230 | |||
231 | if (ch->flags & EEPROM_CHANNEL_RADAR) | ||
232 | geo_ch->flags |= IEEE80211_CHAN_RADAR; | ||
233 | |||
234 | geo_ch->flags |= ch->ht40_extension_channel; | ||
235 | |||
236 | if (ch->max_power_avg > max_tx_power) | ||
237 | max_tx_power = ch->max_power_avg; | ||
238 | } else { | ||
239 | geo_ch->flags |= IEEE80211_CHAN_DISABLED; | ||
240 | } | ||
241 | |||
242 | D_INFO("Channel %d Freq=%d[%sGHz] %s flag=0x%X\n", | ||
243 | ch->channel, geo_ch->center_freq, | ||
244 | il_is_channel_a_band(ch) ? "5.2" : "2.4", | ||
245 | geo_ch->flags & IEEE80211_CHAN_DISABLED ? | ||
246 | "restricted" : "valid", | ||
247 | geo_ch->flags); | ||
248 | } | ||
249 | |||
250 | il->tx_power_device_lmt = max_tx_power; | ||
251 | il->tx_power_user_lmt = max_tx_power; | ||
252 | il->tx_power_next = max_tx_power; | ||
253 | |||
254 | if (il->bands[IEEE80211_BAND_5GHZ].n_channels == 0 && | ||
255 | (il->cfg->sku & IL_SKU_A)) { | ||
256 | IL_INFO("Incorrectly detected BG card as ABG. " | ||
257 | "Please send your PCI ID 0x%04X:0x%04X to maintainer.\n", | ||
258 | il->pci_dev->device, | ||
259 | il->pci_dev->subsystem_device); | ||
260 | il->cfg->sku &= ~IL_SKU_A; | ||
261 | } | ||
262 | |||
263 | IL_INFO("Tunable channels: %d 802.11bg, %d 802.11a channels\n", | ||
264 | il->bands[IEEE80211_BAND_2GHZ].n_channels, | ||
265 | il->bands[IEEE80211_BAND_5GHZ].n_channels); | ||
266 | |||
267 | set_bit(S_GEO_CONFIGURED, &il->status); | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | EXPORT_SYMBOL(il_init_geos); | ||
272 | |||
273 | /* | ||
274 | * il_free_geos - undo allocations in il_init_geos | ||
275 | */ | ||
276 | void il_free_geos(struct il_priv *il) | ||
277 | { | ||
278 | kfree(il->ieee_channels); | ||
279 | kfree(il->ieee_rates); | ||
280 | clear_bit(S_GEO_CONFIGURED, &il->status); | ||
281 | } | ||
282 | EXPORT_SYMBOL(il_free_geos); | ||
283 | |||
284 | static bool il_is_channel_extension(struct il_priv *il, | ||
285 | enum ieee80211_band band, | ||
286 | u16 channel, u8 extension_chan_offset) | ||
287 | { | ||
288 | const struct il_channel_info *ch_info; | ||
289 | |||
290 | ch_info = il_get_channel_info(il, band, channel); | ||
291 | if (!il_is_channel_valid(ch_info)) | ||
292 | return false; | ||
293 | |||
294 | if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) | ||
295 | return !(ch_info->ht40_extension_channel & | ||
296 | IEEE80211_CHAN_NO_HT40PLUS); | ||
297 | else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) | ||
298 | return !(ch_info->ht40_extension_channel & | ||
299 | IEEE80211_CHAN_NO_HT40MINUS); | ||
300 | |||
301 | return false; | ||
302 | } | ||
303 | |||
304 | bool il_is_ht40_tx_allowed(struct il_priv *il, | ||
305 | struct il_rxon_context *ctx, | ||
306 | struct ieee80211_sta_ht_cap *ht_cap) | ||
307 | { | ||
308 | if (!ctx->ht.enabled || !ctx->ht.is_40mhz) | ||
309 | return false; | ||
310 | |||
311 | /* | ||
312 | * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40 | ||
313 | * the bit will not set if it is pure 40MHz case | ||
314 | */ | ||
315 | if (ht_cap && !ht_cap->ht_supported) | ||
316 | return false; | ||
317 | |||
318 | #ifdef CONFIG_IWLEGACY_DEBUGFS | ||
319 | if (il->disable_ht40) | ||
320 | return false; | ||
321 | #endif | ||
322 | |||
323 | return il_is_channel_extension(il, il->band, | ||
324 | le16_to_cpu(ctx->staging.channel), | ||
325 | ctx->ht.extension_chan_offset); | ||
326 | } | ||
327 | EXPORT_SYMBOL(il_is_ht40_tx_allowed); | ||
328 | |||
329 | static u16 il_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val) | ||
330 | { | ||
331 | u16 new_val; | ||
332 | u16 beacon_factor; | ||
333 | |||
334 | /* | ||
335 | * If mac80211 hasn't given us a beacon interval, program | ||
336 | * the default into the device. | ||
337 | */ | ||
338 | if (!beacon_val) | ||
339 | return DEFAULT_BEACON_INTERVAL; | ||
340 | |||
341 | /* | ||
342 | * If the beacon interval we obtained from the peer | ||
343 | * is too large, we'll have to wake up more often | ||
344 | * (and in IBSS case, we'll beacon too much) | ||
345 | * | ||
346 | * For example, if max_beacon_val is 4096, and the | ||
347 | * requested beacon interval is 7000, we'll have to | ||
348 | * use 3500 to be able to wake up on the beacons. | ||
349 | * | ||
350 | * This could badly influence beacon detection stats. | ||
351 | */ | ||
352 | |||
353 | beacon_factor = (beacon_val + max_beacon_val) / max_beacon_val; | ||
354 | new_val = beacon_val / beacon_factor; | ||
355 | |||
356 | if (!new_val) | ||
357 | new_val = max_beacon_val; | ||
358 | |||
359 | return new_val; | ||
360 | } | ||
361 | |||
362 | int | ||
363 | il_send_rxon_timing(struct il_priv *il, struct il_rxon_context *ctx) | ||
364 | { | ||
365 | u64 tsf; | ||
366 | s32 interval_tm, rem; | ||
367 | struct ieee80211_conf *conf = NULL; | ||
368 | u16 beacon_int; | ||
369 | struct ieee80211_vif *vif = ctx->vif; | ||
370 | |||
371 | conf = il_ieee80211_get_hw_conf(il->hw); | ||
372 | |||
373 | lockdep_assert_held(&il->mutex); | ||
374 | |||
375 | memset(&ctx->timing, 0, sizeof(struct il_rxon_time_cmd)); | ||
376 | |||
377 | ctx->timing.timestamp = cpu_to_le64(il->timestamp); | ||
378 | ctx->timing.listen_interval = cpu_to_le16(conf->listen_interval); | ||
379 | |||
380 | beacon_int = vif ? vif->bss_conf.beacon_int : 0; | ||
381 | |||
382 | /* | ||
383 | * TODO: For IBSS we need to get atim_win from mac80211, | ||
384 | * for now just always use 0 | ||
385 | */ | ||
386 | ctx->timing.atim_win = 0; | ||
387 | |||
388 | beacon_int = il_adjust_beacon_interval(beacon_int, | ||
389 | il->hw_params.max_beacon_itrvl * TIME_UNIT); | ||
390 | ctx->timing.beacon_interval = cpu_to_le16(beacon_int); | ||
391 | |||
392 | tsf = il->timestamp; /* tsf is modifed by do_div: copy it */ | ||
393 | interval_tm = beacon_int * TIME_UNIT; | ||
394 | rem = do_div(tsf, interval_tm); | ||
395 | ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem); | ||
396 | |||
397 | ctx->timing.dtim_period = vif ? (vif->bss_conf.dtim_period ?: 1) : 1; | ||
398 | |||
399 | D_ASSOC( | ||
400 | "beacon interval %d beacon timer %d beacon tim %d\n", | ||
401 | le16_to_cpu(ctx->timing.beacon_interval), | ||
402 | le32_to_cpu(ctx->timing.beacon_init_val), | ||
403 | le16_to_cpu(ctx->timing.atim_win)); | ||
404 | |||
405 | return il_send_cmd_pdu(il, ctx->rxon_timing_cmd, | ||
406 | sizeof(ctx->timing), &ctx->timing); | ||
407 | } | ||
408 | EXPORT_SYMBOL(il_send_rxon_timing); | ||
409 | |||
410 | void | ||
411 | il_set_rxon_hwcrypto(struct il_priv *il, | ||
412 | struct il_rxon_context *ctx, | ||
413 | int hw_decrypt) | ||
414 | { | ||
415 | struct il_rxon_cmd *rxon = &ctx->staging; | ||
416 | |||
417 | if (hw_decrypt) | ||
418 | rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK; | ||
419 | else | ||
420 | rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK; | ||
421 | |||
422 | } | ||
423 | EXPORT_SYMBOL(il_set_rxon_hwcrypto); | ||
424 | |||
425 | /* validate RXON structure is valid */ | ||
426 | int | ||
427 | il_check_rxon_cmd(struct il_priv *il, struct il_rxon_context *ctx) | ||
428 | { | ||
429 | struct il_rxon_cmd *rxon = &ctx->staging; | ||
430 | bool error = false; | ||
431 | |||
432 | if (rxon->flags & RXON_FLG_BAND_24G_MSK) { | ||
433 | if (rxon->flags & RXON_FLG_TGJ_NARROW_BAND_MSK) { | ||
434 | IL_WARN("check 2.4G: wrong narrow\n"); | ||
435 | error = true; | ||
436 | } | ||
437 | if (rxon->flags & RXON_FLG_RADAR_DETECT_MSK) { | ||
438 | IL_WARN("check 2.4G: wrong radar\n"); | ||
439 | error = true; | ||
440 | } | ||
441 | } else { | ||
442 | if (!(rxon->flags & RXON_FLG_SHORT_SLOT_MSK)) { | ||
443 | IL_WARN("check 5.2G: not short slot!\n"); | ||
444 | error = true; | ||
445 | } | ||
446 | if (rxon->flags & RXON_FLG_CCK_MSK) { | ||
447 | IL_WARN("check 5.2G: CCK!\n"); | ||
448 | error = true; | ||
449 | } | ||
450 | } | ||
451 | if ((rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1) { | ||
452 | IL_WARN("mac/bssid mcast!\n"); | ||
453 | error = true; | ||
454 | } | ||
455 | |||
456 | /* make sure basic rates 6Mbps and 1Mbps are supported */ | ||
457 | if ((rxon->ofdm_basic_rates & RATE_6M_MASK) == 0 && | ||
458 | (rxon->cck_basic_rates & RATE_1M_MASK) == 0) { | ||
459 | IL_WARN("neither 1 nor 6 are basic\n"); | ||
460 | error = true; | ||
461 | } | ||
462 | |||
463 | if (le16_to_cpu(rxon->assoc_id) > 2007) { | ||
464 | IL_WARN("aid > 2007\n"); | ||
465 | error = true; | ||
466 | } | ||
467 | |||
468 | if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) | ||
469 | == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) { | ||
470 | IL_WARN("CCK and short slot\n"); | ||
471 | error = true; | ||
472 | } | ||
473 | |||
474 | if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) | ||
475 | == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) { | ||
476 | IL_WARN("CCK and auto detect"); | ||
477 | error = true; | ||
478 | } | ||
479 | |||
480 | if ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK | | ||
481 | RXON_FLG_TGG_PROTECT_MSK)) == | ||
482 | RXON_FLG_TGG_PROTECT_MSK) { | ||
483 | IL_WARN("TGg but no auto-detect\n"); | ||
484 | error = true; | ||
485 | } | ||
486 | |||
487 | if (error) | ||
488 | IL_WARN("Tuning to channel %d\n", | ||
489 | le16_to_cpu(rxon->channel)); | ||
490 | |||
491 | if (error) { | ||
492 | IL_ERR("Invalid RXON\n"); | ||
493 | return -EINVAL; | ||
494 | } | ||
495 | return 0; | ||
496 | } | ||
497 | EXPORT_SYMBOL(il_check_rxon_cmd); | ||
498 | |||
499 | /** | ||
500 | * il_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed | ||
501 | * @il: staging_rxon is compared to active_rxon | ||
502 | * | ||
503 | * If the RXON structure is changing enough to require a new tune, | ||
504 | * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that | ||
505 | * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. | ||
506 | */ | ||
507 | int il_full_rxon_required(struct il_priv *il, | ||
508 | struct il_rxon_context *ctx) | ||
509 | { | ||
510 | const struct il_rxon_cmd *staging = &ctx->staging; | ||
511 | const struct il_rxon_cmd *active = &ctx->active; | ||
512 | |||
513 | #define CHK(cond) \ | ||
514 | if ((cond)) { \ | ||
515 | D_INFO("need full RXON - " #cond "\n"); \ | ||
516 | return 1; \ | ||
517 | } | ||
518 | |||
519 | #define CHK_NEQ(c1, c2) \ | ||
520 | if ((c1) != (c2)) { \ | ||
521 | D_INFO("need full RXON - " \ | ||
522 | #c1 " != " #c2 " - %d != %d\n", \ | ||
523 | (c1), (c2)); \ | ||
524 | return 1; \ | ||
525 | } | ||
526 | |||
527 | /* These items are only settable from the full RXON command */ | ||
528 | CHK(!il_is_associated_ctx(ctx)); | ||
529 | CHK(compare_ether_addr(staging->bssid_addr, active->bssid_addr)); | ||
530 | CHK(compare_ether_addr(staging->node_addr, active->node_addr)); | ||
531 | CHK(compare_ether_addr(staging->wlap_bssid_addr, | ||
532 | active->wlap_bssid_addr)); | ||
533 | CHK_NEQ(staging->dev_type, active->dev_type); | ||
534 | CHK_NEQ(staging->channel, active->channel); | ||
535 | CHK_NEQ(staging->air_propagation, active->air_propagation); | ||
536 | CHK_NEQ(staging->ofdm_ht_single_stream_basic_rates, | ||
537 | active->ofdm_ht_single_stream_basic_rates); | ||
538 | CHK_NEQ(staging->ofdm_ht_dual_stream_basic_rates, | ||
539 | active->ofdm_ht_dual_stream_basic_rates); | ||
540 | CHK_NEQ(staging->assoc_id, active->assoc_id); | ||
541 | |||
542 | /* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can | ||
543 | * be updated with the RXON_ASSOC command -- however only some | ||
544 | * flag transitions are allowed using RXON_ASSOC */ | ||
545 | |||
546 | /* Check if we are not switching bands */ | ||
547 | CHK_NEQ(staging->flags & RXON_FLG_BAND_24G_MSK, | ||
548 | active->flags & RXON_FLG_BAND_24G_MSK); | ||
549 | |||
550 | /* Check if we are switching association toggle */ | ||
551 | CHK_NEQ(staging->filter_flags & RXON_FILTER_ASSOC_MSK, | ||
552 | active->filter_flags & RXON_FILTER_ASSOC_MSK); | ||
553 | |||
554 | #undef CHK | ||
555 | #undef CHK_NEQ | ||
556 | |||
557 | return 0; | ||
558 | } | ||
559 | EXPORT_SYMBOL(il_full_rxon_required); | ||
560 | |||
561 | u8 il_get_lowest_plcp(struct il_priv *il, | ||
562 | struct il_rxon_context *ctx) | ||
563 | { | ||
564 | /* | ||
565 | * Assign the lowest rate -- should really get this from | ||
566 | * the beacon skb from mac80211. | ||
567 | */ | ||
568 | if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) | ||
569 | return RATE_1M_PLCP; | ||
570 | else | ||
571 | return RATE_6M_PLCP; | ||
572 | } | ||
573 | EXPORT_SYMBOL(il_get_lowest_plcp); | ||
574 | |||
575 | static void _il_set_rxon_ht(struct il_priv *il, | ||
576 | struct il_ht_config *ht_conf, | ||
577 | struct il_rxon_context *ctx) | ||
578 | { | ||
579 | struct il_rxon_cmd *rxon = &ctx->staging; | ||
580 | |||
581 | if (!ctx->ht.enabled) { | ||
582 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | | ||
583 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | | ||
584 | RXON_FLG_HT40_PROT_MSK | | ||
585 | RXON_FLG_HT_PROT_MSK); | ||
586 | return; | ||
587 | } | ||
588 | |||
589 | rxon->flags |= cpu_to_le32(ctx->ht.protection << | ||
590 | RXON_FLG_HT_OPERATING_MODE_POS); | ||
591 | |||
592 | /* Set up channel bandwidth: | ||
593 | * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */ | ||
594 | /* clear the HT channel mode before set the mode */ | ||
595 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | | ||
596 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); | ||
597 | if (il_is_ht40_tx_allowed(il, ctx, NULL)) { | ||
598 | /* pure ht40 */ | ||
599 | if (ctx->ht.protection == | ||
600 | IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) { | ||
601 | rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40; | ||
602 | /* Note: control channel is opposite of extension channel */ | ||
603 | switch (ctx->ht.extension_chan_offset) { | ||
604 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
605 | rxon->flags &= | ||
606 | ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; | ||
607 | break; | ||
608 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
609 | rxon->flags |= | ||
610 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; | ||
611 | break; | ||
612 | } | ||
613 | } else { | ||
614 | /* Note: control channel is opposite of extension channel */ | ||
615 | switch (ctx->ht.extension_chan_offset) { | ||
616 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
617 | rxon->flags &= | ||
618 | ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); | ||
619 | rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED; | ||
620 | break; | ||
621 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
622 | rxon->flags |= | ||
623 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; | ||
624 | rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED; | ||
625 | break; | ||
626 | case IEEE80211_HT_PARAM_CHA_SEC_NONE: | ||
627 | default: | ||
628 | /* channel location only valid if in Mixed mode */ | ||
629 | IL_ERR( | ||
630 | "invalid extension channel offset\n"); | ||
631 | break; | ||
632 | } | ||
633 | } | ||
634 | } else { | ||
635 | rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY; | ||
636 | } | ||
637 | |||
638 | if (il->cfg->ops->hcmd->set_rxon_chain) | ||
639 | il->cfg->ops->hcmd->set_rxon_chain(il, ctx); | ||
640 | |||
641 | D_ASSOC("rxon flags 0x%X operation mode :0x%X " | ||
642 | "extension channel offset 0x%x\n", | ||
643 | le32_to_cpu(rxon->flags), ctx->ht.protection, | ||
644 | ctx->ht.extension_chan_offset); | ||
645 | } | ||
646 | |||
647 | void il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf) | ||
648 | { | ||
649 | _il_set_rxon_ht(il, ht_conf, &il->ctx); | ||
650 | } | ||
651 | EXPORT_SYMBOL(il_set_rxon_ht); | ||
652 | |||
653 | /* Return valid, unused, channel for a passive scan to reset the RF */ | ||
654 | u8 il_get_single_channel_number(struct il_priv *il, | ||
655 | enum ieee80211_band band) | ||
656 | { | ||
657 | const struct il_channel_info *ch_info; | ||
658 | int i; | ||
659 | u8 channel = 0; | ||
660 | u8 min, max; | ||
661 | |||
662 | if (band == IEEE80211_BAND_5GHZ) { | ||
663 | min = 14; | ||
664 | max = il->channel_count; | ||
665 | } else { | ||
666 | min = 0; | ||
667 | max = 14; | ||
668 | } | ||
669 | |||
670 | for (i = min; i < max; i++) { | ||
671 | channel = il->channel_info[i].channel; | ||
672 | if (channel == le16_to_cpu(il->ctx.staging.channel)) | ||
673 | continue; | ||
674 | |||
675 | ch_info = il_get_channel_info(il, band, channel); | ||
676 | if (il_is_channel_valid(ch_info)) | ||
677 | break; | ||
678 | } | ||
679 | |||
680 | return channel; | ||
681 | } | ||
682 | EXPORT_SYMBOL(il_get_single_channel_number); | ||
683 | |||
684 | /** | ||
685 | * il_set_rxon_channel - Set the band and channel values in staging RXON | ||
686 | * @ch: requested channel as a pointer to struct ieee80211_channel | ||
687 | |||
688 | * NOTE: Does not commit to the hardware; it sets appropriate bit fields | ||
689 | * in the staging RXON flag structure based on the ch->band | ||
690 | */ | ||
691 | int | ||
692 | il_set_rxon_channel(struct il_priv *il, struct ieee80211_channel *ch, | ||
693 | struct il_rxon_context *ctx) | ||
694 | { | ||
695 | enum ieee80211_band band = ch->band; | ||
696 | u16 channel = ch->hw_value; | ||
697 | |||
698 | if (le16_to_cpu(ctx->staging.channel) == channel && il->band == band) | ||
699 | return 0; | ||
700 | |||
701 | ctx->staging.channel = cpu_to_le16(channel); | ||
702 | if (band == IEEE80211_BAND_5GHZ) | ||
703 | ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK; | ||
704 | else | ||
705 | ctx->staging.flags |= RXON_FLG_BAND_24G_MSK; | ||
706 | |||
707 | il->band = band; | ||
708 | |||
709 | D_INFO("Staging channel set to %d [%d]\n", channel, band); | ||
710 | |||
711 | return 0; | ||
712 | } | ||
713 | EXPORT_SYMBOL(il_set_rxon_channel); | ||
714 | |||
715 | void il_set_flags_for_band(struct il_priv *il, | ||
716 | struct il_rxon_context *ctx, | ||
717 | enum ieee80211_band band, | ||
718 | struct ieee80211_vif *vif) | ||
719 | { | ||
720 | if (band == IEEE80211_BAND_5GHZ) { | ||
721 | ctx->staging.flags &= | ||
722 | ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | ||
723 | | RXON_FLG_CCK_MSK); | ||
724 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; | ||
725 | } else { | ||
726 | /* Copied from il_post_associate() */ | ||
727 | if (vif && vif->bss_conf.use_short_slot) | ||
728 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; | ||
729 | else | ||
730 | ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; | ||
731 | |||
732 | ctx->staging.flags |= RXON_FLG_BAND_24G_MSK; | ||
733 | ctx->staging.flags |= RXON_FLG_AUTO_DETECT_MSK; | ||
734 | ctx->staging.flags &= ~RXON_FLG_CCK_MSK; | ||
735 | } | ||
736 | } | ||
737 | EXPORT_SYMBOL(il_set_flags_for_band); | ||
738 | |||
739 | /* | ||
740 | * initialize rxon structure with default values from eeprom | ||
741 | */ | ||
742 | void il_connection_init_rx_config(struct il_priv *il, | ||
743 | struct il_rxon_context *ctx) | ||
744 | { | ||
745 | const struct il_channel_info *ch_info; | ||
746 | |||
747 | memset(&ctx->staging, 0, sizeof(ctx->staging)); | ||
748 | |||
749 | if (!ctx->vif) { | ||
750 | ctx->staging.dev_type = ctx->unused_devtype; | ||
751 | } else | ||
752 | switch (ctx->vif->type) { | ||
753 | |||
754 | case NL80211_IFTYPE_STATION: | ||
755 | ctx->staging.dev_type = ctx->station_devtype; | ||
756 | ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; | ||
757 | break; | ||
758 | |||
759 | case NL80211_IFTYPE_ADHOC: | ||
760 | ctx->staging.dev_type = ctx->ibss_devtype; | ||
761 | ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; | ||
762 | ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK | | ||
763 | RXON_FILTER_ACCEPT_GRP_MSK; | ||
764 | break; | ||
765 | |||
766 | default: | ||
767 | IL_ERR("Unsupported interface type %d\n", | ||
768 | ctx->vif->type); | ||
769 | break; | ||
770 | } | ||
771 | |||
772 | #if 0 | ||
773 | /* TODO: Figure out when short_preamble would be set and cache from | ||
774 | * that */ | ||
775 | if (!hw_to_local(il->hw)->short_preamble) | ||
776 | ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | ||
777 | else | ||
778 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | ||
779 | #endif | ||
780 | |||
781 | ch_info = il_get_channel_info(il, il->band, | ||
782 | le16_to_cpu(ctx->active.channel)); | ||
783 | |||
784 | if (!ch_info) | ||
785 | ch_info = &il->channel_info[0]; | ||
786 | |||
787 | ctx->staging.channel = cpu_to_le16(ch_info->channel); | ||
788 | il->band = ch_info->band; | ||
789 | |||
790 | il_set_flags_for_band(il, ctx, il->band, ctx->vif); | ||
791 | |||
792 | ctx->staging.ofdm_basic_rates = | ||
793 | (IL_OFDM_RATES_MASK >> IL_FIRST_OFDM_RATE) & 0xFF; | ||
794 | ctx->staging.cck_basic_rates = | ||
795 | (IL_CCK_RATES_MASK >> IL_FIRST_CCK_RATE) & 0xF; | ||
796 | |||
797 | /* clear both MIX and PURE40 mode flag */ | ||
798 | ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | | ||
799 | RXON_FLG_CHANNEL_MODE_PURE_40); | ||
800 | if (ctx->vif) | ||
801 | memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN); | ||
802 | |||
803 | ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff; | ||
804 | ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff; | ||
805 | } | ||
806 | EXPORT_SYMBOL(il_connection_init_rx_config); | ||
807 | |||
808 | void il_set_rate(struct il_priv *il) | ||
809 | { | ||
810 | const struct ieee80211_supported_band *hw = NULL; | ||
811 | struct ieee80211_rate *rate; | ||
812 | int i; | ||
813 | |||
814 | hw = il_get_hw_mode(il, il->band); | ||
815 | if (!hw) { | ||
816 | IL_ERR("Failed to set rate: unable to get hw mode\n"); | ||
817 | return; | ||
818 | } | ||
819 | |||
820 | il->active_rate = 0; | ||
821 | |||
822 | for (i = 0; i < hw->n_bitrates; i++) { | ||
823 | rate = &(hw->bitrates[i]); | ||
824 | if (rate->hw_value < RATE_COUNT_LEGACY) | ||
825 | il->active_rate |= (1 << rate->hw_value); | ||
826 | } | ||
827 | |||
828 | D_RATE("Set active_rate = %0x\n", il->active_rate); | ||
829 | |||
830 | il->ctx.staging.cck_basic_rates = | ||
831 | (IL_CCK_BASIC_RATES_MASK >> IL_FIRST_CCK_RATE) & 0xF; | ||
832 | |||
833 | il->ctx.staging.ofdm_basic_rates = | ||
834 | (IL_OFDM_BASIC_RATES_MASK >> IL_FIRST_OFDM_RATE) & 0xFF; | ||
835 | } | ||
836 | EXPORT_SYMBOL(il_set_rate); | ||
837 | |||
838 | void il_chswitch_done(struct il_priv *il, bool is_success) | ||
839 | { | ||
840 | struct il_rxon_context *ctx = &il->ctx; | ||
841 | |||
842 | if (test_bit(S_EXIT_PENDING, &il->status)) | ||
843 | return; | ||
844 | |||
845 | if (test_and_clear_bit(S_CHANNEL_SWITCH_PENDING, &il->status)) | ||
846 | ieee80211_chswitch_done(ctx->vif, is_success); | ||
847 | } | ||
848 | EXPORT_SYMBOL(il_chswitch_done); | ||
849 | |||
850 | void il_hdl_csa(struct il_priv *il, struct il_rx_buf *rxb) | ||
851 | { | ||
852 | struct il_rx_pkt *pkt = rxb_addr(rxb); | ||
853 | struct il_csa_notification *csa = &(pkt->u.csa_notif); | ||
854 | |||
855 | struct il_rxon_context *ctx = &il->ctx; | ||
856 | struct il_rxon_cmd *rxon = (void *)&ctx->active; | ||
857 | |||
858 | if (!test_bit(S_CHANNEL_SWITCH_PENDING, &il->status)) | ||
859 | return; | ||
860 | |||
861 | if (!le32_to_cpu(csa->status) && csa->channel == il->switch_channel) { | ||
862 | rxon->channel = csa->channel; | ||
863 | ctx->staging.channel = csa->channel; | ||
864 | D_11H("CSA notif: channel %d\n", | ||
865 | le16_to_cpu(csa->channel)); | ||
866 | il_chswitch_done(il, true); | ||
867 | } else { | ||
868 | IL_ERR("CSA notif (fail) : channel %d\n", | ||
869 | le16_to_cpu(csa->channel)); | ||
870 | il_chswitch_done(il, false); | ||
871 | } | ||
872 | } | ||
873 | EXPORT_SYMBOL(il_hdl_csa); | ||
874 | |||
875 | #ifdef CONFIG_IWLEGACY_DEBUG | ||
876 | void il_print_rx_config_cmd(struct il_priv *il, | ||
877 | struct il_rxon_context *ctx) | ||
878 | { | ||
879 | struct il_rxon_cmd *rxon = &ctx->staging; | ||
880 | |||
881 | D_RADIO("RX CONFIG:\n"); | ||
882 | il_print_hex_dump(il, IL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); | ||
883 | D_RADIO("u16 channel: 0x%x\n", | ||
884 | le16_to_cpu(rxon->channel)); | ||
885 | D_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags)); | ||
886 | D_RADIO("u32 filter_flags: 0x%08x\n", | ||
887 | le32_to_cpu(rxon->filter_flags)); | ||
888 | D_RADIO("u8 dev_type: 0x%x\n", rxon->dev_type); | ||
889 | D_RADIO("u8 ofdm_basic_rates: 0x%02x\n", | ||
890 | rxon->ofdm_basic_rates); | ||
891 | D_RADIO("u8 cck_basic_rates: 0x%02x\n", | ||
892 | rxon->cck_basic_rates); | ||
893 | D_RADIO("u8[6] node_addr: %pM\n", rxon->node_addr); | ||
894 | D_RADIO("u8[6] bssid_addr: %pM\n", rxon->bssid_addr); | ||
895 | D_RADIO("u16 assoc_id: 0x%x\n", | ||
896 | le16_to_cpu(rxon->assoc_id)); | ||
897 | } | ||
898 | EXPORT_SYMBOL(il_print_rx_config_cmd); | ||
899 | #endif | ||
900 | /** | ||
901 | * il_irq_handle_error - called for HW or SW error interrupt from card | ||
902 | */ | ||
903 | void il_irq_handle_error(struct il_priv *il) | ||
904 | { | ||
905 | /* Set the FW error flag -- cleared on il_down */ | ||
906 | set_bit(S_FW_ERROR, &il->status); | ||
907 | |||
908 | /* Cancel currently queued command. */ | ||
909 | clear_bit(S_HCMD_ACTIVE, &il->status); | ||
910 | |||
911 | IL_ERR("Loaded firmware version: %s\n", | ||
912 | il->hw->wiphy->fw_version); | ||
913 | |||
914 | il->cfg->ops->lib->dump_nic_error_log(il); | ||
915 | if (il->cfg->ops->lib->dump_fh) | ||
916 | il->cfg->ops->lib->dump_fh(il, NULL, false); | ||
917 | #ifdef CONFIG_IWLEGACY_DEBUG | ||
918 | if (il_get_debug_level(il) & IL_DL_FW_ERRORS) | ||
919 | il_print_rx_config_cmd(il, | ||
920 | &il->ctx); | ||
921 | #endif | ||
922 | |||
923 | wake_up(&il->wait_command_queue); | ||
924 | |||
925 | /* Keep the restart process from trying to send host | ||
926 | * commands by clearing the INIT status bit */ | ||
927 | clear_bit(S_READY, &il->status); | ||
928 | |||
929 | if (!test_bit(S_EXIT_PENDING, &il->status)) { | ||
930 | IL_DBG(IL_DL_FW_ERRORS, | ||
931 | "Restarting adapter due to uCode error.\n"); | ||
932 | |||
933 | if (il->cfg->mod_params->restart_fw) | ||
934 | queue_work(il->workqueue, &il->restart); | ||
935 | } | ||
936 | } | ||
937 | EXPORT_SYMBOL(il_irq_handle_error); | ||
938 | |||
939 | static int il_apm_stop_master(struct il_priv *il) | ||
940 | { | ||
941 | int ret = 0; | ||
942 | |||
943 | /* stop device's busmaster DMA activity */ | ||
944 | il_set_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); | ||
945 | |||
946 | ret = _il_poll_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED, | ||
947 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); | ||
948 | if (ret) | ||
949 | IL_WARN("Master Disable Timed Out, 100 usec\n"); | ||
950 | |||
951 | D_INFO("stop master\n"); | ||
952 | |||
953 | return ret; | ||
954 | } | ||
955 | |||
956 | void il_apm_stop(struct il_priv *il) | ||
957 | { | ||
958 | D_INFO("Stop card, put in low power state\n"); | ||
959 | |||
960 | /* Stop device's DMA activity */ | ||
961 | il_apm_stop_master(il); | ||
962 | |||
963 | /* Reset the entire device */ | ||
964 | il_set_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
965 | |||
966 | udelay(10); | ||
967 | |||
968 | /* | ||
969 | * Clear "initialization complete" bit to move adapter from | ||
970 | * D0A* (powered-up Active) --> D0U* (Uninitialized) state. | ||
971 | */ | ||
972 | il_clear_bit(il, CSR_GP_CNTRL, | ||
973 | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
974 | } | ||
975 | EXPORT_SYMBOL(il_apm_stop); | ||
976 | |||
977 | |||
978 | /* | ||
979 | * Start up NIC's basic functionality after it has been reset | ||
980 | * (e.g. after platform boot, or shutdown via il_apm_stop()) | ||
981 | * NOTE: This does not load uCode nor start the embedded processor | ||
982 | */ | ||
983 | int il_apm_init(struct il_priv *il) | ||
984 | { | ||
985 | int ret = 0; | ||
986 | u16 lctl; | ||
987 | |||
988 | D_INFO("Init card's basic functions\n"); | ||
989 | |||
990 | /* | ||
991 | * Use "set_bit" below rather than "write", to preserve any hardware | ||
992 | * bits already set by default after reset. | ||
993 | */ | ||
994 | |||
995 | /* Disable L0S exit timer (platform NMI Work/Around) */ | ||
996 | il_set_bit(il, CSR_GIO_CHICKEN_BITS, | ||
997 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); | ||
998 | |||
999 | /* | ||
1000 | * Disable L0s without affecting L1; | ||
1001 | * don't wait for ICH L0s (ICH bug W/A) | ||
1002 | */ | ||
1003 | il_set_bit(il, CSR_GIO_CHICKEN_BITS, | ||
1004 | CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); | ||
1005 | |||
1006 | /* Set FH wait threshold to maximum (HW error during stress W/A) */ | ||
1007 | il_set_bit(il, CSR_DBG_HPET_MEM_REG, | ||
1008 | CSR_DBG_HPET_MEM_REG_VAL); | ||
1009 | |||
1010 | /* | ||
1011 | * Enable HAP INTA (interrupt from management bus) to | ||
1012 | * wake device's PCI Express link L1a -> L0s | ||
1013 | * NOTE: This is no-op for 3945 (non-existent bit) | ||
1014 | */ | ||
1015 | il_set_bit(il, CSR_HW_IF_CONFIG_REG, | ||
1016 | CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); | ||
1017 | |||
1018 | /* | ||
1019 | * HW bug W/A for instability in PCIe bus L0->L0S->L1 transition. | ||
1020 | * Check if BIOS (or OS) enabled L1-ASPM on this device. | ||
1021 | * If so (likely), disable L0S, so device moves directly L0->L1; | ||
1022 | * costs negligible amount of power savings. | ||
1023 | * If not (unlikely), enable L0S, so there is at least some | ||
1024 | * power savings, even without L1. | ||
1025 | */ | ||
1026 | if (il->cfg->base_params->set_l0s) { | ||
1027 | lctl = il_pcie_link_ctl(il); | ||
1028 | if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == | ||
1029 | PCI_CFG_LINK_CTRL_VAL_L1_EN) { | ||
1030 | /* L1-ASPM enabled; disable(!) L0S */ | ||
1031 | il_set_bit(il, CSR_GIO_REG, | ||
1032 | CSR_GIO_REG_VAL_L0S_ENABLED); | ||
1033 | D_POWER("L1 Enabled; Disabling L0S\n"); | ||
1034 | } else { | ||
1035 | /* L1-ASPM disabled; enable(!) L0S */ | ||
1036 | il_clear_bit(il, CSR_GIO_REG, | ||
1037 | CSR_GIO_REG_VAL_L0S_ENABLED); | ||
1038 | D_POWER("L1 Disabled; Enabling L0S\n"); | ||
1039 | } | ||
1040 | } | ||
1041 | |||
1042 | /* Configure analog phase-lock-loop before activating to D0A */ | ||
1043 | if (il->cfg->base_params->pll_cfg_val) | ||
1044 | il_set_bit(il, CSR_ANA_PLL_CFG, | ||
1045 | il->cfg->base_params->pll_cfg_val); | ||
1046 | |||
1047 | /* | ||
1048 | * Set "initialization complete" bit to move adapter from | ||
1049 | * D0U* --> D0A* (powered-up active) state. | ||
1050 | */ | ||
1051 | il_set_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
1052 | |||
1053 | /* | ||
1054 | * Wait for clock stabilization; once stabilized, access to | ||
1055 | * device-internal resources is supported, e.g. il_wr_prph() | ||
1056 | * and accesses to uCode SRAM. | ||
1057 | */ | ||
1058 | ret = _il_poll_bit(il, CSR_GP_CNTRL, | ||
1059 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
1060 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
1061 | if (ret < 0) { | ||
1062 | D_INFO("Failed to init the card\n"); | ||
1063 | goto out; | ||
1064 | } | ||
1065 | |||
1066 | /* | ||
1067 | * Enable DMA and BSM (if used) clocks, wait for them to stabilize. | ||
1068 | * BSM (Boostrap State Machine) is only in 3945 and 4965. | ||
1069 | * | ||
1070 | * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits | ||
1071 | * do not disable clocks. This preserves any hardware bits already | ||
1072 | * set by default in "CLK_CTRL_REG" after reset. | ||
1073 | */ | ||
1074 | if (il->cfg->base_params->use_bsm) | ||
1075 | il_wr_prph(il, APMG_CLK_EN_REG, | ||
1076 | APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); | ||
1077 | else | ||
1078 | il_wr_prph(il, APMG_CLK_EN_REG, | ||
1079 | APMG_CLK_VAL_DMA_CLK_RQT); | ||
1080 | udelay(20); | ||
1081 | |||
1082 | /* Disable L1-Active */ | ||
1083 | il_set_bits_prph(il, APMG_PCIDEV_STT_REG, | ||
1084 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | ||
1085 | |||
1086 | out: | ||
1087 | return ret; | ||
1088 | } | ||
1089 | EXPORT_SYMBOL(il_apm_init); | ||
1090 | |||
1091 | |||
1092 | int il_set_tx_power(struct il_priv *il, s8 tx_power, bool force) | ||
1093 | { | ||
1094 | int ret; | ||
1095 | s8 prev_tx_power; | ||
1096 | bool defer; | ||
1097 | struct il_rxon_context *ctx = &il->ctx; | ||
1098 | |||
1099 | lockdep_assert_held(&il->mutex); | ||
1100 | |||
1101 | if (il->tx_power_user_lmt == tx_power && !force) | ||
1102 | return 0; | ||
1103 | |||
1104 | if (!il->cfg->ops->lib->send_tx_power) | ||
1105 | return -EOPNOTSUPP; | ||
1106 | |||
1107 | /* 0 dBm mean 1 milliwatt */ | ||
1108 | if (tx_power < 0) { | ||
1109 | IL_WARN( | ||
1110 | "Requested user TXPOWER %d below 1 mW.\n", | ||
1111 | tx_power); | ||
1112 | return -EINVAL; | ||
1113 | } | ||
1114 | |||
1115 | if (tx_power > il->tx_power_device_lmt) { | ||
1116 | IL_WARN( | ||
1117 | "Requested user TXPOWER %d above upper limit %d.\n", | ||
1118 | tx_power, il->tx_power_device_lmt); | ||
1119 | return -EINVAL; | ||
1120 | } | ||
1121 | |||
1122 | if (!il_is_ready_rf(il)) | ||
1123 | return -EIO; | ||
1124 | |||
1125 | /* scan complete and commit_rxon use tx_power_next value, | ||
1126 | * it always need to be updated for newest request */ | ||
1127 | il->tx_power_next = tx_power; | ||
1128 | |||
1129 | /* do not set tx power when scanning or channel changing */ | ||
1130 | defer = test_bit(S_SCANNING, &il->status) || | ||
1131 | memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)); | ||
1132 | if (defer && !force) { | ||
1133 | D_INFO("Deferring tx power set\n"); | ||
1134 | return 0; | ||
1135 | } | ||
1136 | |||
1137 | prev_tx_power = il->tx_power_user_lmt; | ||
1138 | il->tx_power_user_lmt = tx_power; | ||
1139 | |||
1140 | ret = il->cfg->ops->lib->send_tx_power(il); | ||
1141 | |||
1142 | /* if fail to set tx_power, restore the orig. tx power */ | ||
1143 | if (ret) { | ||
1144 | il->tx_power_user_lmt = prev_tx_power; | ||
1145 | il->tx_power_next = prev_tx_power; | ||
1146 | } | ||
1147 | return ret; | ||
1148 | } | ||
1149 | EXPORT_SYMBOL(il_set_tx_power); | ||
1150 | |||
1151 | void il_send_bt_config(struct il_priv *il) | ||
1152 | { | ||
1153 | struct il_bt_cmd bt_cmd = { | ||
1154 | .lead_time = BT_LEAD_TIME_DEF, | ||
1155 | .max_kill = BT_MAX_KILL_DEF, | ||
1156 | .kill_ack_mask = 0, | ||
1157 | .kill_cts_mask = 0, | ||
1158 | }; | ||
1159 | |||
1160 | if (!bt_coex_active) | ||
1161 | bt_cmd.flags = BT_COEX_DISABLE; | ||
1162 | else | ||
1163 | bt_cmd.flags = BT_COEX_ENABLE; | ||
1164 | |||
1165 | D_INFO("BT coex %s\n", | ||
1166 | (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); | ||
1167 | |||
1168 | if (il_send_cmd_pdu(il, C_BT_CONFIG, | ||
1169 | sizeof(struct il_bt_cmd), &bt_cmd)) | ||
1170 | IL_ERR("failed to send BT Coex Config\n"); | ||
1171 | } | ||
1172 | EXPORT_SYMBOL(il_send_bt_config); | ||
1173 | |||
1174 | int il_send_stats_request(struct il_priv *il, u8 flags, bool clear) | ||
1175 | { | ||
1176 | struct il_stats_cmd stats_cmd = { | ||
1177 | .configuration_flags = | ||
1178 | clear ? IL_STATS_CONF_CLEAR_STATS : 0, | ||
1179 | }; | ||
1180 | |||
1181 | if (flags & CMD_ASYNC) | ||
1182 | return il_send_cmd_pdu_async(il, C_STATS, | ||
1183 | sizeof(struct il_stats_cmd), | ||
1184 | &stats_cmd, NULL); | ||
1185 | else | ||
1186 | return il_send_cmd_pdu(il, C_STATS, | ||
1187 | sizeof(struct il_stats_cmd), | ||
1188 | &stats_cmd); | ||
1189 | } | ||
1190 | EXPORT_SYMBOL(il_send_stats_request); | ||
1191 | |||
1192 | void il_hdl_pm_sleep(struct il_priv *il, | ||
1193 | struct il_rx_buf *rxb) | ||
1194 | { | ||
1195 | #ifdef CONFIG_IWLEGACY_DEBUG | ||
1196 | struct il_rx_pkt *pkt = rxb_addr(rxb); | ||
1197 | struct il_sleep_notification *sleep = &(pkt->u.sleep_notif); | ||
1198 | D_RX("sleep mode: %d, src: %d\n", | ||
1199 | sleep->pm_sleep_mode, sleep->pm_wakeup_src); | ||
1200 | #endif | ||
1201 | } | ||
1202 | EXPORT_SYMBOL(il_hdl_pm_sleep); | ||
1203 | |||
1204 | void il_hdl_pm_debug_stats(struct il_priv *il, | ||
1205 | struct il_rx_buf *rxb) | ||
1206 | { | ||
1207 | struct il_rx_pkt *pkt = rxb_addr(rxb); | ||
1208 | u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
1209 | D_RADIO("Dumping %d bytes of unhandled " | ||
1210 | "notification for %s:\n", len, | ||
1211 | il_get_cmd_string(pkt->hdr.cmd)); | ||
1212 | il_print_hex_dump(il, IL_DL_RADIO, pkt->u.raw, len); | ||
1213 | } | ||
1214 | EXPORT_SYMBOL(il_hdl_pm_debug_stats); | ||
1215 | |||
1216 | void il_hdl_error(struct il_priv *il, | ||
1217 | struct il_rx_buf *rxb) | ||
1218 | { | ||
1219 | struct il_rx_pkt *pkt = rxb_addr(rxb); | ||
1220 | |||
1221 | IL_ERR("Error Reply type 0x%08X cmd %s (0x%02X) " | ||
1222 | "seq 0x%04X ser 0x%08X\n", | ||
1223 | le32_to_cpu(pkt->u.err_resp.error_type), | ||
1224 | il_get_cmd_string(pkt->u.err_resp.cmd_id), | ||
1225 | pkt->u.err_resp.cmd_id, | ||
1226 | le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num), | ||
1227 | le32_to_cpu(pkt->u.err_resp.error_info)); | ||
1228 | } | ||
1229 | EXPORT_SYMBOL(il_hdl_error); | ||
1230 | |||
1231 | void il_clear_isr_stats(struct il_priv *il) | ||
1232 | { | ||
1233 | memset(&il->isr_stats, 0, sizeof(il->isr_stats)); | ||
1234 | } | ||
1235 | |||
1236 | int il_mac_conf_tx(struct ieee80211_hw *hw, | ||
1237 | struct ieee80211_vif *vif, u16 queue, | ||
1238 | const struct ieee80211_tx_queue_params *params) | ||
1239 | { | ||
1240 | struct il_priv *il = hw->priv; | ||
1241 | unsigned long flags; | ||
1242 | int q; | ||
1243 | |||
1244 | D_MAC80211("enter\n"); | ||
1245 | |||
1246 | if (!il_is_ready_rf(il)) { | ||
1247 | D_MAC80211("leave - RF not ready\n"); | ||
1248 | return -EIO; | ||
1249 | } | ||
1250 | |||
1251 | if (queue >= AC_NUM) { | ||
1252 | D_MAC80211("leave - queue >= AC_NUM %d\n", queue); | ||
1253 | return 0; | ||
1254 | } | ||
1255 | |||
1256 | q = AC_NUM - 1 - queue; | ||
1257 | |||
1258 | spin_lock_irqsave(&il->lock, flags); | ||
1259 | |||
1260 | il->ctx.qos_data.def_qos_parm.ac[q].cw_min = | ||
1261 | cpu_to_le16(params->cw_min); | ||
1262 | il->ctx.qos_data.def_qos_parm.ac[q].cw_max = | ||
1263 | cpu_to_le16(params->cw_max); | ||
1264 | il->ctx.qos_data.def_qos_parm.ac[q].aifsn = params->aifs; | ||
1265 | il->ctx.qos_data.def_qos_parm.ac[q].edca_txop = | ||
1266 | cpu_to_le16((params->txop * 32)); | ||
1267 | |||
1268 | il->ctx.qos_data.def_qos_parm.ac[q].reserved1 = 0; | ||
1269 | |||
1270 | spin_unlock_irqrestore(&il->lock, flags); | ||
1271 | |||
1272 | D_MAC80211("leave\n"); | ||
1273 | return 0; | ||
1274 | } | ||
1275 | EXPORT_SYMBOL(il_mac_conf_tx); | ||
1276 | |||
1277 | int il_mac_tx_last_beacon(struct ieee80211_hw *hw) | ||
1278 | { | ||
1279 | struct il_priv *il = hw->priv; | ||
1280 | |||
1281 | return il->ibss_manager == IL_IBSS_MANAGER; | ||
1282 | } | ||
1283 | EXPORT_SYMBOL_GPL(il_mac_tx_last_beacon); | ||
1284 | |||
1285 | static int | ||
1286 | il_set_mode(struct il_priv *il, struct il_rxon_context *ctx) | ||
1287 | { | ||
1288 | il_connection_init_rx_config(il, ctx); | ||
1289 | |||
1290 | if (il->cfg->ops->hcmd->set_rxon_chain) | ||
1291 | il->cfg->ops->hcmd->set_rxon_chain(il, ctx); | ||
1292 | |||
1293 | return il_commit_rxon(il, ctx); | ||
1294 | } | ||
1295 | |||
1296 | static int il_setup_interface(struct il_priv *il, | ||
1297 | struct il_rxon_context *ctx) | ||
1298 | { | ||
1299 | struct ieee80211_vif *vif = ctx->vif; | ||
1300 | int err; | ||
1301 | |||
1302 | lockdep_assert_held(&il->mutex); | ||
1303 | |||
1304 | /* | ||
1305 | * This variable will be correct only when there's just | ||
1306 | * a single context, but all code using it is for hardware | ||
1307 | * that supports only one context. | ||
1308 | */ | ||
1309 | il->iw_mode = vif->type; | ||
1310 | |||
1311 | ctx->is_active = true; | ||
1312 | |||
1313 | err = il_set_mode(il, ctx); | ||
1314 | if (err) { | ||
1315 | if (!ctx->always_active) | ||
1316 | ctx->is_active = false; | ||
1317 | return err; | ||
1318 | } | ||
1319 | |||
1320 | return 0; | ||
1321 | } | ||
1322 | |||
1323 | int | ||
1324 | il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | ||
1325 | { | ||
1326 | struct il_priv *il = hw->priv; | ||
1327 | struct il_vif_priv *vif_priv = (void *)vif->drv_priv; | ||
1328 | int err; | ||
1329 | u32 modes; | ||
1330 | |||
1331 | D_MAC80211("enter: type %d, addr %pM\n", | ||
1332 | vif->type, vif->addr); | ||
1333 | |||
1334 | mutex_lock(&il->mutex); | ||
1335 | |||
1336 | if (!il_is_ready_rf(il)) { | ||
1337 | IL_WARN("Try to add interface when device not ready\n"); | ||
1338 | err = -EINVAL; | ||
1339 | goto out; | ||
1340 | } | ||
1341 | |||
1342 | |||
1343 | /* check if busy context is exclusive */ | ||
1344 | if (il->ctx.vif && | ||
1345 | (il->ctx.exclusive_interface_modes & BIT(il->ctx.vif->type))) { | ||
1346 | err = -EINVAL; | ||
1347 | goto out; | ||
1348 | } | ||
1349 | |||
1350 | modes = il->ctx.interface_modes | il->ctx.exclusive_interface_modes; | ||
1351 | if (!(modes & BIT(vif->type))) { | ||
1352 | err = -EOPNOTSUPP; | ||
1353 | goto out; | ||
1354 | } | ||
1355 | |||
1356 | vif_priv->ctx = &il->ctx; | ||
1357 | il->ctx.vif = vif; | ||
1358 | |||
1359 | err = il_setup_interface(il, &il->ctx); | ||
1360 | if (err) { | ||
1361 | il->ctx.vif = NULL; | ||
1362 | il->iw_mode = NL80211_IFTYPE_STATION; | ||
1363 | } | ||
1364 | |||
1365 | out: | ||
1366 | mutex_unlock(&il->mutex); | ||
1367 | |||
1368 | D_MAC80211("leave\n"); | ||
1369 | return err; | ||
1370 | } | ||
1371 | EXPORT_SYMBOL(il_mac_add_interface); | ||
1372 | |||
1373 | static void il_teardown_interface(struct il_priv *il, | ||
1374 | struct ieee80211_vif *vif, | ||
1375 | bool mode_change) | ||
1376 | { | ||
1377 | struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); | ||
1378 | |||
1379 | lockdep_assert_held(&il->mutex); | ||
1380 | |||
1381 | if (il->scan_vif == vif) { | ||
1382 | il_scan_cancel_timeout(il, 200); | ||
1383 | il_force_scan_end(il); | ||
1384 | } | ||
1385 | |||
1386 | if (!mode_change) { | ||
1387 | il_set_mode(il, ctx); | ||
1388 | if (!ctx->always_active) | ||
1389 | ctx->is_active = false; | ||
1390 | } | ||
1391 | } | ||
1392 | |||
1393 | void il_mac_remove_interface(struct ieee80211_hw *hw, | ||
1394 | struct ieee80211_vif *vif) | ||
1395 | { | ||
1396 | struct il_priv *il = hw->priv; | ||
1397 | struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); | ||
1398 | |||
1399 | D_MAC80211("enter\n"); | ||
1400 | |||
1401 | mutex_lock(&il->mutex); | ||
1402 | |||
1403 | WARN_ON(ctx->vif != vif); | ||
1404 | ctx->vif = NULL; | ||
1405 | |||
1406 | il_teardown_interface(il, vif, false); | ||
1407 | |||
1408 | memset(il->bssid, 0, ETH_ALEN); | ||
1409 | mutex_unlock(&il->mutex); | ||
1410 | |||
1411 | D_MAC80211("leave\n"); | ||
1412 | |||
1413 | } | ||
1414 | EXPORT_SYMBOL(il_mac_remove_interface); | ||
1415 | |||
1416 | int il_alloc_txq_mem(struct il_priv *il) | ||
1417 | { | ||
1418 | if (!il->txq) | ||
1419 | il->txq = kzalloc( | ||
1420 | sizeof(struct il_tx_queue) * | ||
1421 | il->cfg->base_params->num_of_queues, | ||
1422 | GFP_KERNEL); | ||
1423 | if (!il->txq) { | ||
1424 | IL_ERR("Not enough memory for txq\n"); | ||
1425 | return -ENOMEM; | ||
1426 | } | ||
1427 | return 0; | ||
1428 | } | ||
1429 | EXPORT_SYMBOL(il_alloc_txq_mem); | ||
1430 | |||
1431 | void il_txq_mem(struct il_priv *il) | ||
1432 | { | ||
1433 | kfree(il->txq); | ||
1434 | il->txq = NULL; | ||
1435 | } | ||
1436 | EXPORT_SYMBOL(il_txq_mem); | ||
1437 | |||
1438 | #ifdef CONFIG_IWLEGACY_DEBUGFS | ||
1439 | |||
1440 | #define IL_TRAFFIC_DUMP_SIZE (IL_TRAFFIC_ENTRY_SIZE * IL_TRAFFIC_ENTRIES) | ||
1441 | |||
1442 | void il_reset_traffic_log(struct il_priv *il) | ||
1443 | { | ||
1444 | il->tx_traffic_idx = 0; | ||
1445 | il->rx_traffic_idx = 0; | ||
1446 | if (il->tx_traffic) | ||
1447 | memset(il->tx_traffic, 0, IL_TRAFFIC_DUMP_SIZE); | ||
1448 | if (il->rx_traffic) | ||
1449 | memset(il->rx_traffic, 0, IL_TRAFFIC_DUMP_SIZE); | ||
1450 | } | ||
1451 | |||
1452 | int il_alloc_traffic_mem(struct il_priv *il) | ||
1453 | { | ||
1454 | u32 traffic_size = IL_TRAFFIC_DUMP_SIZE; | ||
1455 | |||
1456 | if (il_debug_level & IL_DL_TX) { | ||
1457 | if (!il->tx_traffic) { | ||
1458 | il->tx_traffic = | ||
1459 | kzalloc(traffic_size, GFP_KERNEL); | ||
1460 | if (!il->tx_traffic) | ||
1461 | return -ENOMEM; | ||
1462 | } | ||
1463 | } | ||
1464 | if (il_debug_level & IL_DL_RX) { | ||
1465 | if (!il->rx_traffic) { | ||
1466 | il->rx_traffic = | ||
1467 | kzalloc(traffic_size, GFP_KERNEL); | ||
1468 | if (!il->rx_traffic) | ||
1469 | return -ENOMEM; | ||
1470 | } | ||
1471 | } | ||
1472 | il_reset_traffic_log(il); | ||
1473 | return 0; | ||
1474 | } | ||
1475 | EXPORT_SYMBOL(il_alloc_traffic_mem); | ||
1476 | |||
1477 | void il_free_traffic_mem(struct il_priv *il) | ||
1478 | { | ||
1479 | kfree(il->tx_traffic); | ||
1480 | il->tx_traffic = NULL; | ||
1481 | |||
1482 | kfree(il->rx_traffic); | ||
1483 | il->rx_traffic = NULL; | ||
1484 | } | ||
1485 | EXPORT_SYMBOL(il_free_traffic_mem); | ||
1486 | |||
1487 | void il_dbg_log_tx_data_frame(struct il_priv *il, | ||
1488 | u16 length, struct ieee80211_hdr *header) | ||
1489 | { | ||
1490 | __le16 fc; | ||
1491 | u16 len; | ||
1492 | |||
1493 | if (likely(!(il_debug_level & IL_DL_TX))) | ||
1494 | return; | ||
1495 | |||
1496 | if (!il->tx_traffic) | ||
1497 | return; | ||
1498 | |||
1499 | fc = header->frame_control; | ||
1500 | if (ieee80211_is_data(fc)) { | ||
1501 | len = (length > IL_TRAFFIC_ENTRY_SIZE) | ||
1502 | ? IL_TRAFFIC_ENTRY_SIZE : length; | ||
1503 | memcpy((il->tx_traffic + | ||
1504 | (il->tx_traffic_idx * IL_TRAFFIC_ENTRY_SIZE)), | ||
1505 | header, len); | ||
1506 | il->tx_traffic_idx = | ||
1507 | (il->tx_traffic_idx + 1) % IL_TRAFFIC_ENTRIES; | ||
1508 | } | ||
1509 | } | ||
1510 | EXPORT_SYMBOL(il_dbg_log_tx_data_frame); | ||
1511 | |||
1512 | void il_dbg_log_rx_data_frame(struct il_priv *il, | ||
1513 | u16 length, struct ieee80211_hdr *header) | ||
1514 | { | ||
1515 | __le16 fc; | ||
1516 | u16 len; | ||
1517 | |||
1518 | if (likely(!(il_debug_level & IL_DL_RX))) | ||
1519 | return; | ||
1520 | |||
1521 | if (!il->rx_traffic) | ||
1522 | return; | ||
1523 | |||
1524 | fc = header->frame_control; | ||
1525 | if (ieee80211_is_data(fc)) { | ||
1526 | len = (length > IL_TRAFFIC_ENTRY_SIZE) | ||
1527 | ? IL_TRAFFIC_ENTRY_SIZE : length; | ||
1528 | memcpy((il->rx_traffic + | ||
1529 | (il->rx_traffic_idx * IL_TRAFFIC_ENTRY_SIZE)), | ||
1530 | header, len); | ||
1531 | il->rx_traffic_idx = | ||
1532 | (il->rx_traffic_idx + 1) % IL_TRAFFIC_ENTRIES; | ||
1533 | } | ||
1534 | } | ||
1535 | EXPORT_SYMBOL(il_dbg_log_rx_data_frame); | ||
1536 | |||
1537 | const char *il_get_mgmt_string(int cmd) | ||
1538 | { | ||
1539 | switch (cmd) { | ||
1540 | IL_CMD(MANAGEMENT_ASSOC_REQ); | ||
1541 | IL_CMD(MANAGEMENT_ASSOC_RESP); | ||
1542 | IL_CMD(MANAGEMENT_REASSOC_REQ); | ||
1543 | IL_CMD(MANAGEMENT_REASSOC_RESP); | ||
1544 | IL_CMD(MANAGEMENT_PROBE_REQ); | ||
1545 | IL_CMD(MANAGEMENT_PROBE_RESP); | ||
1546 | IL_CMD(MANAGEMENT_BEACON); | ||
1547 | IL_CMD(MANAGEMENT_ATIM); | ||
1548 | IL_CMD(MANAGEMENT_DISASSOC); | ||
1549 | IL_CMD(MANAGEMENT_AUTH); | ||
1550 | IL_CMD(MANAGEMENT_DEAUTH); | ||
1551 | IL_CMD(MANAGEMENT_ACTION); | ||
1552 | default: | ||
1553 | return "UNKNOWN"; | ||
1554 | |||
1555 | } | ||
1556 | } | ||
1557 | |||
1558 | const char *il_get_ctrl_string(int cmd) | ||
1559 | { | ||
1560 | switch (cmd) { | ||
1561 | IL_CMD(CONTROL_BACK_REQ); | ||
1562 | IL_CMD(CONTROL_BACK); | ||
1563 | IL_CMD(CONTROL_PSPOLL); | ||
1564 | IL_CMD(CONTROL_RTS); | ||
1565 | IL_CMD(CONTROL_CTS); | ||
1566 | IL_CMD(CONTROL_ACK); | ||
1567 | IL_CMD(CONTROL_CFEND); | ||
1568 | IL_CMD(CONTROL_CFENDACK); | ||
1569 | default: | ||
1570 | return "UNKNOWN"; | ||
1571 | |||
1572 | } | ||
1573 | } | ||
1574 | |||
1575 | void il_clear_traffic_stats(struct il_priv *il) | ||
1576 | { | ||
1577 | memset(&il->tx_stats, 0, sizeof(struct traffic_stats)); | ||
1578 | memset(&il->rx_stats, 0, sizeof(struct traffic_stats)); | ||
1579 | } | ||
1580 | |||
1581 | /* | ||
1582 | * if CONFIG_IWLEGACY_DEBUGFS defined, | ||
1583 | * il_update_stats function will | ||
1584 | * record all the MGMT, CTRL and DATA pkt for both TX and Rx pass | ||
1585 | * Use debugFs to display the rx/rx_stats | ||
1586 | * if CONFIG_IWLEGACY_DEBUGFS not being defined, then no MGMT and CTRL | ||
1587 | * information will be recorded, but DATA pkt still will be recorded | ||
1588 | * for the reason of il_led.c need to control the led blinking based on | ||
1589 | * number of tx and rx data. | ||
1590 | * | ||
1591 | */ | ||
1592 | void | ||
1593 | il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len) | ||
1594 | { | ||
1595 | struct traffic_stats *stats; | ||
1596 | |||
1597 | if (is_tx) | ||
1598 | stats = &il->tx_stats; | ||
1599 | else | ||
1600 | stats = &il->rx_stats; | ||
1601 | |||
1602 | if (ieee80211_is_mgmt(fc)) { | ||
1603 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { | ||
1604 | case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): | ||
1605 | stats->mgmt[MANAGEMENT_ASSOC_REQ]++; | ||
1606 | break; | ||
1607 | case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP): | ||
1608 | stats->mgmt[MANAGEMENT_ASSOC_RESP]++; | ||
1609 | break; | ||
1610 | case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): | ||
1611 | stats->mgmt[MANAGEMENT_REASSOC_REQ]++; | ||
1612 | break; | ||
1613 | case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP): | ||
1614 | stats->mgmt[MANAGEMENT_REASSOC_RESP]++; | ||
1615 | break; | ||
1616 | case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): | ||
1617 | stats->mgmt[MANAGEMENT_PROBE_REQ]++; | ||
1618 | break; | ||
1619 | case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): | ||
1620 | stats->mgmt[MANAGEMENT_PROBE_RESP]++; | ||
1621 | break; | ||
1622 | case cpu_to_le16(IEEE80211_STYPE_BEACON): | ||
1623 | stats->mgmt[MANAGEMENT_BEACON]++; | ||
1624 | break; | ||
1625 | case cpu_to_le16(IEEE80211_STYPE_ATIM): | ||
1626 | stats->mgmt[MANAGEMENT_ATIM]++; | ||
1627 | break; | ||
1628 | case cpu_to_le16(IEEE80211_STYPE_DISASSOC): | ||
1629 | stats->mgmt[MANAGEMENT_DISASSOC]++; | ||
1630 | break; | ||
1631 | case cpu_to_le16(IEEE80211_STYPE_AUTH): | ||
1632 | stats->mgmt[MANAGEMENT_AUTH]++; | ||
1633 | break; | ||
1634 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): | ||
1635 | stats->mgmt[MANAGEMENT_DEAUTH]++; | ||
1636 | break; | ||
1637 | case cpu_to_le16(IEEE80211_STYPE_ACTION): | ||
1638 | stats->mgmt[MANAGEMENT_ACTION]++; | ||
1639 | break; | ||
1640 | } | ||
1641 | } else if (ieee80211_is_ctl(fc)) { | ||
1642 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { | ||
1643 | case cpu_to_le16(IEEE80211_STYPE_BACK_REQ): | ||
1644 | stats->ctrl[CONTROL_BACK_REQ]++; | ||
1645 | break; | ||
1646 | case cpu_to_le16(IEEE80211_STYPE_BACK): | ||
1647 | stats->ctrl[CONTROL_BACK]++; | ||
1648 | break; | ||
1649 | case cpu_to_le16(IEEE80211_STYPE_PSPOLL): | ||
1650 | stats->ctrl[CONTROL_PSPOLL]++; | ||
1651 | break; | ||
1652 | case cpu_to_le16(IEEE80211_STYPE_RTS): | ||
1653 | stats->ctrl[CONTROL_RTS]++; | ||
1654 | break; | ||
1655 | case cpu_to_le16(IEEE80211_STYPE_CTS): | ||
1656 | stats->ctrl[CONTROL_CTS]++; | ||
1657 | break; | ||
1658 | case cpu_to_le16(IEEE80211_STYPE_ACK): | ||
1659 | stats->ctrl[CONTROL_ACK]++; | ||
1660 | break; | ||
1661 | case cpu_to_le16(IEEE80211_STYPE_CFEND): | ||
1662 | stats->ctrl[CONTROL_CFEND]++; | ||
1663 | break; | ||
1664 | case cpu_to_le16(IEEE80211_STYPE_CFENDACK): | ||
1665 | stats->ctrl[CONTROL_CFENDACK]++; | ||
1666 | break; | ||
1667 | } | ||
1668 | } else { | ||
1669 | /* data */ | ||
1670 | stats->data_cnt++; | ||
1671 | stats->data_bytes += len; | ||
1672 | } | ||
1673 | } | ||
1674 | EXPORT_SYMBOL(il_update_stats); | ||
1675 | #endif | ||
1676 | |||
1677 | int il_force_reset(struct il_priv *il, bool external) | ||
1678 | { | ||
1679 | struct il_force_reset *force_reset; | ||
1680 | |||
1681 | if (test_bit(S_EXIT_PENDING, &il->status)) | ||
1682 | return -EINVAL; | ||
1683 | |||
1684 | force_reset = &il->force_reset; | ||
1685 | force_reset->reset_request_count++; | ||
1686 | if (!external) { | ||
1687 | if (force_reset->last_force_reset_jiffies && | ||
1688 | time_after(force_reset->last_force_reset_jiffies + | ||
1689 | force_reset->reset_duration, jiffies)) { | ||
1690 | D_INFO("force reset rejected\n"); | ||
1691 | force_reset->reset_reject_count++; | ||
1692 | return -EAGAIN; | ||
1693 | } | ||
1694 | } | ||
1695 | force_reset->reset_success_count++; | ||
1696 | force_reset->last_force_reset_jiffies = jiffies; | ||
1697 | |||
1698 | /* | ||
1699 | * if the request is from external(ex: debugfs), | ||
1700 | * then always perform the request in regardless the module | ||
1701 | * parameter setting | ||
1702 | * if the request is from internal (uCode error or driver | ||
1703 | * detect failure), then fw_restart module parameter | ||
1704 | * need to be check before performing firmware reload | ||
1705 | */ | ||
1706 | |||
1707 | if (!external && !il->cfg->mod_params->restart_fw) { | ||
1708 | D_INFO("Cancel firmware reload based on " | ||
1709 | "module parameter setting\n"); | ||
1710 | return 0; | ||
1711 | } | ||
1712 | |||
1713 | IL_ERR("On demand firmware reload\n"); | ||
1714 | |||
1715 | /* Set the FW error flag -- cleared on il_down */ | ||
1716 | set_bit(S_FW_ERROR, &il->status); | ||
1717 | wake_up(&il->wait_command_queue); | ||
1718 | /* | ||
1719 | * Keep the restart process from trying to send host | ||
1720 | * commands by clearing the INIT status bit | ||
1721 | */ | ||
1722 | clear_bit(S_READY, &il->status); | ||
1723 | queue_work(il->workqueue, &il->restart); | ||
1724 | |||
1725 | return 0; | ||
1726 | } | ||
1727 | |||
1728 | int | ||
1729 | il_mac_change_interface(struct ieee80211_hw *hw, | ||
1730 | struct ieee80211_vif *vif, | ||
1731 | enum nl80211_iftype newtype, bool newp2p) | ||
1732 | { | ||
1733 | struct il_priv *il = hw->priv; | ||
1734 | struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); | ||
1735 | u32 modes; | ||
1736 | int err; | ||
1737 | |||
1738 | newtype = ieee80211_iftype_p2p(newtype, newp2p); | ||
1739 | |||
1740 | mutex_lock(&il->mutex); | ||
1741 | |||
1742 | if (!ctx->vif || !il_is_ready_rf(il)) { | ||
1743 | /* | ||
1744 | * Huh? But wait ... this can maybe happen when | ||
1745 | * we're in the middle of a firmware restart! | ||
1746 | */ | ||
1747 | err = -EBUSY; | ||
1748 | goto out; | ||
1749 | } | ||
1750 | |||
1751 | modes = ctx->interface_modes | ctx->exclusive_interface_modes; | ||
1752 | if (!(modes & BIT(newtype))) { | ||
1753 | err = -EOPNOTSUPP; | ||
1754 | goto out; | ||
1755 | } | ||
1756 | |||
1757 | if ((il->ctx.exclusive_interface_modes & BIT(il->ctx.vif->type)) || | ||
1758 | (il->ctx.exclusive_interface_modes & BIT(newtype))) { | ||
1759 | err = -EINVAL; | ||
1760 | goto out; | ||
1761 | } | ||
1762 | |||
1763 | /* success */ | ||
1764 | il_teardown_interface(il, vif, true); | ||
1765 | vif->type = newtype; | ||
1766 | vif->p2p = newp2p; | ||
1767 | err = il_setup_interface(il, ctx); | ||
1768 | WARN_ON(err); | ||
1769 | /* | ||
1770 | * We've switched internally, but submitting to the | ||
1771 | * device may have failed for some reason. Mask this | ||
1772 | * error, because otherwise mac80211 will not switch | ||
1773 | * (and set the interface type back) and we'll be | ||
1774 | * out of sync with it. | ||
1775 | */ | ||
1776 | err = 0; | ||
1777 | |||
1778 | out: | ||
1779 | mutex_unlock(&il->mutex); | ||
1780 | return err; | ||
1781 | } | ||
1782 | EXPORT_SYMBOL(il_mac_change_interface); | ||
1783 | |||
1784 | /* | ||
1785 | * On every watchdog tick we check (latest) time stamp. If it does not | ||
1786 | * change during timeout period and queue is not empty we reset firmware. | ||
1787 | */ | ||
1788 | static int il_check_stuck_queue(struct il_priv *il, int cnt) | ||
1789 | { | ||
1790 | struct il_tx_queue *txq = &il->txq[cnt]; | ||
1791 | struct il_queue *q = &txq->q; | ||
1792 | unsigned long timeout; | ||
1793 | int ret; | ||
1794 | |||
1795 | if (q->read_ptr == q->write_ptr) { | ||
1796 | txq->time_stamp = jiffies; | ||
1797 | return 0; | ||
1798 | } | ||
1799 | |||
1800 | timeout = txq->time_stamp + | ||
1801 | msecs_to_jiffies(il->cfg->base_params->wd_timeout); | ||
1802 | |||
1803 | if (time_after(jiffies, timeout)) { | ||
1804 | IL_ERR("Queue %d stuck for %u ms.\n", | ||
1805 | q->id, il->cfg->base_params->wd_timeout); | ||
1806 | ret = il_force_reset(il, false); | ||
1807 | return (ret == -EAGAIN) ? 0 : 1; | ||
1808 | } | ||
1809 | |||
1810 | return 0; | ||
1811 | } | ||
1812 | |||
1813 | /* | ||
1814 | * Making watchdog tick be a quarter of timeout assure we will | ||
1815 | * discover the queue hung between timeout and 1.25*timeout | ||
1816 | */ | ||
1817 | #define IL_WD_TICK(timeout) ((timeout) / 4) | ||
1818 | |||
1819 | /* | ||
1820 | * Watchdog timer callback, we check each tx queue for stuck, if if hung | ||
1821 | * we reset the firmware. If everything is fine just rearm the timer. | ||
1822 | */ | ||
1823 | void il_bg_watchdog(unsigned long data) | ||
1824 | { | ||
1825 | struct il_priv *il = (struct il_priv *)data; | ||
1826 | int cnt; | ||
1827 | unsigned long timeout; | ||
1828 | |||
1829 | if (test_bit(S_EXIT_PENDING, &il->status)) | ||
1830 | return; | ||
1831 | |||
1832 | timeout = il->cfg->base_params->wd_timeout; | ||
1833 | if (timeout == 0) | ||
1834 | return; | ||
1835 | |||
1836 | /* monitor and check for stuck cmd queue */ | ||
1837 | if (il_check_stuck_queue(il, il->cmd_queue)) | ||
1838 | return; | ||
1839 | |||
1840 | /* monitor and check for other stuck queues */ | ||
1841 | if (il_is_any_associated(il)) { | ||
1842 | for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) { | ||
1843 | /* skip as we already checked the command queue */ | ||
1844 | if (cnt == il->cmd_queue) | ||
1845 | continue; | ||
1846 | if (il_check_stuck_queue(il, cnt)) | ||
1847 | return; | ||
1848 | } | ||
1849 | } | ||
1850 | |||
1851 | mod_timer(&il->watchdog, jiffies + | ||
1852 | msecs_to_jiffies(IL_WD_TICK(timeout))); | ||
1853 | } | ||
1854 | EXPORT_SYMBOL(il_bg_watchdog); | ||
1855 | |||
1856 | void il_setup_watchdog(struct il_priv *il) | ||
1857 | { | ||
1858 | unsigned int timeout = il->cfg->base_params->wd_timeout; | ||
1859 | |||
1860 | if (timeout) | ||
1861 | mod_timer(&il->watchdog, | ||
1862 | jiffies + msecs_to_jiffies(IL_WD_TICK(timeout))); | ||
1863 | else | ||
1864 | del_timer(&il->watchdog); | ||
1865 | } | ||
1866 | EXPORT_SYMBOL(il_setup_watchdog); | ||
1867 | |||
1868 | /* | ||
1869 | * extended beacon time format | ||
1870 | * time in usec will be changed into a 32-bit value in extended:internal format | ||
1871 | * the extended part is the beacon counts | ||
1872 | * the internal part is the time in usec within one beacon interval | ||
1873 | */ | ||
1874 | u32 | ||
1875 | il_usecs_to_beacons(struct il_priv *il, | ||
1876 | u32 usec, u32 beacon_interval) | ||
1877 | { | ||
1878 | u32 quot; | ||
1879 | u32 rem; | ||
1880 | u32 interval = beacon_interval * TIME_UNIT; | ||
1881 | |||
1882 | if (!interval || !usec) | ||
1883 | return 0; | ||
1884 | |||
1885 | quot = (usec / interval) & | ||
1886 | (il_beacon_time_mask_high(il, | ||
1887 | il->hw_params.beacon_time_tsf_bits) >> | ||
1888 | il->hw_params.beacon_time_tsf_bits); | ||
1889 | rem = (usec % interval) & il_beacon_time_mask_low(il, | ||
1890 | il->hw_params.beacon_time_tsf_bits); | ||
1891 | |||
1892 | return (quot << il->hw_params.beacon_time_tsf_bits) + rem; | ||
1893 | } | ||
1894 | EXPORT_SYMBOL(il_usecs_to_beacons); | ||
1895 | |||
1896 | /* base is usually what we get from ucode with each received frame, | ||
1897 | * the same as HW timer counter counting down | ||
1898 | */ | ||
1899 | __le32 il_add_beacon_time(struct il_priv *il, u32 base, | ||
1900 | u32 addon, u32 beacon_interval) | ||
1901 | { | ||
1902 | u32 base_low = base & il_beacon_time_mask_low(il, | ||
1903 | il->hw_params.beacon_time_tsf_bits); | ||
1904 | u32 addon_low = addon & il_beacon_time_mask_low(il, | ||
1905 | il->hw_params.beacon_time_tsf_bits); | ||
1906 | u32 interval = beacon_interval * TIME_UNIT; | ||
1907 | u32 res = (base & il_beacon_time_mask_high(il, | ||
1908 | il->hw_params.beacon_time_tsf_bits)) + | ||
1909 | (addon & il_beacon_time_mask_high(il, | ||
1910 | il->hw_params.beacon_time_tsf_bits)); | ||
1911 | |||
1912 | if (base_low > addon_low) | ||
1913 | res += base_low - addon_low; | ||
1914 | else if (base_low < addon_low) { | ||
1915 | res += interval + base_low - addon_low; | ||
1916 | res += (1 << il->hw_params.beacon_time_tsf_bits); | ||
1917 | } else | ||
1918 | res += (1 << il->hw_params.beacon_time_tsf_bits); | ||
1919 | |||
1920 | return cpu_to_le32(res); | ||
1921 | } | ||
1922 | EXPORT_SYMBOL(il_add_beacon_time); | ||
1923 | |||
1924 | #ifdef CONFIG_PM | ||
1925 | |||
1926 | int il_pci_suspend(struct device *device) | ||
1927 | { | ||
1928 | struct pci_dev *pdev = to_pci_dev(device); | ||
1929 | struct il_priv *il = pci_get_drvdata(pdev); | ||
1930 | |||
1931 | /* | ||
1932 | * This function is called when system goes into suspend state | ||
1933 | * mac80211 will call il_mac_stop() from the mac80211 suspend function | ||
1934 | * first but since il_mac_stop() has no knowledge of who the caller is, | ||
1935 | * it will not call apm_ops.stop() to stop the DMA operation. | ||
1936 | * Calling apm_ops.stop here to make sure we stop the DMA. | ||
1937 | */ | ||
1938 | il_apm_stop(il); | ||
1939 | |||
1940 | return 0; | ||
1941 | } | ||
1942 | EXPORT_SYMBOL(il_pci_suspend); | ||
1943 | |||
1944 | int il_pci_resume(struct device *device) | ||
1945 | { | ||
1946 | struct pci_dev *pdev = to_pci_dev(device); | ||
1947 | struct il_priv *il = pci_get_drvdata(pdev); | ||
1948 | bool hw_rfkill = false; | ||
1949 | |||
1950 | /* | ||
1951 | * We disable the RETRY_TIMEOUT register (0x41) to keep | ||
1952 | * PCI Tx retries from interfering with C3 CPU state. | ||
1953 | */ | ||
1954 | pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); | ||
1955 | |||
1956 | il_enable_interrupts(il); | ||
1957 | |||
1958 | if (!(_il_rd(il, CSR_GP_CNTRL) & | ||
1959 | CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) | ||
1960 | hw_rfkill = true; | ||
1961 | |||
1962 | if (hw_rfkill) | ||
1963 | set_bit(S_RF_KILL_HW, &il->status); | ||
1964 | else | ||
1965 | clear_bit(S_RF_KILL_HW, &il->status); | ||
1966 | |||
1967 | wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rfkill); | ||
1968 | |||
1969 | return 0; | ||
1970 | } | ||
1971 | EXPORT_SYMBOL(il_pci_resume); | ||
1972 | |||
1973 | const struct dev_pm_ops il_pm_ops = { | ||
1974 | .suspend = il_pci_suspend, | ||
1975 | .resume = il_pci_resume, | ||
1976 | .freeze = il_pci_suspend, | ||
1977 | .thaw = il_pci_resume, | ||
1978 | .poweroff = il_pci_suspend, | ||
1979 | .restore = il_pci_resume, | ||
1980 | }; | ||
1981 | EXPORT_SYMBOL(il_pm_ops); | ||
1982 | |||
1983 | #endif /* CONFIG_PM */ | ||
1984 | |||
1985 | static void | ||
1986 | il_update_qos(struct il_priv *il, struct il_rxon_context *ctx) | ||
1987 | { | ||
1988 | if (test_bit(S_EXIT_PENDING, &il->status)) | ||
1989 | return; | ||
1990 | |||
1991 | if (!ctx->is_active) | ||
1992 | return; | ||
1993 | |||
1994 | ctx->qos_data.def_qos_parm.qos_flags = 0; | ||
1995 | |||
1996 | if (ctx->qos_data.qos_active) | ||
1997 | ctx->qos_data.def_qos_parm.qos_flags |= | ||
1998 | QOS_PARAM_FLG_UPDATE_EDCA_MSK; | ||
1999 | |||
2000 | if (ctx->ht.enabled) | ||
2001 | ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; | ||
2002 | |||
2003 | D_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n", | ||
2004 | ctx->qos_data.qos_active, | ||
2005 | ctx->qos_data.def_qos_parm.qos_flags); | ||
2006 | |||
2007 | il_send_cmd_pdu_async(il, ctx->qos_cmd, | ||
2008 | sizeof(struct il_qosparam_cmd), | ||
2009 | &ctx->qos_data.def_qos_parm, NULL); | ||
2010 | } | ||
2011 | |||
2012 | /** | ||
2013 | * il_mac_config - mac80211 config callback | ||
2014 | */ | ||
2015 | int il_mac_config(struct ieee80211_hw *hw, u32 changed) | ||
2016 | { | ||
2017 | struct il_priv *il = hw->priv; | ||
2018 | const struct il_channel_info *ch_info; | ||
2019 | struct ieee80211_conf *conf = &hw->conf; | ||
2020 | struct ieee80211_channel *channel = conf->channel; | ||
2021 | struct il_ht_config *ht_conf = &il->current_ht_config; | ||
2022 | struct il_rxon_context *ctx = &il->ctx; | ||
2023 | unsigned long flags = 0; | ||
2024 | int ret = 0; | ||
2025 | u16 ch; | ||
2026 | int scan_active = 0; | ||
2027 | bool ht_changed = false; | ||
2028 | |||
2029 | if (WARN_ON(!il->cfg->ops->legacy)) | ||
2030 | return -EOPNOTSUPP; | ||
2031 | |||
2032 | mutex_lock(&il->mutex); | ||
2033 | |||
2034 | D_MAC80211("enter to channel %d changed 0x%X\n", | ||
2035 | channel->hw_value, changed); | ||
2036 | |||
2037 | if (unlikely(test_bit(S_SCANNING, &il->status))) { | ||
2038 | scan_active = 1; | ||
2039 | D_MAC80211("scan active\n"); | ||
2040 | } | ||
2041 | |||
2042 | if (changed & (IEEE80211_CONF_CHANGE_SMPS | | ||
2043 | IEEE80211_CONF_CHANGE_CHANNEL)) { | ||
2044 | /* mac80211 uses static for non-HT which is what we want */ | ||
2045 | il->current_ht_config.smps = conf->smps_mode; | ||
2046 | |||
2047 | /* | ||
2048 | * Recalculate chain counts. | ||
2049 | * | ||
2050 | * If monitor mode is enabled then mac80211 will | ||
2051 | * set up the SM PS mode to OFF if an HT channel is | ||
2052 | * configured. | ||
2053 | */ | ||
2054 | if (il->cfg->ops->hcmd->set_rxon_chain) | ||
2055 | il->cfg->ops->hcmd->set_rxon_chain(il, &il->ctx); | ||
2056 | } | ||
2057 | |||
2058 | /* during scanning mac80211 will delay channel setting until | ||
2059 | * scan finish with changed = 0 | ||
2060 | */ | ||
2061 | if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) { | ||
2062 | |||
2063 | if (scan_active) | ||
2064 | goto set_ch_out; | ||
2065 | |||
2066 | ch = channel->hw_value; | ||
2067 | ch_info = il_get_channel_info(il, channel->band, ch); | ||
2068 | if (!il_is_channel_valid(ch_info)) { | ||
2069 | D_MAC80211("leave - invalid channel\n"); | ||
2070 | ret = -EINVAL; | ||
2071 | goto set_ch_out; | ||
2072 | } | ||
2073 | |||
2074 | if (il->iw_mode == NL80211_IFTYPE_ADHOC && | ||
2075 | !il_is_channel_ibss(ch_info)) { | ||
2076 | D_MAC80211("leave - not IBSS channel\n"); | ||
2077 | ret = -EINVAL; | ||
2078 | goto set_ch_out; | ||
2079 | } | ||
2080 | |||
2081 | spin_lock_irqsave(&il->lock, flags); | ||
2082 | |||
2083 | /* Configure HT40 channels */ | ||
2084 | if (ctx->ht.enabled != conf_is_ht(conf)) { | ||
2085 | ctx->ht.enabled = conf_is_ht(conf); | ||
2086 | ht_changed = true; | ||
2087 | } | ||
2088 | if (ctx->ht.enabled) { | ||
2089 | if (conf_is_ht40_minus(conf)) { | ||
2090 | ctx->ht.extension_chan_offset = | ||
2091 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
2092 | ctx->ht.is_40mhz = true; | ||
2093 | } else if (conf_is_ht40_plus(conf)) { | ||
2094 | ctx->ht.extension_chan_offset = | ||
2095 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
2096 | ctx->ht.is_40mhz = true; | ||
2097 | } else { | ||
2098 | ctx->ht.extension_chan_offset = | ||
2099 | IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
2100 | ctx->ht.is_40mhz = false; | ||
2101 | } | ||
2102 | } else | ||
2103 | ctx->ht.is_40mhz = false; | ||
2104 | |||
2105 | /* | ||
2106 | * Default to no protection. Protection mode will | ||
2107 | * later be set from BSS config in il_ht_conf | ||
2108 | */ | ||
2109 | ctx->ht.protection = | ||
2110 | IEEE80211_HT_OP_MODE_PROTECTION_NONE; | ||
2111 | |||
2112 | /* if we are switching from ht to 2.4 clear flags | ||
2113 | * from any ht related info since 2.4 does not | ||
2114 | * support ht */ | ||
2115 | if ((le16_to_cpu(ctx->staging.channel) != ch)) | ||
2116 | ctx->staging.flags = 0; | ||
2117 | |||
2118 | il_set_rxon_channel(il, channel, ctx); | ||
2119 | il_set_rxon_ht(il, ht_conf); | ||
2120 | |||
2121 | il_set_flags_for_band(il, ctx, channel->band, | ||
2122 | ctx->vif); | ||
2123 | |||
2124 | spin_unlock_irqrestore(&il->lock, flags); | ||
2125 | |||
2126 | if (il->cfg->ops->legacy->update_bcast_stations) | ||
2127 | ret = | ||
2128 | il->cfg->ops->legacy->update_bcast_stations(il); | ||
2129 | |||
2130 | set_ch_out: | ||
2131 | /* The list of supported rates and rate mask can be different | ||
2132 | * for each band; since the band may have changed, reset | ||
2133 | * the rate mask to what mac80211 lists */ | ||
2134 | il_set_rate(il); | ||
2135 | } | ||
2136 | |||
2137 | if (changed & (IEEE80211_CONF_CHANGE_PS | | ||
2138 | IEEE80211_CONF_CHANGE_IDLE)) { | ||
2139 | ret = il_power_update_mode(il, false); | ||
2140 | if (ret) | ||
2141 | D_MAC80211("Error setting sleep level\n"); | ||
2142 | } | ||
2143 | |||
2144 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | ||
2145 | D_MAC80211("TX Power old=%d new=%d\n", | ||
2146 | il->tx_power_user_lmt, conf->power_level); | ||
2147 | |||
2148 | il_set_tx_power(il, conf->power_level, false); | ||
2149 | } | ||
2150 | |||
2151 | if (!il_is_ready(il)) { | ||
2152 | D_MAC80211("leave - not ready\n"); | ||
2153 | goto out; | ||
2154 | } | ||
2155 | |||
2156 | if (scan_active) | ||
2157 | goto out; | ||
2158 | |||
2159 | if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging))) | ||
2160 | il_commit_rxon(il, ctx); | ||
2161 | else | ||
2162 | D_INFO("Not re-sending same RXON configuration.\n"); | ||
2163 | if (ht_changed) | ||
2164 | il_update_qos(il, ctx); | ||
2165 | |||
2166 | out: | ||
2167 | D_MAC80211("leave\n"); | ||
2168 | mutex_unlock(&il->mutex); | ||
2169 | return ret; | ||
2170 | } | ||
2171 | EXPORT_SYMBOL(il_mac_config); | ||
2172 | |||
2173 | void il_mac_reset_tsf(struct ieee80211_hw *hw, | ||
2174 | struct ieee80211_vif *vif) | ||
2175 | { | ||
2176 | struct il_priv *il = hw->priv; | ||
2177 | unsigned long flags; | ||
2178 | struct il_rxon_context *ctx = &il->ctx; | ||
2179 | |||
2180 | if (WARN_ON(!il->cfg->ops->legacy)) | ||
2181 | return; | ||
2182 | |||
2183 | mutex_lock(&il->mutex); | ||
2184 | D_MAC80211("enter\n"); | ||
2185 | |||
2186 | spin_lock_irqsave(&il->lock, flags); | ||
2187 | memset(&il->current_ht_config, 0, sizeof(struct il_ht_config)); | ||
2188 | spin_unlock_irqrestore(&il->lock, flags); | ||
2189 | |||
2190 | spin_lock_irqsave(&il->lock, flags); | ||
2191 | |||
2192 | /* new association get rid of ibss beacon skb */ | ||
2193 | if (il->beacon_skb) | ||
2194 | dev_kfree_skb(il->beacon_skb); | ||
2195 | |||
2196 | il->beacon_skb = NULL; | ||
2197 | |||
2198 | il->timestamp = 0; | ||
2199 | |||
2200 | spin_unlock_irqrestore(&il->lock, flags); | ||
2201 | |||
2202 | il_scan_cancel_timeout(il, 100); | ||
2203 | if (!il_is_ready_rf(il)) { | ||
2204 | D_MAC80211("leave - not ready\n"); | ||
2205 | mutex_unlock(&il->mutex); | ||
2206 | return; | ||
2207 | } | ||
2208 | |||
2209 | /* we are restarting association process | ||
2210 | * clear RXON_FILTER_ASSOC_MSK bit | ||
2211 | */ | ||
2212 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | ||
2213 | il_commit_rxon(il, ctx); | ||
2214 | |||
2215 | il_set_rate(il); | ||
2216 | |||
2217 | mutex_unlock(&il->mutex); | ||
2218 | |||
2219 | D_MAC80211("leave\n"); | ||
2220 | } | ||
2221 | EXPORT_SYMBOL(il_mac_reset_tsf); | ||
2222 | |||
2223 | static void il_ht_conf(struct il_priv *il, | ||
2224 | struct ieee80211_vif *vif) | ||
2225 | { | ||
2226 | struct il_ht_config *ht_conf = &il->current_ht_config; | ||
2227 | struct ieee80211_sta *sta; | ||
2228 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
2229 | struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); | ||
2230 | |||
2231 | D_ASSOC("enter:\n"); | ||
2232 | |||
2233 | if (!ctx->ht.enabled) | ||
2234 | return; | ||
2235 | |||
2236 | ctx->ht.protection = | ||
2237 | bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; | ||
2238 | ctx->ht.non_gf_sta_present = | ||
2239 | !!(bss_conf->ht_operation_mode & | ||
2240 | IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | ||
2241 | |||
2242 | ht_conf->single_chain_sufficient = false; | ||
2243 | |||
2244 | switch (vif->type) { | ||
2245 | case NL80211_IFTYPE_STATION: | ||
2246 | rcu_read_lock(); | ||
2247 | sta = ieee80211_find_sta(vif, bss_conf->bssid); | ||
2248 | if (sta) { | ||
2249 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | ||
2250 | int maxstreams; | ||
2251 | |||
2252 | maxstreams = (ht_cap->mcs.tx_params & | ||
2253 | IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK) | ||
2254 | >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; | ||
2255 | maxstreams += 1; | ||
2256 | |||
2257 | if (ht_cap->mcs.rx_mask[1] == 0 && | ||
2258 | ht_cap->mcs.rx_mask[2] == 0) | ||
2259 | ht_conf->single_chain_sufficient = true; | ||
2260 | if (maxstreams <= 1) | ||
2261 | ht_conf->single_chain_sufficient = true; | ||
2262 | } else { | ||
2263 | /* | ||
2264 | * If at all, this can only happen through a race | ||
2265 | * when the AP disconnects us while we're still | ||
2266 | * setting up the connection, in that case mac80211 | ||
2267 | * will soon tell us about that. | ||
2268 | */ | ||
2269 | ht_conf->single_chain_sufficient = true; | ||
2270 | } | ||
2271 | rcu_read_unlock(); | ||
2272 | break; | ||
2273 | case NL80211_IFTYPE_ADHOC: | ||
2274 | ht_conf->single_chain_sufficient = true; | ||
2275 | break; | ||
2276 | default: | ||
2277 | break; | ||
2278 | } | ||
2279 | |||
2280 | D_ASSOC("leave\n"); | ||
2281 | } | ||
2282 | |||
2283 | static inline void il_set_no_assoc(struct il_priv *il, | ||
2284 | struct ieee80211_vif *vif) | ||
2285 | { | ||
2286 | struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); | ||
2287 | |||
2288 | /* | ||
2289 | * inform the ucode that there is no longer an | ||
2290 | * association and that no more packets should be | ||
2291 | * sent | ||
2292 | */ | ||
2293 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | ||
2294 | ctx->staging.assoc_id = 0; | ||
2295 | il_commit_rxon(il, ctx); | ||
2296 | } | ||
2297 | |||
2298 | static void il_beacon_update(struct ieee80211_hw *hw, | ||
2299 | struct ieee80211_vif *vif) | ||
2300 | { | ||
2301 | struct il_priv *il = hw->priv; | ||
2302 | unsigned long flags; | ||
2303 | __le64 timestamp; | ||
2304 | struct sk_buff *skb = ieee80211_beacon_get(hw, vif); | ||
2305 | |||
2306 | if (!skb) | ||
2307 | return; | ||
2308 | |||
2309 | D_MAC80211("enter\n"); | ||
2310 | |||
2311 | lockdep_assert_held(&il->mutex); | ||
2312 | |||
2313 | if (!il->beacon_ctx) { | ||
2314 | IL_ERR("update beacon but no beacon context!\n"); | ||
2315 | dev_kfree_skb(skb); | ||
2316 | return; | ||
2317 | } | ||
2318 | |||
2319 | spin_lock_irqsave(&il->lock, flags); | ||
2320 | |||
2321 | if (il->beacon_skb) | ||
2322 | dev_kfree_skb(il->beacon_skb); | ||
2323 | |||
2324 | il->beacon_skb = skb; | ||
2325 | |||
2326 | timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; | ||
2327 | il->timestamp = le64_to_cpu(timestamp); | ||
2328 | |||
2329 | D_MAC80211("leave\n"); | ||
2330 | spin_unlock_irqrestore(&il->lock, flags); | ||
2331 | |||
2332 | if (!il_is_ready_rf(il)) { | ||
2333 | D_MAC80211("leave - RF not ready\n"); | ||
2334 | return; | ||
2335 | } | ||
2336 | |||
2337 | il->cfg->ops->legacy->post_associate(il); | ||
2338 | } | ||
2339 | |||
2340 | void il_mac_bss_info_changed(struct ieee80211_hw *hw, | ||
2341 | struct ieee80211_vif *vif, | ||
2342 | struct ieee80211_bss_conf *bss_conf, | ||
2343 | u32 changes) | ||
2344 | { | ||
2345 | struct il_priv *il = hw->priv; | ||
2346 | struct il_rxon_context *ctx = il_rxon_ctx_from_vif(vif); | ||
2347 | int ret; | ||
2348 | |||
2349 | if (WARN_ON(!il->cfg->ops->legacy)) | ||
2350 | return; | ||
2351 | |||
2352 | D_MAC80211("changes = 0x%X\n", changes); | ||
2353 | |||
2354 | mutex_lock(&il->mutex); | ||
2355 | |||
2356 | if (!il_is_alive(il)) { | ||
2357 | mutex_unlock(&il->mutex); | ||
2358 | return; | ||
2359 | } | ||
2360 | |||
2361 | if (changes & BSS_CHANGED_QOS) { | ||
2362 | unsigned long flags; | ||
2363 | |||
2364 | spin_lock_irqsave(&il->lock, flags); | ||
2365 | ctx->qos_data.qos_active = bss_conf->qos; | ||
2366 | il_update_qos(il, ctx); | ||
2367 | spin_unlock_irqrestore(&il->lock, flags); | ||
2368 | } | ||
2369 | |||
2370 | if (changes & BSS_CHANGED_BEACON_ENABLED) { | ||
2371 | /* | ||
2372 | * the add_interface code must make sure we only ever | ||
2373 | * have a single interface that could be beaconing at | ||
2374 | * any time. | ||
2375 | */ | ||
2376 | if (vif->bss_conf.enable_beacon) | ||
2377 | il->beacon_ctx = ctx; | ||
2378 | else | ||
2379 | il->beacon_ctx = NULL; | ||
2380 | } | ||
2381 | |||
2382 | if (changes & BSS_CHANGED_BSSID) { | ||
2383 | D_MAC80211("BSSID %pM\n", bss_conf->bssid); | ||
2384 | |||
2385 | /* | ||
2386 | * If there is currently a HW scan going on in the | ||
2387 | * background then we need to cancel it else the RXON | ||
2388 | * below/in post_associate will fail. | ||
2389 | */ | ||
2390 | if (il_scan_cancel_timeout(il, 100)) { | ||
2391 | IL_WARN( | ||
2392 | "Aborted scan still in progress after 100ms\n"); | ||
2393 | D_MAC80211( | ||
2394 | "leaving - scan abort failed.\n"); | ||
2395 | mutex_unlock(&il->mutex); | ||
2396 | return; | ||
2397 | } | ||
2398 | |||
2399 | /* mac80211 only sets assoc when in STATION mode */ | ||
2400 | if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) { | ||
2401 | memcpy(ctx->staging.bssid_addr, | ||
2402 | bss_conf->bssid, ETH_ALEN); | ||
2403 | |||
2404 | /* currently needed in a few places */ | ||
2405 | memcpy(il->bssid, bss_conf->bssid, ETH_ALEN); | ||
2406 | } else { | ||
2407 | ctx->staging.filter_flags &= | ||
2408 | ~RXON_FILTER_ASSOC_MSK; | ||
2409 | } | ||
2410 | |||
2411 | } | ||
2412 | |||
2413 | /* | ||
2414 | * This needs to be after setting the BSSID in case | ||
2415 | * mac80211 decides to do both changes at once because | ||
2416 | * it will invoke post_associate. | ||
2417 | */ | ||
2418 | if (vif->type == NL80211_IFTYPE_ADHOC && (changes & BSS_CHANGED_BEACON)) | ||
2419 | il_beacon_update(hw, vif); | ||
2420 | |||
2421 | if (changes & BSS_CHANGED_ERP_PREAMBLE) { | ||
2422 | D_MAC80211("ERP_PREAMBLE %d\n", | ||
2423 | bss_conf->use_short_preamble); | ||
2424 | if (bss_conf->use_short_preamble) | ||
2425 | ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | ||
2426 | else | ||
2427 | ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; | ||
2428 | } | ||
2429 | |||
2430 | if (changes & BSS_CHANGED_ERP_CTS_PROT) { | ||
2431 | D_MAC80211( | ||
2432 | "ERP_CTS %d\n", bss_conf->use_cts_prot); | ||
2433 | if (bss_conf->use_cts_prot && il->band != IEEE80211_BAND_5GHZ) | ||
2434 | ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; | ||
2435 | else | ||
2436 | ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK; | ||
2437 | if (bss_conf->use_cts_prot) | ||
2438 | ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; | ||
2439 | else | ||
2440 | ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN; | ||
2441 | } | ||
2442 | |||
2443 | if (changes & BSS_CHANGED_BASIC_RATES) { | ||
2444 | /* XXX use this information | ||
2445 | * | ||
2446 | * To do that, remove code from il_set_rate() and put something | ||
2447 | * like this here: | ||
2448 | * | ||
2449 | if (A-band) | ||
2450 | ctx->staging.ofdm_basic_rates = | ||
2451 | bss_conf->basic_rates; | ||
2452 | else | ||
2453 | ctx->staging.ofdm_basic_rates = | ||
2454 | bss_conf->basic_rates >> 4; | ||
2455 | ctx->staging.cck_basic_rates = | ||
2456 | bss_conf->basic_rates & 0xF; | ||
2457 | */ | ||
2458 | } | ||
2459 | |||
2460 | if (changes & BSS_CHANGED_HT) { | ||
2461 | il_ht_conf(il, vif); | ||
2462 | |||
2463 | if (il->cfg->ops->hcmd->set_rxon_chain) | ||
2464 | il->cfg->ops->hcmd->set_rxon_chain(il, ctx); | ||
2465 | } | ||
2466 | |||
2467 | if (changes & BSS_CHANGED_ASSOC) { | ||
2468 | D_MAC80211("ASSOC %d\n", bss_conf->assoc); | ||
2469 | if (bss_conf->assoc) { | ||
2470 | il->timestamp = bss_conf->timestamp; | ||
2471 | |||
2472 | if (!il_is_rfkill(il)) | ||
2473 | il->cfg->ops->legacy->post_associate(il); | ||
2474 | } else | ||
2475 | il_set_no_assoc(il, vif); | ||
2476 | } | ||
2477 | |||
2478 | if (changes && il_is_associated_ctx(ctx) && bss_conf->aid) { | ||
2479 | D_MAC80211("Changes (%#x) while associated\n", | ||
2480 | changes); | ||
2481 | ret = il_send_rxon_assoc(il, ctx); | ||
2482 | if (!ret) { | ||
2483 | /* Sync active_rxon with latest change. */ | ||
2484 | memcpy((void *)&ctx->active, | ||
2485 | &ctx->staging, | ||
2486 | sizeof(struct il_rxon_cmd)); | ||
2487 | } | ||
2488 | } | ||
2489 | |||
2490 | if (changes & BSS_CHANGED_BEACON_ENABLED) { | ||
2491 | if (vif->bss_conf.enable_beacon) { | ||
2492 | memcpy(ctx->staging.bssid_addr, | ||
2493 | bss_conf->bssid, ETH_ALEN); | ||
2494 | memcpy(il->bssid, bss_conf->bssid, ETH_ALEN); | ||
2495 | il->cfg->ops->legacy->config_ap(il); | ||
2496 | } else | ||
2497 | il_set_no_assoc(il, vif); | ||
2498 | } | ||
2499 | |||
2500 | if (changes & BSS_CHANGED_IBSS) { | ||
2501 | ret = il->cfg->ops->legacy->manage_ibss_station(il, vif, | ||
2502 | bss_conf->ibss_joined); | ||
2503 | if (ret) | ||
2504 | IL_ERR("failed to %s IBSS station %pM\n", | ||
2505 | bss_conf->ibss_joined ? "add" : "remove", | ||
2506 | bss_conf->bssid); | ||
2507 | } | ||
2508 | |||
2509 | mutex_unlock(&il->mutex); | ||
2510 | |||
2511 | D_MAC80211("leave\n"); | ||
2512 | } | ||
2513 | EXPORT_SYMBOL(il_mac_bss_info_changed); | ||
2514 | |||
2515 | irqreturn_t il_isr(int irq, void *data) | ||
2516 | { | ||
2517 | struct il_priv *il = data; | ||
2518 | u32 inta, inta_mask; | ||
2519 | u32 inta_fh; | ||
2520 | unsigned long flags; | ||
2521 | if (!il) | ||
2522 | return IRQ_NONE; | ||
2523 | |||
2524 | spin_lock_irqsave(&il->lock, flags); | ||
2525 | |||
2526 | /* Disable (but don't clear!) interrupts here to avoid | ||
2527 | * back-to-back ISRs and sporadic interrupts from our NIC. | ||
2528 | * If we have something to service, the tasklet will re-enable ints. | ||
2529 | * If we *don't* have something, we'll re-enable before leaving here. */ | ||
2530 | inta_mask = _il_rd(il, CSR_INT_MASK); /* just for debug */ | ||
2531 | _il_wr(il, CSR_INT_MASK, 0x00000000); | ||
2532 | |||
2533 | /* Discover which interrupts are active/pending */ | ||
2534 | inta = _il_rd(il, CSR_INT); | ||
2535 | inta_fh = _il_rd(il, CSR_FH_INT_STATUS); | ||
2536 | |||
2537 | /* Ignore interrupt if there's nothing in NIC to service. | ||
2538 | * This may be due to IRQ shared with another device, | ||
2539 | * or due to sporadic interrupts thrown from our NIC. */ | ||
2540 | if (!inta && !inta_fh) { | ||
2541 | D_ISR( | ||
2542 | "Ignore interrupt, inta == 0, inta_fh == 0\n"); | ||
2543 | goto none; | ||
2544 | } | ||
2545 | |||
2546 | if (inta == 0xFFFFFFFF || (inta & 0xFFFFFFF0) == 0xa5a5a5a0) { | ||
2547 | /* Hardware disappeared. It might have already raised | ||
2548 | * an interrupt */ | ||
2549 | IL_WARN("HARDWARE GONE?? INTA == 0x%08x\n", inta); | ||
2550 | goto unplugged; | ||
2551 | } | ||
2552 | |||
2553 | D_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", | ||
2554 | inta, inta_mask, inta_fh); | ||
2555 | |||
2556 | inta &= ~CSR_INT_BIT_SCD; | ||
2557 | |||
2558 | /* il_irq_tasklet() will service interrupts and re-enable them */ | ||
2559 | if (likely(inta || inta_fh)) | ||
2560 | tasklet_schedule(&il->irq_tasklet); | ||
2561 | |||
2562 | unplugged: | ||
2563 | spin_unlock_irqrestore(&il->lock, flags); | ||
2564 | return IRQ_HANDLED; | ||
2565 | |||
2566 | none: | ||
2567 | /* re-enable interrupts here since we don't have anything to service. */ | ||
2568 | /* only Re-enable if disabled by irq */ | ||
2569 | if (test_bit(S_INT_ENABLED, &il->status)) | ||
2570 | il_enable_interrupts(il); | ||
2571 | spin_unlock_irqrestore(&il->lock, flags); | ||
2572 | return IRQ_NONE; | ||
2573 | } | ||
2574 | EXPORT_SYMBOL(il_isr); | ||
2575 | |||
2576 | /* | ||
2577 | * il_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this | ||
2578 | * function. | ||
2579 | */ | ||
2580 | void il_tx_cmd_protection(struct il_priv *il, | ||
2581 | struct ieee80211_tx_info *info, | ||
2582 | __le16 fc, __le32 *tx_flags) | ||
2583 | { | ||
2584 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { | ||
2585 | *tx_flags |= TX_CMD_FLG_RTS_MSK; | ||
2586 | *tx_flags &= ~TX_CMD_FLG_CTS_MSK; | ||
2587 | *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | ||
2588 | |||
2589 | if (!ieee80211_is_mgmt(fc)) | ||
2590 | return; | ||
2591 | |||
2592 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { | ||
2593 | case cpu_to_le16(IEEE80211_STYPE_AUTH): | ||
2594 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): | ||
2595 | case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): | ||
2596 | case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): | ||
2597 | *tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
2598 | *tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
2599 | break; | ||
2600 | } | ||
2601 | } else if (info->control.rates[0].flags & | ||
2602 | IEEE80211_TX_RC_USE_CTS_PROTECT) { | ||
2603 | *tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
2604 | *tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
2605 | *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | ||
2606 | } | ||
2607 | } | ||
2608 | EXPORT_SYMBOL(il_tx_cmd_protection); | ||