blob: cd7ae586b6630f526272e891462df67c67c7a6aa [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"
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -080055#include "iwl-sta.h"
Stanislaw Gruszka6bbb1372011-08-30 14:12:12 +020056#include "3945.h"
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -080057#include "iwl-core.h"
58#include "iwl-helpers.h"
59#include "iwl-dev.h"
60#include "iwl-spectrum.h"
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -080061
62/*
63 * module name, copyright, version, etc.
64 */
65
66#define DRV_DESCRIPTION \
67"Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux"
68
Stanislaw Gruszkad3175162011-11-15 11:25:42 +010069#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -080070#define VD "d"
71#else
72#define VD
73#endif
74
75/*
76 * add "s" to indicate spectrum measurement included.
77 * we add it here to be consistent with previous releases in which
78 * this was configurable.
79 */
80#define DRV_VERSION IWLWIFI_VERSION VD "s"
Wey-Yi Guybe663ab2011-02-21 11:27:26 -080081#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation"
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -080082#define DRV_AUTHOR "<ilw@linux.intel.com>"
83
84MODULE_DESCRIPTION(DRV_DESCRIPTION);
85MODULE_VERSION(DRV_VERSION);
86MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
87MODULE_LICENSE("GPL");
88
89 /* module parameters */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +020090struct il_mod_params il3945_mod_params = {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -080091 .sw_crypto = 1,
92 .restart_fw = 1,
Stanislaw Gruszka0263aa42011-03-29 11:24:21 +020093 .disable_hw_scan = 1,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -080094 /* the rest are 0 by default */
95};
96
97/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +020098 * il3945_get_antenna_flags - Get antenna flags for RXON command
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +020099 * @il: eeprom and antenna fields are used to determine antenna flags
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800100 *
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200101 * il->eeprom39 is used to determine if antenna AUX/MAIN are reversed
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200102 * il3945_mod_params.antenna specifies the antenna diversity mode:
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800103 *
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200104 * IL_ANTENNA_DIVERSITY - NIC selects best antenna by itself
105 * IL_ANTENNA_MAIN - Force MAIN antenna
106 * IL_ANTENNA_AUX - Force AUX antenna
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800107 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200108__le32 il3945_get_antenna_flags(const struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800109{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200110 struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800111
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200112 switch (il3945_mod_params.antenna) {
113 case IL_ANTENNA_DIVERSITY:
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800114 return 0;
115
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200116 case IL_ANTENNA_MAIN:
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800117 if (eeprom->antenna_switch_type)
118 return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
119 return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
120
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200121 case IL_ANTENNA_AUX:
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800122 if (eeprom->antenna_switch_type)
123 return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
124 return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
125 }
126
127 /* bad antenna selector value */
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200128 IL_ERR("Bad antenna selector value (0x%x)\n",
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200129 il3945_mod_params.antenna);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800130
131 return 0; /* "diversity" is default if error */
132}
133
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200134static int il3945_set_ccmp_dynamic_key_info(struct il_priv *il,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800135 struct ieee80211_key_conf *keyconf,
136 u8 sta_id)
137{
138 unsigned long flags;
139 __le16 key_flags = 0;
140 int ret;
141
142 key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
143 key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
144
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +0100145 if (sta_id == il->ctx.bcast_sta_id)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800146 key_flags |= STA_KEY_MULTICAST_MSK;
147
148 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
149 keyconf->hw_key_idx = keyconf->keyidx;
150 key_flags &= ~STA_KEY_FLG_INVALID;
151
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200152 spin_lock_irqsave(&il->sta_lock, flags);
153 il->stations[sta_id].keyinfo.cipher = keyconf->cipher;
154 il->stations[sta_id].keyinfo.keylen = keyconf->keylen;
155 memcpy(il->stations[sta_id].keyinfo.key, keyconf->key,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800156 keyconf->keylen);
157
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200158 memcpy(il->stations[sta_id].sta.key.key, keyconf->key,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800159 keyconf->keylen);
160
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200161 if ((il->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800162 == STA_KEY_FLG_NO_ENC)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200163 il->stations[sta_id].sta.key.key_offset =
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100164 il_get_free_ucode_key_idx(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800165 /* else, we are overriding an existing key => no need to allocated room
166 * in uCode. */
167
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200168 WARN(il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800169 "no space for a new key");
170
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200171 il->stations[sta_id].sta.key.key_flags = key_flags;
172 il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
173 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800174
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100175 D_INFO("hwcrypto: modify ucode station key info\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800176
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200177 ret = il_send_add_sta(il,
178 &il->stations[sta_id].sta, CMD_ASYNC);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800179
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200180 spin_unlock_irqrestore(&il->sta_lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800181
182 return ret;
183}
184
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200185static int il3945_set_tkip_dynamic_key_info(struct il_priv *il,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800186 struct ieee80211_key_conf *keyconf,
187 u8 sta_id)
188{
189 return -EOPNOTSUPP;
190}
191
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200192static int il3945_set_wep_dynamic_key_info(struct il_priv *il,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800193 struct ieee80211_key_conf *keyconf,
194 u8 sta_id)
195{
196 return -EOPNOTSUPP;
197}
198
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200199static int il3945_clear_sta_key_info(struct il_priv *il, u8 sta_id)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800200{
201 unsigned long flags;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200202 struct il_addsta_cmd sta_cmd;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800203
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200204 spin_lock_irqsave(&il->sta_lock, flags);
205 memset(&il->stations[sta_id].keyinfo, 0, sizeof(struct il_hw_key));
206 memset(&il->stations[sta_id].sta.key, 0,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200207 sizeof(struct il4965_keyinfo));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200208 il->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
209 il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
210 il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
211 memcpy(&sta_cmd, &il->stations[sta_id].sta, sizeof(struct il_addsta_cmd));
212 spin_unlock_irqrestore(&il->sta_lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800213
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100214 D_INFO("hwcrypto: clear ucode station key info\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200215 return il_send_add_sta(il, &sta_cmd, CMD_SYNC);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800216}
217
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200218static int il3945_set_dynamic_key(struct il_priv *il,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800219 struct ieee80211_key_conf *keyconf, u8 sta_id)
220{
221 int ret = 0;
222
223 keyconf->hw_key_idx = HW_KEY_DYNAMIC;
224
225 switch (keyconf->cipher) {
226 case WLAN_CIPHER_SUITE_CCMP:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200227 ret = il3945_set_ccmp_dynamic_key_info(il, keyconf, sta_id);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800228 break;
229 case WLAN_CIPHER_SUITE_TKIP:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200230 ret = il3945_set_tkip_dynamic_key_info(il, keyconf, sta_id);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800231 break;
232 case WLAN_CIPHER_SUITE_WEP40:
233 case WLAN_CIPHER_SUITE_WEP104:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200234 ret = il3945_set_wep_dynamic_key_info(il, keyconf, sta_id);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800235 break;
236 default:
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200237 IL_ERR("Unknown alg: %s alg=%x\n", __func__,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800238 keyconf->cipher);
239 ret = -EINVAL;
240 }
241
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100242 D_WEP("Set dynamic key: alg=%x len=%d idx=%d sta=%d ret=%d\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800243 keyconf->cipher, keyconf->keylen, keyconf->keyidx,
244 sta_id, ret);
245
246 return ret;
247}
248
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200249static int il3945_remove_static_key(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800250{
251 int ret = -EOPNOTSUPP;
252
253 return ret;
254}
255
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200256static int il3945_set_static_key(struct il_priv *il,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800257 struct ieee80211_key_conf *key)
258{
259 if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
260 key->cipher == WLAN_CIPHER_SUITE_WEP104)
261 return -EOPNOTSUPP;
262
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200263 IL_ERR("Static key invalid: cipher %x\n", key->cipher);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800264 return -EINVAL;
265}
266
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200267static void il3945_clear_free_frames(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800268{
269 struct list_head *element;
270
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100271 D_INFO("%d frames on pre-allocated heap on clear.\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200272 il->frames_count);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800273
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200274 while (!list_empty(&il->free_frames)) {
275 element = il->free_frames.next;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800276 list_del(element);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200277 kfree(list_entry(element, struct il3945_frame, list));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200278 il->frames_count--;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800279 }
280
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200281 if (il->frames_count) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200282 IL_WARN("%d frames still in use. Did we lose one?\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200283 il->frames_count);
284 il->frames_count = 0;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800285 }
286}
287
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200288static struct il3945_frame *il3945_get_free_frame(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800289{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200290 struct il3945_frame *frame;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800291 struct list_head *element;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200292 if (list_empty(&il->free_frames)) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800293 frame = kzalloc(sizeof(*frame), GFP_KERNEL);
294 if (!frame) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200295 IL_ERR("Could not allocate frame!\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800296 return NULL;
297 }
298
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200299 il->frames_count++;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800300 return frame;
301 }
302
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200303 element = il->free_frames.next;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800304 list_del(element);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200305 return list_entry(element, struct il3945_frame, list);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800306}
307
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200308static void il3945_free_frame(struct il_priv *il, struct il3945_frame *frame)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800309{
310 memset(frame, 0, sizeof(*frame));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200311 list_add(&frame->list, &il->free_frames);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800312}
313
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200314unsigned int il3945_fill_beacon_frame(struct il_priv *il,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800315 struct ieee80211_hdr *hdr,
316 int left)
317{
318
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +0100319 if (!il_is_associated(il) || !il->beacon_skb)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800320 return 0;
321
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200322 if (il->beacon_skb->len > left)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800323 return 0;
324
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200325 memcpy(hdr, il->beacon_skb->data, il->beacon_skb->len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800326
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200327 return il->beacon_skb->len;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800328}
329
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200330static int il3945_send_beacon_cmd(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800331{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200332 struct il3945_frame *frame;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800333 unsigned int frame_size;
334 int rc;
335 u8 rate;
336
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200337 frame = il3945_get_free_frame(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800338
339 if (!frame) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200340 IL_ERR("Could not obtain free frame buffer for beacon "
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800341 "command.\n");
342 return -ENOMEM;
343 }
344
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200345 rate = il_get_lowest_plcp(il,
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +0100346 &il->ctx);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800347
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200348 frame_size = il3945_hw_get_beacon_cmd(il, frame, rate);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800349
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200350 rc = il_send_cmd_pdu(il, C_TX_BEACON, frame_size,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800351 &frame->u.cmd[0]);
352
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200353 il3945_free_frame(il, frame);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800354
355 return rc;
356}
357
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200358static void il3945_unset_hw_params(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800359{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200360 if (il->_3945.shared_virt)
361 dma_free_coherent(&il->pci_dev->dev,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200362 sizeof(struct il3945_shared),
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200363 il->_3945.shared_virt,
364 il->_3945.shared_phys);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800365}
366
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200367static void il3945_build_tx_cmd_hwcrypto(struct il_priv *il,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800368 struct ieee80211_tx_info *info,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200369 struct il_device_cmd *cmd,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800370 struct sk_buff *skb_frag,
371 int sta_id)
372{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200373 struct il3945_tx_cmd *tx_cmd = (struct il3945_tx_cmd *)cmd->cmd.payload;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200374 struct il_hw_key *keyinfo = &il->stations[sta_id].keyinfo;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800375
376 tx_cmd->sec_ctl = 0;
377
378 switch (keyinfo->cipher) {
379 case WLAN_CIPHER_SUITE_CCMP:
380 tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
381 memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100382 D_TX("tx_cmd with AES hwcrypto\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800383 break;
384
385 case WLAN_CIPHER_SUITE_TKIP:
386 break;
387
388 case WLAN_CIPHER_SUITE_WEP104:
389 tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
390 /* fall through */
391 case WLAN_CIPHER_SUITE_WEP40:
392 tx_cmd->sec_ctl |= TX_CMD_SEC_WEP |
393 (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
394
395 memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen);
396
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100397 D_TX("Configuring packet for WEP encryption "
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800398 "with key %d\n", info->control.hw_key->hw_key_idx);
399 break;
400
401 default:
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200402 IL_ERR("Unknown encode cipher %x\n", keyinfo->cipher);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800403 break;
404 }
405}
406
407/*
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200408 * handle build C_TX command notification.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800409 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200410static void il3945_build_tx_cmd_basic(struct il_priv *il,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200411 struct il_device_cmd *cmd,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800412 struct ieee80211_tx_info *info,
413 struct ieee80211_hdr *hdr, u8 std_id)
414{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200415 struct il3945_tx_cmd *tx_cmd = (struct il3945_tx_cmd *)cmd->cmd.payload;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800416 __le32 tx_flags = tx_cmd->tx_flags;
417 __le16 fc = hdr->frame_control;
418
419 tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
420 if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
421 tx_flags |= TX_CMD_FLG_ACK_MSK;
422 if (ieee80211_is_mgmt(fc))
423 tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
424 if (ieee80211_is_probe_resp(fc) &&
425 !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
426 tx_flags |= TX_CMD_FLG_TSF_MSK;
427 } else {
428 tx_flags &= (~TX_CMD_FLG_ACK_MSK);
429 tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
430 }
431
432 tx_cmd->sta_id = std_id;
433 if (ieee80211_has_morefrags(fc))
434 tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
435
436 if (ieee80211_is_data_qos(fc)) {
437 u8 *qc = ieee80211_get_qos_ctl(hdr);
438 tx_cmd->tid_tspec = qc[0] & 0xf;
439 tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
440 } else {
441 tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
442 }
443
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200444 il_tx_cmd_protection(il, info, fc, &tx_flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800445
446 tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
447 if (ieee80211_is_mgmt(fc)) {
448 if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
449 tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3);
450 else
451 tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2);
452 } else {
453 tx_cmd->timeout.pm_frame_timeout = 0;
454 }
455
456 tx_cmd->driver_txop = 0;
457 tx_cmd->tx_flags = tx_flags;
458 tx_cmd->next_frame_len = 0;
459}
460
461/*
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200462 * start C_TX command process
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800463 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200464static int il3945_tx_skb(struct il_priv *il, struct sk_buff *skb)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800465{
466 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
467 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200468 struct il3945_tx_cmd *tx_cmd;
469 struct il_tx_queue *txq = NULL;
470 struct il_queue *q = NULL;
471 struct il_device_cmd *out_cmd;
472 struct il_cmd_meta *out_meta;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800473 dma_addr_t phys_addr;
474 dma_addr_t txcmd_phys;
475 int txq_id = skb_get_queue_mapping(skb);
476 u16 len, idx, hdr_len;
477 u8 id;
478 u8 unicast;
479 u8 sta_id;
480 u8 tid = 0;
481 __le16 fc;
482 u8 wait_write_ptr = 0;
483 unsigned long flags;
484
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200485 spin_lock_irqsave(&il->lock, flags);
486 if (il_is_rfkill(il)) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100487 D_DROP("Dropping - RF KILL\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800488 goto drop_unlock;
489 }
490
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200491 if ((ieee80211_get_tx_rate(il->hw, info)->hw_value & 0xFF) == IL_INVALID_RATE) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200492 IL_ERR("ERROR: No TX rate available.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800493 goto drop_unlock;
494 }
495
496 unicast = !is_multicast_ether_addr(hdr->addr1);
497 id = 0;
498
499 fc = hdr->frame_control;
500
Stanislaw Gruszkad3175162011-11-15 11:25:42 +0100501#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800502 if (ieee80211_is_auth(fc))
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100503 D_TX("Sending AUTH frame\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800504 else if (ieee80211_is_assoc_req(fc))
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100505 D_TX("Sending ASSOC frame\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800506 else if (ieee80211_is_reassoc_req(fc))
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100507 D_TX("Sending REASSOC frame\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800508#endif
509
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200510 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800511
512 hdr_len = ieee80211_hdrlen(fc);
513
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100514 /* Find idx into station table for destination station */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200515 sta_id = il_sta_id_or_broadcast(
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +0100516 il, &il->ctx,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800517 info->control.sta);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200518 if (sta_id == IL_INVALID_STATION) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100519 D_DROP("Dropping - INVALID STATION: %pM\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800520 hdr->addr1);
521 goto drop;
522 }
523
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100524 D_RATE("station Id %d\n", sta_id);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800525
526 if (ieee80211_is_data_qos(fc)) {
527 u8 *qc = ieee80211_get_qos_ctl(hdr);
528 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
529 if (unlikely(tid >= MAX_TID_COUNT))
530 goto drop;
531 }
532
533 /* Descriptor for chosen Tx queue */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200534 txq = &il->txq[txq_id];
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800535 q = &txq->q;
536
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200537 if ((il_queue_space(q) < q->high_mark))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800538 goto drop;
539
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200540 spin_lock_irqsave(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800541
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100542 idx = il_get_cmd_idx(q, q->write_ptr, 0);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800543
544 /* Set up driver data for this TFD */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200545 memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct il_tx_info));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800546 txq->txb[q->write_ptr].skb = skb;
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +0100547 txq->txb[q->write_ptr].ctx = &il->ctx;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800548
549 /* Init first empty entry in queue's array of Tx/cmd buffers */
550 out_cmd = txq->cmd[idx];
551 out_meta = &txq->meta[idx];
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200552 tx_cmd = (struct il3945_tx_cmd *)out_cmd->cmd.payload;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800553 memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
554 memset(tx_cmd, 0, sizeof(*tx_cmd));
555
556 /*
557 * Set up the Tx-command (not MAC!) header.
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100558 * Store the chosen Tx queue and TFD idx within the sequence field;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800559 * after Tx, uCode's Tx response will return this value so driver can
560 * locate the frame within the tx queue and do post-tx processing.
561 */
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200562 out_cmd->hdr.cmd = C_TX;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800563 out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
Stanislaw Gruszka2d09b062011-08-26 16:10:40 +0200564 IDX_TO_SEQ(q->write_ptr)));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800565
566 /* Copy MAC header from skb into command buffer */
567 memcpy(tx_cmd->hdr, hdr, hdr_len);
568
569
570 if (info->control.hw_key)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200571 il3945_build_tx_cmd_hwcrypto(il, info, out_cmd, skb, sta_id);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800572
573 /* TODO need this for burst mode later on */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200574 il3945_build_tx_cmd_basic(il, out_cmd, info, hdr, sta_id);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800575
576 /* set is_hcca to 0; it probably will never be implemented */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200577 il3945_hw_build_tx_cmd_rate(il, out_cmd, info, hdr, sta_id, 0);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800578
579 /* Total # bytes to be transmitted */
580 len = (u16)skb->len;
581 tx_cmd->len = cpu_to_le16(len);
582
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200583 il_dbg_log_tx_data_frame(il, len, hdr);
584 il_update_stats(il, true, fc, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800585 tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
586 tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
587
588 if (!ieee80211_has_morefrags(hdr->frame_control)) {
589 txq->need_update = 1;
590 } else {
591 wait_write_ptr = 1;
592 txq->need_update = 0;
593 }
594
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100595 D_TX("sequence nr = 0X%x\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800596 le16_to_cpu(out_cmd->hdr.sequence));
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100597 D_TX("tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200598 il_print_hex_dump(il, IL_DL_TX, tx_cmd, sizeof(*tx_cmd));
599 il_print_hex_dump(il, IL_DL_TX, (u8 *)tx_cmd->hdr,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800600 ieee80211_hdrlen(fc));
601
602 /*
603 * Use the first empty entry in this queue's command buffer array
604 * to contain the Tx command and MAC header concatenated together
605 * (payload data will be in another buffer).
606 * Size of this varies, due to varying MAC header length.
607 * If end is not dword aligned, we'll have 2 extra bytes at the end
608 * of the MAC header (device reads on dword boundaries).
609 * We'll tell device about this padding later.
610 */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200611 len = sizeof(struct il3945_tx_cmd) +
612 sizeof(struct il_cmd_header) + hdr_len;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800613 len = (len + 3) & ~3;
614
615 /* Physical address of this Tx command's header (not MAC header!),
616 * within command buffer array. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200617 txcmd_phys = pci_map_single(il->pci_dev, &out_cmd->hdr,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800618 len, PCI_DMA_TODEVICE);
619 /* we do not map meta data ... so we can safely access address to
620 * provide to unmap command*/
621 dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
622 dma_unmap_len_set(out_meta, len, len);
623
624 /* Add buffer containing Tx command and MAC(!) header to TFD's
625 * first entry */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200626 il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800627 txcmd_phys, len, 1, 0);
628
629
630 /* Set up TFD's 2nd entry to point directly to remainder of skb,
631 * if any (802.11 null frames have no payload). */
632 len = skb->len - hdr_len;
633 if (len) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200634 phys_addr = pci_map_single(il->pci_dev, skb->data + hdr_len,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800635 len, PCI_DMA_TODEVICE);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200636 il->cfg->ops->lib->txq_attach_buf_to_tfd(il, txq,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800637 phys_addr, len,
638 0, U32_PAD(len));
639 }
640
641
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100642 /* Tell device the write idx *just past* this latest filled TFD */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200643 q->write_ptr = il_queue_inc_wrap(q->write_ptr, q->n_bd);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200644 il_txq_update_write_ptr(il, txq);
645 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800646
Stanislaw Gruszka232913b2011-08-26 10:45:16 +0200647 if (il_queue_space(q) < q->high_mark
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200648 && il->mac80211_registered) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800649 if (wait_write_ptr) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200650 spin_lock_irqsave(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800651 txq->need_update = 1;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200652 il_txq_update_write_ptr(il, txq);
653 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800654 }
655
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200656 il_stop_queue(il, txq);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800657 }
658
659 return 0;
660
661drop_unlock:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200662 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800663drop:
664 return -1;
665}
666
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200667static int il3945_get_measurement(struct il_priv *il,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800668 struct ieee80211_measurement_params *params,
669 u8 type)
670{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200671 struct il_spectrum_cmd spectrum;
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +0200672 struct il_rx_pkt *pkt;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200673 struct il_host_cmd cmd = {
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200674 .id = C_SPECTRUM_MEASUREMENT,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800675 .data = (void *)&spectrum,
676 .flags = CMD_WANT_SKB,
677 };
678 u32 add_time = le64_to_cpu(params->start_time);
679 int rc;
680 int spectrum_resp_status;
681 int duration = le16_to_cpu(params->duration);
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +0100682 struct il_rxon_context *ctx = &il->ctx;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800683
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +0100684 if (il_is_associated(il))
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200685 add_time = il_usecs_to_beacons(il,
686 le64_to_cpu(params->start_time) - il->_3945.last_tsf,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800687 le16_to_cpu(ctx->timing.beacon_interval));
688
689 memset(&spectrum, 0, sizeof(spectrum));
690
691 spectrum.channel_count = cpu_to_le16(1);
692 spectrum.flags =
693 RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK;
694 spectrum.filter_flags = MEASUREMENT_FILTER_FLAG;
695 cmd.len = sizeof(spectrum);
696 spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
697
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +0100698 if (il_is_associated(il))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800699 spectrum.start_time =
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200700 il_add_beacon_time(il,
701 il->_3945.last_beacon_time, add_time,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800702 le16_to_cpu(ctx->timing.beacon_interval));
703 else
704 spectrum.start_time = 0;
705
706 spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT);
707 spectrum.channels[0].channel = params->channel;
708 spectrum.channels[0].type = type;
709 if (ctx->active.flags & RXON_FLG_BAND_24G_MSK)
710 spectrum.flags |= RXON_FLG_BAND_24G_MSK |
711 RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
712
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200713 rc = il_send_cmd_sync(il, &cmd);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800714 if (rc)
715 return rc;
716
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +0200717 pkt = (struct il_rx_pkt *)cmd.reply_page;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200718 if (pkt->hdr.flags & IL_CMD_FAILED_MSK) {
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200719 IL_ERR("Bad return from N_RX_ON_ASSOC command\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800720 rc = -EIO;
721 }
722
723 spectrum_resp_status = le16_to_cpu(pkt->u.spectrum.status);
724 switch (spectrum_resp_status) {
725 case 0: /* Command will be handled */
726 if (pkt->u.spectrum.id != 0xff) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100727 D_INFO("Replaced existing measurement: %d\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800728 pkt->u.spectrum.id);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200729 il->measurement_status &= ~MEASUREMENT_READY;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800730 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200731 il->measurement_status |= MEASUREMENT_ACTIVE;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800732 rc = 0;
733 break;
734
735 case 1: /* Command will not be handled */
736 rc = -EAGAIN;
737 break;
738 }
739
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200740 il_free_pages(il, cmd.reply_page);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800741
742 return rc;
743}
744
Stanislaw Gruszka6e9848b42011-08-30 15:45:31 +0200745static void il3945_hdl_alive(struct il_priv *il,
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +0200746 struct il_rx_buf *rxb)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800747{
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +0200748 struct il_rx_pkt *pkt = rxb_addr(rxb);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200749 struct il_alive_resp *palive;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800750 struct delayed_work *pwork;
751
752 palive = &pkt->u.alive_frame;
753
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100754 D_INFO("Alive ucode status 0x%08X revision "
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800755 "0x%01X 0x%01X\n",
756 palive->is_valid, palive->ver_type,
757 palive->ver_subtype);
758
759 if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100760 D_INFO("Initialization Alive received.\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200761 memcpy(&il->card_alive_init, &pkt->u.alive_frame,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200762 sizeof(struct il_alive_resp));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200763 pwork = &il->init_alive_start;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800764 } else {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100765 D_INFO("Runtime Alive received.\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200766 memcpy(&il->card_alive, &pkt->u.alive_frame,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200767 sizeof(struct il_alive_resp));
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200768 pwork = &il->alive_start;
769 il3945_disable_events(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800770 }
771
772 /* We delay the ALIVE response by 5ms to
773 * give the HW RF Kill time to activate... */
774 if (palive->is_valid == UCODE_VALID_OK)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200775 queue_delayed_work(il->workqueue, pwork,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800776 msecs_to_jiffies(5));
777 else
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200778 IL_WARN("uCode did not respond OK.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800779}
780
Stanislaw Gruszka6e9848b42011-08-30 15:45:31 +0200781static void il3945_hdl_add_sta(struct il_priv *il,
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +0200782 struct il_rx_buf *rxb)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800783{
Stanislaw Gruszkad3175162011-11-15 11:25:42 +0100784#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +0200785 struct il_rx_pkt *pkt = rxb_addr(rxb);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800786#endif
787
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +0200788 D_RX("Received C_ADD_STA: 0x%02X\n", pkt->u.status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800789}
790
Stanislaw Gruszkad2dfb332011-11-15 13:16:38 +0100791static void il3945_hdl_beacon(struct il_priv *il,
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +0200792 struct il_rx_buf *rxb)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800793{
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +0200794 struct il_rx_pkt *pkt = rxb_addr(rxb);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200795 struct il3945_beacon_notif *beacon = &(pkt->u.beacon_status);
Stanislaw Gruszkad3175162011-11-15 11:25:42 +0100796#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800797 u8 rate = beacon->beacon_notify_hdr.rate;
798
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +0100799 D_RX("beacon status %x retries %d iss %d "
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800800 "tsf %d %d rate %d\n",
801 le32_to_cpu(beacon->beacon_notify_hdr.status) & TX_STATUS_MSK,
802 beacon->beacon_notify_hdr.failure_frame,
803 le32_to_cpu(beacon->ibss_mgr_status),
804 le32_to_cpu(beacon->high_tsf),
805 le32_to_cpu(beacon->low_tsf), rate);
806#endif
807
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200808 il->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800809
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800810}
811
812/* Handle notification from uCode that card's power state is changing
813 * due to software, hardware, or critical temperature RFKILL */
Stanislaw Gruszkad2dfb332011-11-15 13:16:38 +0100814static void il3945_hdl_card_state(struct il_priv *il,
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +0200815 struct il_rx_buf *rxb)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800816{
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +0200817 struct il_rx_pkt *pkt = rxb_addr(rxb);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800818 u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200819 unsigned long status = il->status;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800820
Stanislaw Gruszka9406f792011-08-18 22:07:57 +0200821 IL_WARN("Card state received: HW:%s SW:%s\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800822 (flags & HW_CARD_DISABLED) ? "Kill" : "On",
823 (flags & SW_CARD_DISABLED) ? "Kill" : "On");
824
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +0200825 _il_wr(il, CSR_UCODE_DRV_GP1_SET,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800826 CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
827
828 if (flags & HW_CARD_DISABLED)
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +0100829 set_bit(S_RF_KILL_HW, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800830 else
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +0100831 clear_bit(S_RF_KILL_HW, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800832
833
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200834 il_scan_cancel(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800835
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +0100836 if ((test_bit(S_RF_KILL_HW, &status) !=
837 test_bit(S_RF_KILL_HW, &il->status)))
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200838 wiphy_rfkill_set_hw_state(il->hw->wiphy,
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +0100839 test_bit(S_RF_KILL_HW, &il->status));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800840 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200841 wake_up(&il->wait_command_queue);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800842}
843
844/**
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +0200845 * il3945_setup_handlers - Initialize Rx handler callbacks
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800846 *
847 * Setup the RX handlers for each of the reply types sent from the uCode
848 * to the host.
849 *
850 * This function chains into the hardware specific files for them to setup
851 * any hardware specific handlers as well.
852 */
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +0200853static void il3945_setup_handlers(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800854{
Stanislaw Gruszka6e9848b42011-08-30 15:45:31 +0200855 il->handlers[N_ALIVE] = il3945_hdl_alive;
856 il->handlers[C_ADD_STA] = il3945_hdl_add_sta;
857 il->handlers[N_ERROR] = il_hdl_error;
Stanislaw Gruszkad2dfb332011-11-15 13:16:38 +0100858 il->handlers[N_CHANNEL_SWITCH] = il_hdl_csa;
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +0200859 il->handlers[N_SPECTRUM_MEASUREMENT] =
Stanislaw Gruszkad2dfb332011-11-15 13:16:38 +0100860 il_hdl_spectrum_measurement;
861 il->handlers[N_PM_SLEEP] = il_hdl_pm_sleep;
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +0200862 il->handlers[N_PM_DEBUG_STATS] =
Stanislaw Gruszkad2dfb332011-11-15 13:16:38 +0100863 il_hdl_pm_debug_stats;
864 il->handlers[N_BEACON] = il3945_hdl_beacon;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800865
866 /*
867 * The same handler is used for both the REPLY to a discrete
Stanislaw Gruszkaebf0d902011-08-26 15:43:47 +0200868 * stats request from the host as well as for the periodic
869 * stats notifications (after received beacons) from the uCode.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800870 */
Stanislaw Gruszkad2dfb332011-11-15 13:16:38 +0100871 il->handlers[C_STATS] = il3945_hdl_c_stats;
872 il->handlers[N_STATS] = il3945_hdl_stats;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800873
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200874 il_setup_rx_scan_handlers(il);
Stanislaw Gruszkad2dfb332011-11-15 13:16:38 +0100875 il->handlers[N_CARD_STATE] = il3945_hdl_card_state;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800876
877 /* Set up hardware specific Rx handlers */
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +0200878 il3945_hw_handler_setup(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800879}
880
881/************************** RX-FUNCTIONS ****************************/
882/*
883 * Rx theory of operation
884 *
885 * The host allocates 32 DMA target addresses and passes the host address
Stanislaw Gruszka3b98c7f2011-08-26 16:29:35 +0200886 * to the firmware at register IL_RFDS_TBL_LOWER + N * RFD_SIZE where N is
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800887 * 0 to 31
888 *
889 * Rx Queue Indexes
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100890 * The host/firmware share two idx registers for managing the Rx buffers.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800891 *
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100892 * The READ idx maps to the first position that the firmware may be writing
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800893 * to -- the driver can read up to (but not including) this position and get
894 * good data.
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100895 * The READ idx is managed by the firmware once the card is enabled.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800896 *
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100897 * The WRITE idx maps to the last position the driver has read from -- the
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800898 * position preceding WRITE is the last slot the firmware can place a packet.
899 *
900 * The queue is empty (no good data) if WRITE = READ - 1, and is full if
901 * WRITE = READ.
902 *
903 * During initialization, the host sets up the READ queue position to the first
Stanislaw Gruszka2d09b062011-08-26 16:10:40 +0200904 * IDX position, and WRITE to the last (READ - 1 wrapped)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800905 *
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100906 * When the firmware places a packet in a buffer, it will advance the READ idx
907 * and fire the RX interrupt. The driver can then query the READ idx and
908 * process as many packets as possible, moving the WRITE idx forward as it
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800909 * resets the Rx queue buffers with new memory.
910 *
911 * The management in the driver is as follows:
912 * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When
913 * iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
914 * to replenish the iwl->rxq->rx_free.
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200915 * + In il3945_rx_replenish (scheduled) if 'processed' != 'read' then the
Stanislaw Gruszka2d09b062011-08-26 16:10:40 +0200916 * iwl->rxq is replenished and the READ IDX is updated (updating the
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100917 * 'processed' and 'read' driver idxes as well)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800918 * + A received packet is processed and handed to the kernel network stack,
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100919 * detached from the iwl->rxq. The driver 'processed' idx is updated.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800920 * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
921 * list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
Stanislaw Gruszka2d09b062011-08-26 16:10:40 +0200922 * IDX is not incremented and iwl->status(RX_STALLED) is set. If there
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800923 * were enough free buffers and RX_STALLED is set it is cleared.
924 *
925 *
926 * Driver sequence:
927 *
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200928 * il3945_rx_replenish() Replenishes rx_free list from rx_used, and calls
929 * il3945_rx_queue_restock
930 * il3945_rx_queue_restock() Moves available buffers from rx_free into Rx
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800931 * queue, updates firmware pointers, and updates
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100932 * the WRITE idx. If insufficient rx_free buffers
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200933 * are available, schedules il3945_rx_replenish
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800934 *
935 * -- enable interrupts --
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +0200936 * ISR - il3945_rx() Detach il_rx_bufs from pool up to the
Stanislaw Gruszka2d09b062011-08-26 16:10:40 +0200937 * READ IDX, detaching the SKB from the pool.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800938 * Moves the packet buffer from queue to rx_used.
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200939 * Calls il3945_rx_queue_restock to refill any empty
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800940 * slots.
941 * ...
942 *
943 */
944
945/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200946 * il3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800947 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200948static inline __le32 il3945_dma_addr2rbd_ptr(struct il_priv *il,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800949 dma_addr_t dma_addr)
950{
951 return cpu_to_le32((u32)dma_addr);
952}
953
954/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +0200955 * il3945_rx_queue_restock - refill RX queue from pre-allocated pool
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800956 *
957 * If there are slots in the RX queue that need to be restocked,
958 * and we have free pre-allocated buffers, fill the ranks as much
959 * as we can, pulling from rx_free.
960 *
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +0100961 * This moves the 'write' idx forward to catch up with 'processed', and
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800962 * also updates the memory address in the firmware to reference the new
963 * target buffer.
964 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200965static void il3945_rx_queue_restock(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800966{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200967 struct il_rx_queue *rxq = &il->rxq;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800968 struct list_head *element;
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +0200969 struct il_rx_buf *rxb;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800970 unsigned long flags;
971 int write;
972
973 spin_lock_irqsave(&rxq->lock, flags);
974 write = rxq->write & ~0x7;
Stanislaw Gruszka232913b2011-08-26 10:45:16 +0200975 while (il_rx_queue_space(rxq) > 0 && rxq->free_count) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800976 /* Get next free Rx buffer, remove from free list */
977 element = rxq->rx_free.next;
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +0200978 rxb = list_entry(element, struct il_rx_buf, list);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800979 list_del(element);
980
981 /* Point to Rx buffer via next RBD in circular buffer */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200982 rxq->bd[rxq->write] = il3945_dma_addr2rbd_ptr(il, rxb->page_dma);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800983 rxq->queue[rxq->write] = rxb;
984 rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
985 rxq->free_count--;
986 }
987 spin_unlock_irqrestore(&rxq->lock, flags);
988 /* If the pre-allocated buffer pool is dropping low, schedule to
989 * refill it */
990 if (rxq->free_count <= RX_LOW_WATERMARK)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +0200991 queue_work(il->workqueue, &il->rx_replenish);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800992
993
994 /* If we've added more space for the firmware to place data, tell it.
995 * Increment device's write pointer in multiples of 8. */
Stanislaw Gruszka232913b2011-08-26 10:45:16 +0200996 if (rxq->write_actual != (rxq->write & ~0x7) ||
997 abs(rxq->write - rxq->read) > 7) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -0800998 spin_lock_irqsave(&rxq->lock, flags);
999 rxq->need_update = 1;
1000 spin_unlock_irqrestore(&rxq->lock, flags);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001001 il_rx_queue_update_write_ptr(il, rxq);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001002 }
1003}
1004
1005/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001006 * il3945_rx_replenish - Move all used packet from rx_used to rx_free
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001007 *
1008 * When moving to rx_free an SKB is allocated for the slot.
1009 *
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001010 * Also restock the Rx queue via il3945_rx_queue_restock.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001011 * This is called as a scheduled work item (except for during initialization)
1012 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001013static void il3945_rx_allocate(struct il_priv *il, gfp_t priority)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001014{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001015 struct il_rx_queue *rxq = &il->rxq;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001016 struct list_head *element;
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +02001017 struct il_rx_buf *rxb;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001018 struct page *page;
1019 unsigned long flags;
1020 gfp_t gfp_mask = priority;
1021
1022 while (1) {
1023 spin_lock_irqsave(&rxq->lock, flags);
1024
1025 if (list_empty(&rxq->rx_used)) {
1026 spin_unlock_irqrestore(&rxq->lock, flags);
1027 return;
1028 }
1029 spin_unlock_irqrestore(&rxq->lock, flags);
1030
1031 if (rxq->free_count > RX_LOW_WATERMARK)
1032 gfp_mask |= __GFP_NOWARN;
1033
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001034 if (il->hw_params.rx_page_order > 0)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001035 gfp_mask |= __GFP_COMP;
1036
1037 /* Alloc a new receive buffer */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001038 page = alloc_pages(gfp_mask, il->hw_params.rx_page_order);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001039 if (!page) {
1040 if (net_ratelimit())
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001041 D_INFO("Failed to allocate SKB buffer.\n");
Stanislaw Gruszka232913b2011-08-26 10:45:16 +02001042 if (rxq->free_count <= RX_LOW_WATERMARK &&
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001043 net_ratelimit())
Stanislaw Gruszkab6297cd2011-08-18 22:27:04 +02001044 IL_ERR("Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001045 priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL",
1046 rxq->free_count);
1047 /* We don't reschedule replenish work here -- we will
1048 * call the restock method and if it still needs
1049 * more buffers it will schedule replenish */
1050 break;
1051 }
1052
1053 spin_lock_irqsave(&rxq->lock, flags);
1054 if (list_empty(&rxq->rx_used)) {
1055 spin_unlock_irqrestore(&rxq->lock, flags);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001056 __free_pages(page, il->hw_params.rx_page_order);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001057 return;
1058 }
1059 element = rxq->rx_used.next;
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +02001060 rxb = list_entry(element, struct il_rx_buf, list);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001061 list_del(element);
1062 spin_unlock_irqrestore(&rxq->lock, flags);
1063
1064 rxb->page = page;
1065 /* Get physical address of RB/SKB */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001066 rxb->page_dma = pci_map_page(il->pci_dev, page, 0,
1067 PAGE_SIZE << il->hw_params.rx_page_order,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001068 PCI_DMA_FROMDEVICE);
1069
1070 spin_lock_irqsave(&rxq->lock, flags);
1071
1072 list_add_tail(&rxb->list, &rxq->rx_free);
1073 rxq->free_count++;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001074 il->alloc_rxb_page++;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001075
1076 spin_unlock_irqrestore(&rxq->lock, flags);
1077 }
1078}
1079
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001080void il3945_rx_queue_reset(struct il_priv *il, struct il_rx_queue *rxq)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001081{
1082 unsigned long flags;
1083 int i;
1084 spin_lock_irqsave(&rxq->lock, flags);
1085 INIT_LIST_HEAD(&rxq->rx_free);
1086 INIT_LIST_HEAD(&rxq->rx_used);
1087 /* Fill the rx_used queue with _all_ of the Rx buffers */
1088 for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
1089 /* In the reset function, these buffers may have been allocated
1090 * to an SKB, so we need to unmap and free potential storage */
1091 if (rxq->pool[i].page != NULL) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001092 pci_unmap_page(il->pci_dev, rxq->pool[i].page_dma,
1093 PAGE_SIZE << il->hw_params.rx_page_order,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001094 PCI_DMA_FROMDEVICE);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001095 __il_free_pages(il, rxq->pool[i].page);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001096 rxq->pool[i].page = NULL;
1097 }
1098 list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
1099 }
1100
1101 /* Set us so that we have processed and used all buffers, but have
1102 * not restocked the Rx queue with fresh buffers */
1103 rxq->read = rxq->write = 0;
1104 rxq->write_actual = 0;
1105 rxq->free_count = 0;
1106 spin_unlock_irqrestore(&rxq->lock, flags);
1107}
1108
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001109void il3945_rx_replenish(void *data)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001110{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001111 struct il_priv *il = data;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001112 unsigned long flags;
1113
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001114 il3945_rx_allocate(il, GFP_KERNEL);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001115
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001116 spin_lock_irqsave(&il->lock, flags);
1117 il3945_rx_queue_restock(il);
1118 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001119}
1120
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001121static void il3945_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
1128
1129/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
1130 * If an SKB has been detached, the POOL needs to have its SKB set to NULL
1131 * This free routine walks the list of POOL entries and if SKB is set to
1132 * non NULL it is unmapped and freed
1133 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001134static void il3945_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,
1140 PAGE_SIZE << il->hw_params.rx_page_order,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001141 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;
1152 rxq->rb_stts = NULL;
1153}
1154
1155
1156/* Convert linear signal-to-noise ratio into dB */
1157static u8 ratio2dB[100] = {
1158/* 0 1 2 3 4 5 6 7 8 9 */
1159 0, 0, 6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */
1160 20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */
1161 26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */
1162 29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */
1163 32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */
1164 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */
1165 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */
1166 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */
1167 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */
1168 39, 39, 39, 39, 39, 40, 40, 40, 40, 40 /* 90 - 99 */
1169};
1170
1171/* Calculates a relative dB value from a ratio of linear
1172 * (i.e. not dB) signal levels.
1173 * Conversion assumes that levels are voltages (20*log), not powers (10*log). */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001174int il3945_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)
1183 return 20 + (int)ratio2dB[sig_ratio/10];
1184
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 Gruszka46bc8d42011-10-24 16:49:25 +02001200static void il3945_rx_handle(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001201{
Stanislaw Gruszkab73bb5f2011-08-26 14:37:54 +02001202 struct il_rx_buf *rxb;
Stanislaw Gruszkadcae1c62011-08-26 14:36:21 +02001203 struct il_rx_pkt *pkt;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001204 struct il_rx_queue *rxq = &il->rxq;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001205 u32 r, i;
1206 int reclaim;
1207 unsigned long flags;
1208 u8 fill_rx = 0;
1209 u32 count = 8;
1210 int total_empty = 0;
1211
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01001212 /* uCode's read idx (stored in shared DRAM) indicates the last Rx
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001213 * buffer that the driver may process (last buffer filled by ucode). */
1214 r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF;
1215 i = rxq->read;
1216
1217 /* calculate total frames need to be restock after handling RX */
1218 total_empty = r - rxq->write_actual;
1219 if (total_empty < 0)
1220 total_empty += RX_QUEUE_SIZE;
1221
1222 if (total_empty > (RX_QUEUE_SIZE / 2))
1223 fill_rx = 1;
1224 /* Rx interrupt, but nothing sent from uCode */
1225 if (i == r)
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001226 D_RX("r = %d, i = %d\n", r, i);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001227
1228 while (i != r) {
1229 int len;
1230
1231 rxb = rxq->queue[i];
1232
1233 /* If an RXB doesn't have a Rx queue slot associated with it,
1234 * then a bug has been introduced in the queue refilling
1235 * routines -- catch it here */
1236 BUG_ON(rxb == NULL);
1237
1238 rxq->queue[i] = NULL;
1239
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001240 pci_unmap_page(il->pci_dev, rxb->page_dma,
1241 PAGE_SIZE << il->hw_params.rx_page_order,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001242 PCI_DMA_FROMDEVICE);
1243 pkt = rxb_addr(rxb);
1244
1245 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
1246 len += sizeof(u32); /* account for status word */
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001247
1248 /* Reclaim a command buffer only if this packet is a response
1249 * to a (driver-originated) command.
1250 * If the packet (e.g. Rx frame) originated from uCode,
1251 * there is no command buffer to reclaim.
1252 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
1253 * but apparently a few don't get set; catch them here. */
1254 reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02001255 pkt->hdr.cmd != N_STATS &&
1256 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 Gruszkae2ebc832011-10-24 15:41:30 +02001263 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 Gruszka58de00a2011-11-15 11:21:01 +01001268 D_RX(
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001269 "r %d i %d No handler needed for %s, 0x%02x\n",
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001270 r, i, il_get_cmd_string(pkt->hdr.cmd),
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001271 pkt->hdr.cmd);
1272 }
1273
1274 /*
1275 * XXX: After here, we should always check rxb->page
1276 * against NULL before touching it or its virtual
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +02001277 * memory (pkt). Because some handler might have
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001278 * already taken or freed the pages.
1279 */
1280
1281 if (reclaim) {
1282 /* Invoke any callbacks, transfer the buffer to caller,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001283 * and fire off the (possibly) blocking il_send_cmd()
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001284 * as we reclaim the driver command queue */
1285 if (rxb->page)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001286 il_tx_cmd_complete(il, rxb);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001287 else
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001288 IL_WARN("Claim null rxb?\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001289 }
1290
1291 /* Reuse the page if possible. For notification packets and
1292 * SKBs that fail to Rx correctly, add them back into the
1293 * rx_free list for reuse later. */
1294 spin_lock_irqsave(&rxq->lock, flags);
1295 if (rxb->page != NULL) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001296 rxb->page_dma = pci_map_page(il->pci_dev, rxb->page,
1297 0, PAGE_SIZE << il->hw_params.rx_page_order,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001298 PCI_DMA_FROMDEVICE);
1299 list_add_tail(&rxb->list, &rxq->rx_free);
1300 rxq->free_count++;
1301 } else
1302 list_add_tail(&rxb->list, &rxq->rx_used);
1303
1304 spin_unlock_irqrestore(&rxq->lock, flags);
1305
1306 i = (i + 1) & RX_QUEUE_MASK;
1307 /* If there are a lot of unused frames,
1308 * restock the Rx queue so ucode won't assert. */
1309 if (fill_rx) {
1310 count++;
1311 if (count >= 8) {
1312 rxq->read = i;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001313 il3945_rx_replenish_now(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001314 count = 0;
1315 }
1316 }
1317 }
1318
1319 /* Backtrack one entry */
1320 rxq->read = i;
1321 if (fill_rx)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001322 il3945_rx_replenish_now(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001323 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001324 il3945_rx_queue_restock(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001325}
1326
1327/* call this function to flush any scheduled tasklet */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001328static inline void il3945_synchronize_irq(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001329{
1330 /* wait to make sure we flush pending tasklet*/
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001331 synchronize_irq(il->pci_dev->irq);
1332 tasklet_kill(&il->irq_tasklet);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001333}
1334
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001335static const char *il3945_desc_lookup(int i)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001336{
1337 switch (i) {
1338 case 1:
1339 return "FAIL";
1340 case 2:
1341 return "BAD_PARAM";
1342 case 3:
1343 return "BAD_CHECKSUM";
1344 case 4:
1345 return "NMI_INTERRUPT";
1346 case 5:
1347 return "SYSASSERT";
1348 case 6:
1349 return "FATAL_ERROR";
1350 }
1351
1352 return "UNKNOWN";
1353}
1354
1355#define ERROR_START_OFFSET (1 * sizeof(u32))
1356#define ERROR_ELEM_SIZE (7 * sizeof(u32))
1357
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001358void il3945_dump_nic_error_log(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001359{
1360 u32 i;
1361 u32 desc, time, count, base, data1;
1362 u32 blink1, blink2, ilink1, ilink2;
1363
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001364 base = le32_to_cpu(il->card_alive.error_event_table_ptr);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001365
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001366 if (!il3945_hw_valid_rtc_data_addr(base)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001367 IL_ERR("Not valid error log pointer 0x%08X\n", base);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001368 return;
1369 }
1370
1371
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001372 count = il_read_targ_mem(il, base);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001373
1374 if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001375 IL_ERR("Start IWL Error Log Dump:\n");
1376 IL_ERR("Status: 0x%08lX, count: %d\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001377 il->status, count);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001378 }
1379
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001380 IL_ERR("Desc Time asrtPC blink2 "
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001381 "ilink1 nmiPC Line\n");
1382 for (i = ERROR_START_OFFSET;
1383 i < (count * ERROR_ELEM_SIZE) + ERROR_START_OFFSET;
1384 i += ERROR_ELEM_SIZE) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001385 desc = il_read_targ_mem(il, base + i);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001386 time =
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001387 il_read_targ_mem(il, base + i + 1 * sizeof(u32));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001388 blink1 =
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001389 il_read_targ_mem(il, base + i + 2 * sizeof(u32));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001390 blink2 =
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001391 il_read_targ_mem(il, base + i + 3 * sizeof(u32));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001392 ilink1 =
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001393 il_read_targ_mem(il, base + i + 4 * sizeof(u32));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001394 ilink2 =
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001395 il_read_targ_mem(il, base + i + 5 * sizeof(u32));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001396 data1 =
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001397 il_read_targ_mem(il, base + i + 6 * sizeof(u32));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001398
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001399 IL_ERR(
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001400 "%-13s (0x%X) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001401 il3945_desc_lookup(desc), desc, time, blink1, blink2,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001402 ilink1, ilink2, data1);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001403 }
1404}
1405
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001406static void il3945_irq_tasklet(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001407{
1408 u32 inta, handled = 0;
1409 u32 inta_fh;
1410 unsigned long flags;
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001411#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001412 u32 inta_mask;
1413#endif
1414
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001415 spin_lock_irqsave(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001416
1417 /* Ack/clear/reset pending uCode interrupts.
1418 * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
1419 * and will clear only when CSR_FH_INT_STATUS gets cleared. */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001420 inta = _il_rd(il, CSR_INT);
1421 _il_wr(il, CSR_INT, inta);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001422
1423 /* Ack/clear/reset pending flow-handler (DMA) interrupts.
1424 * Any new interrupts that happen after this, either while we're
1425 * in this tasklet, or later, will show up in next ISR/tasklet. */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001426 inta_fh = _il_rd(il, CSR_FH_INT_STATUS);
1427 _il_wr(il, CSR_FH_INT_STATUS, inta_fh);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001428
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001429#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001430 if (il_get_debug_level(il) & IL_DL_ISR) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001431 /* just for debug */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001432 inta_mask = _il_rd(il, CSR_INT_MASK);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001433 D_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001434 inta, inta_mask, inta_fh);
1435 }
1436#endif
1437
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001438 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001439
1440 /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
1441 * atomic, make sure that inta covers all the interrupts that
1442 * we've discovered, even if FH interrupt came in just after
1443 * reading CSR_INT. */
1444 if (inta_fh & CSR39_FH_INT_RX_MASK)
1445 inta |= CSR_INT_BIT_FH_RX;
1446 if (inta_fh & CSR39_FH_INT_TX_MASK)
1447 inta |= CSR_INT_BIT_FH_TX;
1448
1449 /* Now service all interrupt bits discovered above. */
1450 if (inta & CSR_INT_BIT_HW_ERR) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001451 IL_ERR("Hardware error detected. Restarting.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001452
1453 /* Tell the device to stop sending interrupts */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001454 il_disable_interrupts(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001455
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001456 il->isr_stats.hw++;
1457 il_irq_handle_error(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001458
1459 handled |= CSR_INT_BIT_HW_ERR;
1460
1461 return;
1462 }
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 "
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001469 "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 Gruszka9406f792011-08-18 22:07:57 +02001485 IL_ERR("Microcode SW error detected. "
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001486 "Restarting 0x%X.\n", 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 Gruszka0c1a94e2011-08-24 17:37:16 +02001521 il_wr(il, FH39_TCSR_CREDIT
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001522 (FH39_SRVC_CHNL), 0x0);
1523 handled |= CSR_INT_BIT_FH_TX;
1524 }
1525
1526 if (inta & ~handled) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001527 IL_ERR("Unhandled INTA bits 0x%08x\n", inta & ~handled);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001528 il->isr_stats.unhandled++;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001529 }
1530
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001531 if (inta & ~il->inta_mask) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001532 IL_WARN("Disabled INTA bits 0x%08x were pending\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001533 inta & ~il->inta_mask);
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001534 IL_WARN(" with FH_INT = 0x%08x\n", inta_fh);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001535 }
1536
1537 /* Re-enable all interrupts */
1538 /* only Re-enable if disabled by irq */
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01001539 if (test_bit(S_INT_ENABLED, &il->status))
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001540 il_enable_interrupts(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001541
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001542#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001543 if (il_get_debug_level(il) & (IL_DL_ISR)) {
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001544 inta = _il_rd(il, CSR_INT);
1545 inta_mask = _il_rd(il, CSR_INT_MASK);
1546 inta_fh = _il_rd(il, CSR_FH_INT_STATUS);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001547 D_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001548 "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
1549 }
1550#endif
1551}
1552
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001553static int il3945_get_channels_for_scan(struct il_priv *il,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001554 enum ieee80211_band band,
1555 u8 is_active, u8 n_probes,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001556 struct il3945_scan_channel *scan_ch,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001557 struct ieee80211_vif *vif)
1558{
1559 struct ieee80211_channel *chan;
1560 const struct ieee80211_supported_band *sband;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001561 const struct il_channel_info *ch_info;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001562 u16 passive_dwell = 0;
1563 u16 active_dwell = 0;
1564 int added, i;
1565
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001566 sband = il_get_hw_mode(il, band);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001567 if (!sband)
1568 return 0;
1569
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001570 active_dwell = il_get_active_dwell_time(il, band, n_probes);
1571 passive_dwell = il_get_passive_dwell_time(il, band, vif);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001572
1573 if (passive_dwell <= active_dwell)
1574 passive_dwell = active_dwell + 1;
1575
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001576 for (i = 0, added = 0; i < il->scan_request->n_channels; i++) {
1577 chan = il->scan_request->channels[i];
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001578
1579 if (chan->band != band)
1580 continue;
1581
1582 scan_ch->channel = chan->hw_value;
1583
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001584 ch_info = il_get_channel_info(il, band,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001585 scan_ch->channel);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001586 if (!il_is_channel_valid(ch_info)) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001587 D_SCAN(
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001588 "Channel %d is INVALID for this band.\n",
1589 scan_ch->channel);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001590 continue;
1591 }
1592
1593 scan_ch->active_dwell = cpu_to_le16(active_dwell);
1594 scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
1595 /* If passive , set up for auto-switch
1596 * and use long active_dwell time.
1597 */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001598 if (!is_active || il_is_channel_passive(ch_info) ||
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001599 (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
1600 scan_ch->type = 0; /* passive */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001601 if (IL_UCODE_API(il->ucode_ver) == 1)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001602 scan_ch->active_dwell = cpu_to_le16(passive_dwell - 1);
1603 } else {
1604 scan_ch->type = 1; /* active */
1605 }
1606
1607 /* Set direct probe bits. These may be used both for active
1608 * scan channels (probes gets sent right away),
1609 * or for passive channels (probes get se sent only after
1610 * hearing clear Rx packet).*/
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001611 if (IL_UCODE_API(il->ucode_ver) >= 2) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001612 if (n_probes)
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001613 scan_ch->type |= IL39_SCAN_PROBE_MASK(n_probes);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001614 } else {
1615 /* uCode v1 does not allow setting direct probe bits on
1616 * passive channel. */
1617 if ((scan_ch->type & 1) && n_probes)
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001618 scan_ch->type |= IL39_SCAN_PROBE_MASK(n_probes);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001619 }
1620
1621 /* Set txpower levels to defaults */
1622 scan_ch->tpc.dsp_atten = 110;
1623 /* scan_pwr_info->tpc.dsp_atten; */
1624
1625 /*scan_pwr_info->tpc.tx_gain; */
1626 if (band == IEEE80211_BAND_5GHZ)
1627 scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
1628 else {
1629 scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
1630 /* NOTE: if we were doing 6Mb OFDM for scans we'd use
1631 * power level:
1632 * scan_ch->tpc.tx_gain = ((1 << 5) | (2 << 3)) | 3;
1633 */
1634 }
1635
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001636 D_SCAN("Scanning %d [%s %d]\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001637 scan_ch->channel,
1638 (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE",
1639 (scan_ch->type & 1) ?
1640 active_dwell : passive_dwell);
1641
1642 scan_ch++;
1643 added++;
1644 }
1645
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001646 D_SCAN("total channels to scan %d\n", added);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001647 return added;
1648}
1649
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001650static void il3945_init_hw_rates(struct il_priv *il,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001651 struct ieee80211_rate *rates)
1652{
1653 int i;
1654
Stanislaw Gruszka2eb05812011-08-26 16:07:43 +02001655 for (i = 0; i < RATE_COUNT_LEGACY; i++) {
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001656 rates[i].bitrate = il3945_rates[i].ieee * 5;
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01001657 rates[i].hw_value = i; /* Rate scaling will work on idxes */
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001658 rates[i].hw_value_short = i;
1659 rates[i].flags = 0;
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001660 if (i > IL39_LAST_OFDM_RATE || i < IL_FIRST_OFDM_RATE) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001661 /*
1662 * If CCK != 1M then set short preamble rate flag.
1663 */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001664 rates[i].flags |= (il3945_rates[i].plcp == 10) ?
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001665 0 : IEEE80211_RATE_SHORT_PREAMBLE;
1666 }
1667 }
1668}
1669
1670/******************************************************************************
1671 *
1672 * uCode download functions
1673 *
1674 ******************************************************************************/
1675
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001676static void il3945_dealloc_ucode_pci(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001677{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001678 il_free_fw_desc(il->pci_dev, &il->ucode_code);
1679 il_free_fw_desc(il->pci_dev, &il->ucode_data);
1680 il_free_fw_desc(il->pci_dev, &il->ucode_data_backup);
1681 il_free_fw_desc(il->pci_dev, &il->ucode_init);
1682 il_free_fw_desc(il->pci_dev, &il->ucode_init_data);
1683 il_free_fw_desc(il->pci_dev, &il->ucode_boot);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001684}
1685
1686/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001687 * il3945_verify_inst_full - verify runtime uCode image in card vs. host,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001688 * looking at all data.
1689 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001690static int il3945_verify_inst_full(struct il_priv *il, __le32 *image, u32 len)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001691{
1692 u32 val;
1693 u32 save_len = len;
1694 int rc = 0;
1695 u32 errcnt;
1696
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001697 D_INFO("ucode inst image size is %u\n", len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001698
Stanislaw Gruszka0c1a94e2011-08-24 17:37:16 +02001699 il_wr(il, HBUS_TARG_MEM_RADDR,
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001700 IL39_RTC_INST_LOWER_BOUND);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001701
1702 errcnt = 0;
1703 for (; len > 0; len -= sizeof(u32), image++) {
1704 /* read data comes through single port, auto-incr addr */
1705 /* NOTE: Use the debugless read so we don't flood kernel log
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001706 * if IL_DL_IO is set */
Stanislaw Gruszka1c8cae52011-08-24 15:46:03 +02001707 val = _il_rd(il, HBUS_TARG_MEM_RDAT);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001708 if (val != le32_to_cpu(*image)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001709 IL_ERR("uCode INST section is invalid at "
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001710 "offset 0x%x, is 0x%x, s/b 0x%x\n",
1711 save_len - len, val, le32_to_cpu(*image));
1712 rc = -EIO;
1713 errcnt++;
1714 if (errcnt >= 20)
1715 break;
1716 }
1717 }
1718
1719
1720 if (!errcnt)
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001721 D_INFO(
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001722 "ucode image in INSTRUCTION memory is good\n");
1723
1724 return rc;
1725}
1726
1727
1728/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001729 * il3945_verify_inst_sparse - verify runtime uCode image in card vs. host,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001730 * using sample data 100 bytes apart. If these sample points are good,
1731 * it's a pretty good bet that everything between them is good, too.
1732 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001733static int il3945_verify_inst_sparse(struct il_priv *il, __le32 *image, u32 len)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001734{
1735 u32 val;
1736 int rc = 0;
1737 u32 errcnt = 0;
1738 u32 i;
1739
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001740 D_INFO("ucode inst image size is %u\n", len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001741
1742 for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
1743 /* read data comes through single port, auto-incr addr */
1744 /* NOTE: Use the debugless read so we don't flood kernel log
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001745 * if IL_DL_IO is set */
Stanislaw Gruszka0c1a94e2011-08-24 17:37:16 +02001746 il_wr(il, HBUS_TARG_MEM_RADDR,
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001747 i + IL39_RTC_INST_LOWER_BOUND);
Stanislaw Gruszka1c8cae52011-08-24 15:46:03 +02001748 val = _il_rd(il, HBUS_TARG_MEM_RDAT);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001749 if (val != le32_to_cpu(*image)) {
1750#if 0 /* Enable this if you want to see details */
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001751 IL_ERR("uCode INST section is invalid at "
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001752 "offset 0x%x, is 0x%x, s/b 0x%x\n",
1753 i, val, *image);
1754#endif
1755 rc = -EIO;
1756 errcnt++;
1757 if (errcnt >= 3)
1758 break;
1759 }
1760 }
1761
1762 return rc;
1763}
1764
1765
1766/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001767 * il3945_verify_ucode - determine which instruction image is in SRAM,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001768 * and verify its contents
1769 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001770static int il3945_verify_ucode(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001771{
1772 __le32 *image;
1773 u32 len;
1774 int rc = 0;
1775
1776 /* Try bootstrap */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001777 image = (__le32 *)il->ucode_boot.v_addr;
1778 len = il->ucode_boot.len;
1779 rc = il3945_verify_inst_sparse(il, image, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001780 if (rc == 0) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001781 D_INFO("Bootstrap uCode is good in inst SRAM\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001782 return 0;
1783 }
1784
1785 /* Try initialize */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001786 image = (__le32 *)il->ucode_init.v_addr;
1787 len = il->ucode_init.len;
1788 rc = il3945_verify_inst_sparse(il, image, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001789 if (rc == 0) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001790 D_INFO("Initialize uCode is good in inst SRAM\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001791 return 0;
1792 }
1793
1794 /* Try runtime/protocol */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001795 image = (__le32 *)il->ucode_code.v_addr;
1796 len = il->ucode_code.len;
1797 rc = il3945_verify_inst_sparse(il, image, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001798 if (rc == 0) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001799 D_INFO("Runtime uCode is good in inst SRAM\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001800 return 0;
1801 }
1802
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001803 IL_ERR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001804
1805 /* Since nothing seems to match, show first several data entries in
1806 * instruction SRAM, so maybe visual inspection will give a clue.
1807 * Selection of bootstrap image (vs. other images) is arbitrary. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001808 image = (__le32 *)il->ucode_boot.v_addr;
1809 len = il->ucode_boot.len;
1810 rc = il3945_verify_inst_full(il, image, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001811
1812 return rc;
1813}
1814
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001815static void il3945_nic_start(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001816{
1817 /* Remove all resets to allow NIC to operate */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02001818 _il_wr(il, CSR_RESET, 0);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001819}
1820
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001821#define IL3945_UCODE_GET(item) \
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001822static u32 il3945_ucode_get_##item(const struct il_ucode_header *ucode)\
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001823{ \
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001824 return le32_to_cpu(ucode->v1.item); \
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001825}
1826
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001827static u32 il3945_ucode_get_header_size(u32 api_ver)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001828{
1829 return 24;
1830}
1831
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001832static u8 *il3945_ucode_get_data(const struct il_ucode_header *ucode)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001833{
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08001834 return (u8 *) ucode->v1.data;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001835}
1836
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001837IL3945_UCODE_GET(inst_size);
1838IL3945_UCODE_GET(data_size);
1839IL3945_UCODE_GET(init_size);
1840IL3945_UCODE_GET(init_data_size);
1841IL3945_UCODE_GET(boot_size);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001842
1843/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001844 * il3945_read_ucode - Read uCode images from disk file.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001845 *
1846 * Copy into buffers for card to fetch via bus-mastering
1847 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001848static int il3945_read_ucode(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001849{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001850 const struct il_ucode_header *ucode;
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01001851 int ret = -EINVAL, idx;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001852 const struct firmware *ucode_raw;
1853 /* firmware file name contains uCode/driver compatibility version */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001854 const char *name_pre = il->cfg->fw_name_pre;
1855 const unsigned int api_max = il->cfg->ucode_api_max;
1856 const unsigned int api_min = il->cfg->ucode_api_min;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001857 char buf[25];
1858 u8 *src;
1859 size_t len;
1860 u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
1861
1862 /* Ask kernel firmware_class module to get the boot firmware off disk.
1863 * request_firmware() is synchronous, file is in memory on return. */
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01001864 for (idx = api_max; idx >= api_min; idx--) {
1865 sprintf(buf, "%s%u%s", name_pre, idx, ".ucode");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001866 ret = request_firmware(&ucode_raw, buf, &il->pci_dev->dev);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001867 if (ret < 0) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001868 IL_ERR("%s firmware file req failed: %d\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001869 buf, ret);
1870 if (ret == -ENOENT)
1871 continue;
1872 else
1873 goto error;
1874 } else {
Stanislaw Gruszka0c2c8852011-11-15 12:30:17 +01001875 if (idx < api_max)
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001876 IL_ERR("Loaded firmware %s, "
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001877 "which is deprecated. "
1878 " Please use API v%u instead.\n",
1879 buf, api_max);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001880 D_INFO("Got firmware '%s' file "
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001881 "(%zd bytes) from disk\n",
1882 buf, ucode_raw->size);
1883 break;
1884 }
1885 }
1886
1887 if (ret < 0)
1888 goto error;
1889
1890 /* Make sure that we got at least our header! */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001891 if (ucode_raw->size < il3945_ucode_get_header_size(1)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001892 IL_ERR("File size way too small!\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001893 ret = -EINVAL;
1894 goto err_release;
1895 }
1896
1897 /* Data from ucode file: header followed by uCode images */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001898 ucode = (struct il_ucode_header *)ucode_raw->data;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001899
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001900 il->ucode_ver = le32_to_cpu(ucode->ver);
1901 api_ver = IL_UCODE_API(il->ucode_ver);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001902 inst_size = il3945_ucode_get_inst_size(ucode);
1903 data_size = il3945_ucode_get_data_size(ucode);
1904 init_size = il3945_ucode_get_init_size(ucode);
1905 init_data_size = il3945_ucode_get_init_data_size(ucode);
1906 boot_size = il3945_ucode_get_boot_size(ucode);
1907 src = il3945_ucode_get_data(ucode);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001908
1909 /* api_ver should match the api version forming part of the
1910 * firmware filename ... but we don't check for that and only rely
1911 * on the API version read from firmware header from here on forward */
1912
1913 if (api_ver < api_min || api_ver > api_max) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001914 IL_ERR("Driver unable to support your firmware API. "
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001915 "Driver supports v%u, firmware is v%u.\n",
1916 api_max, api_ver);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001917 il->ucode_ver = 0;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001918 ret = -EINVAL;
1919 goto err_release;
1920 }
1921 if (api_ver != api_max)
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001922 IL_ERR("Firmware has old API version. Expected %u, "
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001923 "got %u. New firmware can be obtained "
1924 "from http://www.intellinuxwireless.org.\n",
1925 api_max, api_ver);
1926
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02001927 IL_INFO("loaded firmware version %u.%u.%u.%u\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001928 IL_UCODE_MAJOR(il->ucode_ver),
1929 IL_UCODE_MINOR(il->ucode_ver),
1930 IL_UCODE_API(il->ucode_ver),
1931 IL_UCODE_SERIAL(il->ucode_ver));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001932
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001933 snprintf(il->hw->wiphy->fw_version,
1934 sizeof(il->hw->wiphy->fw_version),
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001935 "%u.%u.%u.%u",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001936 IL_UCODE_MAJOR(il->ucode_ver),
1937 IL_UCODE_MINOR(il->ucode_ver),
1938 IL_UCODE_API(il->ucode_ver),
1939 IL_UCODE_SERIAL(il->ucode_ver));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001940
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001941 D_INFO("f/w package hdr ucode version raw = 0x%x\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02001942 il->ucode_ver);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001943 D_INFO("f/w package hdr runtime inst size = %u\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001944 inst_size);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001945 D_INFO("f/w package hdr runtime data size = %u\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001946 data_size);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001947 D_INFO("f/w package hdr init inst size = %u\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001948 init_size);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001949 D_INFO("f/w package hdr init data size = %u\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001950 init_data_size);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001951 D_INFO("f/w package hdr boot inst size = %u\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001952 boot_size);
1953
1954
1955 /* Verify size of file vs. image size info in file's header */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02001956 if (ucode_raw->size != il3945_ucode_get_header_size(api_ver) +
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001957 inst_size + data_size + init_size +
1958 init_data_size + boot_size) {
1959
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001960 D_INFO(
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001961 "uCode file size %zd does not match expected size\n",
1962 ucode_raw->size);
1963 ret = -EINVAL;
1964 goto err_release;
1965 }
1966
1967 /* Verify that uCode images will fit in card's SRAM */
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001968 if (inst_size > IL39_MAX_INST_SIZE) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001969 D_INFO("uCode instr len %d too large to fit in\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001970 inst_size);
1971 ret = -EINVAL;
1972 goto err_release;
1973 }
1974
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001975 if (data_size > IL39_MAX_DATA_SIZE) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001976 D_INFO("uCode data len %d too large to fit in\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001977 data_size);
1978 ret = -EINVAL;
1979 goto err_release;
1980 }
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001981 if (init_size > IL39_MAX_INST_SIZE) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001982 D_INFO(
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001983 "uCode init instr len %d too large to fit in\n",
1984 init_size);
1985 ret = -EINVAL;
1986 goto err_release;
1987 }
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001988 if (init_data_size > IL39_MAX_DATA_SIZE) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001989 D_INFO(
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001990 "uCode init data len %d too large to fit in\n",
1991 init_data_size);
1992 ret = -EINVAL;
1993 goto err_release;
1994 }
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01001995 if (boot_size > IL39_MAX_BSM_SIZE) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01001996 D_INFO(
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08001997 "uCode boot instr len %d too large to fit in\n",
1998 boot_size);
1999 ret = -EINVAL;
2000 goto err_release;
2001 }
2002
2003 /* Allocate ucode buffers for card's bus-master loading ... */
2004
2005 /* Runtime instructions and 2 copies of data:
2006 * 1) unmodified from disk
2007 * 2) backup cache for save/restore during power-downs */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002008 il->ucode_code.len = inst_size;
2009 il_alloc_fw_desc(il->pci_dev, &il->ucode_code);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002010
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002011 il->ucode_data.len = data_size;
2012 il_alloc_fw_desc(il->pci_dev, &il->ucode_data);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002013
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002014 il->ucode_data_backup.len = data_size;
2015 il_alloc_fw_desc(il->pci_dev, &il->ucode_data_backup);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002016
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002017 if (!il->ucode_code.v_addr || !il->ucode_data.v_addr ||
2018 !il->ucode_data_backup.v_addr)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002019 goto err_pci_alloc;
2020
2021 /* Initialization instructions and data */
2022 if (init_size && init_data_size) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002023 il->ucode_init.len = init_size;
2024 il_alloc_fw_desc(il->pci_dev, &il->ucode_init);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002025
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002026 il->ucode_init_data.len = init_data_size;
2027 il_alloc_fw_desc(il->pci_dev, &il->ucode_init_data);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002028
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002029 if (!il->ucode_init.v_addr || !il->ucode_init_data.v_addr)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002030 goto err_pci_alloc;
2031 }
2032
2033 /* Bootstrap (instructions only, no data) */
2034 if (boot_size) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002035 il->ucode_boot.len = boot_size;
2036 il_alloc_fw_desc(il->pci_dev, &il->ucode_boot);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002037
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002038 if (!il->ucode_boot.v_addr)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002039 goto err_pci_alloc;
2040 }
2041
2042 /* Copy images into buffers for card's bus-master reads ... */
2043
2044 /* Runtime instructions (first block of data in file) */
2045 len = inst_size;
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002046 D_INFO(
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002047 "Copying (but not loading) uCode instr len %zd\n", len);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002048 memcpy(il->ucode_code.v_addr, src, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002049 src += len;
2050
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002051 D_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002052 il->ucode_code.v_addr, (u32)il->ucode_code.p_addr);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002053
2054 /* Runtime data (2nd block)
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002055 * NOTE: Copy into backup buffer will be done in il3945_up() */
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002056 len = data_size;
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002057 D_INFO(
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002058 "Copying (but not loading) uCode data len %zd\n", len);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002059 memcpy(il->ucode_data.v_addr, src, len);
2060 memcpy(il->ucode_data_backup.v_addr, src, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002061 src += len;
2062
2063 /* Initialization instructions (3rd block) */
2064 if (init_size) {
2065 len = init_size;
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002066 D_INFO(
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002067 "Copying (but not loading) init instr len %zd\n", len);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002068 memcpy(il->ucode_init.v_addr, src, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002069 src += len;
2070 }
2071
2072 /* Initialization data (4th block) */
2073 if (init_data_size) {
2074 len = init_data_size;
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002075 D_INFO(
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002076 "Copying (but not loading) init data len %zd\n", len);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002077 memcpy(il->ucode_init_data.v_addr, src, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002078 src += len;
2079 }
2080
2081 /* Bootstrap instructions (5th block) */
2082 len = boot_size;
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002083 D_INFO(
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002084 "Copying (but not loading) boot instr len %zd\n", len);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002085 memcpy(il->ucode_boot.v_addr, src, len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002086
2087 /* We have our copies now, allow OS release its copies */
2088 release_firmware(ucode_raw);
2089 return 0;
2090
2091 err_pci_alloc:
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002092 IL_ERR("failed to allocate pci memory\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002093 ret = -ENOMEM;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002094 il3945_dealloc_ucode_pci(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002095
2096 err_release:
2097 release_firmware(ucode_raw);
2098
2099 error:
2100 return ret;
2101}
2102
2103
2104/**
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002105 * il3945_set_ucode_ptrs - Set uCode address location
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002106 *
2107 * Tell initialization uCode where to find runtime uCode.
2108 *
2109 * BSM registers initially contain pointers to initialization uCode.
2110 * We need to replace them to load runtime uCode inst and data,
2111 * and to save runtime data when powering down.
2112 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002113static int il3945_set_ucode_ptrs(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002114{
2115 dma_addr_t pinst;
2116 dma_addr_t pdata;
2117
2118 /* bits 31:0 for 3945 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002119 pinst = il->ucode_code.p_addr;
2120 pdata = il->ucode_data_backup.p_addr;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002121
2122 /* Tell bootstrap uCode where to find image to load */
Stanislaw Gruszkadb54eb52011-08-24 21:06:33 +02002123 il_wr_prph(il, BSM_DRAM_INST_PTR_REG, pinst);
2124 il_wr_prph(il, BSM_DRAM_DATA_PTR_REG, pdata);
2125 il_wr_prph(il, BSM_DRAM_DATA_BYTECOUNT_REG,
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002126 il->ucode_data.len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002127
2128 /* Inst byte count must be last to set up, bit 31 signals uCode
2129 * that all new ptr/size info is in place */
Stanislaw Gruszkadb54eb52011-08-24 21:06:33 +02002130 il_wr_prph(il, BSM_DRAM_INST_BYTECOUNT_REG,
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002131 il->ucode_code.len | BSM_DRAM_INST_LOAD);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002132
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002133 D_INFO("Runtime uCode pointers are set.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002134
2135 return 0;
2136}
2137
2138/**
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02002139 * il3945_init_alive_start - Called after N_ALIVE notification received
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002140 *
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02002141 * Called after N_ALIVE notification received from "initialize" uCode.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002142 *
2143 * Tell "initialize" uCode to go ahead and load the runtime uCode.
2144 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002145static void il3945_init_alive_start(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002146{
2147 /* Check alive response for "valid" sign from uCode */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002148 if (il->card_alive_init.is_valid != UCODE_VALID_OK) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002149 /* We had an error bringing up the hardware, so take it
2150 * all the way back down so we can try again */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002151 D_INFO("Initialize Alive failed.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002152 goto restart;
2153 }
2154
2155 /* Bootstrap uCode has loaded initialize uCode ... verify inst image.
2156 * This is a paranoid check, because we would not have gotten the
2157 * "initialize" alive if code weren't properly loaded. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002158 if (il3945_verify_ucode(il)) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002159 /* Runtime instruction load was bad;
2160 * take it all the way back down so we can try again */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002161 D_INFO("Bad \"initialize\" uCode load.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002162 goto restart;
2163 }
2164
2165 /* Send pointers to protocol/runtime uCode image ... init code will
2166 * load and launch runtime uCode, which will send us another "Alive"
2167 * notification. */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002168 D_INFO("Initialization Alive received.\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002169 if (il3945_set_ucode_ptrs(il)) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002170 /* Runtime instruction load won't happen;
2171 * take it all the way back down so we can try again */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002172 D_INFO("Couldn't set up uCode pointers.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002173 goto restart;
2174 }
2175 return;
2176
2177 restart:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002178 queue_work(il->workqueue, &il->restart);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002179}
2180
2181/**
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02002182 * il3945_alive_start - called after N_ALIVE notification received
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002183 * from protocol/runtime uCode (initialization uCode's
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002184 * Alive gets handled by il3945_init_alive_start()).
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002185 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002186static void il3945_alive_start(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002187{
2188 int thermal_spin = 0;
2189 u32 rfkill;
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01002190 struct il_rxon_context *ctx = &il->ctx;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002191
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002192 D_INFO("Runtime Alive received.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002193
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002194 if (il->card_alive.is_valid != UCODE_VALID_OK) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002195 /* We had an error bringing up the hardware, so take it
2196 * all the way back down so we can try again */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002197 D_INFO("Alive failed.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002198 goto restart;
2199 }
2200
2201 /* Initialize uCode has loaded Runtime uCode ... verify inst image.
2202 * This is a paranoid check, because we would not have gotten the
2203 * "runtime" alive if code weren't properly loaded. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002204 if (il3945_verify_ucode(il)) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002205 /* Runtime instruction load was bad;
2206 * take it all the way back down so we can try again */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002207 D_INFO("Bad runtime uCode load.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002208 goto restart;
2209 }
2210
Stanislaw Gruszkadb54eb52011-08-24 21:06:33 +02002211 rfkill = il_rd_prph(il, APMG_RFKILL_REG);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002212 D_INFO("RFKILL status: 0x%x\n", rfkill);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002213
2214 if (rfkill & 0x1) {
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002215 clear_bit(S_RF_KILL_HW, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002216 /* if RFKILL is not on, then wait for thermal
2217 * sensor in adapter to kick in */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002218 while (il3945_hw_get_temperature(il) == 0) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002219 thermal_spin++;
2220 udelay(10);
2221 }
2222
2223 if (thermal_spin)
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002224 D_INFO("Thermal calibration took %dus\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002225 thermal_spin * 10);
2226 } else
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002227 set_bit(S_RF_KILL_HW, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002228
2229 /* After the ALIVE response, we can send commands to 3945 uCode */
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002230 set_bit(S_ALIVE, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002231
2232 /* Enable watchdog to monitor the driver tx queues */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002233 il_setup_watchdog(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002234
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002235 if (il_is_rfkill(il))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002236 return;
2237
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002238 ieee80211_wake_queues(il->hw);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002239
Stanislaw Gruszka2eb05812011-08-26 16:07:43 +02002240 il->active_rate = RATES_MASK_3945;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002241
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002242 il_power_update_mode(il, true);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002243
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01002244 if (il_is_associated(il)) {
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002245 struct il3945_rxon_cmd *active_rxon =
2246 (struct il3945_rxon_cmd *)(&ctx->active);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002247
2248 ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
2249 active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
2250 } else {
2251 /* Initialize our rx_config data */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002252 il_connection_init_rx_config(il, ctx);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002253 }
2254
2255 /* Configure Bluetooth device coexistence support */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002256 il_send_bt_config(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002257
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002258 set_bit(S_READY, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002259
2260 /* Configure the adapter for unassociated operation */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002261 il3945_commit_rxon(il, ctx);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002262
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002263 il3945_reg_txpower_periodic(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002264
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002265 D_INFO("ALIVE processing complete.\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002266 wake_up(&il->wait_command_queue);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002267
2268 return;
2269
2270 restart:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002271 queue_work(il->workqueue, &il->restart);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002272}
2273
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002274static void il3945_cancel_deferred_work(struct il_priv *il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002275
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002276static void __il3945_down(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002277{
2278 unsigned long flags;
2279 int exit_pending;
2280
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002281 D_INFO(DRV_NAME " is going down\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002282
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002283 il_scan_cancel_timeout(il, 200);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002284
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002285 exit_pending = test_and_set_bit(S_EXIT_PENDING, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002286
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002287 /* Stop TX queues watchdog. We need to have S_EXIT_PENDING bit set
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002288 * to prevent rearm timer */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002289 del_timer_sync(&il->watchdog);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002290
2291 /* Station information will now be cleared in device */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002292 il_clear_ucode_stations(il, NULL);
2293 il_dealloc_bcast_stations(il);
2294 il_clear_driver_stations(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002295
2296 /* Unblock any waiting calls */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002297 wake_up_all(&il->wait_command_queue);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002298
2299 /* Wipe out the EXIT_PENDING status bit if we are not actually
2300 * exiting the module */
2301 if (!exit_pending)
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002302 clear_bit(S_EXIT_PENDING, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002303
2304 /* stop and reset the on-board processor */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002305 _il_wr(il, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002306
2307 /* tell the device to stop sending interrupts */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002308 spin_lock_irqsave(&il->lock, flags);
2309 il_disable_interrupts(il);
2310 spin_unlock_irqrestore(&il->lock, flags);
2311 il3945_synchronize_irq(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002312
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002313 if (il->mac80211_registered)
2314 ieee80211_stop_queues(il->hw);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002315
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002316 /* If we have not previously called il3945_init() then
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002317 * clear all bits but the RF Kill bits and return */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002318 if (!il_is_init(il)) {
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002319 il->status = test_bit(S_RF_KILL_HW, &il->status) <<
2320 S_RF_KILL_HW |
2321 test_bit(S_GEO_CONFIGURED, &il->status) <<
2322 S_GEO_CONFIGURED |
2323 test_bit(S_EXIT_PENDING, &il->status) <<
2324 S_EXIT_PENDING;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002325 goto exit;
2326 }
2327
2328 /* ...otherwise clear out all the status bits but the RF Kill
2329 * bit and continue taking the NIC down. */
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002330 il->status &= test_bit(S_RF_KILL_HW, &il->status) <<
2331 S_RF_KILL_HW |
2332 test_bit(S_GEO_CONFIGURED, &il->status) <<
2333 S_GEO_CONFIGURED |
2334 test_bit(S_FW_ERROR, &il->status) <<
2335 S_FW_ERROR |
2336 test_bit(S_EXIT_PENDING, &il->status) <<
2337 S_EXIT_PENDING;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002338
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002339 il3945_hw_txq_ctx_stop(il);
2340 il3945_hw_rxq_stop(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002341
2342 /* Power-down device's busmaster DMA clocks */
Stanislaw Gruszkadb54eb52011-08-24 21:06:33 +02002343 il_wr_prph(il, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002344 udelay(5);
2345
2346 /* Stop the device, and put it in low power state */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002347 il_apm_stop(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002348
2349 exit:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002350 memset(&il->card_alive, 0, sizeof(struct il_alive_resp));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002351
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002352 if (il->beacon_skb)
2353 dev_kfree_skb(il->beacon_skb);
2354 il->beacon_skb = NULL;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002355
2356 /* clear out any free frames */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002357 il3945_clear_free_frames(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002358}
2359
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002360static void il3945_down(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002361{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002362 mutex_lock(&il->mutex);
2363 __il3945_down(il);
2364 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002365
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002366 il3945_cancel_deferred_work(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002367}
2368
2369#define MAX_HW_RESTARTS 5
2370
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002371static int il3945_alloc_bcast_station(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002372{
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01002373 struct il_rxon_context *ctx = &il->ctx;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002374 unsigned long flags;
2375 u8 sta_id;
2376
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002377 spin_lock_irqsave(&il->sta_lock, flags);
2378 sta_id = il_prep_station(il, ctx,
Stanislaw Gruszkad2ddf622011-08-16 14:17:04 +02002379 il_bcast_addr, false, NULL);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002380 if (sta_id == IL_INVALID_STATION) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002381 IL_ERR("Unable to prepare broadcast station\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002382 spin_unlock_irqrestore(&il->sta_lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002383
2384 return -EINVAL;
2385 }
2386
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002387 il->stations[sta_id].used |= IL_STA_DRIVER_ACTIVE;
2388 il->stations[sta_id].used |= IL_STA_BCAST;
2389 spin_unlock_irqrestore(&il->sta_lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002390
2391 return 0;
2392}
2393
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002394static int __il3945_up(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002395{
2396 int rc, i;
2397
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002398 rc = il3945_alloc_bcast_station(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002399 if (rc)
2400 return rc;
2401
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002402 if (test_bit(S_EXIT_PENDING, &il->status)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002403 IL_WARN("Exit pending; will not bring the NIC up\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002404 return -EIO;
2405 }
2406
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002407 if (!il->ucode_data_backup.v_addr || !il->ucode_data.v_addr) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002408 IL_ERR("ucode not available for device bring up\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002409 return -EIO;
2410 }
2411
2412 /* If platform's RF_KILL switch is NOT set to KILL */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002413 if (_il_rd(il, CSR_GP_CNTRL) &
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002414 CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002415 clear_bit(S_RF_KILL_HW, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002416 else {
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002417 set_bit(S_RF_KILL_HW, &il->status);
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002418 IL_WARN("Radio disabled by HW RF Kill switch\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002419 return -ENODEV;
2420 }
2421
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002422 _il_wr(il, CSR_INT, 0xFFFFFFFF);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002423
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002424 rc = il3945_hw_nic_init(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002425 if (rc) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002426 IL_ERR("Unable to int nic\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002427 return rc;
2428 }
2429
2430 /* make sure rfkill handshake bits are cleared */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002431 _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
2432 _il_wr(il, CSR_UCODE_DRV_GP1_CLR,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002433 CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
2434
2435 /* clear (again), then enable host interrupts */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002436 _il_wr(il, CSR_INT, 0xFFFFFFFF);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002437 il_enable_interrupts(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002438
2439 /* really make sure rfkill handshake bits are cleared */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002440 _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
2441 _il_wr(il, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002442
2443 /* Copy original ucode data image from disk into backup cache.
2444 * This will be used to initialize the on-board processor's
2445 * data SRAM for a clean start when the runtime program first loads. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002446 memcpy(il->ucode_data_backup.v_addr, il->ucode_data.v_addr,
2447 il->ucode_data.len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002448
2449 /* We return success when we resume from suspend and rf_kill is on. */
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002450 if (test_bit(S_RF_KILL_HW, &il->status))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002451 return 0;
2452
2453 for (i = 0; i < MAX_HW_RESTARTS; i++) {
2454
2455 /* load bootstrap state machine,
2456 * load bootstrap program into processor's memory,
2457 * prepare to load the "initialize" uCode */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002458 rc = il->cfg->ops->lib->load_ucode(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002459
2460 if (rc) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002461 IL_ERR(
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002462 "Unable to set up bootstrap uCode: %d\n", rc);
2463 continue;
2464 }
2465
2466 /* start card; "initialize" will load runtime ucode */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002467 il3945_nic_start(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002468
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002469 D_INFO(DRV_NAME " is coming up\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002470
2471 return 0;
2472 }
2473
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002474 set_bit(S_EXIT_PENDING, &il->status);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002475 __il3945_down(il);
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002476 clear_bit(S_EXIT_PENDING, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002477
2478 /* tried to restart and config the device for as long as our
2479 * patience could withstand */
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002480 IL_ERR("Unable to initialize device after %d attempts.\n", i);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002481 return -EIO;
2482}
2483
2484
2485/*****************************************************************************
2486 *
2487 * Workqueue callbacks
2488 *
2489 *****************************************************************************/
2490
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002491static void il3945_bg_init_alive_start(struct work_struct *data)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002492{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002493 struct il_priv *il =
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002494 container_of(data, struct il_priv, init_alive_start.work);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002495
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002496 mutex_lock(&il->mutex);
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002497 if (test_bit(S_EXIT_PENDING, &il->status))
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002498 goto out;
2499
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002500 il3945_init_alive_start(il);
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002501out:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002502 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002503}
2504
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002505static void il3945_bg_alive_start(struct work_struct *data)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002506{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002507 struct il_priv *il =
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002508 container_of(data, struct il_priv, alive_start.work);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002509
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002510 mutex_lock(&il->mutex);
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002511 if (test_bit(S_EXIT_PENDING, &il->status))
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002512 goto out;
2513
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002514 il3945_alive_start(il);
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002515out:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002516 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002517}
2518
2519/*
2520 * 3945 cannot interrupt driver when hardware rf kill switch toggles;
2521 * driver must poll CSR_GP_CNTRL_REG register for change. This register
2522 * *is* readable even when device has been SW_RESET into low power mode
2523 * (e.g. during RF KILL).
2524 */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002525static void il3945_rfkill_poll(struct work_struct *data)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002526{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002527 struct il_priv *il =
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002528 container_of(data, struct il_priv, _3945.rfkill_poll.work);
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002529 bool old_rfkill = test_bit(S_RF_KILL_HW, &il->status);
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02002530 bool new_rfkill = !(_il_rd(il, CSR_GP_CNTRL)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002531 & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
2532
2533 if (new_rfkill != old_rfkill) {
2534 if (new_rfkill)
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002535 set_bit(S_RF_KILL_HW, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002536 else
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002537 clear_bit(S_RF_KILL_HW, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002538
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002539 wiphy_rfkill_set_hw_state(il->hw->wiphy, new_rfkill);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002540
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002541 D_RF_KILL("RF_KILL bit toggled to %s.\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002542 new_rfkill ? "disable radio" : "enable radio");
2543 }
2544
2545 /* Keep this running, even if radio now enabled. This will be
2546 * cancelled in mac_start() if system decides to start again */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002547 queue_delayed_work(il->workqueue, &il->_3945.rfkill_poll,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002548 round_jiffies_relative(2 * HZ));
2549
2550}
2551
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002552int il3945_request_scan(struct il_priv *il, struct ieee80211_vif *vif)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002553{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002554 struct il_host_cmd cmd = {
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02002555 .id = C_SCAN,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002556 .len = sizeof(struct il3945_scan_cmd),
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002557 .flags = CMD_SIZE_HUGE,
2558 };
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002559 struct il3945_scan_cmd *scan;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002560 u8 n_probes = 0;
2561 enum ieee80211_band band;
2562 bool is_active = false;
2563 int ret;
Stanislaw Gruszkadd6d2a82011-06-08 15:28:26 +02002564 u16 len;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002565
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002566 lockdep_assert_held(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002567
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002568 if (!il->scan_cmd) {
2569 il->scan_cmd = kmalloc(sizeof(struct il3945_scan_cmd) +
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002570 IL_MAX_SCAN_SIZE, GFP_KERNEL);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002571 if (!il->scan_cmd) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002572 D_SCAN("Fail to allocate scan memory\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002573 return -ENOMEM;
2574 }
2575 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002576 scan = il->scan_cmd;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002577 memset(scan, 0, sizeof(struct il3945_scan_cmd) + IL_MAX_SCAN_SIZE);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002578
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002579 scan->quiet_plcp_th = IL_PLCP_QUIET_THRESH;
2580 scan->quiet_time = IL_ACTIVE_QUIET_TIME;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002581
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01002582 if (il_is_associated(il)) {
Stanislaw Gruszkadd6d2a82011-06-08 15:28:26 +02002583 u16 interval;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002584 u32 extra;
2585 u32 suspend_time = 100;
2586 u32 scan_suspend_time = 100;
2587
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002588 D_INFO("Scanning while associated...\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002589
Stanislaw Gruszkadd6d2a82011-06-08 15:28:26 +02002590 interval = vif->bss_conf.beacon_int;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002591
2592 scan->suspend_time = 0;
2593 scan->max_out_time = cpu_to_le32(200 * 1024);
2594 if (!interval)
2595 interval = suspend_time;
2596 /*
2597 * suspend time format:
2598 * 0-19: beacon interval in usec (time before exec.)
2599 * 20-23: 0
2600 * 24-31: number of beacons (suspend between channels)
2601 */
2602
2603 extra = (suspend_time / interval) << 24;
2604 scan_suspend_time = 0xFF0FFFFF &
2605 (extra | ((suspend_time % interval) * 1024));
2606
2607 scan->suspend_time = cpu_to_le32(scan_suspend_time);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002608 D_SCAN("suspend_time 0x%X beacon interval %d\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002609 scan_suspend_time, interval);
2610 }
2611
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002612 if (il->scan_request->n_ssids) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002613 int i, p = 0;
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002614 D_SCAN("Kicking off active scan\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002615 for (i = 0; i < il->scan_request->n_ssids; i++) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002616 /* always does wildcard anyway */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002617 if (!il->scan_request->ssids[i].ssid_len)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002618 continue;
2619 scan->direct_scan[p].id = WLAN_EID_SSID;
2620 scan->direct_scan[p].len =
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002621 il->scan_request->ssids[i].ssid_len;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002622 memcpy(scan->direct_scan[p].ssid,
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002623 il->scan_request->ssids[i].ssid,
2624 il->scan_request->ssids[i].ssid_len);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002625 n_probes++;
2626 p++;
2627 }
2628 is_active = true;
2629 } else
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002630 D_SCAN("Kicking off passive scan.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002631
2632 /* We don't build a direct scan probe request; the uCode will do
2633 * that based on the direct_mask added to each channel entry */
2634 scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01002635 scan->tx_cmd.sta_id = il->ctx.bcast_sta_id;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002636 scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
2637
2638 /* flags + rate selection */
2639
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002640 switch (il->scan_band) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002641 case IEEE80211_BAND_2GHZ:
2642 scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
Stanislaw Gruszka2eb05812011-08-26 16:07:43 +02002643 scan->tx_cmd.rate = RATE_1M_PLCP;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002644 band = IEEE80211_BAND_2GHZ;
2645 break;
2646 case IEEE80211_BAND_5GHZ:
Stanislaw Gruszka2eb05812011-08-26 16:07:43 +02002647 scan->tx_cmd.rate = RATE_6M_PLCP;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002648 band = IEEE80211_BAND_5GHZ;
2649 break;
2650 default:
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002651 IL_WARN("Invalid scan band\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002652 return -EIO;
2653 }
2654
2655 /*
2656 * If active scaning is requested but a certain channel
2657 * is marked passive, we can do active scanning if we
2658 * detect transmissions.
2659 */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002660 scan->good_CRC_th = is_active ? IL_GOOD_CRC_TH_DEFAULT :
2661 IL_GOOD_CRC_TH_DISABLED;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002662
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002663 len = il_fill_probe_req(il, (struct ieee80211_mgmt *)scan->data,
2664 vif->addr, il->scan_request->ie,
2665 il->scan_request->ie_len,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002666 IL_MAX_SCAN_SIZE - sizeof(*scan));
Stanislaw Gruszkadd6d2a82011-06-08 15:28:26 +02002667 scan->tx_cmd.len = cpu_to_le16(len);
2668
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002669 /* select Rx antennas */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002670 scan->flags |= il3945_get_antenna_flags(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002671
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002672 scan->channel_count = il3945_get_channels_for_scan(il, band, is_active, n_probes,
Stanislaw Gruszkadd6d2a82011-06-08 15:28:26 +02002673 (void *)&scan->data[len], vif);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002674 if (scan->channel_count == 0) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002675 D_SCAN("channel count %d\n", scan->channel_count);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002676 return -EIO;
2677 }
2678
2679 cmd.len += le16_to_cpu(scan->tx_cmd.len) +
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002680 scan->channel_count * sizeof(struct il3945_scan_channel);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002681 cmd.data = scan;
2682 scan->len = cpu_to_le16(cmd.len);
2683
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002684 set_bit(S_SCAN_HW, &il->status);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002685 ret = il_send_cmd_sync(il, &cmd);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002686 if (ret)
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002687 clear_bit(S_SCAN_HW, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002688 return ret;
2689}
2690
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002691void il3945_post_scan(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002692{
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01002693 struct il_rxon_context *ctx = &il->ctx;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002694
2695 /*
2696 * Since setting the RXON may have been deferred while
2697 * performing the scan, fire one off if needed
2698 */
2699 if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002700 il3945_commit_rxon(il, ctx);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002701}
2702
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002703static void il3945_bg_restart(struct work_struct *data)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002704{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002705 struct il_priv *il = container_of(data, struct il_priv, restart);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002706
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002707 if (test_bit(S_EXIT_PENDING, &il->status))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002708 return;
2709
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002710 if (test_and_clear_bit(S_FW_ERROR, &il->status)) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002711 mutex_lock(&il->mutex);
Stanislaw Gruszka17d6e552011-08-29 12:52:20 +02002712 il->ctx.vif = NULL;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002713 il->is_open = 0;
2714 mutex_unlock(&il->mutex);
2715 il3945_down(il);
2716 ieee80211_restart_hw(il->hw);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002717 } else {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002718 il3945_down(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002719
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002720 mutex_lock(&il->mutex);
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002721 if (test_bit(S_EXIT_PENDING, &il->status)) {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002722 mutex_unlock(&il->mutex);
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002723 return;
2724 }
2725
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002726 __il3945_up(il);
2727 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002728 }
2729}
2730
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002731static void il3945_bg_rx_replenish(struct work_struct *data)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002732{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002733 struct il_priv *il =
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002734 container_of(data, struct il_priv, rx_replenish);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002735
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002736 mutex_lock(&il->mutex);
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002737 if (test_bit(S_EXIT_PENDING, &il->status))
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002738 goto out;
2739
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002740 il3945_rx_replenish(il);
Stanislaw Gruszka28a6e572011-04-28 11:51:32 +02002741out:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002742 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002743}
2744
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002745void il3945_post_associate(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002746{
2747 int rc = 0;
2748 struct ieee80211_conf *conf = NULL;
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01002749 struct il_rxon_context *ctx = &il->ctx;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002750
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002751 if (!ctx->vif || !il->is_open)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002752 return;
2753
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002754 D_ASSOC("Associated as %d to: %pM\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002755 ctx->vif->bss_conf.aid, ctx->active.bssid_addr);
2756
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002757 if (test_bit(S_EXIT_PENDING, &il->status))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002758 return;
2759
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002760 il_scan_cancel_timeout(il, 200);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002761
Stanislaw Gruszka6278dda2011-08-31 11:13:05 +02002762 conf = &il->hw->conf;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002763
2764 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002765 il3945_commit_rxon(il, ctx);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002766
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002767 rc = il_send_rxon_timing(il, ctx);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002768 if (rc)
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02002769 IL_WARN("C_RXON_TIMING failed - "
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002770 "Attempting to continue.\n");
2771
2772 ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
2773
2774 ctx->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid);
2775
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002776 D_ASSOC("assoc id %d beacon interval %d\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002777 ctx->vif->bss_conf.aid, ctx->vif->bss_conf.beacon_int);
2778
2779 if (ctx->vif->bss_conf.use_short_preamble)
2780 ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
2781 else
2782 ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
2783
2784 if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
2785 if (ctx->vif->bss_conf.use_short_slot)
2786 ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
2787 else
2788 ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
2789 }
2790
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002791 il3945_commit_rxon(il, ctx);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002792
2793 switch (ctx->vif->type) {
2794 case NL80211_IFTYPE_STATION:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002795 il3945_rate_scale_init(il->hw, IL_AP_ID);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002796 break;
2797 case NL80211_IFTYPE_ADHOC:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002798 il3945_send_beacon_cmd(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002799 break;
2800 default:
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002801 IL_ERR("%s Should not be called in %d mode\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002802 __func__, ctx->vif->type);
2803 break;
2804 }
2805}
2806
2807/*****************************************************************************
2808 *
2809 * mac80211 entry point functions
2810 *
2811 *****************************************************************************/
2812
2813#define UCODE_READY_TIMEOUT (2 * HZ)
2814
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002815static int il3945_mac_start(struct ieee80211_hw *hw)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002816{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002817 struct il_priv *il = hw->priv;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002818 int ret;
2819
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002820 D_MAC80211("enter\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002821
2822 /* we should be verifying the device is ready to be opened */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002823 mutex_lock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002824
2825 /* fetch ucode file from disk, alloc and copy to bus-master buffers ...
2826 * ucode filename and max sizes are card-specific. */
2827
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002828 if (!il->ucode_code.len) {
2829 ret = il3945_read_ucode(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002830 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002831 IL_ERR("Could not read microcode: %d\n", ret);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002832 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002833 goto out_release_irq;
2834 }
2835 }
2836
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002837 ret = __il3945_up(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002838
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002839 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002840
2841 if (ret)
2842 goto out_release_irq;
2843
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002844 D_INFO("Start UP work.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002845
2846 /* Wait for START_ALIVE from ucode. Otherwise callbacks from
2847 * mac80211 will not be run successfully. */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002848 ret = wait_event_timeout(il->wait_command_queue,
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002849 test_bit(S_READY, &il->status),
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002850 UCODE_READY_TIMEOUT);
2851 if (!ret) {
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002852 if (!test_bit(S_READY, &il->status)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02002853 IL_ERR(
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002854 "Wait for START_ALIVE timeout after %dms.\n",
2855 jiffies_to_msecs(UCODE_READY_TIMEOUT));
2856 ret = -ETIMEDOUT;
2857 goto out_release_irq;
2858 }
2859 }
2860
2861 /* ucode is running and will send rfkill notifications,
2862 * no need to poll the killswitch state anymore */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002863 cancel_delayed_work(&il->_3945.rfkill_poll);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002864
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002865 il->is_open = 1;
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002866 D_MAC80211("leave\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002867 return 0;
2868
2869out_release_irq:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002870 il->is_open = 0;
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002871 D_MAC80211("leave - failed\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002872 return ret;
2873}
2874
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002875static void il3945_mac_stop(struct ieee80211_hw *hw)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002876{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002877 struct il_priv *il = hw->priv;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002878
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002879 D_MAC80211("enter\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002880
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002881 if (!il->is_open) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002882 D_MAC80211("leave - skip\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002883 return;
2884 }
2885
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002886 il->is_open = 0;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002887
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002888 il3945_down(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002889
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002890 flush_workqueue(il->workqueue);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002891
2892 /* start polling the killswitch state again */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002893 queue_delayed_work(il->workqueue, &il->_3945.rfkill_poll,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002894 round_jiffies_relative(2 * HZ));
2895
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002896 D_MAC80211("leave\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002897}
2898
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002899static void il3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002900{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002901 struct il_priv *il = hw->priv;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002902
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002903 D_MAC80211("enter\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002904
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002905 D_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002906 ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
2907
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002908 if (il3945_tx_skb(il, skb))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002909 dev_kfree_skb_any(skb);
2910
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002911 D_MAC80211("leave\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002912}
2913
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002914void il3945_config_ap(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002915{
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01002916 struct il_rxon_context *ctx = &il->ctx;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002917 struct ieee80211_vif *vif = ctx->vif;
2918 int rc = 0;
2919
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01002920 if (test_bit(S_EXIT_PENDING, &il->status))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002921 return;
2922
2923 /* The following should be done only at AP bring up */
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01002924 if (!(il_is_associated(il))) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002925
2926 /* RXON - unassoc (to set timing command) */
2927 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002928 il3945_commit_rxon(il, ctx);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002929
2930 /* RXON Timing */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002931 rc = il_send_rxon_timing(il, ctx);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002932 if (rc)
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02002933 IL_WARN("C_RXON_TIMING failed - "
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002934 "Attempting to continue.\n");
2935
2936 ctx->staging.assoc_id = 0;
2937
2938 if (vif->bss_conf.use_short_preamble)
2939 ctx->staging.flags |=
2940 RXON_FLG_SHORT_PREAMBLE_MSK;
2941 else
2942 ctx->staging.flags &=
2943 ~RXON_FLG_SHORT_PREAMBLE_MSK;
2944
2945 if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
2946 if (vif->bss_conf.use_short_slot)
2947 ctx->staging.flags |=
2948 RXON_FLG_SHORT_SLOT_MSK;
2949 else
2950 ctx->staging.flags &=
2951 ~RXON_FLG_SHORT_SLOT_MSK;
2952 }
2953 /* restore RXON assoc */
2954 ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002955 il3945_commit_rxon(il, ctx);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002956 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002957 il3945_send_beacon_cmd(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002958}
2959
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002960static int il3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002961 struct ieee80211_vif *vif,
2962 struct ieee80211_sta *sta,
2963 struct ieee80211_key_conf *key)
2964{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002965 struct il_priv *il = hw->priv;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002966 int ret = 0;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002967 u8 sta_id = IL_INVALID_STATION;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002968 u8 static_key;
2969
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002970 D_MAC80211("enter\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002971
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002972 if (il3945_mod_params.sw_crypto) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01002973 D_MAC80211("leave - hwcrypto disabled\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002974 return -EOPNOTSUPP;
2975 }
2976
2977 /*
2978 * To support IBSS RSN, don't program group keys in IBSS, the
2979 * hardware will then not attempt to decrypt the frames.
2980 */
2981 if (vif->type == NL80211_IFTYPE_ADHOC &&
2982 !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
2983 return -EOPNOTSUPP;
2984
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01002985 static_key = !il_is_associated(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002986
2987 if (!static_key) {
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002988 sta_id = il_sta_id_or_broadcast(
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01002989 il, &il->ctx, sta);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02002990 if (sta_id == IL_INVALID_STATION)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002991 return -EINVAL;
2992 }
2993
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02002994 mutex_lock(&il->mutex);
2995 il_scan_cancel_timeout(il, 100);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08002996
2997 switch (cmd) {
2998 case SET_KEY:
2999 if (static_key)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003000 ret = il3945_set_static_key(il, key);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003001 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003002 ret = il3945_set_dynamic_key(il, key, sta_id);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003003 D_MAC80211("enable hwcrypto key\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003004 break;
3005 case DISABLE_KEY:
3006 if (static_key)
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003007 ret = il3945_remove_static_key(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003008 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003009 ret = il3945_clear_sta_key_info(il, sta_id);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003010 D_MAC80211("disable hwcrypto key\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003011 break;
3012 default:
3013 ret = -EINVAL;
3014 }
3015
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003016 mutex_unlock(&il->mutex);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003017 D_MAC80211("leave\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003018
3019 return ret;
3020}
3021
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003022static int il3945_mac_sta_add(struct ieee80211_hw *hw,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003023 struct ieee80211_vif *vif,
3024 struct ieee80211_sta *sta)
3025{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003026 struct il_priv *il = hw->priv;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003027 struct il3945_sta_priv *sta_priv = (void *)sta->drv_priv;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003028 int ret;
3029 bool is_ap = vif->type == NL80211_IFTYPE_STATION;
3030 u8 sta_id;
3031
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003032 D_INFO("received request to add station %pM\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003033 sta->addr);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003034 mutex_lock(&il->mutex);
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003035 D_INFO("proceeding to add station %pM\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003036 sta->addr);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003037 sta_priv->common.sta_id = IL_INVALID_STATION;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003038
3039
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003040 ret = il_add_station_common(il,
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003041 &il->ctx,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003042 sta->addr, is_ap, sta, &sta_id);
3043 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003044 IL_ERR("Unable to add station %pM (%d)\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003045 sta->addr, ret);
3046 /* Should we return success if return code is EEXIST ? */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003047 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003048 return ret;
3049 }
3050
3051 sta_priv->common.sta_id = sta_id;
3052
3053 /* Initialize rate scaling */
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003054 D_INFO("Initializing rate scaling for station %pM\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003055 sta->addr);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003056 il3945_rs_rate_init(il, sta, sta_id);
3057 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003058
3059 return 0;
3060}
3061
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003062static void il3945_configure_filter(struct ieee80211_hw *hw,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003063 unsigned int changed_flags,
3064 unsigned int *total_flags,
3065 u64 multicast)
3066{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003067 struct il_priv *il = hw->priv;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003068 __le32 filter_or = 0, filter_nand = 0;
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003069 struct il_rxon_context *ctx = &il->ctx;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003070
3071#define CHK(test, flag) do { \
3072 if (*total_flags & (test)) \
3073 filter_or |= (flag); \
3074 else \
3075 filter_nand |= (flag); \
3076 } while (0)
3077
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003078 D_MAC80211("Enter: changed: 0x%x, total: 0x%x\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003079 changed_flags, *total_flags);
3080
3081 CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
3082 CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
3083 CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
3084
3085#undef CHK
3086
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003087 mutex_lock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003088
3089 ctx->staging.filter_flags &= ~filter_nand;
3090 ctx->staging.filter_flags |= filter_or;
3091
3092 /*
3093 * Not committing directly because hardware can perform a scan,
3094 * but even if hw is ready, committing here breaks for some reason,
3095 * we'll eventually commit the filter flags change anyway.
3096 */
3097
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003098 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003099
3100 /*
3101 * Receiving all multicast frames is always enabled by the
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003102 * default flags setup in il_connection_init_rx_config()
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003103 * since we currently do not support programming multicast
3104 * filters into the device.
3105 */
3106 *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
3107 FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
3108}
3109
3110
3111/*****************************************************************************
3112 *
3113 * sysfs attributes
3114 *
3115 *****************************************************************************/
3116
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003117#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003118
3119/*
3120 * The following adds a new attribute to the sysfs representation
3121 * of this device driver (i.e. a new file in /sys/bus/pci/drivers/iwl/)
3122 * used for controlling the debug level.
3123 *
3124 * See the level definitions in iwl for details.
3125 *
3126 * The debug_level being managed using sysfs below is a per device debug
3127 * level that is used instead of the global debug level if it (the per
3128 * device debug level) is set.
3129 */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003130static ssize_t il3945_show_debug_level(struct device *d,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003131 struct device_attribute *attr, char *buf)
3132{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003133 struct il_priv *il = dev_get_drvdata(d);
3134 return sprintf(buf, "0x%08X\n", il_get_debug_level(il));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003135}
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003136static ssize_t il3945_store_debug_level(struct device *d,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003137 struct device_attribute *attr,
3138 const char *buf, size_t count)
3139{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003140 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003141 unsigned long val;
3142 int ret;
3143
3144 ret = strict_strtoul(buf, 0, &val);
3145 if (ret)
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003146 IL_INFO("%s is not in hex or decimal form.\n", buf);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003147 else {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003148 il->debug_level = val;
3149 if (il_alloc_traffic_mem(il))
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003150 IL_ERR(
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003151 "Not enough memory to generate traffic log\n");
3152 }
3153 return strnlen(buf, count);
3154}
3155
3156static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003157 il3945_show_debug_level, il3945_store_debug_level);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003158
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003159#endif /* CONFIG_IWLEGACY_DEBUG */
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003160
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003161static ssize_t il3945_show_temperature(struct device *d,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003162 struct device_attribute *attr, char *buf)
3163{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003164 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003165
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003166 if (!il_is_alive(il))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003167 return -EAGAIN;
3168
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003169 return sprintf(buf, "%d\n", il3945_hw_get_temperature(il));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003170}
3171
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003172static DEVICE_ATTR(temperature, S_IRUGO, il3945_show_temperature, NULL);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003173
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003174static ssize_t il3945_show_tx_power(struct device *d,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003175 struct device_attribute *attr, char *buf)
3176{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003177 struct il_priv *il = dev_get_drvdata(d);
3178 return sprintf(buf, "%d\n", il->tx_power_user_lmt);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003179}
3180
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003181static ssize_t il3945_store_tx_power(struct device *d,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003182 struct device_attribute *attr,
3183 const char *buf, size_t count)
3184{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003185 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003186 char *p = (char *)buf;
3187 u32 val;
3188
3189 val = simple_strtoul(p, &p, 10);
3190 if (p == buf)
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003191 IL_INFO(": %s is not in decimal form.\n", buf);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003192 else
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003193 il3945_hw_reg_set_txpower(il, val);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003194
3195 return count;
3196}
3197
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003198static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, il3945_show_tx_power, il3945_store_tx_power);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003199
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003200static ssize_t il3945_show_flags(struct device *d,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003201 struct device_attribute *attr, char *buf)
3202{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003203 struct il_priv *il = dev_get_drvdata(d);
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003204 struct il_rxon_context *ctx = &il->ctx;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003205
3206 return sprintf(buf, "0x%04X\n", ctx->active.flags);
3207}
3208
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003209static ssize_t il3945_store_flags(struct device *d,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003210 struct device_attribute *attr,
3211 const char *buf, size_t count)
3212{
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 u32 flags = simple_strtoul(buf, NULL, 0);
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003215 struct il_rxon_context *ctx = &il->ctx;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003216
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003217 mutex_lock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003218 if (le32_to_cpu(ctx->staging.flags) != flags) {
3219 /* Cancel any currently running scans... */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003220 if (il_scan_cancel_timeout(il, 100))
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003221 IL_WARN("Could not cancel scan.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003222 else {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003223 D_INFO("Committing rxon.flags = 0x%04X\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003224 flags);
3225 ctx->staging.flags = cpu_to_le32(flags);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003226 il3945_commit_rxon(il, ctx);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003227 }
3228 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003229 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003230
3231 return count;
3232}
3233
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003234static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, il3945_show_flags, il3945_store_flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003235
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003236static ssize_t il3945_show_filter_flags(struct device *d,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003237 struct device_attribute *attr, char *buf)
3238{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003239 struct il_priv *il = dev_get_drvdata(d);
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003240 struct il_rxon_context *ctx = &il->ctx;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003241
3242 return sprintf(buf, "0x%04X\n",
3243 le32_to_cpu(ctx->active.filter_flags));
3244}
3245
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003246static ssize_t il3945_store_filter_flags(struct device *d,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003247 struct device_attribute *attr,
3248 const char *buf, size_t count)
3249{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003250 struct il_priv *il = dev_get_drvdata(d);
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003251 struct il_rxon_context *ctx = &il->ctx;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003252 u32 filter_flags = simple_strtoul(buf, NULL, 0);
3253
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003254 mutex_lock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003255 if (le32_to_cpu(ctx->staging.filter_flags) != filter_flags) {
3256 /* Cancel any currently running scans... */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003257 if (il_scan_cancel_timeout(il, 100))
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003258 IL_WARN("Could not cancel scan.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003259 else {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003260 D_INFO("Committing rxon.filter_flags = "
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003261 "0x%04X\n", filter_flags);
3262 ctx->staging.filter_flags =
3263 cpu_to_le32(filter_flags);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003264 il3945_commit_rxon(il, ctx);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003265 }
3266 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003267 mutex_unlock(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003268
3269 return count;
3270}
3271
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003272static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, il3945_show_filter_flags,
3273 il3945_store_filter_flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003274
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003275static ssize_t il3945_show_measurement(struct device *d,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003276 struct device_attribute *attr, char *buf)
3277{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003278 struct il_priv *il = dev_get_drvdata(d);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003279 struct il_spectrum_notification measure_report;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003280 u32 size = sizeof(measure_report), len = 0, ofs = 0;
3281 u8 *data = (u8 *)&measure_report;
3282 unsigned long flags;
3283
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003284 spin_lock_irqsave(&il->lock, flags);
3285 if (!(il->measurement_status & MEASUREMENT_READY)) {
3286 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003287 return 0;
3288 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003289 memcpy(&measure_report, &il->measure_report, size);
3290 il->measurement_status = 0;
3291 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003292
Stanislaw Gruszka232913b2011-08-26 10:45:16 +02003293 while (size && PAGE_SIZE - len) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003294 hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
3295 PAGE_SIZE - len, 1);
3296 len = strlen(buf);
3297 if (PAGE_SIZE - len)
3298 buf[len++] = '\n';
3299
3300 ofs += 16;
3301 size -= min(size, 16U);
3302 }
3303
3304 return len;
3305}
3306
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003307static ssize_t il3945_store_measurement(struct device *d,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003308 struct device_attribute *attr,
3309 const char *buf, size_t count)
3310{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003311 struct il_priv *il = dev_get_drvdata(d);
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003312 struct il_rxon_context *ctx = &il->ctx;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003313 struct ieee80211_measurement_params params = {
3314 .channel = le16_to_cpu(ctx->active.channel),
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003315 .start_time = cpu_to_le64(il->_3945.last_tsf),
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003316 .duration = cpu_to_le16(1),
3317 };
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003318 u8 type = IL_MEASURE_BASIC;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003319 u8 buffer[32];
3320 u8 channel;
3321
3322 if (count) {
3323 char *p = buffer;
3324 strncpy(buffer, buf, min(sizeof(buffer), count));
3325 channel = simple_strtoul(p, NULL, 0);
3326 if (channel)
3327 params.channel = channel;
3328
3329 p = buffer;
3330 while (*p && *p != ' ')
3331 p++;
3332 if (*p)
3333 type = simple_strtoul(p + 1, NULL, 0);
3334 }
3335
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003336 D_INFO("Invoking measurement of type %d on "
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003337 "channel %d (for '%s')\n", type, params.channel, buf);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003338 il3945_get_measurement(il, &params, type);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003339
3340 return count;
3341}
3342
3343static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003344 il3945_show_measurement, il3945_store_measurement);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003345
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003346static ssize_t il3945_store_retry_rate(struct device *d,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003347 struct device_attribute *attr,
3348 const char *buf, size_t count)
3349{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003350 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003351
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003352 il->retry_rate = simple_strtoul(buf, NULL, 0);
3353 if (il->retry_rate <= 0)
3354 il->retry_rate = 1;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003355
3356 return count;
3357}
3358
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003359static ssize_t il3945_show_retry_rate(struct device *d,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003360 struct device_attribute *attr, char *buf)
3361{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003362 struct il_priv *il = dev_get_drvdata(d);
3363 return sprintf(buf, "%d", il->retry_rate);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003364}
3365
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003366static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, il3945_show_retry_rate,
3367 il3945_store_retry_rate);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003368
3369
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003370static ssize_t il3945_show_channels(struct device *d,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003371 struct device_attribute *attr, char *buf)
3372{
3373 /* all this shit doesn't belong into sysfs anyway */
3374 return 0;
3375}
3376
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003377static DEVICE_ATTR(channels, S_IRUSR, il3945_show_channels, NULL);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003378
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003379static ssize_t il3945_show_antenna(struct device *d,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003380 struct device_attribute *attr, char *buf)
3381{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003382 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003383
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003384 if (!il_is_alive(il))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003385 return -EAGAIN;
3386
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003387 return sprintf(buf, "%d\n", il3945_mod_params.antenna);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003388}
3389
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003390static ssize_t il3945_store_antenna(struct device *d,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003391 struct device_attribute *attr,
3392 const char *buf, size_t count)
3393{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003394 struct il_priv *il __maybe_unused = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003395 int ant;
3396
3397 if (count == 0)
3398 return 0;
3399
3400 if (sscanf(buf, "%1i", &ant) != 1) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003401 D_INFO("not in hex or decimal form.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003402 return count;
3403 }
3404
Stanislaw Gruszka232913b2011-08-26 10:45:16 +02003405 if (ant >= 0 && ant <= 2) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003406 D_INFO("Setting antenna select to %d.\n", ant);
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003407 il3945_mod_params.antenna = (enum il3945_antenna)ant;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003408 } else
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003409 D_INFO("Bad antenna select value %d.\n", ant);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003410
3411
3412 return count;
3413}
3414
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003415static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, il3945_show_antenna, il3945_store_antenna);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003416
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003417static ssize_t il3945_show_status(struct device *d,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003418 struct device_attribute *attr, char *buf)
3419{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003420 struct il_priv *il = dev_get_drvdata(d);
3421 if (!il_is_alive(il))
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003422 return -EAGAIN;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003423 return sprintf(buf, "0x%08x\n", (int)il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003424}
3425
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003426static DEVICE_ATTR(status, S_IRUGO, il3945_show_status, NULL);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003427
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003428static ssize_t il3945_dump_error_log(struct device *d,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003429 struct device_attribute *attr,
3430 const char *buf, size_t count)
3431{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003432 struct il_priv *il = dev_get_drvdata(d);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003433 char *p = (char *)buf;
3434
3435 if (p[0] == '1')
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003436 il3945_dump_nic_error_log(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003437
3438 return strnlen(buf, count);
3439}
3440
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003441static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, il3945_dump_error_log);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003442
3443/*****************************************************************************
3444 *
3445 * driver setup and tear down
3446 *
3447 *****************************************************************************/
3448
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003449static void il3945_setup_deferred_work(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003450{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003451 il->workqueue = create_singlethread_workqueue(DRV_NAME);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003452
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003453 init_waitqueue_head(&il->wait_command_queue);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003454
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003455 INIT_WORK(&il->restart, il3945_bg_restart);
3456 INIT_WORK(&il->rx_replenish, il3945_bg_rx_replenish);
3457 INIT_DELAYED_WORK(&il->init_alive_start, il3945_bg_init_alive_start);
3458 INIT_DELAYED_WORK(&il->alive_start, il3945_bg_alive_start);
3459 INIT_DELAYED_WORK(&il->_3945.rfkill_poll, il3945_rfkill_poll);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003460
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003461 il_setup_scan_deferred_work(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003462
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003463 il3945_hw_setup_deferred_work(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003464
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003465 init_timer(&il->watchdog);
3466 il->watchdog.data = (unsigned long)il;
3467 il->watchdog.function = il_bg_watchdog;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003468
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003469 tasklet_init(&il->irq_tasklet, (void (*)(unsigned long))
3470 il3945_irq_tasklet, (unsigned long)il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003471}
3472
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003473static void il3945_cancel_deferred_work(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003474{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003475 il3945_hw_cancel_deferred_work(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003476
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003477 cancel_delayed_work_sync(&il->init_alive_start);
3478 cancel_delayed_work(&il->alive_start);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003479
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003480 il_cancel_scan_deferred_work(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003481}
3482
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003483static struct attribute *il3945_sysfs_entries[] = {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003484 &dev_attr_antenna.attr,
3485 &dev_attr_channels.attr,
3486 &dev_attr_dump_errors.attr,
3487 &dev_attr_flags.attr,
3488 &dev_attr_filter_flags.attr,
3489 &dev_attr_measurement.attr,
3490 &dev_attr_retry_rate.attr,
3491 &dev_attr_status.attr,
3492 &dev_attr_temperature.attr,
3493 &dev_attr_tx_power.attr,
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003494#ifdef CONFIG_IWLEGACY_DEBUG
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003495 &dev_attr_debug_level.attr,
3496#endif
3497 NULL
3498};
3499
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003500static struct attribute_group il3945_attribute_group = {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003501 .name = NULL, /* put in device directory */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003502 .attrs = il3945_sysfs_entries,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003503};
3504
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003505struct ieee80211_ops il3945_hw_ops = {
3506 .tx = il3945_mac_tx,
3507 .start = il3945_mac_start,
3508 .stop = il3945_mac_stop,
3509 .add_interface = il_mac_add_interface,
3510 .remove_interface = il_mac_remove_interface,
3511 .change_interface = il_mac_change_interface,
3512 .config = il_mac_config,
3513 .configure_filter = il3945_configure_filter,
3514 .set_key = il3945_mac_set_key,
3515 .conf_tx = il_mac_conf_tx,
3516 .reset_tsf = il_mac_reset_tsf,
3517 .bss_info_changed = il_mac_bss_info_changed,
3518 .hw_scan = il_mac_hw_scan,
3519 .sta_add = il3945_mac_sta_add,
3520 .sta_remove = il_mac_sta_remove,
3521 .tx_last_beacon = il_mac_tx_last_beacon,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003522};
3523
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003524static int il3945_init_drv(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003525{
3526 int ret;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003527 struct il3945_eeprom *eeprom = (struct il3945_eeprom *)il->eeprom;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003528
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003529 il->retry_rate = 1;
3530 il->beacon_skb = NULL;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003531
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003532 spin_lock_init(&il->sta_lock);
3533 spin_lock_init(&il->hcmd_lock);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003534
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003535 INIT_LIST_HEAD(&il->free_frames);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003536
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003537 mutex_init(&il->mutex);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003538
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003539 il->ieee_channels = NULL;
3540 il->ieee_rates = NULL;
3541 il->band = IEEE80211_BAND_2GHZ;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003542
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003543 il->iw_mode = NL80211_IFTYPE_STATION;
3544 il->missed_beacon_threshold = IL_MISSED_BEACON_THRESHOLD_DEF;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003545
3546 /* initialize force reset */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003547 il->force_reset.reset_duration = IL_DELAY_NEXT_FORCE_FW_RELOAD;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003548
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003549 if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003550 IL_WARN("Unsupported EEPROM version: 0x%04X\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003551 eeprom->version);
3552 ret = -EINVAL;
3553 goto err;
3554 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003555 ret = il_init_channel_map(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003556 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003557 IL_ERR("initializing regulatory failed: %d\n", ret);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003558 goto err;
3559 }
3560
3561 /* Set up txpower settings in driver for all channels */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003562 if (il3945_txpower_set_from_eeprom(il)) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003563 ret = -EIO;
3564 goto err_free_channel_map;
3565 }
3566
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003567 ret = il_init_geos(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003568 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003569 IL_ERR("initializing geos failed: %d\n", ret);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003570 goto err_free_channel_map;
3571 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003572 il3945_init_hw_rates(il, il->ieee_rates);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003573
3574 return 0;
3575
3576err_free_channel_map:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003577 il_free_channel_map(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003578err:
3579 return ret;
3580}
3581
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003582#define IL3945_MAX_PROBE_REQUEST 200
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003583
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003584static int il3945_setup_mac(struct il_priv *il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003585{
3586 int ret;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003587 struct ieee80211_hw *hw = il->hw;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003588
3589 hw->rate_control_algorithm = "iwl-3945-rs";
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003590 hw->sta_data_size = sizeof(struct il3945_sta_priv);
3591 hw->vif_data_size = sizeof(struct il_vif_priv);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003592
3593 /* Tell mac80211 our characteristics */
3594 hw->flags = IEEE80211_HW_SIGNAL_DBM |
3595 IEEE80211_HW_SPECTRUM_MGMT;
3596
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003597 hw->wiphy->interface_modes =
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003598 il->ctx.interface_modes;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003599
3600 hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
3601 WIPHY_FLAG_DISABLE_BEACON_HINTS |
3602 WIPHY_FLAG_IBSS_RSN;
3603
3604 hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;
3605 /* we create the 802.11 header and a zero-length SSID element */
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003606 hw->wiphy->max_scan_ie_len = IL3945_MAX_PROBE_REQUEST - 24 - 2;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003607
3608 /* Default value; 4 EDCA QOS priorities */
3609 hw->queues = 4;
3610
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003611 if (il->bands[IEEE80211_BAND_2GHZ].n_channels)
3612 il->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
3613 &il->bands[IEEE80211_BAND_2GHZ];
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003614
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003615 if (il->bands[IEEE80211_BAND_5GHZ].n_channels)
3616 il->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
3617 &il->bands[IEEE80211_BAND_5GHZ];
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003618
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003619 il_leds_init(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003620
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003621 ret = ieee80211_register_hw(il->hw);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003622 if (ret) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003623 IL_ERR("Failed to register hw (error %d)\n", ret);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003624 return ret;
3625 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003626 il->mac80211_registered = 1;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003627
3628 return 0;
3629}
3630
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003631static int il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003632{
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003633 int err = 0;
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003634 struct il_priv *il;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003635 struct ieee80211_hw *hw;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003636 struct il_cfg *cfg = (struct il_cfg *)(ent->driver_data);
3637 struct il3945_eeprom *eeprom;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003638 unsigned long flags;
3639
3640 /***********************
3641 * 1. Allocating HW data
3642 * ********************/
3643
3644 /* mac80211 allocates memory for this device instance, including
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003645 * space for this driver's ilate structure */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003646 hw = il_alloc_all(cfg);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003647 if (hw == NULL) {
3648 pr_err("Can not allocate network device\n");
3649 err = -ENOMEM;
3650 goto out;
3651 }
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003652 il = hw->priv;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003653 SET_IEEE80211_DEV(hw, &pdev->dev);
3654
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003655 il->cmd_queue = IL39_CMD_QUEUE_NUM;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003656
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003657 il->ctx.ctxid = 0;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003658
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02003659 il->ctx.rxon_cmd = C_RXON;
3660 il->ctx.rxon_timing_cmd = C_RXON_TIMING;
3661 il->ctx.rxon_assoc_cmd = C_RXON_ASSOC;
3662 il->ctx.qos_cmd = C_QOS_PARAM;
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003663 il->ctx.ap_sta_id = IL_AP_ID;
Stanislaw Gruszka4d69c752011-08-30 15:26:35 +02003664 il->ctx.wep_key_cmd = C_WEPKEY;
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003665 il->ctx.interface_modes =
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003666 BIT(NL80211_IFTYPE_STATION) |
3667 BIT(NL80211_IFTYPE_ADHOC);
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003668 il->ctx.ibss_devtype = RXON_DEV_TYPE_IBSS;
3669 il->ctx.station_devtype = RXON_DEV_TYPE_ESS;
3670 il->ctx.unused_devtype = RXON_DEV_TYPE_ESS;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003671
3672 /*
3673 * Disabling hardware scan means that mac80211 will perform scans
3674 * "the hard way", rather than using device's scan.
3675 */
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003676 if (il3945_mod_params.disable_hw_scan) {
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003677 D_INFO("Disabling hw_scan\n");
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003678 il3945_hw_ops.hw_scan = NULL;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003679 }
3680
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003681 D_INFO("*** LOAD DRIVER ***\n");
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003682 il->cfg = cfg;
3683 il->pci_dev = pdev;
3684 il->inta_mask = CSR_INI_SET_MASK;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003685
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003686 if (il_alloc_traffic_mem(il))
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003687 IL_ERR("Not enough memory to generate traffic log\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003688
3689 /***************************
3690 * 2. Initializing PCI bus
3691 * *************************/
3692 pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
3693 PCIE_LINK_STATE_CLKPM);
3694
3695 if (pci_enable_device(pdev)) {
3696 err = -ENODEV;
3697 goto out_ieee80211_free_hw;
3698 }
3699
3700 pci_set_master(pdev);
3701
3702 err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
3703 if (!err)
3704 err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
3705 if (err) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003706 IL_WARN("No suitable DMA available.\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003707 goto out_pci_disable_device;
3708 }
3709
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003710 pci_set_drvdata(pdev, il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003711 err = pci_request_regions(pdev, DRV_NAME);
3712 if (err)
3713 goto out_pci_disable_device;
3714
3715 /***********************
3716 * 3. Read REV Register
3717 * ********************/
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003718 il->hw_base = pci_iomap(pdev, 0, 0);
3719 if (!il->hw_base) {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003720 err = -ENODEV;
3721 goto out_pci_release_regions;
3722 }
3723
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003724 D_INFO("pci_resource_len = 0x%08llx\n",
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003725 (unsigned long long) pci_resource_len(pdev, 0));
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003726 D_INFO("pci_resource_base = %p\n", il->hw_base);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003727
3728 /* We disable the RETRY_TIMEOUT register (0x41) to keep
3729 * PCI Tx retries from interfering with C3 CPU state */
3730 pci_write_config_byte(pdev, 0x41, 0x00);
3731
3732 /* these spin locks will be used in apm_ops.init and EEPROM access
3733 * we should init now
3734 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003735 spin_lock_init(&il->reg_lock);
3736 spin_lock_init(&il->lock);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003737
3738 /*
3739 * stop and reset the on-board processor just in case it is in a
3740 * strange state ... like being left stranded by a primary kernel
3741 * and this is now the kdump kernel trying to start up
3742 */
Stanislaw Gruszka841b2cc2011-08-24 15:14:03 +02003743 _il_wr(il, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003744
3745 /***********************
3746 * 4. Read EEPROM
3747 * ********************/
3748
3749 /* Read the EEPROM */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003750 err = il_eeprom_init(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003751 if (err) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003752 IL_ERR("Unable to init EEPROM\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003753 goto out_iounmap;
3754 }
3755 /* MAC Address location in EEPROM same for 3945/4965 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003756 eeprom = (struct il3945_eeprom *)il->eeprom;
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003757 D_INFO("MAC address: %pM\n", eeprom->mac_address);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003758 SET_IEEE80211_PERM_ADDR(il->hw, eeprom->mac_address);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003759
3760 /***********************
3761 * 5. Setup HW Constants
3762 * ********************/
3763 /* Device-specific setup */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003764 if (il3945_hw_set_hw_params(il)) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003765 IL_ERR("failed to set hw settings\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003766 goto out_eeprom_free;
3767 }
3768
3769 /***********************
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003770 * 6. Setup il
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003771 * ********************/
3772
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003773 err = il3945_init_drv(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003774 if (err) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003775 IL_ERR("initializing driver failed\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003776 goto out_unset_hw_params;
3777 }
3778
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003779 IL_INFO("Detected Intel Wireless WiFi Link %s\n",
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003780 il->cfg->name);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003781
3782 /***********************
3783 * 7. Setup Services
3784 * ********************/
3785
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003786 spin_lock_irqsave(&il->lock, flags);
3787 il_disable_interrupts(il);
3788 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003789
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003790 pci_enable_msi(il->pci_dev);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003791
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003792 err = request_irq(il->pci_dev->irq, il_isr,
3793 IRQF_SHARED, DRV_NAME, il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003794 if (err) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003795 IL_ERR("Error allocating IRQ %d\n", il->pci_dev->irq);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003796 goto out_disable_msi;
3797 }
3798
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003799 err = sysfs_create_group(&pdev->dev.kobj, &il3945_attribute_group);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003800 if (err) {
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003801 IL_ERR("failed to create sysfs device attributes\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003802 goto out_release_irq;
3803 }
3804
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003805 il_set_rxon_channel(il,
3806 &il->bands[IEEE80211_BAND_2GHZ].channels[5],
Stanislaw Gruszka7c2cde22011-11-15 11:29:04 +01003807 &il->ctx);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003808 il3945_setup_deferred_work(il);
Stanislaw Gruszkad0c72342011-08-30 15:39:42 +02003809 il3945_setup_handlers(il);
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003810 il_power_initialize(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003811
3812 /*********************************
3813 * 8. Setup and Register mac80211
3814 * *******************************/
3815
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003816 il_enable_interrupts(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003817
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003818 err = il3945_setup_mac(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003819 if (err)
3820 goto out_remove_sysfs;
3821
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003822 err = il_dbgfs_register(il, DRV_NAME);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003823 if (err)
Stanislaw Gruszka9406f792011-08-18 22:07:57 +02003824 IL_ERR("failed to create debugfs files. Ignoring error: %d\n", err);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003825
3826 /* Start monitoring the killswitch */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003827 queue_delayed_work(il->workqueue, &il->_3945.rfkill_poll,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003828 2 * HZ);
3829
3830 return 0;
3831
3832 out_remove_sysfs:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003833 destroy_workqueue(il->workqueue);
3834 il->workqueue = NULL;
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003835 sysfs_remove_group(&pdev->dev.kobj, &il3945_attribute_group);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003836 out_release_irq:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003837 free_irq(il->pci_dev->irq, il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003838 out_disable_msi:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003839 pci_disable_msi(il->pci_dev);
3840 il_free_geos(il);
3841 il_free_channel_map(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003842 out_unset_hw_params:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003843 il3945_unset_hw_params(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003844 out_eeprom_free:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003845 il_eeprom_free(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003846 out_iounmap:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003847 pci_iounmap(pdev, il->hw_base);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003848 out_pci_release_regions:
3849 pci_release_regions(pdev);
3850 out_pci_disable_device:
3851 pci_set_drvdata(pdev, NULL);
3852 pci_disable_device(pdev);
3853 out_ieee80211_free_hw:
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003854 il_free_traffic_mem(il);
3855 ieee80211_free_hw(il->hw);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003856 out:
3857 return err;
3858}
3859
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003860static void __devexit il3945_pci_remove(struct pci_dev *pdev)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003861{
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003862 struct il_priv *il = pci_get_drvdata(pdev);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003863 unsigned long flags;
3864
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003865 if (!il)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003866 return;
3867
Stanislaw Gruszka58de00a2011-11-15 11:21:01 +01003868 D_INFO("*** UNLOAD DRIVER ***\n");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003869
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003870 il_dbgfs_unregister(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003871
Stanislaw Gruszkaa6766cc2011-11-15 13:09:01 +01003872 set_bit(S_EXIT_PENDING, &il->status);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003873
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003874 il_leds_exit(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003875
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003876 if (il->mac80211_registered) {
3877 ieee80211_unregister_hw(il->hw);
3878 il->mac80211_registered = 0;
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003879 } else {
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003880 il3945_down(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003881 }
3882
3883 /*
3884 * Make sure device is reset to low power before unloading driver.
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003885 * This may be redundant with il_down(), but there are paths to
3886 * run il_down() without calling apm_ops.stop(), and there are
3887 * paths to avoid running il_down() at all before leaving driver.
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003888 * This (inexpensive) call *makes sure* device is reset.
3889 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003890 il_apm_stop(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003891
3892 /* make sure we flush any pending irq or
3893 * tasklet for the driver
3894 */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003895 spin_lock_irqsave(&il->lock, flags);
3896 il_disable_interrupts(il);
3897 spin_unlock_irqrestore(&il->lock, flags);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003898
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003899 il3945_synchronize_irq(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003900
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003901 sysfs_remove_group(&pdev->dev.kobj, &il3945_attribute_group);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003902
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003903 cancel_delayed_work_sync(&il->_3945.rfkill_poll);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003904
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003905 il3945_dealloc_ucode_pci(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003906
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003907 if (il->rxq.bd)
3908 il3945_rx_queue_free(il, &il->rxq);
3909 il3945_hw_txq_ctx_free(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003910
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003911 il3945_unset_hw_params(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003912
3913 /*netif_stop_queue(dev); */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003914 flush_workqueue(il->workqueue);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003915
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003916 /* ieee80211_unregister_hw calls il3945_mac_stop, which flushes
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003917 * il->workqueue... so we can't take down the workqueue
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003918 * until now... */
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003919 destroy_workqueue(il->workqueue);
3920 il->workqueue = NULL;
3921 il_free_traffic_mem(il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003922
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003923 free_irq(pdev->irq, il);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003924 pci_disable_msi(pdev);
3925
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003926 pci_iounmap(pdev, il->hw_base);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003927 pci_release_regions(pdev);
3928 pci_disable_device(pdev);
3929 pci_set_drvdata(pdev, NULL);
3930
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003931 il_free_channel_map(il);
3932 il_free_geos(il);
3933 kfree(il->scan_cmd);
3934 if (il->beacon_skb)
3935 dev_kfree_skb(il->beacon_skb);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003936
Stanislaw Gruszka46bc8d42011-10-24 16:49:25 +02003937 ieee80211_free_hw(il->hw);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003938}
3939
3940
3941/*****************************************************************************
3942 *
3943 * driver and module entry point
3944 *
3945 *****************************************************************************/
3946
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003947static struct pci_driver il3945_driver = {
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003948 .name = DRV_NAME,
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003949 .id_table = il3945_hw_card_ids,
3950 .probe = il3945_pci_probe,
3951 .remove = __devexit_p(il3945_pci_remove),
3952 .driver.pm = IL_LEGACY_PM_OPS,
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003953};
3954
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003955static int __init il3945_init(void)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003956{
3957
3958 int ret;
3959 pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
3960 pr_info(DRV_COPYRIGHT "\n");
3961
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003962 ret = il3945_rate_control_register();
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003963 if (ret) {
3964 pr_err("Unable to register rate control algorithm: %d\n", ret);
3965 return ret;
3966 }
3967
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003968 ret = pci_register_driver(&il3945_driver);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003969 if (ret) {
3970 pr_err("Unable to initialize PCI module\n");
3971 goto error_register;
3972 }
3973
3974 return ret;
3975
3976error_register:
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003977 il3945_rate_control_unregister();
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003978 return ret;
3979}
3980
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003981static void __exit il3945_exit(void)
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003982{
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003983 pci_unregister_driver(&il3945_driver);
3984 il3945_rate_control_unregister();
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003985}
3986
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003987MODULE_FIRMWARE(IL3945_MODULE_FIRMWARE(IL3945_UCODE_API_MAX));
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003988
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003989module_param_named(antenna, il3945_mod_params.antenna, int, S_IRUGO);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003990MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003991module_param_named(swcrypto, il3945_mod_params.sw_crypto, int, S_IRUGO);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003992MODULE_PARM_DESC(swcrypto,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003993 "using software crypto (default 1 [software])");
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02003994module_param_named(disable_hw_scan, il3945_mod_params.disable_hw_scan,
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08003995 int, S_IRUGO);
Stanislaw Gruszka0263aa42011-03-29 11:24:21 +02003996MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 1)");
Stanislaw Gruszkad3175162011-11-15 11:25:42 +01003997#ifdef CONFIG_IWLEGACY_DEBUG
Stanislaw Gruszkad2ddf622011-08-16 14:17:04 +02003998module_param_named(debug, il_debug_level, uint, S_IRUGO | S_IWUSR);
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08003999MODULE_PARM_DESC(debug, "debug output mask");
4000#endif
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004001module_param_named(fw_restart, il3945_mod_params.restart_fw, int, S_IRUGO);
Wey-Yi Guybe663ab2011-02-21 11:27:26 -08004002MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
Wey-Yi Guy4bc85c12011-02-21 11:11:05 -08004003
Stanislaw Gruszkae2ebc832011-10-24 15:41:30 +02004004module_exit(il3945_exit);
4005module_init(il3945_init);