blob: a21400cd84ac956e307b6a48b4bea59c87057af8 [file] [log] [blame]
Zhu Yib481de92007-09-25 17:54:57 -07001/******************************************************************************
2 *
Emmanuel Grumbach51368bf2013-12-30 13:15:54 +02003 * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
Zhu Yib481de92007-09-25 17:54:57 -07004 *
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:
Winkler, Tomas759ef892008-12-09 11:28:58 -080025 * Intel Linux Wireless <ilw@linux.intel.com>
Zhu Yib481de92007-09-25 17:54:57 -070026 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
27 *
28 *****************************************************************************/
Joe Perches69b87972012-03-26 08:27:40 -070029
30#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31
Zhu Yib481de92007-09-25 17:54:57 -070032#include <linux/kernel.h>
33#include <linux/module.h>
Zhu Yib481de92007-09-25 17:54:57 -070034#include <linux/init.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090035#include <linux/slab.h>
Zhu Yib481de92007-09-25 17:54:57 -070036#include <linux/delay.h>
Alexey Dobriyand43c36d2009-10-07 17:09:06 +040037#include <linux/sched.h>
Zhu Yib481de92007-09-25 17:54:57 -070038#include <linux/skbuff.h>
39#include <linux/netdevice.h>
Zhu Yib481de92007-09-25 17:54:57 -070040#include <linux/etherdevice.h>
41#include <linux/if_arp.h>
42
Zhu Yib481de92007-09-25 17:54:57 -070043#include <net/mac80211.h>
44
45#include <asm/div64.h>
46
Johannes Berg26a7ca92012-05-21 11:55:54 +020047#include "iwl-eeprom-read.h"
48#include "iwl-eeprom-parse.h"
Tomas Winkler3395f6e2008-03-25 16:33:37 -070049#include "iwl-io.h"
Emmanuel Grumbachc85eb612011-06-14 10:13:24 +030050#include "iwl-trans.h"
Emmanuel Grumbachd0f76d62012-02-09 16:08:15 +020051#include "iwl-op-mode.h"
Johannes Berg82575102012-04-03 16:44:37 -070052#include "iwl-drv.h"
Johannes Berg65de7e82012-04-17 07:36:30 -070053#include "iwl-modparams.h"
Emmanuel Grumbachdada03c2012-06-17 15:42:37 +030054#include "iwl-prph.h"
Christoph Hellwig416e1432007-10-25 17:15:49 +080055
Johannes Berg1023fdc2012-05-15 12:16:34 +020056#include "dev.h"
57#include "calib.h"
58#include "agn.h"
59
Emmanuel Grumbachdada03c2012-06-17 15:42:37 +030060
Zhu Yib481de92007-09-25 17:54:57 -070061/******************************************************************************
62 *
63 * module boiler plate
64 *
65 ******************************************************************************/
66
Tomas Winklerd783b062008-07-18 13:53:02 +080067#define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link AGN driver for Linux"
Zhu Yib481de92007-09-25 17:54:57 -070068MODULE_DESCRIPTION(DRV_DESCRIPTION);
Tomas Winklera7b75202008-12-11 10:33:41 -080069MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
Zhu Yib481de92007-09-25 17:54:57 -070070MODULE_LICENSE("GPL");
71
Johannes Bergb1abeda2012-05-31 13:54:56 +020072static const struct iwl_op_mode_ops iwl_dvm_ops;
73
Emmanuel Grumbach5b9f8cd2008-10-29 14:05:46 -070074void iwl_update_chain_flags(struct iwl_priv *priv)
Mohamed Abbas5da4b552008-04-21 15:41:51 -070075{
Johannes Berg246ed352010-08-23 10:46:32 +020076 struct iwl_rxon_context *ctx;
Mohamed Abbas5da4b552008-04-21 15:41:51 -070077
Wey-Yi Guye3f10ce2011-07-01 07:59:26 -070078 for_each_context(priv, ctx) {
79 iwlagn_set_rxon_chain(priv, ctx);
80 if (ctx->active.rx_chain != ctx->staging.rx_chain)
81 iwlagn_commit_rxon(priv, ctx);
Johannes Berg246ed352010-08-23 10:46:32 +020082 }
Mohamed Abbas5da4b552008-04-21 15:41:51 -070083}
84
Daniel C Halperin47ff65c2009-11-13 11:56:33 -080085/* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */
86static void iwl_set_beacon_tim(struct iwl_priv *priv,
Johannes Berg77834542010-10-04 05:50:36 -070087 struct iwl_tx_beacon_cmd *tx_beacon_cmd,
88 u8 *beacon, u32 frame_size)
Daniel C Halperin47ff65c2009-11-13 11:56:33 -080089{
90 u16 tim_idx;
91 struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
92
93 /*
94 * The index is relative to frame start but we start looking at the
95 * variable-length part of the beacon.
96 */
97 tim_idx = mgmt->u.beacon.variable - beacon;
98
99 /* Parse variable-length elements of beacon to find WLAN_EID_TIM */
100 while ((tim_idx < (frame_size - 2)) &&
101 (beacon[tim_idx] != WLAN_EID_TIM))
102 tim_idx += beacon[tim_idx+1] + 2;
103
104 /* If TIM field was found, set variables */
105 if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) {
106 tx_beacon_cmd->tim_idx = cpu_to_le16(tim_idx);
107 tx_beacon_cmd->tim_size = beacon[tim_idx+1];
108 } else
109 IWL_WARN(priv, "Unable to find TIM Element in beacon\n");
110}
111
Johannes Berg8a98d492011-04-29 09:48:14 -0700112int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
Tomas Winkler4bf64ef2008-07-18 13:53:03 +0800113{
114 struct iwl_tx_beacon_cmd *tx_beacon_cmd;
Johannes Berg8a98d492011-04-29 09:48:14 -0700115 struct iwl_host_cmd cmd = {
116 .id = REPLY_TX_BEACON,
Johannes Berg8a98d492011-04-29 09:48:14 -0700117 };
Johannes Berg0b5b3ff2011-06-22 06:33:43 -0700118 struct ieee80211_tx_info *info;
Daniel C Halperin47ff65c2009-11-13 11:56:33 -0800119 u32 frame_size;
120 u32 rate_flags;
121 u32 rate;
Johannes Berg8a98d492011-04-29 09:48:14 -0700122
Daniel C Halperin47ff65c2009-11-13 11:56:33 -0800123 /*
124 * We have to set up the TX command, the TX Beacon command, and the
125 * beacon contents.
126 */
Tomas Winkler4bf64ef2008-07-18 13:53:03 +0800127
Johannes Bergb1eea292012-03-06 13:30:42 -0800128 lockdep_assert_held(&priv->mutex);
Johannes Berg76d04812010-08-23 10:46:47 +0200129
130 if (!priv->beacon_ctx) {
131 IWL_ERR(priv, "trying to build beacon w/o beacon context!\n");
Julia Lawall950094c2010-09-05 21:00:26 +0200132 return 0;
Johannes Berg76d04812010-08-23 10:46:47 +0200133 }
134
Johannes Berg8a98d492011-04-29 09:48:14 -0700135 if (WARN_ON(!priv->beacon_skb))
136 return -EINVAL;
137
Johannes Berg4ce7cc22011-05-13 11:57:40 -0700138 /* Allocate beacon command */
139 if (!priv->beacon_cmd)
140 priv->beacon_cmd = kzalloc(sizeof(*tx_beacon_cmd), GFP_KERNEL);
141 tx_beacon_cmd = priv->beacon_cmd;
Johannes Berg8a98d492011-04-29 09:48:14 -0700142 if (!tx_beacon_cmd)
143 return -ENOMEM;
144
145 frame_size = priv->beacon_skb->len;
Tomas Winkler4bf64ef2008-07-18 13:53:03 +0800146
Daniel C Halperin47ff65c2009-11-13 11:56:33 -0800147 /* Set up TX command fields */
Tomas Winkler4bf64ef2008-07-18 13:53:03 +0800148 tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
Johannes Berg76d04812010-08-23 10:46:47 +0200149 tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id;
Daniel C Halperin47ff65c2009-11-13 11:56:33 -0800150 tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
Tomas Winkler4bf64ef2008-07-18 13:53:03 +0800151 tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK |
Daniel C Halperin47ff65c2009-11-13 11:56:33 -0800152 TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK;
153
154 /* Set up TX beacon command fields */
Johannes Berg4ce7cc22011-05-13 11:57:40 -0700155 iwl_set_beacon_tim(priv, tx_beacon_cmd, priv->beacon_skb->data,
Johannes Berg77834542010-10-04 05:50:36 -0700156 frame_size);
Daniel C Halperin47ff65c2009-11-13 11:56:33 -0800157
158 /* Set up packet rate and flags */
Johannes Berg0b5b3ff2011-06-22 06:33:43 -0700159 info = IEEE80211_SKB_CB(priv->beacon_skb);
160
161 /*
162 * Let's set up the rate at least somewhat correctly;
163 * it will currently not actually be used by the uCode,
164 * it uses the broadcast station's rate instead.
165 */
166 if (info->control.rates[0].idx < 0 ||
167 info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
168 rate = 0;
169 else
170 rate = info->control.rates[0].idx;
171
Johannes Berg0e1654f2010-05-18 02:48:36 -0700172 priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
Eytan Lifshitzb7998c82012-12-01 20:59:49 +0200173 priv->nvm_data->valid_tx_ant);
Daniel C Halperin47ff65c2009-11-13 11:56:33 -0800174 rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
Johannes Berg0b5b3ff2011-06-22 06:33:43 -0700175
176 /* In mac80211, rates for 5 GHz start at 0 */
177 if (info->band == IEEE80211_BAND_5GHZ)
178 rate += IWL_FIRST_OFDM_RATE;
179 else if (rate >= IWL_FIRST_CCK_RATE && rate <= IWL_LAST_CCK_RATE)
Daniel C Halperin47ff65c2009-11-13 11:56:33 -0800180 rate_flags |= RATE_MCS_CCK_MSK;
Johannes Berg0b5b3ff2011-06-22 06:33:43 -0700181
182 tx_beacon_cmd->tx.rate_n_flags =
183 iwl_hw_set_rate_n_flags(rate, rate_flags);
Tomas Winkler4bf64ef2008-07-18 13:53:03 +0800184
Johannes Berg8a98d492011-04-29 09:48:14 -0700185 /* Submit command */
Johannes Berg4ce7cc22011-05-13 11:57:40 -0700186 cmd.len[0] = sizeof(*tx_beacon_cmd);
Johannes Berg3fa50732011-05-04 07:50:38 -0700187 cmd.data[0] = tx_beacon_cmd;
Johannes Berg4ce7cc22011-05-13 11:57:40 -0700188 cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
189 cmd.len[1] = frame_size;
190 cmd.data[1] = priv->beacon_skb->data;
191 cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
Johannes Berg2295c662010-10-23 09:15:41 -0700192
Johannes Berge10a0532012-03-06 13:30:39 -0800193 return iwl_dvm_send_cmd(priv, &cmd);
Samuel Ortiza8e74e272009-01-23 13:45:14 -0800194}
195
Emmanuel Grumbach5b9f8cd2008-10-29 14:05:46 -0700196static void iwl_bg_beacon_update(struct work_struct *work)
Zhu Yib481de92007-09-25 17:54:57 -0700197{
Tomas Winklerc79dd5b2008-03-12 16:58:50 -0700198 struct iwl_priv *priv =
199 container_of(work, struct iwl_priv, beacon_update);
Zhu Yib481de92007-09-25 17:54:57 -0700200 struct sk_buff *beacon;
201
Johannes Bergb1eea292012-03-06 13:30:42 -0800202 mutex_lock(&priv->mutex);
Johannes Berg76d04812010-08-23 10:46:47 +0200203 if (!priv->beacon_ctx) {
204 IWL_ERR(priv, "updating beacon w/o beacon context!\n");
205 goto out;
Zhu Yib481de92007-09-25 17:54:57 -0700206 }
207
Johannes Berg60744f62010-08-23 10:46:50 +0200208 if (priv->beacon_ctx->vif->type != NL80211_IFTYPE_AP) {
209 /*
210 * The ucode will send beacon notifications even in
211 * IBSS mode, but we don't want to process them. But
212 * we need to defer the type check to here due to
213 * requiring locking around the beacon_ctx access.
214 */
215 goto out;
216 }
217
Johannes Berg76d04812010-08-23 10:46:47 +0200218 /* Pull updated AP beacon from mac80211. will fail if not in AP mode */
219 beacon = ieee80211_beacon_get(priv->hw, priv->beacon_ctx->vif);
220 if (!beacon) {
Johannes Berg77834542010-10-04 05:50:36 -0700221 IWL_ERR(priv, "update beacon failed -- keeping old\n");
Johannes Berg76d04812010-08-23 10:46:47 +0200222 goto out;
223 }
224
Zhu Yib481de92007-09-25 17:54:57 -0700225 /* new beacon skb is allocated every time; dispose previous.*/
Johannes Berg77834542010-10-04 05:50:36 -0700226 dev_kfree_skb(priv->beacon_skb);
Zhu Yib481de92007-09-25 17:54:57 -0700227
Johannes Berg12e934d2010-10-04 05:50:06 -0700228 priv->beacon_skb = beacon;
Zhu Yib481de92007-09-25 17:54:57 -0700229
Johannes Berg2295c662010-10-23 09:15:41 -0700230 iwlagn_send_beacon_cmd(priv);
Johannes Berg76d04812010-08-23 10:46:47 +0200231 out:
Johannes Bergb1eea292012-03-06 13:30:42 -0800232 mutex_unlock(&priv->mutex);
Zhu Yib481de92007-09-25 17:54:57 -0700233}
234
Wey-Yi Guyfbba9412010-08-23 07:57:10 -0700235static void iwl_bg_bt_runtime_config(struct work_struct *work)
236{
237 struct iwl_priv *priv =
238 container_of(work, struct iwl_priv, bt_runtime_config);
239
Emmanuel Grumbach82e5a642014-03-10 15:22:03 +0200240 mutex_lock(&priv->mutex);
Don Fry83626402012-03-07 09:52:37 -0800241 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
Emmanuel Grumbach82e5a642014-03-10 15:22:03 +0200242 goto out;
Wey-Yi Guyfbba9412010-08-23 07:57:10 -0700243
244 /* dont send host command if rf-kill is on */
Don Fry83626402012-03-07 09:52:37 -0800245 if (!iwl_is_ready_rf(priv))
Emmanuel Grumbach82e5a642014-03-10 15:22:03 +0200246 goto out;
247
Wey-Yi Guye55b5172011-06-28 11:46:28 -0700248 iwlagn_send_advance_bt_config(priv);
Emmanuel Grumbach82e5a642014-03-10 15:22:03 +0200249out:
250 mutex_unlock(&priv->mutex);
Wey-Yi Guyfbba9412010-08-23 07:57:10 -0700251}
252
Wey-Yi Guybee008b2010-08-23 07:57:04 -0700253static void iwl_bg_bt_full_concurrency(struct work_struct *work)
254{
255 struct iwl_priv *priv =
256 container_of(work, struct iwl_priv, bt_full_concurrency);
Johannes Berg246ed352010-08-23 10:46:32 +0200257 struct iwl_rxon_context *ctx;
Wey-Yi Guybee008b2010-08-23 07:57:04 -0700258
Johannes Bergb1eea292012-03-06 13:30:42 -0800259 mutex_lock(&priv->mutex);
Stanislaw Gruszkadc1a4062011-03-31 17:36:27 +0200260
Don Fry83626402012-03-07 09:52:37 -0800261 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
Stanislaw Gruszkadc1a4062011-03-31 17:36:27 +0200262 goto out;
Wey-Yi Guybee008b2010-08-23 07:57:04 -0700263
264 /* dont send host command if rf-kill is on */
Don Fry83626402012-03-07 09:52:37 -0800265 if (!iwl_is_ready_rf(priv))
Stanislaw Gruszkadc1a4062011-03-31 17:36:27 +0200266 goto out;
Wey-Yi Guybee008b2010-08-23 07:57:04 -0700267
268 IWL_DEBUG_INFO(priv, "BT coex in %s mode\n",
269 priv->bt_full_concurrent ?
270 "full concurrency" : "3-wire");
271
272 /*
273 * LQ & RXON updated cmds must be sent before BT Config cmd
274 * to avoid 3-wire collisions
275 */
Johannes Berg246ed352010-08-23 10:46:32 +0200276 for_each_context(priv, ctx) {
Wey-Yi Guye3f10ce2011-07-01 07:59:26 -0700277 iwlagn_set_rxon_chain(priv, ctx);
Wey-Yi Guy805a3b82011-06-03 07:54:16 -0700278 iwlagn_commit_rxon(priv, ctx);
Johannes Berg246ed352010-08-23 10:46:32 +0200279 }
Wey-Yi Guybee008b2010-08-23 07:57:04 -0700280
Wey-Yi Guye55b5172011-06-28 11:46:28 -0700281 iwlagn_send_advance_bt_config(priv);
Stanislaw Gruszkadc1a4062011-03-31 17:36:27 +0200282out:
Johannes Bergb1eea292012-03-06 13:30:42 -0800283 mutex_unlock(&priv->mutex);
Wey-Yi Guybee008b2010-08-23 07:57:04 -0700284}
285
Meenakshi Venkataraman15911292012-03-14 15:49:37 -0700286int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
287{
288 struct iwl_statistics_cmd statistics_cmd = {
289 .configuration_flags =
290 clear ? IWL_STATS_CONF_CLEAR_STATS : 0,
291 };
292
293 if (flags & CMD_ASYNC)
294 return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
295 CMD_ASYNC,
296 sizeof(struct iwl_statistics_cmd),
297 &statistics_cmd);
298 else
Emmanuel Grumbacha1022922014-05-12 11:36:41 +0300299 return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, 0,
Meenakshi Venkataraman15911292012-03-14 15:49:37 -0700300 sizeof(struct iwl_statistics_cmd),
301 &statistics_cmd);
302}
303
Emmanuel Grumbach4e393172008-06-12 09:46:53 +0800304/**
Emmanuel Grumbach5b9f8cd2008-10-29 14:05:46 -0700305 * iwl_bg_statistics_periodic - Timer callback to queue statistics
Emmanuel Grumbach4e393172008-06-12 09:46:53 +0800306 *
307 * This callback is provided in order to send a statistics request.
308 *
309 * This timer function is continually reset to execute within
310 * REG_RECALIB_PERIOD seconds since the last STATISTICS_NOTIFICATION
311 * was received. We need to ensure we receive the statistics in order
312 * to update the temperature used for calibrating the TXPOWER.
313 */
Emmanuel Grumbach5b9f8cd2008-10-29 14:05:46 -0700314static void iwl_bg_statistics_periodic(unsigned long data)
Emmanuel Grumbach4e393172008-06-12 09:46:53 +0800315{
316 struct iwl_priv *priv = (struct iwl_priv *)data;
317
Don Fry83626402012-03-07 09:52:37 -0800318 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
Emmanuel Grumbach4e393172008-06-12 09:46:53 +0800319 return;
320
Mohamed Abbas61780ee2008-10-29 14:05:49 -0700321 /* dont send host command if rf-kill is on */
Don Fry83626402012-03-07 09:52:37 -0800322 if (!iwl_is_ready_rf(priv))
Mohamed Abbas61780ee2008-10-29 14:05:49 -0700323 return;
324
Wey-Yi Guyef8d5522009-11-13 11:56:28 -0800325 iwl_send_statistics_request(priv, CMD_ASYNC, false);
Emmanuel Grumbach4e393172008-06-12 09:46:53 +0800326}
327
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800328
329static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
330 u32 start_idx, u32 num_events,
Johannes Berg98d4bf02012-01-13 11:56:11 +0100331 u32 capacity, u32 mode)
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800332{
333 u32 i;
334 u32 ptr; /* SRAM byte address of log data */
335 u32 ev, time, data; /* event log data */
336 unsigned long reg_flags;
337
338 if (mode == 0)
339 ptr = base + (4 * sizeof(u32)) + (start_idx * 2 * sizeof(u32));
340 else
341 ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32));
342
343 /* Make sure device is powered up for SRAM reads */
Lilach Edelsteine56b04e2013-01-16 11:34:49 +0200344 if (!iwl_trans_grab_nic_access(priv->trans, false, &reg_flags))
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800345 return;
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800346
347 /* Set starting address; reads will auto-increment */
Emmanuel Grumbach68e8dfd2012-04-18 07:28:17 -0700348 iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, ptr);
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800349
350 /*
Johannes Berg98d4bf02012-01-13 11:56:11 +0100351 * Refuse to read more than would have fit into the log from
352 * the current start_idx. This used to happen due to the race
353 * described below, but now WARN because the code below should
354 * prevent it from happening here.
355 */
356 if (WARN_ON(num_events > capacity - start_idx))
357 num_events = capacity - start_idx;
358
359 /*
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800360 * "time" is actually "data" for mode 0 (no timestamp).
361 * place event id # at far right for easier visual parsing.
362 */
363 for (i = 0; i < num_events; i++) {
Emmanuel Grumbach68e8dfd2012-04-18 07:28:17 -0700364 ev = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT);
365 time = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT);
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800366 if (mode == 0) {
Johannes Berg6c1011e2012-03-06 13:30:48 -0800367 trace_iwlwifi_dev_ucode_cont_event(
Emmanuel Grumbach68e8dfd2012-04-18 07:28:17 -0700368 priv->trans->dev, 0, time, ev);
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800369 } else {
Emmanuel Grumbach68e8dfd2012-04-18 07:28:17 -0700370 data = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT);
Johannes Berg6c1011e2012-03-06 13:30:48 -0800371 trace_iwlwifi_dev_ucode_cont_event(
Emmanuel Grumbach68e8dfd2012-04-18 07:28:17 -0700372 priv->trans->dev, time, data, ev);
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800373 }
374 }
375 /* Allow device to power down */
Lilach Edelsteine56b04e2013-01-16 11:34:49 +0200376 iwl_trans_release_nic_access(priv->trans, &reg_flags);
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800377}
378
Johannes Berg875295f2010-01-22 14:22:55 -0800379static void iwl_continuous_event_trace(struct iwl_priv *priv)
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800380{
381 u32 capacity; /* event log capacity in # entries */
Johannes Berg98d4bf02012-01-13 11:56:11 +0100382 struct {
383 u32 capacity;
384 u32 mode;
385 u32 wrap_counter;
386 u32 write_counter;
387 } __packed read;
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800388 u32 base; /* SRAM byte address of event log header */
389 u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
390 u32 num_wraps; /* # times uCode wrapped to top of log */
391 u32 next_entry; /* index of next entry to be written by uCode */
392
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -0700393 base = priv->device_pointers.log_event_table;
Fry, Donald H4caab322011-07-07 15:24:07 -0700394 if (iwlagn_hw_valid_rtc_data_addr(base)) {
Emmanuel Grumbach4fd442d2012-12-24 14:27:11 +0200395 iwl_trans_read_mem_bytes(priv->trans, base,
396 &read, sizeof(read));
Johannes Berg98d4bf02012-01-13 11:56:11 +0100397 capacity = read.capacity;
398 mode = read.mode;
399 num_wraps = read.wrap_counter;
400 next_entry = read.write_counter;
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800401 } else
402 return;
403
Johannes Berg98d4bf02012-01-13 11:56:11 +0100404 /*
405 * Unfortunately, the uCode doesn't use temporary variables.
406 * Therefore, it can happen that we read next_entry == capacity,
407 * which really means next_entry == 0.
408 */
409 if (unlikely(next_entry == capacity))
410 next_entry = 0;
411 /*
412 * Additionally, the uCode increases the write pointer before
413 * the wraps counter, so if the write pointer is smaller than
414 * the old write pointer (wrap occurred) but we read that no
415 * wrap occurred, we actually read between the next_entry and
416 * num_wraps update (this does happen in practice!!) -- take
417 * that into account by increasing num_wraps.
418 */
419 if (unlikely(next_entry < priv->event_log.next_entry &&
420 num_wraps == priv->event_log.num_wraps))
421 num_wraps++;
422
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800423 if (num_wraps == priv->event_log.num_wraps) {
Johannes Berg98d4bf02012-01-13 11:56:11 +0100424 iwl_print_cont_event_trace(
425 priv, base, priv->event_log.next_entry,
426 next_entry - priv->event_log.next_entry,
427 capacity, mode);
428
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800429 priv->event_log.non_wraps_count++;
430 } else {
Johannes Berg98d4bf02012-01-13 11:56:11 +0100431 if (num_wraps - priv->event_log.num_wraps > 1)
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800432 priv->event_log.wraps_more_count++;
433 else
434 priv->event_log.wraps_once_count++;
Johannes Berg98d4bf02012-01-13 11:56:11 +0100435
Emmanuel Grumbach68e8dfd2012-04-18 07:28:17 -0700436 trace_iwlwifi_dev_ucode_wrap_event(priv->trans->dev,
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800437 num_wraps - priv->event_log.num_wraps,
438 next_entry, priv->event_log.next_entry);
Johannes Berg98d4bf02012-01-13 11:56:11 +0100439
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800440 if (next_entry < priv->event_log.next_entry) {
Johannes Berg98d4bf02012-01-13 11:56:11 +0100441 iwl_print_cont_event_trace(
442 priv, base, priv->event_log.next_entry,
443 capacity - priv->event_log.next_entry,
444 capacity, mode);
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800445
Johannes Berg98d4bf02012-01-13 11:56:11 +0100446 iwl_print_cont_event_trace(
447 priv, base, 0, next_entry, capacity, mode);
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800448 } else {
Johannes Berg98d4bf02012-01-13 11:56:11 +0100449 iwl_print_cont_event_trace(
450 priv, base, next_entry,
451 capacity - next_entry,
452 capacity, mode);
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800453
Johannes Berg98d4bf02012-01-13 11:56:11 +0100454 iwl_print_cont_event_trace(
455 priv, base, 0, next_entry, capacity, mode);
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800456 }
457 }
Johannes Berg98d4bf02012-01-13 11:56:11 +0100458
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800459 priv->event_log.num_wraps = num_wraps;
460 priv->event_log.next_entry = next_entry;
461}
462
463/**
464 * iwl_bg_ucode_trace - Timer callback to log ucode event
465 *
466 * The timer is continually set to execute every
467 * UCODE_TRACE_PERIOD milliseconds after the last timer expired
468 * this function is to perform continuous uCode event logging operation
469 * if enabled
470 */
471static void iwl_bg_ucode_trace(unsigned long data)
472{
473 struct iwl_priv *priv = (struct iwl_priv *)data;
474
Don Fry83626402012-03-07 09:52:37 -0800475 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -0800476 return;
477
478 if (priv->event_log.ucode_trace) {
479 iwl_continuous_event_trace(priv);
480 /* Reschedule the timer to occur in UCODE_TRACE_PERIOD */
481 mod_timer(&priv->ucode_trace,
482 jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
483 }
484}
485
Wey-Yi Guy65550632010-06-24 13:18:35 -0700486static void iwl_bg_tx_flush(struct work_struct *work)
487{
488 struct iwl_priv *priv =
489 container_of(work, struct iwl_priv, tx_flush);
490
Don Fry83626402012-03-07 09:52:37 -0800491 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
Wey-Yi Guy65550632010-06-24 13:18:35 -0700492 return;
493
494 /* do nothing if rf-kill is on */
Don Fry83626402012-03-07 09:52:37 -0800495 if (!iwl_is_ready_rf(priv))
Wey-Yi Guy65550632010-06-24 13:18:35 -0700496 return;
497
Wey-Yi Guyc68744f2011-06-18 08:03:18 -0700498 IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
Johannes Berga4dece92012-10-31 22:21:28 +0100499 iwlagn_dev_txfifo_flush(priv);
Wey-Yi Guy65550632010-06-24 13:18:35 -0700500}
501
Johannes Berg9eae88f2012-03-15 13:26:52 -0700502/*
503 * queue/FIFO/AC mapping definitions
504 */
505
Johannes Berg9eae88f2012-03-15 13:26:52 -0700506static const u8 iwlagn_bss_ac_to_fifo[] = {
507 IWL_TX_FIFO_VO,
508 IWL_TX_FIFO_VI,
509 IWL_TX_FIFO_BE,
510 IWL_TX_FIFO_BK,
511};
512
513static const u8 iwlagn_bss_ac_to_queue[] = {
514 0, 1, 2, 3,
515};
516
517static const u8 iwlagn_pan_ac_to_fifo[] = {
518 IWL_TX_FIFO_VO_IPAN,
519 IWL_TX_FIFO_VI_IPAN,
520 IWL_TX_FIFO_BE_IPAN,
521 IWL_TX_FIFO_BK_IPAN,
522};
523
524static const u8 iwlagn_pan_ac_to_queue[] = {
525 7, 6, 5, 4,
526};
527
Johannes Bergaca86262012-05-14 09:08:50 +0200528static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
Johannes Berg4d2a5d02011-07-23 10:24:46 -0700529{
Johannes Berg4d2a5d02011-07-23 10:24:46 -0700530 int i;
531
532 /*
533 * The default context is always valid,
534 * the PAN context depends on uCode.
535 */
Johannes Berga18f61b2012-03-15 13:26:53 -0700536 priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
Johannes Berg4d2a5d02011-07-23 10:24:46 -0700537 if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN)
Johannes Berga18f61b2012-03-15 13:26:53 -0700538 priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN);
Johannes Berg4d2a5d02011-07-23 10:24:46 -0700539
540 for (i = 0; i < NUM_IWL_RXON_CTX; i++)
541 priv->contexts[i].ctxid = i;
542
543 priv->contexts[IWL_RXON_CTX_BSS].always_active = true;
544 priv->contexts[IWL_RXON_CTX_BSS].is_active = true;
545 priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
546 priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
547 priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
548 priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
549 priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
550 priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
Don Fry87272af2012-01-25 15:26:34 -0800551 priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
Johannes Berg4d2a5d02011-07-23 10:24:46 -0700552 priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes =
Johannes Berg57897722012-05-11 10:53:18 +0200553 BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MONITOR);
Johannes Berg4d2a5d02011-07-23 10:24:46 -0700554 priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
555 BIT(NL80211_IFTYPE_STATION);
556 priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP;
557 priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
558 priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
559 priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
Johannes Berg9eae88f2012-03-15 13:26:52 -0700560 memcpy(priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue,
561 iwlagn_bss_ac_to_queue, sizeof(iwlagn_bss_ac_to_queue));
562 memcpy(priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo,
563 iwlagn_bss_ac_to_fifo, sizeof(iwlagn_bss_ac_to_fifo));
Johannes Berg4d2a5d02011-07-23 10:24:46 -0700564
565 priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON;
566 priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd =
567 REPLY_WIPAN_RXON_TIMING;
568 priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd =
569 REPLY_WIPAN_RXON_ASSOC;
570 priv->contexts[IWL_RXON_CTX_PAN].qos_cmd = REPLY_WIPAN_QOS_PARAM;
571 priv->contexts[IWL_RXON_CTX_PAN].ap_sta_id = IWL_AP_ID_PAN;
572 priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY;
573 priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID;
574 priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION;
Johannes Berg4d2a5d02011-07-23 10:24:46 -0700575 priv->contexts[IWL_RXON_CTX_PAN].interface_modes =
576 BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP);
Johannes Bergc6baf7f2011-07-23 10:24:47 -0700577
Johannes Berg4d2a5d02011-07-23 10:24:46 -0700578 priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP;
579 priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA;
580 priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
Johannes Berg9eae88f2012-03-15 13:26:52 -0700581 memcpy(priv->contexts[IWL_RXON_CTX_PAN].ac_to_queue,
582 iwlagn_pan_ac_to_queue, sizeof(iwlagn_pan_ac_to_queue));
583 memcpy(priv->contexts[IWL_RXON_CTX_PAN].ac_to_fifo,
584 iwlagn_pan_ac_to_fifo, sizeof(iwlagn_pan_ac_to_fifo));
585 priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE;
Johannes Berg4d2a5d02011-07-23 10:24:46 -0700586
587 BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
588}
589
Johannes Bergaca86262012-05-14 09:08:50 +0200590static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
Wey-Yi Guy0975cc82010-07-31 08:34:07 -0700591{
592 struct iwl_ct_kill_config cmd;
593 struct iwl_ct_kill_throttling_config adv_cmd;
Wey-Yi Guy0975cc82010-07-31 08:34:07 -0700594 int ret = 0;
595
Emmanuel Grumbach68e8dfd2012-04-18 07:28:17 -0700596 iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR,
Wey-Yi Guy0975cc82010-07-31 08:34:07 -0700597 CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
Johannes Berg08ae86a2012-03-05 11:24:27 -0800598
Wey-Yi Guy0975cc82010-07-31 08:34:07 -0700599 priv->thermal_throttle.ct_kill_toggle = false;
600
Johannes Berg0d8877a2013-05-17 10:36:29 +0200601 if (priv->lib->support_ct_kill_exit) {
Wey-Yi Guy0975cc82010-07-31 08:34:07 -0700602 adv_cmd.critical_temperature_enter =
Johannes Berg9e295112012-04-09 17:46:55 -0700603 cpu_to_le32(priv->hw_params.ct_kill_threshold);
Wey-Yi Guy0975cc82010-07-31 08:34:07 -0700604 adv_cmd.critical_temperature_exit =
Johannes Berg9e295112012-04-09 17:46:55 -0700605 cpu_to_le32(priv->hw_params.ct_kill_exit_threshold);
Wey-Yi Guy0975cc82010-07-31 08:34:07 -0700606
Johannes Berge10a0532012-03-06 13:30:39 -0800607 ret = iwl_dvm_send_cmd_pdu(priv,
Emmanuel Grumbache419d622011-07-08 08:46:14 -0700608 REPLY_CT_KILL_CONFIG_CMD,
Emmanuel Grumbacha1022922014-05-12 11:36:41 +0300609 0, sizeof(adv_cmd), &adv_cmd);
Wey-Yi Guy0975cc82010-07-31 08:34:07 -0700610 if (ret)
611 IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
612 else
613 IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
Emmanuel Grumbachd6189122011-08-25 23:10:39 -0700614 "succeeded, critical temperature enter is %d,"
615 "exit is %d\n",
Johannes Berg9e295112012-04-09 17:46:55 -0700616 priv->hw_params.ct_kill_threshold,
617 priv->hw_params.ct_kill_exit_threshold);
Wey-Yi Guy0975cc82010-07-31 08:34:07 -0700618 } else {
619 cmd.critical_temperature_R =
Johannes Berg9e295112012-04-09 17:46:55 -0700620 cpu_to_le32(priv->hw_params.ct_kill_threshold);
Wey-Yi Guy0975cc82010-07-31 08:34:07 -0700621
Johannes Berge10a0532012-03-06 13:30:39 -0800622 ret = iwl_dvm_send_cmd_pdu(priv,
Emmanuel Grumbache419d622011-07-08 08:46:14 -0700623 REPLY_CT_KILL_CONFIG_CMD,
Emmanuel Grumbacha1022922014-05-12 11:36:41 +0300624 0, sizeof(cmd), &cmd);
Wey-Yi Guy0975cc82010-07-31 08:34:07 -0700625 if (ret)
626 IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
627 else
628 IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
Emmanuel Grumbachd6189122011-08-25 23:10:39 -0700629 "succeeded, "
630 "critical temperature is %d\n",
Johannes Berg9e295112012-04-09 17:46:55 -0700631 priv->hw_params.ct_kill_threshold);
Wey-Yi Guy0975cc82010-07-31 08:34:07 -0700632 }
633}
634
Shanyu Zhao6d6a1af2010-09-14 18:13:31 -0700635static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
636{
637 struct iwl_calib_cfg_cmd calib_cfg_cmd;
638 struct iwl_host_cmd cmd = {
639 .id = CALIBRATION_CFG_CMD,
Johannes Berg3fa50732011-05-04 07:50:38 -0700640 .len = { sizeof(struct iwl_calib_cfg_cmd), },
641 .data = { &calib_cfg_cmd, },
Shanyu Zhao6d6a1af2010-09-14 18:13:31 -0700642 };
643
644 memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd));
Wey-Yi Guyaf4dc882011-10-04 07:10:19 -0700645 calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_RT_CFG_ALL;
Wey-Yi Guy7cb1b082010-10-06 08:10:00 -0700646 calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg);
Shanyu Zhao6d6a1af2010-09-14 18:13:31 -0700647
Johannes Berge10a0532012-03-06 13:30:39 -0800648 return iwl_dvm_send_cmd(priv, &cmd);
Shanyu Zhao6d6a1af2010-09-14 18:13:31 -0700649}
650
651
Wey-Yi Guye505c432011-07-07 08:27:41 -0700652static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
653{
654 struct iwl_tx_ant_config_cmd tx_ant_cmd = {
655 .valid = cpu_to_le32(valid_tx_ant),
656 };
657
Johannes Berg0692fe42012-03-06 13:30:37 -0800658 if (IWL_UCODE_API(priv->fw->ucode_ver) > 1) {
Wey-Yi Guye505c432011-07-07 08:27:41 -0700659 IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant);
Emmanuel Grumbacha1022922014-05-12 11:36:41 +0300660 return iwl_dvm_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD, 0,
Wey-Yi Guye505c432011-07-07 08:27:41 -0700661 sizeof(struct iwl_tx_ant_config_cmd),
662 &tx_ant_cmd);
663 } else {
664 IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n");
665 return -EOPNOTSUPP;
666 }
667}
668
Johannes Bergaca86262012-05-14 09:08:50 +0200669static void iwl_send_bt_config(struct iwl_priv *priv)
Meenakshi Venkataramane4c52ab2012-03-13 18:23:51 -0700670{
671 struct iwl_bt_cmd bt_cmd = {
672 .lead_time = BT_LEAD_TIME_DEF,
673 .max_kill = BT_MAX_KILL_DEF,
674 .kill_ack_mask = 0,
675 .kill_cts_mask = 0,
676 };
677
Johannes Berg65de7e82012-04-17 07:36:30 -0700678 if (!iwlwifi_mod_params.bt_coex_active)
Meenakshi Venkataramane4c52ab2012-03-13 18:23:51 -0700679 bt_cmd.flags = BT_COEX_DISABLE;
680 else
681 bt_cmd.flags = BT_COEX_ENABLE;
682
683 priv->bt_enable_flag = bt_cmd.flags;
684 IWL_DEBUG_INFO(priv, "BT coex %s\n",
685 (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
686
687 if (iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
Emmanuel Grumbacha1022922014-05-12 11:36:41 +0300688 0, sizeof(struct iwl_bt_cmd), &bt_cmd))
Meenakshi Venkataramane4c52ab2012-03-13 18:23:51 -0700689 IWL_ERR(priv, "failed to send BT Coex Config\n");
690}
691
Zhu Yib481de92007-09-25 17:54:57 -0700692/**
Tomas Winkler4a4a9e82008-05-29 16:34:54 +0800693 * iwl_alive_start - called after REPLY_ALIVE notification received
Zhu Yib481de92007-09-25 17:54:57 -0700694 * from protocol/runtime uCode (initialization uCode's
Tomas Winkler4a4a9e82008-05-29 16:34:54 +0800695 * Alive gets handled by iwl_init_alive_start()).
Zhu Yib481de92007-09-25 17:54:57 -0700696 */
Cindy H. Kao4613e722011-05-06 10:40:15 -0700697int iwl_alive_start(struct iwl_priv *priv)
Zhu Yib481de92007-09-25 17:54:57 -0700698{
Tomas Winkler57aab752008-04-14 21:16:03 -0700699 int ret = 0;
Johannes Berg246ed352010-08-23 10:46:32 +0200700 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
Zhu Yib481de92007-09-25 17:54:57 -0700701
Tomas Winklere1623442009-01-27 14:27:56 -0800702 IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
Zhu Yib481de92007-09-25 17:54:57 -0700703
Emmanuel Grumbach5b9f8cd2008-10-29 14:05:46 -0700704 /* After the ALIVE response, we can send host commands to the uCode */
Don Fry83626402012-03-07 09:52:37 -0800705 set_bit(STATUS_ALIVE, &priv->status);
Zhu Yib481de92007-09-25 17:54:57 -0700706
Don Fry83626402012-03-07 09:52:37 -0800707 if (iwl_is_rfkill(priv))
Johannes Bergca7966c2011-04-22 10:15:23 -0700708 return -ERFKILL;
Zhu Yib481de92007-09-25 17:54:57 -0700709
Johannes Berg98d4bf02012-01-13 11:56:11 +0100710 if (priv->event_log.ucode_trace) {
711 /* start collecting data now */
712 mod_timer(&priv->ucode_trace, jiffies);
713 }
714
Wey-Yi Guybc795df2010-10-11 14:24:05 -0700715 /* download priority table before any calibration request */
Johannes Berg0d8877a2013-05-17 10:36:29 +0200716 if (priv->lib->bt_params &&
717 priv->lib->bt_params->advanced_bt_coexist) {
Wey-Yi Guyf7322f82010-08-23 15:24:49 -0700718 /* Configure Bluetooth device coexistence support */
Johannes Berg0d8877a2013-05-17 10:36:29 +0200719 if (priv->lib->bt_params->bt_sco_disable)
Meenakshi Venkataraman207ecc52011-07-08 08:46:23 -0700720 priv->bt_enable_pspoll = false;
721 else
722 priv->bt_enable_pspoll = true;
723
Wey-Yi Guyf7322f82010-08-23 15:24:49 -0700724 priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
725 priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
726 priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
Wey-Yi Guye55b5172011-06-28 11:46:28 -0700727 iwlagn_send_advance_bt_config(priv);
Wey-Yi Guyf7322f82010-08-23 15:24:49 -0700728 priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
Meenakshi Venkataraman207ecc52011-07-08 08:46:23 -0700729 priv->cur_rssi_ctx = NULL;
730
Johannes Berge1991882012-03-06 13:30:36 -0800731 iwl_send_prio_tbl(priv);
Wey-Yi Guyf7322f82010-08-23 15:24:49 -0700732
733 /* FIXME: w/a to force change uCode BT state machine */
Johannes Berge1991882012-03-06 13:30:36 -0800734 ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
Johannes Bergca7966c2011-04-22 10:15:23 -0700735 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
736 if (ret)
737 return ret;
Johannes Berge1991882012-03-06 13:30:36 -0800738 ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE,
Johannes Bergca7966c2011-04-22 10:15:23 -0700739 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
740 if (ret)
741 return ret;
Johannes Berg707aee42013-05-03 18:58:16 +0200742 } else if (priv->lib->bt_params) {
Wey-Yi Guye55b5172011-06-28 11:46:28 -0700743 /*
744 * default is 2-wire BT coexexistence support
745 */
746 iwl_send_bt_config(priv);
Wey-Yi Guyf7322f82010-08-23 15:24:49 -0700747 }
Wey-Yi Guye55b5172011-06-28 11:46:28 -0700748
Venkataraman, Meenakshi885765f2011-12-14 16:54:21 -0800749 /*
750 * Perform runtime calibrations, including DC calibration.
751 */
752 iwlagn_send_calib_cfg_rt(priv, IWL_CALIB_CFG_DC_IDX);
Wey-Yi Guybc795df2010-10-11 14:24:05 -0700753
Johannes Berg36d68252008-05-15 12:55:26 +0200754 ieee80211_wake_queues(priv->hw);
Zhu Yib481de92007-09-25 17:54:57 -0700755
Wey-Yi Guy2f748de2009-09-17 10:43:51 -0700756 /* Configure Tx antenna selection based on H/W config */
Eytan Lifshitzb7998c82012-12-01 20:59:49 +0200757 iwlagn_send_tx_ant_config(priv, priv->nvm_data->valid_tx_ant);
Wey-Yi Guy2f748de2009-09-17 10:43:51 -0700758
Johannes Berg15b86bf2012-03-05 11:24:36 -0800759 if (iwl_is_associated_ctx(ctx) && !priv->wowlan) {
Gregory Greenmanc1adf9f2008-05-15 13:53:59 +0800760 struct iwl_rxon_cmd *active_rxon =
Johannes Berg246ed352010-08-23 10:46:32 +0200761 (struct iwl_rxon_cmd *)&ctx->active;
Mohamed Abbas019fb972009-03-17 21:59:18 -0700762 /* apply any changes in staging */
Johannes Berg246ed352010-08-23 10:46:32 +0200763 ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
Zhu Yib481de92007-09-25 17:54:57 -0700764 active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
765 } else {
Johannes Bergd0fe4782010-08-23 10:46:58 +0200766 struct iwl_rxon_context *tmp;
Zhu Yib481de92007-09-25 17:54:57 -0700767 /* Initialize our rx_config data */
Johannes Bergd0fe4782010-08-23 10:46:58 +0200768 for_each_context(priv, tmp)
769 iwl_connection_init_rx_config(priv, tmp);
Abhijeet Kolekar45823532009-04-08 11:26:44 -0700770
Wey-Yi Guye3f10ce2011-07-01 07:59:26 -0700771 iwlagn_set_rxon_chain(priv, ctx);
Zhu Yib481de92007-09-25 17:54:57 -0700772 }
773
Johannes Berg15b86bf2012-03-05 11:24:36 -0800774 if (!priv->wowlan) {
Johannes Bergc8ac61c2011-07-15 13:23:45 -0700775 /* WoWLAN ucode will not reply in the same way, skip it */
776 iwl_reset_run_time_calib(priv);
777 }
Tomas Winkler4a4a9e82008-05-29 16:34:54 +0800778
Don Fry83626402012-03-07 09:52:37 -0800779 set_bit(STATUS_READY, &priv->status);
Wey-Yi Guy9e2e7422010-11-12 13:52:37 -0800780
Zhu Yib481de92007-09-25 17:54:57 -0700781 /* Configure the adapter for unassociated operation */
Wey-Yi Guy805a3b82011-06-03 07:54:16 -0700782 ret = iwlagn_commit_rxon(priv, ctx);
Johannes Bergca7966c2011-04-22 10:15:23 -0700783 if (ret)
784 return ret;
Zhu Yib481de92007-09-25 17:54:57 -0700785
786 /* At this point, the NIC is initialized and operational */
Emmanuel Grumbach47f4a582008-06-12 09:47:13 +0800787 iwl_rf_kill_ct_config(priv);
Zhu Yi5a66926a2008-01-14 17:46:18 -0800788
Tomas Winklere1623442009-01-27 14:27:56 -0800789 IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
Zhu Yib481de92007-09-25 17:54:57 -0700790
Johannes Bergca7966c2011-04-22 10:15:23 -0700791 return iwl_power_update_mode(priv, true);
Zhu Yib481de92007-09-25 17:54:57 -0700792}
793
Johannes Bergd3163832012-03-05 11:24:19 -0800794/**
795 * iwl_clear_driver_stations - clear knowledge of all stations from driver
796 * @priv: iwl priv struct
797 *
798 * This is called during iwl_down() to make sure that in the case
799 * we're coming there from a hardware restart mac80211 will be
800 * able to reconfigure stations -- if we're getting there in the
801 * normal down flow then the stations will already be cleared.
802 */
803static void iwl_clear_driver_stations(struct iwl_priv *priv)
804{
Johannes Bergd3163832012-03-05 11:24:19 -0800805 struct iwl_rxon_context *ctx;
806
Johannes Bergfa23cb02012-03-05 11:24:25 -0800807 spin_lock_bh(&priv->sta_lock);
Johannes Bergd3163832012-03-05 11:24:19 -0800808 memset(priv->stations, 0, sizeof(priv->stations));
809 priv->num_stations = 0;
810
811 priv->ucode_key_table = 0;
812
813 for_each_context(priv, ctx) {
814 /*
815 * Remove all key information that is not stored as part
816 * of station information since mac80211 may not have had
817 * a chance to remove all the keys. When device is
818 * reconfigured by mac80211 after an error all keys will
819 * be reconfigured.
820 */
821 memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys));
822 ctx->key_mapping_keys = 0;
823 }
824
Johannes Bergfa23cb02012-03-05 11:24:25 -0800825 spin_unlock_bh(&priv->sta_lock);
Johannes Bergd3163832012-03-05 11:24:19 -0800826}
827
Emmanuel Grumbach78e5a462012-02-17 10:34:53 -0800828void iwl_down(struct iwl_priv *priv)
Zhu Yib481de92007-09-25 17:54:57 -0700829{
Dan Carpenter22dd2fd2011-03-15 10:03:24 +0300830 int exit_pending;
Zhu Yib481de92007-09-25 17:54:57 -0700831
Tomas Winklere1623442009-01-27 14:27:56 -0800832 IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
Zhu Yib481de92007-09-25 17:54:57 -0700833
Johannes Bergb1eea292012-03-06 13:30:42 -0800834 lockdep_assert_held(&priv->mutex);
Emmanuel Grumbach78e5a462012-02-17 10:34:53 -0800835
Stanislaw Gruszkad745d472010-09-13 14:46:35 +0200836 iwl_scan_cancel_timeout(priv, 200);
837
Emmanuel Grumbach63013ae2011-08-25 23:10:42 -0700838 exit_pending =
Don Fry83626402012-03-07 09:52:37 -0800839 test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
Zhu Yib481de92007-09-25 17:54:57 -0700840
Johannes Bergdcef7322010-08-27 08:55:52 -0700841 iwl_clear_ucode_stations(priv, NULL);
Johannes Berga194e322010-08-27 08:53:46 -0700842 iwl_dealloc_bcast_stations(priv);
Johannes Bergdb125c72010-05-07 01:49:15 -0700843 iwl_clear_driver_stations(priv);
Zhu Yib481de92007-09-25 17:54:57 -0700844
Johannes Berga1174132010-08-23 07:56:59 -0700845 /* reset BT coex data */
Wey-Yi Guyda5dbb92010-08-23 07:57:13 -0700846 priv->bt_status = 0;
Meenakshi Venkataraman207ecc52011-07-08 08:46:23 -0700847 priv->cur_rssi_ctx = NULL;
848 priv->bt_is_sco = 0;
Johannes Berg0d8877a2013-05-17 10:36:29 +0200849 if (priv->lib->bt_params)
Wey-Yi Guy7cb1b082010-10-06 08:10:00 -0700850 priv->bt_traffic_load =
Johannes Berg0d8877a2013-05-17 10:36:29 +0200851 priv->lib->bt_params->bt_init_traffic_load;
Wey-Yi Guy7cb1b082010-10-06 08:10:00 -0700852 else
853 priv->bt_traffic_load = 0;
Wey-Yi Guybee008b2010-08-23 07:57:04 -0700854 priv->bt_full_concurrent = false;
855 priv->bt_ci_compliance = 0;
Johannes Berga1174132010-08-23 07:56:59 -0700856
Zhu Yib481de92007-09-25 17:54:57 -0700857 /* Wipe out the EXIT_PENDING status bit if we are not actually
858 * exiting the module */
859 if (!exit_pending)
Don Fry83626402012-03-07 09:52:37 -0800860 clear_bit(STATUS_EXIT_PENDING, &priv->status);
Zhu Yib481de92007-09-25 17:54:57 -0700861
Emmanuel Grumbach859cfb02011-09-15 11:46:31 -0700862 if (priv->mac80211_registered)
Zhu Yib481de92007-09-25 17:54:57 -0700863 ieee80211_stop_queues(priv->hw);
864
David Spinadel8f7ffbe2012-03-10 13:00:10 -0800865 priv->ucode_loaded = false;
Emmanuel Grumbach68e8dfd2012-04-18 07:28:17 -0700866 iwl_trans_stop_device(priv->trans);
Emmanuel Grumbach909e9b22011-09-15 11:46:30 -0700867
Ilan Peer622a9262012-05-09 16:11:55 +0300868 /* Set num_aux_in_flight must be done after the transport is stopped */
869 atomic_set(&priv->num_aux_in_flight, 0);
870
Johannes Berg1a10f432011-04-13 03:14:44 -0700871 /* Clear out all status bits but a few that are stable across reset */
Don Fry1353a7b2012-03-07 09:52:43 -0800872 priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
Zhu Yib481de92007-09-25 17:54:57 -0700873 STATUS_RF_KILL_HW |
Don Fry17acd0b2012-03-15 13:27:05 -0700874 test_bit(STATUS_FW_ERROR, &priv->status) <<
875 STATUS_FW_ERROR |
Don Fry83626402012-03-07 09:52:37 -0800876 test_bit(STATUS_EXIT_PENDING, &priv->status) <<
Mohamed Abbas052ec3f2008-06-30 17:23:15 +0800877 STATUS_EXIT_PENDING;
Zhu Yib481de92007-09-25 17:54:57 -0700878
Johannes Berg77834542010-10-04 05:50:36 -0700879 dev_kfree_skb(priv->beacon_skb);
Johannes Berg12e934d2010-10-04 05:50:06 -0700880 priv->beacon_skb = NULL;
Zhu Yib481de92007-09-25 17:54:57 -0700881}
882
Zhu Yib481de92007-09-25 17:54:57 -0700883/*****************************************************************************
884 *
885 * Workqueue callbacks
886 *
887 *****************************************************************************/
888
Emmanuel Grumbach16e727e2008-06-12 09:46:52 +0800889static void iwl_bg_run_time_calib_work(struct work_struct *work)
890{
891 struct iwl_priv *priv = container_of(work, struct iwl_priv,
892 run_time_calib_work);
893
Johannes Bergb1eea292012-03-06 13:30:42 -0800894 mutex_lock(&priv->mutex);
Emmanuel Grumbach16e727e2008-06-12 09:46:52 +0800895
Don Fry83626402012-03-07 09:52:37 -0800896 if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
897 test_bit(STATUS_SCANNING, &priv->status)) {
Johannes Bergb1eea292012-03-06 13:30:42 -0800898 mutex_unlock(&priv->mutex);
Emmanuel Grumbach16e727e2008-06-12 09:46:52 +0800899 return;
900 }
901
902 if (priv->start_calib) {
Johannes Berg0da0e5b2011-04-08 08:14:56 -0700903 iwl_chain_noise_calibration(priv);
904 iwl_sensitivity_calibration(priv);
Emmanuel Grumbach16e727e2008-06-12 09:46:52 +0800905 }
906
Johannes Bergb1eea292012-03-06 13:30:42 -0800907 mutex_unlock(&priv->mutex);
Emmanuel Grumbach16e727e2008-06-12 09:46:52 +0800908}
909
Wey-Yi Guy73356132011-11-10 06:55:11 -0800910void iwlagn_prepare_restart(struct iwl_priv *priv)
Johannes Berge43e85c2011-04-19 07:45:16 -0700911{
Johannes Berge43e85c2011-04-19 07:45:16 -0700912 bool bt_full_concurrent;
913 u8 bt_ci_compliance;
914 u8 bt_load;
915 u8 bt_status;
Meenakshi Venkataraman207ecc52011-07-08 08:46:23 -0700916 bool bt_is_sco;
Johannes Berg9eae88f2012-03-15 13:26:52 -0700917 int i;
Johannes Berge43e85c2011-04-19 07:45:16 -0700918
Johannes Bergb1eea292012-03-06 13:30:42 -0800919 lockdep_assert_held(&priv->mutex);
Johannes Berge43e85c2011-04-19 07:45:16 -0700920
Johannes Berge43e85c2011-04-19 07:45:16 -0700921 priv->is_open = 0;
922
923 /*
924 * __iwl_down() will clear the BT status variables,
925 * which is correct, but when we restart we really
926 * want to keep them so restore them afterwards.
927 *
928 * The restart process will later pick them up and
929 * re-configure the hw when we reconfigure the BT
930 * command.
931 */
932 bt_full_concurrent = priv->bt_full_concurrent;
933 bt_ci_compliance = priv->bt_ci_compliance;
934 bt_load = priv->bt_traffic_load;
935 bt_status = priv->bt_status;
Meenakshi Venkataraman207ecc52011-07-08 08:46:23 -0700936 bt_is_sco = priv->bt_is_sco;
Johannes Berge43e85c2011-04-19 07:45:16 -0700937
Emmanuel Grumbach78e5a462012-02-17 10:34:53 -0800938 iwl_down(priv);
Johannes Berge43e85c2011-04-19 07:45:16 -0700939
940 priv->bt_full_concurrent = bt_full_concurrent;
941 priv->bt_ci_compliance = bt_ci_compliance;
942 priv->bt_traffic_load = bt_load;
943 priv->bt_status = bt_status;
Meenakshi Venkataraman207ecc52011-07-08 08:46:23 -0700944 priv->bt_is_sco = bt_is_sco;
Johannes Berg9eae88f2012-03-15 13:26:52 -0700945
Johannes Berg14791772012-04-17 07:39:03 -0700946 /* reset aggregation queues */
Johannes Berg9eae88f2012-03-15 13:26:52 -0700947 for (i = IWLAGN_FIRST_AMPDU_QUEUE; i < IWL_MAX_HW_QUEUES; i++)
Johannes Berg14791772012-04-17 07:39:03 -0700948 priv->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE;
949 /* and stop counts */
950 for (i = 0; i < IWL_MAX_HW_QUEUES; i++)
951 atomic_set(&priv->queue_stop_count[i], 0);
Johannes Berg9eae88f2012-03-15 13:26:52 -0700952
953 memset(priv->agg_q_alloc, 0, sizeof(priv->agg_q_alloc));
Johannes Berge43e85c2011-04-19 07:45:16 -0700954}
955
Emmanuel Grumbach5b9f8cd2008-10-29 14:05:46 -0700956static void iwl_bg_restart(struct work_struct *data)
Zhu Yib481de92007-09-25 17:54:57 -0700957{
Tomas Winklerc79dd5b2008-03-12 16:58:50 -0700958 struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
Zhu Yib481de92007-09-25 17:54:57 -0700959
Don Fry83626402012-03-07 09:52:37 -0800960 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
Zhu Yib481de92007-09-25 17:54:57 -0700961 return;
962
Don Fry17acd0b2012-03-15 13:27:05 -0700963 if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
Johannes Bergb1eea292012-03-06 13:30:42 -0800964 mutex_lock(&priv->mutex);
Johannes Berge43e85c2011-04-19 07:45:16 -0700965 iwlagn_prepare_restart(priv);
Johannes Bergb1eea292012-03-06 13:30:42 -0800966 mutex_unlock(&priv->mutex);
Johannes Berga1174132010-08-23 07:56:59 -0700967 iwl_cancel_deferred_work(priv);
Amit Beka40503f72012-08-06 17:01:05 +0300968 if (priv->mac80211_registered)
969 ieee80211_restart_hw(priv->hw);
970 else
971 IWL_ERR(priv,
Johannes Berg3c6acb62014-05-07 11:47:53 +0200972 "Cannot request restart before registrating with mac80211\n");
Johannes Berg19cc1082009-05-08 13:44:36 -0700973 } else {
Johannes Bergca7966c2011-04-22 10:15:23 -0700974 WARN_ON(1);
Johannes Berg19cc1082009-05-08 13:44:36 -0700975 }
Zhu Yib481de92007-09-25 17:54:57 -0700976}
977
Zhu Yib481de92007-09-25 17:54:57 -0700978/*****************************************************************************
979 *
Zhu Yib481de92007-09-25 17:54:57 -0700980 * driver setup and teardown
981 *
982 *****************************************************************************/
983
Johannes Bergaca86262012-05-14 09:08:50 +0200984static void iwl_setup_deferred_work(struct iwl_priv *priv)
Zhu Yib481de92007-09-25 17:54:57 -0700985{
Johannes Berg1ee158d2012-02-17 10:07:44 -0800986 priv->workqueue = create_singlethread_workqueue(DRV_NAME);
Zhu Yib481de92007-09-25 17:54:57 -0700987
Emmanuel Grumbach5b9f8cd2008-10-29 14:05:46 -0700988 INIT_WORK(&priv->restart, iwl_bg_restart);
Emmanuel Grumbach5b9f8cd2008-10-29 14:05:46 -0700989 INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
Emmanuel Grumbach16e727e2008-06-12 09:46:52 +0800990 INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
Wey-Yi Guy65550632010-06-24 13:18:35 -0700991 INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush);
Wey-Yi Guybee008b2010-08-23 07:57:04 -0700992 INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency);
Wey-Yi Guyfbba9412010-08-23 07:57:10 -0700993 INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config);
Tomas Winkler2a421b92008-06-12 09:47:10 +0800994
Tomas Winkler2a421b92008-06-12 09:47:10 +0800995 iwl_setup_scan_deferred_work(priv);
Zhu Yib481de92007-09-25 17:54:57 -0700996
Johannes Berg0d8877a2013-05-17 10:36:29 +0200997 if (priv->lib->bt_params)
Johannes Berg562f08e2012-03-07 09:52:18 -0800998 iwlagn_bt_setup_deferred_work(priv);
Emmanuel Grumbach4e393172008-06-12 09:46:53 +0800999
Julia Lawallbd9c5042014-12-26 15:35:44 +01001000 setup_timer(&priv->statistics_periodic, iwl_bg_statistics_periodic,
1001 (unsigned long)priv);
Zhu Yib481de92007-09-25 17:54:57 -07001002
Julia Lawallbd9c5042014-12-26 15:35:44 +01001003 setup_timer(&priv->ucode_trace, iwl_bg_ucode_trace,
1004 (unsigned long)priv);
Zhu Yib481de92007-09-25 17:54:57 -07001005}
1006
Emmanuel Grumbach78e5a462012-02-17 10:34:53 -08001007void iwl_cancel_deferred_work(struct iwl_priv *priv)
Zhu Yib481de92007-09-25 17:54:57 -07001008{
Johannes Berg0d8877a2013-05-17 10:36:29 +02001009 if (priv->lib->bt_params)
Johannes Berg562f08e2012-03-07 09:52:18 -08001010 iwlagn_bt_cancel_deferred_work(priv);
Zhu Yib481de92007-09-25 17:54:57 -07001011
Wey-Yi Guy815e6292010-06-03 10:14:01 -07001012 cancel_work_sync(&priv->run_time_calib_work);
Zhu Yib481de92007-09-25 17:54:57 -07001013 cancel_work_sync(&priv->beacon_update);
Stanislaw Gruszkae7e16b92010-09-13 14:46:41 +02001014
1015 iwl_cancel_scan_deferred_work(priv);
1016
Wey-Yi Guybee008b2010-08-23 07:57:04 -07001017 cancel_work_sync(&priv->bt_full_concurrency);
Wey-Yi Guyfbba9412010-08-23 07:57:10 -07001018 cancel_work_sync(&priv->bt_runtime_config);
Stanislaw Gruszkae7e16b92010-09-13 14:46:41 +02001019
Emmanuel Grumbach4e393172008-06-12 09:46:53 +08001020 del_timer_sync(&priv->statistics_periodic);
Wey-Yi Guya9e1cb62009-12-10 14:37:26 -08001021 del_timer_sync(&priv->ucode_trace);
Zhu Yib481de92007-09-25 17:54:57 -07001022}
1023
Johannes Bergaca86262012-05-14 09:08:50 +02001024static int iwl_init_drv(struct iwl_priv *priv)
Reinette Chatre89f186a2009-10-30 14:36:11 -07001025{
Johannes Bergfa23cb02012-03-05 11:24:25 -08001026 spin_lock_init(&priv->sta_lock);
Reinette Chatre89f186a2009-10-30 14:36:11 -07001027
Johannes Bergb1eea292012-03-06 13:30:42 -08001028 mutex_init(&priv->mutex);
Reinette Chatre89f186a2009-10-30 14:36:11 -07001029
Johannes Berge1991882012-03-06 13:30:36 -08001030 INIT_LIST_HEAD(&priv->calib_results);
Johannes Berg80e83da2011-11-25 11:11:44 -08001031
Reinette Chatre89f186a2009-10-30 14:36:11 -07001032 priv->band = IEEE80211_BAND_2GHZ;
1033
Johannes Berg0d8877a2013-05-17 10:36:29 +02001034 priv->plcp_delta_threshold = priv->lib->plcp_delta_threshold;
Johannes Bergab5c0f12012-03-06 13:30:53 -08001035
Reinette Chatre89f186a2009-10-30 14:36:11 -07001036 priv->iw_mode = NL80211_IFTYPE_STATION;
Johannes Bergba37a3d2009-12-10 14:37:27 -08001037 priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
Wey-Yi Guya13d2762010-01-22 14:22:42 -08001038 priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
Wey-Yi Guy898ed672011-07-13 08:38:57 -07001039 priv->agg_tids_count = 0;
Reinette Chatre89f186a2009-10-30 14:36:11 -07001040
Stanislaw Gruszka410f2bb2011-03-04 17:51:51 +01001041 priv->rx_statistics_jiffies = jiffies;
1042
Reinette Chatre89f186a2009-10-30 14:36:11 -07001043 /* Choose which receivers/antennas to use */
Wey-Yi Guye3f10ce2011-07-01 07:59:26 -07001044 iwlagn_set_rxon_chain(priv, &priv->contexts[IWL_RXON_CTX_BSS]);
Reinette Chatre89f186a2009-10-30 14:36:11 -07001045
1046 iwl_init_scan_params(priv);
1047
Wey-Yi Guy22bf59a2010-08-23 07:57:11 -07001048 /* init bt coex */
Johannes Berg0d8877a2013-05-17 10:36:29 +02001049 if (priv->lib->bt_params &&
1050 priv->lib->bt_params->advanced_bt_coexist) {
Wey-Yi Guyb6e116e2010-08-23 07:57:14 -07001051 priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
1052 priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
1053 priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
Wey-Yi Guy22bf59a2010-08-23 07:57:11 -07001054 priv->bt_on_thresh = BT_ON_THRESHOLD_DEF;
1055 priv->bt_duration = BT_DURATION_LIMIT_DEF;
1056 priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF;
Wey-Yi Guy22bf59a2010-08-23 07:57:11 -07001057 }
1058
Reinette Chatre89f186a2009-10-30 14:36:11 -07001059 return 0;
Reinette Chatre89f186a2009-10-30 14:36:11 -07001060}
1061
Johannes Bergaca86262012-05-14 09:08:50 +02001062static void iwl_uninit_drv(struct iwl_priv *priv)
Reinette Chatre89f186a2009-10-30 14:36:11 -07001063{
Johannes Berg811ecc92010-04-06 04:12:41 -07001064 kfree(priv->scan_cmd);
Johannes Berg4ce7cc22011-05-13 11:57:40 -07001065 kfree(priv->beacon_cmd);
Johannes Berg79d3eef2011-11-10 06:55:01 -08001066 kfree(rcu_dereference_raw(priv->noa_data));
Johannes Berge1991882012-03-06 13:30:36 -08001067 iwl_calib_free_results(priv);
Johannes Bergc8ac61c2011-07-15 13:23:45 -07001068#ifdef CONFIG_IWLWIFI_DEBUGFS
1069 kfree(priv->wowlan_sram);
1070#endif
Reinette Chatre89f186a2009-10-30 14:36:11 -07001071}
1072
Johannes Bergaca86262012-05-14 09:08:50 +02001073static void iwl_set_hw_params(struct iwl_priv *priv)
Wey-Yi Guy07d4f1a2010-07-31 08:34:08 -07001074{
Emmanuel Grumbach21522682012-03-22 17:51:44 +02001075 if (priv->cfg->ht_params)
Johannes Berg9e295112012-04-09 17:46:55 -07001076 priv->hw_params.use_rts_for_aggregation =
Emmanuel Grumbach21522682012-03-22 17:51:44 +02001077 priv->cfg->ht_params->use_rts_for_aggregation;
Johannes Bergb9ad70d2012-03-06 13:30:55 -08001078
Wey-Yi Guy07d4f1a2010-07-31 08:34:08 -07001079 /* Device-specific setup */
Johannes Berge9676692012-04-10 14:10:28 -07001080 priv->lib->set_hw_params(priv);
Wey-Yi Guy07d4f1a2010-07-31 08:34:08 -07001081}
1082
Wey-Yi Guy119ea182011-04-18 09:34:06 -07001083
Wey-Yi Guy119ea182011-04-18 09:34:06 -07001084
Wey-Yi Guy07d3c152012-04-27 16:18:47 -07001085/* show what optional capabilities we have */
Johannes Bergaca86262012-05-14 09:08:50 +02001086static void iwl_option_config(struct iwl_priv *priv)
Wey-Yi Guyebfa8672011-11-25 11:11:47 -08001087{
Wey-Yi Guyebfa8672011-11-25 11:11:47 -08001088#ifdef CONFIG_IWLWIFI_DEBUG
Wey-Yi Guy07d3c152012-04-27 16:18:47 -07001089 IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUG enabled\n");
Wey-Yi Guyebfa8672011-11-25 11:11:47 -08001090#else
Wey-Yi Guy07d3c152012-04-27 16:18:47 -07001091 IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUG disabled\n");
Wey-Yi Guyebfa8672011-11-25 11:11:47 -08001092#endif
Wey-Yi Guy07d3c152012-04-27 16:18:47 -07001093
Wey-Yi Guyebfa8672011-11-25 11:11:47 -08001094#ifdef CONFIG_IWLWIFI_DEBUGFS
Wey-Yi Guy07d3c152012-04-27 16:18:47 -07001095 IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUGFS enabled\n");
Wey-Yi Guyebfa8672011-11-25 11:11:47 -08001096#else
Wey-Yi Guy07d3c152012-04-27 16:18:47 -07001097 IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUGFS disabled\n");
Wey-Yi Guyebfa8672011-11-25 11:11:47 -08001098#endif
Wey-Yi Guy07d3c152012-04-27 16:18:47 -07001099
Wey-Yi Guyebfa8672011-11-25 11:11:47 -08001100#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
Wey-Yi Guy07d3c152012-04-27 16:18:47 -07001101 IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING enabled\n");
Wey-Yi Guyebfa8672011-11-25 11:11:47 -08001102#else
Wey-Yi Guy07d3c152012-04-27 16:18:47 -07001103 IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING disabled\n");
Wey-Yi Guyebfa8672011-11-25 11:11:47 -08001104#endif
Wey-Yi Guyebfa8672011-11-25 11:11:47 -08001105}
1106
Johannes Berg26a7ca92012-05-21 11:55:54 +02001107static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
1108{
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001109 struct iwl_nvm_data *data = priv->nvm_data;
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001110
1111 if (data->sku_cap_11n_enable &&
Johannes Berg26a7ca92012-05-21 11:55:54 +02001112 !priv->cfg->ht_params) {
1113 IWL_ERR(priv, "Invalid 11n configuration\n");
1114 return -EINVAL;
1115 }
1116
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001117 if (!data->sku_cap_11n_enable && !data->sku_cap_band_24GHz_enable &&
1118 !data->sku_cap_band_52GHz_enable) {
Johannes Berg26a7ca92012-05-21 11:55:54 +02001119 IWL_ERR(priv, "Invalid device sku\n");
1120 return -EINVAL;
1121 }
1122
Johannes Berg3c6acb62014-05-07 11:47:53 +02001123 IWL_DEBUG_INFO(priv,
1124 "Device SKU: 24GHz %s %s, 52GHz %s %s, 11.n %s %s\n",
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001125 data->sku_cap_band_24GHz_enable ? "" : "NOT", "enabled",
1126 data->sku_cap_band_52GHz_enable ? "" : "NOT", "enabled",
1127 data->sku_cap_11n_enable ? "" : "NOT", "enabled");
Johannes Berg26a7ca92012-05-21 11:55:54 +02001128
Johannes Berg26a7ca92012-05-21 11:55:54 +02001129 priv->hw_params.tx_chains_num =
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001130 num_of_ant(data->valid_tx_ant);
Johannes Berg26a7ca92012-05-21 11:55:54 +02001131 if (priv->cfg->rx_with_siso_diversity)
1132 priv->hw_params.rx_chains_num = 1;
1133 else
1134 priv->hw_params.rx_chains_num =
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001135 num_of_ant(data->valid_rx_ant);
Johannes Berg26a7ca92012-05-21 11:55:54 +02001136
Johannes Berg468b4bf2012-11-05 19:48:33 +01001137 IWL_DEBUG_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n",
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001138 data->valid_tx_ant,
1139 data->valid_rx_ant);
Johannes Berg26a7ca92012-05-21 11:55:54 +02001140
1141 return 0;
1142}
1143
Johannes Berg0692fe42012-03-06 13:30:37 -08001144static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
Emmanuel Grumbach21522682012-03-22 17:51:44 +02001145 const struct iwl_cfg *cfg,
Meenakshi Venkataraman9da987a2012-07-16 18:43:56 -07001146 const struct iwl_fw *fw,
1147 struct dentry *dbgfs_dir)
Wey-Yi Guyb2ea3452011-06-07 08:53:14 -07001148{
Wey-Yi Guyb2ea3452011-06-07 08:53:14 -07001149 struct iwl_priv *priv;
1150 struct ieee80211_hw *hw;
Emmanuel Grumbachd0f76d62012-02-09 16:08:15 +02001151 struct iwl_op_mode *op_mode;
Emmanuel Grumbach084dd7912011-05-31 09:07:00 +03001152 u16 num_mac;
Johannes Berga78be212012-02-21 18:31:06 +02001153 u32 ucode_flags;
Emmanuel Grumbache7332692012-11-05 12:52:57 +02001154 struct iwl_trans_config trans_cfg = {};
Johannes Bergd663ee72012-03-10 13:00:07 -08001155 static const u8 no_reclaim_cmds[] = {
1156 REPLY_RX_PHY_CMD,
Johannes Bergd663ee72012-03-10 13:00:07 -08001157 REPLY_RX_MPDU_CMD,
1158 REPLY_COMPRESSED_BA,
1159 STATISTICS_NOTIFICATION,
1160 REPLY_TX,
1161 };
Johannes Berg9eae88f2012-03-15 13:26:52 -07001162 int i;
Wey-Yi Guyb2ea3452011-06-07 08:53:14 -07001163
1164 /************************
1165 * 1. Allocating HW data
1166 ************************/
Don Fryfa06ec72011-10-14 12:54:46 -07001167 hw = iwl_alloc_all();
Wey-Yi Guyb2ea3452011-06-07 08:53:14 -07001168 if (!hw) {
Emmanuel Grumbach21522682012-03-22 17:51:44 +02001169 pr_err("%s: Cannot allocate network device\n", cfg->name);
Emmanuel Grumbach807caf22011-06-09 02:55:55 -07001170 goto out;
1171 }
1172
Emmanuel Grumbachd0f76d62012-02-09 16:08:15 +02001173 op_mode = hw->priv;
1174 op_mode->ops = &iwl_dvm_ops;
1175 priv = IWL_OP_MODE_GET_DVM(op_mode);
Emmanuel Grumbach68e8dfd2012-04-18 07:28:17 -07001176 priv->trans = trans;
Emmanuel Grumbach4b9844f2012-03-22 23:59:52 +02001177 priv->dev = trans->dev;
Emmanuel Grumbach21522682012-03-22 17:51:44 +02001178 priv->cfg = cfg;
Johannes Berg0692fe42012-03-06 13:30:37 -08001179 priv->fw = fw;
Emmanuel Grumbacha48709c2011-05-31 08:22:30 +03001180
Emmanuel Grumbach21522682012-03-22 17:51:44 +02001181 switch (priv->cfg->device_family) {
Johannes Berge9676692012-04-10 14:10:28 -07001182 case IWL_DEVICE_FAMILY_1000:
1183 case IWL_DEVICE_FAMILY_100:
Johannes Bergee4d5472013-05-17 09:58:27 +02001184 priv->lib = &iwl_dvm_1000_cfg;
Johannes Berge9676692012-04-10 14:10:28 -07001185 break;
1186 case IWL_DEVICE_FAMILY_2000:
Johannes Bergee4d5472013-05-17 09:58:27 +02001187 priv->lib = &iwl_dvm_2000_cfg;
Johannes Berge9676692012-04-10 14:10:28 -07001188 break;
Johannes Berg0d8877a2013-05-17 10:36:29 +02001189 case IWL_DEVICE_FAMILY_105:
1190 priv->lib = &iwl_dvm_105_cfg;
1191 break;
Johannes Berge9676692012-04-10 14:10:28 -07001192 case IWL_DEVICE_FAMILY_2030:
1193 case IWL_DEVICE_FAMILY_135:
Johannes Bergee4d5472013-05-17 09:58:27 +02001194 priv->lib = &iwl_dvm_2030_cfg;
Johannes Berge9676692012-04-10 14:10:28 -07001195 break;
1196 case IWL_DEVICE_FAMILY_5000:
Johannes Bergee4d5472013-05-17 09:58:27 +02001197 priv->lib = &iwl_dvm_5000_cfg;
Johannes Berge9676692012-04-10 14:10:28 -07001198 break;
1199 case IWL_DEVICE_FAMILY_5150:
Johannes Bergee4d5472013-05-17 09:58:27 +02001200 priv->lib = &iwl_dvm_5150_cfg;
Johannes Berge9676692012-04-10 14:10:28 -07001201 break;
1202 case IWL_DEVICE_FAMILY_6000:
Johannes Berge9676692012-04-10 14:10:28 -07001203 case IWL_DEVICE_FAMILY_6000i:
Johannes Berg0d8877a2013-05-17 10:36:29 +02001204 priv->lib = &iwl_dvm_6000_cfg;
1205 break;
1206 case IWL_DEVICE_FAMILY_6005:
1207 priv->lib = &iwl_dvm_6005_cfg;
1208 break;
Johannes Berge9676692012-04-10 14:10:28 -07001209 case IWL_DEVICE_FAMILY_6050:
1210 case IWL_DEVICE_FAMILY_6150:
Johannes Berg0d8877a2013-05-17 10:36:29 +02001211 priv->lib = &iwl_dvm_6050_cfg;
Johannes Berge9676692012-04-10 14:10:28 -07001212 break;
1213 case IWL_DEVICE_FAMILY_6030:
Johannes Bergee4d5472013-05-17 09:58:27 +02001214 priv->lib = &iwl_dvm_6030_cfg;
Johannes Berge9676692012-04-10 14:10:28 -07001215 break;
1216 default:
1217 break;
1218 }
1219
1220 if (WARN_ON(!priv->lib))
Johannes Berg063c5162012-04-03 16:35:41 -07001221 goto out_free_hw;
Johannes Berge9676692012-04-10 14:10:28 -07001222
Emmanuel Grumbach3dc420b2012-03-07 09:52:41 -08001223 /*
1224 * Populate the state variables that the transport layer needs
1225 * to know about.
1226 */
1227 trans_cfg.op_mode = op_mode;
Johannes Bergd663ee72012-03-10 13:00:07 -08001228 trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
1229 trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
Johannes Berg65de7e82012-04-17 07:36:30 -07001230 trans_cfg.rx_buf_size_8k = iwlwifi_mod_params.amsdu_size_8K;
Emmanuel Grumbachce71c2f2015-01-11 17:19:39 +02001231 trans_cfg.queue_watchdog_timeout = IWL_WATCHDOG_DISABLED;
Johannes Bergd9fb6462012-03-26 08:23:39 -07001232 trans_cfg.command_names = iwl_dvm_cmd_strings;
Emmanuel Grumbachb04db9a2012-06-21 11:53:44 +03001233 trans_cfg.cmd_fifo = IWLAGN_CMD_FIFO_NUM;
Meenakshi Venkataraman9bdfbfa2012-03-07 09:52:36 -08001234
Emmanuel Grumbach303e56f2012-06-13 19:37:06 +03001235 WARN_ON(sizeof(priv->transport_queue_stop) * BITS_PER_BYTE <
1236 priv->cfg->base_params->num_of_queues);
1237
Meenakshi Venkataraman9bdfbfa2012-03-07 09:52:36 -08001238 ucode_flags = fw->ucode_capa.flags;
1239
Meenakshi Venkataramanc6f600f2012-03-08 11:29:12 -08001240 if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) {
1241 priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
1242 trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
1243 } else {
1244 priv->sta_key_max_num = STA_KEY_MAX_NUM;
1245 trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
1246 }
1247
Meenakshi Venkataraman92d743a2012-03-07 09:52:35 -08001248 /* Configure transport layer */
Emmanuel Grumbach68e8dfd2012-04-18 07:28:17 -07001249 iwl_trans_configure(priv->trans, &trans_cfg);
Emmanuel Grumbached277c92012-02-09 16:08:15 +02001250
Johannes Bergf042c2e2012-09-05 22:34:44 +02001251 trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
1252 trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start);
1253
Wey-Yi Guyb2ea3452011-06-07 08:53:14 -07001254 /* At this point both hw and priv are allocated. */
Johannes Berg8f2d3d22010-08-23 10:46:37 +02001255
Emmanuel Grumbach68e8dfd2012-04-18 07:28:17 -07001256 SET_IEEE80211_DEV(priv->hw, priv->trans->dev);
Zhu Yib481de92007-09-25 17:54:57 -07001257
Wey-Yi Guy07d3c152012-04-27 16:18:47 -07001258 iwl_option_config(priv);
Wey-Yi Guyebfa8672011-11-25 11:11:47 -08001259
Tomas Winklere1623442009-01-27 14:27:56 -08001260 IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
Assaf Krauss316c30d2008-03-14 10:38:46 -07001261
Wey-Yi Guybee008b2010-08-23 07:57:04 -07001262 /* is antenna coupling more than 35dB ? */
1263 priv->bt_ant_couple_ok =
Johannes Berg65de7e82012-04-17 07:36:30 -07001264 (iwlwifi_mod_params.ant_coupling >
Emmanuel Grumbach48f20d32011-08-25 23:10:36 -07001265 IWL_BT_ANTENNA_COUPLING_THRESHOLD) ?
1266 true : false;
Wey-Yi Guybee008b2010-08-23 07:57:04 -07001267
Emmanuel Grumbachbc53cd42013-06-18 06:29:56 +03001268 /* bt channel inhibition enabled*/
1269 priv->bt_ch_announce = true;
Wey-Yi Guy9f28ebc2010-11-26 13:24:19 -08001270 IWL_DEBUG_INFO(priv, "BT channel inhibition is %s\n",
1271 (priv->bt_ch_announce) ? "On" : "Off");
Wey-Yi Guyf37837c2010-08-23 07:57:12 -07001272
Reinette Chatre731a29b2009-12-14 14:12:11 -08001273 /* these spin locks will be used in apm_ops.init and EEPROM access
Mohamed Abbasa8b50a02009-05-22 11:01:47 -07001274 * we should init now
1275 */
Johannes Berg4ff70fc2012-03-05 11:24:26 -08001276 spin_lock_init(&priv->statistics.lock);
Reinette Chatre4843b5a2010-02-03 09:38:59 -08001277
Emmanuel Grumbach084dd7912011-05-31 09:07:00 +03001278 /***********************
Emmanuel Grumbach3dc420b2012-03-07 09:52:41 -08001279 * 2. Read REV register
Emmanuel Grumbach084dd7912011-05-31 09:07:00 +03001280 ***********************/
Shanyu Zhaoc11362c2010-03-05 17:05:20 -08001281 IWL_INFO(priv, "Detected %s, REV=0x%X\n",
Emmanuel Grumbach21522682012-03-22 17:51:44 +02001282 priv->cfg->name, priv->trans->hw_rev);
Assaf Krauss316c30d2008-03-14 10:38:46 -07001283
Emmanuel Grumbach68e8dfd2012-04-18 07:28:17 -07001284 if (iwl_trans_start_hw(priv->trans))
Johannes Berg063c5162012-04-03 16:35:41 -07001285 goto out_free_hw;
Emmanuel Grumbach1e89cbac2011-07-20 17:51:22 -07001286
Wey-Yi Guy88f10a12012-03-15 13:26:42 -07001287 /* Read the EEPROM */
Johannes Berg26a7ca92012-05-21 11:55:54 +02001288 if (iwl_read_eeprom(priv->trans, &priv->eeprom_blob,
1289 &priv->eeprom_blob_size)) {
Winkler, Tomas15b16872008-12-19 10:37:33 +08001290 IWL_ERR(priv, "Unable to init EEPROM\n");
Johannes Berg063c5162012-04-03 16:35:41 -07001291 goto out_free_hw;
Assaf Krauss316c30d2008-03-14 10:38:46 -07001292 }
Johannes Berg26a7ca92012-05-21 11:55:54 +02001293
Wey-Yi Guy88f10a12012-03-15 13:26:42 -07001294 /* Reset chip to save power until we load uCode during "up". */
Arik Nemtsova4082842013-11-24 19:10:46 +02001295 iwl_trans_stop_device(priv->trans);
Wey-Yi Guy88f10a12012-03-15 13:26:42 -07001296
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001297 priv->nvm_data = iwl_parse_eeprom_data(priv->trans->dev, priv->cfg,
Johannes Berg26a7ca92012-05-21 11:55:54 +02001298 priv->eeprom_blob,
1299 priv->eeprom_blob_size);
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001300 if (!priv->nvm_data)
Johannes Berg26a7ca92012-05-21 11:55:54 +02001301 goto out_free_eeprom_blob;
1302
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001303 if (iwl_nvm_check_version(priv->nvm_data, priv->trans))
Reinette Chatrec8f16132009-02-27 16:21:22 -08001304 goto out_free_eeprom;
Tomas Winkler8614f362008-04-23 17:14:55 -07001305
Wey-Yi Guy88f10a12012-03-15 13:26:42 -07001306 if (iwl_eeprom_init_hw_params(priv))
Wey-Yi Guy21a5b3c2010-11-10 13:32:59 -08001307 goto out_free_eeprom;
1308
Ron Rindjunsky02883012008-05-15 13:53:53 +08001309 /* extract MAC Address */
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001310 memcpy(priv->addresses[0].addr, priv->nvm_data->hw_addr, ETH_ALEN);
Wey-Yi Guyc6fa17e2010-07-15 05:58:30 -07001311 IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr);
1312 priv->hw->wiphy->addresses = priv->addresses;
1313 priv->hw->wiphy->n_addresses = 1;
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001314 num_mac = priv->nvm_data->n_hw_addrs;
Wey-Yi Guyc6fa17e2010-07-15 05:58:30 -07001315 if (num_mac > 1) {
1316 memcpy(priv->addresses[1].addr, priv->addresses[0].addr,
1317 ETH_ALEN);
1318 priv->addresses[1].addr[5]++;
1319 priv->hw->wiphy->n_addresses++;
1320 }
Assaf Krauss316c30d2008-03-14 10:38:46 -07001321
Emmanuel Grumbach3dc420b2012-03-07 09:52:41 -08001322 /************************
1323 * 4. Setup HW constants
1324 ************************/
1325 iwl_set_hw_params(priv);
1326
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001327 if (!(priv->nvm_data->sku_cap_ipan_enable)) {
Johannes Berg3c6acb62014-05-07 11:47:53 +02001328 IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN\n");
Emmanuel Grumbach3dc420b2012-03-07 09:52:41 -08001329 ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
1330 /*
1331 * if not PAN, then don't support P2P -- might be a uCode
1332 * packaging bug or due to the eeprom check above
1333 */
Emmanuel Grumbach3dc420b2012-03-07 09:52:41 -08001334 priv->sta_key_max_num = STA_KEY_MAX_NUM;
1335 trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
1336
1337 /* Configure transport layer again*/
Emmanuel Grumbach68e8dfd2012-04-18 07:28:17 -07001338 iwl_trans_configure(priv->trans, &trans_cfg);
Emmanuel Grumbach3dc420b2012-03-07 09:52:41 -08001339 }
1340
Assaf Krauss316c30d2008-03-14 10:38:46 -07001341 /*******************
Emmanuel Grumbach3dc420b2012-03-07 09:52:41 -08001342 * 5. Setup priv
Assaf Krauss316c30d2008-03-14 10:38:46 -07001343 *******************/
Johannes Berg9eae88f2012-03-15 13:26:52 -07001344 for (i = 0; i < IWL_MAX_HW_QUEUES; i++) {
Johannes Berg14791772012-04-17 07:39:03 -07001345 priv->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE;
1346 if (i < IWLAGN_FIRST_AMPDU_QUEUE &&
1347 i != IWL_DEFAULT_CMD_QUEUE_NUM &&
1348 i != IWL_IPAN_CMD_QUEUE_NUM)
1349 priv->queue_to_mac80211[i] = i;
1350 atomic_set(&priv->queue_stop_count[i], 0);
Johannes Berg9eae88f2012-03-15 13:26:52 -07001351 }
1352
Wey-Yi Guy88f10a12012-03-15 13:26:42 -07001353 if (iwl_init_drv(priv))
Ron Rindjunsky399f4902008-04-23 17:14:56 -07001354 goto out_free_eeprom;
Wey-Yi Guy88f10a12012-03-15 13:26:42 -07001355
Assaf Kraussbf85ea42008-03-14 10:38:49 -07001356 /* At this point both hw and priv are initialized. */
Assaf Krauss316c30d2008-03-14 10:38:46 -07001357
Assaf Krauss316c30d2008-03-14 10:38:46 -07001358 /********************
Emmanuel Grumbach3dc420b2012-03-07 09:52:41 -08001359 * 6. Setup services
Assaf Krauss316c30d2008-03-14 10:38:46 -07001360 ********************/
Emmanuel Grumbach4e393172008-06-12 09:46:53 +08001361 iwl_setup_deferred_work(priv);
Emmanuel Grumbach653fa4a2008-06-30 17:23:11 +08001362 iwl_setup_rx_handlers(priv);
Assaf Krauss316c30d2008-03-14 10:38:46 -07001363
Emmanuel Grumbach58d0f362008-06-12 09:47:19 +08001364 iwl_power_initialize(priv);
Wey-Yi Guy39b73fb12009-07-24 11:13:02 -07001365 iwl_tt_initialize(priv);
Johannes Berg158bea02010-01-22 14:22:53 -08001366
Emmanuel Grumbache211b242012-02-07 10:35:18 +02001367 snprintf(priv->hw->wiphy->fw_version,
1368 sizeof(priv->hw->wiphy->fw_version),
1369 "%s", fw->fw_version);
Johannes Berg562db532010-04-29 07:41:53 -07001370
Emmanuel Grumbache211b242012-02-07 10:35:18 +02001371 priv->new_scan_threshold_behaviour =
Johannes Berga78be212012-02-21 18:31:06 +02001372 !!(ucode_flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
Emmanuel Grumbache211b242012-02-07 10:35:18 +02001373
Emmanuel Grumbache211b242012-02-07 10:35:18 +02001374 priv->phy_calib_chain_noise_reset_cmd =
1375 fw->ucode_capa.standard_phy_calibration_size;
1376 priv->phy_calib_chain_noise_gain_cmd =
1377 fw->ucode_capa.standard_phy_calibration_size + 1;
1378
1379 /* initialize all valid contexts */
Johannes Berga78be212012-02-21 18:31:06 +02001380 iwl_init_context(priv, ucode_flags);
Emmanuel Grumbache211b242012-02-07 10:35:18 +02001381
1382 /**************************************************
1383 * This is still part of probe() in a sense...
1384 *
Emmanuel Grumbach3dc420b2012-03-07 09:52:41 -08001385 * 7. Setup and register with mac80211 and debugfs
Emmanuel Grumbache211b242012-02-07 10:35:18 +02001386 **************************************************/
Wey-Yi Guy88f10a12012-03-15 13:26:42 -07001387 if (iwlagn_mac_setup_register(priv, &fw->ucode_capa))
Emmanuel Grumbach7d476182010-05-23 00:14:08 -07001388 goto out_destroy_workqueue;
Johannes Berg158bea02010-01-22 14:22:53 -08001389
Meenakshi Venkataraman9da987a2012-07-16 18:43:56 -07001390 if (iwl_dbgfs_register(priv, dbgfs_dir))
1391 goto out_mac80211_unregister;
Emmanuel Grumbache211b242012-02-07 10:35:18 +02001392
Emmanuel Grumbachd0f76d62012-02-09 16:08:15 +02001393 return op_mode;
Zhu Yib481de92007-09-25 17:54:57 -07001394
Meenakshi Venkataraman9da987a2012-07-16 18:43:56 -07001395out_mac80211_unregister:
1396 iwlagn_mac_unregister(priv);
Emmanuel Grumbach34c1b7b2011-07-04 08:58:19 +03001397out_destroy_workqueue:
Meenakshi Venkataraman273a5762012-07-17 13:05:03 -07001398 iwl_tt_exit(priv);
Meenakshi Venkataraman273a5762012-07-17 13:05:03 -07001399 iwl_cancel_deferred_work(priv);
Johannes Berg1ee158d2012-02-17 10:07:44 -08001400 destroy_workqueue(priv->workqueue);
1401 priv->workqueue = NULL;
Tomas Winkler6ba87952008-05-15 13:54:17 +08001402 iwl_uninit_drv(priv);
Johannes Berg26a7ca92012-05-21 11:55:54 +02001403out_free_eeprom_blob:
1404 kfree(priv->eeprom_blob);
Emmanuel Grumbach34c1b7b2011-07-04 08:58:19 +03001405out_free_eeprom:
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001406 iwl_free_nvm_data(priv->nvm_data);
Johannes Berg063c5162012-04-03 16:35:41 -07001407out_free_hw:
Wey-Yi Guyd7c76f42009-10-09 13:20:17 -07001408 ieee80211_free_hw(priv->hw);
Emmanuel Grumbach34c1b7b2011-07-04 08:58:19 +03001409out:
Emmanuel Grumbachd0f76d62012-02-09 16:08:15 +02001410 op_mode = NULL;
1411 return op_mode;
Zhu Yib481de92007-09-25 17:54:57 -07001412}
1413
Johannes Bergaca86262012-05-14 09:08:50 +02001414static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
Zhu Yib481de92007-09-25 17:54:57 -07001415{
Emmanuel Grumbachd0f76d62012-02-09 16:08:15 +02001416 struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
1417
Tomas Winklere1623442009-01-27 14:27:56 -08001418 IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
Zhu Yib481de92007-09-25 17:54:57 -07001419
Don Fry09af1402011-12-09 10:07:38 -08001420 iwlagn_mac_unregister(priv);
Ron Rindjunskyc4f55232008-03-28 16:21:10 -07001421
Wey-Yi Guy39b73fb12009-07-24 11:13:02 -07001422 iwl_tt_exit(priv);
1423
Johannes Berg26a7ca92012-05-21 11:55:54 +02001424 kfree(priv->eeprom_blob);
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001425 iwl_free_nvm_data(priv->nvm_data);
Zhu Yib481de92007-09-25 17:54:57 -07001426
Mohamed Abbas948c1712007-10-25 17:15:45 +08001427 /*netif_stop_queue(dev); */
Johannes Berg1ee158d2012-02-17 10:07:44 -08001428 flush_workqueue(priv->workqueue);
Mohamed Abbas948c1712007-10-25 17:15:45 +08001429
Wey-Yi Guyade4c642011-10-10 07:27:11 -07001430 /* ieee80211_unregister_hw calls iwlagn_mac_stop, which flushes
Johannes Berg1ee158d2012-02-17 10:07:44 -08001431 * priv->workqueue... so we can't take down the workqueue
Zhu Yib481de92007-09-25 17:54:57 -07001432 * until now... */
Johannes Berg1ee158d2012-02-17 10:07:44 -08001433 destroy_workqueue(priv->workqueue);
1434 priv->workqueue = NULL;
Zhu Yib481de92007-09-25 17:54:57 -07001435
Tomas Winkler6ba87952008-05-15 13:54:17 +08001436 iwl_uninit_drv(priv);
Zhu Yib481de92007-09-25 17:54:57 -07001437
Johannes Berg77834542010-10-04 05:50:36 -07001438 dev_kfree_skb(priv->beacon_skb);
Zhu Yib481de92007-09-25 17:54:57 -07001439
Arik Nemtsova4082842013-11-24 19:10:46 +02001440 iwl_trans_op_mode_leave(priv->trans);
Zhu Yib481de92007-09-25 17:54:57 -07001441 ieee80211_free_hw(priv->hw);
1442}
1443
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001444static const char * const desc_lookup_text[] = {
1445 "OK",
1446 "FAIL",
1447 "BAD_PARAM",
1448 "BAD_CHECKSUM",
1449 "NMI_INTERRUPT_WDG",
1450 "SYSASSERT",
1451 "FATAL_ERROR",
1452 "BAD_COMMAND",
1453 "HW_ERROR_TUNE_LOCK",
1454 "HW_ERROR_TEMPERATURE",
1455 "ILLEGAL_CHAN_FREQ",
1456 "VCC_NOT_STABLE",
1457 "FH_ERROR",
1458 "NMI_INTERRUPT_HOST",
1459 "NMI_INTERRUPT_ACTION_PT",
1460 "NMI_INTERRUPT_UNKNOWN",
1461 "UCODE_VERSION_MISMATCH",
1462 "HW_ERROR_ABS_LOCK",
1463 "HW_ERROR_CAL_LOCK_FAIL",
1464 "NMI_INTERRUPT_INST_ACTION_PT",
1465 "NMI_INTERRUPT_DATA_ACTION_PT",
1466 "NMI_TRM_HW_ER",
1467 "NMI_INTERRUPT_TRM",
1468 "NMI_INTERRUPT_BREAK_POINT",
1469 "DEBUG_0",
1470 "DEBUG_1",
1471 "DEBUG_2",
1472 "DEBUG_3",
1473};
1474
1475static struct { char *name; u8 num; } advanced_lookup[] = {
1476 { "NMI_INTERRUPT_WDG", 0x34 },
1477 { "SYSASSERT", 0x35 },
1478 { "UCODE_VERSION_MISMATCH", 0x37 },
1479 { "BAD_COMMAND", 0x38 },
1480 { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C },
1481 { "FATAL_ERROR", 0x3D },
1482 { "NMI_TRM_HW_ERR", 0x46 },
1483 { "NMI_INTERRUPT_TRM", 0x4C },
1484 { "NMI_INTERRUPT_BREAK_POINT", 0x54 },
1485 { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C },
1486 { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 },
1487 { "NMI_INTERRUPT_HOST", 0x66 },
1488 { "NMI_INTERRUPT_ACTION_PT", 0x7C },
1489 { "NMI_INTERRUPT_UNKNOWN", 0x84 },
1490 { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 },
1491 { "ADVANCED_SYSASSERT", 0 },
1492};
1493
1494static const char *desc_lookup(u32 num)
1495{
1496 int i;
1497 int max = ARRAY_SIZE(desc_lookup_text);
1498
1499 if (num < max)
1500 return desc_lookup_text[num];
1501
1502 max = ARRAY_SIZE(advanced_lookup) - 1;
1503 for (i = 0; i < max; i++) {
1504 if (advanced_lookup[i].num == num)
1505 break;
1506 }
1507 return advanced_lookup[i].name;
1508}
1509
1510#define ERROR_START_OFFSET (1 * sizeof(u32))
1511#define ERROR_ELEM_SIZE (7 * sizeof(u32))
1512
1513static void iwl_dump_nic_error_log(struct iwl_priv *priv)
1514{
Emmanuel Grumbach68e8dfd2012-04-18 07:28:17 -07001515 struct iwl_trans *trans = priv->trans;
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001516 u32 base;
1517 struct iwl_error_event_table table;
1518
1519 base = priv->device_pointers.error_event_table;
Meenakshi Venkataramana42506e2012-03-15 13:26:57 -07001520 if (priv->cur_ucode == IWL_UCODE_INIT) {
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001521 if (!base)
Meenakshi Venkataramane3ec26d2012-03-15 13:27:04 -07001522 base = priv->fw->init_errlog_ptr;
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001523 } else {
1524 if (!base)
Meenakshi Venkataramane3ec26d2012-03-15 13:27:04 -07001525 base = priv->fw->inst_errlog_ptr;
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001526 }
1527
1528 if (!iwlagn_hw_valid_rtc_data_addr(base)) {
1529 IWL_ERR(priv,
1530 "Not valid error log pointer 0x%08X for %s uCode\n",
1531 base,
Meenakshi Venkataramana42506e2012-03-15 13:26:57 -07001532 (priv->cur_ucode == IWL_UCODE_INIT)
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001533 ? "Init" : "RT");
1534 return;
1535 }
1536
1537 /*TODO: Update dbgfs with ISR error stats obtained below */
Emmanuel Grumbach4fd442d2012-12-24 14:27:11 +02001538 iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001539
1540 if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
1541 IWL_ERR(trans, "Start IWL Error Log Dump:\n");
1542 IWL_ERR(trans, "Status: 0x%08lX, count: %d\n",
Don Fry74fda972012-03-20 16:36:54 -07001543 priv->status, table.valid);
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001544 }
1545
1546 trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low,
1547 table.data1, table.data2, table.line,
1548 table.blink1, table.blink2, table.ilink1,
1549 table.ilink2, table.bcon_time, table.gp1,
1550 table.gp2, table.gp3, table.ucode_ver,
1551 table.hw_ver, table.brd_ver);
1552 IWL_ERR(priv, "0x%08X | %-28s\n", table.error_id,
1553 desc_lookup(table.error_id));
1554 IWL_ERR(priv, "0x%08X | uPc\n", table.pc);
1555 IWL_ERR(priv, "0x%08X | branchlink1\n", table.blink1);
1556 IWL_ERR(priv, "0x%08X | branchlink2\n", table.blink2);
1557 IWL_ERR(priv, "0x%08X | interruptlink1\n", table.ilink1);
1558 IWL_ERR(priv, "0x%08X | interruptlink2\n", table.ilink2);
1559 IWL_ERR(priv, "0x%08X | data1\n", table.data1);
1560 IWL_ERR(priv, "0x%08X | data2\n", table.data2);
1561 IWL_ERR(priv, "0x%08X | line\n", table.line);
1562 IWL_ERR(priv, "0x%08X | beacon time\n", table.bcon_time);
1563 IWL_ERR(priv, "0x%08X | tsf low\n", table.tsf_low);
1564 IWL_ERR(priv, "0x%08X | tsf hi\n", table.tsf_hi);
1565 IWL_ERR(priv, "0x%08X | time gp1\n", table.gp1);
1566 IWL_ERR(priv, "0x%08X | time gp2\n", table.gp2);
1567 IWL_ERR(priv, "0x%08X | time gp3\n", table.gp3);
1568 IWL_ERR(priv, "0x%08X | uCode version\n", table.ucode_ver);
1569 IWL_ERR(priv, "0x%08X | hw version\n", table.hw_ver);
1570 IWL_ERR(priv, "0x%08X | board version\n", table.brd_ver);
1571 IWL_ERR(priv, "0x%08X | hcmd\n", table.hcmd);
1572 IWL_ERR(priv, "0x%08X | isr0\n", table.isr0);
1573 IWL_ERR(priv, "0x%08X | isr1\n", table.isr1);
1574 IWL_ERR(priv, "0x%08X | isr2\n", table.isr2);
1575 IWL_ERR(priv, "0x%08X | isr3\n", table.isr3);
1576 IWL_ERR(priv, "0x%08X | isr4\n", table.isr4);
1577 IWL_ERR(priv, "0x%08X | isr_pref\n", table.isr_pref);
1578 IWL_ERR(priv, "0x%08X | wait_event\n", table.wait_event);
1579 IWL_ERR(priv, "0x%08X | l2p_control\n", table.l2p_control);
1580 IWL_ERR(priv, "0x%08X | l2p_duration\n", table.l2p_duration);
1581 IWL_ERR(priv, "0x%08X | l2p_mhvalid\n", table.l2p_mhvalid);
1582 IWL_ERR(priv, "0x%08X | l2p_addr_match\n", table.l2p_addr_match);
1583 IWL_ERR(priv, "0x%08X | lmpm_pmg_sel\n", table.lmpm_pmg_sel);
1584 IWL_ERR(priv, "0x%08X | timestamp\n", table.u_timestamp);
1585 IWL_ERR(priv, "0x%08X | flow_handler\n", table.flow_handler);
1586}
1587
1588#define EVENT_START_OFFSET (4 * sizeof(u32))
1589
1590/**
1591 * iwl_print_event_log - Dump error event log to syslog
1592 *
1593 */
1594static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
1595 u32 num_events, u32 mode,
1596 int pos, char **buf, size_t bufsz)
1597{
1598 u32 i;
1599 u32 base; /* SRAM byte address of event log header */
1600 u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
1601 u32 ptr; /* SRAM byte address of log data */
1602 u32 ev, time, data; /* event log data */
1603 unsigned long reg_flags;
1604
Emmanuel Grumbach68e8dfd2012-04-18 07:28:17 -07001605 struct iwl_trans *trans = priv->trans;
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001606
1607 if (num_events == 0)
1608 return pos;
1609
1610 base = priv->device_pointers.log_event_table;
Meenakshi Venkataramana42506e2012-03-15 13:26:57 -07001611 if (priv->cur_ucode == IWL_UCODE_INIT) {
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001612 if (!base)
Meenakshi Venkataramane3ec26d2012-03-15 13:27:04 -07001613 base = priv->fw->init_evtlog_ptr;
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001614 } else {
1615 if (!base)
Meenakshi Venkataramane3ec26d2012-03-15 13:27:04 -07001616 base = priv->fw->inst_evtlog_ptr;
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001617 }
1618
1619 if (mode == 0)
1620 event_size = 2 * sizeof(u32);
1621 else
1622 event_size = 3 * sizeof(u32);
1623
1624 ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
1625
1626 /* Make sure device is powered up for SRAM reads */
Lilach Edelsteine56b04e2013-01-16 11:34:49 +02001627 if (!iwl_trans_grab_nic_access(trans, false, &reg_flags))
1628 return pos;
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001629
1630 /* Set starting address; reads will auto-increment */
1631 iwl_write32(trans, HBUS_TARG_MEM_RADDR, ptr);
1632
1633 /* "time" is actually "data" for mode 0 (no timestamp).
1634 * place event id # at far right for easier visual parsing. */
1635 for (i = 0; i < num_events; i++) {
1636 ev = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
1637 time = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
1638 if (mode == 0) {
1639 /* data, ev */
1640 if (bufsz) {
1641 pos += scnprintf(*buf + pos, bufsz - pos,
1642 "EVT_LOG:0x%08x:%04u\n",
1643 time, ev);
1644 } else {
1645 trace_iwlwifi_dev_ucode_event(trans->dev, 0,
1646 time, ev);
1647 IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n",
1648 time, ev);
1649 }
1650 } else {
1651 data = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
1652 if (bufsz) {
1653 pos += scnprintf(*buf + pos, bufsz - pos,
1654 "EVT_LOGT:%010u:0x%08x:%04u\n",
1655 time, data, ev);
1656 } else {
1657 IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
1658 time, data, ev);
1659 trace_iwlwifi_dev_ucode_event(trans->dev, time,
1660 data, ev);
1661 }
1662 }
1663 }
1664
1665 /* Allow device to power down */
Lilach Edelsteine56b04e2013-01-16 11:34:49 +02001666 iwl_trans_release_nic_access(trans, &reg_flags);
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001667 return pos;
1668}
1669
1670/**
1671 * iwl_print_last_event_logs - Dump the newest # of event log to syslog
1672 */
1673static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
1674 u32 num_wraps, u32 next_entry,
1675 u32 size, u32 mode,
1676 int pos, char **buf, size_t bufsz)
1677{
1678 /*
1679 * display the newest DEFAULT_LOG_ENTRIES entries
1680 * i.e the entries just before the next ont that uCode would fill.
1681 */
1682 if (num_wraps) {
1683 if (next_entry < size) {
1684 pos = iwl_print_event_log(priv,
1685 capacity - (size - next_entry),
1686 size - next_entry, mode,
1687 pos, buf, bufsz);
1688 pos = iwl_print_event_log(priv, 0,
1689 next_entry, mode,
1690 pos, buf, bufsz);
1691 } else
1692 pos = iwl_print_event_log(priv, next_entry - size,
1693 size, mode, pos, buf, bufsz);
1694 } else {
1695 if (next_entry < size) {
1696 pos = iwl_print_event_log(priv, 0, next_entry,
1697 mode, pos, buf, bufsz);
1698 } else {
1699 pos = iwl_print_event_log(priv, next_entry - size,
1700 size, mode, pos, buf, bufsz);
1701 }
1702 }
1703 return pos;
1704}
1705
1706#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20)
1707
1708int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
Stanislaw Gruszkaa6db0062013-04-16 15:40:54 +02001709 char **buf)
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001710{
1711 u32 base; /* SRAM byte address of event log header */
1712 u32 capacity; /* event log capacity in # entries */
1713 u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
1714 u32 num_wraps; /* # times uCode wrapped to top of log */
1715 u32 next_entry; /* index of next entry to be written by uCode */
1716 u32 size; /* # entries that we'll print */
1717 u32 logsize;
1718 int pos = 0;
1719 size_t bufsz = 0;
Emmanuel Grumbach68e8dfd2012-04-18 07:28:17 -07001720 struct iwl_trans *trans = priv->trans;
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001721
1722 base = priv->device_pointers.log_event_table;
Meenakshi Venkataramana42506e2012-03-15 13:26:57 -07001723 if (priv->cur_ucode == IWL_UCODE_INIT) {
Meenakshi Venkataramane3ec26d2012-03-15 13:27:04 -07001724 logsize = priv->fw->init_evtlog_size;
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001725 if (!base)
Meenakshi Venkataramane3ec26d2012-03-15 13:27:04 -07001726 base = priv->fw->init_evtlog_ptr;
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001727 } else {
Meenakshi Venkataramane3ec26d2012-03-15 13:27:04 -07001728 logsize = priv->fw->inst_evtlog_size;
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001729 if (!base)
Meenakshi Venkataramane3ec26d2012-03-15 13:27:04 -07001730 base = priv->fw->inst_evtlog_ptr;
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001731 }
1732
1733 if (!iwlagn_hw_valid_rtc_data_addr(base)) {
1734 IWL_ERR(priv,
1735 "Invalid event log pointer 0x%08X for %s uCode\n",
1736 base,
Meenakshi Venkataramana42506e2012-03-15 13:26:57 -07001737 (priv->cur_ucode == IWL_UCODE_INIT)
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001738 ? "Init" : "RT");
1739 return -EINVAL;
1740 }
1741
1742 /* event log header */
Emmanuel Grumbach4fd442d2012-12-24 14:27:11 +02001743 capacity = iwl_trans_read_mem32(trans, base);
1744 mode = iwl_trans_read_mem32(trans, base + (1 * sizeof(u32)));
1745 num_wraps = iwl_trans_read_mem32(trans, base + (2 * sizeof(u32)));
1746 next_entry = iwl_trans_read_mem32(trans, base + (3 * sizeof(u32)));
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001747
1748 if (capacity > logsize) {
1749 IWL_ERR(priv, "Log capacity %d is bogus, limit to %d "
1750 "entries\n", capacity, logsize);
1751 capacity = logsize;
1752 }
1753
1754 if (next_entry > logsize) {
1755 IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
1756 next_entry, logsize);
1757 next_entry = logsize;
1758 }
1759
1760 size = num_wraps ? capacity : next_entry;
1761
1762 /* bail out if nothing in log */
1763 if (size == 0) {
1764 IWL_ERR(trans, "Start IWL Event Log Dump: nothing in log\n");
1765 return pos;
1766 }
1767
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001768 if (!(iwl_have_debug_level(IWL_DL_FW_ERRORS)) && !full_log)
1769 size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
1770 ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001771 IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n",
1772 size);
1773
1774#ifdef CONFIG_IWLWIFI_DEBUG
Stanislaw Gruszkaa6db0062013-04-16 15:40:54 +02001775 if (buf) {
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001776 if (full_log)
1777 bufsz = capacity * 48;
1778 else
1779 bufsz = size * 48;
1780 *buf = kmalloc(bufsz, GFP_KERNEL);
1781 if (!*buf)
1782 return -ENOMEM;
1783 }
1784 if (iwl_have_debug_level(IWL_DL_FW_ERRORS) || full_log) {
1785 /*
1786 * if uCode has wrapped back to top of log,
1787 * start at the oldest entry,
1788 * i.e the next one that uCode would fill.
1789 */
1790 if (num_wraps)
1791 pos = iwl_print_event_log(priv, next_entry,
1792 capacity - next_entry, mode,
1793 pos, buf, bufsz);
1794 /* (then/else) start at top of log */
1795 pos = iwl_print_event_log(priv, 0,
1796 next_entry, mode, pos, buf, bufsz);
1797 } else
1798 pos = iwl_print_last_event_logs(priv, capacity, num_wraps,
1799 next_entry, size, mode,
1800 pos, buf, bufsz);
1801#else
1802 pos = iwl_print_last_event_logs(priv, capacity, num_wraps,
1803 next_entry, size, mode,
1804 pos, buf, bufsz);
1805#endif
1806 return pos;
1807}
1808
Meenakshi Venkataraman193219c2012-03-13 18:00:15 -07001809static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
1810{
1811 unsigned int reload_msec;
1812 unsigned long reload_jiffies;
1813
Meenakshi Venkataraman193219c2012-03-13 18:00:15 -07001814 if (iwl_have_debug_level(IWL_DL_FW_ERRORS))
1815 iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS);
Meenakshi Venkataraman193219c2012-03-13 18:00:15 -07001816
1817 /* uCode is no longer loaded. */
1818 priv->ucode_loaded = false;
1819
1820 /* Set the FW error flag -- cleared on iwl_down */
1821 set_bit(STATUS_FW_ERROR, &priv->status);
1822
Meenakshi Venkataraman193219c2012-03-13 18:00:15 -07001823 iwl_abort_notification_waits(&priv->notif_wait);
1824
1825 /* Keep the restart process from trying to send host
1826 * commands by clearing the ready bit */
1827 clear_bit(STATUS_READY, &priv->status);
1828
Meenakshi Venkataraman193219c2012-03-13 18:00:15 -07001829 if (!ondemand) {
1830 /*
1831 * If firmware keep reloading, then it indicate something
1832 * serious wrong and firmware having problem to recover
1833 * from it. Instead of keep trying which will fill the syslog
1834 * and hang the system, let's just stop it
1835 */
1836 reload_jiffies = jiffies;
1837 reload_msec = jiffies_to_msecs((long) reload_jiffies -
1838 (long) priv->reload_jiffies);
1839 priv->reload_jiffies = reload_jiffies;
1840 if (reload_msec <= IWL_MIN_RELOAD_DURATION) {
1841 priv->reload_count++;
1842 if (priv->reload_count >= IWL_MAX_CONTINUE_RELOAD_CNT) {
1843 IWL_ERR(priv, "BUG_ON, Stop restarting\n");
1844 return;
1845 }
1846 } else
1847 priv->reload_count = 0;
1848 }
1849
1850 if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
Johannes Berg65de7e82012-04-17 07:36:30 -07001851 if (iwlwifi_mod_params.restart_fw) {
Meenakshi Venkataraman193219c2012-03-13 18:00:15 -07001852 IWL_DEBUG_FW_ERRORS(priv,
1853 "Restarting adapter due to uCode error.\n");
1854 queue_work(priv->workqueue, &priv->restart);
1855 } else
1856 IWL_DEBUG_FW_ERRORS(priv,
1857 "Detected FW error, but not restarting\n");
1858 }
1859}
1860
Johannes Bergaca86262012-05-14 09:08:50 +02001861static void iwl_nic_error(struct iwl_op_mode *op_mode)
Meenakshi Venkataraman19469f42012-03-15 13:26:55 -07001862{
1863 struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
1864
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001865 IWL_ERR(priv, "Loaded firmware version: %s\n",
Meenakshi Venkataramane3ec26d2012-03-15 13:27:04 -07001866 priv->fw->fw_version);
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001867
1868 iwl_dump_nic_error_log(priv);
Stanislaw Gruszkaa6db0062013-04-16 15:40:54 +02001869 iwl_dump_nic_event_log(priv, false, NULL);
Meenakshi Venkataraman2fdfc472012-03-15 13:26:56 -07001870
Meenakshi Venkataraman19469f42012-03-15 13:26:55 -07001871 iwlagn_fw_error(priv, false);
1872}
1873
Johannes Bergaca86262012-05-14 09:08:50 +02001874static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode)
Johannes Berg0e781842012-03-06 13:30:49 -08001875{
1876 struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
1877
1878 if (!iwl_check_for_ct_kill(priv)) {
1879 IWL_ERR(priv, "Restarting adapter queue is full\n");
Meenakshi Venkataramanb7e21bf2012-03-15 13:26:54 -07001880 iwlagn_fw_error(priv, false);
Johannes Berg0e781842012-03-06 13:30:49 -08001881 }
1882}
1883
Johannes Berg1280d422012-05-30 12:36:23 +02001884#define EEPROM_RF_CONFIG_TYPE_MAX 0x3
1885
Johannes Bergaca86262012-05-14 09:08:50 +02001886static void iwl_nic_config(struct iwl_op_mode *op_mode)
Johannes Bergecdb9752012-03-06 13:31:03 -08001887{
1888 struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
1889
Emmanuel Grumbach08838cd2012-05-29 17:48:08 +03001890 /* SKU Control */
Lilach Edelsteine139dc42013-01-13 13:31:10 +02001891 iwl_trans_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
1892 CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
1893 CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP,
1894 (CSR_HW_REV_STEP(priv->trans->hw_rev) <<
1895 CSR_HW_IF_CONFIG_REG_POS_MAC_STEP) |
1896 (CSR_HW_REV_DASH(priv->trans->hw_rev) <<
1897 CSR_HW_IF_CONFIG_REG_POS_MAC_DASH));
Emmanuel Grumbach08838cd2012-05-29 17:48:08 +03001898
Johannes Berg1280d422012-05-30 12:36:23 +02001899 /* write radio config values to register */
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001900 if (priv->nvm_data->radio_cfg_type <= EEPROM_RF_CONFIG_TYPE_MAX) {
Johannes Berg1280d422012-05-30 12:36:23 +02001901 u32 reg_val =
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001902 priv->nvm_data->radio_cfg_type <<
Johannes Berg1280d422012-05-30 12:36:23 +02001903 CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE |
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001904 priv->nvm_data->radio_cfg_step <<
Johannes Berg1280d422012-05-30 12:36:23 +02001905 CSR_HW_IF_CONFIG_REG_POS_PHY_STEP |
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001906 priv->nvm_data->radio_cfg_dash <<
Johannes Berg1280d422012-05-30 12:36:23 +02001907 CSR_HW_IF_CONFIG_REG_POS_PHY_DASH;
1908
Lilach Edelsteine139dc42013-01-13 13:31:10 +02001909 iwl_trans_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
1910 CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE |
1911 CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP |
1912 CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH,
1913 reg_val);
Johannes Berg1280d422012-05-30 12:36:23 +02001914
1915 IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n",
Eytan Lifshitzb7998c82012-12-01 20:59:49 +02001916 priv->nvm_data->radio_cfg_type,
1917 priv->nvm_data->radio_cfg_step,
1918 priv->nvm_data->radio_cfg_dash);
Johannes Berg1280d422012-05-30 12:36:23 +02001919 } else {
1920 WARN_ON(1);
1921 }
1922
1923 /* set CSR_HW_CONFIG_REG for uCode use */
1924 iwl_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG,
1925 CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
1926 CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
1927
Emmanuel Grumbachdada03c2012-06-17 15:42:37 +03001928 /* W/A : NIC is stuck in a reset state after Early PCIe power off
1929 * (PCIe power is lost before PERST# is asserted),
1930 * causing ME FW to lose ownership and not being able to obtain it back.
1931 */
1932 iwl_set_bits_mask_prph(priv->trans, APMG_PS_CTRL_REG,
1933 APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
1934 ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
1935
1936 if (priv->lib->nic_config)
1937 priv->lib->nic_config(priv);
Johannes Bergecdb9752012-03-06 13:31:03 -08001938}
1939
Don Fry8a8bbdb2012-03-20 10:33:34 -07001940static void iwl_wimax_active(struct iwl_op_mode *op_mode)
1941{
1942 struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
1943
1944 clear_bit(STATUS_READY, &priv->status);
1945 IWL_ERR(priv, "RF is used by WiMAX\n");
1946}
1947
Johannes Bergaca86262012-05-14 09:08:50 +02001948static void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue)
Johannes Berge755f882012-03-07 09:52:16 -08001949{
1950 struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
Johannes Berg14791772012-04-17 07:39:03 -07001951 int mq = priv->queue_to_mac80211[queue];
Johannes Berg9eae88f2012-03-15 13:26:52 -07001952
Johannes Berg14791772012-04-17 07:39:03 -07001953 if (WARN_ON_ONCE(mq == IWL_INVALID_MAC80211_QUEUE))
Johannes Berg9eae88f2012-03-15 13:26:52 -07001954 return;
1955
Johannes Berg14791772012-04-17 07:39:03 -07001956 if (atomic_inc_return(&priv->queue_stop_count[mq]) > 1) {
Johannes Berg9eae88f2012-03-15 13:26:52 -07001957 IWL_DEBUG_TX_QUEUES(priv,
Johannes Berg14791772012-04-17 07:39:03 -07001958 "queue %d (mac80211 %d) already stopped\n",
1959 queue, mq);
Johannes Berg9eae88f2012-03-15 13:26:52 -07001960 return;
1961 }
Johannes Berge755f882012-03-07 09:52:16 -08001962
Johannes Berg14791772012-04-17 07:39:03 -07001963 set_bit(mq, &priv->transport_queue_stop);
1964 ieee80211_stop_queue(priv->hw, mq);
Johannes Berge755f882012-03-07 09:52:16 -08001965}
1966
Johannes Bergaca86262012-05-14 09:08:50 +02001967static void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue)
Johannes Berge755f882012-03-07 09:52:16 -08001968{
1969 struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
Johannes Berg14791772012-04-17 07:39:03 -07001970 int mq = priv->queue_to_mac80211[queue];
Johannes Berg9eae88f2012-03-15 13:26:52 -07001971
Johannes Berg14791772012-04-17 07:39:03 -07001972 if (WARN_ON_ONCE(mq == IWL_INVALID_MAC80211_QUEUE))
Johannes Berg9eae88f2012-03-15 13:26:52 -07001973 return;
1974
Johannes Berg14791772012-04-17 07:39:03 -07001975 if (atomic_dec_return(&priv->queue_stop_count[mq]) > 0) {
Johannes Berg9eae88f2012-03-15 13:26:52 -07001976 IWL_DEBUG_TX_QUEUES(priv,
Johannes Berg14791772012-04-17 07:39:03 -07001977 "queue %d (mac80211 %d) already awake\n",
1978 queue, mq);
Johannes Berg9eae88f2012-03-15 13:26:52 -07001979 return;
1980 }
Johannes Berge755f882012-03-07 09:52:16 -08001981
Johannes Berg14791772012-04-17 07:39:03 -07001982 clear_bit(mq, &priv->transport_queue_stop);
Johannes Berge755f882012-03-07 09:52:16 -08001983
1984 if (!priv->passive_no_rx)
Johannes Berg14791772012-04-17 07:39:03 -07001985 ieee80211_wake_queue(priv->hw, mq);
Johannes Berge755f882012-03-07 09:52:16 -08001986}
1987
1988void iwlagn_lift_passive_no_rx(struct iwl_priv *priv)
1989{
Johannes Berg14791772012-04-17 07:39:03 -07001990 int mq;
Johannes Berge755f882012-03-07 09:52:16 -08001991
1992 if (!priv->passive_no_rx)
1993 return;
1994
Johannes Berg14791772012-04-17 07:39:03 -07001995 for (mq = 0; mq < IWLAGN_FIRST_AMPDU_QUEUE; mq++) {
1996 if (!test_bit(mq, &priv->transport_queue_stop)) {
Johannes Berg3c6acb62014-05-07 11:47:53 +02001997 IWL_DEBUG_TX_QUEUES(priv, "Wake queue %d\n", mq);
Johannes Berg14791772012-04-17 07:39:03 -07001998 ieee80211_wake_queue(priv->hw, mq);
Emmanuel Grumbach32517152012-03-07 09:52:34 -08001999 } else {
Johannes Berg3c6acb62014-05-07 11:47:53 +02002000 IWL_DEBUG_TX_QUEUES(priv, "Don't wake queue %d\n", mq);
Emmanuel Grumbach32517152012-03-07 09:52:34 -08002001 }
Johannes Berge755f882012-03-07 09:52:16 -08002002 }
2003
2004 priv->passive_no_rx = false;
2005}
2006
Johannes Bergaca86262012-05-14 09:08:50 +02002007static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
Meenakshi Venkataramanae625db2012-03-13 15:24:44 -07002008{
Emmanuel Grumbach59c647b2012-05-24 19:24:34 +03002009 struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
Meenakshi Venkataramanae625db2012-03-13 15:24:44 -07002010 struct ieee80211_tx_info *info;
2011
2012 info = IEEE80211_SKB_CB(skb);
Emmanuel Grumbach59c647b2012-05-24 19:24:34 +03002013 iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]);
Johannes Berg31df3bb2012-10-31 22:07:39 +01002014 ieee80211_free_txskb(priv->hw, skb);
Meenakshi Venkataramanae625db2012-03-13 15:24:44 -07002015}
2016
Johannes Berg14cfca72014-02-25 20:50:53 +01002017static bool iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
Meenakshi Venkataramana297d952012-03-13 15:33:18 -07002018{
2019 struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
2020
2021 if (state)
2022 set_bit(STATUS_RF_KILL_HW, &priv->status);
2023 else
2024 clear_bit(STATUS_RF_KILL_HW, &priv->status);
2025
2026 wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
Johannes Berg14cfca72014-02-25 20:50:53 +01002027
2028 return false;
Meenakshi Venkataramana297d952012-03-13 15:33:18 -07002029}
2030
Johannes Bergf14d6b32014-03-21 13:30:03 +01002031static void iwl_napi_add(struct iwl_op_mode *op_mode,
2032 struct napi_struct *napi,
2033 struct net_device *napi_dev,
2034 int (*poll)(struct napi_struct *, int),
2035 int weight)
2036{
2037 struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
2038
2039 ieee80211_napi_add(priv->hw, napi, napi_dev, poll, weight);
2040}
2041
Johannes Bergb1abeda2012-05-31 13:54:56 +02002042static const struct iwl_op_mode_ops iwl_dvm_ops = {
Emmanuel Grumbachd0f76d62012-02-09 16:08:15 +02002043 .start = iwl_op_mode_dvm_start,
2044 .stop = iwl_op_mode_dvm_stop,
Emmanuel Grumbachdb70f292012-02-09 16:08:15 +02002045 .rx = iwl_rx_dispatch,
Emmanuel Grumbach02e38352012-02-09 16:08:15 +02002046 .queue_full = iwl_stop_sw_queue,
2047 .queue_not_full = iwl_wake_sw_queue,
Emmanuel Grumbach7120d982012-02-09 16:08:15 +02002048 .hw_rf_kill = iwl_set_hw_rfkill_state,
Emmanuel Grumbached277c92012-02-09 16:08:15 +02002049 .free_skb = iwl_free_skb,
Emmanuel Grumbachbcb93212012-02-09 16:08:15 +02002050 .nic_error = iwl_nic_error,
Johannes Berg0e781842012-03-06 13:30:49 -08002051 .cmd_queue_full = iwl_cmd_queue_full,
Johannes Bergecdb9752012-03-06 13:31:03 -08002052 .nic_config = iwl_nic_config,
Don Fry8a8bbdb2012-03-20 10:33:34 -07002053 .wimax_active = iwl_wimax_active,
Johannes Bergf14d6b32014-03-21 13:30:03 +01002054 .napi_add = iwl_napi_add,
Emmanuel Grumbachd0f76d62012-02-09 16:08:15 +02002055};
Zhu Yib481de92007-09-25 17:54:57 -07002056
2057/*****************************************************************************
2058 *
2059 * driver and module entry point
2060 *
2061 *****************************************************************************/
Emmanuel Grumbach5b9f8cd2008-10-29 14:05:46 -07002062static int __init iwl_init(void)
Zhu Yib481de92007-09-25 17:54:57 -07002063{
2064
2065 int ret;
Reinette Chatre897e1cf2008-03-28 16:21:09 -07002066
Tomas Winklere227cea2008-07-18 13:53:05 +08002067 ret = iwlagn_rate_control_register();
Reinette Chatre897e1cf2008-03-28 16:21:09 -07002068 if (ret) {
Joe Perchesc96c31e2010-07-26 14:39:58 -07002069 pr_err("Unable to register rate control algorithm: %d\n", ret);
Emmanuel Grumbach59c647b2012-05-24 19:24:34 +03002070 return ret;
Reinette Chatre897e1cf2008-03-28 16:21:09 -07002071 }
2072
Don Frycc5f7e32012-05-16 22:54:27 +02002073 ret = iwl_opmode_register("iwldvm", &iwl_dvm_ops);
2074 if (ret) {
2075 pr_err("Unable to register op_mode: %d\n", ret);
Emmanuel Grumbach59c647b2012-05-24 19:24:34 +03002076 iwlagn_rate_control_unregister();
Don Frycc5f7e32012-05-16 22:54:27 +02002077 }
Reinette Chatre897e1cf2008-03-28 16:21:09 -07002078
Reinette Chatre897e1cf2008-03-28 16:21:09 -07002079 return ret;
Zhu Yib481de92007-09-25 17:54:57 -07002080}
Don Frycc5f7e32012-05-16 22:54:27 +02002081module_init(iwl_init);
Zhu Yib481de92007-09-25 17:54:57 -07002082
Emmanuel Grumbach5b9f8cd2008-10-29 14:05:46 -07002083static void __exit iwl_exit(void)
Zhu Yib481de92007-09-25 17:54:57 -07002084{
Don Frycc5f7e32012-05-16 22:54:27 +02002085 iwl_opmode_deregister("iwldvm");
Tomas Winklere227cea2008-07-18 13:53:05 +08002086 iwlagn_rate_control_unregister();
Zhu Yib481de92007-09-25 17:54:57 -07002087}
Emmanuel Grumbach5b9f8cd2008-10-29 14:05:46 -07002088module_exit(iwl_exit);