blob: 3630a41df50d7c64815abae048696ea04329a703 [file] [log] [blame]
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001/******************************************************************************
2 *
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003 * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08004 *
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 Guy4bc85c12011-02-21 11:11:05 -080043#include <linux/firmware.h>
44#include <linux/etherdevice.h>
45#include <linux/if_arp.h>
46
47#include <net/ieee80211_radiotap.h>
48#include <net/mac80211.h>
49
50#include <asm/div64.h>
51
52#define DRV_NAME "iwl3945"
53
Stanislaw Gruszkad4459a92011-08-31 10:59:02 +020054#include "commands.h"
Stanislaw Gruszka98613be2011-11-15 14:19:34 +010055#include "common.h"
Stanislaw Gruszkae94a4092011-08-31 13:23:20 +020056#include "3945.h"
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -080057#include "iwl-spectrum.h"
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -080058
59/*
60 * module name, copyright, version, etc.
61 */
62
63#define DRV_DESCRIPTION \
64"Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux"
65
Stanislaw Gruszkad3175162011-11-15 11:25:42 +010066#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -080067#define VD "d"
68#else
69#define VD
70#endif
71
72/*
73 * add "s" to indicate spectrum measurement included.
74 * we add it here to be consistent with previous releases in which
75 * this was configurable.
76 */
77#define DRV_VERSION IWLWIFI_VERSION VD "s"
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080078#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation"
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -080079#define DRV_AUTHOR "<ilw@linux.intel.com>"
80
81MODULE_DESCRIPTION(DRV_DESCRIPTION);
82MODULE_VERSION(DRV_VERSION);
83MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
84MODULE_LICENSE("GPL");
85
86 /* module parameters */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +020087struct il_mod_params il3945_mod_params = {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -080088 .sw_crypto = 1,
89 .restart_fw = 1,
Stanislaw Gruszka0263aa42011-03-29 11:24:21 +020090 .disable_hw_scan = 1,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -080091 /* the rest are 0 by default */
92};
93
94/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +020095 * il3945_get_antenna_flags - Get antenna flags for RXON command
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +020096 * @il: eeprom and antenna fields are used to determine antenna flags
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -080097 *
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +020098 * il->eeprom39 is used to determine if antenna AUX/MAIN are reversed
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +020099 * il3945_mod_params.antenna specifies the antenna diversity mode:
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800100 *
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200101 * IL_ANTENNA_DIVERSITY - NIC selects best antenna by itself
102 * IL_ANTENNA_MAIN - Force MAIN antenna
103 * IL_ANTENNA_AUX - Force AUX antenna
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800104 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100105__le32
106il3945_get_antenna_flags(const struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800107{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200108 struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800109
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200110 switch (il3945_mod_params.antenna) {
111 case IL_ANTENNA_DIVERSITY:
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800112 return 0;
113
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200114 case IL_ANTENNA_MAIN:
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800115 if (eeprom->antenna_switch_type)
116 return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
117 return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
118
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200119 case IL_ANTENNA_AUX:
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800120 if (eeprom->antenna_switch_type)
121 return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
122 return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
123 }
124
125 /* bad antenna selector value */
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200126 IL_ERR("Bad antenna selector value (0x%x)\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100127 il3945_mod_params.antenna);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800128
129 return 0; /* "diversity" is default if error */
130}
131
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100132static int
133il3945_set_ccmp_dynamic_key_info(struct il_priv *il,
134 struct ieee80211_key_conf *keyconf, u8 sta_id)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800135{
136 unsigned long flags;
137 __le16 key_flags = 0;
138 int ret;
139
140 key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
141 key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
142
Stanislaw Gruszkab16db502012-02-03 17:31:44 +0100143 if (sta_id == il->hw_params.bcast_id)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800144 key_flags |= STA_KEY_MULTICAST_MSK;
145
146 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
147 keyconf->hw_key_idx = keyconf->keyidx;
148 key_flags &= ~STA_KEY_FLG_INVALID;
149
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200150 spin_lock_irqsave(&il->sta_lock, flags);
151 il->stations[sta_id].keyinfo.cipher = keyconf->cipher;
152 il->stations[sta_id].keyinfo.keylen = keyconf->keylen;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100153 memcpy(il->stations[sta_id].keyinfo.key, keyconf->key, keyconf->keylen);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800154
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100155 memcpy(il->stations[sta_id].sta.key.key, keyconf->key, keyconf->keylen);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800156
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100157 if ((il->stations[sta_id].sta.key.
158 key_flags & STA_KEY_FLG_ENCRYPT_MSK) == STA_KEY_FLG_NO_ENC)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200159 il->stations[sta_id].sta.key.key_offset =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100160 il_get_free_ucode_key_idx(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800161 /* else, we are overriding an existing key => no need to allocated room
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100162 * in uCode. */
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800163
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200164 WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100165 "no space for a new key");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800166
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200167 il->stations[sta_id].sta.key.key_flags = key_flags;
168 il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
169 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800170
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100171 D_INFO("hwcrypto: modify ucode station key info\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800172
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100173 ret = il_send_add_sta(il, &il->stations[sta_id].sta, CMD_ASYNC);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800174
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200175 spin_unlock_irqrestore(&il->sta_lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800176
177 return ret;
178}
179
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100180static int
181il3945_set_tkip_dynamic_key_info(struct il_priv *il,
182 struct ieee80211_key_conf *keyconf, u8 sta_id)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800183{
184 return -EOPNOTSUPP;
185}
186
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100187static int
188il3945_set_wep_dynamic_key_info(struct il_priv *il,
189 struct ieee80211_key_conf *keyconf, u8 sta_id)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800190{
191 return -EOPNOTSUPP;
192}
193
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100194static int
195il3945_clear_sta_key_info(struct il_priv *il, u8 sta_id)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800196{
197 unsigned long flags;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200198 struct il_addsta_cmd sta_cmd;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800199
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200200 spin_lock_irqsave(&il->sta_lock, flags);
201 memset(&il->stations[sta_id].keyinfo, 0, sizeof(struct il_hw_key));
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100202 memset(&il->stations[sta_id].sta.key, 0, sizeof(struct il4965_keyinfo));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200203 il->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
204 il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
205 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100206 memcpy(&sta_cmd, &il->stations[sta_id].sta,
207 sizeof(struct il_addsta_cmd));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200208 spin_unlock_irqrestore(&il->sta_lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800209
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100210 D_INFO("hwcrypto: clear ucode station key info\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200211 return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800212}
213
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100214static int
215il3945_set_dynamic_key(struct il_priv *il, struct ieee80211_key_conf *keyconf,
216 u8 sta_id)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800217{
218 int ret = 0;
219
220 keyconf->hw_key_idx = HW_KEY_DYNAMIC;
221
222 switch (keyconf->cipher) {
223 case WLAN_CIPHER_SUITE_CCMP:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200224 ret = il3945_set_ccmp_dynamic_key_info(il, keyconf, sta_id);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800225 break;
226 case WLAN_CIPHER_SUITE_TKIP:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200227 ret = il3945_set_tkip_dynamic_key_info(il, keyconf, sta_id);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800228 break;
229 case WLAN_CIPHER_SUITE_WEP40:
230 case WLAN_CIPHER_SUITE_WEP104:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200231 ret = il3945_set_wep_dynamic_key_info(il, keyconf, sta_id);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800232 break;
233 default:
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100234 IL_ERR("Unknown alg: %s alg=%x\n", __func__, keyconf->cipher);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800235 ret = -EINVAL;
236 }
237
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100238 D_WEP("Set dynamic key: alg=%x len=%d idx=%d sta=%d ret=%d\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100239 keyconf->cipher, keyconf->keylen, keyconf->keyidx, sta_id, ret);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800240
241 return ret;
242}
243
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100244static int
245il3945_remove_static_key(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800246{
247 int ret = -EOPNOTSUPP;
248
249 return ret;
250}
251
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100252static int
253il3945_set_static_key(struct il_priv *il, struct ieee80211_key_conf *key)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800254{
255 if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
256 key->cipher == WLAN_CIPHER_SUITE_WEP104)
257 return -EOPNOTSUPP;
258
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200259 IL_ERR("Static key invalid: cipher %x\n", key->cipher);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800260 return -EINVAL;
261}
262
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100263static void
264il3945_clear_free_frames(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800265{
266 struct list_head *element;
267
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100268 D_INFO("%d frames on pre-allocated heap on clear.\n", il->frames_count);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800269
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200270 while (!list_empty(&il->free_frames)) {
271 element = il->free_frames.next;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800272 list_del(element);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200273 kfree(list_entry(element, struct il3945_frame, list));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200274 il->frames_count--;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800275 }
276
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200277 if (il->frames_count) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200278 IL_WARN("%d frames still in use. Did we lose one?\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100279 il->frames_count);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200280 il->frames_count = 0;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800281 }
282}
283
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100284static struct il3945_frame *
285il3945_get_free_frame(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800286{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200287 struct il3945_frame *frame;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800288 struct list_head *element;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200289 if (list_empty(&il->free_frames)) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800290 frame = kzalloc(sizeof(*frame), GFP_KERNEL);
291 if (!frame) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200292 IL_ERR("Could not allocate frame!\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800293 return NULL;
294 }
295
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200296 il->frames_count++;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800297 return frame;
298 }
299
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200300 element = il->free_frames.next;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800301 list_del(element);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200302 return list_entry(element, struct il3945_frame, list);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800303}
304
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100305static void
306il3945_free_frame(struct il_priv *il, struct il3945_frame *frame)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800307{
308 memset(frame, 0, sizeof(*frame));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200309 list_add(&frame->list, &il->free_frames);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800310}
311
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100312unsigned int
313il3945_fill_beacon_frame(struct il_priv *il, struct ieee80211_hdr *hdr,
314 int left)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800315{
316
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +0100317 if (!il_is_associated(il) || !il->beacon_skb)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800318 return 0;
319
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200320 if (il->beacon_skb->len > left)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800321 return 0;
322
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200323 memcpy(hdr, il->beacon_skb->data, il->beacon_skb->len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800324
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200325 return il->beacon_skb->len;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800326}
327
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100328static int
329il3945_send_beacon_cmd(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800330{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200331 struct il3945_frame *frame;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800332 unsigned int frame_size;
333 int rc;
334 u8 rate;
335
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200336 frame = il3945_get_free_frame(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800337
338 if (!frame) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200339 IL_ERR("Could not obtain free frame buffer for beacon "
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100340 "command.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800341 return -ENOMEM;
342 }
343
Stanislaw Gruszka83007192012-02-03 17:31:57 +0100344 rate = il_get_lowest_plcp(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800345
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200346 frame_size = il3945_hw_get_beacon_cmd(il, frame, rate);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800347
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100348 rc = il_send_cmd_pdu(il, C_TX_BEACON, frame_size, &frame->u.cmd[0]);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800349
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200350 il3945_free_frame(il, frame);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800351
352 return rc;
353}
354
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100355static void
356il3945_unset_hw_params(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800357{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200358 if (il->_3945.shared_virt)
359 dma_free_coherent(&il->pci_dev->dev,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200360 sizeof(struct il3945_shared),
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100361 il->_3945.shared_virt, il->_3945.shared_phys);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800362}
363
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100364static void
365il3945_build_tx_cmd_hwcrypto(struct il_priv *il, struct ieee80211_tx_info *info,
366 struct il_device_cmd *cmd,
367 struct sk_buff *skb_frag, int sta_id)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800368{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200369 struct il3945_tx_cmd *tx_cmd = (struct il3945_tx_cmd *)cmd->cmd.payload;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200370 struct il_hw_key *keyinfo = &il->stations[sta_id].keyinfo;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800371
372 tx_cmd->sec_ctl = 0;
373
374 switch (keyinfo->cipher) {
375 case WLAN_CIPHER_SUITE_CCMP:
376 tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
377 memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100378 D_TX("tx_cmd with AES hwcrypto\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800379 break;
380
381 case WLAN_CIPHER_SUITE_TKIP:
382 break;
383
384 case WLAN_CIPHER_SUITE_WEP104:
385 tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
386 /* fall through */
387 case WLAN_CIPHER_SUITE_WEP40:
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100388 tx_cmd->sec_ctl |=
389 TX_CMD_SEC_WEP | (info->control.hw_key->
390 hw_key_idx & TX_CMD_SEC_MSK) <<
391 TX_CMD_SEC_SHIFT;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800392
393 memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen);
394
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100395 D_TX("Configuring packet for WEP encryption " "with key %d\n",
396 info->control.hw_key->hw_key_idx);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800397 break;
398
399 default:
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200400 IL_ERR("Unknown encode cipher %x\n", keyinfo->cipher);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800401 break;
402 }
403}
404
405/*
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200406 * handle build C_TX command notification.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800407 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100408static void
409il3945_build_tx_cmd_basic(struct il_priv *il, struct il_device_cmd *cmd,
410 struct ieee80211_tx_info *info,
411 struct ieee80211_hdr *hdr, u8 std_id)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800412{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200413 struct il3945_tx_cmd *tx_cmd = (struct il3945_tx_cmd *)cmd->cmd.payload;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800414 __le32 tx_flags = tx_cmd->tx_flags;
415 __le16 fc = hdr->frame_control;
416
417 tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
418 if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
419 tx_flags |= TX_CMD_FLG_ACK_MSK;
420 if (ieee80211_is_mgmt(fc))
421 tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
422 if (ieee80211_is_probe_resp(fc) &&
423 !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
424 tx_flags |= TX_CMD_FLG_TSF_MSK;
425 } else {
426 tx_flags &= (~TX_CMD_FLG_ACK_MSK);
427 tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
428 }
429
430 tx_cmd->sta_id = std_id;
431 if (ieee80211_has_morefrags(fc))
432 tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
433
434 if (ieee80211_is_data_qos(fc)) {
435 u8 *qc = ieee80211_get_qos_ctl(hdr);
436 tx_cmd->tid_tspec = qc[0] & 0xf;
437 tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
438 } else {
439 tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
440 }
441
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200442 il_tx_cmd_protection(il, info, fc, &tx_flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800443
444 tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
445 if (ieee80211_is_mgmt(fc)) {
446 if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
447 tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3);
448 else
449 tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2);
450 } else {
451 tx_cmd->timeout.pm_frame_timeout = 0;
452 }
453
454 tx_cmd->driver_txop = 0;
455 tx_cmd->tx_flags = tx_flags;
456 tx_cmd->next_frame_len = 0;
457}
458
459/*
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200460 * start C_TX command process
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800461 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100462static int
Thomas Huehn36323f82012-07-23 21:33:42 +0200463il3945_tx_skb(struct il_priv *il,
464 struct ieee80211_sta *sta,
465 struct sk_buff *skb)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800466{
467 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
468 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200469 struct il3945_tx_cmd *tx_cmd;
470 struct il_tx_queue *txq = NULL;
471 struct il_queue *q = NULL;
472 struct il_device_cmd *out_cmd;
473 struct il_cmd_meta *out_meta;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800474 dma_addr_t phys_addr;
475 dma_addr_t txcmd_phys;
476 int txq_id = skb_get_queue_mapping(skb);
477 u16 len, idx, hdr_len;
478 u8 id;
479 u8 unicast;
480 u8 sta_id;
481 u8 tid = 0;
482 __le16 fc;
483 u8 wait_write_ptr = 0;
484 unsigned long flags;
485
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200486 spin_lock_irqsave(&il->lock, flags);
487 if (il_is_rfkill(il)) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100488 D_DROP("Dropping - RF KILL\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800489 goto drop_unlock;
490 }
491
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100492 if ((ieee80211_get_tx_rate(il->hw, info)->hw_value & 0xFF) ==
493 IL_INVALID_RATE) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200494 IL_ERR("ERROR: No TX rate available.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800495 goto drop_unlock;
496 }
497
498 unicast = !is_multicast_ether_addr(hdr->addr1);
499 id = 0;
500
501 fc = hdr->frame_control;
502
Stanislaw Gruszkad3175162011-11-15 11:25:42 +0100503#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800504 if (ieee80211_is_auth(fc))
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100505 D_TX("Sending AUTH frame\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800506 else if (ieee80211_is_assoc_req(fc))
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100507 D_TX("Sending ASSOC frame\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800508 else if (ieee80211_is_reassoc_req(fc))
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100509 D_TX("Sending REASSOC frame\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800510#endif
511
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200512 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800513
514 hdr_len = ieee80211_hdrlen(fc);
515
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100516 /* Find idx into station table for destination station */
Thomas Huehn36323f82012-07-23 21:33:42 +0200517 sta_id = il_sta_id_or_broadcast(il, sta);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200518 if (sta_id == IL_INVALID_STATION) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100519 D_DROP("Dropping - INVALID STATION: %pM\n", hdr->addr1);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800520 goto drop;
521 }
522
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100523 D_RATE("station Id %d\n", sta_id);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800524
525 if (ieee80211_is_data_qos(fc)) {
526 u8 *qc = ieee80211_get_qos_ctl(hdr);
527 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
528 if (unlikely(tid >= MAX_TID_COUNT))
529 goto drop;
530 }
531
532 /* Descriptor for chosen Tx queue */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200533 txq = &il->txq[txq_id];
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800534 q = &txq->q;
535
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200536 if ((il_queue_space(q) < q->high_mark))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800537 goto drop;
538
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200539 spin_lock_irqsave(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800540
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100541 idx = il_get_cmd_idx(q, q->write_ptr, 0);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800542
Stanislaw Gruszka00ea99e2012-02-03 17:32:00 +0100543 txq->skbs[q->write_ptr] = skb;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800544
545 /* Init first empty entry in queue's array of Tx/cmd buffers */
546 out_cmd = txq->cmd[idx];
547 out_meta = &txq->meta[idx];
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200548 tx_cmd = (struct il3945_tx_cmd *)out_cmd->cmd.payload;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800549 memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
550 memset(tx_cmd, 0, sizeof(*tx_cmd));
551
552 /*
553 * Set up the Tx-command (not MAC!) header.
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100554 * Store the chosen Tx queue and TFD idx within the sequence field;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800555 * after Tx, uCode's Tx response will return this value so driver can
556 * locate the frame within the tx queue and do post-tx processing.
557 */
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200558 out_cmd->hdr.cmd = C_TX;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100559 out_cmd->hdr.sequence =
560 cpu_to_le16((u16)
561 (QUEUE_TO_SEQ(txq_id) | IDX_TO_SEQ(q->write_ptr)));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800562
563 /* Copy MAC header from skb into command buffer */
564 memcpy(tx_cmd->hdr, hdr, hdr_len);
565
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800566 if (info->control.hw_key)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200567 il3945_build_tx_cmd_hwcrypto(il, info, out_cmd, skb, sta_id);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800568
569 /* TODO need this for burst mode later on */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200570 il3945_build_tx_cmd_basic(il, out_cmd, info, hdr, sta_id);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800571
Stanislaw Gruszka81fb4612011-12-23 08:13:49 +0100572 il3945_hw_build_tx_cmd_rate(il, out_cmd, info, hdr, sta_id);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800573
574 /* Total # bytes to be transmitted */
Stanislaw Gruszkabdb084b2013-02-13 15:49:08 +0100575 tx_cmd->len = cpu_to_le16((u16) skb->len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800576
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800577 tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
578 tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
579
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800580 /*
581 * Use the first empty entry in this queue's command buffer array
582 * to contain the Tx command and MAC header concatenated together
583 * (payload data will be in another buffer).
584 * Size of this varies, due to varying MAC header length.
585 * If end is not dword aligned, we'll have 2 extra bytes at the end
586 * of the MAC header (device reads on dword boundaries).
587 * We'll tell device about this padding later.
588 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100589 len =
590 sizeof(struct il3945_tx_cmd) + sizeof(struct il_cmd_header) +
591 hdr_len;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800592 len = (len + 3) & ~3;
593
594 /* Physical address of this Tx command's header (not MAC header!),
595 * within command buffer array. */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100596 txcmd_phys =
597 pci_map_single(il->pci_dev, &out_cmd->hdr, len, PCI_DMA_TODEVICE);
Stanislaw Gruszkabdb084b2013-02-13 15:49:08 +0100598 if (unlikely(pci_dma_mapping_error(il->pci_dev, txcmd_phys)))
599 goto drop_unlock;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800600
601 /* Set up TFD's 2nd entry to point directly to remainder of skb,
602 * if any (802.11 null frames have no payload). */
603 len = skb->len - hdr_len;
604 if (len) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100605 phys_addr =
606 pci_map_single(il->pci_dev, skb->data + hdr_len, len,
607 PCI_DMA_TODEVICE);
Stanislaw Gruszkabdb084b2013-02-13 15:49:08 +0100608 if (unlikely(pci_dma_mapping_error(il->pci_dev, phys_addr)))
609 goto drop_unlock;
610 }
611
612 /* Add buffer containing Tx command and MAC(!) header to TFD's
613 * first entry */
614 il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, len, 1, 0);
615 dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
616 dma_unmap_len_set(out_meta, len, len);
617 if (len)
Stanislaw Gruszka1600b872012-02-13 11:23:18 +0100618 il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, len, 0,
619 U32_PAD(len));
Stanislaw Gruszkabdb084b2013-02-13 15:49:08 +0100620
621 if (!ieee80211_has_morefrags(hdr->frame_control)) {
622 txq->need_update = 1;
623 } else {
624 wait_write_ptr = 1;
625 txq->need_update = 0;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800626 }
627
Stanislaw Gruszkabdb084b2013-02-13 15:49:08 +0100628 il_update_stats(il, true, fc, skb->len);
629
630 D_TX("sequence nr = 0X%x\n", le16_to_cpu(out_cmd->hdr.sequence));
631 D_TX("tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
632 il_print_hex_dump(il, IL_DL_TX, tx_cmd, sizeof(*tx_cmd));
633 il_print_hex_dump(il, IL_DL_TX, (u8 *) tx_cmd->hdr,
634 ieee80211_hdrlen(fc));
635
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100636 /* Tell device the write idx *just past* this latest filled TFD */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200637 q->write_ptr = il_queue_inc_wrap(q->write_ptr, q->n_bd);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200638 il_txq_update_write_ptr(il, txq);
639 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800640
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100641 if (il_queue_space(q) < q->high_mark && il->mac80211_registered) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800642 if (wait_write_ptr) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200643 spin_lock_irqsave(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800644 txq->need_update = 1;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200645 il_txq_update_write_ptr(il, txq);
646 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800647 }
648
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200649 il_stop_queue(il, txq);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800650 }
651
652 return 0;
653
654drop_unlock:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200655 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800656drop:
657 return -1;
658}
659
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100660static int
661il3945_get_measurement(struct il_priv *il,
662 struct ieee80211_measurement_params *params, u8 type)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800663{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200664 struct il_spectrum_cmd spectrum;
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +0200665 struct il_rx_pkt *pkt;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200666 struct il_host_cmd cmd = {
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200667 .id = C_SPECTRUM_MEASUREMENT,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800668 .data = (void *)&spectrum,
669 .flags = CMD_WANT_SKB,
670 };
671 u32 add_time = le64_to_cpu(params->start_time);
672 int rc;
673 int spectrum_resp_status;
674 int duration = le16_to_cpu(params->duration);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800675
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +0100676 if (il_is_associated(il))
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100677 add_time =
678 il_usecs_to_beacons(il,
679 le64_to_cpu(params->start_time) -
680 il->_3945.last_tsf,
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +0100681 le16_to_cpu(il->timing.beacon_interval));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800682
683 memset(&spectrum, 0, sizeof(spectrum));
684
685 spectrum.channel_count = cpu_to_le16(1);
686 spectrum.flags =
687 RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK;
688 spectrum.filter_flags = MEASUREMENT_FILTER_FLAG;
689 cmd.len = sizeof(spectrum);
690 spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
691
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +0100692 if (il_is_associated(il))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800693 spectrum.start_time =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100694 il_add_beacon_time(il, il->_3945.last_beacon_time, add_time,
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +0100695 le16_to_cpu(il->timing.beacon_interval));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800696 else
697 spectrum.start_time = 0;
698
699 spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT);
700 spectrum.channels[0].channel = params->channel;
701 spectrum.channels[0].type = type;
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +0100702 if (il->active.flags & RXON_FLG_BAND_24G_MSK)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100703 spectrum.flags |=
704 RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK |
705 RXON_FLG_TGG_PROTECT_MSK;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800706
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200707 rc = il_send_cmd_sync(il, &cmd);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800708 if (rc)
709 return rc;
710
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +0200711 pkt = (struct il_rx_pkt *)cmd.reply_page;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200712 if (pkt->hdr.flags & IL_CMD_FAILED_MSK) {
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200713 IL_ERR("Bad return from N_RX_ON_ASSOC command\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800714 rc = -EIO;
715 }
716
717 spectrum_resp_status = le16_to_cpu(pkt->u.spectrum.status);
718 switch (spectrum_resp_status) {
719 case 0: /* Command will be handled */
720 if (pkt->u.spectrum.id != 0xff) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100721 D_INFO("Replaced existing measurement: %d\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100722 pkt->u.spectrum.id);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200723 il->measurement_status &= ~MEASUREMENT_READY;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800724 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200725 il->measurement_status |= MEASUREMENT_ACTIVE;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800726 rc = 0;
727 break;
728
729 case 1: /* Command will not be handled */
730 rc = -EAGAIN;
731 break;
732 }
733
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200734 il_free_pages(il, cmd.reply_page);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800735
736 return rc;
737}
738
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100739static void
740il3945_hdl_alive(struct il_priv *il, struct il_rx_buf *rxb)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800741{
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +0200742 struct il_rx_pkt *pkt = rxb_addr(rxb);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200743 struct il_alive_resp *palive;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800744 struct delayed_work *pwork;
745
746 palive = &pkt->u.alive_frame;
747
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100748 D_INFO("Alive ucode status 0x%08X revision " "0x%01X 0x%01X\n",
749 palive->is_valid, palive->ver_type, palive->ver_subtype);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800750
751 if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100752 D_INFO("Initialization Alive received.\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200753 memcpy(&il->card_alive_init, &pkt->u.alive_frame,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200754 sizeof(struct il_alive_resp));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200755 pwork = &il->init_alive_start;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800756 } else {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100757 D_INFO("Runtime Alive received.\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200758 memcpy(&il->card_alive, &pkt->u.alive_frame,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200759 sizeof(struct il_alive_resp));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200760 pwork = &il->alive_start;
761 il3945_disable_events(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800762 }
763
764 /* We delay the ALIVE response by 5ms to
765 * give the HW RF Kill time to activate... */
766 if (palive->is_valid == UCODE_VALID_OK)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100767 queue_delayed_work(il->workqueue, pwork, msecs_to_jiffies(5));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800768 else
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200769 IL_WARN("uCode did not respond OK.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800770}
771
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100772static void
773il3945_hdl_add_sta(struct il_priv *il, struct il_rx_buf *rxb)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800774{
Stanislaw Gruszkad3175162011-11-15 11:25:42 +0100775#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +0200776 struct il_rx_pkt *pkt = rxb_addr(rxb);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800777#endif
778
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200779 D_RX("Received C_ADD_STA: 0x%02X\n", pkt->u.status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800780}
781
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100782static void
783il3945_hdl_beacon(struct il_priv *il, struct il_rx_buf *rxb)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800784{
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +0200785 struct il_rx_pkt *pkt = rxb_addr(rxb);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200786 struct il3945_beacon_notif *beacon = &(pkt->u.beacon_status);
Stanislaw Gruszkad3175162011-11-15 11:25:42 +0100787#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800788 u8 rate = beacon->beacon_notify_hdr.rate;
789
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100790 D_RX("beacon status %x retries %d iss %d " "tsf %d %d rate %d\n",
791 le32_to_cpu(beacon->beacon_notify_hdr.status) & TX_STATUS_MSK,
792 beacon->beacon_notify_hdr.failure_frame,
793 le32_to_cpu(beacon->ibss_mgr_status),
794 le32_to_cpu(beacon->high_tsf), le32_to_cpu(beacon->low_tsf), rate);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800795#endif
796
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200797 il->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800798
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800799}
800
801/* Handle notification from uCode that card's power state is changing
802 * due to software, hardware, or critical temperature RFKILL */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100803static void
804il3945_hdl_card_state(struct il_priv *il, struct il_rx_buf *rxb)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800805{
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +0200806 struct il_rx_pkt *pkt = rxb_addr(rxb);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800807 u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200808 unsigned long status = il->status;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800809
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200810 IL_WARN("Card state received: HW:%s SW:%s\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100811 (flags & HW_CARD_DISABLED) ? "Kill" : "On",
812 (flags & SW_CARD_DISABLED) ? "Kill" : "On");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800813
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100814 _il_wr(il, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800815
816 if (flags & HW_CARD_DISABLED)
Stanislaw Gruszkabc269a82012-02-13 11:23:29 +0100817 set_bit(S_RFKILL, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800818 else
Stanislaw Gruszkabc269a82012-02-13 11:23:29 +0100819 clear_bit(S_RFKILL, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800820
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200821 il_scan_cancel(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800822
Stanislaw Gruszkabc269a82012-02-13 11:23:29 +0100823 if ((test_bit(S_RFKILL, &status) !=
824 test_bit(S_RFKILL, &il->status)))
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200825 wiphy_rfkill_set_hw_state(il->hw->wiphy,
Stanislaw Gruszkabc269a82012-02-13 11:23:29 +0100826 test_bit(S_RFKILL, &il->status));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800827 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200828 wake_up(&il->wait_command_queue);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800829}
830
831/**
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +0200832 * il3945_setup_handlers - Initialize Rx handler callbacks
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800833 *
834 * Setup the RX handlers for each of the reply types sent from the uCode
835 * to the host.
836 *
837 * This function chains into the hardware specific files for them to setup
838 * any hardware specific handlers as well.
839 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100840static void
841il3945_setup_handlers(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800842{
Stanislaw Gruszka6e9848b42011-08-30 15:45:31 +0200843 il->handlers[N_ALIVE] = il3945_hdl_alive;
844 il->handlers[C_ADD_STA] = il3945_hdl_add_sta;
845 il->handlers[N_ERROR] = il_hdl_error;
Stanislaw Gruszkad2dfb332011-11-15 13:16:38 +0100846 il->handlers[N_CHANNEL_SWITCH] = il_hdl_csa;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100847 il->handlers[N_SPECTRUM_MEASUREMENT] = il_hdl_spectrum_measurement;
Stanislaw Gruszkad2dfb332011-11-15 13:16:38 +0100848 il->handlers[N_PM_SLEEP] = il_hdl_pm_sleep;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100849 il->handlers[N_PM_DEBUG_STATS] = il_hdl_pm_debug_stats;
Stanislaw Gruszkad2dfb332011-11-15 13:16:38 +0100850 il->handlers[N_BEACON] = il3945_hdl_beacon;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800851
852 /*
853 * The same handler is used for both the REPLY to a discrete
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +0200854 * stats request from the host as well as for the periodic
855 * stats notifications (after received beacons) from the uCode.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800856 */
Stanislaw Gruszkad2dfb332011-11-15 13:16:38 +0100857 il->handlers[C_STATS] = il3945_hdl_c_stats;
858 il->handlers[N_STATS] = il3945_hdl_stats;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800859
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200860 il_setup_rx_scan_handlers(il);
Stanislaw Gruszkad2dfb332011-11-15 13:16:38 +0100861 il->handlers[N_CARD_STATE] = il3945_hdl_card_state;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800862
863 /* Set up hardware specific Rx handlers */
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +0200864 il3945_hw_handler_setup(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800865}
866
867/************************** RX-FUNCTIONS ****************************/
868/*
869 * Rx theory of operation
870 *
871 * The host allocates 32 DMA target addresses and passes the host address
Stanislaw Gruszka3b98c7f2011-08-26 16:29:35 +0200872 * to the firmware at register IL_RFDS_TBL_LOWER + N * RFD_SIZE where N is
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800873 * 0 to 31
874 *
875 * Rx Queue Indexes
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100876 * The host/firmware share two idx registers for managing the Rx buffers.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800877 *
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100878 * The READ idx maps to the first position that the firmware may be writing
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800879 * to -- the driver can read up to (but not including) this position and get
880 * good data.
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100881 * The READ idx is managed by the firmware once the card is enabled.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800882 *
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100883 * The WRITE idx maps to the last position the driver has read from -- the
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800884 * position preceding WRITE is the last slot the firmware can place a packet.
885 *
886 * The queue is empty (no good data) if WRITE = READ - 1, and is full if
887 * WRITE = READ.
888 *
889 * During initialization, the host sets up the READ queue position to the first
Stanislaw Gruszka2d09b062011-08-26 16:10:40 +0200890 * IDX position, and WRITE to the last (READ - 1 wrapped)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800891 *
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100892 * When the firmware places a packet in a buffer, it will advance the READ idx
893 * and fire the RX interrupt. The driver can then query the READ idx and
894 * process as many packets as possible, moving the WRITE idx forward as it
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800895 * resets the Rx queue buffers with new memory.
896 *
897 * The management in the driver is as follows:
898 * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When
899 * iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
900 * to replenish the iwl->rxq->rx_free.
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200901 * + In il3945_rx_replenish (scheduled) if 'processed' != 'read' then the
Stanislaw Gruszka2d09b062011-08-26 16:10:40 +0200902 * iwl->rxq is replenished and the READ IDX is updated (updating the
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100903 * 'processed' and 'read' driver idxes as well)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800904 * + A received packet is processed and handed to the kernel network stack,
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100905 * detached from the iwl->rxq. The driver 'processed' idx is updated.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800906 * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
907 * list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
Stanislaw Gruszka2d09b062011-08-26 16:10:40 +0200908 * IDX is not incremented and iwl->status(RX_STALLED) is set. If there
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800909 * were enough free buffers and RX_STALLED is set it is cleared.
910 *
911 *
912 * Driver sequence:
913 *
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200914 * il3945_rx_replenish() Replenishes rx_free list from rx_used, and calls
915 * il3945_rx_queue_restock
916 * il3945_rx_queue_restock() Moves available buffers from rx_free into Rx
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800917 * queue, updates firmware pointers, and updates
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100918 * the WRITE idx. If insufficient rx_free buffers
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200919 * are available, schedules il3945_rx_replenish
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800920 *
921 * -- enable interrupts --
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +0200922 * ISR - il3945_rx() Detach il_rx_bufs from pool up to the
Stanislaw Gruszka2d09b062011-08-26 16:10:40 +0200923 * READ IDX, detaching the SKB from the pool.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800924 * Moves the packet buffer from queue to rx_used.
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200925 * Calls il3945_rx_queue_restock to refill any empty
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800926 * slots.
927 * ...
928 *
929 */
930
931/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200932 * il3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800933 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100934static inline __le32
935il3945_dma_addr2rbd_ptr(struct il_priv *il, dma_addr_t dma_addr)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800936{
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100937 return cpu_to_le32((u32) dma_addr);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800938}
939
940/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200941 * il3945_rx_queue_restock - refill RX queue from pre-allocated pool
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800942 *
943 * If there are slots in the RX queue that need to be restocked,
944 * and we have free pre-allocated buffers, fill the ranks as much
945 * as we can, pulling from rx_free.
946 *
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100947 * This moves the 'write' idx forward to catch up with 'processed', and
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800948 * also updates the memory address in the firmware to reference the new
949 * target buffer.
950 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100951static void
952il3945_rx_queue_restock(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800953{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200954 struct il_rx_queue *rxq = &il->rxq;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800955 struct list_head *element;
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +0200956 struct il_rx_buf *rxb;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800957 unsigned long flags;
958 int write;
959
960 spin_lock_irqsave(&rxq->lock, flags);
961 write = rxq->write & ~0x7;
Stanislaw Gruszka232913b2011-08-26 10:45:16 +0200962 while (il_rx_queue_space(rxq) > 0 && rxq->free_count) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800963 /* Get next free Rx buffer, remove from free list */
964 element = rxq->rx_free.next;
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +0200965 rxb = list_entry(element, struct il_rx_buf, list);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800966 list_del(element);
967
968 /* Point to Rx buffer via next RBD in circular buffer */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +0100969 rxq->bd[rxq->write] =
970 il3945_dma_addr2rbd_ptr(il, rxb->page_dma);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800971 rxq->queue[rxq->write] = rxb;
972 rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
973 rxq->free_count--;
974 }
975 spin_unlock_irqrestore(&rxq->lock, flags);
976 /* If the pre-allocated buffer pool is dropping low, schedule to
977 * refill it */
978 if (rxq->free_count <= RX_LOW_WATERMARK)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200979 queue_work(il->workqueue, &il->rx_replenish);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800980
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800981 /* If we've added more space for the firmware to place data, tell it.
982 * Increment device's write pointer in multiples of 8. */
Stanislaw Gruszka232913b2011-08-26 10:45:16 +0200983 if (rxq->write_actual != (rxq->write & ~0x7) ||
984 abs(rxq->write - rxq->read) > 7) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800985 spin_lock_irqsave(&rxq->lock, flags);
986 rxq->need_update = 1;
987 spin_unlock_irqrestore(&rxq->lock, flags);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200988 il_rx_queue_update_write_ptr(il, rxq);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800989 }
990}
991
992/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200993 * il3945_rx_replenish - Move all used packet from rx_used to rx_free
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800994 *
995 * When moving to rx_free an SKB is allocated for the slot.
996 *
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200997 * Also restock the Rx queue via il3945_rx_queue_restock.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800998 * This is called as a scheduled work item (except for during initialization)
999 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001000static void
1001il3945_rx_allocate(struct il_priv *il, gfp_t priority)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001002{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001003 struct il_rx_queue *rxq = &il->rxq;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001004 struct list_head *element;
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +02001005 struct il_rx_buf *rxb;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001006 struct page *page;
Stanislaw Gruszka96ebbe82013-01-30 17:08:03 +01001007 dma_addr_t page_dma;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001008 unsigned long flags;
1009 gfp_t gfp_mask = priority;
1010
1011 while (1) {
1012 spin_lock_irqsave(&rxq->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001013 if (list_empty(&rxq->rx_used)) {
1014 spin_unlock_irqrestore(&rxq->lock, flags);
1015 return;
1016 }
1017 spin_unlock_irqrestore(&rxq->lock, flags);
1018
1019 if (rxq->free_count > RX_LOW_WATERMARK)
1020 gfp_mask |= __GFP_NOWARN;
1021
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001022 if (il->hw_params.rx_page_order > 0)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001023 gfp_mask |= __GFP_COMP;
1024
1025 /* Alloc a new receive buffer */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001026 page = alloc_pages(gfp_mask, il->hw_params.rx_page_order);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001027 if (!page) {
1028 if (net_ratelimit())
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001029 D_INFO("Failed to allocate SKB buffer.\n");
Stanislaw Gruszka232913b2011-08-26 10:45:16 +02001030 if (rxq->free_count <= RX_LOW_WATERMARK &&
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001031 net_ratelimit())
Stanislaw Gruszka1722f8e2011-11-15 14:51:01 +01001032 IL_ERR("Failed to allocate SKB buffer with %0x."
1033 "Only %u free buffers remaining.\n",
1034 priority, rxq->free_count);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001035 /* We don't reschedule replenish work here -- we will
1036 * call the restock method and if it still needs
1037 * more buffers it will schedule replenish */
1038 break;
1039 }
1040
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001041 /* Get physical address of RB/SKB */
Stanislaw Gruszka96ebbe82013-01-30 17:08:03 +01001042 page_dma =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001043 pci_map_page(il->pci_dev, page, 0,
1044 PAGE_SIZE << il->hw_params.rx_page_order,
1045 PCI_DMA_FROMDEVICE);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001046
Stanislaw Gruszka96ebbe82013-01-30 17:08:03 +01001047 if (unlikely(pci_dma_mapping_error(il->pci_dev, page_dma))) {
1048 __free_pages(page, il->hw_params.rx_page_order);
1049 break;
1050 }
1051
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001052 spin_lock_irqsave(&rxq->lock, flags);
1053
Stanislaw Gruszka96ebbe82013-01-30 17:08:03 +01001054 if (list_empty(&rxq->rx_used)) {
1055 spin_unlock_irqrestore(&rxq->lock, flags);
1056 pci_unmap_page(il->pci_dev, page_dma,
1057 PAGE_SIZE << il->hw_params.rx_page_order,
1058 PCI_DMA_FROMDEVICE);
1059 __free_pages(page, il->hw_params.rx_page_order);
1060 return;
1061 }
1062
1063 element = rxq->rx_used.next;
1064 rxb = list_entry(element, struct il_rx_buf, list);
1065 list_del(element);
1066
1067 rxb->page = page;
1068 rxb->page_dma = page_dma;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001069 list_add_tail(&rxb->list, &rxq->rx_free);
1070 rxq->free_count++;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001071 il->alloc_rxb_page++;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001072
1073 spin_unlock_irqrestore(&rxq->lock, flags);
1074 }
1075}
1076
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001077void
1078il3945_rx_queue_reset(struct il_priv *il, struct il_rx_queue *rxq)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001079{
1080 unsigned long flags;
1081 int i;
1082 spin_lock_irqsave(&rxq->lock, flags);
1083 INIT_LIST_HEAD(&rxq->rx_free);
1084 INIT_LIST_HEAD(&rxq->rx_used);
1085 /* Fill the rx_used queue with _all_ of the Rx buffers */
1086 for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
1087 /* In the reset function, these buffers may have been allocated
1088 * to an SKB, so we need to unmap and free potential storage */
1089 if (rxq->pool[i].page != NULL) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001090 pci_unmap_page(il->pci_dev, rxq->pool[i].page_dma,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001091 PAGE_SIZE << il->hw_params.rx_page_order,
1092 PCI_DMA_FROMDEVICE);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001093 __il_free_pages(il, rxq->pool[i].page);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001094 rxq->pool[i].page = NULL;
1095 }
1096 list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
1097 }
1098
1099 /* Set us so that we have processed and used all buffers, but have
1100 * not restocked the Rx queue with fresh buffers */
1101 rxq->read = rxq->write = 0;
1102 rxq->write_actual = 0;
1103 rxq->free_count = 0;
1104 spin_unlock_irqrestore(&rxq->lock, flags);
1105}
1106
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001107void
1108il3945_rx_replenish(void *data)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001109{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001110 struct il_priv *il = data;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001111 unsigned long flags;
1112
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001113 il3945_rx_allocate(il, GFP_KERNEL);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001114
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001115 spin_lock_irqsave(&il->lock, flags);
1116 il3945_rx_queue_restock(il);
1117 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001118}
1119
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001120static void
1121il3945_rx_replenish_now(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001122{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001123 il3945_rx_allocate(il, GFP_ATOMIC);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001124
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001125 il3945_rx_queue_restock(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001126}
1127
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001128/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
1129 * If an SKB has been detached, the POOL needs to have its SKB set to NULL
1130 * This free routine walks the list of POOL entries and if SKB is set to
1131 * non NULL it is unmapped and freed
1132 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001133static void
1134il3945_rx_queue_free(struct il_priv *il, struct il_rx_queue *rxq)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001135{
1136 int i;
1137 for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
1138 if (rxq->pool[i].page != NULL) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001139 pci_unmap_page(il->pci_dev, rxq->pool[i].page_dma,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001140 PAGE_SIZE << il->hw_params.rx_page_order,
1141 PCI_DMA_FROMDEVICE);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001142 __il_free_pages(il, rxq->pool[i].page);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001143 rxq->pool[i].page = NULL;
1144 }
1145 }
1146
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001147 dma_free_coherent(&il->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001148 rxq->bd_dma);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001149 dma_free_coherent(&il->pci_dev->dev, sizeof(struct il_rb_status),
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001150 rxq->rb_stts, rxq->rb_stts_dma);
1151 rxq->bd = NULL;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001152 rxq->rb_stts = NULL;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001153}
1154
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001155/* Convert linear signal-to-noise ratio into dB */
1156static u8 ratio2dB[100] = {
1157/* 0 1 2 3 4 5 6 7 8 9 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001158 0, 0, 6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */
1159 20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */
1160 26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */
1161 29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */
1162 32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */
1163 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */
1164 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */
1165 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */
1166 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */
1167 39, 39, 39, 39, 39, 40, 40, 40, 40, 40 /* 90 - 99 */
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001168};
1169
1170/* Calculates a relative dB value from a ratio of linear
1171 * (i.e. not dB) signal levels.
1172 * Conversion assumes that levels are voltages (20*log), not powers (10*log). */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001173int
1174il3945_calc_db_from_ratio(int sig_ratio)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001175{
1176 /* 1000:1 or higher just report as 60 dB */
1177 if (sig_ratio >= 1000)
1178 return 60;
1179
1180 /* 100:1 or higher, divide by 10 and use table,
1181 * add 20 dB to make up for divide by 10 */
1182 if (sig_ratio >= 100)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001183 return 20 + (int)ratio2dB[sig_ratio / 10];
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001184
1185 /* We shouldn't see this */
1186 if (sig_ratio < 1)
1187 return 0;
1188
1189 /* Use table for ratios 1:1 - 99:1 */
1190 return (int)ratio2dB[sig_ratio];
1191}
1192
1193/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001194 * il3945_rx_handle - Main entry function for receiving responses from uCode
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001195 *
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +02001196 * Uses the il->handlers callback function array to invoke
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001197 * the appropriate handlers, including command responses,
1198 * frame-received notifications, and other notifications.
1199 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001200static void
1201il3945_rx_handle(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001202{
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +02001203 struct il_rx_buf *rxb;
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +02001204 struct il_rx_pkt *pkt;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001205 struct il_rx_queue *rxq = &il->rxq;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001206 u32 r, i;
1207 int reclaim;
1208 unsigned long flags;
1209 u8 fill_rx = 0;
1210 u32 count = 8;
1211 int total_empty = 0;
1212
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01001213 /* uCode's read idx (stored in shared DRAM) indicates the last Rx
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001214 * buffer that the driver may process (last buffer filled by ucode). */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001215 r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001216 i = rxq->read;
1217
1218 /* calculate total frames need to be restock after handling RX */
1219 total_empty = r - rxq->write_actual;
1220 if (total_empty < 0)
1221 total_empty += RX_QUEUE_SIZE;
1222
1223 if (total_empty > (RX_QUEUE_SIZE / 2))
1224 fill_rx = 1;
1225 /* Rx interrupt, but nothing sent from uCode */
1226 if (i == r)
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001227 D_RX("r = %d, i = %d\n", r, i);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001228
1229 while (i != r) {
1230 int len;
1231
1232 rxb = rxq->queue[i];
1233
1234 /* If an RXB doesn't have a Rx queue slot associated with it,
1235 * then a bug has been introduced in the queue refilling
1236 * routines -- catch it here */
1237 BUG_ON(rxb == NULL);
1238
1239 rxq->queue[i] = NULL;
1240
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001241 pci_unmap_page(il->pci_dev, rxb->page_dma,
1242 PAGE_SIZE << il->hw_params.rx_page_order,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001243 PCI_DMA_FROMDEVICE);
1244 pkt = rxb_addr(rxb);
1245
Stanislaw Gruszkae94a4092011-08-31 13:23:20 +02001246 len = le32_to_cpu(pkt->len_n_flags) & IL_RX_FRAME_SIZE_MSK;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001247 len += sizeof(u32); /* account for status word */
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001248
1249 /* Reclaim a command buffer only if this packet is a response
1250 * to a (driver-originated) command.
1251 * If the packet (e.g. Rx frame) originated from uCode,
1252 * there is no command buffer to reclaim.
1253 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
1254 * but apparently a few don't get set; catch them here. */
1255 reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001256 pkt->hdr.cmd != N_STATS && pkt->hdr.cmd != C_TX;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001257
1258 /* Based on type of command response or notification,
1259 * handle those that need handling via function in
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +02001260 * handlers table. See il3945_setup_handlers() */
1261 if (il->handlers[pkt->hdr.cmd]) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001262 D_RX("r = %d, i = %d, %s, 0x%02x\n", r, i,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001263 il_get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +02001264 il->isr_stats.handlers[pkt->hdr.cmd]++;
1265 il->handlers[pkt->hdr.cmd] (il, rxb);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001266 } else {
1267 /* No handling needed */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001268 D_RX("r %d i %d No handler needed for %s, 0x%02x\n", r,
1269 i, il_get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001270 }
1271
1272 /*
1273 * XXX: After here, we should always check rxb->page
1274 * against NULL before touching it or its virtual
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +02001275 * memory (pkt). Because some handler might have
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001276 * already taken or freed the pages.
1277 */
1278
1279 if (reclaim) {
1280 /* Invoke any callbacks, transfer the buffer to caller,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001281 * and fire off the (possibly) blocking il_send_cmd()
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001282 * as we reclaim the driver command queue */
1283 if (rxb->page)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001284 il_tx_cmd_complete(il, rxb);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001285 else
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001286 IL_WARN("Claim null rxb?\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001287 }
1288
1289 /* Reuse the page if possible. For notification packets and
1290 * SKBs that fail to Rx correctly, add them back into the
1291 * rx_free list for reuse later. */
1292 spin_lock_irqsave(&rxq->lock, flags);
1293 if (rxb->page != NULL) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001294 rxb->page_dma =
1295 pci_map_page(il->pci_dev, rxb->page, 0,
1296 PAGE_SIZE << il->hw_params.
1297 rx_page_order, PCI_DMA_FROMDEVICE);
Stanislaw Gruszka96ebbe82013-01-30 17:08:03 +01001298 if (unlikely(pci_dma_mapping_error(il->pci_dev,
1299 rxb->page_dma))) {
1300 __il_free_pages(il, rxb->page);
1301 rxb->page = NULL;
1302 list_add_tail(&rxb->list, &rxq->rx_used);
1303 } else {
1304 list_add_tail(&rxb->list, &rxq->rx_free);
1305 rxq->free_count++;
1306 }
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001307 } else
1308 list_add_tail(&rxb->list, &rxq->rx_used);
1309
1310 spin_unlock_irqrestore(&rxq->lock, flags);
1311
1312 i = (i + 1) & RX_QUEUE_MASK;
1313 /* If there are a lot of unused frames,
1314 * restock the Rx queue so ucode won't assert. */
1315 if (fill_rx) {
1316 count++;
1317 if (count >= 8) {
1318 rxq->read = i;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001319 il3945_rx_replenish_now(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001320 count = 0;
1321 }
1322 }
1323 }
1324
1325 /* Backtrack one entry */
1326 rxq->read = i;
1327 if (fill_rx)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001328 il3945_rx_replenish_now(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001329 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001330 il3945_rx_queue_restock(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001331}
1332
1333/* call this function to flush any scheduled tasklet */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001334static inline void
1335il3945_synchronize_irq(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001336{
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001337 /* wait to make sure we flush pending tasklet */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001338 synchronize_irq(il->pci_dev->irq);
1339 tasklet_kill(&il->irq_tasklet);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001340}
1341
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001342static const char *
1343il3945_desc_lookup(int i)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001344{
1345 switch (i) {
1346 case 1:
1347 return "FAIL";
1348 case 2:
1349 return "BAD_PARAM";
1350 case 3:
1351 return "BAD_CHECKSUM";
1352 case 4:
1353 return "NMI_INTERRUPT";
1354 case 5:
1355 return "SYSASSERT";
1356 case 6:
1357 return "FATAL_ERROR";
1358 }
1359
1360 return "UNKNOWN";
1361}
1362
1363#define ERROR_START_OFFSET (1 * sizeof(u32))
1364#define ERROR_ELEM_SIZE (7 * sizeof(u32))
1365
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001366void
1367il3945_dump_nic_error_log(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001368{
1369 u32 i;
1370 u32 desc, time, count, base, data1;
1371 u32 blink1, blink2, ilink1, ilink2;
1372
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001373 base = le32_to_cpu(il->card_alive.error_event_table_ptr);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001374
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001375 if (!il3945_hw_valid_rtc_data_addr(base)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001376 IL_ERR("Not valid error log pointer 0x%08X\n", base);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001377 return;
1378 }
1379
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001380 count = il_read_targ_mem(il, base);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001381
1382 if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001383 IL_ERR("Start IWL Error Log Dump:\n");
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001384 IL_ERR("Status: 0x%08lX, count: %d\n", il->status, count);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001385 }
1386
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001387 IL_ERR("Desc Time asrtPC blink2 "
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001388 "ilink1 nmiPC Line\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001389 for (i = ERROR_START_OFFSET;
1390 i < (count * ERROR_ELEM_SIZE) + ERROR_START_OFFSET;
1391 i += ERROR_ELEM_SIZE) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001392 desc = il_read_targ_mem(il, base + i);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001393 time = il_read_targ_mem(il, base + i + 1 * sizeof(u32));
1394 blink1 = il_read_targ_mem(il, base + i + 2 * sizeof(u32));
1395 blink2 = il_read_targ_mem(il, base + i + 3 * sizeof(u32));
1396 ilink1 = il_read_targ_mem(il, base + i + 4 * sizeof(u32));
1397 ilink2 = il_read_targ_mem(il, base + i + 5 * sizeof(u32));
1398 data1 = il_read_targ_mem(il, base + i + 6 * sizeof(u32));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001399
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001400 IL_ERR("%-13s (0x%X) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
1401 il3945_desc_lookup(desc), desc, time, blink1, blink2,
1402 ilink1, ilink2, data1);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001403 }
1404}
1405
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001406static void
1407il3945_irq_tasklet(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001408{
1409 u32 inta, handled = 0;
1410 u32 inta_fh;
1411 unsigned long flags;
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001412#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001413 u32 inta_mask;
1414#endif
1415
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001416 spin_lock_irqsave(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001417
1418 /* Ack/clear/reset pending uCode interrupts.
1419 * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
1420 * and will clear only when CSR_FH_INT_STATUS gets cleared. */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001421 inta = _il_rd(il, CSR_INT);
1422 _il_wr(il, CSR_INT, inta);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001423
1424 /* Ack/clear/reset pending flow-handler (DMA) interrupts.
1425 * Any new interrupts that happen after this, either while we're
1426 * in this tasklet, or later, will show up in next ISR/tasklet. */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001427 inta_fh = _il_rd(il, CSR_FH_INT_STATUS);
1428 _il_wr(il, CSR_FH_INT_STATUS, inta_fh);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001429
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001430#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001431 if (il_get_debug_level(il) & IL_DL_ISR) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001432 /* just for debug */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001433 inta_mask = _il_rd(il, CSR_INT_MASK);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001434 D_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta,
1435 inta_mask, inta_fh);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001436 }
1437#endif
1438
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001439 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001440
1441 /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
1442 * atomic, make sure that inta covers all the interrupts that
1443 * we've discovered, even if FH interrupt came in just after
1444 * reading CSR_INT. */
1445 if (inta_fh & CSR39_FH_INT_RX_MASK)
1446 inta |= CSR_INT_BIT_FH_RX;
1447 if (inta_fh & CSR39_FH_INT_TX_MASK)
1448 inta |= CSR_INT_BIT_FH_TX;
1449
1450 /* Now service all interrupt bits discovered above. */
1451 if (inta & CSR_INT_BIT_HW_ERR) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001452 IL_ERR("Hardware error detected. Restarting.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001453
1454 /* Tell the device to stop sending interrupts */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001455 il_disable_interrupts(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001456
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001457 il->isr_stats.hw++;
1458 il_irq_handle_error(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001459
1460 handled |= CSR_INT_BIT_HW_ERR;
1461
1462 return;
1463 }
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001464#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001465 if (il_get_debug_level(il) & (IL_DL_ISR)) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001466 /* NIC fires this, but we don't use it, redundant with WAKEUP */
1467 if (inta & CSR_INT_BIT_SCD) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001468 D_ISR("Scheduler finished to transmit "
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001469 "the frame/frames.\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001470 il->isr_stats.sch++;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001471 }
1472
1473 /* Alive notification via Rx interrupt will do the real work */
1474 if (inta & CSR_INT_BIT_ALIVE) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001475 D_ISR("Alive interrupt\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001476 il->isr_stats.alive++;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001477 }
1478 }
1479#endif
1480 /* Safely ignore these bits for debug checks below */
1481 inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
1482
1483 /* Error detected by uCode */
1484 if (inta & CSR_INT_BIT_SW_ERR) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001485 IL_ERR("Microcode SW error detected. " "Restarting 0x%X.\n",
1486 inta);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001487 il->isr_stats.sw++;
1488 il_irq_handle_error(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001489 handled |= CSR_INT_BIT_SW_ERR;
1490 }
1491
1492 /* uCode wakes up after power-down sleep */
1493 if (inta & CSR_INT_BIT_WAKEUP) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001494 D_ISR("Wakeup interrupt\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001495 il_rx_queue_update_write_ptr(il, &il->rxq);
1496 il_txq_update_write_ptr(il, &il->txq[0]);
1497 il_txq_update_write_ptr(il, &il->txq[1]);
1498 il_txq_update_write_ptr(il, &il->txq[2]);
1499 il_txq_update_write_ptr(il, &il->txq[3]);
1500 il_txq_update_write_ptr(il, &il->txq[4]);
1501 il_txq_update_write_ptr(il, &il->txq[5]);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001502
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001503 il->isr_stats.wakeup++;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001504 handled |= CSR_INT_BIT_WAKEUP;
1505 }
1506
1507 /* All uCode command responses, including Tx command responses,
1508 * Rx "responses" (frame-received notification), and other
1509 * notifications from uCode come through here*/
1510 if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001511 il3945_rx_handle(il);
1512 il->isr_stats.rx++;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001513 handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
1514 }
1515
1516 if (inta & CSR_INT_BIT_FH_TX) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001517 D_ISR("Tx interrupt\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001518 il->isr_stats.tx++;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001519
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001520 _il_wr(il, CSR_FH_INT_STATUS, (1 << 6));
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001521 il_wr(il, FH39_TCSR_CREDIT(FH39_SRVC_CHNL), 0x0);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001522 handled |= CSR_INT_BIT_FH_TX;
1523 }
1524
1525 if (inta & ~handled) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001526 IL_ERR("Unhandled INTA bits 0x%08x\n", inta & ~handled);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001527 il->isr_stats.unhandled++;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001528 }
1529
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001530 if (inta & ~il->inta_mask) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001531 IL_WARN("Disabled INTA bits 0x%08x were pending\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001532 inta & ~il->inta_mask);
Stanislaw Gruszka53143a12011-08-31 14:14:18 +02001533 IL_WARN(" with inta_fh = 0x%08x\n", inta_fh);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001534 }
1535
1536 /* Re-enable all interrupts */
1537 /* only Re-enable if disabled by irq */
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01001538 if (test_bit(S_INT_ENABLED, &il->status))
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001539 il_enable_interrupts(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001540
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001541#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001542 if (il_get_debug_level(il) & (IL_DL_ISR)) {
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001543 inta = _il_rd(il, CSR_INT);
1544 inta_mask = _il_rd(il, CSR_INT_MASK);
1545 inta_fh = _il_rd(il, CSR_FH_INT_STATUS);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001546 D_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001547 "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001548 }
1549#endif
1550}
1551
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001552static int
1553il3945_get_channels_for_scan(struct il_priv *il, enum ieee80211_band band,
1554 u8 is_active, u8 n_probes,
1555 struct il3945_scan_channel *scan_ch,
1556 struct ieee80211_vif *vif)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001557{
1558 struct ieee80211_channel *chan;
1559 const struct ieee80211_supported_band *sband;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001560 const struct il_channel_info *ch_info;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001561 u16 passive_dwell = 0;
1562 u16 active_dwell = 0;
1563 int added, i;
1564
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001565 sband = il_get_hw_mode(il, band);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001566 if (!sband)
1567 return 0;
1568
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001569 active_dwell = il_get_active_dwell_time(il, band, n_probes);
1570 passive_dwell = il_get_passive_dwell_time(il, band, vif);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001571
1572 if (passive_dwell <= active_dwell)
1573 passive_dwell = active_dwell + 1;
1574
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001575 for (i = 0, added = 0; i < il->scan_request->n_channels; i++) {
1576 chan = il->scan_request->channels[i];
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001577
1578 if (chan->band != band)
1579 continue;
1580
1581 scan_ch->channel = chan->hw_value;
1582
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001583 ch_info = il_get_channel_info(il, band, scan_ch->channel);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001584 if (!il_is_channel_valid(ch_info)) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001585 D_SCAN("Channel %d is INVALID for this band.\n",
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001586 scan_ch->channel);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001587 continue;
1588 }
1589
1590 scan_ch->active_dwell = cpu_to_le16(active_dwell);
1591 scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
1592 /* If passive , set up for auto-switch
1593 * and use long active_dwell time.
1594 */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001595 if (!is_active || il_is_channel_passive(ch_info) ||
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001596 (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
1597 scan_ch->type = 0; /* passive */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001598 if (IL_UCODE_API(il->ucode_ver) == 1)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001599 scan_ch->active_dwell =
1600 cpu_to_le16(passive_dwell - 1);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001601 } else {
1602 scan_ch->type = 1; /* active */
1603 }
1604
1605 /* Set direct probe bits. These may be used both for active
1606 * scan channels (probes gets sent right away),
1607 * or for passive channels (probes get se sent only after
1608 * hearing clear Rx packet).*/
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001609 if (IL_UCODE_API(il->ucode_ver) >= 2) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001610 if (n_probes)
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001611 scan_ch->type |= IL39_SCAN_PROBE_MASK(n_probes);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001612 } else {
1613 /* uCode v1 does not allow setting direct probe bits on
1614 * passive channel. */
1615 if ((scan_ch->type & 1) && n_probes)
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001616 scan_ch->type |= IL39_SCAN_PROBE_MASK(n_probes);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001617 }
1618
1619 /* Set txpower levels to defaults */
1620 scan_ch->tpc.dsp_atten = 110;
1621 /* scan_pwr_info->tpc.dsp_atten; */
1622
1623 /*scan_pwr_info->tpc.tx_gain; */
1624 if (band == IEEE80211_BAND_5GHZ)
1625 scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
1626 else {
1627 scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
1628 /* NOTE: if we were doing 6Mb OFDM for scans we'd use
1629 * power level:
1630 * scan_ch->tpc.tx_gain = ((1 << 5) | (2 << 3)) | 3;
1631 */
1632 }
1633
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001634 D_SCAN("Scanning %d [%s %d]\n", scan_ch->channel,
1635 (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE",
1636 (scan_ch->type & 1) ? active_dwell : passive_dwell);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001637
1638 scan_ch++;
1639 added++;
1640 }
1641
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001642 D_SCAN("total channels to scan %d\n", added);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001643 return added;
1644}
1645
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001646static void
1647il3945_init_hw_rates(struct il_priv *il, struct ieee80211_rate *rates)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001648{
1649 int i;
1650
Stanislaw Gruszka2eb05812011-08-26 16:07:43 +02001651 for (i = 0; i < RATE_COUNT_LEGACY; i++) {
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001652 rates[i].bitrate = il3945_rates[i].ieee * 5;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001653 rates[i].hw_value = i; /* Rate scaling will work on idxes */
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001654 rates[i].hw_value_short = i;
1655 rates[i].flags = 0;
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001656 if (i > IL39_LAST_OFDM_RATE || i < IL_FIRST_OFDM_RATE) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001657 /*
1658 * If CCK != 1M then set short preamble rate flag.
1659 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001660 rates[i].flags |=
1661 (il3945_rates[i].plcp ==
1662 10) ? 0 : IEEE80211_RATE_SHORT_PREAMBLE;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001663 }
1664 }
1665}
1666
1667/******************************************************************************
1668 *
1669 * uCode download functions
1670 *
1671 ******************************************************************************/
1672
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001673static void
1674il3945_dealloc_ucode_pci(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001675{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001676 il_free_fw_desc(il->pci_dev, &il->ucode_code);
1677 il_free_fw_desc(il->pci_dev, &il->ucode_data);
1678 il_free_fw_desc(il->pci_dev, &il->ucode_data_backup);
1679 il_free_fw_desc(il->pci_dev, &il->ucode_init);
1680 il_free_fw_desc(il->pci_dev, &il->ucode_init_data);
1681 il_free_fw_desc(il->pci_dev, &il->ucode_boot);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001682}
1683
1684/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001685 * il3945_verify_inst_full - verify runtime uCode image in card vs. host,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001686 * looking at all data.
1687 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001688static int
1689il3945_verify_inst_full(struct il_priv *il, __le32 * image, u32 len)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001690{
1691 u32 val;
1692 u32 save_len = len;
1693 int rc = 0;
1694 u32 errcnt;
1695
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001696 D_INFO("ucode inst image size is %u\n", len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001697
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001698 il_wr(il, HBUS_TARG_MEM_RADDR, IL39_RTC_INST_LOWER_BOUND);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001699
1700 errcnt = 0;
1701 for (; len > 0; len -= sizeof(u32), image++) {
1702 /* read data comes through single port, auto-incr addr */
1703 /* NOTE: Use the debugless read so we don't flood kernel log
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001704 * if IL_DL_IO is set */
Stanislaw Gruszka1c8cae52011-08-24 15:46:03 +02001705 val = _il_rd(il, HBUS_TARG_MEM_RDAT);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001706 if (val != le32_to_cpu(*image)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001707 IL_ERR("uCode INST section is invalid at "
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001708 "offset 0x%x, is 0x%x, s/b 0x%x\n",
1709 save_len - len, val, le32_to_cpu(*image));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001710 rc = -EIO;
1711 errcnt++;
1712 if (errcnt >= 20)
1713 break;
1714 }
1715 }
1716
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001717 if (!errcnt)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001718 D_INFO("ucode image in INSTRUCTION memory is good\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001719
1720 return rc;
1721}
1722
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001723/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001724 * il3945_verify_inst_sparse - verify runtime uCode image in card vs. host,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001725 * using sample data 100 bytes apart. If these sample points are good,
1726 * it's a pretty good bet that everything between them is good, too.
1727 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001728static int
1729il3945_verify_inst_sparse(struct il_priv *il, __le32 * image, u32 len)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001730{
1731 u32 val;
1732 int rc = 0;
1733 u32 errcnt = 0;
1734 u32 i;
1735
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001736 D_INFO("ucode inst image size is %u\n", len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001737
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001738 for (i = 0; i < len; i += 100, image += 100 / sizeof(u32)) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001739 /* read data comes through single port, auto-incr addr */
1740 /* NOTE: Use the debugless read so we don't flood kernel log
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001741 * if IL_DL_IO is set */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001742 il_wr(il, HBUS_TARG_MEM_RADDR, i + IL39_RTC_INST_LOWER_BOUND);
Stanislaw Gruszka1c8cae52011-08-24 15:46:03 +02001743 val = _il_rd(il, HBUS_TARG_MEM_RDAT);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001744 if (val != le32_to_cpu(*image)) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001745#if 0 /* Enable this if you want to see details */
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001746 IL_ERR("uCode INST section is invalid at "
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001747 "offset 0x%x, is 0x%x, s/b 0x%x\n", i, val,
1748 *image);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001749#endif
1750 rc = -EIO;
1751 errcnt++;
1752 if (errcnt >= 3)
1753 break;
1754 }
1755 }
1756
1757 return rc;
1758}
1759
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001760/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001761 * il3945_verify_ucode - determine which instruction image is in SRAM,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001762 * and verify its contents
1763 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001764static int
1765il3945_verify_ucode(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001766{
1767 __le32 *image;
1768 u32 len;
1769 int rc = 0;
1770
1771 /* Try bootstrap */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001772 image = (__le32 *) il->ucode_boot.v_addr;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001773 len = il->ucode_boot.len;
1774 rc = il3945_verify_inst_sparse(il, image, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001775 if (rc == 0) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001776 D_INFO("Bootstrap uCode is good in inst SRAM\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001777 return 0;
1778 }
1779
1780 /* Try initialize */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001781 image = (__le32 *) il->ucode_init.v_addr;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001782 len = il->ucode_init.len;
1783 rc = il3945_verify_inst_sparse(il, image, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001784 if (rc == 0) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001785 D_INFO("Initialize uCode is good in inst SRAM\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001786 return 0;
1787 }
1788
1789 /* Try runtime/protocol */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001790 image = (__le32 *) il->ucode_code.v_addr;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001791 len = il->ucode_code.len;
1792 rc = il3945_verify_inst_sparse(il, image, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001793 if (rc == 0) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001794 D_INFO("Runtime uCode is good in inst SRAM\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001795 return 0;
1796 }
1797
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001798 IL_ERR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001799
1800 /* Since nothing seems to match, show first several data entries in
1801 * instruction SRAM, so maybe visual inspection will give a clue.
1802 * Selection of bootstrap image (vs. other images) is arbitrary. */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001803 image = (__le32 *) il->ucode_boot.v_addr;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001804 len = il->ucode_boot.len;
1805 rc = il3945_verify_inst_full(il, image, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001806
1807 return rc;
1808}
1809
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001810static void
1811il3945_nic_start(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001812{
1813 /* Remove all resets to allow NIC to operate */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001814 _il_wr(il, CSR_RESET, 0);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001815}
1816
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001817#define IL3945_UCODE_GET(item) \
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001818static u32 il3945_ucode_get_##item(const struct il_ucode_header *ucode)\
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001819{ \
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001820 return le32_to_cpu(ucode->v1.item); \
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001821}
1822
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001823static u32
1824il3945_ucode_get_header_size(u32 api_ver)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001825{
1826 return 24;
1827}
1828
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001829static u8 *
1830il3945_ucode_get_data(const struct il_ucode_header *ucode)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001831{
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001832 return (u8 *) ucode->v1.data;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001833}
1834
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001835IL3945_UCODE_GET(inst_size);
1836IL3945_UCODE_GET(data_size);
1837IL3945_UCODE_GET(init_size);
1838IL3945_UCODE_GET(init_data_size);
1839IL3945_UCODE_GET(boot_size);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001840
1841/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001842 * il3945_read_ucode - Read uCode images from disk file.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001843 *
1844 * Copy into buffers for card to fetch via bus-mastering
1845 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001846static int
1847il3945_read_ucode(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001848{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001849 const struct il_ucode_header *ucode;
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01001850 int ret = -EINVAL, idx;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001851 const struct firmware *ucode_raw;
1852 /* firmware file name contains uCode/driver compatibility version */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001853 const char *name_pre = il->cfg->fw_name_pre;
1854 const unsigned int api_max = il->cfg->ucode_api_max;
1855 const unsigned int api_min = il->cfg->ucode_api_min;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001856 char buf[25];
1857 u8 *src;
1858 size_t len;
1859 u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
1860
1861 /* Ask kernel firmware_class module to get the boot firmware off disk.
1862 * request_firmware() is synchronous, file is in memory on return. */
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01001863 for (idx = api_max; idx >= api_min; idx--) {
1864 sprintf(buf, "%s%u%s", name_pre, idx, ".ucode");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001865 ret = request_firmware(&ucode_raw, buf, &il->pci_dev->dev);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001866 if (ret < 0) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001867 IL_ERR("%s firmware file req failed: %d\n", buf, ret);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001868 if (ret == -ENOENT)
1869 continue;
1870 else
1871 goto error;
1872 } else {
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01001873 if (idx < api_max)
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001874 IL_ERR("Loaded firmware %s, "
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001875 "which is deprecated. "
1876 " Please use API v%u instead.\n", buf,
1877 api_max);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001878 D_INFO("Got firmware '%s' file "
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001879 "(%zd bytes) from disk\n", buf, ucode_raw->size);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001880 break;
1881 }
1882 }
1883
1884 if (ret < 0)
1885 goto error;
1886
1887 /* Make sure that we got at least our header! */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001888 if (ucode_raw->size < il3945_ucode_get_header_size(1)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001889 IL_ERR("File size way too small!\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001890 ret = -EINVAL;
1891 goto err_release;
1892 }
1893
1894 /* Data from ucode file: header followed by uCode images */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001895 ucode = (struct il_ucode_header *)ucode_raw->data;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001896
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001897 il->ucode_ver = le32_to_cpu(ucode->ver);
1898 api_ver = IL_UCODE_API(il->ucode_ver);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001899 inst_size = il3945_ucode_get_inst_size(ucode);
1900 data_size = il3945_ucode_get_data_size(ucode);
1901 init_size = il3945_ucode_get_init_size(ucode);
1902 init_data_size = il3945_ucode_get_init_data_size(ucode);
1903 boot_size = il3945_ucode_get_boot_size(ucode);
1904 src = il3945_ucode_get_data(ucode);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001905
1906 /* api_ver should match the api version forming part of the
1907 * firmware filename ... but we don't check for that and only rely
1908 * on the API version read from firmware header from here on forward */
1909
1910 if (api_ver < api_min || api_ver > api_max) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001911 IL_ERR("Driver unable to support your firmware API. "
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001912 "Driver supports v%u, firmware is v%u.\n", api_max,
1913 api_ver);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001914 il->ucode_ver = 0;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001915 ret = -EINVAL;
1916 goto err_release;
1917 }
1918 if (api_ver != api_max)
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001919 IL_ERR("Firmware has old API version. Expected %u, "
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001920 "got %u. New firmware can be obtained "
1921 "from http://www.intellinuxwireless.org.\n", api_max,
1922 api_ver);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001923
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001924 IL_INFO("loaded firmware version %u.%u.%u.%u\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001925 IL_UCODE_MAJOR(il->ucode_ver), IL_UCODE_MINOR(il->ucode_ver),
1926 IL_UCODE_API(il->ucode_ver), IL_UCODE_SERIAL(il->ucode_ver));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001927
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001928 snprintf(il->hw->wiphy->fw_version, sizeof(il->hw->wiphy->fw_version),
1929 "%u.%u.%u.%u", IL_UCODE_MAJOR(il->ucode_ver),
1930 IL_UCODE_MINOR(il->ucode_ver), IL_UCODE_API(il->ucode_ver),
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001931 IL_UCODE_SERIAL(il->ucode_ver));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001932
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001933 D_INFO("f/w package hdr ucode version raw = 0x%x\n", il->ucode_ver);
1934 D_INFO("f/w package hdr runtime inst size = %u\n", inst_size);
1935 D_INFO("f/w package hdr runtime data size = %u\n", data_size);
1936 D_INFO("f/w package hdr init inst size = %u\n", init_size);
1937 D_INFO("f/w package hdr init data size = %u\n", init_data_size);
1938 D_INFO("f/w package hdr boot inst size = %u\n", boot_size);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001939
1940 /* Verify size of file vs. image size info in file's header */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001941 if (ucode_raw->size !=
1942 il3945_ucode_get_header_size(api_ver) + inst_size + data_size +
1943 init_size + init_data_size + boot_size) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001944
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001945 D_INFO("uCode file size %zd does not match expected size\n",
1946 ucode_raw->size);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001947 ret = -EINVAL;
1948 goto err_release;
1949 }
1950
1951 /* Verify that uCode images will fit in card's SRAM */
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001952 if (inst_size > IL39_MAX_INST_SIZE) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001953 D_INFO("uCode instr len %d too large to fit in\n", inst_size);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001954 ret = -EINVAL;
1955 goto err_release;
1956 }
1957
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001958 if (data_size > IL39_MAX_DATA_SIZE) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001959 D_INFO("uCode data len %d too large to fit in\n", data_size);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001960 ret = -EINVAL;
1961 goto err_release;
1962 }
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001963 if (init_size > IL39_MAX_INST_SIZE) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001964 D_INFO("uCode init instr len %d too large to fit in\n",
1965 init_size);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001966 ret = -EINVAL;
1967 goto err_release;
1968 }
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001969 if (init_data_size > IL39_MAX_DATA_SIZE) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001970 D_INFO("uCode init data len %d too large to fit in\n",
1971 init_data_size);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001972 ret = -EINVAL;
1973 goto err_release;
1974 }
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001975 if (boot_size > IL39_MAX_BSM_SIZE) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01001976 D_INFO("uCode boot instr len %d too large to fit in\n",
1977 boot_size);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001978 ret = -EINVAL;
1979 goto err_release;
1980 }
1981
1982 /* Allocate ucode buffers for card's bus-master loading ... */
1983
1984 /* Runtime instructions and 2 copies of data:
1985 * 1) unmodified from disk
1986 * 2) backup cache for save/restore during power-downs */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001987 il->ucode_code.len = inst_size;
1988 il_alloc_fw_desc(il->pci_dev, &il->ucode_code);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001989
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001990 il->ucode_data.len = data_size;
1991 il_alloc_fw_desc(il->pci_dev, &il->ucode_data);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001992
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001993 il->ucode_data_backup.len = data_size;
1994 il_alloc_fw_desc(il->pci_dev, &il->ucode_data_backup);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001995
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001996 if (!il->ucode_code.v_addr || !il->ucode_data.v_addr ||
1997 !il->ucode_data_backup.v_addr)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001998 goto err_pci_alloc;
1999
2000 /* Initialization instructions and data */
2001 if (init_size && init_data_size) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002002 il->ucode_init.len = init_size;
2003 il_alloc_fw_desc(il->pci_dev, &il->ucode_init);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002004
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002005 il->ucode_init_data.len = init_data_size;
2006 il_alloc_fw_desc(il->pci_dev, &il->ucode_init_data);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002007
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002008 if (!il->ucode_init.v_addr || !il->ucode_init_data.v_addr)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002009 goto err_pci_alloc;
2010 }
2011
2012 /* Bootstrap (instructions only, no data) */
2013 if (boot_size) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002014 il->ucode_boot.len = boot_size;
2015 il_alloc_fw_desc(il->pci_dev, &il->ucode_boot);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002016
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002017 if (!il->ucode_boot.v_addr)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002018 goto err_pci_alloc;
2019 }
2020
2021 /* Copy images into buffers for card's bus-master reads ... */
2022
2023 /* Runtime instructions (first block of data in file) */
2024 len = inst_size;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002025 D_INFO("Copying (but not loading) uCode instr len %zd\n", len);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002026 memcpy(il->ucode_code.v_addr, src, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002027 src += len;
2028
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002029 D_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002030 il->ucode_code.v_addr, (u32) il->ucode_code.p_addr);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002031
2032 /* Runtime data (2nd block)
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002033 * NOTE: Copy into backup buffer will be done in il3945_up() */
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002034 len = data_size;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002035 D_INFO("Copying (but not loading) uCode data len %zd\n", len);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002036 memcpy(il->ucode_data.v_addr, src, len);
2037 memcpy(il->ucode_data_backup.v_addr, src, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002038 src += len;
2039
2040 /* Initialization instructions (3rd block) */
2041 if (init_size) {
2042 len = init_size;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002043 D_INFO("Copying (but not loading) init instr len %zd\n", len);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002044 memcpy(il->ucode_init.v_addr, src, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002045 src += len;
2046 }
2047
2048 /* Initialization data (4th block) */
2049 if (init_data_size) {
2050 len = init_data_size;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002051 D_INFO("Copying (but not loading) init data len %zd\n", len);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002052 memcpy(il->ucode_init_data.v_addr, src, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002053 src += len;
2054 }
2055
2056 /* Bootstrap instructions (5th block) */
2057 len = boot_size;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002058 D_INFO("Copying (but not loading) boot instr len %zd\n", len);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002059 memcpy(il->ucode_boot.v_addr, src, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002060
2061 /* We have our copies now, allow OS release its copies */
2062 release_firmware(ucode_raw);
2063 return 0;
2064
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002065err_pci_alloc:
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002066 IL_ERR("failed to allocate pci memory\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002067 ret = -ENOMEM;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002068 il3945_dealloc_ucode_pci(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002069
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002070err_release:
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002071 release_firmware(ucode_raw);
2072
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002073error:
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002074 return ret;
2075}
2076
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002077/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002078 * il3945_set_ucode_ptrs - Set uCode address location
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002079 *
2080 * Tell initialization uCode where to find runtime uCode.
2081 *
2082 * BSM registers initially contain pointers to initialization uCode.
2083 * We need to replace them to load runtime uCode inst and data,
2084 * and to save runtime data when powering down.
2085 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002086static int
2087il3945_set_ucode_ptrs(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002088{
2089 dma_addr_t pinst;
2090 dma_addr_t pdata;
2091
2092 /* bits 31:0 for 3945 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002093 pinst = il->ucode_code.p_addr;
2094 pdata = il->ucode_data_backup.p_addr;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002095
2096 /* Tell bootstrap uCode where to find image to load */
Stanislaw Gruszkadb54eb52011-08-24 21:06:33 +02002097 il_wr_prph(il, BSM_DRAM_INST_PTR_REG, pinst);
2098 il_wr_prph(il, BSM_DRAM_DATA_PTR_REG, pdata);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002099 il_wr_prph(il, BSM_DRAM_DATA_BYTECOUNT_REG, il->ucode_data.len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002100
2101 /* Inst byte count must be last to set up, bit 31 signals uCode
2102 * that all new ptr/size info is in place */
Stanislaw Gruszkadb54eb52011-08-24 21:06:33 +02002103 il_wr_prph(il, BSM_DRAM_INST_BYTECOUNT_REG,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002104 il->ucode_code.len | BSM_DRAM_INST_LOAD);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002105
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002106 D_INFO("Runtime uCode pointers are set.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002107
2108 return 0;
2109}
2110
2111/**
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02002112 * il3945_init_alive_start - Called after N_ALIVE notification received
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002113 *
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02002114 * Called after N_ALIVE notification received from "initialize" uCode.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002115 *
2116 * Tell "initialize" uCode to go ahead and load the runtime uCode.
2117 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002118static void
2119il3945_init_alive_start(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002120{
2121 /* Check alive response for "valid" sign from uCode */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002122 if (il->card_alive_init.is_valid != UCODE_VALID_OK) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002123 /* We had an error bringing up the hardware, so take it
2124 * all the way back down so we can try again */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002125 D_INFO("Initialize Alive failed.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002126 goto restart;
2127 }
2128
2129 /* Bootstrap uCode has loaded initialize uCode ... verify inst image.
2130 * This is a paranoid check, because we would not have gotten the
2131 * "initialize" alive if code weren't properly loaded. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002132 if (il3945_verify_ucode(il)) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002133 /* Runtime instruction load was bad;
2134 * take it all the way back down so we can try again */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002135 D_INFO("Bad \"initialize\" uCode load.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002136 goto restart;
2137 }
2138
2139 /* Send pointers to protocol/runtime uCode image ... init code will
2140 * load and launch runtime uCode, which will send us another "Alive"
2141 * notification. */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002142 D_INFO("Initialization Alive received.\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002143 if (il3945_set_ucode_ptrs(il)) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002144 /* Runtime instruction load won't happen;
2145 * take it all the way back down so we can try again */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002146 D_INFO("Couldn't set up uCode pointers.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002147 goto restart;
2148 }
2149 return;
2150
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002151restart:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002152 queue_work(il->workqueue, &il->restart);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002153}
2154
2155/**
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02002156 * il3945_alive_start - called after N_ALIVE notification received
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002157 * from protocol/runtime uCode (initialization uCode's
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002158 * Alive gets handled by il3945_init_alive_start()).
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002159 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002160static void
2161il3945_alive_start(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002162{
2163 int thermal_spin = 0;
2164 u32 rfkill;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002165
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002166 D_INFO("Runtime Alive received.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002167
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002168 if (il->card_alive.is_valid != UCODE_VALID_OK) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002169 /* We had an error bringing up the hardware, so take it
2170 * all the way back down so we can try again */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002171 D_INFO("Alive failed.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002172 goto restart;
2173 }
2174
2175 /* Initialize uCode has loaded Runtime uCode ... verify inst image.
2176 * This is a paranoid check, because we would not have gotten the
2177 * "runtime" alive if code weren't properly loaded. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002178 if (il3945_verify_ucode(il)) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002179 /* Runtime instruction load was bad;
2180 * take it all the way back down so we can try again */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002181 D_INFO("Bad runtime uCode load.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002182 goto restart;
2183 }
2184
Stanislaw Gruszkadb54eb52011-08-24 21:06:33 +02002185 rfkill = il_rd_prph(il, APMG_RFKILL_REG);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002186 D_INFO("RFKILL status: 0x%x\n", rfkill);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002187
2188 if (rfkill & 0x1) {
Stanislaw Gruszkabc269a82012-02-13 11:23:29 +01002189 clear_bit(S_RFKILL, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002190 /* if RFKILL is not on, then wait for thermal
2191 * sensor in adapter to kick in */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002192 while (il3945_hw_get_temperature(il) == 0) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002193 thermal_spin++;
2194 udelay(10);
2195 }
2196
2197 if (thermal_spin)
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002198 D_INFO("Thermal calibration took %dus\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002199 thermal_spin * 10);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002200 } else
Stanislaw Gruszkabc269a82012-02-13 11:23:29 +01002201 set_bit(S_RFKILL, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002202
2203 /* After the ALIVE response, we can send commands to 3945 uCode */
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002204 set_bit(S_ALIVE, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002205
2206 /* Enable watchdog to monitor the driver tx queues */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002207 il_setup_watchdog(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002208
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002209 if (il_is_rfkill(il))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002210 return;
2211
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002212 ieee80211_wake_queues(il->hw);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002213
Stanislaw Gruszka2eb05812011-08-26 16:07:43 +02002214 il->active_rate = RATES_MASK_3945;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002215
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002216 il_power_update_mode(il, true);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002217
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01002218 if (il_is_associated(il)) {
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002219 struct il3945_rxon_cmd *active_rxon =
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002220 (struct il3945_rxon_cmd *)(&il->active);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002221
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002222 il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002223 active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
2224 } else {
2225 /* Initialize our rx_config data */
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002226 il_connection_init_rx_config(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002227 }
2228
2229 /* Configure Bluetooth device coexistence support */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002230 il_send_bt_config(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002231
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002232 set_bit(S_READY, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002233
2234 /* Configure the adapter for unassociated operation */
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002235 il3945_commit_rxon(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002236
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002237 il3945_reg_txpower_periodic(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002238
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002239 D_INFO("ALIVE processing complete.\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002240 wake_up(&il->wait_command_queue);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002241
2242 return;
2243
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002244restart:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002245 queue_work(il->workqueue, &il->restart);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002246}
2247
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002248static void il3945_cancel_deferred_work(struct il_priv *il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002249
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002250static void
2251__il3945_down(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002252{
2253 unsigned long flags;
2254 int exit_pending;
2255
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002256 D_INFO(DRV_NAME " is going down\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002257
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002258 il_scan_cancel_timeout(il, 200);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002259
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002260 exit_pending = test_and_set_bit(S_EXIT_PENDING, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002261
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002262 /* Stop TX queues watchdog. We need to have S_EXIT_PENDING bit set
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002263 * to prevent rearm timer */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002264 del_timer_sync(&il->watchdog);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002265
2266 /* Station information will now be cleared in device */
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002267 il_clear_ucode_stations(il);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002268 il_dealloc_bcast_stations(il);
2269 il_clear_driver_stations(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002270
2271 /* Unblock any waiting calls */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002272 wake_up_all(&il->wait_command_queue);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002273
2274 /* Wipe out the EXIT_PENDING status bit if we are not actually
2275 * exiting the module */
2276 if (!exit_pending)
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002277 clear_bit(S_EXIT_PENDING, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002278
2279 /* stop and reset the on-board processor */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002280 _il_wr(il, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002281
2282 /* tell the device to stop sending interrupts */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002283 spin_lock_irqsave(&il->lock, flags);
2284 il_disable_interrupts(il);
2285 spin_unlock_irqrestore(&il->lock, flags);
2286 il3945_synchronize_irq(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002287
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002288 if (il->mac80211_registered)
2289 ieee80211_stop_queues(il->hw);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002290
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002291 /* If we have not previously called il3945_init() then
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002292 * clear all bits but the RF Kill bits and return */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002293 if (!il_is_init(il)) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002294 il->status =
Stanislaw Gruszkabc269a82012-02-13 11:23:29 +01002295 test_bit(S_RFKILL, &il->status) << S_RFKILL |
Stanislaw Gruszkac37281a2012-02-13 11:23:23 +01002296 test_bit(S_GEO_CONFIGURED, &il->status) << S_GEO_CONFIGURED |
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002297 test_bit(S_EXIT_PENDING, &il->status) << S_EXIT_PENDING;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002298 goto exit;
2299 }
2300
2301 /* ...otherwise clear out all the status bits but the RF Kill
2302 * bit and continue taking the NIC down. */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002303 il->status &=
Stanislaw Gruszkabc269a82012-02-13 11:23:29 +01002304 test_bit(S_RFKILL, &il->status) << S_RFKILL |
Stanislaw Gruszkac37281a2012-02-13 11:23:23 +01002305 test_bit(S_GEO_CONFIGURED, &il->status) << S_GEO_CONFIGURED |
2306 test_bit(S_FW_ERROR, &il->status) << S_FW_ERROR |
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002307 test_bit(S_EXIT_PENDING, &il->status) << S_EXIT_PENDING;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002308
Stanislaw Gruszka775ed8a2012-02-13 11:23:24 +01002309 /*
2310 * We disabled and synchronized interrupt, and priv->mutex is taken, so
2311 * here is the only thread which will program device registers, but
2312 * still have lockdep assertions, so we are taking reg_lock.
2313 */
2314 spin_lock_irq(&il->reg_lock);
2315 /* FIXME: il_grab_nic_access if rfkill is off ? */
2316
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002317 il3945_hw_txq_ctx_stop(il);
2318 il3945_hw_rxq_stop(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002319 /* Power-down device's busmaster DMA clocks */
Stanislaw Gruszka775ed8a2012-02-13 11:23:24 +01002320 _il_wr_prph(il, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002321 udelay(5);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002322 /* Stop the device, and put it in low power state */
Stanislaw Gruszka775ed8a2012-02-13 11:23:24 +01002323 _il_apm_stop(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002324
Stanislaw Gruszka775ed8a2012-02-13 11:23:24 +01002325 spin_unlock_irq(&il->reg_lock);
2326
2327 il3945_hw_txq_ctx_free(il);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002328exit:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002329 memset(&il->card_alive, 0, sizeof(struct il_alive_resp));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002330
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002331 if (il->beacon_skb)
2332 dev_kfree_skb(il->beacon_skb);
2333 il->beacon_skb = NULL;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002334
2335 /* clear out any free frames */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002336 il3945_clear_free_frames(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002337}
2338
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002339static void
2340il3945_down(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002341{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002342 mutex_lock(&il->mutex);
2343 __il3945_down(il);
2344 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002345
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002346 il3945_cancel_deferred_work(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002347}
2348
2349#define MAX_HW_RESTARTS 5
2350
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002351static int
2352il3945_alloc_bcast_station(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002353{
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002354 unsigned long flags;
2355 u8 sta_id;
2356
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002357 spin_lock_irqsave(&il->sta_lock, flags);
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002358 sta_id = il_prep_station(il, il_bcast_addr, false, NULL);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002359 if (sta_id == IL_INVALID_STATION) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002360 IL_ERR("Unable to prepare broadcast station\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002361 spin_unlock_irqrestore(&il->sta_lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002362
2363 return -EINVAL;
2364 }
2365
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002366 il->stations[sta_id].used |= IL_STA_DRIVER_ACTIVE;
2367 il->stations[sta_id].used |= IL_STA_BCAST;
2368 spin_unlock_irqrestore(&il->sta_lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002369
2370 return 0;
2371}
2372
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002373static int
2374__il3945_up(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002375{
2376 int rc, i;
2377
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002378 rc = il3945_alloc_bcast_station(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002379 if (rc)
2380 return rc;
2381
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002382 if (test_bit(S_EXIT_PENDING, &il->status)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002383 IL_WARN("Exit pending; will not bring the NIC up\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002384 return -EIO;
2385 }
2386
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002387 if (!il->ucode_data_backup.v_addr || !il->ucode_data.v_addr) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002388 IL_ERR("ucode not available for device bring up\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002389 return -EIO;
2390 }
2391
2392 /* If platform's RF_KILL switch is NOT set to KILL */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002393 if (_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
Stanislaw Gruszkabc269a82012-02-13 11:23:29 +01002394 clear_bit(S_RFKILL, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002395 else {
Stanislaw Gruszkabc269a82012-02-13 11:23:29 +01002396 set_bit(S_RFKILL, &il->status);
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002397 IL_WARN("Radio disabled by HW RF Kill switch\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002398 return -ENODEV;
2399 }
2400
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002401 _il_wr(il, CSR_INT, 0xFFFFFFFF);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002402
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002403 rc = il3945_hw_nic_init(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002404 if (rc) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002405 IL_ERR("Unable to int nic\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002406 return rc;
2407 }
2408
2409 /* make sure rfkill handshake bits are cleared */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002410 _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002411 _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002412
2413 /* clear (again), then enable host interrupts */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002414 _il_wr(il, CSR_INT, 0xFFFFFFFF);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002415 il_enable_interrupts(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002416
2417 /* really make sure rfkill handshake bits are cleared */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002418 _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
2419 _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002420
2421 /* Copy original ucode data image from disk into backup cache.
2422 * This will be used to initialize the on-board processor's
2423 * data SRAM for a clean start when the runtime program first loads. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002424 memcpy(il->ucode_data_backup.v_addr, il->ucode_data.v_addr,
2425 il->ucode_data.len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002426
2427 /* We return success when we resume from suspend and rf_kill is on. */
Stanislaw Gruszkabc269a82012-02-13 11:23:29 +01002428 if (test_bit(S_RFKILL, &il->status))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002429 return 0;
2430
2431 for (i = 0; i < MAX_HW_RESTARTS; i++) {
2432
2433 /* load bootstrap state machine,
2434 * load bootstrap program into processor's memory,
2435 * prepare to load the "initialize" uCode */
Stanislaw Gruszka1600b872012-02-13 11:23:18 +01002436 rc = il->ops->load_ucode(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002437
2438 if (rc) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002439 IL_ERR("Unable to set up bootstrap uCode: %d\n", rc);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002440 continue;
2441 }
2442
2443 /* start card; "initialize" will load runtime ucode */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002444 il3945_nic_start(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002445
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002446 D_INFO(DRV_NAME " is coming up\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002447
2448 return 0;
2449 }
2450
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002451 set_bit(S_EXIT_PENDING, &il->status);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002452 __il3945_down(il);
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002453 clear_bit(S_EXIT_PENDING, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002454
2455 /* tried to restart and config the device for as long as our
2456 * patience could withstand */
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002457 IL_ERR("Unable to initialize device after %d attempts.\n", i);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002458 return -EIO;
2459}
2460
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002461/*****************************************************************************
2462 *
2463 * Workqueue callbacks
2464 *
2465 *****************************************************************************/
2466
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002467static void
2468il3945_bg_init_alive_start(struct work_struct *data)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002469{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002470 struct il_priv *il =
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002471 container_of(data, struct il_priv, init_alive_start.work);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002472
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002473 mutex_lock(&il->mutex);
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002474 if (test_bit(S_EXIT_PENDING, &il->status))
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002475 goto out;
2476
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002477 il3945_init_alive_start(il);
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002478out:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002479 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002480}
2481
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002482static void
2483il3945_bg_alive_start(struct work_struct *data)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002484{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002485 struct il_priv *il =
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002486 container_of(data, struct il_priv, alive_start.work);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002487
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002488 mutex_lock(&il->mutex);
Stanislaw Gruszka210787e2012-03-08 13:16:01 +01002489 if (test_bit(S_EXIT_PENDING, &il->status) || il->txq == NULL)
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002490 goto out;
2491
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002492 il3945_alive_start(il);
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002493out:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002494 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002495}
2496
2497/*
2498 * 3945 cannot interrupt driver when hardware rf kill switch toggles;
2499 * driver must poll CSR_GP_CNTRL_REG register for change. This register
2500 * *is* readable even when device has been SW_RESET into low power mode
2501 * (e.g. during RF KILL).
2502 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002503static void
2504il3945_rfkill_poll(struct work_struct *data)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002505{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002506 struct il_priv *il =
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002507 container_of(data, struct il_priv, _3945.rfkill_poll.work);
Stanislaw Gruszkabc269a82012-02-13 11:23:29 +01002508 bool old_rfkill = test_bit(S_RFKILL, &il->status);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002509 bool new_rfkill =
2510 !(_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002511
2512 if (new_rfkill != old_rfkill) {
2513 if (new_rfkill)
Stanislaw Gruszkabc269a82012-02-13 11:23:29 +01002514 set_bit(S_RFKILL, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002515 else
Stanislaw Gruszkabc269a82012-02-13 11:23:29 +01002516 clear_bit(S_RFKILL, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002517
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002518 wiphy_rfkill_set_hw_state(il->hw->wiphy, new_rfkill);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002519
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002520 D_RF_KILL("RF_KILL bit toggled to %s.\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002521 new_rfkill ? "disable radio" : "enable radio");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002522 }
2523
2524 /* Keep this running, even if radio now enabled. This will be
2525 * cancelled in mac_start() if system decides to start again */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002526 queue_delayed_work(il->workqueue, &il->_3945.rfkill_poll,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002527 round_jiffies_relative(2 * HZ));
2528
2529}
2530
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002531int
2532il3945_request_scan(struct il_priv *il, struct ieee80211_vif *vif)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002533{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002534 struct il_host_cmd cmd = {
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02002535 .id = C_SCAN,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002536 .len = sizeof(struct il3945_scan_cmd),
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002537 .flags = CMD_SIZE_HUGE,
2538 };
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002539 struct il3945_scan_cmd *scan;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002540 u8 n_probes = 0;
2541 enum ieee80211_band band;
2542 bool is_active = false;
2543 int ret;
Stanislaw Gruszkadd6d2a82011-06-08 15:28:26 +02002544 u16 len;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002545
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002546 lockdep_assert_held(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002547
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002548 if (!il->scan_cmd) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002549 il->scan_cmd =
2550 kmalloc(sizeof(struct il3945_scan_cmd) + IL_MAX_SCAN_SIZE,
2551 GFP_KERNEL);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002552 if (!il->scan_cmd) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002553 D_SCAN("Fail to allocate scan memory\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002554 return -ENOMEM;
2555 }
2556 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002557 scan = il->scan_cmd;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002558 memset(scan, 0, sizeof(struct il3945_scan_cmd) + IL_MAX_SCAN_SIZE);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002559
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002560 scan->quiet_plcp_th = IL_PLCP_QUIET_THRESH;
2561 scan->quiet_time = IL_ACTIVE_QUIET_TIME;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002562
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01002563 if (il_is_associated(il)) {
Stanislaw Gruszkadd6d2a82011-06-08 15:28:26 +02002564 u16 interval;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002565 u32 extra;
2566 u32 suspend_time = 100;
2567 u32 scan_suspend_time = 100;
2568
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002569 D_INFO("Scanning while associated...\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002570
Stanislaw Gruszkadd6d2a82011-06-08 15:28:26 +02002571 interval = vif->bss_conf.beacon_int;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002572
2573 scan->suspend_time = 0;
2574 scan->max_out_time = cpu_to_le32(200 * 1024);
2575 if (!interval)
2576 interval = suspend_time;
2577 /*
2578 * suspend time format:
2579 * 0-19: beacon interval in usec (time before exec.)
2580 * 20-23: 0
2581 * 24-31: number of beacons (suspend between channels)
2582 */
2583
2584 extra = (suspend_time / interval) << 24;
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002585 scan_suspend_time =
2586 0xFF0FFFFF & (extra | ((suspend_time % interval) * 1024));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002587
2588 scan->suspend_time = cpu_to_le32(scan_suspend_time);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002589 D_SCAN("suspend_time 0x%X beacon interval %d\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002590 scan_suspend_time, interval);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002591 }
2592
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002593 if (il->scan_request->n_ssids) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002594 int i, p = 0;
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002595 D_SCAN("Kicking off active scan\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002596 for (i = 0; i < il->scan_request->n_ssids; i++) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002597 /* always does wildcard anyway */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002598 if (!il->scan_request->ssids[i].ssid_len)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002599 continue;
2600 scan->direct_scan[p].id = WLAN_EID_SSID;
2601 scan->direct_scan[p].len =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002602 il->scan_request->ssids[i].ssid_len;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002603 memcpy(scan->direct_scan[p].ssid,
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002604 il->scan_request->ssids[i].ssid,
2605 il->scan_request->ssids[i].ssid_len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002606 n_probes++;
2607 p++;
2608 }
2609 is_active = true;
2610 } else
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002611 D_SCAN("Kicking off passive scan.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002612
2613 /* We don't build a direct scan probe request; the uCode will do
2614 * that based on the direct_mask added to each channel entry */
2615 scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
Stanislaw Gruszkab16db502012-02-03 17:31:44 +01002616 scan->tx_cmd.sta_id = il->hw_params.bcast_id;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002617 scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
2618
2619 /* flags + rate selection */
2620
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002621 switch (il->scan_band) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002622 case IEEE80211_BAND_2GHZ:
2623 scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
Stanislaw Gruszka2eb05812011-08-26 16:07:43 +02002624 scan->tx_cmd.rate = RATE_1M_PLCP;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002625 band = IEEE80211_BAND_2GHZ;
2626 break;
2627 case IEEE80211_BAND_5GHZ:
Stanislaw Gruszka2eb05812011-08-26 16:07:43 +02002628 scan->tx_cmd.rate = RATE_6M_PLCP;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002629 band = IEEE80211_BAND_5GHZ;
2630 break;
2631 default:
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002632 IL_WARN("Invalid scan band\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002633 return -EIO;
2634 }
2635
2636 /*
Stanislaw Gruszka68acc4a2011-12-23 08:13:50 +01002637 * If active scaning is requested but a certain channel is marked
2638 * passive, we can do active scanning if we detect transmissions. For
2639 * passive only scanning disable switching to active on any channel.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002640 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002641 scan->good_CRC_th =
Stanislaw Gruszka68acc4a2011-12-23 08:13:50 +01002642 is_active ? IL_GOOD_CRC_TH_DEFAULT : IL_GOOD_CRC_TH_NEVER;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002643
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002644 len =
2645 il_fill_probe_req(il, (struct ieee80211_mgmt *)scan->data,
2646 vif->addr, il->scan_request->ie,
2647 il->scan_request->ie_len,
2648 IL_MAX_SCAN_SIZE - sizeof(*scan));
Stanislaw Gruszkadd6d2a82011-06-08 15:28:26 +02002649 scan->tx_cmd.len = cpu_to_le16(len);
2650
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002651 /* select Rx antennas */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002652 scan->flags |= il3945_get_antenna_flags(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002653
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002654 scan->channel_count =
2655 il3945_get_channels_for_scan(il, band, is_active, n_probes,
2656 (void *)&scan->data[len], vif);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002657 if (scan->channel_count == 0) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002658 D_SCAN("channel count %d\n", scan->channel_count);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002659 return -EIO;
2660 }
2661
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002662 cmd.len +=
2663 le16_to_cpu(scan->tx_cmd.len) +
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002664 scan->channel_count * sizeof(struct il3945_scan_channel);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002665 cmd.data = scan;
2666 scan->len = cpu_to_le16(cmd.len);
2667
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002668 set_bit(S_SCAN_HW, &il->status);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002669 ret = il_send_cmd_sync(il, &cmd);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002670 if (ret)
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002671 clear_bit(S_SCAN_HW, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002672 return ret;
2673}
2674
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002675void
2676il3945_post_scan(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002677{
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002678 /*
2679 * Since setting the RXON may have been deferred while
2680 * performing the scan, fire one off if needed
2681 */
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002682 if (memcmp(&il->staging, &il->active, sizeof(il->staging)))
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002683 il3945_commit_rxon(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002684}
2685
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002686static void
2687il3945_bg_restart(struct work_struct *data)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002688{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002689 struct il_priv *il = container_of(data, struct il_priv, restart);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002690
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002691 if (test_bit(S_EXIT_PENDING, &il->status))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002692 return;
2693
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002694 if (test_and_clear_bit(S_FW_ERROR, &il->status)) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002695 mutex_lock(&il->mutex);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002696 il->is_open = 0;
2697 mutex_unlock(&il->mutex);
2698 il3945_down(il);
2699 ieee80211_restart_hw(il->hw);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002700 } else {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002701 il3945_down(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002702
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002703 mutex_lock(&il->mutex);
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002704 if (test_bit(S_EXIT_PENDING, &il->status)) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002705 mutex_unlock(&il->mutex);
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002706 return;
2707 }
2708
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002709 __il3945_up(il);
2710 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002711 }
2712}
2713
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002714static void
2715il3945_bg_rx_replenish(struct work_struct *data)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002716{
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002717 struct il_priv *il = container_of(data, struct il_priv, rx_replenish);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002718
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002719 mutex_lock(&il->mutex);
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002720 if (test_bit(S_EXIT_PENDING, &il->status))
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002721 goto out;
2722
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002723 il3945_rx_replenish(il);
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002724out:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002725 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002726}
2727
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002728void
2729il3945_post_associate(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002730{
2731 int rc = 0;
2732 struct ieee80211_conf *conf = NULL;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002733
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002734 if (!il->vif || !il->is_open)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002735 return;
2736
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002737 D_ASSOC("Associated as %d to: %pM\n", il->vif->bss_conf.aid,
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002738 il->active.bssid_addr);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002739
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002740 if (test_bit(S_EXIT_PENDING, &il->status))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002741 return;
2742
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002743 il_scan_cancel_timeout(il, 200);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002744
Stanislaw Gruszka6278dda2011-08-31 11:13:05 +02002745 conf = &il->hw->conf;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002746
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002747 il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002748 il3945_commit_rxon(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002749
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002750 rc = il_send_rxon_timing(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002751 if (rc)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002752 IL_WARN("C_RXON_TIMING failed - " "Attempting to continue.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002753
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002754 il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002755
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002756 il->staging.assoc_id = cpu_to_le16(il->vif->bss_conf.aid);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002757
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002758 D_ASSOC("assoc id %d beacon interval %d\n", il->vif->bss_conf.aid,
2759 il->vif->bss_conf.beacon_int);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002760
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002761 if (il->vif->bss_conf.use_short_preamble)
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002762 il->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002763 else
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002764 il->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002765
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002766 if (il->staging.flags & RXON_FLG_BAND_24G_MSK) {
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002767 if (il->vif->bss_conf.use_short_slot)
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002768 il->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002769 else
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002770 il->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002771 }
2772
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002773 il3945_commit_rxon(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002774
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002775 switch (il->vif->type) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002776 case NL80211_IFTYPE_STATION:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002777 il3945_rate_scale_init(il->hw, IL_AP_ID);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002778 break;
2779 case NL80211_IFTYPE_ADHOC:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002780 il3945_send_beacon_cmd(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002781 break;
2782 default:
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002783 IL_ERR("%s Should not be called in %d mode\n", __func__,
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002784 il->vif->type);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002785 break;
2786 }
2787}
2788
2789/*****************************************************************************
2790 *
2791 * mac80211 entry point functions
2792 *
2793 *****************************************************************************/
2794
2795#define UCODE_READY_TIMEOUT (2 * HZ)
2796
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002797static int
2798il3945_mac_start(struct ieee80211_hw *hw)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002799{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002800 struct il_priv *il = hw->priv;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002801 int ret;
2802
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002803 /* we should be verifying the device is ready to be opened */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002804 mutex_lock(&il->mutex);
Stanislaw Gruszka9ce7b732012-02-13 11:23:21 +01002805 D_MAC80211("enter\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002806
2807 /* fetch ucode file from disk, alloc and copy to bus-master buffers ...
2808 * ucode filename and max sizes are card-specific. */
2809
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002810 if (!il->ucode_code.len) {
2811 ret = il3945_read_ucode(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002812 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002813 IL_ERR("Could not read microcode: %d\n", ret);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002814 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002815 goto out_release_irq;
2816 }
2817 }
2818
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002819 ret = __il3945_up(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002820
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002821 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002822
2823 if (ret)
2824 goto out_release_irq;
2825
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002826 D_INFO("Start UP work.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002827
2828 /* Wait for START_ALIVE from ucode. Otherwise callbacks from
2829 * mac80211 will not be run successfully. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002830 ret = wait_event_timeout(il->wait_command_queue,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002831 test_bit(S_READY, &il->status),
2832 UCODE_READY_TIMEOUT);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002833 if (!ret) {
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002834 if (!test_bit(S_READY, &il->status)) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002835 IL_ERR("Wait for START_ALIVE timeout after %dms.\n",
2836 jiffies_to_msecs(UCODE_READY_TIMEOUT));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002837 ret = -ETIMEDOUT;
2838 goto out_release_irq;
2839 }
2840 }
2841
2842 /* ucode is running and will send rfkill notifications,
2843 * no need to poll the killswitch state anymore */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002844 cancel_delayed_work(&il->_3945.rfkill_poll);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002845
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002846 il->is_open = 1;
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002847 D_MAC80211("leave\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002848 return 0;
2849
2850out_release_irq:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002851 il->is_open = 0;
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002852 D_MAC80211("leave - failed\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002853 return ret;
2854}
2855
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002856static void
2857il3945_mac_stop(struct ieee80211_hw *hw)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002858{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002859 struct il_priv *il = hw->priv;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002860
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002861 D_MAC80211("enter\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002862
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002863 if (!il->is_open) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002864 D_MAC80211("leave - skip\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002865 return;
2866 }
2867
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002868 il->is_open = 0;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002869
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002870 il3945_down(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002871
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002872 flush_workqueue(il->workqueue);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002873
2874 /* start polling the killswitch state again */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002875 queue_delayed_work(il->workqueue, &il->_3945.rfkill_poll,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002876 round_jiffies_relative(2 * HZ));
2877
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002878 D_MAC80211("leave\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002879}
2880
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002881static void
Thomas Huehn36323f82012-07-23 21:33:42 +02002882il3945_mac_tx(struct ieee80211_hw *hw,
2883 struct ieee80211_tx_control *control,
2884 struct sk_buff *skb)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002885{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002886 struct il_priv *il = hw->priv;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002887
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002888 D_MAC80211("enter\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002889
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002890 D_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002891 ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002892
Thomas Huehn36323f82012-07-23 21:33:42 +02002893 if (il3945_tx_skb(il, control->sta, skb))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002894 dev_kfree_skb_any(skb);
2895
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002896 D_MAC80211("leave\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002897}
2898
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002899void
2900il3945_config_ap(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002901{
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002902 struct ieee80211_vif *vif = il->vif;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002903 int rc = 0;
2904
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002905 if (test_bit(S_EXIT_PENDING, &il->status))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002906 return;
2907
2908 /* The following should be done only at AP bring up */
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01002909 if (!(il_is_associated(il))) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002910
2911 /* RXON - unassoc (to set timing command) */
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002912 il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002913 il3945_commit_rxon(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002914
2915 /* RXON Timing */
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002916 rc = il_send_rxon_timing(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002917 if (rc)
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02002918 IL_WARN("C_RXON_TIMING failed - "
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002919 "Attempting to continue.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002920
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002921 il->staging.assoc_id = 0;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002922
2923 if (vif->bss_conf.use_short_preamble)
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002924 il->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002925 else
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002926 il->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002927
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002928 if (il->staging.flags & RXON_FLG_BAND_24G_MSK) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002929 if (vif->bss_conf.use_short_slot)
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002930 il->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002931 else
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002932 il->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002933 }
2934 /* restore RXON assoc */
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01002935 il->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002936 il3945_commit_rxon(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002937 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002938 il3945_send_beacon_cmd(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002939}
2940
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01002941static int
2942il3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
2943 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
2944 struct ieee80211_key_conf *key)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002945{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002946 struct il_priv *il = hw->priv;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002947 int ret = 0;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002948 u8 sta_id = IL_INVALID_STATION;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002949 u8 static_key;
2950
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002951 D_MAC80211("enter\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002952
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002953 if (il3945_mod_params.sw_crypto) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002954 D_MAC80211("leave - hwcrypto disabled\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002955 return -EOPNOTSUPP;
2956 }
2957
2958 /*
2959 * To support IBSS RSN, don't program group keys in IBSS, the
2960 * hardware will then not attempt to decrypt the frames.
2961 */
2962 if (vif->type == NL80211_IFTYPE_ADHOC &&
Stanislaw Gruszka9ce7b732012-02-13 11:23:21 +01002963 !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
2964 D_MAC80211("leave - IBSS RSN\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002965 return -EOPNOTSUPP;
Stanislaw Gruszka9ce7b732012-02-13 11:23:21 +01002966 }
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002967
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01002968 static_key = !il_is_associated(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002969
2970 if (!static_key) {
Stanislaw Gruszka83007192012-02-03 17:31:57 +01002971 sta_id = il_sta_id_or_broadcast(il, sta);
Stanislaw Gruszka9ce7b732012-02-13 11:23:21 +01002972 if (sta_id == IL_INVALID_STATION) {
2973 D_MAC80211("leave - station not found\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002974 return -EINVAL;
Stanislaw Gruszka9ce7b732012-02-13 11:23:21 +01002975 }
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002976 }
2977
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002978 mutex_lock(&il->mutex);
2979 il_scan_cancel_timeout(il, 100);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002980
2981 switch (cmd) {
2982 case SET_KEY:
2983 if (static_key)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002984 ret = il3945_set_static_key(il, key);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002985 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002986 ret = il3945_set_dynamic_key(il, key, sta_id);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002987 D_MAC80211("enable hwcrypto key\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002988 break;
2989 case DISABLE_KEY:
2990 if (static_key)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002991 ret = il3945_remove_static_key(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002992 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002993 ret = il3945_clear_sta_key_info(il, sta_id);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002994 D_MAC80211("disable hwcrypto key\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002995 break;
2996 default:
2997 ret = -EINVAL;
2998 }
2999
Stanislaw Gruszka9ce7b732012-02-13 11:23:21 +01003000 D_MAC80211("leave ret %d\n", ret);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003001 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003002
3003 return ret;
3004}
3005
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003006static int
3007il3945_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
3008 struct ieee80211_sta *sta)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003009{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003010 struct il_priv *il = hw->priv;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003011 struct il3945_sta_priv *sta_priv = (void *)sta->drv_priv;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003012 int ret;
3013 bool is_ap = vif->type == NL80211_IFTYPE_STATION;
3014 u8 sta_id;
3015
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003016 mutex_lock(&il->mutex);
Stanislaw Gruszka9ce7b732012-02-13 11:23:21 +01003017 D_INFO("station %pM\n", sta->addr);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003018 sta_priv->common.sta_id = IL_INVALID_STATION;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003019
Stanislaw Gruszka83007192012-02-03 17:31:57 +01003020 ret = il_add_station_common(il, sta->addr, is_ap, sta, &sta_id);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003021 if (ret) {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003022 IL_ERR("Unable to add station %pM (%d)\n", sta->addr, ret);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003023 /* Should we return success if return code is EEXIST ? */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003024 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003025 return ret;
3026 }
3027
3028 sta_priv->common.sta_id = sta_id;
3029
3030 /* Initialize rate scaling */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003031 D_INFO("Initializing rate scaling for station %pM\n", sta->addr);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003032 il3945_rs_rate_init(il, sta, sta_id);
3033 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003034
3035 return 0;
3036}
3037
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003038static void
3039il3945_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
3040 unsigned int *total_flags, u64 multicast)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003041{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003042 struct il_priv *il = hw->priv;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003043 __le32 filter_or = 0, filter_nand = 0;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003044
3045#define CHK(test, flag) do { \
3046 if (*total_flags & (test)) \
3047 filter_or |= (flag); \
3048 else \
3049 filter_nand |= (flag); \
3050 } while (0)
3051
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003052 D_MAC80211("Enter: changed: 0x%x, total: 0x%x\n", changed_flags,
3053 *total_flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003054
3055 CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
3056 CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
3057 CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
3058
3059#undef CHK
3060
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003061 mutex_lock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003062
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01003063 il->staging.filter_flags &= ~filter_nand;
3064 il->staging.filter_flags |= filter_or;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003065
3066 /*
3067 * Not committing directly because hardware can perform a scan,
3068 * but even if hw is ready, committing here breaks for some reason,
3069 * we'll eventually commit the filter flags change anyway.
3070 */
3071
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003072 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003073
3074 /*
3075 * Receiving all multicast frames is always enabled by the
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003076 * default flags setup in il_connection_init_rx_config()
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003077 * since we currently do not support programming multicast
3078 * filters into the device.
3079 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003080 *total_flags &=
3081 FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
3082 FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003083}
3084
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003085/*****************************************************************************
3086 *
3087 * sysfs attributes
3088 *
3089 *****************************************************************************/
3090
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003091#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003092
3093/*
3094 * The following adds a new attribute to the sysfs representation
3095 * of this device driver (i.e. a new file in /sys/bus/pci/drivers/iwl/)
3096 * used for controlling the debug level.
3097 *
3098 * See the level definitions in iwl for details.
3099 *
3100 * The debug_level being managed using sysfs below is a per device debug
3101 * level that is used instead of the global debug level if it (the per
3102 * device debug level) is set.
3103 */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003104static ssize_t
3105il3945_show_debug_level(struct device *d, struct device_attribute *attr,
3106 char *buf)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003107{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003108 struct il_priv *il = dev_get_drvdata(d);
3109 return sprintf(buf, "0x%08X\n", il_get_debug_level(il));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003110}
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003111
3112static ssize_t
3113il3945_store_debug_level(struct device *d, struct device_attribute *attr,
3114 const char *buf, size_t count)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003115{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003116 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003117 unsigned long val;
3118 int ret;
3119
3120 ret = strict_strtoul(buf, 0, &val);
3121 if (ret)
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003122 IL_INFO("%s is not in hex or decimal form.\n", buf);
Stanislaw Gruszka288f99542012-02-13 11:23:20 +01003123 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003124 il->debug_level = val;
Stanislaw Gruszka288f99542012-02-13 11:23:20 +01003125
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003126 return strnlen(buf, count);
3127}
3128
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003129static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, il3945_show_debug_level,
3130 il3945_store_debug_level);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003131
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003132#endif /* CONFIG_IWLEGACY_DEBUG */
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003133
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003134static ssize_t
3135il3945_show_temperature(struct device *d, struct device_attribute *attr,
3136 char *buf)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003137{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003138 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003139
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003140 if (!il_is_alive(il))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003141 return -EAGAIN;
3142
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003143 return sprintf(buf, "%d\n", il3945_hw_get_temperature(il));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003144}
3145
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003146static DEVICE_ATTR(temperature, S_IRUGO, il3945_show_temperature, NULL);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003147
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003148static ssize_t
3149il3945_show_tx_power(struct device *d, struct device_attribute *attr, char *buf)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003150{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003151 struct il_priv *il = dev_get_drvdata(d);
3152 return sprintf(buf, "%d\n", il->tx_power_user_lmt);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003153}
3154
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003155static ssize_t
3156il3945_store_tx_power(struct device *d, struct device_attribute *attr,
3157 const char *buf, size_t count)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003158{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003159 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003160 char *p = (char *)buf;
3161 u32 val;
3162
3163 val = simple_strtoul(p, &p, 10);
3164 if (p == buf)
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003165 IL_INFO(": %s is not in decimal form.\n", buf);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003166 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003167 il3945_hw_reg_set_txpower(il, val);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003168
3169 return count;
3170}
3171
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003172static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, il3945_show_tx_power,
3173 il3945_store_tx_power);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003174
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003175static ssize_t
3176il3945_show_flags(struct device *d, struct device_attribute *attr, char *buf)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003177{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003178 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003179
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01003180 return sprintf(buf, "0x%04X\n", il->active.flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003181}
3182
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003183static ssize_t
3184il3945_store_flags(struct device *d, struct device_attribute *attr,
3185 const char *buf, size_t count)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003186{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003187 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003188 u32 flags = simple_strtoul(buf, NULL, 0);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003189
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003190 mutex_lock(&il->mutex);
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01003191 if (le32_to_cpu(il->staging.flags) != flags) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003192 /* Cancel any currently running scans... */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003193 if (il_scan_cancel_timeout(il, 100))
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003194 IL_WARN("Could not cancel scan.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003195 else {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003196 D_INFO("Committing rxon.flags = 0x%04X\n", flags);
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01003197 il->staging.flags = cpu_to_le32(flags);
Stanislaw Gruszka83007192012-02-03 17:31:57 +01003198 il3945_commit_rxon(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003199 }
3200 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003201 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003202
3203 return count;
3204}
3205
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003206static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, il3945_show_flags,
3207 il3945_store_flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003208
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003209static ssize_t
3210il3945_show_filter_flags(struct device *d, struct device_attribute *attr,
3211 char *buf)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003212{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003213 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003214
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01003215 return sprintf(buf, "0x%04X\n", le32_to_cpu(il->active.filter_flags));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003216}
3217
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003218static ssize_t
3219il3945_store_filter_flags(struct device *d, struct device_attribute *attr,
3220 const char *buf, size_t count)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003221{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003222 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003223 u32 filter_flags = simple_strtoul(buf, NULL, 0);
3224
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003225 mutex_lock(&il->mutex);
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01003226 if (le32_to_cpu(il->staging.filter_flags) != filter_flags) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003227 /* Cancel any currently running scans... */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003228 if (il_scan_cancel_timeout(il, 100))
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003229 IL_WARN("Could not cancel scan.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003230 else {
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003231 D_INFO("Committing rxon.filter_flags = " "0x%04X\n",
3232 filter_flags);
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01003233 il->staging.filter_flags = cpu_to_le32(filter_flags);
Stanislaw Gruszka83007192012-02-03 17:31:57 +01003234 il3945_commit_rxon(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003235 }
3236 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003237 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003238
3239 return count;
3240}
3241
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003242static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, il3945_show_filter_flags,
3243 il3945_store_filter_flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003244
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003245static ssize_t
3246il3945_show_measurement(struct device *d, struct device_attribute *attr,
3247 char *buf)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003248{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003249 struct il_priv *il = dev_get_drvdata(d);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003250 struct il_spectrum_notification measure_report;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003251 u32 size = sizeof(measure_report), len = 0, ofs = 0;
Stanislaw Gruszka1722f8e2011-11-15 14:51:01 +01003252 u8 *data = (u8 *) &measure_report;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003253 unsigned long flags;
3254
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003255 spin_lock_irqsave(&il->lock, flags);
3256 if (!(il->measurement_status & MEASUREMENT_READY)) {
3257 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003258 return 0;
3259 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003260 memcpy(&measure_report, &il->measure_report, size);
3261 il->measurement_status = 0;
3262 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003263
Stanislaw Gruszka232913b2011-08-26 10:45:16 +02003264 while (size && PAGE_SIZE - len) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003265 hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
3266 PAGE_SIZE - len, 1);
3267 len = strlen(buf);
3268 if (PAGE_SIZE - len)
3269 buf[len++] = '\n';
3270
3271 ofs += 16;
3272 size -= min(size, 16U);
3273 }
3274
3275 return len;
3276}
3277
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003278static ssize_t
3279il3945_store_measurement(struct device *d, struct device_attribute *attr,
3280 const char *buf, size_t count)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003281{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003282 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003283 struct ieee80211_measurement_params params = {
Stanislaw Gruszkac8b03952012-02-03 17:31:37 +01003284 .channel = le16_to_cpu(il->active.channel),
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003285 .start_time = cpu_to_le64(il->_3945.last_tsf),
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003286 .duration = cpu_to_le16(1),
3287 };
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003288 u8 type = IL_MEASURE_BASIC;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003289 u8 buffer[32];
3290 u8 channel;
3291
3292 if (count) {
3293 char *p = buffer;
Chen Gang407ee232013-01-07 12:42:46 +08003294 strlcpy(buffer, buf, sizeof(buffer));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003295 channel = simple_strtoul(p, NULL, 0);
3296 if (channel)
3297 params.channel = channel;
3298
3299 p = buffer;
3300 while (*p && *p != ' ')
3301 p++;
3302 if (*p)
3303 type = simple_strtoul(p + 1, NULL, 0);
3304 }
3305
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003306 D_INFO("Invoking measurement of type %d on " "channel %d (for '%s')\n",
3307 type, params.channel, buf);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003308 il3945_get_measurement(il, &params, type);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003309
3310 return count;
3311}
3312
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003313static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR, il3945_show_measurement,
3314 il3945_store_measurement);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003315
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003316static ssize_t
3317il3945_store_retry_rate(struct device *d, struct device_attribute *attr,
3318 const char *buf, size_t count)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003319{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003320 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003321
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003322 il->retry_rate = simple_strtoul(buf, NULL, 0);
3323 if (il->retry_rate <= 0)
3324 il->retry_rate = 1;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003325
3326 return count;
3327}
3328
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003329static ssize_t
3330il3945_show_retry_rate(struct device *d, struct device_attribute *attr,
3331 char *buf)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003332{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003333 struct il_priv *il = dev_get_drvdata(d);
3334 return sprintf(buf, "%d", il->retry_rate);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003335}
3336
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003337static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, il3945_show_retry_rate,
3338 il3945_store_retry_rate);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003339
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003340static ssize_t
3341il3945_show_channels(struct device *d, struct device_attribute *attr, char *buf)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003342{
3343 /* all this shit doesn't belong into sysfs anyway */
3344 return 0;
3345}
3346
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003347static DEVICE_ATTR(channels, S_IRUSR, il3945_show_channels, NULL);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003348
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003349static ssize_t
3350il3945_show_antenna(struct device *d, struct device_attribute *attr, char *buf)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003351{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003352 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003353
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003354 if (!il_is_alive(il))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003355 return -EAGAIN;
3356
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003357 return sprintf(buf, "%d\n", il3945_mod_params.antenna);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003358}
3359
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003360static ssize_t
3361il3945_store_antenna(struct device *d, struct device_attribute *attr,
3362 const char *buf, size_t count)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003363{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003364 struct il_priv *il __maybe_unused = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003365 int ant;
3366
3367 if (count == 0)
3368 return 0;
3369
3370 if (sscanf(buf, "%1i", &ant) != 1) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003371 D_INFO("not in hex or decimal form.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003372 return count;
3373 }
3374
Stanislaw Gruszka232913b2011-08-26 10:45:16 +02003375 if (ant >= 0 && ant <= 2) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003376 D_INFO("Setting antenna select to %d.\n", ant);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003377 il3945_mod_params.antenna = (enum il3945_antenna)ant;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003378 } else
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003379 D_INFO("Bad antenna select value %d.\n", ant);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003380
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003381 return count;
3382}
3383
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003384static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, il3945_show_antenna,
3385 il3945_store_antenna);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003386
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003387static ssize_t
3388il3945_show_status(struct device *d, struct device_attribute *attr, char *buf)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003389{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003390 struct il_priv *il = dev_get_drvdata(d);
3391 if (!il_is_alive(il))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003392 return -EAGAIN;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003393 return sprintf(buf, "0x%08x\n", (int)il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003394}
3395
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003396static DEVICE_ATTR(status, S_IRUGO, il3945_show_status, NULL);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003397
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003398static ssize_t
3399il3945_dump_error_log(struct device *d, struct device_attribute *attr,
3400 const char *buf, size_t count)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003401{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003402 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003403 char *p = (char *)buf;
3404
3405 if (p[0] == '1')
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003406 il3945_dump_nic_error_log(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003407
3408 return strnlen(buf, count);
3409}
3410
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003411static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, il3945_dump_error_log);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003412
3413/*****************************************************************************
3414 *
3415 * driver setup and tear down
3416 *
3417 *****************************************************************************/
3418
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003419static void
3420il3945_setup_deferred_work(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003421{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003422 il->workqueue = create_singlethread_workqueue(DRV_NAME);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003423
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003424 init_waitqueue_head(&il->wait_command_queue);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003425
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003426 INIT_WORK(&il->restart, il3945_bg_restart);
3427 INIT_WORK(&il->rx_replenish, il3945_bg_rx_replenish);
3428 INIT_DELAYED_WORK(&il->init_alive_start, il3945_bg_init_alive_start);
3429 INIT_DELAYED_WORK(&il->alive_start, il3945_bg_alive_start);
3430 INIT_DELAYED_WORK(&il->_3945.rfkill_poll, il3945_rfkill_poll);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003431
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003432 il_setup_scan_deferred_work(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003433
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003434 il3945_hw_setup_deferred_work(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003435
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003436 init_timer(&il->watchdog);
3437 il->watchdog.data = (unsigned long)il;
3438 il->watchdog.function = il_bg_watchdog;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003439
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003440 tasklet_init(&il->irq_tasklet,
3441 (void (*)(unsigned long))il3945_irq_tasklet,
3442 (unsigned long)il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003443}
3444
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003445static void
3446il3945_cancel_deferred_work(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003447{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003448 il3945_hw_cancel_deferred_work(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003449
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003450 cancel_delayed_work_sync(&il->init_alive_start);
3451 cancel_delayed_work(&il->alive_start);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003452
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003453 il_cancel_scan_deferred_work(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003454}
3455
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003456static struct attribute *il3945_sysfs_entries[] = {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003457 &dev_attr_antenna.attr,
3458 &dev_attr_channels.attr,
3459 &dev_attr_dump_errors.attr,
3460 &dev_attr_flags.attr,
3461 &dev_attr_filter_flags.attr,
3462 &dev_attr_measurement.attr,
3463 &dev_attr_retry_rate.attr,
3464 &dev_attr_status.attr,
3465 &dev_attr_temperature.attr,
3466 &dev_attr_tx_power.attr,
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003467#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003468 &dev_attr_debug_level.attr,
3469#endif
3470 NULL
3471};
3472
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003473static struct attribute_group il3945_attribute_group = {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003474 .name = NULL, /* put in device directory */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003475 .attrs = il3945_sysfs_entries,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003476};
3477
Stanislaw Gruszkac39ae9f2012-02-03 17:31:58 +01003478struct ieee80211_ops il3945_mac_ops = {
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003479 .tx = il3945_mac_tx,
3480 .start = il3945_mac_start,
3481 .stop = il3945_mac_stop,
3482 .add_interface = il_mac_add_interface,
3483 .remove_interface = il_mac_remove_interface,
3484 .change_interface = il_mac_change_interface,
3485 .config = il_mac_config,
3486 .configure_filter = il3945_configure_filter,
3487 .set_key = il3945_mac_set_key,
3488 .conf_tx = il_mac_conf_tx,
3489 .reset_tsf = il_mac_reset_tsf,
3490 .bss_info_changed = il_mac_bss_info_changed,
3491 .hw_scan = il_mac_hw_scan,
3492 .sta_add = il3945_mac_sta_add,
3493 .sta_remove = il_mac_sta_remove,
3494 .tx_last_beacon = il_mac_tx_last_beacon,
Stanislaw Gruszka70277f42012-12-20 14:31:51 +01003495 .flush = il_mac_flush,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003496};
3497
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003498static int
3499il3945_init_drv(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003500{
3501 int ret;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003502 struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003503
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003504 il->retry_rate = 1;
3505 il->beacon_skb = NULL;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003506
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003507 spin_lock_init(&il->sta_lock);
3508 spin_lock_init(&il->hcmd_lock);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003509
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003510 INIT_LIST_HEAD(&il->free_frames);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003511
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003512 mutex_init(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003513
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003514 il->ieee_channels = NULL;
3515 il->ieee_rates = NULL;
3516 il->band = IEEE80211_BAND_2GHZ;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003517
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003518 il->iw_mode = NL80211_IFTYPE_STATION;
3519 il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003520
3521 /* initialize force reset */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003522 il->force_reset.reset_duration = IL_DELAY_NEXT_FORCE_FW_RELOAD;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003523
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003524 if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003525 IL_WARN("Unsupported EEPROM version: 0x%04X\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003526 eeprom->version);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003527 ret = -EINVAL;
3528 goto err;
3529 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003530 ret = il_init_channel_map(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003531 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003532 IL_ERR("initializing regulatory failed: %d\n", ret);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003533 goto err;
3534 }
3535
3536 /* Set up txpower settings in driver for all channels */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003537 if (il3945_txpower_set_from_eeprom(il)) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003538 ret = -EIO;
3539 goto err_free_channel_map;
3540 }
3541
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003542 ret = il_init_geos(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003543 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003544 IL_ERR("initializing geos failed: %d\n", ret);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003545 goto err_free_channel_map;
3546 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003547 il3945_init_hw_rates(il, il->ieee_rates);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003548
3549 return 0;
3550
3551err_free_channel_map:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003552 il_free_channel_map(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003553err:
3554 return ret;
3555}
3556
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003557#define IL3945_MAX_PROBE_REQUEST 200
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003558
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003559static int
3560il3945_setup_mac(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003561{
3562 int ret;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003563 struct ieee80211_hw *hw = il->hw;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003564
3565 hw->rate_control_algorithm = "iwl-3945-rs";
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003566 hw->sta_data_size = sizeof(struct il3945_sta_priv);
3567 hw->vif_data_size = sizeof(struct il_vif_priv);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003568
3569 /* Tell mac80211 our characteristics */
Stanislaw Gruszka07db8f82012-12-20 14:31:53 +01003570 hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SPECTRUM_MGMT |
3571 IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003572
Stanislaw Gruszka8c9c48d2012-02-03 17:31:50 +01003573 hw->wiphy->interface_modes =
3574 BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003575
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003576 hw->wiphy->flags |=
3577 WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS |
3578 WIPHY_FLAG_IBSS_RSN;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003579
Stanislaw Gruszka07db8f82012-12-20 14:31:53 +01003580 hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
3581
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003582 hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;
3583 /* we create the 802.11 header and a zero-length SSID element */
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003584 hw->wiphy->max_scan_ie_len = IL3945_MAX_PROBE_REQUEST - 24 - 2;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003585
3586 /* Default value; 4 EDCA QOS priorities */
3587 hw->queues = 4;
3588
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003589 if (il->bands[IEEE80211_BAND_2GHZ].n_channels)
3590 il->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003591 &il->bands[IEEE80211_BAND_2GHZ];
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003592
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003593 if (il->bands[IEEE80211_BAND_5GHZ].n_channels)
3594 il->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003595 &il->bands[IEEE80211_BAND_5GHZ];
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003596
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003597 il_leds_init(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003598
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003599 ret = ieee80211_register_hw(il->hw);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003600 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003601 IL_ERR("Failed to register hw (error %d)\n", ret);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003602 return ret;
3603 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003604 il->mac80211_registered = 1;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003605
3606 return 0;
3607}
3608
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003609static int
3610il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003611{
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003612 int err = 0;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003613 struct il_priv *il;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003614 struct ieee80211_hw *hw;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003615 struct il_cfg *cfg = (struct il_cfg *)(ent->driver_data);
3616 struct il3945_eeprom *eeprom;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003617 unsigned long flags;
3618
3619 /***********************
3620 * 1. Allocating HW data
3621 * ********************/
3622
Stanislaw Gruszkac39ae9f2012-02-03 17:31:58 +01003623 hw = ieee80211_alloc_hw(sizeof(struct il_priv), &il3945_mac_ops);
3624 if (!hw) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003625 err = -ENOMEM;
3626 goto out;
3627 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003628 il = hw->priv;
Stanislaw Gruszkac39ae9f2012-02-03 17:31:58 +01003629 il->hw = hw;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003630 SET_IEEE80211_DEV(hw, &pdev->dev);
3631
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003632 il->cmd_queue = IL39_CMD_QUEUE_NUM;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003633
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003634 /*
3635 * Disabling hardware scan means that mac80211 will perform scans
3636 * "the hard way", rather than using device's scan.
3637 */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003638 if (il3945_mod_params.disable_hw_scan) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003639 D_INFO("Disabling hw_scan\n");
Stanislaw Gruszkac39ae9f2012-02-03 17:31:58 +01003640 il3945_mac_ops.hw_scan = NULL;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003641 }
3642
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003643 D_INFO("*** LOAD DRIVER ***\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003644 il->cfg = cfg;
Stanislaw Gruszkac39ae9f2012-02-03 17:31:58 +01003645 il->ops = &il3945_ops;
Stanislaw Gruszka93b76542012-02-13 11:23:14 +01003646#ifdef CONFIG_IWLEGACY_DEBUGFS
3647 il->debugfs_ops = &il3945_debugfs_ops;
3648#endif
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003649 il->pci_dev = pdev;
3650 il->inta_mask = CSR_INI_SET_MASK;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003651
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003652 /***************************
3653 * 2. Initializing PCI bus
3654 * *************************/
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003655 pci_disable_link_state(pdev,
3656 PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
3657 PCIE_LINK_STATE_CLKPM);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003658
3659 if (pci_enable_device(pdev)) {
3660 err = -ENODEV;
3661 goto out_ieee80211_free_hw;
3662 }
3663
3664 pci_set_master(pdev);
3665
3666 err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
3667 if (!err)
3668 err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
3669 if (err) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003670 IL_WARN("No suitable DMA available.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003671 goto out_pci_disable_device;
3672 }
3673
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003674 pci_set_drvdata(pdev, il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003675 err = pci_request_regions(pdev, DRV_NAME);
3676 if (err)
3677 goto out_pci_disable_device;
3678
3679 /***********************
3680 * 3. Read REV Register
3681 * ********************/
Stanislaw Gruszkaa5f16132012-02-13 11:23:11 +01003682 il->hw_base = pci_ioremap_bar(pdev, 0);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003683 if (!il->hw_base) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003684 err = -ENODEV;
3685 goto out_pci_release_regions;
3686 }
3687
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003688 D_INFO("pci_resource_len = 0x%08llx\n",
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003689 (unsigned long long)pci_resource_len(pdev, 0));
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003690 D_INFO("pci_resource_base = %p\n", il->hw_base);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003691
3692 /* We disable the RETRY_TIMEOUT register (0x41) to keep
3693 * PCI Tx retries from interfering with C3 CPU state */
3694 pci_write_config_byte(pdev, 0x41, 0x00);
3695
Stanislaw Gruszkaf03ee2a2012-02-13 11:23:17 +01003696 /* these spin locks will be used in apm_init and EEPROM access
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003697 * we should init now
3698 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003699 spin_lock_init(&il->reg_lock);
3700 spin_lock_init(&il->lock);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003701
3702 /*
3703 * stop and reset the on-board processor just in case it is in a
3704 * strange state ... like being left stranded by a primary kernel
3705 * and this is now the kdump kernel trying to start up
3706 */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02003707 _il_wr(il, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003708
3709 /***********************
3710 * 4. Read EEPROM
3711 * ********************/
3712
3713 /* Read the EEPROM */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003714 err = il_eeprom_init(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003715 if (err) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003716 IL_ERR("Unable to init EEPROM\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003717 goto out_iounmap;
3718 }
3719 /* MAC Address location in EEPROM same for 3945/4965 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003720 eeprom = (struct il3945_eeprom *)il->eeprom;
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003721 D_INFO("MAC address: %pM\n", eeprom->mac_address);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003722 SET_IEEE80211_PERM_ADDR(il->hw, eeprom->mac_address);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003723
3724 /***********************
3725 * 5. Setup HW Constants
3726 * ********************/
3727 /* Device-specific setup */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003728 if (il3945_hw_set_hw_params(il)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003729 IL_ERR("failed to set hw settings\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003730 goto out_eeprom_free;
3731 }
3732
3733 /***********************
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003734 * 6. Setup il
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003735 * ********************/
3736
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003737 err = il3945_init_drv(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003738 if (err) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003739 IL_ERR("initializing driver failed\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003740 goto out_unset_hw_params;
3741 }
3742
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003743 IL_INFO("Detected Intel Wireless WiFi Link %s\n", il->cfg->name);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003744
3745 /***********************
3746 * 7. Setup Services
3747 * ********************/
3748
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003749 spin_lock_irqsave(&il->lock, flags);
3750 il_disable_interrupts(il);
3751 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003752
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003753 pci_enable_msi(il->pci_dev);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003754
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003755 err = request_irq(il->pci_dev->irq, il_isr, IRQF_SHARED, DRV_NAME, il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003756 if (err) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003757 IL_ERR("Error allocating IRQ %d\n", il->pci_dev->irq);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003758 goto out_disable_msi;
3759 }
3760
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003761 err = sysfs_create_group(&pdev->dev.kobj, &il3945_attribute_group);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003762 if (err) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003763 IL_ERR("failed to create sysfs device attributes\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003764 goto out_release_irq;
3765 }
3766
Stanislaw Gruszka83007192012-02-03 17:31:57 +01003767 il_set_rxon_channel(il, &il->bands[IEEE80211_BAND_2GHZ].channels[5]);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003768 il3945_setup_deferred_work(il);
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +02003769 il3945_setup_handlers(il);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003770 il_power_initialize(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003771
3772 /*********************************
3773 * 8. Setup and Register mac80211
3774 * *******************************/
3775
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003776 il_enable_interrupts(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003777
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003778 err = il3945_setup_mac(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003779 if (err)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003780 goto out_remove_sysfs;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003781
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003782 err = il_dbgfs_register(il, DRV_NAME);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003783 if (err)
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003784 IL_ERR("failed to create debugfs files. Ignoring error: %d\n",
3785 err);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003786
3787 /* Start monitoring the killswitch */
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003788 queue_delayed_work(il->workqueue, &il->_3945.rfkill_poll, 2 * HZ);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003789
3790 return 0;
3791
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003792out_remove_sysfs:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003793 destroy_workqueue(il->workqueue);
3794 il->workqueue = NULL;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003795 sysfs_remove_group(&pdev->dev.kobj, &il3945_attribute_group);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003796out_release_irq:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003797 free_irq(il->pci_dev->irq, il);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003798out_disable_msi:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003799 pci_disable_msi(il->pci_dev);
3800 il_free_geos(il);
3801 il_free_channel_map(il);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003802out_unset_hw_params:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003803 il3945_unset_hw_params(il);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003804out_eeprom_free:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003805 il_eeprom_free(il);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003806out_iounmap:
Stanislaw Gruszkaa5f16132012-02-13 11:23:11 +01003807 iounmap(il->hw_base);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003808out_pci_release_regions:
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003809 pci_release_regions(pdev);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003810out_pci_disable_device:
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003811 pci_set_drvdata(pdev, NULL);
3812 pci_disable_device(pdev);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003813out_ieee80211_free_hw:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003814 ieee80211_free_hw(il->hw);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003815out:
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003816 return err;
3817}
3818
Bill Pembertona027cb82012-12-03 09:56:33 -05003819static void
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003820il3945_pci_remove(struct pci_dev *pdev)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003821{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003822 struct il_priv *il = pci_get_drvdata(pdev);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003823 unsigned long flags;
3824
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003825 if (!il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003826 return;
3827
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003828 D_INFO("*** UNLOAD DRIVER ***\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003829
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003830 il_dbgfs_unregister(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003831
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01003832 set_bit(S_EXIT_PENDING, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003833
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003834 il_leds_exit(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003835
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003836 if (il->mac80211_registered) {
3837 ieee80211_unregister_hw(il->hw);
3838 il->mac80211_registered = 0;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003839 } else {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003840 il3945_down(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003841 }
3842
3843 /*
3844 * Make sure device is reset to low power before unloading driver.
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003845 * This may be redundant with il_down(), but there are paths to
3846 * run il_down() without calling apm_ops.stop(), and there are
3847 * paths to avoid running il_down() at all before leaving driver.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003848 * This (inexpensive) call *makes sure* device is reset.
3849 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003850 il_apm_stop(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003851
3852 /* make sure we flush any pending irq or
3853 * tasklet for the driver
3854 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003855 spin_lock_irqsave(&il->lock, flags);
3856 il_disable_interrupts(il);
3857 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003858
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003859 il3945_synchronize_irq(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003860
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003861 sysfs_remove_group(&pdev->dev.kobj, &il3945_attribute_group);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003862
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003863 cancel_delayed_work_sync(&il->_3945.rfkill_poll);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003864
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003865 il3945_dealloc_ucode_pci(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003866
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003867 if (il->rxq.bd)
3868 il3945_rx_queue_free(il, &il->rxq);
3869 il3945_hw_txq_ctx_free(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003870
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003871 il3945_unset_hw_params(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003872
3873 /*netif_stop_queue(dev); */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003874 flush_workqueue(il->workqueue);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003875
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003876 /* ieee80211_unregister_hw calls il3945_mac_stop, which flushes
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003877 * il->workqueue... so we can't take down the workqueue
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003878 * until now... */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003879 destroy_workqueue(il->workqueue);
3880 il->workqueue = NULL;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003881
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003882 free_irq(pdev->irq, il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003883 pci_disable_msi(pdev);
3884
Stanislaw Gruszkaa5f16132012-02-13 11:23:11 +01003885 iounmap(il->hw_base);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003886 pci_release_regions(pdev);
3887 pci_disable_device(pdev);
3888 pci_set_drvdata(pdev, NULL);
3889
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003890 il_free_channel_map(il);
3891 il_free_geos(il);
3892 kfree(il->scan_cmd);
3893 if (il->beacon_skb)
3894 dev_kfree_skb(il->beacon_skb);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003895
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003896 ieee80211_free_hw(il->hw);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003897}
3898
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003899/*****************************************************************************
3900 *
3901 * driver and module entry point
3902 *
3903 *****************************************************************************/
3904
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003905static struct pci_driver il3945_driver = {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003906 .name = DRV_NAME,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003907 .id_table = il3945_hw_card_ids,
3908 .probe = il3945_pci_probe,
Bill Pembertona027cb82012-12-03 09:56:33 -05003909 .remove = il3945_pci_remove,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003910 .driver.pm = IL_LEGACY_PM_OPS,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003911};
3912
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003913static int __init
3914il3945_init(void)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003915{
3916
3917 int ret;
3918 pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
3919 pr_info(DRV_COPYRIGHT "\n");
3920
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003921 ret = il3945_rate_control_register();
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003922 if (ret) {
3923 pr_err("Unable to register rate control algorithm: %d\n", ret);
3924 return ret;
3925 }
3926
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003927 ret = pci_register_driver(&il3945_driver);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003928 if (ret) {
3929 pr_err("Unable to initialize PCI module\n");
3930 goto error_register;
3931 }
3932
3933 return ret;
3934
3935error_register:
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003936 il3945_rate_control_unregister();
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003937 return ret;
3938}
3939
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003940static void __exit
3941il3945_exit(void)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003942{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003943 pci_unregister_driver(&il3945_driver);
3944 il3945_rate_control_unregister();
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003945}
3946
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003947MODULE_FIRMWARE(IL3945_MODULE_FIRMWARE(IL3945_UCODE_API_MAX));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003948
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003949module_param_named(antenna, il3945_mod_params.antenna, int, S_IRUGO);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003950MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003951module_param_named(swcrypto, il3945_mod_params.sw_crypto, int, S_IRUGO);
Stanislaw Gruszkae7392362011-11-15 14:45:59 +01003952MODULE_PARM_DESC(swcrypto, "using software crypto (default 1 [software])");
3953module_param_named(disable_hw_scan, il3945_mod_params.disable_hw_scan, int,
3954 S_IRUGO);
Stanislaw Gruszka0263aa42011-03-29 11:24:21 +02003955MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 1)");
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003956#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszkad2ddf6212011-08-16 14:17:04 +02003957module_param_named(debug, il_debug_level, uint, S_IRUGO | S_IWUSR);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003958MODULE_PARM_DESC(debug, "debug output mask");
3959#endif
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003960module_param_named(fw_restart, il3945_mod_params.restart_fw, int, S_IRUGO);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003961MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003962
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003963module_exit(il3945_exit);
3964module_init(il3945_init);