blob: 142d39f94498edd0208e07b7073ab248f4682864 [file] [log] [blame]
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001/******************************************************************************
2 *
3 * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
4 *
5 * Portions of this file are derived from the ipw3945 project, as well
6 * as portions of the ieee80211 subsystem header files.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of version 2 of the GNU General Public License as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
20 *
21 * The full GNU General Public License is included in this distribution in the
22 * file called LICENSE.
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
30#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31
32#include <linux/kernel.h>
33#include <linux/module.h>
34#include <linux/init.h>
35#include <linux/pci.h>
36#include <linux/pci-aspm.h>
37#include <linux/slab.h>
38#include <linux/dma-mapping.h>
39#include <linux/delay.h>
40#include <linux/sched.h>
41#include <linux/skbuff.h>
42#include <linux/netdevice.h>
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080043#include <linux/firmware.h>
44#include <linux/etherdevice.h>
45#include <linux/if_arp.h>
46
47#include <net/mac80211.h>
48
49#include <asm/div64.h>
50
51#define DRV_NAME "iwl4965"
52
53#include "iwl-eeprom.h"
54#include "iwl-dev.h"
55#include "iwl-core.h"
56#include "iwl-io.h"
57#include "iwl-helpers.h"
58#include "iwl-sta.h"
59#include "iwl-4965-calib.h"
60#include "iwl-4965.h"
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080061
62
63/******************************************************************************
64 *
65 * module boiler plate
66 *
67 ******************************************************************************/
68
69/*
70 * module name, copyright, version, etc.
71 */
72#define DRV_DESCRIPTION "Intel(R) Wireless WiFi 4965 driver for Linux"
73
Stanislaw Gruszkad3175162011-11-15 11:25:42 +010074#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080075#define VD "d"
76#else
77#define VD
78#endif
79
80#define DRV_VERSION IWLWIFI_VERSION VD
81
82
83MODULE_DESCRIPTION(DRV_DESCRIPTION);
84MODULE_VERSION(DRV_VERSION);
85MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
86MODULE_LICENSE("GPL");
87MODULE_ALIAS("iwl4965");
88
Stanislaw Gruszkaeb3cdfb2011-08-30 12:58:35 +020089static struct il_link_quality_cmd *
90il4965_sta_alloc_lq(struct il_priv *il, u8 sta_id)
91{
92 int i, r;
93 struct il_link_quality_cmd *link_cmd;
94 u32 rate_flags = 0;
95 __le32 rate_n_flags;
96
97 link_cmd = kzalloc(sizeof(struct il_link_quality_cmd), GFP_KERNEL);
98 if (!link_cmd) {
99 IL_ERR("Unable to allocate memory for LQ cmd.\n");
100 return NULL;
101 }
102 /* Set up the rate scaling to start at selected rate, fall back
103 * all the way down to 1M in IEEE order, and then spin on 1M */
104 if (il->band == IEEE80211_BAND_5GHZ)
105 r = RATE_6M_IDX;
106 else
107 r = RATE_1M_IDX;
108
109 if (r >= IL_FIRST_CCK_RATE && r <= IL_LAST_CCK_RATE)
110 rate_flags |= RATE_MCS_CCK_MSK;
111
112 rate_flags |= il4965_first_antenna(il->hw_params.valid_tx_ant) <<
113 RATE_MCS_ANT_POS;
114 rate_n_flags = il4965_hw_set_rate_n_flags(il_rates[r].plcp,
115 rate_flags);
116 for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
117 link_cmd->rs_table[i].rate_n_flags = rate_n_flags;
118
119 link_cmd->general_params.single_stream_ant_msk =
120 il4965_first_antenna(il->hw_params.valid_tx_ant);
121
122 link_cmd->general_params.dual_stream_ant_msk =
123 il->hw_params.valid_tx_ant &
124 ~il4965_first_antenna(il->hw_params.valid_tx_ant);
125 if (!link_cmd->general_params.dual_stream_ant_msk) {
126 link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
127 } else if (il4965_num_of_ant(il->hw_params.valid_tx_ant) == 2) {
128 link_cmd->general_params.dual_stream_ant_msk =
129 il->hw_params.valid_tx_ant;
130 }
131
132 link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
133 link_cmd->agg_params.agg_time_limit =
134 cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
135
136 link_cmd->sta_id = sta_id;
137
138 return link_cmd;
139}
140
141/*
142 * il4965_add_bssid_station - Add the special IBSS BSSID station
143 *
144 * Function sleeps.
145 */
146int
147il4965_add_bssid_station(struct il_priv *il, struct il_rxon_context *ctx,
148 const u8 *addr, u8 *sta_id_r)
149{
150 int ret;
151 u8 sta_id;
152 struct il_link_quality_cmd *link_cmd;
153 unsigned long flags;
154
155 if (sta_id_r)
156 *sta_id_r = IL_INVALID_STATION;
157
158 ret = il_add_station_common(il, ctx, addr, 0, NULL, &sta_id);
159 if (ret) {
160 IL_ERR("Unable to add station %pM\n", addr);
161 return ret;
162 }
163
164 if (sta_id_r)
165 *sta_id_r = sta_id;
166
167 spin_lock_irqsave(&il->sta_lock, flags);
168 il->stations[sta_id].used |= IL_STA_LOCAL;
169 spin_unlock_irqrestore(&il->sta_lock, flags);
170
171 /* Set up default rate scaling table in device's station table */
172 link_cmd = il4965_sta_alloc_lq(il, sta_id);
173 if (!link_cmd) {
174 IL_ERR(
175 "Unable to initialize rate scaling for station %pM.\n",
176 addr);
177 return -ENOMEM;
178 }
179
180 ret = il_send_lq_cmd(il, ctx, link_cmd, CMD_SYNC, true);
181 if (ret)
182 IL_ERR("Link quality command failed (%d)\n", ret);
183
184 spin_lock_irqsave(&il->sta_lock, flags);
185 il->stations[sta_id].lq = link_cmd;
186 spin_unlock_irqrestore(&il->sta_lock, flags);
187
188 return 0;
189}
190
191static int il4965_static_wepkey_cmd(struct il_priv *il,
192 struct il_rxon_context *ctx,
193 bool send_if_empty)
194{
195 int i, not_empty = 0;
196 u8 buff[sizeof(struct il_wep_cmd) +
197 sizeof(struct il_wep_key) * WEP_KEYS_MAX];
198 struct il_wep_cmd *wep_cmd = (struct il_wep_cmd *)buff;
199 size_t cmd_size = sizeof(struct il_wep_cmd);
200 struct il_host_cmd cmd = {
201 .id = ctx->wep_key_cmd,
202 .data = wep_cmd,
203 .flags = CMD_SYNC,
204 };
205
206 might_sleep();
207
208 memset(wep_cmd, 0, cmd_size +
209 (sizeof(struct il_wep_key) * WEP_KEYS_MAX));
210
211 for (i = 0; i < WEP_KEYS_MAX ; i++) {
212 wep_cmd->key[i].key_idx = i;
213 if (ctx->wep_keys[i].key_size) {
214 wep_cmd->key[i].key_offset = i;
215 not_empty = 1;
216 } else {
217 wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET;
218 }
219
220 wep_cmd->key[i].key_size = ctx->wep_keys[i].key_size;
221 memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key,
222 ctx->wep_keys[i].key_size);
223 }
224
225 wep_cmd->global_key_type = WEP_KEY_WEP_TYPE;
226 wep_cmd->num_keys = WEP_KEYS_MAX;
227
228 cmd_size += sizeof(struct il_wep_key) * WEP_KEYS_MAX;
229
230 cmd.len = cmd_size;
231
232 if (not_empty || send_if_empty)
233 return il_send_cmd(il, &cmd);
234 else
235 return 0;
236}
237
238int il4965_restore_default_wep_keys(struct il_priv *il,
239 struct il_rxon_context *ctx)
240{
241 lockdep_assert_held(&il->mutex);
242
243 return il4965_static_wepkey_cmd(il, ctx, false);
244}
245
246int il4965_remove_default_wep_key(struct il_priv *il,
247 struct il_rxon_context *ctx,
248 struct ieee80211_key_conf *keyconf)
249{
250 int ret;
251
252 lockdep_assert_held(&il->mutex);
253
254 D_WEP("Removing default WEP key: idx=%d\n",
255 keyconf->keyidx);
256
257 memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0]));
258 if (il_is_rfkill(il)) {
259 D_WEP(
260 "Not sending REPLY_WEPKEY command due to RFKILL.\n");
261 /* but keys in device are clear anyway so return success */
262 return 0;
263 }
264 ret = il4965_static_wepkey_cmd(il, ctx, 1);
265 D_WEP("Remove default WEP key: idx=%d ret=%d\n",
266 keyconf->keyidx, ret);
267
268 return ret;
269}
270
271int il4965_set_default_wep_key(struct il_priv *il,
272 struct il_rxon_context *ctx,
273 struct ieee80211_key_conf *keyconf)
274{
275 int ret;
276
277 lockdep_assert_held(&il->mutex);
278
279 if (keyconf->keylen != WEP_KEY_LEN_128 &&
280 keyconf->keylen != WEP_KEY_LEN_64) {
281 D_WEP("Bad WEP key length %d\n", keyconf->keylen);
282 return -EINVAL;
283 }
284
285 keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
286 keyconf->hw_key_idx = HW_KEY_DEFAULT;
287 il->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher;
288
289 ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
290 memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key,
291 keyconf->keylen);
292
293 ret = il4965_static_wepkey_cmd(il, ctx, false);
294 D_WEP("Set default WEP key: len=%d idx=%d ret=%d\n",
295 keyconf->keylen, keyconf->keyidx, ret);
296
297 return ret;
298}
299
300static int il4965_set_wep_dynamic_key_info(struct il_priv *il,
301 struct il_rxon_context *ctx,
302 struct ieee80211_key_conf *keyconf,
303 u8 sta_id)
304{
305 unsigned long flags;
306 __le16 key_flags = 0;
307 struct il_addsta_cmd sta_cmd;
308
309 lockdep_assert_held(&il->mutex);
310
311 keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
312
313 key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
314 key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
315 key_flags &= ~STA_KEY_FLG_INVALID;
316
317 if (keyconf->keylen == WEP_KEY_LEN_128)
318 key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
319
320 if (sta_id == ctx->bcast_sta_id)
321 key_flags |= STA_KEY_MULTICAST_MSK;
322
323 spin_lock_irqsave(&il->sta_lock, flags);
324
325 il->stations[sta_id].keyinfo.cipher = keyconf->cipher;
326 il->stations[sta_id].keyinfo.keylen = keyconf->keylen;
327 il->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
328
329 memcpy(il->stations[sta_id].keyinfo.key,
330 keyconf->key, keyconf->keylen);
331
332 memcpy(&il->stations[sta_id].sta.key.key[3],
333 keyconf->key, keyconf->keylen);
334
335 if ((il->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
336 == STA_KEY_FLG_NO_ENC)
337 il->stations[sta_id].sta.key.key_offset =
338 il_get_free_ucode_key_idx(il);
339 /* else, we are overriding an existing key => no need to allocated room
340 * in uCode. */
341
342 WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
343 "no space for a new key");
344
345 il->stations[sta_id].sta.key.key_flags = key_flags;
346 il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
347 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
348
349 memcpy(&sta_cmd, &il->stations[sta_id].sta,
350 sizeof(struct il_addsta_cmd));
351 spin_unlock_irqrestore(&il->sta_lock, flags);
352
353 return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
354}
355
356static int il4965_set_ccmp_dynamic_key_info(struct il_priv *il,
357 struct il_rxon_context *ctx,
358 struct ieee80211_key_conf *keyconf,
359 u8 sta_id)
360{
361 unsigned long flags;
362 __le16 key_flags = 0;
363 struct il_addsta_cmd sta_cmd;
364
365 lockdep_assert_held(&il->mutex);
366
367 key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
368 key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
369 key_flags &= ~STA_KEY_FLG_INVALID;
370
371 if (sta_id == ctx->bcast_sta_id)
372 key_flags |= STA_KEY_MULTICAST_MSK;
373
374 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
375
376 spin_lock_irqsave(&il->sta_lock, flags);
377 il->stations[sta_id].keyinfo.cipher = keyconf->cipher;
378 il->stations[sta_id].keyinfo.keylen = keyconf->keylen;
379
380 memcpy(il->stations[sta_id].keyinfo.key, keyconf->key,
381 keyconf->keylen);
382
383 memcpy(il->stations[sta_id].sta.key.key, keyconf->key,
384 keyconf->keylen);
385
386 if ((il->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
387 == STA_KEY_FLG_NO_ENC)
388 il->stations[sta_id].sta.key.key_offset =
389 il_get_free_ucode_key_idx(il);
390 /* else, we are overriding an existing key => no need to allocated room
391 * in uCode. */
392
393 WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
394 "no space for a new key");
395
396 il->stations[sta_id].sta.key.key_flags = key_flags;
397 il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
398 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
399
400 memcpy(&sta_cmd, &il->stations[sta_id].sta,
401 sizeof(struct il_addsta_cmd));
402 spin_unlock_irqrestore(&il->sta_lock, flags);
403
404 return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
405}
406
407static int il4965_set_tkip_dynamic_key_info(struct il_priv *il,
408 struct il_rxon_context *ctx,
409 struct ieee80211_key_conf *keyconf,
410 u8 sta_id)
411{
412 unsigned long flags;
413 int ret = 0;
414 __le16 key_flags = 0;
415
416 key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
417 key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
418 key_flags &= ~STA_KEY_FLG_INVALID;
419
420 if (sta_id == ctx->bcast_sta_id)
421 key_flags |= STA_KEY_MULTICAST_MSK;
422
423 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
424 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
425
426 spin_lock_irqsave(&il->sta_lock, flags);
427
428 il->stations[sta_id].keyinfo.cipher = keyconf->cipher;
429 il->stations[sta_id].keyinfo.keylen = 16;
430
431 if ((il->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
432 == STA_KEY_FLG_NO_ENC)
433 il->stations[sta_id].sta.key.key_offset =
434 il_get_free_ucode_key_idx(il);
435 /* else, we are overriding an existing key => no need to allocated room
436 * in uCode. */
437
438 WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
439 "no space for a new key");
440
441 il->stations[sta_id].sta.key.key_flags = key_flags;
442
443
444 /* This copy is acutally not needed: we get the key with each TX */
445 memcpy(il->stations[sta_id].keyinfo.key, keyconf->key, 16);
446
447 memcpy(il->stations[sta_id].sta.key.key, keyconf->key, 16);
448
449 spin_unlock_irqrestore(&il->sta_lock, flags);
450
451 return ret;
452}
453
454void il4965_update_tkip_key(struct il_priv *il,
455 struct il_rxon_context *ctx,
456 struct ieee80211_key_conf *keyconf,
457 struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
458{
459 u8 sta_id;
460 unsigned long flags;
461 int i;
462
463 if (il_scan_cancel(il)) {
464 /* cancel scan failed, just live w/ bad key and rely
465 briefly on SW decryption */
466 return;
467 }
468
469 sta_id = il_sta_id_or_broadcast(il, ctx, sta);
470 if (sta_id == IL_INVALID_STATION)
471 return;
472
473 spin_lock_irqsave(&il->sta_lock, flags);
474
475 il->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
476
477 for (i = 0; i < 5; i++)
478 il->stations[sta_id].sta.key.tkip_rx_ttak[i] =
479 cpu_to_le16(phase1key[i]);
480
481 il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
482 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
483
484 il_send_add_sta(il, &il->stations[sta_id].sta, CMD_ASYNC);
485
486 spin_unlock_irqrestore(&il->sta_lock, flags);
487
488}
489
490int il4965_remove_dynamic_key(struct il_priv *il,
491 struct il_rxon_context *ctx,
492 struct ieee80211_key_conf *keyconf,
493 u8 sta_id)
494{
495 unsigned long flags;
496 u16 key_flags;
497 u8 keyidx;
498 struct il_addsta_cmd sta_cmd;
499
500 lockdep_assert_held(&il->mutex);
501
502 ctx->key_mapping_keys--;
503
504 spin_lock_irqsave(&il->sta_lock, flags);
505 key_flags = le16_to_cpu(il->stations[sta_id].sta.key.key_flags);
506 keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;
507
508 D_WEP("Remove dynamic key: idx=%d sta=%d\n",
509 keyconf->keyidx, sta_id);
510
511 if (keyconf->keyidx != keyidx) {
512 /* We need to remove a key with idx different that the one
513 * in the uCode. This means that the key we need to remove has
514 * been replaced by another one with different idx.
515 * Don't do anything and return ok
516 */
517 spin_unlock_irqrestore(&il->sta_lock, flags);
518 return 0;
519 }
520
521 if (il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
522 IL_WARN("Removing wrong key %d 0x%x\n",
523 keyconf->keyidx, key_flags);
524 spin_unlock_irqrestore(&il->sta_lock, flags);
525 return 0;
526 }
527
528 if (!test_and_clear_bit(il->stations[sta_id].sta.key.key_offset,
529 &il->ucode_key_table))
530 IL_ERR("idx %d not used in uCode key table.\n",
531 il->stations[sta_id].sta.key.key_offset);
532 memset(&il->stations[sta_id].keyinfo, 0,
533 sizeof(struct il_hw_key));
534 memset(&il->stations[sta_id].sta.key, 0,
535 sizeof(struct il4965_keyinfo));
536 il->stations[sta_id].sta.key.key_flags =
537 STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
538 il->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
539 il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
540 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
541
542 if (il_is_rfkill(il)) {
543 D_WEP(
544 "Not sending REPLY_ADD_STA command because RFKILL enabled.\n");
545 spin_unlock_irqrestore(&il->sta_lock, flags);
546 return 0;
547 }
548 memcpy(&sta_cmd, &il->stations[sta_id].sta,
549 sizeof(struct il_addsta_cmd));
550 spin_unlock_irqrestore(&il->sta_lock, flags);
551
552 return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
553}
554
555int il4965_set_dynamic_key(struct il_priv *il, struct il_rxon_context *ctx,
556 struct ieee80211_key_conf *keyconf, u8 sta_id)
557{
558 int ret;
559
560 lockdep_assert_held(&il->mutex);
561
562 ctx->key_mapping_keys++;
563 keyconf->hw_key_idx = HW_KEY_DYNAMIC;
564
565 switch (keyconf->cipher) {
566 case WLAN_CIPHER_SUITE_CCMP:
567 ret = il4965_set_ccmp_dynamic_key_info(il, ctx,
568 keyconf, sta_id);
569 break;
570 case WLAN_CIPHER_SUITE_TKIP:
571 ret = il4965_set_tkip_dynamic_key_info(il, ctx,
572 keyconf, sta_id);
573 break;
574 case WLAN_CIPHER_SUITE_WEP40:
575 case WLAN_CIPHER_SUITE_WEP104:
576 ret = il4965_set_wep_dynamic_key_info(il, ctx,
577 keyconf, sta_id);
578 break;
579 default:
580 IL_ERR(
581 "Unknown alg: %s cipher = %x\n", __func__,
582 keyconf->cipher);
583 ret = -EINVAL;
584 }
585
586 D_WEP(
587 "Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n",
588 keyconf->cipher, keyconf->keylen, keyconf->keyidx,
589 sta_id, ret);
590
591 return ret;
592}
593
594/**
595 * il4965_alloc_bcast_station - add broadcast station into driver's station table.
596 *
597 * This adds the broadcast station into the driver's station table
598 * and marks it driver active, so that it will be restored to the
599 * device at the next best time.
600 */
601int il4965_alloc_bcast_station(struct il_priv *il,
602 struct il_rxon_context *ctx)
603{
604 struct il_link_quality_cmd *link_cmd;
605 unsigned long flags;
606 u8 sta_id;
607
608 spin_lock_irqsave(&il->sta_lock, flags);
609 sta_id = il_prep_station(il, ctx, il_bcast_addr,
610 false, NULL);
611 if (sta_id == IL_INVALID_STATION) {
612 IL_ERR("Unable to prepare broadcast station\n");
613 spin_unlock_irqrestore(&il->sta_lock, flags);
614
615 return -EINVAL;
616 }
617
618 il->stations[sta_id].used |= IL_STA_DRIVER_ACTIVE;
619 il->stations[sta_id].used |= IL_STA_BCAST;
620 spin_unlock_irqrestore(&il->sta_lock, flags);
621
622 link_cmd = il4965_sta_alloc_lq(il, sta_id);
623 if (!link_cmd) {
624 IL_ERR(
625 "Unable to initialize rate scaling for bcast station.\n");
626 return -ENOMEM;
627 }
628
629 spin_lock_irqsave(&il->sta_lock, flags);
630 il->stations[sta_id].lq = link_cmd;
631 spin_unlock_irqrestore(&il->sta_lock, flags);
632
633 return 0;
634}
635
636/**
637 * il4965_update_bcast_station - update broadcast station's LQ command
638 *
639 * Only used by iwl4965. Placed here to have all bcast station management
640 * code together.
641 */
642static int il4965_update_bcast_station(struct il_priv *il,
643 struct il_rxon_context *ctx)
644{
645 unsigned long flags;
646 struct il_link_quality_cmd *link_cmd;
647 u8 sta_id = ctx->bcast_sta_id;
648
649 link_cmd = il4965_sta_alloc_lq(il, sta_id);
650 if (!link_cmd) {
651 IL_ERR(
652 "Unable to initialize rate scaling for bcast station.\n");
653 return -ENOMEM;
654 }
655
656 spin_lock_irqsave(&il->sta_lock, flags);
657 if (il->stations[sta_id].lq)
658 kfree(il->stations[sta_id].lq);
659 else
660 D_INFO(
661 "Bcast station rate scaling has not been initialized yet.\n");
662 il->stations[sta_id].lq = link_cmd;
663 spin_unlock_irqrestore(&il->sta_lock, flags);
664
665 return 0;
666}
667
668int il4965_update_bcast_stations(struct il_priv *il)
669{
670 return il4965_update_bcast_station(il, &il->ctx);
671}
672
673/**
674 * il4965_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
675 */
676int il4965_sta_tx_modify_enable_tid(struct il_priv *il, int sta_id, int tid)
677{
678 unsigned long flags;
679 struct il_addsta_cmd sta_cmd;
680
681 lockdep_assert_held(&il->mutex);
682
683 /* Remove "disable" flag, to enable Tx for this TID */
684 spin_lock_irqsave(&il->sta_lock, flags);
685 il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
686 il->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
687 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
688 memcpy(&sta_cmd, &il->stations[sta_id].sta,
689 sizeof(struct il_addsta_cmd));
690 spin_unlock_irqrestore(&il->sta_lock, flags);
691
692 return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
693}
694
695int il4965_sta_rx_agg_start(struct il_priv *il, struct ieee80211_sta *sta,
696 int tid, u16 ssn)
697{
698 unsigned long flags;
699 int sta_id;
700 struct il_addsta_cmd sta_cmd;
701
702 lockdep_assert_held(&il->mutex);
703
704 sta_id = il_sta_id(sta);
705 if (sta_id == IL_INVALID_STATION)
706 return -ENXIO;
707
708 spin_lock_irqsave(&il->sta_lock, flags);
709 il->stations[sta_id].sta.station_flags_msk = 0;
710 il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
711 il->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
712 il->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
713 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
714 memcpy(&sta_cmd, &il->stations[sta_id].sta,
715 sizeof(struct il_addsta_cmd));
716 spin_unlock_irqrestore(&il->sta_lock, flags);
717
718 return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
719}
720
721int il4965_sta_rx_agg_stop(struct il_priv *il, struct ieee80211_sta *sta,
722 int tid)
723{
724 unsigned long flags;
725 int sta_id;
726 struct il_addsta_cmd sta_cmd;
727
728 lockdep_assert_held(&il->mutex);
729
730 sta_id = il_sta_id(sta);
731 if (sta_id == IL_INVALID_STATION) {
732 IL_ERR("Invalid station for AGG tid %d\n", tid);
733 return -ENXIO;
734 }
735
736 spin_lock_irqsave(&il->sta_lock, flags);
737 il->stations[sta_id].sta.station_flags_msk = 0;
738 il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
739 il->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
740 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
741 memcpy(&sta_cmd, &il->stations[sta_id].sta,
742 sizeof(struct il_addsta_cmd));
743 spin_unlock_irqrestore(&il->sta_lock, flags);
744
745 return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
746}
747
748void
749il4965_sta_modify_sleep_tx_count(struct il_priv *il, int sta_id, int cnt)
750{
751 unsigned long flags;
752
753 spin_lock_irqsave(&il->sta_lock, flags);
754 il->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
755 il->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
756 il->stations[sta_id].sta.sta.modify_mask =
757 STA_MODIFY_SLEEP_TX_COUNT_MSK;
758 il->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
759 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
760 il_send_add_sta(il,
761 &il->stations[sta_id].sta, CMD_ASYNC);
762 spin_unlock_irqrestore(&il->sta_lock, flags);
763
764}
765
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200766void il4965_update_chain_flags(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800767{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200768 if (il->cfg->ops->hcmd->set_rxon_chain) {
Stanislaw Gruszka17d6e552011-08-29 12:52:20 +0200769 il->cfg->ops->hcmd->set_rxon_chain(il, &il->ctx);
770 if (il->ctx.active.rx_chain != il->ctx.staging.rx_chain)
771 il_commit_rxon(il, &il->ctx);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800772 }
773}
774
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200775static void il4965_clear_free_frames(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800776{
777 struct list_head *element;
778
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100779 D_INFO("%d frames on pre-allocated heap on clear.\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200780 il->frames_count);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800781
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200782 while (!list_empty(&il->free_frames)) {
783 element = il->free_frames.next;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800784 list_del(element);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200785 kfree(list_entry(element, struct il_frame, list));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200786 il->frames_count--;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800787 }
788
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200789 if (il->frames_count) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200790 IL_WARN("%d frames still in use. Did we lose one?\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200791 il->frames_count);
792 il->frames_count = 0;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800793 }
794}
795
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200796static struct il_frame *il4965_get_free_frame(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800797{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200798 struct il_frame *frame;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800799 struct list_head *element;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200800 if (list_empty(&il->free_frames)) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800801 frame = kzalloc(sizeof(*frame), GFP_KERNEL);
802 if (!frame) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200803 IL_ERR("Could not allocate frame!\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800804 return NULL;
805 }
806
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200807 il->frames_count++;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800808 return frame;
809 }
810
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200811 element = il->free_frames.next;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800812 list_del(element);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200813 return list_entry(element, struct il_frame, list);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800814}
815
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200816static void il4965_free_frame(struct il_priv *il, struct il_frame *frame)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800817{
818 memset(frame, 0, sizeof(*frame));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200819 list_add(&frame->list, &il->free_frames);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800820}
821
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200822static u32 il4965_fill_beacon_frame(struct il_priv *il,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800823 struct ieee80211_hdr *hdr,
824 int left)
825{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200826 lockdep_assert_held(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800827
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200828 if (!il->beacon_skb)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800829 return 0;
830
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200831 if (il->beacon_skb->len > left)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800832 return 0;
833
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200834 memcpy(hdr, il->beacon_skb->data, il->beacon_skb->len);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800835
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200836 return il->beacon_skb->len;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800837}
838
839/* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200840static void il4965_set_beacon_tim(struct il_priv *il,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200841 struct il_tx_beacon_cmd *tx_beacon_cmd,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800842 u8 *beacon, u32 frame_size)
843{
844 u16 tim_idx;
845 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
846
847 /*
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100848 * The idx is relative to frame start but we start looking at the
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800849 * variable-length part of the beacon.
850 */
851 tim_idx = mgmt->u.beacon.variable - beacon;
852
853 /* Parse variable-length elements of beacon to find WLAN_EID_TIM */
854 while ((tim_idx < (frame_size - 2)) &&
855 (beacon[tim_idx] != WLAN_EID_TIM))
856 tim_idx += beacon[tim_idx+1] + 2;
857
858 /* If TIM field was found, set variables */
859 if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) {
860 tx_beacon_cmd->tim_idx = cpu_to_le16(tim_idx);
861 tx_beacon_cmd->tim_size = beacon[tim_idx+1];
862 } else
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200863 IL_WARN("Unable to find TIM Element in beacon\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800864}
865
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200866static unsigned int il4965_hw_get_beacon_cmd(struct il_priv *il,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200867 struct il_frame *frame)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800868{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200869 struct il_tx_beacon_cmd *tx_beacon_cmd;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800870 u32 frame_size;
871 u32 rate_flags;
872 u32 rate;
873 /*
874 * We have to set up the TX command, the TX Beacon command, and the
875 * beacon contents.
876 */
877
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200878 lockdep_assert_held(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800879
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200880 if (!il->beacon_ctx) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200881 IL_ERR("trying to build beacon w/o beacon context!\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800882 return 0;
883 }
884
885 /* Initialize memory */
886 tx_beacon_cmd = &frame->u.beacon;
887 memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
888
889 /* Set up TX beacon contents */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200890 frame_size = il4965_fill_beacon_frame(il, tx_beacon_cmd->frame,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800891 sizeof(frame->u) - sizeof(*tx_beacon_cmd));
892 if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE))
893 return 0;
894 if (!frame_size)
895 return 0;
896
897 /* Set up TX command fields */
898 tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200899 tx_beacon_cmd->tx.sta_id = il->beacon_ctx->bcast_sta_id;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800900 tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
901 tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK |
902 TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK;
903
904 /* Set up TX beacon command fields */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200905 il4965_set_beacon_tim(il, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800906 frame_size);
907
908 /* Set up packet rate and flags */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200909 rate = il_get_lowest_plcp(il, il->beacon_ctx);
910 il->mgmt_tx_ant = il4965_toggle_tx_ant(il, il->mgmt_tx_ant,
911 il->hw_params.valid_tx_ant);
912 rate_flags = il4965_ant_idx_to_flags(il->mgmt_tx_ant);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200913 if ((rate >= IL_FIRST_CCK_RATE) && (rate <= IL_LAST_CCK_RATE))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800914 rate_flags |= RATE_MCS_CCK_MSK;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200915 tx_beacon_cmd->tx.rate_n_flags = il4965_hw_set_rate_n_flags(rate,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800916 rate_flags);
917
918 return sizeof(*tx_beacon_cmd) + frame_size;
919}
920
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200921int il4965_send_beacon_cmd(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800922{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200923 struct il_frame *frame;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800924 unsigned int frame_size;
925 int rc;
926
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200927 frame = il4965_get_free_frame(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800928 if (!frame) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200929 IL_ERR("Could not obtain free frame buffer for beacon "
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800930 "command.\n");
931 return -ENOMEM;
932 }
933
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200934 frame_size = il4965_hw_get_beacon_cmd(il, frame);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800935 if (!frame_size) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200936 IL_ERR("Error configuring the beacon command\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200937 il4965_free_frame(il, frame);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800938 return -EINVAL;
939 }
940
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200941 rc = il_send_cmd_pdu(il, REPLY_TX_BEACON, frame_size,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800942 &frame->u.cmd[0]);
943
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200944 il4965_free_frame(il, frame);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800945
946 return rc;
947}
948
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200949static inline dma_addr_t il4965_tfd_tb_get_addr(struct il_tfd *tfd, u8 idx)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800950{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200951 struct il_tfd_tb *tb = &tfd->tbs[idx];
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800952
953 dma_addr_t addr = get_unaligned_le32(&tb->lo);
954 if (sizeof(dma_addr_t) > sizeof(u32))
955 addr |=
956 ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16;
957
958 return addr;
959}
960
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200961static inline u16 il4965_tfd_tb_get_len(struct il_tfd *tfd, u8 idx)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800962{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200963 struct il_tfd_tb *tb = &tfd->tbs[idx];
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800964
965 return le16_to_cpu(tb->hi_n_len) >> 4;
966}
967
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200968static inline void il4965_tfd_set_tb(struct il_tfd *tfd, u8 idx,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800969 dma_addr_t addr, u16 len)
970{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200971 struct il_tfd_tb *tb = &tfd->tbs[idx];
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800972 u16 hi_n_len = len << 4;
973
974 put_unaligned_le32(addr, &tb->lo);
975 if (sizeof(dma_addr_t) > sizeof(u32))
976 hi_n_len |= ((addr >> 16) >> 16) & 0xF;
977
978 tb->hi_n_len = cpu_to_le16(hi_n_len);
979
980 tfd->num_tbs = idx + 1;
981}
982
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200983static inline u8 il4965_tfd_get_num_tbs(struct il_tfd *tfd)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800984{
985 return tfd->num_tbs & 0x1f;
986}
987
988/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200989 * il4965_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200990 * @il - driver ilate data
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800991 * @txq - tx queue
992 *
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100993 * Does NOT advance any TFD circular buffer read/write idxes
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800994 * Does NOT free the TFD itself (which is within circular buffer)
995 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200996void il4965_hw_txq_free_tfd(struct il_priv *il, struct il_tx_queue *txq)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -0800997{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200998 struct il_tfd *tfd_tmp = (struct il_tfd *)txq->tfds;
999 struct il_tfd *tfd;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001000 struct pci_dev *dev = il->pci_dev;
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01001001 int idx = txq->q.read_ptr;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001002 int i;
1003 int num_tbs;
1004
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01001005 tfd = &tfd_tmp[idx];
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001006
1007 /* Sanity check on number of chunks */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001008 num_tbs = il4965_tfd_get_num_tbs(tfd);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001009
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001010 if (num_tbs >= IL_NUM_OF_TBS) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001011 IL_ERR("Too many chunks: %i\n", num_tbs);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001012 /* @todo issue fatal error, it is quite serious situation */
1013 return;
1014 }
1015
1016 /* Unmap tx_cmd */
1017 if (num_tbs)
1018 pci_unmap_single(dev,
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01001019 dma_unmap_addr(&txq->meta[idx], mapping),
1020 dma_unmap_len(&txq->meta[idx], len),
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001021 PCI_DMA_BIDIRECTIONAL);
1022
1023 /* Unmap chunks, if any. */
1024 for (i = 1; i < num_tbs; i++)
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001025 pci_unmap_single(dev, il4965_tfd_tb_get_addr(tfd, i),
1026 il4965_tfd_tb_get_len(tfd, i),
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001027 PCI_DMA_TODEVICE);
1028
1029 /* free SKB */
1030 if (txq->txb) {
1031 struct sk_buff *skb;
1032
1033 skb = txq->txb[txq->q.read_ptr].skb;
1034
1035 /* can be called from irqs-disabled context */
1036 if (skb) {
1037 dev_kfree_skb_any(skb);
1038 txq->txb[txq->q.read_ptr].skb = NULL;
1039 }
1040 }
1041}
1042
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001043int il4965_hw_txq_attach_buf_to_tfd(struct il_priv *il,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001044 struct il_tx_queue *txq,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001045 dma_addr_t addr, u16 len,
1046 u8 reset, u8 pad)
1047{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001048 struct il_queue *q;
1049 struct il_tfd *tfd, *tfd_tmp;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001050 u32 num_tbs;
1051
1052 q = &txq->q;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001053 tfd_tmp = (struct il_tfd *)txq->tfds;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001054 tfd = &tfd_tmp[q->write_ptr];
1055
1056 if (reset)
1057 memset(tfd, 0, sizeof(*tfd));
1058
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001059 num_tbs = il4965_tfd_get_num_tbs(tfd);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001060
1061 /* Each TFD can point to a maximum 20 Tx buffers */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001062 if (num_tbs >= IL_NUM_OF_TBS) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001063 IL_ERR("Error can not send more than %d chunks\n",
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001064 IL_NUM_OF_TBS);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001065 return -EINVAL;
1066 }
1067
1068 BUG_ON(addr & ~DMA_BIT_MASK(36));
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001069 if (unlikely(addr & ~IL_TX_DMA_MASK))
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001070 IL_ERR("Unaligned address = %llx\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001071 (unsigned long long)addr);
1072
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001073 il4965_tfd_set_tb(tfd, num_tbs, addr, len);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001074
1075 return 0;
1076}
1077
1078/*
1079 * Tell nic where to find circular buffer of Tx Frame Descriptors for
1080 * given Tx queue, and enable the DMA channel used for that queue.
1081 *
1082 * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
1083 * channels supported in hardware.
1084 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001085int il4965_hw_tx_queue_init(struct il_priv *il,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001086 struct il_tx_queue *txq)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001087{
1088 int txq_id = txq->q.id;
1089
1090 /* Circular buffer (TFD queue in DRAM) physical base address */
Stanislaw Gruszka0c1a94e2011-08-24 17:37:16 +02001091 il_wr(il, FH_MEM_CBBC_QUEUE(txq_id),
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001092 txq->q.dma_addr >> 8);
1093
1094 return 0;
1095}
1096
1097/******************************************************************************
1098 *
1099 * Generic RX handler implementations
1100 *
1101 ******************************************************************************/
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001102static void il4965_rx_reply_alive(struct il_priv *il,
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +02001103 struct il_rx_buf *rxb)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001104{
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +02001105 struct il_rx_pkt *pkt = rxb_addr(rxb);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001106 struct il_alive_resp *palive;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001107 struct delayed_work *pwork;
1108
1109 palive = &pkt->u.alive_frame;
1110
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001111 D_INFO("Alive ucode status 0x%08X revision "
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001112 "0x%01X 0x%01X\n",
1113 palive->is_valid, palive->ver_type,
1114 palive->ver_subtype);
1115
1116 if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001117 D_INFO("Initialization Alive received.\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001118 memcpy(&il->card_alive_init,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001119 &pkt->u.alive_frame,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001120 sizeof(struct il_init_alive_resp));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001121 pwork = &il->init_alive_start;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001122 } else {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001123 D_INFO("Runtime Alive received.\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001124 memcpy(&il->card_alive, &pkt->u.alive_frame,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001125 sizeof(struct il_alive_resp));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001126 pwork = &il->alive_start;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001127 }
1128
1129 /* We delay the ALIVE response by 5ms to
1130 * give the HW RF Kill time to activate... */
1131 if (palive->is_valid == UCODE_VALID_OK)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001132 queue_delayed_work(il->workqueue, pwork,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001133 msecs_to_jiffies(5));
1134 else
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001135 IL_WARN("uCode did not respond OK.\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001136}
1137
1138/**
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02001139 * il4965_bg_stats_periodic - Timer callback to queue stats
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001140 *
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02001141 * This callback is provided in order to send a stats request.
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001142 *
1143 * This timer function is continually reset to execute within
1144 * REG_RECALIB_PERIOD seconds since the last STATISTICS_NOTIFICATION
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02001145 * was received. We need to ensure we receive the stats in order
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001146 * to update the temperature used for calibrating the TXPOWER.
1147 */
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02001148static void il4965_bg_stats_periodic(unsigned long data)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001149{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001150 struct il_priv *il = (struct il_priv *)data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001151
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001152 if (test_bit(STATUS_EXIT_PENDING, &il->status))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001153 return;
1154
1155 /* dont send host command if rf-kill is on */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001156 if (!il_is_ready_rf(il))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001157 return;
1158
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02001159 il_send_stats_request(il, CMD_ASYNC, false);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001160}
1161
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001162static void il4965_rx_beacon_notif(struct il_priv *il,
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +02001163 struct il_rx_buf *rxb)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001164{
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +02001165 struct il_rx_pkt *pkt = rxb_addr(rxb);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001166 struct il4965_beacon_notif *beacon =
1167 (struct il4965_beacon_notif *)pkt->u.raw;
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001168#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001169 u8 rate = il4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001170
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001171 D_RX("beacon status %x retries %d iss %d "
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001172 "tsf %d %d rate %d\n",
1173 le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK,
1174 beacon->beacon_notify_hdr.failure_frame,
1175 le32_to_cpu(beacon->ibss_mgr_status),
1176 le32_to_cpu(beacon->high_tsf),
1177 le32_to_cpu(beacon->low_tsf), rate);
1178#endif
1179
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001180 il->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001181}
1182
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001183static void il4965_perform_ct_kill_task(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001184{
1185 unsigned long flags;
1186
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001187 D_POWER("Stop all queues\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001188
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001189 if (il->mac80211_registered)
1190 ieee80211_stop_queues(il->hw);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001191
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001192 _il_wr(il, CSR_UCODE_DRV_GP1_SET,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001193 CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001194 _il_rd(il, CSR_UCODE_DRV_GP1);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001195
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001196 spin_lock_irqsave(&il->reg_lock, flags);
Stanislaw Gruszka13882262011-08-24 15:39:23 +02001197 if (!_il_grab_nic_access(il))
1198 _il_release_nic_access(il);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001199 spin_unlock_irqrestore(&il->reg_lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001200}
1201
1202/* Handle notification from uCode that card's power state is changing
1203 * due to software, hardware, or critical temperature RFKILL */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001204static void il4965_rx_card_state_notif(struct il_priv *il,
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +02001205 struct il_rx_buf *rxb)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001206{
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +02001207 struct il_rx_pkt *pkt = rxb_addr(rxb);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001208 u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001209 unsigned long status = il->status;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001210
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001211 D_RF_KILL("Card state received: HW:%s SW:%s CT:%s\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001212 (flags & HW_CARD_DISABLED) ? "Kill" : "On",
1213 (flags & SW_CARD_DISABLED) ? "Kill" : "On",
1214 (flags & CT_CARD_DISABLED) ?
1215 "Reached" : "Not reached");
1216
1217 if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
1218 CT_CARD_DISABLED)) {
1219
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001220 _il_wr(il, CSR_UCODE_DRV_GP1_SET,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001221 CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
1222
Stanislaw Gruszka0c1a94e2011-08-24 17:37:16 +02001223 il_wr(il, HBUS_TARG_MBX_C,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001224 HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
1225
1226 if (!(flags & RXON_CARD_DISABLED)) {
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001227 _il_wr(il, CSR_UCODE_DRV_GP1_CLR,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001228 CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
Stanislaw Gruszka0c1a94e2011-08-24 17:37:16 +02001229 il_wr(il, HBUS_TARG_MBX_C,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001230 HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
1231 }
1232 }
1233
1234 if (flags & CT_CARD_DISABLED)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001235 il4965_perform_ct_kill_task(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001236
1237 if (flags & HW_CARD_DISABLED)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001238 set_bit(STATUS_RF_KILL_HW, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001239 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001240 clear_bit(STATUS_RF_KILL_HW, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001241
1242 if (!(flags & RXON_CARD_DISABLED))
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001243 il_scan_cancel(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001244
1245 if ((test_bit(STATUS_RF_KILL_HW, &status) !=
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001246 test_bit(STATUS_RF_KILL_HW, &il->status)))
1247 wiphy_rfkill_set_hw_state(il->hw->wiphy,
1248 test_bit(STATUS_RF_KILL_HW, &il->status));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001249 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001250 wake_up(&il->wait_command_queue);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001251}
1252
1253/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001254 * il4965_setup_rx_handlers - Initialize Rx handler callbacks
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001255 *
1256 * Setup the RX handlers for each of the reply types sent from the uCode
1257 * to the host.
1258 *
1259 * This function chains into the hardware specific files for them to setup
1260 * any hardware specific handlers as well.
1261 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001262static void il4965_setup_rx_handlers(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001263{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001264 il->rx_handlers[REPLY_ALIVE] = il4965_rx_reply_alive;
1265 il->rx_handlers[REPLY_ERROR] = il_rx_reply_error;
1266 il->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = il_rx_csa;
1267 il->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001268 il_rx_spectrum_measure_notif;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001269 il->rx_handlers[PM_SLEEP_NOTIFICATION] = il_rx_pm_sleep_notif;
1270 il->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02001271 il_rx_pm_debug_stats_notif;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001272 il->rx_handlers[BEACON_NOTIFICATION] = il4965_rx_beacon_notif;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001273
1274 /*
1275 * The same handler is used for both the REPLY to a discrete
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02001276 * stats request from the host as well as for the periodic
1277 * stats notifications (after received beacons) from the uCode.
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001278 */
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02001279 il->rx_handlers[REPLY_STATISTICS_CMD] = il4965_reply_stats;
1280 il->rx_handlers[STATISTICS_NOTIFICATION] = il4965_rx_stats;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001281
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001282 il_setup_rx_scan_handlers(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001283
1284 /* status change handler */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001285 il->rx_handlers[CARD_STATE_NOTIFICATION] =
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001286 il4965_rx_card_state_notif;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001287
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001288 il->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001289 il4965_rx_missed_beacon_notif;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001290 /* Rx handlers */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001291 il->rx_handlers[REPLY_RX_PHY_CMD] = il4965_rx_reply_rx_phy;
1292 il->rx_handlers[REPLY_RX_MPDU_CMD] = il4965_rx_reply_rx;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001293 /* block ack */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001294 il->rx_handlers[REPLY_COMPRESSED_BA] = il4965_rx_reply_compressed_ba;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001295 /* Set up hardware specific Rx handlers */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001296 il->cfg->ops->lib->rx_handler_setup(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001297}
1298
1299/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001300 * il4965_rx_handle - Main entry function for receiving responses from uCode
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001301 *
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001302 * Uses the il->rx_handlers callback function array to invoke
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001303 * the appropriate handlers, including command responses,
1304 * frame-received notifications, and other notifications.
1305 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001306void il4965_rx_handle(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001307{
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +02001308 struct il_rx_buf *rxb;
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +02001309 struct il_rx_pkt *pkt;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001310 struct il_rx_queue *rxq = &il->rxq;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001311 u32 r, i;
1312 int reclaim;
1313 unsigned long flags;
1314 u8 fill_rx = 0;
1315 u32 count = 8;
1316 int total_empty;
1317
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01001318 /* uCode's read idx (stored in shared DRAM) indicates the last Rx
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001319 * buffer that the driver may process (last buffer filled by ucode). */
1320 r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF;
1321 i = rxq->read;
1322
1323 /* Rx interrupt, but nothing sent from uCode */
1324 if (i == r)
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001325 D_RX("r = %d, i = %d\n", r, i);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001326
1327 /* calculate total frames need to be restock after handling RX */
1328 total_empty = r - rxq->write_actual;
1329 if (total_empty < 0)
1330 total_empty += RX_QUEUE_SIZE;
1331
1332 if (total_empty > (RX_QUEUE_SIZE / 2))
1333 fill_rx = 1;
1334
1335 while (i != r) {
1336 int len;
1337
1338 rxb = rxq->queue[i];
1339
1340 /* If an RXB doesn't have a Rx queue slot associated with it,
1341 * then a bug has been introduced in the queue refilling
1342 * routines -- catch it here */
1343 BUG_ON(rxb == NULL);
1344
1345 rxq->queue[i] = NULL;
1346
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001347 pci_unmap_page(il->pci_dev, rxb->page_dma,
1348 PAGE_SIZE << il->hw_params.rx_page_order,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001349 PCI_DMA_FROMDEVICE);
1350 pkt = rxb_addr(rxb);
1351
1352 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
1353 len += sizeof(u32); /* account for status word */
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001354
1355 /* Reclaim a command buffer only if this packet is a response
1356 * to a (driver-originated) command.
1357 * If the packet (e.g. Rx frame) originated from uCode,
1358 * there is no command buffer to reclaim.
1359 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
1360 * but apparently a few don't get set; catch them here. */
1361 reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
1362 (pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
1363 (pkt->hdr.cmd != REPLY_RX) &&
1364 (pkt->hdr.cmd != REPLY_RX_MPDU_CMD) &&
1365 (pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
1366 (pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
1367 (pkt->hdr.cmd != REPLY_TX);
1368
1369 /* Based on type of command response or notification,
1370 * handle those that need handling via function in
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001371 * rx_handlers table. See il4965_setup_rx_handlers() */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001372 if (il->rx_handlers[pkt->hdr.cmd]) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001373 D_RX("r = %d, i = %d, %s, 0x%02x\n", r,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001374 i, il_get_cmd_string(pkt->hdr.cmd),
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001375 pkt->hdr.cmd);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001376 il->isr_stats.rx_handlers[pkt->hdr.cmd]++;
1377 il->rx_handlers[pkt->hdr.cmd] (il, rxb);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001378 } else {
1379 /* No handling needed */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001380 D_RX(
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001381 "r %d i %d No handler needed for %s, 0x%02x\n",
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001382 r, i, il_get_cmd_string(pkt->hdr.cmd),
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001383 pkt->hdr.cmd);
1384 }
1385
1386 /*
1387 * XXX: After here, we should always check rxb->page
1388 * against NULL before touching it or its virtual
1389 * memory (pkt). Because some rx_handler might have
1390 * already taken or freed the pages.
1391 */
1392
1393 if (reclaim) {
1394 /* Invoke any callbacks, transfer the buffer to caller,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001395 * and fire off the (possibly) blocking il_send_cmd()
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001396 * as we reclaim the driver command queue */
1397 if (rxb->page)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001398 il_tx_cmd_complete(il, rxb);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001399 else
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001400 IL_WARN("Claim null rxb?\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001401 }
1402
1403 /* Reuse the page if possible. For notification packets and
1404 * SKBs that fail to Rx correctly, add them back into the
1405 * rx_free list for reuse later. */
1406 spin_lock_irqsave(&rxq->lock, flags);
1407 if (rxb->page != NULL) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001408 rxb->page_dma = pci_map_page(il->pci_dev, rxb->page,
1409 0, PAGE_SIZE << il->hw_params.rx_page_order,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001410 PCI_DMA_FROMDEVICE);
1411 list_add_tail(&rxb->list, &rxq->rx_free);
1412 rxq->free_count++;
1413 } else
1414 list_add_tail(&rxb->list, &rxq->rx_used);
1415
1416 spin_unlock_irqrestore(&rxq->lock, flags);
1417
1418 i = (i + 1) & RX_QUEUE_MASK;
1419 /* If there are a lot of unused frames,
1420 * restock the Rx queue so ucode wont assert. */
1421 if (fill_rx) {
1422 count++;
1423 if (count >= 8) {
1424 rxq->read = i;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001425 il4965_rx_replenish_now(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001426 count = 0;
1427 }
1428 }
1429 }
1430
1431 /* Backtrack one entry */
1432 rxq->read = i;
1433 if (fill_rx)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001434 il4965_rx_replenish_now(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001435 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001436 il4965_rx_queue_restock(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001437}
1438
1439/* call this function to flush any scheduled tasklet */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001440static inline void il4965_synchronize_irq(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001441{
1442 /* wait to make sure we flush pending tasklet*/
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001443 synchronize_irq(il->pci_dev->irq);
1444 tasklet_kill(&il->irq_tasklet);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001445}
1446
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001447static void il4965_irq_tasklet(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001448{
1449 u32 inta, handled = 0;
1450 u32 inta_fh;
1451 unsigned long flags;
1452 u32 i;
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001453#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001454 u32 inta_mask;
1455#endif
1456
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001457 spin_lock_irqsave(&il->lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001458
1459 /* Ack/clear/reset pending uCode interrupts.
1460 * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
1461 * and will clear only when CSR_FH_INT_STATUS gets cleared. */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001462 inta = _il_rd(il, CSR_INT);
1463 _il_wr(il, CSR_INT, inta);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001464
1465 /* Ack/clear/reset pending flow-handler (DMA) interrupts.
1466 * Any new interrupts that happen after this, either while we're
1467 * in this tasklet, or later, will show up in next ISR/tasklet. */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001468 inta_fh = _il_rd(il, CSR_FH_INT_STATUS);
1469 _il_wr(il, CSR_FH_INT_STATUS, inta_fh);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001470
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001471#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001472 if (il_get_debug_level(il) & IL_DL_ISR) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001473 /* just for debug */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001474 inta_mask = _il_rd(il, CSR_INT_MASK);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001475 D_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001476 inta, inta_mask, inta_fh);
1477 }
1478#endif
1479
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001480 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001481
1482 /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
1483 * atomic, make sure that inta covers all the interrupts that
1484 * we've discovered, even if FH interrupt came in just after
1485 * reading CSR_INT. */
1486 if (inta_fh & CSR49_FH_INT_RX_MASK)
1487 inta |= CSR_INT_BIT_FH_RX;
1488 if (inta_fh & CSR49_FH_INT_TX_MASK)
1489 inta |= CSR_INT_BIT_FH_TX;
1490
1491 /* Now service all interrupt bits discovered above. */
1492 if (inta & CSR_INT_BIT_HW_ERR) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001493 IL_ERR("Hardware error detected. Restarting.\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001494
1495 /* Tell the device to stop sending interrupts */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001496 il_disable_interrupts(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001497
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001498 il->isr_stats.hw++;
1499 il_irq_handle_error(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001500
1501 handled |= CSR_INT_BIT_HW_ERR;
1502
1503 return;
1504 }
1505
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001506#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001507 if (il_get_debug_level(il) & (IL_DL_ISR)) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001508 /* NIC fires this, but we don't use it, redundant with WAKEUP */
1509 if (inta & CSR_INT_BIT_SCD) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001510 D_ISR("Scheduler finished to transmit "
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001511 "the frame/frames.\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001512 il->isr_stats.sch++;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001513 }
1514
1515 /* Alive notification via Rx interrupt will do the real work */
1516 if (inta & CSR_INT_BIT_ALIVE) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001517 D_ISR("Alive interrupt\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001518 il->isr_stats.alive++;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001519 }
1520 }
1521#endif
1522 /* Safely ignore these bits for debug checks below */
1523 inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
1524
1525 /* HW RF KILL switch toggled */
1526 if (inta & CSR_INT_BIT_RF_KILL) {
1527 int hw_rf_kill = 0;
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001528 if (!(_il_rd(il, CSR_GP_CNTRL) &
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001529 CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
1530 hw_rf_kill = 1;
1531
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001532 IL_WARN("RF_KILL bit toggled to %s.\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001533 hw_rf_kill ? "disable radio" : "enable radio");
1534
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001535 il->isr_stats.rfkill++;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001536
1537 /* driver only loads ucode once setting the interface up.
1538 * the driver allows loading the ucode even if the radio
1539 * is killed. Hence update the killswitch state here. The
1540 * rfkill handler will care about restarting if needed.
1541 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001542 if (!test_bit(STATUS_ALIVE, &il->status)) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001543 if (hw_rf_kill)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001544 set_bit(STATUS_RF_KILL_HW, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001545 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001546 clear_bit(STATUS_RF_KILL_HW, &il->status);
1547 wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001548 }
1549
1550 handled |= CSR_INT_BIT_RF_KILL;
1551 }
1552
1553 /* Chip got too hot and stopped itself */
1554 if (inta & CSR_INT_BIT_CT_KILL) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001555 IL_ERR("Microcode CT kill error detected.\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001556 il->isr_stats.ctkill++;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001557 handled |= CSR_INT_BIT_CT_KILL;
1558 }
1559
1560 /* Error detected by uCode */
1561 if (inta & CSR_INT_BIT_SW_ERR) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001562 IL_ERR("Microcode SW error detected. "
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001563 " Restarting 0x%X.\n", inta);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001564 il->isr_stats.sw++;
1565 il_irq_handle_error(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001566 handled |= CSR_INT_BIT_SW_ERR;
1567 }
1568
1569 /*
1570 * uCode wakes up after power-down sleep.
1571 * Tell device about any new tx or host commands enqueued,
1572 * and about any Rx buffers made available while asleep.
1573 */
1574 if (inta & CSR_INT_BIT_WAKEUP) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001575 D_ISR("Wakeup interrupt\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001576 il_rx_queue_update_write_ptr(il, &il->rxq);
1577 for (i = 0; i < il->hw_params.max_txq_num; i++)
1578 il_txq_update_write_ptr(il, &il->txq[i]);
1579 il->isr_stats.wakeup++;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001580 handled |= CSR_INT_BIT_WAKEUP;
1581 }
1582
1583 /* All uCode command responses, including Tx command responses,
1584 * Rx "responses" (frame-received notification), and other
1585 * notifications from uCode come through here*/
1586 if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001587 il4965_rx_handle(il);
1588 il->isr_stats.rx++;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001589 handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
1590 }
1591
1592 /* This "Tx" DMA channel is used only for loading uCode */
1593 if (inta & CSR_INT_BIT_FH_TX) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001594 D_ISR("uCode load interrupt\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001595 il->isr_stats.tx++;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001596 handled |= CSR_INT_BIT_FH_TX;
1597 /* Wake up uCode load routine, now that load is complete */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001598 il->ucode_write_complete = 1;
1599 wake_up(&il->wait_command_queue);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001600 }
1601
1602 if (inta & ~handled) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001603 IL_ERR("Unhandled INTA bits 0x%08x\n", inta & ~handled);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001604 il->isr_stats.unhandled++;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001605 }
1606
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001607 if (inta & ~(il->inta_mask)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001608 IL_WARN("Disabled INTA bits 0x%08x were pending\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001609 inta & ~il->inta_mask);
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001610 IL_WARN(" with FH_INT = 0x%08x\n", inta_fh);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001611 }
1612
1613 /* Re-enable all interrupts */
Stanislaw Gruszka93fd74e2011-04-28 11:51:30 +02001614 /* only Re-enable if disabled by irq */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001615 if (test_bit(STATUS_INT_ENABLED, &il->status))
1616 il_enable_interrupts(il);
Stanislaw Gruszkaa078a1f2011-04-28 11:51:25 +02001617 /* Re-enable RF_KILL if it occurred */
1618 else if (handled & CSR_INT_BIT_RF_KILL)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001619 il_enable_rfkill_int(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001620
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001621#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001622 if (il_get_debug_level(il) & (IL_DL_ISR)) {
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001623 inta = _il_rd(il, CSR_INT);
1624 inta_mask = _il_rd(il, CSR_INT_MASK);
1625 inta_fh = _il_rd(il, CSR_FH_INT_STATUS);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001626 D_ISR(
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001627 "End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
1628 "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
1629 }
1630#endif
1631}
1632
1633/*****************************************************************************
1634 *
1635 * sysfs attributes
1636 *
1637 *****************************************************************************/
1638
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001639#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001640
1641/*
1642 * The following adds a new attribute to the sysfs representation
1643 * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
1644 * used for controlling the debug level.
1645 *
1646 * See the level definitions in iwl for details.
1647 *
1648 * The debug_level being managed using sysfs below is a per device debug
1649 * level that is used instead of the global debug level if it (the per
1650 * device debug level) is set.
1651 */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001652static ssize_t il4965_show_debug_level(struct device *d,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001653 struct device_attribute *attr, char *buf)
1654{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001655 struct il_priv *il = dev_get_drvdata(d);
1656 return sprintf(buf, "0x%08X\n", il_get_debug_level(il));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001657}
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001658static ssize_t il4965_store_debug_level(struct device *d,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001659 struct device_attribute *attr,
1660 const char *buf, size_t count)
1661{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001662 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001663 unsigned long val;
1664 int ret;
1665
1666 ret = strict_strtoul(buf, 0, &val);
1667 if (ret)
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001668 IL_ERR("%s is not in hex or decimal form.\n", buf);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001669 else {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001670 il->debug_level = val;
1671 if (il_alloc_traffic_mem(il))
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001672 IL_ERR(
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001673 "Not enough memory to generate traffic log\n");
1674 }
1675 return strnlen(buf, count);
1676}
1677
1678static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001679 il4965_show_debug_level, il4965_store_debug_level);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001680
1681
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001682#endif /* CONFIG_IWLEGACY_DEBUG */
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001683
1684
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001685static ssize_t il4965_show_temperature(struct device *d,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001686 struct device_attribute *attr, char *buf)
1687{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001688 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001689
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001690 if (!il_is_alive(il))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001691 return -EAGAIN;
1692
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001693 return sprintf(buf, "%d\n", il->temperature);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001694}
1695
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001696static DEVICE_ATTR(temperature, S_IRUGO, il4965_show_temperature, NULL);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001697
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001698static ssize_t il4965_show_tx_power(struct device *d,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001699 struct device_attribute *attr, char *buf)
1700{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001701 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001702
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001703 if (!il_is_ready_rf(il))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001704 return sprintf(buf, "off\n");
1705 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001706 return sprintf(buf, "%d\n", il->tx_power_user_lmt);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001707}
1708
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001709static ssize_t il4965_store_tx_power(struct device *d,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001710 struct device_attribute *attr,
1711 const char *buf, size_t count)
1712{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001713 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001714 unsigned long val;
1715 int ret;
1716
1717 ret = strict_strtoul(buf, 10, &val);
1718 if (ret)
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001719 IL_INFO("%s is not in decimal form.\n", buf);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001720 else {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001721 ret = il_set_tx_power(il, val, false);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001722 if (ret)
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001723 IL_ERR("failed setting tx power (0x%d).\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001724 ret);
1725 else
1726 ret = count;
1727 }
1728 return ret;
1729}
1730
1731static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001732 il4965_show_tx_power, il4965_store_tx_power);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001733
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001734static struct attribute *il_sysfs_entries[] = {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001735 &dev_attr_temperature.attr,
1736 &dev_attr_tx_power.attr,
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001737#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001738 &dev_attr_debug_level.attr,
1739#endif
1740 NULL
1741};
1742
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001743static struct attribute_group il_attribute_group = {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001744 .name = NULL, /* put in device directory */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001745 .attrs = il_sysfs_entries,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001746};
1747
1748/******************************************************************************
1749 *
1750 * uCode download functions
1751 *
1752 ******************************************************************************/
1753
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001754static void il4965_dealloc_ucode_pci(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001755{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001756 il_free_fw_desc(il->pci_dev, &il->ucode_code);
1757 il_free_fw_desc(il->pci_dev, &il->ucode_data);
1758 il_free_fw_desc(il->pci_dev, &il->ucode_data_backup);
1759 il_free_fw_desc(il->pci_dev, &il->ucode_init);
1760 il_free_fw_desc(il->pci_dev, &il->ucode_init_data);
1761 il_free_fw_desc(il->pci_dev, &il->ucode_boot);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001762}
1763
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001764static void il4965_nic_start(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001765{
1766 /* Remove all resets to allow NIC to operate */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001767 _il_wr(il, CSR_RESET, 0);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001768}
1769
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001770static void il4965_ucode_callback(const struct firmware *ucode_raw,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001771 void *context);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001772static int il4965_mac_setup_register(struct il_priv *il,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001773 u32 max_probe_length);
1774
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001775static int __must_check il4965_request_firmware(struct il_priv *il, bool first)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001776{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001777 const char *name_pre = il->cfg->fw_name_pre;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001778 char tag[8];
1779
1780 if (first) {
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01001781 il->fw_idx = il->cfg->ucode_api_max;
1782 sprintf(tag, "%d", il->fw_idx);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001783 } else {
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01001784 il->fw_idx--;
1785 sprintf(tag, "%d", il->fw_idx);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001786 }
1787
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01001788 if (il->fw_idx < il->cfg->ucode_api_min) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001789 IL_ERR("no suitable firmware found!\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001790 return -ENOENT;
1791 }
1792
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001793 sprintf(il->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001794
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001795 D_INFO("attempting to load firmware '%s'\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001796 il->firmware_name);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001797
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001798 return request_firmware_nowait(THIS_MODULE, 1, il->firmware_name,
1799 &il->pci_dev->dev, GFP_KERNEL, il,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001800 il4965_ucode_callback);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001801}
1802
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001803struct il4965_firmware_pieces {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001804 const void *inst, *data, *init, *init_data, *boot;
1805 size_t inst_size, data_size, init_size, init_data_size, boot_size;
1806};
1807
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001808static int il4965_load_firmware(struct il_priv *il,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001809 const struct firmware *ucode_raw,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001810 struct il4965_firmware_pieces *pieces)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001811{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001812 struct il_ucode_header *ucode = (void *)ucode_raw->data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001813 u32 api_ver, hdr_size;
1814 const u8 *src;
1815
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001816 il->ucode_ver = le32_to_cpu(ucode->ver);
1817 api_ver = IL_UCODE_API(il->ucode_ver);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001818
1819 switch (api_ver) {
1820 default:
1821 case 0:
1822 case 1:
1823 case 2:
1824 hdr_size = 24;
1825 if (ucode_raw->size < hdr_size) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001826 IL_ERR("File size too small!\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001827 return -EINVAL;
1828 }
1829 pieces->inst_size = le32_to_cpu(ucode->v1.inst_size);
1830 pieces->data_size = le32_to_cpu(ucode->v1.data_size);
1831 pieces->init_size = le32_to_cpu(ucode->v1.init_size);
1832 pieces->init_data_size =
1833 le32_to_cpu(ucode->v1.init_data_size);
1834 pieces->boot_size = le32_to_cpu(ucode->v1.boot_size);
1835 src = ucode->v1.data;
1836 break;
1837 }
1838
1839 /* Verify size of file vs. image size info in file's header */
1840 if (ucode_raw->size != hdr_size + pieces->inst_size +
1841 pieces->data_size + pieces->init_size +
1842 pieces->init_data_size + pieces->boot_size) {
1843
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001844 IL_ERR(
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001845 "uCode file size %d does not match expected size\n",
1846 (int)ucode_raw->size);
1847 return -EINVAL;
1848 }
1849
1850 pieces->inst = src;
1851 src += pieces->inst_size;
1852 pieces->data = src;
1853 src += pieces->data_size;
1854 pieces->init = src;
1855 src += pieces->init_size;
1856 pieces->init_data = src;
1857 src += pieces->init_data_size;
1858 pieces->boot = src;
1859 src += pieces->boot_size;
1860
1861 return 0;
1862}
1863
1864/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001865 * il4965_ucode_callback - callback when firmware was loaded
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001866 *
1867 * If loaded successfully, copies the firmware into buffers
1868 * for the card to fetch (via DMA).
1869 */
1870static void
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001871il4965_ucode_callback(const struct firmware *ucode_raw, void *context)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001872{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001873 struct il_priv *il = context;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001874 struct il_ucode_header *ucode;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001875 int err;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001876 struct il4965_firmware_pieces pieces;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001877 const unsigned int api_max = il->cfg->ucode_api_max;
1878 const unsigned int api_min = il->cfg->ucode_api_min;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001879 u32 api_ver;
1880
1881 u32 max_probe_length = 200;
1882 u32 standard_phy_calibration_size =
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001883 IL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001884
1885 memset(&pieces, 0, sizeof(pieces));
1886
1887 if (!ucode_raw) {
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01001888 if (il->fw_idx <= il->cfg->ucode_api_max)
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001889 IL_ERR(
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001890 "request for firmware file '%s' failed.\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001891 il->firmware_name);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001892 goto try_again;
1893 }
1894
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001895 D_INFO("Loaded firmware file '%s' (%zd bytes).\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001896 il->firmware_name, ucode_raw->size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001897
1898 /* Make sure that we got at least the API version number */
1899 if (ucode_raw->size < 4) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001900 IL_ERR("File size way too small!\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001901 goto try_again;
1902 }
1903
1904 /* Data from ucode file: header followed by uCode images */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001905 ucode = (struct il_ucode_header *)ucode_raw->data;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001906
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001907 err = il4965_load_firmware(il, ucode_raw, &pieces);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001908
1909 if (err)
1910 goto try_again;
1911
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001912 api_ver = IL_UCODE_API(il->ucode_ver);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001913
1914 /*
1915 * api_ver should match the api version forming part of the
1916 * firmware filename ... but we don't check for that and only rely
1917 * on the API version read from firmware header from here on forward
1918 */
1919 if (api_ver < api_min || api_ver > api_max) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001920 IL_ERR(
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001921 "Driver unable to support your firmware API. "
1922 "Driver supports v%u, firmware is v%u.\n",
1923 api_max, api_ver);
1924 goto try_again;
1925 }
1926
1927 if (api_ver != api_max)
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001928 IL_ERR(
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001929 "Firmware has old API version. Expected v%u, "
1930 "got v%u. New firmware can be obtained "
1931 "from http://www.intellinuxwireless.org.\n",
1932 api_max, api_ver);
1933
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001934 IL_INFO("loaded firmware version %u.%u.%u.%u\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001935 IL_UCODE_MAJOR(il->ucode_ver),
1936 IL_UCODE_MINOR(il->ucode_ver),
1937 IL_UCODE_API(il->ucode_ver),
1938 IL_UCODE_SERIAL(il->ucode_ver));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001939
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001940 snprintf(il->hw->wiphy->fw_version,
1941 sizeof(il->hw->wiphy->fw_version),
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001942 "%u.%u.%u.%u",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001943 IL_UCODE_MAJOR(il->ucode_ver),
1944 IL_UCODE_MINOR(il->ucode_ver),
1945 IL_UCODE_API(il->ucode_ver),
1946 IL_UCODE_SERIAL(il->ucode_ver));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001947
1948 /*
1949 * For any of the failures below (before allocating pci memory)
1950 * we will try to load a version with a smaller API -- maybe the
1951 * user just got a corrupted version of the latest API.
1952 */
1953
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001954 D_INFO("f/w package hdr ucode version raw = 0x%x\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001955 il->ucode_ver);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001956 D_INFO("f/w package hdr runtime inst size = %Zd\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001957 pieces.inst_size);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001958 D_INFO("f/w package hdr runtime data size = %Zd\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001959 pieces.data_size);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001960 D_INFO("f/w package hdr init inst size = %Zd\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001961 pieces.init_size);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001962 D_INFO("f/w package hdr init data size = %Zd\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001963 pieces.init_data_size);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001964 D_INFO("f/w package hdr boot inst size = %Zd\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001965 pieces.boot_size);
1966
1967 /* Verify that uCode images will fit in card's SRAM */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001968 if (pieces.inst_size > il->hw_params.max_inst_size) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001969 IL_ERR("uCode instr len %Zd too large to fit in\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001970 pieces.inst_size);
1971 goto try_again;
1972 }
1973
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001974 if (pieces.data_size > il->hw_params.max_data_size) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001975 IL_ERR("uCode data len %Zd too large to fit in\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001976 pieces.data_size);
1977 goto try_again;
1978 }
1979
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001980 if (pieces.init_size > il->hw_params.max_inst_size) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001981 IL_ERR("uCode init instr len %Zd too large to fit in\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001982 pieces.init_size);
1983 goto try_again;
1984 }
1985
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001986 if (pieces.init_data_size > il->hw_params.max_data_size) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001987 IL_ERR("uCode init data len %Zd too large to fit in\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001988 pieces.init_data_size);
1989 goto try_again;
1990 }
1991
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001992 if (pieces.boot_size > il->hw_params.max_bsm_size) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001993 IL_ERR("uCode boot instr len %Zd too large to fit in\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001994 pieces.boot_size);
1995 goto try_again;
1996 }
1997
1998 /* Allocate ucode buffers for card's bus-master loading ... */
1999
2000 /* Runtime instructions and 2 copies of data:
2001 * 1) unmodified from disk
2002 * 2) backup cache for save/restore during power-downs */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002003 il->ucode_code.len = pieces.inst_size;
2004 il_alloc_fw_desc(il->pci_dev, &il->ucode_code);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002005
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002006 il->ucode_data.len = pieces.data_size;
2007 il_alloc_fw_desc(il->pci_dev, &il->ucode_data);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002008
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002009 il->ucode_data_backup.len = pieces.data_size;
2010 il_alloc_fw_desc(il->pci_dev, &il->ucode_data_backup);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002011
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002012 if (!il->ucode_code.v_addr || !il->ucode_data.v_addr ||
2013 !il->ucode_data_backup.v_addr)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002014 goto err_pci_alloc;
2015
2016 /* Initialization instructions and data */
2017 if (pieces.init_size && pieces.init_data_size) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002018 il->ucode_init.len = pieces.init_size;
2019 il_alloc_fw_desc(il->pci_dev, &il->ucode_init);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002020
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002021 il->ucode_init_data.len = pieces.init_data_size;
2022 il_alloc_fw_desc(il->pci_dev, &il->ucode_init_data);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002023
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002024 if (!il->ucode_init.v_addr || !il->ucode_init_data.v_addr)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002025 goto err_pci_alloc;
2026 }
2027
2028 /* Bootstrap (instructions only, no data) */
2029 if (pieces.boot_size) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002030 il->ucode_boot.len = pieces.boot_size;
2031 il_alloc_fw_desc(il->pci_dev, &il->ucode_boot);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002032
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002033 if (!il->ucode_boot.v_addr)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002034 goto err_pci_alloc;
2035 }
2036
2037 /* Now that we can no longer fail, copy information */
2038
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002039 il->sta_key_max_num = STA_KEY_MAX_NUM;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002040
2041 /* Copy images into buffers for card's bus-master reads ... */
2042
2043 /* Runtime instructions (first block of data in file) */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002044 D_INFO("Copying (but not loading) uCode instr len %Zd\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002045 pieces.inst_size);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002046 memcpy(il->ucode_code.v_addr, pieces.inst, pieces.inst_size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002047
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002048 D_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002049 il->ucode_code.v_addr, (u32)il->ucode_code.p_addr);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002050
2051 /*
2052 * Runtime data
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002053 * NOTE: Copy into backup buffer will be done in il_up()
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002054 */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002055 D_INFO("Copying (but not loading) uCode data len %Zd\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002056 pieces.data_size);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002057 memcpy(il->ucode_data.v_addr, pieces.data, pieces.data_size);
2058 memcpy(il->ucode_data_backup.v_addr, pieces.data, pieces.data_size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002059
2060 /* Initialization instructions */
2061 if (pieces.init_size) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002062 D_INFO(
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002063 "Copying (but not loading) init instr len %Zd\n",
2064 pieces.init_size);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002065 memcpy(il->ucode_init.v_addr, pieces.init, pieces.init_size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002066 }
2067
2068 /* Initialization data */
2069 if (pieces.init_data_size) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002070 D_INFO(
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002071 "Copying (but not loading) init data len %Zd\n",
2072 pieces.init_data_size);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002073 memcpy(il->ucode_init_data.v_addr, pieces.init_data,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002074 pieces.init_data_size);
2075 }
2076
2077 /* Bootstrap instructions */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002078 D_INFO("Copying (but not loading) boot instr len %Zd\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002079 pieces.boot_size);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002080 memcpy(il->ucode_boot.v_addr, pieces.boot, pieces.boot_size);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002081
2082 /*
2083 * figure out the offset of chain noise reset and gain commands
2084 * base on the size of standard phy calibration commands table size
2085 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002086 il->_4965.phy_calib_chain_noise_reset_cmd =
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002087 standard_phy_calibration_size;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002088 il->_4965.phy_calib_chain_noise_gain_cmd =
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002089 standard_phy_calibration_size + 1;
2090
2091 /**************************************************
2092 * This is still part of probe() in a sense...
2093 *
2094 * 9. Setup and register with mac80211 and debugfs
2095 **************************************************/
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002096 err = il4965_mac_setup_register(il, max_probe_length);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002097 if (err)
2098 goto out_unbind;
2099
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002100 err = il_dbgfs_register(il, DRV_NAME);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002101 if (err)
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002102 IL_ERR(
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002103 "failed to create debugfs files. Ignoring error: %d\n", err);
2104
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002105 err = sysfs_create_group(&il->pci_dev->dev.kobj,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002106 &il_attribute_group);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002107 if (err) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002108 IL_ERR("failed to create sysfs device attributes\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002109 goto out_unbind;
2110 }
2111
2112 /* We have our copies now, allow OS release its copies */
2113 release_firmware(ucode_raw);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002114 complete(&il->_4965.firmware_loading_complete);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002115 return;
2116
2117 try_again:
2118 /* try next, if any */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002119 if (il4965_request_firmware(il, false))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002120 goto out_unbind;
2121 release_firmware(ucode_raw);
2122 return;
2123
2124 err_pci_alloc:
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002125 IL_ERR("failed to allocate pci memory\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002126 il4965_dealloc_ucode_pci(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002127 out_unbind:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002128 complete(&il->_4965.firmware_loading_complete);
2129 device_release_driver(&il->pci_dev->dev);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002130 release_firmware(ucode_raw);
2131}
2132
2133static const char * const desc_lookup_text[] = {
2134 "OK",
2135 "FAIL",
2136 "BAD_PARAM",
2137 "BAD_CHECKSUM",
2138 "NMI_INTERRUPT_WDG",
2139 "SYSASSERT",
2140 "FATAL_ERROR",
2141 "BAD_COMMAND",
2142 "HW_ERROR_TUNE_LOCK",
2143 "HW_ERROR_TEMPERATURE",
2144 "ILLEGAL_CHAN_FREQ",
Stanislaw Gruszka3b98c7f2011-08-26 16:29:35 +02002145 "VCC_NOT_STBL",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002146 "FH_ERROR",
2147 "NMI_INTERRUPT_HOST",
2148 "NMI_INTERRUPT_ACTION_PT",
2149 "NMI_INTERRUPT_UNKNOWN",
2150 "UCODE_VERSION_MISMATCH",
2151 "HW_ERROR_ABS_LOCK",
2152 "HW_ERROR_CAL_LOCK_FAIL",
2153 "NMI_INTERRUPT_INST_ACTION_PT",
2154 "NMI_INTERRUPT_DATA_ACTION_PT",
2155 "NMI_TRM_HW_ER",
2156 "NMI_INTERRUPT_TRM",
Joe Perches861d9c32011-07-08 23:20:24 -07002157 "NMI_INTERRUPT_BREAK_POINT",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002158 "DEBUG_0",
2159 "DEBUG_1",
2160 "DEBUG_2",
2161 "DEBUG_3",
2162};
2163
2164static struct { char *name; u8 num; } advanced_lookup[] = {
2165 { "NMI_INTERRUPT_WDG", 0x34 },
2166 { "SYSASSERT", 0x35 },
2167 { "UCODE_VERSION_MISMATCH", 0x37 },
2168 { "BAD_COMMAND", 0x38 },
2169 { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C },
2170 { "FATAL_ERROR", 0x3D },
2171 { "NMI_TRM_HW_ERR", 0x46 },
2172 { "NMI_INTERRUPT_TRM", 0x4C },
2173 { "NMI_INTERRUPT_BREAK_POINT", 0x54 },
2174 { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C },
2175 { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 },
2176 { "NMI_INTERRUPT_HOST", 0x66 },
2177 { "NMI_INTERRUPT_ACTION_PT", 0x7C },
2178 { "NMI_INTERRUPT_UNKNOWN", 0x84 },
2179 { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 },
2180 { "ADVANCED_SYSASSERT", 0 },
2181};
2182
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002183static const char *il4965_desc_lookup(u32 num)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002184{
2185 int i;
2186 int max = ARRAY_SIZE(desc_lookup_text);
2187
2188 if (num < max)
2189 return desc_lookup_text[num];
2190
2191 max = ARRAY_SIZE(advanced_lookup) - 1;
2192 for (i = 0; i < max; i++) {
2193 if (advanced_lookup[i].num == num)
2194 break;
2195 }
2196 return advanced_lookup[i].name;
2197}
2198
2199#define ERROR_START_OFFSET (1 * sizeof(u32))
2200#define ERROR_ELEM_SIZE (7 * sizeof(u32))
2201
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002202void il4965_dump_nic_error_log(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002203{
2204 u32 data2, line;
2205 u32 desc, time, count, base, data1;
2206 u32 blink1, blink2, ilink1, ilink2;
2207 u32 pc, hcmd;
2208
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002209 if (il->ucode_type == UCODE_INIT) {
2210 base = le32_to_cpu(il->card_alive_init.error_event_table_ptr);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002211 } else {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002212 base = le32_to_cpu(il->card_alive.error_event_table_ptr);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002213 }
2214
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002215 if (!il->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002216 IL_ERR(
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002217 "Not valid error log pointer 0x%08X for %s uCode\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002218 base, (il->ucode_type == UCODE_INIT) ? "Init" : "RT");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002219 return;
2220 }
2221
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002222 count = il_read_targ_mem(il, base);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002223
2224 if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002225 IL_ERR("Start IWL Error Log Dump:\n");
2226 IL_ERR("Status: 0x%08lX, count: %d\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002227 il->status, count);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002228 }
2229
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002230 desc = il_read_targ_mem(il, base + 1 * sizeof(u32));
2231 il->isr_stats.err_code = desc;
2232 pc = il_read_targ_mem(il, base + 2 * sizeof(u32));
2233 blink1 = il_read_targ_mem(il, base + 3 * sizeof(u32));
2234 blink2 = il_read_targ_mem(il, base + 4 * sizeof(u32));
2235 ilink1 = il_read_targ_mem(il, base + 5 * sizeof(u32));
2236 ilink2 = il_read_targ_mem(il, base + 6 * sizeof(u32));
2237 data1 = il_read_targ_mem(il, base + 7 * sizeof(u32));
2238 data2 = il_read_targ_mem(il, base + 8 * sizeof(u32));
2239 line = il_read_targ_mem(il, base + 9 * sizeof(u32));
2240 time = il_read_targ_mem(il, base + 11 * sizeof(u32));
2241 hcmd = il_read_targ_mem(il, base + 22 * sizeof(u32));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002242
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002243 IL_ERR("Desc Time "
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002244 "data1 data2 line\n");
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002245 IL_ERR("%-28s (0x%04X) %010u 0x%08X 0x%08X %u\n",
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002246 il4965_desc_lookup(desc), desc, time, data1, data2, line);
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002247 IL_ERR("pc blink1 blink2 ilink1 ilink2 hcmd\n");
2248 IL_ERR("0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002249 pc, blink1, blink2, ilink1, ilink2, hcmd);
2250}
2251
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002252static void il4965_rf_kill_ct_config(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002253{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002254 struct il_ct_kill_config cmd;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002255 unsigned long flags;
2256 int ret = 0;
2257
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002258 spin_lock_irqsave(&il->lock, flags);
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002259 _il_wr(il, CSR_UCODE_DRV_GP1_CLR,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002260 CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002261 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002262
2263 cmd.critical_temperature_R =
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002264 cpu_to_le32(il->hw_params.ct_kill_threshold);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002265
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002266 ret = il_send_cmd_pdu(il, REPLY_CT_KILL_CONFIG_CMD,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002267 sizeof(cmd), &cmd);
2268 if (ret)
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002269 IL_ERR("REPLY_CT_KILL_CONFIG_CMD failed\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002270 else
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002271 D_INFO("REPLY_CT_KILL_CONFIG_CMD "
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002272 "succeeded, "
2273 "critical temperature is %d\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002274 il->hw_params.ct_kill_threshold);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002275}
2276
2277static const s8 default_queue_to_tx_fifo[] = {
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002278 IL_TX_FIFO_VO,
2279 IL_TX_FIFO_VI,
2280 IL_TX_FIFO_BE,
2281 IL_TX_FIFO_BK,
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01002282 IL49_CMD_FIFO_NUM,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002283 IL_TX_FIFO_UNUSED,
2284 IL_TX_FIFO_UNUSED,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002285};
2286
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002287static int il4965_alive_notify(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002288{
2289 u32 a;
2290 unsigned long flags;
2291 int i, chan;
2292 u32 reg_val;
2293
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002294 spin_lock_irqsave(&il->lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002295
2296 /* Clear 4965's internal Tx Scheduler data base */
Stanislaw Gruszkadb54eb52011-08-24 21:06:33 +02002297 il->scd_base_addr = il_rd_prph(il,
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01002298 IL49_SCD_SRAM_BASE_ADDR);
2299 a = il->scd_base_addr + IL49_SCD_CONTEXT_DATA_OFFSET;
2300 for (; a < il->scd_base_addr + IL49_SCD_TX_STTS_BITMAP_OFFSET; a += 4)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002301 il_write_targ_mem(il, a, 0);
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01002302 for (; a < il->scd_base_addr + IL49_SCD_TRANSLATE_TBL_OFFSET; a += 4)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002303 il_write_targ_mem(il, a, 0);
2304 for (; a < il->scd_base_addr +
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01002305 IL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(il->hw_params.max_txq_num); a += 4)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002306 il_write_targ_mem(il, a, 0);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002307
2308 /* Tel 4965 where to find Tx byte count tables */
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01002309 il_wr_prph(il, IL49_SCD_DRAM_BASE_ADDR,
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002310 il->scd_bc_tbls.dma >> 10);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002311
2312 /* Enable DMA channel */
2313 for (chan = 0; chan < FH49_TCSR_CHNL_NUM ; chan++)
Stanislaw Gruszka0c1a94e2011-08-24 17:37:16 +02002314 il_wr(il,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002315 FH_TCSR_CHNL_TX_CONFIG_REG(chan),
2316 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
2317 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
2318
2319 /* Update FH chicken bits */
Stanislaw Gruszka0c1a94e2011-08-24 17:37:16 +02002320 reg_val = il_rd(il, FH_TX_CHICKEN_BITS_REG);
2321 il_wr(il, FH_TX_CHICKEN_BITS_REG,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002322 reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
2323
2324 /* Disable chain mode for all queues */
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01002325 il_wr_prph(il, IL49_SCD_QUEUECHAIN_SEL, 0);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002326
2327 /* Initialize each Tx queue (including the command queue) */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002328 for (i = 0; i < il->hw_params.max_txq_num; i++) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002329
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01002330 /* TFD circular buffer read/write idxes */
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01002331 il_wr_prph(il, IL49_SCD_QUEUE_RDPTR(i), 0);
Stanislaw Gruszka0c1a94e2011-08-24 17:37:16 +02002332 il_wr(il, HBUS_TARG_WRPTR, 0 | (i << 8));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002333
2334 /* Max Tx Window size for Scheduler-ACK mode */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002335 il_write_targ_mem(il, il->scd_base_addr +
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01002336 IL49_SCD_CONTEXT_QUEUE_OFFSET(i),
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002337 (SCD_WIN_SIZE <<
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01002338 IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
2339 IL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002340
2341 /* Frame limit */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002342 il_write_targ_mem(il, il->scd_base_addr +
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01002343 IL49_SCD_CONTEXT_QUEUE_OFFSET(i) +
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002344 sizeof(u32),
2345 (SCD_FRAME_LIMIT <<
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01002346 IL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
2347 IL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002348
2349 }
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01002350 il_wr_prph(il, IL49_SCD_INTERRUPT_MASK,
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002351 (1 << il->hw_params.max_txq_num) - 1);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002352
2353 /* Activate all Tx DMA/FIFO channels */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002354 il4965_txq_set_sched(il, IL_MASK(0, 6));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002355
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002356 il4965_set_wr_ptrs(il, IL_DEFAULT_CMD_QUEUE_NUM, 0);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002357
2358 /* make sure all queue are not stopped */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002359 memset(&il->queue_stopped[0], 0, sizeof(il->queue_stopped));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002360 for (i = 0; i < 4; i++)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002361 atomic_set(&il->queue_stop_count[i], 0);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002362
2363 /* reset to 0 to enable all the queue first */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002364 il->txq_ctx_active_msk = 0;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002365 /* Map each Tx/cmd queue to its corresponding fifo */
2366 BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7);
2367
2368 for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
2369 int ac = default_queue_to_tx_fifo[i];
2370
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002371 il_txq_ctx_activate(il, i);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002372
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002373 if (ac == IL_TX_FIFO_UNUSED)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002374 continue;
2375
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002376 il4965_tx_queue_set_status(il, &il->txq[i], ac, 0);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002377 }
2378
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002379 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002380
2381 return 0;
2382}
2383
2384/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002385 * il4965_alive_start - called after REPLY_ALIVE notification received
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002386 * from protocol/runtime uCode (initialization uCode's
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002387 * Alive gets handled by il_init_alive_start()).
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002388 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002389static void il4965_alive_start(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002390{
2391 int ret = 0;
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01002392 struct il_rxon_context *ctx = &il->ctx;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002393
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002394 D_INFO("Runtime Alive received.\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002395
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002396 if (il->card_alive.is_valid != UCODE_VALID_OK) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002397 /* We had an error bringing up the hardware, so take it
2398 * all the way back down so we can try again */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002399 D_INFO("Alive failed.\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002400 goto restart;
2401 }
2402
2403 /* Initialize uCode has loaded Runtime uCode ... verify inst image.
2404 * This is a paranoid check, because we would not have gotten the
2405 * "runtime" alive if code weren't properly loaded. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002406 if (il4965_verify_ucode(il)) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002407 /* Runtime instruction load was bad;
2408 * take it all the way back down so we can try again */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002409 D_INFO("Bad runtime uCode load.\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002410 goto restart;
2411 }
2412
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002413 ret = il4965_alive_notify(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002414 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002415 IL_WARN(
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002416 "Could not complete ALIVE transition [ntf]: %d\n", ret);
2417 goto restart;
2418 }
2419
2420
2421 /* After the ALIVE response, we can send host commands to the uCode */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002422 set_bit(STATUS_ALIVE, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002423
2424 /* Enable watchdog to monitor the driver tx queues */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002425 il_setup_watchdog(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002426
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002427 if (il_is_rfkill(il))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002428 return;
2429
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002430 ieee80211_wake_queues(il->hw);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002431
Stanislaw Gruszka2eb05812011-08-26 16:07:43 +02002432 il->active_rate = RATES_MASK;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002433
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002434 if (il_is_associated_ctx(ctx)) {
2435 struct il_rxon_cmd *active_rxon =
2436 (struct il_rxon_cmd *)&ctx->active;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002437 /* apply any changes in staging */
2438 ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
2439 active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
2440 } else {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002441 /* Initialize our rx_config data */
Stanislaw Gruszka17d6e552011-08-29 12:52:20 +02002442 il_connection_init_rx_config(il, &il->ctx);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002443
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002444 if (il->cfg->ops->hcmd->set_rxon_chain)
2445 il->cfg->ops->hcmd->set_rxon_chain(il, ctx);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002446 }
2447
2448 /* Configure bluetooth coexistence if enabled */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002449 il_send_bt_config(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002450
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002451 il4965_reset_run_time_calib(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002452
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002453 set_bit(STATUS_READY, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002454
2455 /* Configure the adapter for unassociated operation */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002456 il_commit_rxon(il, ctx);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002457
2458 /* At this point, the NIC is initialized and operational */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002459 il4965_rf_kill_ct_config(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002460
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002461 D_INFO("ALIVE processing complete.\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002462 wake_up(&il->wait_command_queue);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002463
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002464 il_power_update_mode(il, true);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002465 D_INFO("Updated power mode\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002466
2467 return;
2468
2469 restart:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002470 queue_work(il->workqueue, &il->restart);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002471}
2472
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002473static void il4965_cancel_deferred_work(struct il_priv *il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002474
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002475static void __il4965_down(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002476{
2477 unsigned long flags;
Stanislaw Gruszkaab42b402011-04-28 11:51:24 +02002478 int exit_pending;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002479
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002480 D_INFO(DRV_NAME " is going down\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002481
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002482 il_scan_cancel_timeout(il, 200);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002483
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002484 exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002485
2486 /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
2487 * to prevent rearm timer */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002488 del_timer_sync(&il->watchdog);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002489
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002490 il_clear_ucode_stations(il, NULL);
2491 il_dealloc_bcast_stations(il);
2492 il_clear_driver_stations(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002493
2494 /* Unblock any waiting calls */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002495 wake_up_all(&il->wait_command_queue);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002496
2497 /* Wipe out the EXIT_PENDING status bit if we are not actually
2498 * exiting the module */
2499 if (!exit_pending)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002500 clear_bit(STATUS_EXIT_PENDING, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002501
2502 /* stop and reset the on-board processor */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002503 _il_wr(il, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002504
2505 /* tell the device to stop sending interrupts */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002506 spin_lock_irqsave(&il->lock, flags);
2507 il_disable_interrupts(il);
2508 spin_unlock_irqrestore(&il->lock, flags);
2509 il4965_synchronize_irq(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002510
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002511 if (il->mac80211_registered)
2512 ieee80211_stop_queues(il->hw);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002513
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002514 /* If we have not previously called il_init() then
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002515 * clear all bits but the RF Kill bit and return */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002516 if (!il_is_init(il)) {
2517 il->status = test_bit(STATUS_RF_KILL_HW, &il->status) <<
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002518 STATUS_RF_KILL_HW |
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002519 test_bit(STATUS_GEO_CONFIGURED, &il->status) <<
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002520 STATUS_GEO_CONFIGURED |
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002521 test_bit(STATUS_EXIT_PENDING, &il->status) <<
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002522 STATUS_EXIT_PENDING;
2523 goto exit;
2524 }
2525
2526 /* ...otherwise clear out all the status bits but the RF Kill
2527 * bit and continue taking the NIC down. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002528 il->status &= test_bit(STATUS_RF_KILL_HW, &il->status) <<
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002529 STATUS_RF_KILL_HW |
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002530 test_bit(STATUS_GEO_CONFIGURED, &il->status) <<
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002531 STATUS_GEO_CONFIGURED |
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002532 test_bit(STATUS_FW_ERROR, &il->status) <<
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002533 STATUS_FW_ERROR |
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002534 test_bit(STATUS_EXIT_PENDING, &il->status) <<
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002535 STATUS_EXIT_PENDING;
2536
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002537 il4965_txq_ctx_stop(il);
2538 il4965_rxq_stop(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002539
2540 /* Power-down device's busmaster DMA clocks */
Stanislaw Gruszkadb54eb52011-08-24 21:06:33 +02002541 il_wr_prph(il, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002542 udelay(5);
2543
2544 /* Make sure (redundant) we've released our request to stay awake */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002545 il_clear_bit(il, CSR_GP_CNTRL,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002546 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
2547
2548 /* Stop the device, and put it in low power state */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002549 il_apm_stop(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002550
2551 exit:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002552 memset(&il->card_alive, 0, sizeof(struct il_alive_resp));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002553
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002554 dev_kfree_skb(il->beacon_skb);
2555 il->beacon_skb = NULL;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002556
2557 /* clear out any free frames */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002558 il4965_clear_free_frames(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002559}
2560
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002561static void il4965_down(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002562{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002563 mutex_lock(&il->mutex);
2564 __il4965_down(il);
2565 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002566
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002567 il4965_cancel_deferred_work(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002568}
2569
2570#define HW_READY_TIMEOUT (50)
2571
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002572static int il4965_set_hw_ready(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002573{
2574 int ret = 0;
2575
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002576 il_set_bit(il, CSR_HW_IF_CONFIG_REG,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002577 CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
2578
2579 /* See if we got it */
Stanislaw Gruszka142b3432011-08-24 15:22:57 +02002580 ret = _il_poll_bit(il, CSR_HW_IF_CONFIG_REG,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002581 CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
2582 CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
2583 HW_READY_TIMEOUT);
2584 if (ret != -ETIMEDOUT)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002585 il->hw_ready = true;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002586 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002587 il->hw_ready = false;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002588
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002589 D_INFO("hardware %s\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002590 (il->hw_ready == 1) ? "ready" : "not ready");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002591 return ret;
2592}
2593
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002594static int il4965_prepare_card_hw(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002595{
2596 int ret = 0;
2597
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002598 D_INFO("il4965_prepare_card_hw enter\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002599
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002600 ret = il4965_set_hw_ready(il);
2601 if (il->hw_ready)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002602 return ret;
2603
2604 /* If HW is not ready, prepare the conditions to check again */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002605 il_set_bit(il, CSR_HW_IF_CONFIG_REG,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002606 CSR_HW_IF_CONFIG_REG_PREPARE);
2607
Stanislaw Gruszka142b3432011-08-24 15:22:57 +02002608 ret = _il_poll_bit(il, CSR_HW_IF_CONFIG_REG,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002609 ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
2610 CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
2611
2612 /* HW should be ready by now, check again. */
2613 if (ret != -ETIMEDOUT)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002614 il4965_set_hw_ready(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002615
2616 return ret;
2617}
2618
2619#define MAX_HW_RESTARTS 5
2620
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002621static int __il4965_up(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002622{
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002623 int i;
2624 int ret;
2625
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002626 if (test_bit(STATUS_EXIT_PENDING, &il->status)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002627 IL_WARN("Exit pending; will not bring the NIC up\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002628 return -EIO;
2629 }
2630
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002631 if (!il->ucode_data_backup.v_addr || !il->ucode_data.v_addr) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002632 IL_ERR("ucode not available for device bringup\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002633 return -EIO;
2634 }
2635
Stanislaw Gruszka17d6e552011-08-29 12:52:20 +02002636 ret = il4965_alloc_bcast_station(il, &il->ctx);
2637 if (ret) {
2638 il_dealloc_bcast_stations(il);
2639 return ret;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002640 }
2641
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002642 il4965_prepare_card_hw(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002643
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002644 if (!il->hw_ready) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002645 IL_WARN("Exit HW not ready\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002646 return -EIO;
2647 }
2648
2649 /* If platform's RF_KILL switch is NOT set to KILL */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002650 if (_il_rd(il,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002651 CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002652 clear_bit(STATUS_RF_KILL_HW, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002653 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002654 set_bit(STATUS_RF_KILL_HW, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002655
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002656 if (il_is_rfkill(il)) {
2657 wiphy_rfkill_set_hw_state(il->hw->wiphy, true);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002658
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002659 il_enable_interrupts(il);
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002660 IL_WARN("Radio disabled by HW RF Kill switch\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002661 return 0;
2662 }
2663
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002664 _il_wr(il, CSR_INT, 0xFFFFFFFF);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002665
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002666 /* must be initialised before il_hw_nic_init */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002667 il->cmd_queue = IL_DEFAULT_CMD_QUEUE_NUM;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002668
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002669 ret = il4965_hw_nic_init(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002670 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002671 IL_ERR("Unable to init nic\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002672 return ret;
2673 }
2674
2675 /* make sure rfkill handshake bits are cleared */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002676 _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
2677 _il_wr(il, CSR_UCODE_DRV_GP1_CLR,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002678 CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
2679
2680 /* clear (again), then enable host interrupts */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002681 _il_wr(il, CSR_INT, 0xFFFFFFFF);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002682 il_enable_interrupts(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002683
2684 /* really make sure rfkill handshake bits are cleared */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002685 _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
2686 _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002687
2688 /* Copy original ucode data image from disk into backup cache.
2689 * This will be used to initialize the on-board processor's
2690 * data SRAM for a clean start when the runtime program first loads. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002691 memcpy(il->ucode_data_backup.v_addr, il->ucode_data.v_addr,
2692 il->ucode_data.len);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002693
2694 for (i = 0; i < MAX_HW_RESTARTS; i++) {
2695
2696 /* load bootstrap state machine,
2697 * load bootstrap program into processor's memory,
2698 * prepare to load the "initialize" uCode */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002699 ret = il->cfg->ops->lib->load_ucode(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002700
2701 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002702 IL_ERR("Unable to set up bootstrap uCode: %d\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002703 ret);
2704 continue;
2705 }
2706
2707 /* start card; "initialize" will load runtime ucode */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002708 il4965_nic_start(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002709
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002710 D_INFO(DRV_NAME " is coming up\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002711
2712 return 0;
2713 }
2714
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002715 set_bit(STATUS_EXIT_PENDING, &il->status);
2716 __il4965_down(il);
2717 clear_bit(STATUS_EXIT_PENDING, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002718
2719 /* tried to restart and config the device for as long as our
2720 * patience could withstand */
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002721 IL_ERR("Unable to initialize device after %d attempts.\n", i);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002722 return -EIO;
2723}
2724
2725
2726/*****************************************************************************
2727 *
2728 * Workqueue callbacks
2729 *
2730 *****************************************************************************/
2731
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002732static void il4965_bg_init_alive_start(struct work_struct *data)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002733{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002734 struct il_priv *il =
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002735 container_of(data, struct il_priv, init_alive_start.work);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002736
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002737 mutex_lock(&il->mutex);
2738 if (test_bit(STATUS_EXIT_PENDING, &il->status))
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002739 goto out;
2740
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002741 il->cfg->ops->lib->init_alive_start(il);
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002742out:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002743 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002744}
2745
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002746static void il4965_bg_alive_start(struct work_struct *data)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002747{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002748 struct il_priv *il =
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002749 container_of(data, struct il_priv, alive_start.work);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002750
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002751 mutex_lock(&il->mutex);
2752 if (test_bit(STATUS_EXIT_PENDING, &il->status))
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002753 goto out;
2754
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002755 il4965_alive_start(il);
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002756out:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002757 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002758}
2759
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002760static void il4965_bg_run_time_calib_work(struct work_struct *work)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002761{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002762 struct il_priv *il = container_of(work, struct il_priv,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002763 run_time_calib_work);
2764
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002765 mutex_lock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002766
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002767 if (test_bit(STATUS_EXIT_PENDING, &il->status) ||
2768 test_bit(STATUS_SCANNING, &il->status)) {
2769 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002770 return;
2771 }
2772
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002773 if (il->start_calib) {
2774 il4965_chain_noise_calibration(il,
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02002775 (void *)&il->_4965.stats);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002776 il4965_sensitivity_calibration(il,
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02002777 (void *)&il->_4965.stats);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002778 }
2779
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002780 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002781}
2782
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002783static void il4965_bg_restart(struct work_struct *data)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002784{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002785 struct il_priv *il = container_of(data, struct il_priv, restart);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002786
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002787 if (test_bit(STATUS_EXIT_PENDING, &il->status))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002788 return;
2789
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002790 if (test_and_clear_bit(STATUS_FW_ERROR, &il->status)) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002791 mutex_lock(&il->mutex);
Stanislaw Gruszka17d6e552011-08-29 12:52:20 +02002792 il->ctx.vif = NULL;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002793 il->is_open = 0;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002794
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002795 __il4965_down(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002796
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002797 mutex_unlock(&il->mutex);
2798 il4965_cancel_deferred_work(il);
2799 ieee80211_restart_hw(il->hw);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002800 } else {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002801 il4965_down(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002802
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002803 mutex_lock(&il->mutex);
2804 if (test_bit(STATUS_EXIT_PENDING, &il->status)) {
2805 mutex_unlock(&il->mutex);
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002806 return;
2807 }
2808
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002809 __il4965_up(il);
2810 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002811 }
2812}
2813
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002814static void il4965_bg_rx_replenish(struct work_struct *data)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002815{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002816 struct il_priv *il =
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002817 container_of(data, struct il_priv, rx_replenish);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002818
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002819 if (test_bit(STATUS_EXIT_PENDING, &il->status))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002820 return;
2821
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002822 mutex_lock(&il->mutex);
2823 il4965_rx_replenish(il);
2824 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002825}
2826
2827/*****************************************************************************
2828 *
2829 * mac80211 entry point functions
2830 *
2831 *****************************************************************************/
2832
2833#define UCODE_READY_TIMEOUT (4 * HZ)
2834
2835/*
2836 * Not a mac80211 entry point function, but it fits in with all the
2837 * other mac80211 functions grouped here.
2838 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002839static int il4965_mac_setup_register(struct il_priv *il,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002840 u32 max_probe_length)
2841{
2842 int ret;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002843 struct ieee80211_hw *hw = il->hw;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002844
2845 hw->rate_control_algorithm = "iwl-4965-rs";
2846
2847 /* Tell mac80211 our characteristics */
2848 hw->flags = IEEE80211_HW_SIGNAL_DBM |
2849 IEEE80211_HW_AMPDU_AGGREGATION |
2850 IEEE80211_HW_NEED_DTIM_PERIOD |
2851 IEEE80211_HW_SPECTRUM_MGMT |
2852 IEEE80211_HW_REPORTS_TX_ACK_STATUS;
2853
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002854 if (il->cfg->sku & IL_SKU_N)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002855 hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
2856 IEEE80211_HW_SUPPORTS_STATIC_SMPS;
2857
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002858 hw->sta_data_size = sizeof(struct il_station_priv);
2859 hw->vif_data_size = sizeof(struct il_vif_priv);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002860
Stanislaw Gruszka17d6e552011-08-29 12:52:20 +02002861 hw->wiphy->interface_modes |= il->ctx.interface_modes;
2862 hw->wiphy->interface_modes |= il->ctx.exclusive_interface_modes;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002863
2864 hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
2865 WIPHY_FLAG_DISABLE_BEACON_HINTS;
2866
2867 /*
2868 * For now, disable PS by default because it affects
2869 * RX performance significantly.
2870 */
2871 hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
2872
2873 hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
2874 /* we create the 802.11 header and a zero-length SSID element */
2875 hw->wiphy->max_scan_ie_len = max_probe_length - 24 - 2;
2876
2877 /* Default value; 4 EDCA QOS priorities */
2878 hw->queues = 4;
2879
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002880 hw->max_listen_interval = IL_CONN_MAX_LISTEN_INTERVAL;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002881
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002882 if (il->bands[IEEE80211_BAND_2GHZ].n_channels)
2883 il->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
2884 &il->bands[IEEE80211_BAND_2GHZ];
2885 if (il->bands[IEEE80211_BAND_5GHZ].n_channels)
2886 il->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
2887 &il->bands[IEEE80211_BAND_5GHZ];
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002888
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002889 il_leds_init(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002890
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002891 ret = ieee80211_register_hw(il->hw);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002892 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002893 IL_ERR("Failed to register hw (error %d)\n", ret);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002894 return ret;
2895 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002896 il->mac80211_registered = 1;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002897
2898 return 0;
2899}
2900
2901
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002902int il4965_mac_start(struct ieee80211_hw *hw)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002903{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002904 struct il_priv *il = hw->priv;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002905 int ret;
2906
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002907 D_MAC80211("enter\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002908
2909 /* we should be verifying the device is ready to be opened */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002910 mutex_lock(&il->mutex);
2911 ret = __il4965_up(il);
2912 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002913
2914 if (ret)
2915 return ret;
2916
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002917 if (il_is_rfkill(il))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002918 goto out;
2919
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002920 D_INFO("Start UP work done.\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002921
2922 /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from
2923 * mac80211 will not be run successfully. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002924 ret = wait_event_timeout(il->wait_command_queue,
2925 test_bit(STATUS_READY, &il->status),
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002926 UCODE_READY_TIMEOUT);
2927 if (!ret) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002928 if (!test_bit(STATUS_READY, &il->status)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002929 IL_ERR("START_ALIVE timeout after %dms.\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002930 jiffies_to_msecs(UCODE_READY_TIMEOUT));
2931 return -ETIMEDOUT;
2932 }
2933 }
2934
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002935 il4965_led_enable(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002936
2937out:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002938 il->is_open = 1;
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002939 D_MAC80211("leave\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002940 return 0;
2941}
2942
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002943void il4965_mac_stop(struct ieee80211_hw *hw)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002944{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002945 struct il_priv *il = hw->priv;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002946
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002947 D_MAC80211("enter\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002948
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002949 if (!il->is_open)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002950 return;
2951
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002952 il->is_open = 0;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002953
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002954 il4965_down(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002955
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002956 flush_workqueue(il->workqueue);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002957
Stanislaw Gruszkaa078a1f2011-04-28 11:51:25 +02002958 /* User space software may expect getting rfkill changes
2959 * even if interface is down */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002960 _il_wr(il, CSR_INT, 0xFFFFFFFF);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002961 il_enable_rfkill_int(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002962
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002963 D_MAC80211("leave\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002964}
2965
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002966void il4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002967{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002968 struct il_priv *il = hw->priv;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002969
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002970 D_MACDUMP("enter\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002971
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002972 D_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002973 ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
2974
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002975 if (il4965_tx_skb(il, skb))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002976 dev_kfree_skb_any(skb);
2977
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002978 D_MACDUMP("leave\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002979}
2980
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002981void il4965_mac_update_tkip_key(struct ieee80211_hw *hw,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002982 struct ieee80211_vif *vif,
2983 struct ieee80211_key_conf *keyconf,
2984 struct ieee80211_sta *sta,
2985 u32 iv32, u16 *phase1key)
2986{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002987 struct il_priv *il = hw->priv;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002988 struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002989
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002990 D_MAC80211("enter\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002991
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002992 il4965_update_tkip_key(il, vif_priv->ctx, keyconf, sta,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002993 iv32, phase1key);
2994
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002995 D_MAC80211("leave\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002996}
2997
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002998int il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08002999 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
3000 struct ieee80211_key_conf *key)
3001{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003002 struct il_priv *il = hw->priv;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003003 struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
3004 struct il_rxon_context *ctx = vif_priv->ctx;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003005 int ret;
3006 u8 sta_id;
3007 bool is_default_wep_key = false;
3008
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003009 D_MAC80211("enter\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003010
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003011 if (il->cfg->mod_params->sw_crypto) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003012 D_MAC80211("leave - hwcrypto disabled\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003013 return -EOPNOTSUPP;
3014 }
3015
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003016 sta_id = il_sta_id_or_broadcast(il, vif_priv->ctx, sta);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003017 if (sta_id == IL_INVALID_STATION)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003018 return -EINVAL;
3019
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003020 mutex_lock(&il->mutex);
3021 il_scan_cancel_timeout(il, 100);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003022
3023 /*
3024 * If we are getting WEP group key and we didn't receive any key mapping
3025 * so far, we are in legacy wep mode (group key only), otherwise we are
3026 * in 1X mode.
3027 * In legacy wep mode, we use another host command to the uCode.
3028 */
3029 if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
3030 key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
3031 !sta) {
3032 if (cmd == SET_KEY)
3033 is_default_wep_key = !ctx->key_mapping_keys;
3034 else
3035 is_default_wep_key =
3036 (key->hw_key_idx == HW_KEY_DEFAULT);
3037 }
3038
3039 switch (cmd) {
3040 case SET_KEY:
3041 if (is_default_wep_key)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003042 ret = il4965_set_default_wep_key(il,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003043 vif_priv->ctx, key);
3044 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003045 ret = il4965_set_dynamic_key(il, vif_priv->ctx,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003046 key, sta_id);
3047
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003048 D_MAC80211("enable hwcrypto key\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003049 break;
3050 case DISABLE_KEY:
3051 if (is_default_wep_key)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003052 ret = il4965_remove_default_wep_key(il, ctx, key);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003053 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003054 ret = il4965_remove_dynamic_key(il, ctx,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003055 key, sta_id);
3056
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003057 D_MAC80211("disable hwcrypto key\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003058 break;
3059 default:
3060 ret = -EINVAL;
3061 }
3062
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003063 mutex_unlock(&il->mutex);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003064 D_MAC80211("leave\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003065
3066 return ret;
3067}
3068
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003069int il4965_mac_ampdu_action(struct ieee80211_hw *hw,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003070 struct ieee80211_vif *vif,
3071 enum ieee80211_ampdu_mlme_action action,
3072 struct ieee80211_sta *sta, u16 tid, u16 *ssn,
3073 u8 buf_size)
3074{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003075 struct il_priv *il = hw->priv;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003076 int ret = -EINVAL;
3077
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003078 D_HT("A-MPDU action on addr %pM tid %d\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003079 sta->addr, tid);
3080
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003081 if (!(il->cfg->sku & IL_SKU_N))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003082 return -EACCES;
3083
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003084 mutex_lock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003085
3086 switch (action) {
3087 case IEEE80211_AMPDU_RX_START:
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003088 D_HT("start Rx\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003089 ret = il4965_sta_rx_agg_start(il, sta, tid, *ssn);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003090 break;
3091 case IEEE80211_AMPDU_RX_STOP:
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003092 D_HT("stop Rx\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003093 ret = il4965_sta_rx_agg_stop(il, sta, tid);
3094 if (test_bit(STATUS_EXIT_PENDING, &il->status))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003095 ret = 0;
3096 break;
3097 case IEEE80211_AMPDU_TX_START:
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003098 D_HT("start Tx\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003099 ret = il4965_tx_agg_start(il, vif, sta, tid, ssn);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003100 break;
3101 case IEEE80211_AMPDU_TX_STOP:
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003102 D_HT("stop Tx\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003103 ret = il4965_tx_agg_stop(il, vif, sta, tid);
3104 if (test_bit(STATUS_EXIT_PENDING, &il->status))
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003105 ret = 0;
3106 break;
3107 case IEEE80211_AMPDU_TX_OPERATIONAL:
3108 ret = 0;
3109 break;
3110 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003111 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003112
3113 return ret;
3114}
3115
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003116int il4965_mac_sta_add(struct ieee80211_hw *hw,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003117 struct ieee80211_vif *vif,
3118 struct ieee80211_sta *sta)
3119{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003120 struct il_priv *il = hw->priv;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003121 struct il_station_priv *sta_priv = (void *)sta->drv_priv;
3122 struct il_vif_priv *vif_priv = (void *)vif->drv_priv;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003123 bool is_ap = vif->type == NL80211_IFTYPE_STATION;
3124 int ret;
3125 u8 sta_id;
3126
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003127 D_INFO("received request to add station %pM\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003128 sta->addr);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003129 mutex_lock(&il->mutex);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003130 D_INFO("proceeding to add station %pM\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003131 sta->addr);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003132 sta_priv->common.sta_id = IL_INVALID_STATION;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003133
3134 atomic_set(&sta_priv->pending_frames, 0);
3135
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003136 ret = il_add_station_common(il, vif_priv->ctx, sta->addr,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003137 is_ap, sta, &sta_id);
3138 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003139 IL_ERR("Unable to add station %pM (%d)\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003140 sta->addr, ret);
3141 /* Should we return success if return code is EEXIST ? */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003142 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003143 return ret;
3144 }
3145
3146 sta_priv->common.sta_id = sta_id;
3147
3148 /* Initialize rate scaling */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003149 D_INFO("Initializing rate scaling for station %pM\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003150 sta->addr);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003151 il4965_rs_rate_init(il, sta, sta_id);
3152 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003153
3154 return 0;
3155}
3156
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003157void il4965_mac_channel_switch(struct ieee80211_hw *hw,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003158 struct ieee80211_channel_switch *ch_switch)
3159{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003160 struct il_priv *il = hw->priv;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003161 const struct il_channel_info *ch_info;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003162 struct ieee80211_conf *conf = &hw->conf;
3163 struct ieee80211_channel *channel = ch_switch->channel;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003164 struct il_ht_config *ht_conf = &il->current_ht_config;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003165
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003166 struct il_rxon_context *ctx = &il->ctx;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003167 u16 ch;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003168
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003169 D_MAC80211("enter\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003170
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003171 mutex_lock(&il->mutex);
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02003172
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003173 if (il_is_rfkill(il))
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02003174 goto out;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003175
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003176 if (test_bit(STATUS_EXIT_PENDING, &il->status) ||
3177 test_bit(STATUS_SCANNING, &il->status) ||
3178 test_bit(STATUS_CHANNEL_SWITCH_PENDING, &il->status))
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02003179 goto out;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003180
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003181 if (!il_is_associated_ctx(ctx))
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02003182 goto out;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003183
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003184 if (!il->cfg->ops->lib->set_channel_switch)
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02003185 goto out;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003186
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02003187 ch = channel->hw_value;
3188 if (le16_to_cpu(ctx->active.channel) == ch)
3189 goto out;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003190
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003191 ch_info = il_get_channel_info(il, channel->band, ch);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003192 if (!il_is_channel_valid(ch_info)) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003193 D_MAC80211("invalid channel\n");
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02003194 goto out;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003195 }
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02003196
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003197 spin_lock_irq(&il->lock);
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02003198
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003199 il->current_ht_config.smps = conf->smps_mode;
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02003200
3201 /* Configure HT40 channels */
3202 ctx->ht.enabled = conf_is_ht(conf);
3203 if (ctx->ht.enabled) {
3204 if (conf_is_ht40_minus(conf)) {
3205 ctx->ht.extension_chan_offset =
3206 IEEE80211_HT_PARAM_CHA_SEC_BELOW;
3207 ctx->ht.is_40mhz = true;
3208 } else if (conf_is_ht40_plus(conf)) {
3209 ctx->ht.extension_chan_offset =
3210 IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
3211 ctx->ht.is_40mhz = true;
3212 } else {
3213 ctx->ht.extension_chan_offset =
3214 IEEE80211_HT_PARAM_CHA_SEC_NONE;
3215 ctx->ht.is_40mhz = false;
3216 }
3217 } else
3218 ctx->ht.is_40mhz = false;
3219
3220 if ((le16_to_cpu(ctx->staging.channel) != ch))
3221 ctx->staging.flags = 0;
3222
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003223 il_set_rxon_channel(il, channel, ctx);
3224 il_set_rxon_ht(il, ht_conf);
3225 il_set_flags_for_band(il, ctx, channel->band, ctx->vif);
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02003226
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003227 spin_unlock_irq(&il->lock);
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02003228
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003229 il_set_rate(il);
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02003230 /*
3231 * at this point, staging_rxon has the
3232 * configuration for channel switch
3233 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003234 set_bit(STATUS_CHANNEL_SWITCH_PENDING, &il->status);
3235 il->switch_channel = cpu_to_le16(ch);
3236 if (il->cfg->ops->lib->set_channel_switch(il, ch_switch)) {
3237 clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &il->status);
3238 il->switch_channel = 0;
Stanislaw Gruszka7f1f9742011-06-08 15:28:29 +02003239 ieee80211_chswitch_done(ctx->vif, false);
3240 }
3241
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003242out:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003243 mutex_unlock(&il->mutex);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003244 D_MAC80211("leave\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003245}
3246
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003247void il4965_configure_filter(struct ieee80211_hw *hw,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003248 unsigned int changed_flags,
3249 unsigned int *total_flags,
3250 u64 multicast)
3251{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003252 struct il_priv *il = hw->priv;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003253 __le32 filter_or = 0, filter_nand = 0;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003254
3255#define CHK(test, flag) do { \
3256 if (*total_flags & (test)) \
3257 filter_or |= (flag); \
3258 else \
3259 filter_nand |= (flag); \
3260 } while (0)
3261
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003262 D_MAC80211("Enter: changed: 0x%x, total: 0x%x\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003263 changed_flags, *total_flags);
3264
3265 CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
3266 /* Setting _just_ RXON_FILTER_CTL2HOST_MSK causes FH errors */
3267 CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK);
3268 CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
3269
3270#undef CHK
3271
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003272 mutex_lock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003273
Stanislaw Gruszka17d6e552011-08-29 12:52:20 +02003274 il->ctx.staging.filter_flags &= ~filter_nand;
3275 il->ctx.staging.filter_flags |= filter_or;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003276
Stanislaw Gruszka17d6e552011-08-29 12:52:20 +02003277 /*
3278 * Not committing directly because hardware can perform a scan,
3279 * but we'll eventually commit the filter flags change anyway.
3280 */
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003281
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003282 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003283
3284 /*
3285 * Receiving all multicast frames is always enabled by the
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003286 * default flags setup in il_connection_init_rx_config()
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003287 * since we currently do not support programming multicast
3288 * filters into the device.
3289 */
3290 *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
3291 FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
3292}
3293
3294/*****************************************************************************
3295 *
3296 * driver setup and teardown
3297 *
3298 *****************************************************************************/
3299
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003300static void il4965_bg_txpower_work(struct work_struct *work)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003301{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003302 struct il_priv *il = container_of(work, struct il_priv,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003303 txpower_work);
3304
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003305 mutex_lock(&il->mutex);
Stanislaw Gruszkaf3257572011-04-28 11:36:54 +02003306
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003307 /* If a scan happened to start before we got here
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02003308 * then just return; the stats notification will
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003309 * kick off another scheduled work to compensate for
3310 * any temperature delta we missed here. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003311 if (test_bit(STATUS_EXIT_PENDING, &il->status) ||
3312 test_bit(STATUS_SCANNING, &il->status))
Stanislaw Gruszkaf3257572011-04-28 11:36:54 +02003313 goto out;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003314
3315 /* Regardless of if we are associated, we must reconfigure the
3316 * TX power since frames can be sent on non-radar channels while
3317 * not associated */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003318 il->cfg->ops->lib->send_tx_power(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003319
3320 /* Update last_temperature to keep is_calib_needed from running
3321 * when it isn't needed... */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003322 il->last_temperature = il->temperature;
Stanislaw Gruszkaf3257572011-04-28 11:36:54 +02003323out:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003324 mutex_unlock(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003325}
3326
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003327static void il4965_setup_deferred_work(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003328{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003329 il->workqueue = create_singlethread_workqueue(DRV_NAME);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003330
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003331 init_waitqueue_head(&il->wait_command_queue);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003332
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003333 INIT_WORK(&il->restart, il4965_bg_restart);
3334 INIT_WORK(&il->rx_replenish, il4965_bg_rx_replenish);
3335 INIT_WORK(&il->run_time_calib_work, il4965_bg_run_time_calib_work);
3336 INIT_DELAYED_WORK(&il->init_alive_start, il4965_bg_init_alive_start);
3337 INIT_DELAYED_WORK(&il->alive_start, il4965_bg_alive_start);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003338
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003339 il_setup_scan_deferred_work(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003340
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003341 INIT_WORK(&il->txpower_work, il4965_bg_txpower_work);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003342
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02003343 init_timer(&il->stats_periodic);
3344 il->stats_periodic.data = (unsigned long)il;
3345 il->stats_periodic.function = il4965_bg_stats_periodic;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003346
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003347 init_timer(&il->watchdog);
3348 il->watchdog.data = (unsigned long)il;
3349 il->watchdog.function = il_bg_watchdog;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003350
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003351 tasklet_init(&il->irq_tasklet, (void (*)(unsigned long))
3352 il4965_irq_tasklet, (unsigned long)il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003353}
3354
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003355static void il4965_cancel_deferred_work(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003356{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003357 cancel_work_sync(&il->txpower_work);
3358 cancel_delayed_work_sync(&il->init_alive_start);
3359 cancel_delayed_work(&il->alive_start);
3360 cancel_work_sync(&il->run_time_calib_work);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003361
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003362 il_cancel_scan_deferred_work(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003363
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +02003364 del_timer_sync(&il->stats_periodic);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003365}
3366
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003367static void il4965_init_hw_rates(struct il_priv *il,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003368 struct ieee80211_rate *rates)
3369{
3370 int i;
3371
Stanislaw Gruszka2eb05812011-08-26 16:07:43 +02003372 for (i = 0; i < RATE_COUNT_LEGACY; i++) {
Stanislaw Gruszkad2ddf6212011-08-16 14:17:04 +02003373 rates[i].bitrate = il_rates[i].ieee * 5;
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01003374 rates[i].hw_value = i; /* Rate scaling will work on idxes */
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003375 rates[i].hw_value_short = i;
3376 rates[i].flags = 0;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003377 if ((i >= IL_FIRST_CCK_RATE) && (i <= IL_LAST_CCK_RATE)) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003378 /*
3379 * If CCK != 1M then set short preamble rate flag.
3380 */
3381 rates[i].flags |=
Stanislaw Gruszka2eb05812011-08-26 16:07:43 +02003382 (il_rates[i].plcp == RATE_1M_PLCP) ?
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003383 0 : IEEE80211_RATE_SHORT_PREAMBLE;
3384 }
3385 }
3386}
3387/*
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003388 * Acquire il->lock before calling this function !
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003389 */
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01003390void il4965_set_wr_ptrs(struct il_priv *il, int txq_id, u32 idx)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003391{
Stanislaw Gruszka0c1a94e2011-08-24 17:37:16 +02003392 il_wr(il, HBUS_TARG_WRPTR,
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01003393 (idx & 0xff) | (txq_id << 8));
3394 il_wr_prph(il, IL49_SCD_QUEUE_RDPTR(txq_id), idx);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003395}
3396
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003397void il4965_tx_queue_set_status(struct il_priv *il,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003398 struct il_tx_queue *txq,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003399 int tx_fifo_id, int scd_retry)
3400{
3401 int txq_id = txq->q.id;
3402
3403 /* Find out whether to activate Tx queue */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003404 int active = test_bit(txq_id, &il->txq_ctx_active_msk) ? 1 : 0;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003405
3406 /* Set up and activate */
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003407 il_wr_prph(il, IL49_SCD_QUEUE_STATUS_BITS(txq_id),
3408 (active << IL49_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
3409 (tx_fifo_id << IL49_SCD_QUEUE_STTS_REG_POS_TXF) |
3410 (scd_retry << IL49_SCD_QUEUE_STTS_REG_POS_WSL) |
3411 (scd_retry << IL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK) |
3412 IL49_SCD_QUEUE_STTS_REG_MSK);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003413
3414 txq->sched_retry = scd_retry;
3415
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003416 D_INFO("%s %s Queue %d on AC %d\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003417 active ? "Activate" : "Deactivate",
3418 scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
3419}
3420
3421
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003422static int il4965_init_drv(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003423{
3424 int ret;
3425
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003426 spin_lock_init(&il->sta_lock);
3427 spin_lock_init(&il->hcmd_lock);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003428
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003429 INIT_LIST_HEAD(&il->free_frames);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003430
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003431 mutex_init(&il->mutex);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003432
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003433 il->ieee_channels = NULL;
3434 il->ieee_rates = NULL;
3435 il->band = IEEE80211_BAND_2GHZ;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003436
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003437 il->iw_mode = NL80211_IFTYPE_STATION;
3438 il->current_ht_config.smps = IEEE80211_SMPS_STATIC;
3439 il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003440
3441 /* initialize force reset */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003442 il->force_reset.reset_duration = IL_DELAY_NEXT_FORCE_FW_RELOAD;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003443
3444 /* Choose which receivers/antennas to use */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003445 if (il->cfg->ops->hcmd->set_rxon_chain)
3446 il->cfg->ops->hcmd->set_rxon_chain(il,
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003447 &il->ctx);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003448
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003449 il_init_scan_params(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003450
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003451 ret = il_init_channel_map(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003452 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003453 IL_ERR("initializing regulatory failed: %d\n", ret);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003454 goto err;
3455 }
3456
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003457 ret = il_init_geos(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003458 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003459 IL_ERR("initializing geos failed: %d\n", ret);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003460 goto err_free_channel_map;
3461 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003462 il4965_init_hw_rates(il, il->ieee_rates);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003463
3464 return 0;
3465
3466err_free_channel_map:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003467 il_free_channel_map(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003468err:
3469 return ret;
3470}
3471
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003472static void il4965_uninit_drv(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003473{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003474 il4965_calib_free_results(il);
3475 il_free_geos(il);
3476 il_free_channel_map(il);
3477 kfree(il->scan_cmd);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003478}
3479
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003480static void il4965_hw_detect(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003481{
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02003482 il->hw_rev = _il_rd(il, CSR_HW_REV);
3483 il->hw_wa_rev = _il_rd(il, CSR_HW_REV_WA_REG);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003484 il->rev_id = il->pci_dev->revision;
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003485 D_INFO("HW Revision ID = 0x%X\n", il->rev_id);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003486}
3487
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003488static int il4965_set_hw_params(struct il_priv *il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003489{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003490 il->hw_params.max_rxq_size = RX_QUEUE_SIZE;
3491 il->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
3492 if (il->cfg->mod_params->amsdu_size_8K)
3493 il->hw_params.rx_page_order = get_order(IL_RX_BUF_SIZE_8K);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003494 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003495 il->hw_params.rx_page_order = get_order(IL_RX_BUF_SIZE_4K);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003496
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003497 il->hw_params.max_beacon_itrvl = IL_MAX_UCODE_BEACON_INTERVAL;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003498
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003499 if (il->cfg->mod_params->disable_11n)
3500 il->cfg->sku &= ~IL_SKU_N;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003501
3502 /* Device-specific setup */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003503 return il->cfg->ops->lib->set_hw_params(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003504}
3505
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003506static const u8 il4965_bss_ac_to_fifo[] = {
3507 IL_TX_FIFO_VO,
3508 IL_TX_FIFO_VI,
3509 IL_TX_FIFO_BE,
3510 IL_TX_FIFO_BK,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003511};
3512
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003513static const u8 il4965_bss_ac_to_queue[] = {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003514 0, 1, 2, 3,
3515};
3516
3517static int
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003518il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003519{
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003520 int err = 0;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003521 struct il_priv *il;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003522 struct ieee80211_hw *hw;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003523 struct il_cfg *cfg = (struct il_cfg *)(ent->driver_data);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003524 unsigned long flags;
3525 u16 pci_cmd;
3526
3527 /************************
3528 * 1. Allocating HW data
3529 ************************/
3530
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003531 hw = il_alloc_all(cfg);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003532 if (!hw) {
3533 err = -ENOMEM;
3534 goto out;
3535 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003536 il = hw->priv;
3537 /* At this point both hw and il are allocated. */
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003538
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003539 il->ctx.ctxid = 0;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003540
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003541 il->ctx.always_active = true;
3542 il->ctx.is_active = true;
3543 il->ctx.rxon_cmd = REPLY_RXON;
3544 il->ctx.rxon_timing_cmd = REPLY_RXON_TIMING;
3545 il->ctx.rxon_assoc_cmd = REPLY_RXON_ASSOC;
3546 il->ctx.qos_cmd = REPLY_QOS_PARAM;
3547 il->ctx.ap_sta_id = IL_AP_ID;
3548 il->ctx.wep_key_cmd = REPLY_WEPKEY;
3549 il->ctx.ac_to_fifo = il4965_bss_ac_to_fifo;
3550 il->ctx.ac_to_queue = il4965_bss_ac_to_queue;
3551 il->ctx.exclusive_interface_modes =
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003552 BIT(NL80211_IFTYPE_ADHOC);
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003553 il->ctx.interface_modes =
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003554 BIT(NL80211_IFTYPE_STATION);
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003555 il->ctx.ap_devtype = RXON_DEV_TYPE_AP;
3556 il->ctx.ibss_devtype = RXON_DEV_TYPE_IBSS;
3557 il->ctx.station_devtype = RXON_DEV_TYPE_ESS;
3558 il->ctx.unused_devtype = RXON_DEV_TYPE_ESS;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003559
3560 SET_IEEE80211_DEV(hw, &pdev->dev);
3561
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003562 D_INFO("*** LOAD DRIVER ***\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003563 il->cfg = cfg;
3564 il->pci_dev = pdev;
3565 il->inta_mask = CSR_INI_SET_MASK;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003566
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003567 if (il_alloc_traffic_mem(il))
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003568 IL_ERR("Not enough memory to generate traffic log\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003569
3570 /**************************
3571 * 2. Initializing PCI bus
3572 **************************/
3573 pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
3574 PCIE_LINK_STATE_CLKPM);
3575
3576 if (pci_enable_device(pdev)) {
3577 err = -ENODEV;
3578 goto out_ieee80211_free_hw;
3579 }
3580
3581 pci_set_master(pdev);
3582
3583 err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
3584 if (!err)
3585 err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
3586 if (err) {
3587 err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
3588 if (!err)
3589 err = pci_set_consistent_dma_mask(pdev,
3590 DMA_BIT_MASK(32));
3591 /* both attempts failed: */
3592 if (err) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003593 IL_WARN("No suitable DMA available.\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003594 goto out_pci_disable_device;
3595 }
3596 }
3597
3598 err = pci_request_regions(pdev, DRV_NAME);
3599 if (err)
3600 goto out_pci_disable_device;
3601
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003602 pci_set_drvdata(pdev, il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003603
3604
3605 /***********************
3606 * 3. Read REV register
3607 ***********************/
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003608 il->hw_base = pci_iomap(pdev, 0, 0);
3609 if (!il->hw_base) {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003610 err = -ENODEV;
3611 goto out_pci_release_regions;
3612 }
3613
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003614 D_INFO("pci_resource_len = 0x%08llx\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003615 (unsigned long long) pci_resource_len(pdev, 0));
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003616 D_INFO("pci_resource_base = %p\n", il->hw_base);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003617
3618 /* these spin locks will be used in apm_ops.init and EEPROM access
3619 * we should init now
3620 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003621 spin_lock_init(&il->reg_lock);
3622 spin_lock_init(&il->lock);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003623
3624 /*
3625 * stop and reset the on-board processor just in case it is in a
3626 * strange state ... like being left stranded by a primary kernel
3627 * and this is now the kdump kernel trying to start up
3628 */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02003629 _il_wr(il, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003630
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003631 il4965_hw_detect(il);
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003632 IL_INFO("Detected %s, REV=0x%X\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003633 il->cfg->name, il->hw_rev);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003634
3635 /* We disable the RETRY_TIMEOUT register (0x41) to keep
3636 * PCI Tx retries from interfering with C3 CPU state */
3637 pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
3638
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003639 il4965_prepare_card_hw(il);
3640 if (!il->hw_ready) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003641 IL_WARN("Failed, HW not ready\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003642 goto out_iounmap;
3643 }
3644
3645 /*****************
3646 * 4. Read EEPROM
3647 *****************/
3648 /* Read the EEPROM */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003649 err = il_eeprom_init(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003650 if (err) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003651 IL_ERR("Unable to init EEPROM\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003652 goto out_iounmap;
3653 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003654 err = il4965_eeprom_check_version(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003655 if (err)
3656 goto out_free_eeprom;
3657
3658 if (err)
3659 goto out_free_eeprom;
3660
3661 /* extract MAC Address */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003662 il4965_eeprom_get_mac(il, il->addresses[0].addr);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003663 D_INFO("MAC address: %pM\n", il->addresses[0].addr);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003664 il->hw->wiphy->addresses = il->addresses;
3665 il->hw->wiphy->n_addresses = 1;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003666
3667 /************************
3668 * 5. Setup HW constants
3669 ************************/
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003670 if (il4965_set_hw_params(il)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003671 IL_ERR("failed to set hw parameters\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003672 goto out_free_eeprom;
3673 }
3674
3675 /*******************
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003676 * 6. Setup il
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003677 *******************/
3678
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003679 err = il4965_init_drv(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003680 if (err)
3681 goto out_free_eeprom;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003682 /* At this point both hw and il are initialized. */
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003683
3684 /********************
3685 * 7. Setup services
3686 ********************/
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003687 spin_lock_irqsave(&il->lock, flags);
3688 il_disable_interrupts(il);
3689 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003690
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003691 pci_enable_msi(il->pci_dev);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003692
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003693 err = request_irq(il->pci_dev->irq, il_isr,
3694 IRQF_SHARED, DRV_NAME, il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003695 if (err) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003696 IL_ERR("Error allocating IRQ %d\n", il->pci_dev->irq);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003697 goto out_disable_msi;
3698 }
3699
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003700 il4965_setup_deferred_work(il);
3701 il4965_setup_rx_handlers(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003702
3703 /*********************************************
3704 * 8. Enable interrupts and read RFKILL state
3705 *********************************************/
3706
Stanislaw Gruszkaa078a1f2011-04-28 11:51:25 +02003707 /* enable rfkill interrupt: hw bug w/a */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003708 pci_read_config_word(il->pci_dev, PCI_COMMAND, &pci_cmd);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003709 if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
3710 pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003711 pci_write_config_word(il->pci_dev, PCI_COMMAND, pci_cmd);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003712 }
3713
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003714 il_enable_rfkill_int(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003715
3716 /* If platform's RF_KILL switch is NOT set to KILL */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02003717 if (_il_rd(il, CSR_GP_CNTRL) &
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003718 CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003719 clear_bit(STATUS_RF_KILL_HW, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003720 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003721 set_bit(STATUS_RF_KILL_HW, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003722
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003723 wiphy_rfkill_set_hw_state(il->hw->wiphy,
3724 test_bit(STATUS_RF_KILL_HW, &il->status));
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003725
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003726 il_power_initialize(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003727
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003728 init_completion(&il->_4965.firmware_loading_complete);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003729
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003730 err = il4965_request_firmware(il, true);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003731 if (err)
3732 goto out_destroy_workqueue;
3733
3734 return 0;
3735
3736 out_destroy_workqueue:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003737 destroy_workqueue(il->workqueue);
3738 il->workqueue = NULL;
3739 free_irq(il->pci_dev->irq, il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003740 out_disable_msi:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003741 pci_disable_msi(il->pci_dev);
3742 il4965_uninit_drv(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003743 out_free_eeprom:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003744 il_eeprom_free(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003745 out_iounmap:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003746 pci_iounmap(pdev, il->hw_base);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003747 out_pci_release_regions:
3748 pci_set_drvdata(pdev, NULL);
3749 pci_release_regions(pdev);
3750 out_pci_disable_device:
3751 pci_disable_device(pdev);
3752 out_ieee80211_free_hw:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003753 il_free_traffic_mem(il);
3754 ieee80211_free_hw(il->hw);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003755 out:
3756 return err;
3757}
3758
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003759static void __devexit il4965_pci_remove(struct pci_dev *pdev)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003760{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003761 struct il_priv *il = pci_get_drvdata(pdev);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003762 unsigned long flags;
3763
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003764 if (!il)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003765 return;
3766
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003767 wait_for_completion(&il->_4965.firmware_loading_complete);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003768
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003769 D_INFO("*** UNLOAD DRIVER ***\n");
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003770
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003771 il_dbgfs_unregister(il);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003772 sysfs_remove_group(&pdev->dev.kobj, &il_attribute_group);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003773
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003774 /* ieee80211_unregister_hw call wil cause il_mac_stop to
3775 * to be called and il4965_down since we are removing the device
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003776 * we need to set STATUS_EXIT_PENDING bit.
3777 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003778 set_bit(STATUS_EXIT_PENDING, &il->status);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003779
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003780 il_leds_exit(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003781
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003782 if (il->mac80211_registered) {
3783 ieee80211_unregister_hw(il->hw);
3784 il->mac80211_registered = 0;
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003785 } else {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003786 il4965_down(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003787 }
3788
3789 /*
3790 * Make sure device is reset to low power before unloading driver.
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003791 * This may be redundant with il4965_down(), but there are paths to
3792 * run il4965_down() without calling apm_ops.stop(), and there are
3793 * paths to avoid running il4965_down() at all before leaving driver.
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003794 * This (inexpensive) call *makes sure* device is reset.
3795 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003796 il_apm_stop(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003797
3798 /* make sure we flush any pending irq or
3799 * tasklet for the driver
3800 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003801 spin_lock_irqsave(&il->lock, flags);
3802 il_disable_interrupts(il);
3803 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003804
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003805 il4965_synchronize_irq(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003806
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003807 il4965_dealloc_ucode_pci(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003808
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003809 if (il->rxq.bd)
3810 il4965_rx_queue_free(il, &il->rxq);
3811 il4965_hw_txq_ctx_free(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003812
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003813 il_eeprom_free(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003814
3815
3816 /*netif_stop_queue(dev); */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003817 flush_workqueue(il->workqueue);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003818
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003819 /* ieee80211_unregister_hw calls il_mac_stop, which flushes
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003820 * il->workqueue... so we can't take down the workqueue
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003821 * until now... */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003822 destroy_workqueue(il->workqueue);
3823 il->workqueue = NULL;
3824 il_free_traffic_mem(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003825
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003826 free_irq(il->pci_dev->irq, il);
3827 pci_disable_msi(il->pci_dev);
3828 pci_iounmap(pdev, il->hw_base);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003829 pci_release_regions(pdev);
3830 pci_disable_device(pdev);
3831 pci_set_drvdata(pdev, NULL);
3832
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003833 il4965_uninit_drv(il);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003834
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003835 dev_kfree_skb(il->beacon_skb);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003836
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003837 ieee80211_free_hw(il->hw);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003838}
3839
3840/*
3841 * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003842 * must be called under il->lock and mac access
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003843 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003844void il4965_txq_set_sched(struct il_priv *il, u32 mask)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003845{
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003846 il_wr_prph(il, IL49_SCD_TXFACT, mask);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003847}
3848
3849/*****************************************************************************
3850 *
3851 * driver and module entry point
3852 *
3853 *****************************************************************************/
3854
3855/* Hardware specific file defines the PCI IDs table for that hardware module */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003856static DEFINE_PCI_DEVICE_TABLE(il4965_hw_card_ids) = {
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003857 {IL_PCI_DEVICE(0x4229, PCI_ANY_ID, il4965_cfg)},
3858 {IL_PCI_DEVICE(0x4230, PCI_ANY_ID, il4965_cfg)},
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003859 {0}
3860};
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003861MODULE_DEVICE_TABLE(pci, il4965_hw_card_ids);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003862
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003863static struct pci_driver il4965_driver = {
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003864 .name = DRV_NAME,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003865 .id_table = il4965_hw_card_ids,
3866 .probe = il4965_pci_probe,
3867 .remove = __devexit_p(il4965_pci_remove),
3868 .driver.pm = IL_LEGACY_PM_OPS,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003869};
3870
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003871static int __init il4965_init(void)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003872{
3873
3874 int ret;
3875 pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
3876 pr_info(DRV_COPYRIGHT "\n");
3877
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003878 ret = il4965_rate_control_register();
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003879 if (ret) {
3880 pr_err("Unable to register rate control algorithm: %d\n", ret);
3881 return ret;
3882 }
3883
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003884 ret = pci_register_driver(&il4965_driver);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003885 if (ret) {
3886 pr_err("Unable to initialize PCI module\n");
3887 goto error_register;
3888 }
3889
3890 return ret;
3891
3892error_register:
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003893 il4965_rate_control_unregister();
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003894 return ret;
3895}
3896
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003897static void __exit il4965_exit(void)
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003898{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003899 pci_unregister_driver(&il4965_driver);
3900 il4965_rate_control_unregister();
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003901}
3902
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003903module_exit(il4965_exit);
3904module_init(il4965_init);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003905
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003906#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszkad2ddf6212011-08-16 14:17:04 +02003907module_param_named(debug, il_debug_level, uint, S_IRUGO | S_IWUSR);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003908MODULE_PARM_DESC(debug, "debug output mask");
3909#endif
3910
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003911module_param_named(swcrypto, il4965_mod_params.sw_crypto, int, S_IRUGO);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003912MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003913module_param_named(queues_num, il4965_mod_params.num_of_queues, int, S_IRUGO);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003914MODULE_PARM_DESC(queues_num, "number of hw queues.");
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003915module_param_named(11n_disable, il4965_mod_params.disable_11n, int, S_IRUGO);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003916MODULE_PARM_DESC(11n_disable, "disable 11n functionality");
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003917module_param_named(amsdu_size_8K, il4965_mod_params.amsdu_size_8K,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003918 int, S_IRUGO);
3919MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003920module_param_named(fw_restart, il4965_mod_params.restart_fw, int, S_IRUGO);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003921MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");