14273a380SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2e705c121SKalle Valo /******************************************************************************
3e705c121SKalle Valo *
46e8912a5SShaul Triebitz * Copyright(c) 2003 - 2014, 2018 - 2022 Intel Corporation. All rights reserved.
5b476564bSEmmanuel Grumbach * Copyright(c) 2024 Intel Corporation. All rights reserved.
639bdb17eSSharon Dvir * Copyright(c) 2015 Intel Deutschland GmbH
7e705c121SKalle Valo *
8e705c121SKalle Valo * Portions of this file are derived from the ipw3945 project, as well
9e705c121SKalle Valo * as portions of the ieee80211 subsystem header files.
10e705c121SKalle Valo *****************************************************************************/
11e705c121SKalle Valo
12e705c121SKalle Valo #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13e705c121SKalle Valo
14e705c121SKalle Valo #include <linux/kernel.h>
15e705c121SKalle Valo #include <linux/module.h>
16e705c121SKalle Valo #include <linux/init.h>
17e705c121SKalle Valo #include <linux/slab.h>
18e705c121SKalle Valo #include <linux/delay.h>
19e705c121SKalle Valo #include <linux/sched.h>
20e705c121SKalle Valo #include <linux/skbuff.h>
21e705c121SKalle Valo #include <linux/netdevice.h>
22e705c121SKalle Valo #include <linux/etherdevice.h>
23e705c121SKalle Valo #include <linux/if_arp.h>
24e705c121SKalle Valo
25e705c121SKalle Valo #include <net/mac80211.h>
26e705c121SKalle Valo
27e705c121SKalle Valo #include <asm/div64.h>
28e705c121SKalle Valo
29*6584b9d0SEmmanuel Grumbach #include "iwl-nvm-utils.h"
30e705c121SKalle Valo #include "iwl-io.h"
31e705c121SKalle Valo #include "iwl-trans.h"
32e705c121SKalle Valo #include "iwl-op-mode.h"
33e705c121SKalle Valo #include "iwl-drv.h"
34e705c121SKalle Valo #include "iwl-modparams.h"
35e705c121SKalle Valo #include "iwl-prph.h"
36e705c121SKalle Valo
37e705c121SKalle Valo #include "dev.h"
38e705c121SKalle Valo #include "calib.h"
39e705c121SKalle Valo #include "agn.h"
40e705c121SKalle Valo
41e705c121SKalle Valo
42e705c121SKalle Valo /******************************************************************************
43e705c121SKalle Valo *
44e705c121SKalle Valo * module boiler plate
45e705c121SKalle Valo *
46e705c121SKalle Valo ******************************************************************************/
47e705c121SKalle Valo
48e705c121SKalle Valo #define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link AGN driver for Linux"
49e705c121SKalle Valo MODULE_DESCRIPTION(DRV_DESCRIPTION);
50e705c121SKalle Valo MODULE_LICENSE("GPL");
51872f6bb0SJohannes Berg MODULE_IMPORT_NS(IWLWIFI);
52e705c121SKalle Valo
5339bdb17eSSharon Dvir /* Please keep this array *SORTED* by hex value.
5439bdb17eSSharon Dvir * Access is done through binary search.
5539bdb17eSSharon Dvir * A warning will be triggered on violation.
5639bdb17eSSharon Dvir */
5739bdb17eSSharon Dvir static const struct iwl_hcmd_names iwl_dvm_cmd_names[] = {
5839bdb17eSSharon Dvir HCMD_NAME(REPLY_ALIVE),
5939bdb17eSSharon Dvir HCMD_NAME(REPLY_ERROR),
6039bdb17eSSharon Dvir HCMD_NAME(REPLY_ECHO),
6139bdb17eSSharon Dvir HCMD_NAME(REPLY_RXON),
6239bdb17eSSharon Dvir HCMD_NAME(REPLY_RXON_ASSOC),
6339bdb17eSSharon Dvir HCMD_NAME(REPLY_QOS_PARAM),
6439bdb17eSSharon Dvir HCMD_NAME(REPLY_RXON_TIMING),
6539bdb17eSSharon Dvir HCMD_NAME(REPLY_ADD_STA),
6639bdb17eSSharon Dvir HCMD_NAME(REPLY_REMOVE_STA),
6739bdb17eSSharon Dvir HCMD_NAME(REPLY_REMOVE_ALL_STA),
6839bdb17eSSharon Dvir HCMD_NAME(REPLY_TX),
6939bdb17eSSharon Dvir HCMD_NAME(REPLY_TXFIFO_FLUSH),
7039bdb17eSSharon Dvir HCMD_NAME(REPLY_WEPKEY),
7139bdb17eSSharon Dvir HCMD_NAME(REPLY_LEDS_CMD),
7239bdb17eSSharon Dvir HCMD_NAME(REPLY_TX_LINK_QUALITY_CMD),
7339bdb17eSSharon Dvir HCMD_NAME(COEX_PRIORITY_TABLE_CMD),
7439bdb17eSSharon Dvir HCMD_NAME(COEX_MEDIUM_NOTIFICATION),
7539bdb17eSSharon Dvir HCMD_NAME(COEX_EVENT_CMD),
7639bdb17eSSharon Dvir HCMD_NAME(TEMPERATURE_NOTIFICATION),
7739bdb17eSSharon Dvir HCMD_NAME(CALIBRATION_CFG_CMD),
7839bdb17eSSharon Dvir HCMD_NAME(CALIBRATION_RES_NOTIFICATION),
7939bdb17eSSharon Dvir HCMD_NAME(CALIBRATION_COMPLETE_NOTIFICATION),
8039bdb17eSSharon Dvir HCMD_NAME(REPLY_QUIET_CMD),
8139bdb17eSSharon Dvir HCMD_NAME(REPLY_CHANNEL_SWITCH),
8239bdb17eSSharon Dvir HCMD_NAME(CHANNEL_SWITCH_NOTIFICATION),
8339bdb17eSSharon Dvir HCMD_NAME(REPLY_SPECTRUM_MEASUREMENT_CMD),
8439bdb17eSSharon Dvir HCMD_NAME(SPECTRUM_MEASURE_NOTIFICATION),
8539bdb17eSSharon Dvir HCMD_NAME(POWER_TABLE_CMD),
8639bdb17eSSharon Dvir HCMD_NAME(PM_SLEEP_NOTIFICATION),
8739bdb17eSSharon Dvir HCMD_NAME(PM_DEBUG_STATISTIC_NOTIFIC),
8839bdb17eSSharon Dvir HCMD_NAME(REPLY_SCAN_CMD),
8939bdb17eSSharon Dvir HCMD_NAME(REPLY_SCAN_ABORT_CMD),
9039bdb17eSSharon Dvir HCMD_NAME(SCAN_START_NOTIFICATION),
9139bdb17eSSharon Dvir HCMD_NAME(SCAN_RESULTS_NOTIFICATION),
9239bdb17eSSharon Dvir HCMD_NAME(SCAN_COMPLETE_NOTIFICATION),
9339bdb17eSSharon Dvir HCMD_NAME(BEACON_NOTIFICATION),
9439bdb17eSSharon Dvir HCMD_NAME(REPLY_TX_BEACON),
9539bdb17eSSharon Dvir HCMD_NAME(WHO_IS_AWAKE_NOTIFICATION),
9639bdb17eSSharon Dvir HCMD_NAME(REPLY_TX_POWER_DBM_CMD),
9739bdb17eSSharon Dvir HCMD_NAME(QUIET_NOTIFICATION),
9839bdb17eSSharon Dvir HCMD_NAME(REPLY_TX_PWR_TABLE_CMD),
9939bdb17eSSharon Dvir HCMD_NAME(REPLY_TX_POWER_DBM_CMD_V1),
10039bdb17eSSharon Dvir HCMD_NAME(TX_ANT_CONFIGURATION_CMD),
10139bdb17eSSharon Dvir HCMD_NAME(MEASURE_ABORT_NOTIFICATION),
10239bdb17eSSharon Dvir HCMD_NAME(REPLY_BT_CONFIG),
10339bdb17eSSharon Dvir HCMD_NAME(REPLY_STATISTICS_CMD),
10439bdb17eSSharon Dvir HCMD_NAME(STATISTICS_NOTIFICATION),
10539bdb17eSSharon Dvir HCMD_NAME(REPLY_CARD_STATE_CMD),
10639bdb17eSSharon Dvir HCMD_NAME(CARD_STATE_NOTIFICATION),
10739bdb17eSSharon Dvir HCMD_NAME(MISSED_BEACONS_NOTIFICATION),
10839bdb17eSSharon Dvir HCMD_NAME(REPLY_CT_KILL_CONFIG_CMD),
10939bdb17eSSharon Dvir HCMD_NAME(SENSITIVITY_CMD),
11039bdb17eSSharon Dvir HCMD_NAME(REPLY_PHY_CALIBRATION_CMD),
11139bdb17eSSharon Dvir HCMD_NAME(REPLY_WIPAN_PARAMS),
11239bdb17eSSharon Dvir HCMD_NAME(REPLY_WIPAN_RXON),
11339bdb17eSSharon Dvir HCMD_NAME(REPLY_WIPAN_RXON_TIMING),
11439bdb17eSSharon Dvir HCMD_NAME(REPLY_WIPAN_RXON_ASSOC),
11539bdb17eSSharon Dvir HCMD_NAME(REPLY_WIPAN_QOS_PARAM),
11639bdb17eSSharon Dvir HCMD_NAME(REPLY_WIPAN_WEPKEY),
11739bdb17eSSharon Dvir HCMD_NAME(REPLY_WIPAN_P2P_CHANNEL_SWITCH),
11839bdb17eSSharon Dvir HCMD_NAME(REPLY_WIPAN_NOA_NOTIFICATION),
11939bdb17eSSharon Dvir HCMD_NAME(REPLY_WIPAN_DEACTIVATION_COMPLETE),
12039bdb17eSSharon Dvir HCMD_NAME(REPLY_RX_PHY_CMD),
12139bdb17eSSharon Dvir HCMD_NAME(REPLY_RX_MPDU_CMD),
12239bdb17eSSharon Dvir HCMD_NAME(REPLY_RX),
12339bdb17eSSharon Dvir HCMD_NAME(REPLY_COMPRESSED_BA),
12439bdb17eSSharon Dvir HCMD_NAME(REPLY_BT_COEX_PRIO_TABLE),
12539bdb17eSSharon Dvir HCMD_NAME(REPLY_BT_COEX_PROT_ENV),
12639bdb17eSSharon Dvir HCMD_NAME(REPLY_BT_COEX_PROFILE_NOTIF),
12739bdb17eSSharon Dvir HCMD_NAME(REPLY_D3_CONFIG),
12839bdb17eSSharon Dvir HCMD_NAME(REPLY_WOWLAN_PATTERNS),
12939bdb17eSSharon Dvir HCMD_NAME(REPLY_WOWLAN_WAKEUP_FILTER),
13039bdb17eSSharon Dvir HCMD_NAME(REPLY_WOWLAN_TSC_RSC_PARAMS),
13139bdb17eSSharon Dvir HCMD_NAME(REPLY_WOWLAN_TKIP_PARAMS),
13239bdb17eSSharon Dvir HCMD_NAME(REPLY_WOWLAN_KEK_KCK_MATERIAL),
13339bdb17eSSharon Dvir HCMD_NAME(REPLY_WOWLAN_GET_STATUS),
13439bdb17eSSharon Dvir };
13539bdb17eSSharon Dvir
13639bdb17eSSharon Dvir static const struct iwl_hcmd_arr iwl_dvm_groups[] = {
13739bdb17eSSharon Dvir [0x0] = HCMD_ARR(iwl_dvm_cmd_names),
13839bdb17eSSharon Dvir };
13939bdb17eSSharon Dvir
140e705c121SKalle Valo static const struct iwl_op_mode_ops iwl_dvm_ops;
141e705c121SKalle Valo
iwl_update_chain_flags(struct iwl_priv * priv)142e705c121SKalle Valo void iwl_update_chain_flags(struct iwl_priv *priv)
143e705c121SKalle Valo {
144e705c121SKalle Valo struct iwl_rxon_context *ctx;
145e705c121SKalle Valo
146e705c121SKalle Valo for_each_context(priv, ctx) {
147e705c121SKalle Valo iwlagn_set_rxon_chain(priv, ctx);
148e705c121SKalle Valo if (ctx->active.rx_chain != ctx->staging.rx_chain)
149e705c121SKalle Valo iwlagn_commit_rxon(priv, ctx);
150e705c121SKalle Valo }
151e705c121SKalle Valo }
152e705c121SKalle Valo
153e705c121SKalle Valo /* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */
iwl_set_beacon_tim(struct iwl_priv * priv,struct iwl_tx_beacon_cmd * tx_beacon_cmd,u8 * beacon,u32 frame_size)154e705c121SKalle Valo static void iwl_set_beacon_tim(struct iwl_priv *priv,
155e705c121SKalle Valo struct iwl_tx_beacon_cmd *tx_beacon_cmd,
156e705c121SKalle Valo u8 *beacon, u32 frame_size)
157e705c121SKalle Valo {
158e705c121SKalle Valo u16 tim_idx;
159e705c121SKalle Valo struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
160e705c121SKalle Valo
161e705c121SKalle Valo /*
162e705c121SKalle Valo * The index is relative to frame start but we start looking at the
163e705c121SKalle Valo * variable-length part of the beacon.
164e705c121SKalle Valo */
165e705c121SKalle Valo tim_idx = mgmt->u.beacon.variable - beacon;
166e705c121SKalle Valo
167e705c121SKalle Valo /* Parse variable-length elements of beacon to find WLAN_EID_TIM */
168e705c121SKalle Valo while ((tim_idx < (frame_size - 2)) &&
169e705c121SKalle Valo (beacon[tim_idx] != WLAN_EID_TIM))
170e705c121SKalle Valo tim_idx += beacon[tim_idx+1] + 2;
171e705c121SKalle Valo
172e705c121SKalle Valo /* If TIM field was found, set variables */
173e705c121SKalle Valo if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) {
174e705c121SKalle Valo tx_beacon_cmd->tim_idx = cpu_to_le16(tim_idx);
175e705c121SKalle Valo tx_beacon_cmd->tim_size = beacon[tim_idx+1];
176e705c121SKalle Valo } else
177e705c121SKalle Valo IWL_WARN(priv, "Unable to find TIM Element in beacon\n");
178e705c121SKalle Valo }
179e705c121SKalle Valo
iwlagn_send_beacon_cmd(struct iwl_priv * priv)180e705c121SKalle Valo int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
181e705c121SKalle Valo {
182e705c121SKalle Valo struct iwl_tx_beacon_cmd *tx_beacon_cmd;
183e705c121SKalle Valo struct iwl_host_cmd cmd = {
184e705c121SKalle Valo .id = REPLY_TX_BEACON,
185e705c121SKalle Valo };
186e705c121SKalle Valo struct ieee80211_tx_info *info;
187e705c121SKalle Valo u32 frame_size;
188e705c121SKalle Valo u32 rate_flags;
189e705c121SKalle Valo u32 rate;
190e705c121SKalle Valo
191e705c121SKalle Valo /*
192e705c121SKalle Valo * We have to set up the TX command, the TX Beacon command, and the
193e705c121SKalle Valo * beacon contents.
194e705c121SKalle Valo */
195e705c121SKalle Valo
196e705c121SKalle Valo lockdep_assert_held(&priv->mutex);
197e705c121SKalle Valo
198e705c121SKalle Valo if (!priv->beacon_ctx) {
199e705c121SKalle Valo IWL_ERR(priv, "trying to build beacon w/o beacon context!\n");
200e705c121SKalle Valo return 0;
201e705c121SKalle Valo }
202e705c121SKalle Valo
203e705c121SKalle Valo if (WARN_ON(!priv->beacon_skb))
204e705c121SKalle Valo return -EINVAL;
205e705c121SKalle Valo
206e705c121SKalle Valo /* Allocate beacon command */
207e705c121SKalle Valo if (!priv->beacon_cmd)
208e705c121SKalle Valo priv->beacon_cmd = kzalloc(sizeof(*tx_beacon_cmd), GFP_KERNEL);
209e705c121SKalle Valo tx_beacon_cmd = priv->beacon_cmd;
210e705c121SKalle Valo if (!tx_beacon_cmd)
211e705c121SKalle Valo return -ENOMEM;
212e705c121SKalle Valo
213e705c121SKalle Valo frame_size = priv->beacon_skb->len;
214e705c121SKalle Valo
215e705c121SKalle Valo /* Set up TX command fields */
216e705c121SKalle Valo tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
217e705c121SKalle Valo tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id;
218e705c121SKalle Valo tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
219e705c121SKalle Valo tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK |
220e705c121SKalle Valo TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK;
221e705c121SKalle Valo
222e705c121SKalle Valo /* Set up TX beacon command fields */
223e705c121SKalle Valo iwl_set_beacon_tim(priv, tx_beacon_cmd, priv->beacon_skb->data,
224e705c121SKalle Valo frame_size);
225e705c121SKalle Valo
226e705c121SKalle Valo /* Set up packet rate and flags */
227e705c121SKalle Valo info = IEEE80211_SKB_CB(priv->beacon_skb);
228e705c121SKalle Valo
229e705c121SKalle Valo /*
230e705c121SKalle Valo * Let's set up the rate at least somewhat correctly;
231e705c121SKalle Valo * it will currently not actually be used by the uCode,
232e705c121SKalle Valo * it uses the broadcast station's rate instead.
233e705c121SKalle Valo */
234e705c121SKalle Valo if (info->control.rates[0].idx < 0 ||
235e705c121SKalle Valo info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
236e705c121SKalle Valo rate = 0;
237e705c121SKalle Valo else
238e705c121SKalle Valo rate = info->control.rates[0].idx;
239e705c121SKalle Valo
240e705c121SKalle Valo priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
241e705c121SKalle Valo priv->nvm_data->valid_tx_ant);
242e705c121SKalle Valo rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
243e705c121SKalle Valo
244e705c121SKalle Valo /* In mac80211, rates for 5 GHz start at 0 */
24557fbcce3SJohannes Berg if (info->band == NL80211_BAND_5GHZ)
246e705c121SKalle Valo rate += IWL_FIRST_OFDM_RATE;
247e705c121SKalle Valo else if (rate >= IWL_FIRST_CCK_RATE && rate <= IWL_LAST_CCK_RATE)
248e705c121SKalle Valo rate_flags |= RATE_MCS_CCK_MSK;
249e705c121SKalle Valo
250e705c121SKalle Valo tx_beacon_cmd->tx.rate_n_flags =
251e705c121SKalle Valo iwl_hw_set_rate_n_flags(rate, rate_flags);
252e705c121SKalle Valo
253e705c121SKalle Valo /* Submit command */
254e705c121SKalle Valo cmd.len[0] = sizeof(*tx_beacon_cmd);
255e705c121SKalle Valo cmd.data[0] = tx_beacon_cmd;
256e705c121SKalle Valo cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
257e705c121SKalle Valo cmd.len[1] = frame_size;
258e705c121SKalle Valo cmd.data[1] = priv->beacon_skb->data;
259e705c121SKalle Valo cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
260e705c121SKalle Valo
261e705c121SKalle Valo return iwl_dvm_send_cmd(priv, &cmd);
262e705c121SKalle Valo }
263e705c121SKalle Valo
iwl_bg_beacon_update(struct work_struct * work)264e705c121SKalle Valo static void iwl_bg_beacon_update(struct work_struct *work)
265e705c121SKalle Valo {
266e705c121SKalle Valo struct iwl_priv *priv =
267e705c121SKalle Valo container_of(work, struct iwl_priv, beacon_update);
268e705c121SKalle Valo struct sk_buff *beacon;
269e705c121SKalle Valo
270e705c121SKalle Valo mutex_lock(&priv->mutex);
271e705c121SKalle Valo if (!priv->beacon_ctx) {
272e705c121SKalle Valo IWL_ERR(priv, "updating beacon w/o beacon context!\n");
273e705c121SKalle Valo goto out;
274e705c121SKalle Valo }
275e705c121SKalle Valo
276e705c121SKalle Valo if (priv->beacon_ctx->vif->type != NL80211_IFTYPE_AP) {
277e705c121SKalle Valo /*
278e705c121SKalle Valo * The ucode will send beacon notifications even in
279e705c121SKalle Valo * IBSS mode, but we don't want to process them. But
280e705c121SKalle Valo * we need to defer the type check to here due to
281e705c121SKalle Valo * requiring locking around the beacon_ctx access.
282e705c121SKalle Valo */
283e705c121SKalle Valo goto out;
284e705c121SKalle Valo }
285e705c121SKalle Valo
286e705c121SKalle Valo /* Pull updated AP beacon from mac80211. will fail if not in AP mode */
2876e8912a5SShaul Triebitz beacon = ieee80211_beacon_get(priv->hw, priv->beacon_ctx->vif, 0);
288e705c121SKalle Valo if (!beacon) {
289e705c121SKalle Valo IWL_ERR(priv, "update beacon failed -- keeping old\n");
290e705c121SKalle Valo goto out;
291e705c121SKalle Valo }
292e705c121SKalle Valo
293e705c121SKalle Valo /* new beacon skb is allocated every time; dispose previous.*/
294e705c121SKalle Valo dev_kfree_skb(priv->beacon_skb);
295e705c121SKalle Valo
296e705c121SKalle Valo priv->beacon_skb = beacon;
297e705c121SKalle Valo
298e705c121SKalle Valo iwlagn_send_beacon_cmd(priv);
299e705c121SKalle Valo out:
300e705c121SKalle Valo mutex_unlock(&priv->mutex);
301e705c121SKalle Valo }
302e705c121SKalle Valo
iwl_bg_bt_runtime_config(struct work_struct * work)303e705c121SKalle Valo static void iwl_bg_bt_runtime_config(struct work_struct *work)
304e705c121SKalle Valo {
305e705c121SKalle Valo struct iwl_priv *priv =
306e705c121SKalle Valo container_of(work, struct iwl_priv, bt_runtime_config);
307e705c121SKalle Valo
308e705c121SKalle Valo mutex_lock(&priv->mutex);
309e705c121SKalle Valo if (test_bit(STATUS_EXIT_PENDING, &priv->status))
310e705c121SKalle Valo goto out;
311e705c121SKalle Valo
312e705c121SKalle Valo /* dont send host command if rf-kill is on */
313e705c121SKalle Valo if (!iwl_is_ready_rf(priv))
314e705c121SKalle Valo goto out;
315e705c121SKalle Valo
316e705c121SKalle Valo iwlagn_send_advance_bt_config(priv);
317e705c121SKalle Valo out:
318e705c121SKalle Valo mutex_unlock(&priv->mutex);
319e705c121SKalle Valo }
320e705c121SKalle Valo
iwl_bg_bt_full_concurrency(struct work_struct * work)321e705c121SKalle Valo static void iwl_bg_bt_full_concurrency(struct work_struct *work)
322e705c121SKalle Valo {
323e705c121SKalle Valo struct iwl_priv *priv =
324e705c121SKalle Valo container_of(work, struct iwl_priv, bt_full_concurrency);
325e705c121SKalle Valo struct iwl_rxon_context *ctx;
326e705c121SKalle Valo
327e705c121SKalle Valo mutex_lock(&priv->mutex);
328e705c121SKalle Valo
329e705c121SKalle Valo if (test_bit(STATUS_EXIT_PENDING, &priv->status))
330e705c121SKalle Valo goto out;
331e705c121SKalle Valo
332e705c121SKalle Valo /* dont send host command if rf-kill is on */
333e705c121SKalle Valo if (!iwl_is_ready_rf(priv))
334e705c121SKalle Valo goto out;
335e705c121SKalle Valo
336e705c121SKalle Valo IWL_DEBUG_INFO(priv, "BT coex in %s mode\n",
337e705c121SKalle Valo priv->bt_full_concurrent ?
338e705c121SKalle Valo "full concurrency" : "3-wire");
339e705c121SKalle Valo
340e705c121SKalle Valo /*
341e705c121SKalle Valo * LQ & RXON updated cmds must be sent before BT Config cmd
342e705c121SKalle Valo * to avoid 3-wire collisions
343e705c121SKalle Valo */
344e705c121SKalle Valo for_each_context(priv, ctx) {
345e705c121SKalle Valo iwlagn_set_rxon_chain(priv, ctx);
346e705c121SKalle Valo iwlagn_commit_rxon(priv, ctx);
347e705c121SKalle Valo }
348e705c121SKalle Valo
349e705c121SKalle Valo iwlagn_send_advance_bt_config(priv);
350e705c121SKalle Valo out:
351e705c121SKalle Valo mutex_unlock(&priv->mutex);
352e705c121SKalle Valo }
353e705c121SKalle Valo
iwl_send_statistics_request(struct iwl_priv * priv,u8 flags,bool clear)354e705c121SKalle Valo int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
355e705c121SKalle Valo {
356e705c121SKalle Valo struct iwl_statistics_cmd statistics_cmd = {
357e705c121SKalle Valo .configuration_flags =
358e705c121SKalle Valo clear ? IWL_STATS_CONF_CLEAR_STATS : 0,
359e705c121SKalle Valo };
360e705c121SKalle Valo
361e705c121SKalle Valo if (flags & CMD_ASYNC)
362e705c121SKalle Valo return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
363e705c121SKalle Valo CMD_ASYNC,
364e705c121SKalle Valo sizeof(struct iwl_statistics_cmd),
365e705c121SKalle Valo &statistics_cmd);
366e705c121SKalle Valo else
367e705c121SKalle Valo return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, 0,
368e705c121SKalle Valo sizeof(struct iwl_statistics_cmd),
369e705c121SKalle Valo &statistics_cmd);
370e705c121SKalle Valo }
371e705c121SKalle Valo
3727cb391ffSLee Jones /*
373e705c121SKalle Valo * iwl_bg_statistics_periodic - Timer callback to queue statistics
374e705c121SKalle Valo *
375e705c121SKalle Valo * This callback is provided in order to send a statistics request.
376e705c121SKalle Valo *
377e705c121SKalle Valo * This timer function is continually reset to execute within
378e705c121SKalle Valo * REG_RECALIB_PERIOD seconds since the last STATISTICS_NOTIFICATION
379e705c121SKalle Valo * was received. We need to ensure we receive the statistics in order
380e705c121SKalle Valo * to update the temperature used for calibrating the TXPOWER.
381e705c121SKalle Valo */
iwl_bg_statistics_periodic(struct timer_list * t)382e99e88a9SKees Cook static void iwl_bg_statistics_periodic(struct timer_list *t)
383e705c121SKalle Valo {
384e99e88a9SKees Cook struct iwl_priv *priv = from_timer(priv, t, statistics_periodic);
385e705c121SKalle Valo
386e705c121SKalle Valo if (test_bit(STATUS_EXIT_PENDING, &priv->status))
387e705c121SKalle Valo return;
388e705c121SKalle Valo
389e705c121SKalle Valo /* dont send host command if rf-kill is on */
390e705c121SKalle Valo if (!iwl_is_ready_rf(priv))
391e705c121SKalle Valo return;
392e705c121SKalle Valo
393e705c121SKalle Valo iwl_send_statistics_request(priv, CMD_ASYNC, false);
394e705c121SKalle Valo }
395e705c121SKalle Valo
396e705c121SKalle Valo
iwl_print_cont_event_trace(struct iwl_priv * priv,u32 base,u32 start_idx,u32 num_events,u32 capacity,u32 mode)397e705c121SKalle Valo static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
398e705c121SKalle Valo u32 start_idx, u32 num_events,
399e705c121SKalle Valo u32 capacity, u32 mode)
400e705c121SKalle Valo {
401e705c121SKalle Valo u32 i;
402e705c121SKalle Valo u32 ptr; /* SRAM byte address of log data */
403e705c121SKalle Valo u32 ev, time, data; /* event log data */
404e705c121SKalle Valo
405e705c121SKalle Valo if (mode == 0)
406e705c121SKalle Valo ptr = base + (4 * sizeof(u32)) + (start_idx * 2 * sizeof(u32));
407e705c121SKalle Valo else
408e705c121SKalle Valo ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32));
409e705c121SKalle Valo
410e705c121SKalle Valo /* Make sure device is powered up for SRAM reads */
4111ed08f6fSJohannes Berg if (!iwl_trans_grab_nic_access(priv->trans))
412e705c121SKalle Valo return;
413e705c121SKalle Valo
414e705c121SKalle Valo /* Set starting address; reads will auto-increment */
415e705c121SKalle Valo iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, ptr);
416e705c121SKalle Valo
417e705c121SKalle Valo /*
418e705c121SKalle Valo * Refuse to read more than would have fit into the log from
419e705c121SKalle Valo * the current start_idx. This used to happen due to the race
420e705c121SKalle Valo * described below, but now WARN because the code below should
421e705c121SKalle Valo * prevent it from happening here.
422e705c121SKalle Valo */
423e705c121SKalle Valo if (WARN_ON(num_events > capacity - start_idx))
424e705c121SKalle Valo num_events = capacity - start_idx;
425e705c121SKalle Valo
426e705c121SKalle Valo /*
427e705c121SKalle Valo * "time" is actually "data" for mode 0 (no timestamp).
428e705c121SKalle Valo * place event id # at far right for easier visual parsing.
429e705c121SKalle Valo */
430e705c121SKalle Valo for (i = 0; i < num_events; i++) {
431e705c121SKalle Valo ev = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT);
432e705c121SKalle Valo time = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT);
433e705c121SKalle Valo if (mode == 0) {
434e705c121SKalle Valo trace_iwlwifi_dev_ucode_cont_event(
435e705c121SKalle Valo priv->trans->dev, 0, time, ev);
436e705c121SKalle Valo } else {
437e705c121SKalle Valo data = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT);
438e705c121SKalle Valo trace_iwlwifi_dev_ucode_cont_event(
439e705c121SKalle Valo priv->trans->dev, time, data, ev);
440e705c121SKalle Valo }
441e705c121SKalle Valo }
442e705c121SKalle Valo /* Allow device to power down */
4431ed08f6fSJohannes Berg iwl_trans_release_nic_access(priv->trans);
444e705c121SKalle Valo }
445e705c121SKalle Valo
iwl_continuous_event_trace(struct iwl_priv * priv)446e705c121SKalle Valo static void iwl_continuous_event_trace(struct iwl_priv *priv)
447e705c121SKalle Valo {
448e705c121SKalle Valo u32 capacity; /* event log capacity in # entries */
449e705c121SKalle Valo struct {
450e705c121SKalle Valo u32 capacity;
451e705c121SKalle Valo u32 mode;
452e705c121SKalle Valo u32 wrap_counter;
453e705c121SKalle Valo u32 write_counter;
454e705c121SKalle Valo } __packed read;
455e705c121SKalle Valo u32 base; /* SRAM byte address of event log header */
456e705c121SKalle Valo u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
457e705c121SKalle Valo u32 num_wraps; /* # times uCode wrapped to top of log */
458e705c121SKalle Valo u32 next_entry; /* index of next entry to be written by uCode */
459e705c121SKalle Valo
460e705c121SKalle Valo base = priv->device_pointers.log_event_table;
461e705c121SKalle Valo if (iwlagn_hw_valid_rtc_data_addr(base)) {
462e705c121SKalle Valo iwl_trans_read_mem_bytes(priv->trans, base,
463e705c121SKalle Valo &read, sizeof(read));
464e705c121SKalle Valo capacity = read.capacity;
465e705c121SKalle Valo mode = read.mode;
466e705c121SKalle Valo num_wraps = read.wrap_counter;
467e705c121SKalle Valo next_entry = read.write_counter;
468e705c121SKalle Valo } else
469e705c121SKalle Valo return;
470e705c121SKalle Valo
471e705c121SKalle Valo /*
472e705c121SKalle Valo * Unfortunately, the uCode doesn't use temporary variables.
473e705c121SKalle Valo * Therefore, it can happen that we read next_entry == capacity,
474e705c121SKalle Valo * which really means next_entry == 0.
475e705c121SKalle Valo */
476e705c121SKalle Valo if (unlikely(next_entry == capacity))
477e705c121SKalle Valo next_entry = 0;
478e705c121SKalle Valo /*
479e705c121SKalle Valo * Additionally, the uCode increases the write pointer before
480e705c121SKalle Valo * the wraps counter, so if the write pointer is smaller than
481e705c121SKalle Valo * the old write pointer (wrap occurred) but we read that no
482e705c121SKalle Valo * wrap occurred, we actually read between the next_entry and
483e705c121SKalle Valo * num_wraps update (this does happen in practice!!) -- take
484e705c121SKalle Valo * that into account by increasing num_wraps.
485e705c121SKalle Valo */
486e705c121SKalle Valo if (unlikely(next_entry < priv->event_log.next_entry &&
487e705c121SKalle Valo num_wraps == priv->event_log.num_wraps))
488e705c121SKalle Valo num_wraps++;
489e705c121SKalle Valo
490e705c121SKalle Valo if (num_wraps == priv->event_log.num_wraps) {
491e705c121SKalle Valo iwl_print_cont_event_trace(
492e705c121SKalle Valo priv, base, priv->event_log.next_entry,
493e705c121SKalle Valo next_entry - priv->event_log.next_entry,
494e705c121SKalle Valo capacity, mode);
495e705c121SKalle Valo
496e705c121SKalle Valo priv->event_log.non_wraps_count++;
497e705c121SKalle Valo } else {
498e705c121SKalle Valo if (num_wraps - priv->event_log.num_wraps > 1)
499e705c121SKalle Valo priv->event_log.wraps_more_count++;
500e705c121SKalle Valo else
501e705c121SKalle Valo priv->event_log.wraps_once_count++;
502e705c121SKalle Valo
503e705c121SKalle Valo trace_iwlwifi_dev_ucode_wrap_event(priv->trans->dev,
504e705c121SKalle Valo num_wraps - priv->event_log.num_wraps,
505e705c121SKalle Valo next_entry, priv->event_log.next_entry);
506e705c121SKalle Valo
507e705c121SKalle Valo if (next_entry < priv->event_log.next_entry) {
508e705c121SKalle Valo iwl_print_cont_event_trace(
509e705c121SKalle Valo priv, base, priv->event_log.next_entry,
510e705c121SKalle Valo capacity - priv->event_log.next_entry,
511e705c121SKalle Valo capacity, mode);
512e705c121SKalle Valo
513e705c121SKalle Valo iwl_print_cont_event_trace(
514e705c121SKalle Valo priv, base, 0, next_entry, capacity, mode);
515e705c121SKalle Valo } else {
516e705c121SKalle Valo iwl_print_cont_event_trace(
517e705c121SKalle Valo priv, base, next_entry,
518e705c121SKalle Valo capacity - next_entry,
519e705c121SKalle Valo capacity, mode);
520e705c121SKalle Valo
521e705c121SKalle Valo iwl_print_cont_event_trace(
522e705c121SKalle Valo priv, base, 0, next_entry, capacity, mode);
523e705c121SKalle Valo }
524e705c121SKalle Valo }
525e705c121SKalle Valo
526e705c121SKalle Valo priv->event_log.num_wraps = num_wraps;
527e705c121SKalle Valo priv->event_log.next_entry = next_entry;
528e705c121SKalle Valo }
529e705c121SKalle Valo
5307cb391ffSLee Jones /*
531e705c121SKalle Valo * iwl_bg_ucode_trace - Timer callback to log ucode event
532e705c121SKalle Valo *
533e705c121SKalle Valo * The timer is continually set to execute every
534e705c121SKalle Valo * UCODE_TRACE_PERIOD milliseconds after the last timer expired
535e705c121SKalle Valo * this function is to perform continuous uCode event logging operation
536e705c121SKalle Valo * if enabled
537e705c121SKalle Valo */
iwl_bg_ucode_trace(struct timer_list * t)538e99e88a9SKees Cook static void iwl_bg_ucode_trace(struct timer_list *t)
539e705c121SKalle Valo {
540e99e88a9SKees Cook struct iwl_priv *priv = from_timer(priv, t, ucode_trace);
541e705c121SKalle Valo
542e705c121SKalle Valo if (test_bit(STATUS_EXIT_PENDING, &priv->status))
543e705c121SKalle Valo return;
544e705c121SKalle Valo
545e705c121SKalle Valo if (priv->event_log.ucode_trace) {
546e705c121SKalle Valo iwl_continuous_event_trace(priv);
547e705c121SKalle Valo /* Reschedule the timer to occur in UCODE_TRACE_PERIOD */
548e705c121SKalle Valo mod_timer(&priv->ucode_trace,
549e705c121SKalle Valo jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
550e705c121SKalle Valo }
551e705c121SKalle Valo }
552e705c121SKalle Valo
iwl_bg_tx_flush(struct work_struct * work)553e705c121SKalle Valo static void iwl_bg_tx_flush(struct work_struct *work)
554e705c121SKalle Valo {
555e705c121SKalle Valo struct iwl_priv *priv =
556e705c121SKalle Valo container_of(work, struct iwl_priv, tx_flush);
557e705c121SKalle Valo
558e705c121SKalle Valo if (test_bit(STATUS_EXIT_PENDING, &priv->status))
559e705c121SKalle Valo return;
560e705c121SKalle Valo
561e705c121SKalle Valo /* do nothing if rf-kill is on */
562e705c121SKalle Valo if (!iwl_is_ready_rf(priv))
563e705c121SKalle Valo return;
564e705c121SKalle Valo
565e705c121SKalle Valo IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
566e705c121SKalle Valo iwlagn_dev_txfifo_flush(priv);
567e705c121SKalle Valo }
568e705c121SKalle Valo
569e705c121SKalle Valo /*
570e705c121SKalle Valo * queue/FIFO/AC mapping definitions
571e705c121SKalle Valo */
572e705c121SKalle Valo
573e705c121SKalle Valo static const u8 iwlagn_bss_ac_to_fifo[] = {
574e705c121SKalle Valo IWL_TX_FIFO_VO,
575e705c121SKalle Valo IWL_TX_FIFO_VI,
576e705c121SKalle Valo IWL_TX_FIFO_BE,
577e705c121SKalle Valo IWL_TX_FIFO_BK,
578e705c121SKalle Valo };
579e705c121SKalle Valo
580e705c121SKalle Valo static const u8 iwlagn_bss_ac_to_queue[] = {
581e705c121SKalle Valo 0, 1, 2, 3,
582e705c121SKalle Valo };
583e705c121SKalle Valo
584e705c121SKalle Valo static const u8 iwlagn_pan_ac_to_fifo[] = {
585e705c121SKalle Valo IWL_TX_FIFO_VO_IPAN,
586e705c121SKalle Valo IWL_TX_FIFO_VI_IPAN,
587e705c121SKalle Valo IWL_TX_FIFO_BE_IPAN,
588e705c121SKalle Valo IWL_TX_FIFO_BK_IPAN,
589e705c121SKalle Valo };
590e705c121SKalle Valo
591e705c121SKalle Valo static const u8 iwlagn_pan_ac_to_queue[] = {
592e705c121SKalle Valo 7, 6, 5, 4,
593e705c121SKalle Valo };
594e705c121SKalle Valo
iwl_init_context(struct iwl_priv * priv,u32 ucode_flags)595e705c121SKalle Valo static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
596e705c121SKalle Valo {
597e705c121SKalle Valo int i;
598e705c121SKalle Valo
599e705c121SKalle Valo /*
600e705c121SKalle Valo * The default context is always valid,
601e705c121SKalle Valo * the PAN context depends on uCode.
602e705c121SKalle Valo */
603e705c121SKalle Valo priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
604e705c121SKalle Valo if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN)
605e705c121SKalle Valo priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN);
606e705c121SKalle Valo
607e705c121SKalle Valo for (i = 0; i < NUM_IWL_RXON_CTX; i++)
608e705c121SKalle Valo priv->contexts[i].ctxid = i;
609e705c121SKalle Valo
610e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_BSS].always_active = true;
611e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_BSS].is_active = true;
612e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
613e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
614e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
615e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
616e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
617e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
618e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
619e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes =
620e705c121SKalle Valo BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MONITOR);
621e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
622e705c121SKalle Valo BIT(NL80211_IFTYPE_STATION);
623e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP;
624e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
625e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
626e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
627e705c121SKalle Valo memcpy(priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue,
628e705c121SKalle Valo iwlagn_bss_ac_to_queue, sizeof(iwlagn_bss_ac_to_queue));
629e705c121SKalle Valo memcpy(priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo,
630e705c121SKalle Valo iwlagn_bss_ac_to_fifo, sizeof(iwlagn_bss_ac_to_fifo));
631e705c121SKalle Valo
632e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON;
633e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd =
634e705c121SKalle Valo REPLY_WIPAN_RXON_TIMING;
635e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd =
636e705c121SKalle Valo REPLY_WIPAN_RXON_ASSOC;
637e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_PAN].qos_cmd = REPLY_WIPAN_QOS_PARAM;
638e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_PAN].ap_sta_id = IWL_AP_ID_PAN;
639e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY;
640e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID;
641e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION;
642e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_PAN].interface_modes =
643e705c121SKalle Valo BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP);
644e705c121SKalle Valo
645e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP;
646e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA;
647e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
648e705c121SKalle Valo memcpy(priv->contexts[IWL_RXON_CTX_PAN].ac_to_queue,
649e705c121SKalle Valo iwlagn_pan_ac_to_queue, sizeof(iwlagn_pan_ac_to_queue));
650e705c121SKalle Valo memcpy(priv->contexts[IWL_RXON_CTX_PAN].ac_to_fifo,
651e705c121SKalle Valo iwlagn_pan_ac_to_fifo, sizeof(iwlagn_pan_ac_to_fifo));
652e705c121SKalle Valo priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE;
653e705c121SKalle Valo
654e705c121SKalle Valo BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
655e705c121SKalle Valo }
656e705c121SKalle Valo
iwl_rf_kill_ct_config(struct iwl_priv * priv)657e705c121SKalle Valo static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
658e705c121SKalle Valo {
659e705c121SKalle Valo struct iwl_ct_kill_config cmd;
660e705c121SKalle Valo struct iwl_ct_kill_throttling_config adv_cmd;
661e705c121SKalle Valo int ret = 0;
662e705c121SKalle Valo
663e705c121SKalle Valo iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_CLR,
664e705c121SKalle Valo CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
665e705c121SKalle Valo
666e705c121SKalle Valo priv->thermal_throttle.ct_kill_toggle = false;
667e705c121SKalle Valo
668e705c121SKalle Valo if (priv->lib->support_ct_kill_exit) {
669e705c121SKalle Valo adv_cmd.critical_temperature_enter =
670e705c121SKalle Valo cpu_to_le32(priv->hw_params.ct_kill_threshold);
671e705c121SKalle Valo adv_cmd.critical_temperature_exit =
672e705c121SKalle Valo cpu_to_le32(priv->hw_params.ct_kill_exit_threshold);
673e705c121SKalle Valo
674e705c121SKalle Valo ret = iwl_dvm_send_cmd_pdu(priv,
675e705c121SKalle Valo REPLY_CT_KILL_CONFIG_CMD,
676e705c121SKalle Valo 0, sizeof(adv_cmd), &adv_cmd);
677e705c121SKalle Valo if (ret)
678e705c121SKalle Valo IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
679e705c121SKalle Valo else
680e705c121SKalle Valo IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
681e705c121SKalle Valo "succeeded, critical temperature enter is %d,"
682e705c121SKalle Valo "exit is %d\n",
683e705c121SKalle Valo priv->hw_params.ct_kill_threshold,
684e705c121SKalle Valo priv->hw_params.ct_kill_exit_threshold);
685e705c121SKalle Valo } else {
686e705c121SKalle Valo cmd.critical_temperature_R =
687e705c121SKalle Valo cpu_to_le32(priv->hw_params.ct_kill_threshold);
688e705c121SKalle Valo
689e705c121SKalle Valo ret = iwl_dvm_send_cmd_pdu(priv,
690e705c121SKalle Valo REPLY_CT_KILL_CONFIG_CMD,
691e705c121SKalle Valo 0, sizeof(cmd), &cmd);
692e705c121SKalle Valo if (ret)
693e705c121SKalle Valo IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
694e705c121SKalle Valo else
695e705c121SKalle Valo IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
696e705c121SKalle Valo "succeeded, "
697e705c121SKalle Valo "critical temperature is %d\n",
698e705c121SKalle Valo priv->hw_params.ct_kill_threshold);
699e705c121SKalle Valo }
700e705c121SKalle Valo }
701e705c121SKalle Valo
iwlagn_send_calib_cfg_rt(struct iwl_priv * priv,u32 cfg)702e705c121SKalle Valo static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
703e705c121SKalle Valo {
704e705c121SKalle Valo struct iwl_calib_cfg_cmd calib_cfg_cmd;
705e705c121SKalle Valo struct iwl_host_cmd cmd = {
706e705c121SKalle Valo .id = CALIBRATION_CFG_CMD,
707e705c121SKalle Valo .len = { sizeof(struct iwl_calib_cfg_cmd), },
708e705c121SKalle Valo .data = { &calib_cfg_cmd, },
709e705c121SKalle Valo };
710e705c121SKalle Valo
711e705c121SKalle Valo memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd));
712e705c121SKalle Valo calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_RT_CFG_ALL;
713e705c121SKalle Valo calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg);
714e705c121SKalle Valo
715e705c121SKalle Valo return iwl_dvm_send_cmd(priv, &cmd);
716e705c121SKalle Valo }
717e705c121SKalle Valo
718e705c121SKalle Valo
iwlagn_send_tx_ant_config(struct iwl_priv * priv,u8 valid_tx_ant)719e705c121SKalle Valo static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
720e705c121SKalle Valo {
721e705c121SKalle Valo struct iwl_tx_ant_config_cmd tx_ant_cmd = {
722e705c121SKalle Valo .valid = cpu_to_le32(valid_tx_ant),
723e705c121SKalle Valo };
724e705c121SKalle Valo
725e705c121SKalle Valo if (IWL_UCODE_API(priv->fw->ucode_ver) > 1) {
726e705c121SKalle Valo IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant);
727e705c121SKalle Valo return iwl_dvm_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD, 0,
728e705c121SKalle Valo sizeof(struct iwl_tx_ant_config_cmd),
729e705c121SKalle Valo &tx_ant_cmd);
730e705c121SKalle Valo } else {
731e705c121SKalle Valo IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n");
732e705c121SKalle Valo return -EOPNOTSUPP;
733e705c121SKalle Valo }
734e705c121SKalle Valo }
735e705c121SKalle Valo
iwl_send_bt_config(struct iwl_priv * priv)736e705c121SKalle Valo static void iwl_send_bt_config(struct iwl_priv *priv)
737e705c121SKalle Valo {
738e705c121SKalle Valo struct iwl_bt_cmd bt_cmd = {
739e705c121SKalle Valo .lead_time = BT_LEAD_TIME_DEF,
740e705c121SKalle Valo .max_kill = BT_MAX_KILL_DEF,
741e705c121SKalle Valo .kill_ack_mask = 0,
742e705c121SKalle Valo .kill_cts_mask = 0,
743e705c121SKalle Valo };
744e705c121SKalle Valo
745e705c121SKalle Valo if (!iwlwifi_mod_params.bt_coex_active)
746e705c121SKalle Valo bt_cmd.flags = BT_COEX_DISABLE;
747e705c121SKalle Valo else
748e705c121SKalle Valo bt_cmd.flags = BT_COEX_ENABLE;
749e705c121SKalle Valo
750e705c121SKalle Valo priv->bt_enable_flag = bt_cmd.flags;
751e705c121SKalle Valo IWL_DEBUG_INFO(priv, "BT coex %s\n",
752e705c121SKalle Valo (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
753e705c121SKalle Valo
754e705c121SKalle Valo if (iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
755e705c121SKalle Valo 0, sizeof(struct iwl_bt_cmd), &bt_cmd))
756e705c121SKalle Valo IWL_ERR(priv, "failed to send BT Coex Config\n");
757e705c121SKalle Valo }
758e705c121SKalle Valo
7597cb391ffSLee Jones /*
760e705c121SKalle Valo * iwl_alive_start - called after REPLY_ALIVE notification received
761e705c121SKalle Valo * from protocol/runtime uCode (initialization uCode's
762e705c121SKalle Valo * Alive gets handled by iwl_init_alive_start()).
763e705c121SKalle Valo */
iwl_alive_start(struct iwl_priv * priv)764e705c121SKalle Valo int iwl_alive_start(struct iwl_priv *priv)
765e705c121SKalle Valo {
766e705c121SKalle Valo int ret = 0;
767e705c121SKalle Valo struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
768e705c121SKalle Valo
769e705c121SKalle Valo IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
770e705c121SKalle Valo
771e705c121SKalle Valo /* After the ALIVE response, we can send host commands to the uCode */
772e705c121SKalle Valo set_bit(STATUS_ALIVE, &priv->status);
773e705c121SKalle Valo
774e705c121SKalle Valo if (iwl_is_rfkill(priv))
775e705c121SKalle Valo return -ERFKILL;
776e705c121SKalle Valo
777e705c121SKalle Valo if (priv->event_log.ucode_trace) {
778e705c121SKalle Valo /* start collecting data now */
779e705c121SKalle Valo mod_timer(&priv->ucode_trace, jiffies);
780e705c121SKalle Valo }
781e705c121SKalle Valo
782e705c121SKalle Valo /* download priority table before any calibration request */
783e705c121SKalle Valo if (priv->lib->bt_params &&
784e705c121SKalle Valo priv->lib->bt_params->advanced_bt_coexist) {
785e705c121SKalle Valo /* Configure Bluetooth device coexistence support */
786e705c121SKalle Valo if (priv->lib->bt_params->bt_sco_disable)
787e705c121SKalle Valo priv->bt_enable_pspoll = false;
788e705c121SKalle Valo else
789e705c121SKalle Valo priv->bt_enable_pspoll = true;
790e705c121SKalle Valo
791e705c121SKalle Valo priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
792e705c121SKalle Valo priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
793e705c121SKalle Valo priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
794e705c121SKalle Valo iwlagn_send_advance_bt_config(priv);
795e705c121SKalle Valo priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
796e705c121SKalle Valo priv->cur_rssi_ctx = NULL;
797e705c121SKalle Valo
798e705c121SKalle Valo iwl_send_prio_tbl(priv);
799e705c121SKalle Valo
800e705c121SKalle Valo /* FIXME: w/a to force change uCode BT state machine */
801e705c121SKalle Valo ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
802e705c121SKalle Valo BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
803e705c121SKalle Valo if (ret)
804e705c121SKalle Valo return ret;
805e705c121SKalle Valo ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE,
806e705c121SKalle Valo BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
807e705c121SKalle Valo if (ret)
808e705c121SKalle Valo return ret;
809e705c121SKalle Valo } else if (priv->lib->bt_params) {
810e705c121SKalle Valo /*
811e705c121SKalle Valo * default is 2-wire BT coexexistence support
812e705c121SKalle Valo */
813e705c121SKalle Valo iwl_send_bt_config(priv);
814e705c121SKalle Valo }
815e705c121SKalle Valo
816e705c121SKalle Valo /*
817e705c121SKalle Valo * Perform runtime calibrations, including DC calibration.
818e705c121SKalle Valo */
819e705c121SKalle Valo iwlagn_send_calib_cfg_rt(priv, IWL_CALIB_CFG_DC_IDX);
820e705c121SKalle Valo
821e705c121SKalle Valo ieee80211_wake_queues(priv->hw);
822e705c121SKalle Valo
823e705c121SKalle Valo /* Configure Tx antenna selection based on H/W config */
824e705c121SKalle Valo iwlagn_send_tx_ant_config(priv, priv->nvm_data->valid_tx_ant);
825e705c121SKalle Valo
826e705c121SKalle Valo if (iwl_is_associated_ctx(ctx) && !priv->wowlan) {
827e705c121SKalle Valo struct iwl_rxon_cmd *active_rxon =
828e705c121SKalle Valo (struct iwl_rxon_cmd *)&ctx->active;
829e705c121SKalle Valo /* apply any changes in staging */
830e705c121SKalle Valo ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
831e705c121SKalle Valo active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
832e705c121SKalle Valo } else {
833e705c121SKalle Valo struct iwl_rxon_context *tmp;
834e705c121SKalle Valo /* Initialize our rx_config data */
835e705c121SKalle Valo for_each_context(priv, tmp)
836e705c121SKalle Valo iwl_connection_init_rx_config(priv, tmp);
837e705c121SKalle Valo
838e705c121SKalle Valo iwlagn_set_rxon_chain(priv, ctx);
839e705c121SKalle Valo }
840e705c121SKalle Valo
841e705c121SKalle Valo if (!priv->wowlan) {
842e705c121SKalle Valo /* WoWLAN ucode will not reply in the same way, skip it */
843e705c121SKalle Valo iwl_reset_run_time_calib(priv);
844e705c121SKalle Valo }
845e705c121SKalle Valo
846e705c121SKalle Valo set_bit(STATUS_READY, &priv->status);
847e705c121SKalle Valo
848e705c121SKalle Valo /* Configure the adapter for unassociated operation */
849e705c121SKalle Valo ret = iwlagn_commit_rxon(priv, ctx);
850e705c121SKalle Valo if (ret)
851e705c121SKalle Valo return ret;
852e705c121SKalle Valo
853e705c121SKalle Valo /* At this point, the NIC is initialized and operational */
854e705c121SKalle Valo iwl_rf_kill_ct_config(priv);
855e705c121SKalle Valo
856e705c121SKalle Valo IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
857e705c121SKalle Valo
858e705c121SKalle Valo return iwl_power_update_mode(priv, true);
859e705c121SKalle Valo }
860e705c121SKalle Valo
861e705c121SKalle Valo /**
862e705c121SKalle Valo * iwl_clear_driver_stations - clear knowledge of all stations from driver
863e705c121SKalle Valo * @priv: iwl priv struct
864e705c121SKalle Valo *
865e705c121SKalle Valo * This is called during iwl_down() to make sure that in the case
866e705c121SKalle Valo * we're coming there from a hardware restart mac80211 will be
867e705c121SKalle Valo * able to reconfigure stations -- if we're getting there in the
868e705c121SKalle Valo * normal down flow then the stations will already be cleared.
869e705c121SKalle Valo */
iwl_clear_driver_stations(struct iwl_priv * priv)870e705c121SKalle Valo static void iwl_clear_driver_stations(struct iwl_priv *priv)
871e705c121SKalle Valo {
872e705c121SKalle Valo struct iwl_rxon_context *ctx;
873e705c121SKalle Valo
874e705c121SKalle Valo spin_lock_bh(&priv->sta_lock);
875e705c121SKalle Valo memset(priv->stations, 0, sizeof(priv->stations));
876e705c121SKalle Valo priv->num_stations = 0;
877e705c121SKalle Valo
878e705c121SKalle Valo priv->ucode_key_table = 0;
879e705c121SKalle Valo
880e705c121SKalle Valo for_each_context(priv, ctx) {
881e705c121SKalle Valo /*
882e705c121SKalle Valo * Remove all key information that is not stored as part
883e705c121SKalle Valo * of station information since mac80211 may not have had
884e705c121SKalle Valo * a chance to remove all the keys. When device is
885e705c121SKalle Valo * reconfigured by mac80211 after an error all keys will
886e705c121SKalle Valo * be reconfigured.
887e705c121SKalle Valo */
888e705c121SKalle Valo memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys));
889e705c121SKalle Valo ctx->key_mapping_keys = 0;
890e705c121SKalle Valo }
891e705c121SKalle Valo
892e705c121SKalle Valo spin_unlock_bh(&priv->sta_lock);
893e705c121SKalle Valo }
894e705c121SKalle Valo
iwl_down(struct iwl_priv * priv)895e705c121SKalle Valo void iwl_down(struct iwl_priv *priv)
896e705c121SKalle Valo {
897e705c121SKalle Valo int exit_pending;
898e705c121SKalle Valo
899e705c121SKalle Valo IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
900e705c121SKalle Valo
901e705c121SKalle Valo lockdep_assert_held(&priv->mutex);
902e705c121SKalle Valo
903e705c121SKalle Valo iwl_scan_cancel_timeout(priv, 200);
904e705c121SKalle Valo
905e705c121SKalle Valo exit_pending =
906e705c121SKalle Valo test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
907e705c121SKalle Valo
908e705c121SKalle Valo iwl_clear_ucode_stations(priv, NULL);
909e705c121SKalle Valo iwl_dealloc_bcast_stations(priv);
910e705c121SKalle Valo iwl_clear_driver_stations(priv);
911e705c121SKalle Valo
912e705c121SKalle Valo /* reset BT coex data */
913e705c121SKalle Valo priv->bt_status = 0;
914e705c121SKalle Valo priv->cur_rssi_ctx = NULL;
915e705c121SKalle Valo priv->bt_is_sco = 0;
916e705c121SKalle Valo if (priv->lib->bt_params)
917e705c121SKalle Valo priv->bt_traffic_load =
918e705c121SKalle Valo priv->lib->bt_params->bt_init_traffic_load;
919e705c121SKalle Valo else
920e705c121SKalle Valo priv->bt_traffic_load = 0;
921e705c121SKalle Valo priv->bt_full_concurrent = false;
922e705c121SKalle Valo priv->bt_ci_compliance = 0;
923e705c121SKalle Valo
924e705c121SKalle Valo /* Wipe out the EXIT_PENDING status bit if we are not actually
925e705c121SKalle Valo * exiting the module */
926e705c121SKalle Valo if (!exit_pending)
927e705c121SKalle Valo clear_bit(STATUS_EXIT_PENDING, &priv->status);
928e705c121SKalle Valo
929e705c121SKalle Valo if (priv->mac80211_registered)
930e705c121SKalle Valo ieee80211_stop_queues(priv->hw);
931e705c121SKalle Valo
932e705c121SKalle Valo priv->ucode_loaded = false;
933e705c121SKalle Valo iwl_trans_stop_device(priv->trans);
934e705c121SKalle Valo
935e705c121SKalle Valo /* Set num_aux_in_flight must be done after the transport is stopped */
936e705c121SKalle Valo atomic_set(&priv->num_aux_in_flight, 0);
937e705c121SKalle Valo
938e705c121SKalle Valo /* Clear out all status bits but a few that are stable across reset */
939e705c121SKalle Valo priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
940e705c121SKalle Valo STATUS_RF_KILL_HW |
941e705c121SKalle Valo test_bit(STATUS_FW_ERROR, &priv->status) <<
942e705c121SKalle Valo STATUS_FW_ERROR |
943e705c121SKalle Valo test_bit(STATUS_EXIT_PENDING, &priv->status) <<
944e705c121SKalle Valo STATUS_EXIT_PENDING;
945e705c121SKalle Valo
946e705c121SKalle Valo dev_kfree_skb(priv->beacon_skb);
947e705c121SKalle Valo priv->beacon_skb = NULL;
948e705c121SKalle Valo }
949e705c121SKalle Valo
950e705c121SKalle Valo /*****************************************************************************
951e705c121SKalle Valo *
952e705c121SKalle Valo * Workqueue callbacks
953e705c121SKalle Valo *
954e705c121SKalle Valo *****************************************************************************/
955e705c121SKalle Valo
iwl_bg_run_time_calib_work(struct work_struct * work)956e705c121SKalle Valo static void iwl_bg_run_time_calib_work(struct work_struct *work)
957e705c121SKalle Valo {
958e705c121SKalle Valo struct iwl_priv *priv = container_of(work, struct iwl_priv,
959e705c121SKalle Valo run_time_calib_work);
960e705c121SKalle Valo
961e705c121SKalle Valo mutex_lock(&priv->mutex);
962e705c121SKalle Valo
963e705c121SKalle Valo if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
964e705c121SKalle Valo test_bit(STATUS_SCANNING, &priv->status)) {
965e705c121SKalle Valo mutex_unlock(&priv->mutex);
966e705c121SKalle Valo return;
967e705c121SKalle Valo }
968e705c121SKalle Valo
969e705c121SKalle Valo if (priv->start_calib) {
970e705c121SKalle Valo iwl_chain_noise_calibration(priv);
971e705c121SKalle Valo iwl_sensitivity_calibration(priv);
972e705c121SKalle Valo }
973e705c121SKalle Valo
974e705c121SKalle Valo mutex_unlock(&priv->mutex);
975e705c121SKalle Valo }
976e705c121SKalle Valo
iwlagn_prepare_restart(struct iwl_priv * priv)977e705c121SKalle Valo void iwlagn_prepare_restart(struct iwl_priv *priv)
978e705c121SKalle Valo {
979e705c121SKalle Valo bool bt_full_concurrent;
980e705c121SKalle Valo u8 bt_ci_compliance;
981e705c121SKalle Valo u8 bt_load;
982e705c121SKalle Valo u8 bt_status;
983e705c121SKalle Valo bool bt_is_sco;
984e705c121SKalle Valo int i;
985e705c121SKalle Valo
986e705c121SKalle Valo lockdep_assert_held(&priv->mutex);
987e705c121SKalle Valo
988e705c121SKalle Valo priv->is_open = 0;
989e705c121SKalle Valo
990e705c121SKalle Valo /*
991e705c121SKalle Valo * __iwl_down() will clear the BT status variables,
992e705c121SKalle Valo * which is correct, but when we restart we really
993e705c121SKalle Valo * want to keep them so restore them afterwards.
994e705c121SKalle Valo *
995e705c121SKalle Valo * The restart process will later pick them up and
996e705c121SKalle Valo * re-configure the hw when we reconfigure the BT
997e705c121SKalle Valo * command.
998e705c121SKalle Valo */
999e705c121SKalle Valo bt_full_concurrent = priv->bt_full_concurrent;
1000e705c121SKalle Valo bt_ci_compliance = priv->bt_ci_compliance;
1001e705c121SKalle Valo bt_load = priv->bt_traffic_load;
1002e705c121SKalle Valo bt_status = priv->bt_status;
1003e705c121SKalle Valo bt_is_sco = priv->bt_is_sco;
1004e705c121SKalle Valo
1005e705c121SKalle Valo iwl_down(priv);
1006e705c121SKalle Valo
1007e705c121SKalle Valo priv->bt_full_concurrent = bt_full_concurrent;
1008e705c121SKalle Valo priv->bt_ci_compliance = bt_ci_compliance;
1009e705c121SKalle Valo priv->bt_traffic_load = bt_load;
1010e705c121SKalle Valo priv->bt_status = bt_status;
1011e705c121SKalle Valo priv->bt_is_sco = bt_is_sco;
1012e705c121SKalle Valo
1013e705c121SKalle Valo /* reset aggregation queues */
1014e705c121SKalle Valo for (i = IWLAGN_FIRST_AMPDU_QUEUE; i < IWL_MAX_HW_QUEUES; i++)
1015e705c121SKalle Valo priv->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE;
1016e705c121SKalle Valo /* and stop counts */
1017e705c121SKalle Valo for (i = 0; i < IWL_MAX_HW_QUEUES; i++)
1018e705c121SKalle Valo atomic_set(&priv->queue_stop_count[i], 0);
1019e705c121SKalle Valo
1020e705c121SKalle Valo memset(priv->agg_q_alloc, 0, sizeof(priv->agg_q_alloc));
1021e705c121SKalle Valo }
1022e705c121SKalle Valo
iwl_bg_restart(struct work_struct * data)1023e705c121SKalle Valo static void iwl_bg_restart(struct work_struct *data)
1024e705c121SKalle Valo {
1025e705c121SKalle Valo struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
1026e705c121SKalle Valo
1027e705c121SKalle Valo if (test_bit(STATUS_EXIT_PENDING, &priv->status))
1028e705c121SKalle Valo return;
1029e705c121SKalle Valo
1030e705c121SKalle Valo if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
1031e705c121SKalle Valo mutex_lock(&priv->mutex);
1032e705c121SKalle Valo iwlagn_prepare_restart(priv);
1033e705c121SKalle Valo mutex_unlock(&priv->mutex);
1034e705c121SKalle Valo iwl_cancel_deferred_work(priv);
1035e705c121SKalle Valo if (priv->mac80211_registered)
1036e705c121SKalle Valo ieee80211_restart_hw(priv->hw);
1037e705c121SKalle Valo else
1038e705c121SKalle Valo IWL_ERR(priv,
1039d6f9c772SColin Ian King "Cannot request restart before registering with mac80211\n");
1040e705c121SKalle Valo } else {
1041e705c121SKalle Valo WARN_ON(1);
1042e705c121SKalle Valo }
1043e705c121SKalle Valo }
1044e705c121SKalle Valo
1045e705c121SKalle Valo /*****************************************************************************
1046e705c121SKalle Valo *
1047e705c121SKalle Valo * driver setup and teardown
1048e705c121SKalle Valo *
1049e705c121SKalle Valo *****************************************************************************/
1050e705c121SKalle Valo
iwl_setup_deferred_work(struct iwl_priv * priv)1051e705c121SKalle Valo static void iwl_setup_deferred_work(struct iwl_priv *priv)
1052e705c121SKalle Valo {
1053b429a773SEva Rachel Retuya priv->workqueue = alloc_ordered_workqueue(DRV_NAME, 0);
1054e705c121SKalle Valo
1055e705c121SKalle Valo INIT_WORK(&priv->restart, iwl_bg_restart);
1056e705c121SKalle Valo INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
1057e705c121SKalle Valo INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
1058e705c121SKalle Valo INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush);
1059e705c121SKalle Valo INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency);
1060e705c121SKalle Valo INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config);
1061e705c121SKalle Valo
1062e705c121SKalle Valo iwl_setup_scan_deferred_work(priv);
1063e705c121SKalle Valo
1064e705c121SKalle Valo if (priv->lib->bt_params)
1065e705c121SKalle Valo iwlagn_bt_setup_deferred_work(priv);
1066e705c121SKalle Valo
1067e99e88a9SKees Cook timer_setup(&priv->statistics_periodic, iwl_bg_statistics_periodic, 0);
1068e705c121SKalle Valo
1069e99e88a9SKees Cook timer_setup(&priv->ucode_trace, iwl_bg_ucode_trace, 0);
1070e705c121SKalle Valo }
1071e705c121SKalle Valo
iwl_cancel_deferred_work(struct iwl_priv * priv)1072e705c121SKalle Valo void iwl_cancel_deferred_work(struct iwl_priv *priv)
1073e705c121SKalle Valo {
1074e705c121SKalle Valo if (priv->lib->bt_params)
1075e705c121SKalle Valo iwlagn_bt_cancel_deferred_work(priv);
1076e705c121SKalle Valo
1077e705c121SKalle Valo cancel_work_sync(&priv->run_time_calib_work);
1078e705c121SKalle Valo cancel_work_sync(&priv->beacon_update);
1079e705c121SKalle Valo
1080e705c121SKalle Valo iwl_cancel_scan_deferred_work(priv);
1081e705c121SKalle Valo
1082e705c121SKalle Valo cancel_work_sync(&priv->bt_full_concurrency);
1083e705c121SKalle Valo cancel_work_sync(&priv->bt_runtime_config);
1084e705c121SKalle Valo
1085e705c121SKalle Valo del_timer_sync(&priv->statistics_periodic);
1086e705c121SKalle Valo del_timer_sync(&priv->ucode_trace);
1087e705c121SKalle Valo }
1088e705c121SKalle Valo
iwl_init_drv(struct iwl_priv * priv)1089e705c121SKalle Valo static int iwl_init_drv(struct iwl_priv *priv)
1090e705c121SKalle Valo {
1091e705c121SKalle Valo spin_lock_init(&priv->sta_lock);
1092e705c121SKalle Valo
1093e705c121SKalle Valo mutex_init(&priv->mutex);
1094e705c121SKalle Valo
1095e705c121SKalle Valo INIT_LIST_HEAD(&priv->calib_results);
1096e705c121SKalle Valo
109757fbcce3SJohannes Berg priv->band = NL80211_BAND_2GHZ;
1098e705c121SKalle Valo
1099e705c121SKalle Valo priv->plcp_delta_threshold = priv->lib->plcp_delta_threshold;
1100e705c121SKalle Valo
1101e705c121SKalle Valo priv->iw_mode = NL80211_IFTYPE_STATION;
1102e705c121SKalle Valo priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
1103e705c121SKalle Valo priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
1104e705c121SKalle Valo priv->agg_tids_count = 0;
1105e705c121SKalle Valo
1106e705c121SKalle Valo priv->rx_statistics_jiffies = jiffies;
1107e705c121SKalle Valo
1108e705c121SKalle Valo /* Choose which receivers/antennas to use */
1109e705c121SKalle Valo iwlagn_set_rxon_chain(priv, &priv->contexts[IWL_RXON_CTX_BSS]);
1110e705c121SKalle Valo
1111e705c121SKalle Valo iwl_init_scan_params(priv);
1112e705c121SKalle Valo
1113e705c121SKalle Valo /* init bt coex */
1114e705c121SKalle Valo if (priv->lib->bt_params &&
1115e705c121SKalle Valo priv->lib->bt_params->advanced_bt_coexist) {
1116e705c121SKalle Valo priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;
1117e705c121SKalle Valo priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT;
1118e705c121SKalle Valo priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;
1119e705c121SKalle Valo priv->bt_on_thresh = BT_ON_THRESHOLD_DEF;
1120e705c121SKalle Valo priv->bt_duration = BT_DURATION_LIMIT_DEF;
1121e705c121SKalle Valo priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF;
1122e705c121SKalle Valo }
1123e705c121SKalle Valo
1124e705c121SKalle Valo return 0;
1125e705c121SKalle Valo }
1126e705c121SKalle Valo
iwl_uninit_drv(struct iwl_priv * priv)1127e705c121SKalle Valo static void iwl_uninit_drv(struct iwl_priv *priv)
1128e705c121SKalle Valo {
1129e705c121SKalle Valo kfree(priv->scan_cmd);
1130e705c121SKalle Valo kfree(priv->beacon_cmd);
1131e705c121SKalle Valo kfree(rcu_dereference_raw(priv->noa_data));
1132e705c121SKalle Valo iwl_calib_free_results(priv);
1133e705c121SKalle Valo #ifdef CONFIG_IWLWIFI_DEBUGFS
1134e705c121SKalle Valo kfree(priv->wowlan_sram);
1135e705c121SKalle Valo #endif
1136e705c121SKalle Valo }
1137e705c121SKalle Valo
iwl_set_hw_params(struct iwl_priv * priv)1138e705c121SKalle Valo static void iwl_set_hw_params(struct iwl_priv *priv)
1139e705c121SKalle Valo {
1140e705c121SKalle Valo if (priv->cfg->ht_params)
1141e705c121SKalle Valo priv->hw_params.use_rts_for_aggregation =
1142e705c121SKalle Valo priv->cfg->ht_params->use_rts_for_aggregation;
1143e705c121SKalle Valo
1144e705c121SKalle Valo /* Device-specific setup */
1145e705c121SKalle Valo priv->lib->set_hw_params(priv);
1146e705c121SKalle Valo }
1147e705c121SKalle Valo
1148e705c121SKalle Valo
1149e705c121SKalle Valo
1150e705c121SKalle Valo /* show what optional capabilities we have */
iwl_option_config(struct iwl_priv * priv)1151e705c121SKalle Valo static void iwl_option_config(struct iwl_priv *priv)
1152e705c121SKalle Valo {
1153e705c121SKalle Valo #ifdef CONFIG_IWLWIFI_DEBUG
1154e705c121SKalle Valo IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUG enabled\n");
1155e705c121SKalle Valo #else
1156e705c121SKalle Valo IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUG disabled\n");
1157e705c121SKalle Valo #endif
1158e705c121SKalle Valo
1159e705c121SKalle Valo #ifdef CONFIG_IWLWIFI_DEBUGFS
1160e705c121SKalle Valo IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUGFS enabled\n");
1161e705c121SKalle Valo #else
1162e705c121SKalle Valo IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUGFS disabled\n");
1163e705c121SKalle Valo #endif
1164e705c121SKalle Valo
1165e705c121SKalle Valo #ifdef CONFIG_IWLWIFI_DEVICE_TRACING
1166e705c121SKalle Valo IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING enabled\n");
1167e705c121SKalle Valo #else
1168e705c121SKalle Valo IWL_INFO(priv, "CONFIG_IWLWIFI_DEVICE_TRACING disabled\n");
1169e705c121SKalle Valo #endif
1170e705c121SKalle Valo }
1171e705c121SKalle Valo
iwl_eeprom_init_hw_params(struct iwl_priv * priv)1172e705c121SKalle Valo static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
1173e705c121SKalle Valo {
1174e705c121SKalle Valo struct iwl_nvm_data *data = priv->nvm_data;
1175e705c121SKalle Valo
1176e705c121SKalle Valo if (data->sku_cap_11n_enable &&
1177e705c121SKalle Valo !priv->cfg->ht_params) {
1178e705c121SKalle Valo IWL_ERR(priv, "Invalid 11n configuration\n");
1179e705c121SKalle Valo return -EINVAL;
1180e705c121SKalle Valo }
1181e705c121SKalle Valo
118228e9c00fSLuca Coelho if (!data->sku_cap_11n_enable && !data->sku_cap_band_24ghz_enable &&
118328e9c00fSLuca Coelho !data->sku_cap_band_52ghz_enable) {
1184e705c121SKalle Valo IWL_ERR(priv, "Invalid device sku\n");
1185e705c121SKalle Valo return -EINVAL;
1186e705c121SKalle Valo }
1187e705c121SKalle Valo
1188e705c121SKalle Valo IWL_DEBUG_INFO(priv,
1189e705c121SKalle Valo "Device SKU: 24GHz %s %s, 52GHz %s %s, 11.n %s %s\n",
119028e9c00fSLuca Coelho data->sku_cap_band_24ghz_enable ? "" : "NOT", "enabled",
119128e9c00fSLuca Coelho data->sku_cap_band_52ghz_enable ? "" : "NOT", "enabled",
1192e705c121SKalle Valo data->sku_cap_11n_enable ? "" : "NOT", "enabled");
1193e705c121SKalle Valo
1194e705c121SKalle Valo priv->hw_params.tx_chains_num =
1195e705c121SKalle Valo num_of_ant(data->valid_tx_ant);
1196e705c121SKalle Valo if (priv->cfg->rx_with_siso_diversity)
1197e705c121SKalle Valo priv->hw_params.rx_chains_num = 1;
1198e705c121SKalle Valo else
1199e705c121SKalle Valo priv->hw_params.rx_chains_num =
1200e705c121SKalle Valo num_of_ant(data->valid_rx_ant);
1201e705c121SKalle Valo
1202e705c121SKalle Valo IWL_DEBUG_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n",
1203e705c121SKalle Valo data->valid_tx_ant,
1204e705c121SKalle Valo data->valid_rx_ant);
1205e705c121SKalle Valo
1206e705c121SKalle Valo return 0;
1207e705c121SKalle Valo }
1208e705c121SKalle Valo
iwl_nvm_check_version(struct iwl_nvm_data * data,struct iwl_trans * trans)120964866e5dSLuca Coelho static int iwl_nvm_check_version(struct iwl_nvm_data *data,
121064866e5dSLuca Coelho struct iwl_trans *trans)
121164866e5dSLuca Coelho {
121264866e5dSLuca Coelho if (data->nvm_version >= trans->cfg->nvm_ver ||
121364866e5dSLuca Coelho data->calib_version >= trans->cfg->nvm_calib_ver) {
121464866e5dSLuca Coelho IWL_DEBUG_INFO(trans, "device EEPROM VER=0x%x, CALIB=0x%x\n",
121564866e5dSLuca Coelho data->nvm_version, data->calib_version);
121664866e5dSLuca Coelho return 0;
121764866e5dSLuca Coelho }
121864866e5dSLuca Coelho
121964866e5dSLuca Coelho IWL_ERR(trans,
122064866e5dSLuca Coelho "Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n",
122164866e5dSLuca Coelho data->nvm_version, trans->cfg->nvm_ver,
122264866e5dSLuca Coelho data->calib_version, trans->cfg->nvm_calib_ver);
122364866e5dSLuca Coelho return -EINVAL;
122464866e5dSLuca Coelho }
122564866e5dSLuca Coelho
iwl_op_mode_dvm_start(struct iwl_trans * trans,const struct iwl_cfg * cfg,const struct iwl_fw * fw,struct dentry * dbgfs_dir)1226e705c121SKalle Valo static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
1227e705c121SKalle Valo const struct iwl_cfg *cfg,
1228e705c121SKalle Valo const struct iwl_fw *fw,
1229e705c121SKalle Valo struct dentry *dbgfs_dir)
1230e705c121SKalle Valo {
1231e705c121SKalle Valo struct iwl_priv *priv;
1232e705c121SKalle Valo struct ieee80211_hw *hw;
1233e705c121SKalle Valo struct iwl_op_mode *op_mode;
1234e705c121SKalle Valo u16 num_mac;
1235e705c121SKalle Valo u32 ucode_flags;
1236e705c121SKalle Valo struct iwl_trans_config trans_cfg = {};
1237e705c121SKalle Valo static const u8 no_reclaim_cmds[] = {
1238e705c121SKalle Valo REPLY_RX_PHY_CMD,
1239e705c121SKalle Valo REPLY_RX_MPDU_CMD,
1240e705c121SKalle Valo REPLY_COMPRESSED_BA,
1241e705c121SKalle Valo STATISTICS_NOTIFICATION,
1242e705c121SKalle Valo REPLY_TX,
1243e705c121SKalle Valo };
1244e705c121SKalle Valo int i;
1245e705c121SKalle Valo
1246e705c121SKalle Valo /************************
1247e705c121SKalle Valo * 1. Allocating HW data
1248e705c121SKalle Valo ************************/
1249e705c121SKalle Valo hw = iwl_alloc_all();
1250e705c121SKalle Valo if (!hw) {
12510b295a1eSLuca Coelho pr_err("%s: Cannot allocate network device\n", trans->name);
1252e705c121SKalle Valo goto out;
1253e705c121SKalle Valo }
1254e705c121SKalle Valo
1255e705c121SKalle Valo op_mode = hw->priv;
1256e705c121SKalle Valo op_mode->ops = &iwl_dvm_ops;
1257e705c121SKalle Valo priv = IWL_OP_MODE_GET_DVM(op_mode);
1258e705c121SKalle Valo priv->trans = trans;
1259e705c121SKalle Valo priv->dev = trans->dev;
1260e705c121SKalle Valo priv->cfg = cfg;
1261e705c121SKalle Valo priv->fw = fw;
1262e705c121SKalle Valo
12637d34a7d7SLuca Coelho switch (priv->trans->trans_cfg->device_family) {
1264e705c121SKalle Valo case IWL_DEVICE_FAMILY_1000:
1265e705c121SKalle Valo case IWL_DEVICE_FAMILY_100:
1266e705c121SKalle Valo priv->lib = &iwl_dvm_1000_cfg;
1267e705c121SKalle Valo break;
1268e705c121SKalle Valo case IWL_DEVICE_FAMILY_2000:
1269e705c121SKalle Valo priv->lib = &iwl_dvm_2000_cfg;
1270e705c121SKalle Valo break;
1271e705c121SKalle Valo case IWL_DEVICE_FAMILY_105:
1272e705c121SKalle Valo priv->lib = &iwl_dvm_105_cfg;
1273e705c121SKalle Valo break;
1274e705c121SKalle Valo case IWL_DEVICE_FAMILY_2030:
1275e705c121SKalle Valo case IWL_DEVICE_FAMILY_135:
1276e705c121SKalle Valo priv->lib = &iwl_dvm_2030_cfg;
1277e705c121SKalle Valo break;
1278e705c121SKalle Valo case IWL_DEVICE_FAMILY_5000:
1279e705c121SKalle Valo priv->lib = &iwl_dvm_5000_cfg;
1280e705c121SKalle Valo break;
1281e705c121SKalle Valo case IWL_DEVICE_FAMILY_5150:
1282e705c121SKalle Valo priv->lib = &iwl_dvm_5150_cfg;
1283e705c121SKalle Valo break;
1284e705c121SKalle Valo case IWL_DEVICE_FAMILY_6000:
1285e705c121SKalle Valo case IWL_DEVICE_FAMILY_6000i:
1286e705c121SKalle Valo priv->lib = &iwl_dvm_6000_cfg;
1287e705c121SKalle Valo break;
1288e705c121SKalle Valo case IWL_DEVICE_FAMILY_6005:
1289e705c121SKalle Valo priv->lib = &iwl_dvm_6005_cfg;
1290e705c121SKalle Valo break;
1291e705c121SKalle Valo case IWL_DEVICE_FAMILY_6050:
1292e705c121SKalle Valo case IWL_DEVICE_FAMILY_6150:
1293e705c121SKalle Valo priv->lib = &iwl_dvm_6050_cfg;
1294e705c121SKalle Valo break;
1295e705c121SKalle Valo case IWL_DEVICE_FAMILY_6030:
1296e705c121SKalle Valo priv->lib = &iwl_dvm_6030_cfg;
1297e705c121SKalle Valo break;
1298e705c121SKalle Valo default:
1299e705c121SKalle Valo break;
1300e705c121SKalle Valo }
1301e705c121SKalle Valo
1302e705c121SKalle Valo if (WARN_ON(!priv->lib))
1303e705c121SKalle Valo goto out_free_hw;
1304e705c121SKalle Valo
1305e705c121SKalle Valo /*
1306e705c121SKalle Valo * Populate the state variables that the transport layer needs
1307e705c121SKalle Valo * to know about.
1308e705c121SKalle Valo */
1309e705c121SKalle Valo trans_cfg.op_mode = op_mode;
1310e705c121SKalle Valo trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
1311e705c121SKalle Valo trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
13126c4fbcbcSEmmanuel Grumbach
13136c4fbcbcSEmmanuel Grumbach switch (iwlwifi_mod_params.amsdu_size) {
13144bdd4dfeSEmmanuel Grumbach case IWL_AMSDU_DEF:
13156c4fbcbcSEmmanuel Grumbach case IWL_AMSDU_4K:
13166c4fbcbcSEmmanuel Grumbach trans_cfg.rx_buf_size = IWL_AMSDU_4K;
13176c4fbcbcSEmmanuel Grumbach break;
13186c4fbcbcSEmmanuel Grumbach case IWL_AMSDU_8K:
13196c4fbcbcSEmmanuel Grumbach trans_cfg.rx_buf_size = IWL_AMSDU_8K;
13206c4fbcbcSEmmanuel Grumbach break;
13216c4fbcbcSEmmanuel Grumbach case IWL_AMSDU_12K:
13226c4fbcbcSEmmanuel Grumbach default:
13236c4fbcbcSEmmanuel Grumbach trans_cfg.rx_buf_size = IWL_AMSDU_4K;
13246c4fbcbcSEmmanuel Grumbach pr_err("Unsupported amsdu_size: %d\n",
13256c4fbcbcSEmmanuel Grumbach iwlwifi_mod_params.amsdu_size);
13266c4fbcbcSEmmanuel Grumbach }
13276c4fbcbcSEmmanuel Grumbach
132839bdb17eSSharon Dvir trans_cfg.command_groups = iwl_dvm_groups;
132939bdb17eSSharon Dvir trans_cfg.command_groups_size = ARRAY_SIZE(iwl_dvm_groups);
133039bdb17eSSharon Dvir
1331e705c121SKalle Valo trans_cfg.cmd_fifo = IWLAGN_CMD_FIFO_NUM;
133221cb3222SJohannes Berg trans_cfg.cb_data_offs = offsetof(struct ieee80211_tx_info,
133321cb3222SJohannes Berg driver_data[2]);
1334e705c121SKalle Valo
1335e705c121SKalle Valo WARN_ON(sizeof(priv->transport_queue_stop) * BITS_PER_BYTE <
13367d34a7d7SLuca Coelho priv->trans->trans_cfg->base_params->num_of_queues);
1337e705c121SKalle Valo
1338e705c121SKalle Valo ucode_flags = fw->ucode_capa.flags;
1339e705c121SKalle Valo
1340e705c121SKalle Valo if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) {
1341e705c121SKalle Valo priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
1342e705c121SKalle Valo trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
1343e705c121SKalle Valo } else {
1344e705c121SKalle Valo priv->sta_key_max_num = STA_KEY_MAX_NUM;
1345e705c121SKalle Valo trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
1346e705c121SKalle Valo }
1347e705c121SKalle Valo
1348e705c121SKalle Valo /* Configure transport layer */
1349e705c121SKalle Valo iwl_trans_configure(priv->trans, &trans_cfg);
1350e705c121SKalle Valo
1351e705c121SKalle Valo trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
1352e705c121SKalle Valo trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start);
135339bdb17eSSharon Dvir trans->command_groups = trans_cfg.command_groups;
135439bdb17eSSharon Dvir trans->command_groups_size = trans_cfg.command_groups_size;
1355e705c121SKalle Valo
1356e705c121SKalle Valo /* At this point both hw and priv are allocated. */
1357e705c121SKalle Valo
1358e705c121SKalle Valo SET_IEEE80211_DEV(priv->hw, priv->trans->dev);
1359e705c121SKalle Valo
1360e705c121SKalle Valo iwl_option_config(priv);
1361e705c121SKalle Valo
1362e705c121SKalle Valo IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
1363e705c121SKalle Valo
1364e705c121SKalle Valo /* bt channel inhibition enabled*/
1365e705c121SKalle Valo priv->bt_ch_announce = true;
1366e705c121SKalle Valo IWL_DEBUG_INFO(priv, "BT channel inhibition is %s\n",
1367e705c121SKalle Valo (priv->bt_ch_announce) ? "On" : "Off");
1368e705c121SKalle Valo
1369e705c121SKalle Valo /* these spin locks will be used in apm_ops.init and EEPROM access
1370e705c121SKalle Valo * we should init now
1371e705c121SKalle Valo */
1372e705c121SKalle Valo spin_lock_init(&priv->statistics.lock);
1373e705c121SKalle Valo
1374e705c121SKalle Valo /***********************
1375e705c121SKalle Valo * 2. Read REV register
1376e705c121SKalle Valo ***********************/
1377e705c121SKalle Valo IWL_INFO(priv, "Detected %s, REV=0x%X\n",
13780b295a1eSLuca Coelho priv->trans->name, priv->trans->hw_rev);
1379e705c121SKalle Valo
1380e705c121SKalle Valo if (iwl_trans_start_hw(priv->trans))
1381e705c121SKalle Valo goto out_free_hw;
1382e705c121SKalle Valo
1383e705c121SKalle Valo /* Read the EEPROM */
1384e705c121SKalle Valo if (iwl_read_eeprom(priv->trans, &priv->eeprom_blob,
1385e705c121SKalle Valo &priv->eeprom_blob_size)) {
1386e705c121SKalle Valo IWL_ERR(priv, "Unable to init EEPROM\n");
1387e705c121SKalle Valo goto out_free_hw;
1388e705c121SKalle Valo }
1389e705c121SKalle Valo
1390e705c121SKalle Valo /* Reset chip to save power until we load uCode during "up". */
1391e705c121SKalle Valo iwl_trans_stop_device(priv->trans);
1392e705c121SKalle Valo
13937d34a7d7SLuca Coelho priv->nvm_data = iwl_parse_eeprom_data(priv->trans, priv->cfg,
1394e705c121SKalle Valo priv->eeprom_blob,
1395e705c121SKalle Valo priv->eeprom_blob_size);
1396e705c121SKalle Valo if (!priv->nvm_data)
1397e705c121SKalle Valo goto out_free_eeprom_blob;
1398e705c121SKalle Valo
1399e705c121SKalle Valo if (iwl_nvm_check_version(priv->nvm_data, priv->trans))
1400e705c121SKalle Valo goto out_free_eeprom;
1401e705c121SKalle Valo
1402e705c121SKalle Valo if (iwl_eeprom_init_hw_params(priv))
1403e705c121SKalle Valo goto out_free_eeprom;
1404e705c121SKalle Valo
1405e705c121SKalle Valo /* extract MAC Address */
1406e705c121SKalle Valo memcpy(priv->addresses[0].addr, priv->nvm_data->hw_addr, ETH_ALEN);
1407e705c121SKalle Valo IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr);
1408e705c121SKalle Valo priv->hw->wiphy->addresses = priv->addresses;
1409e705c121SKalle Valo priv->hw->wiphy->n_addresses = 1;
1410e705c121SKalle Valo num_mac = priv->nvm_data->n_hw_addrs;
1411e705c121SKalle Valo if (num_mac > 1) {
1412e705c121SKalle Valo memcpy(priv->addresses[1].addr, priv->addresses[0].addr,
1413e705c121SKalle Valo ETH_ALEN);
1414e705c121SKalle Valo priv->addresses[1].addr[5]++;
1415e705c121SKalle Valo priv->hw->wiphy->n_addresses++;
1416e705c121SKalle Valo }
1417e705c121SKalle Valo
1418e705c121SKalle Valo /************************
1419e705c121SKalle Valo * 4. Setup HW constants
1420e705c121SKalle Valo ************************/
1421e705c121SKalle Valo iwl_set_hw_params(priv);
1422e705c121SKalle Valo
1423e705c121SKalle Valo if (!(priv->nvm_data->sku_cap_ipan_enable)) {
1424e705c121SKalle Valo IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN\n");
1425e705c121SKalle Valo ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
1426e705c121SKalle Valo /*
1427e705c121SKalle Valo * if not PAN, then don't support P2P -- might be a uCode
1428e705c121SKalle Valo * packaging bug or due to the eeprom check above
1429e705c121SKalle Valo */
1430e705c121SKalle Valo priv->sta_key_max_num = STA_KEY_MAX_NUM;
1431e705c121SKalle Valo trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
1432e705c121SKalle Valo
1433e705c121SKalle Valo /* Configure transport layer again*/
1434e705c121SKalle Valo iwl_trans_configure(priv->trans, &trans_cfg);
1435e705c121SKalle Valo }
1436e705c121SKalle Valo
1437e705c121SKalle Valo /*******************
1438e705c121SKalle Valo * 5. Setup priv
1439e705c121SKalle Valo *******************/
1440e705c121SKalle Valo for (i = 0; i < IWL_MAX_HW_QUEUES; i++) {
1441e705c121SKalle Valo priv->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE;
1442e705c121SKalle Valo if (i < IWLAGN_FIRST_AMPDU_QUEUE &&
1443e705c121SKalle Valo i != IWL_DEFAULT_CMD_QUEUE_NUM &&
1444e705c121SKalle Valo i != IWL_IPAN_CMD_QUEUE_NUM)
1445e705c121SKalle Valo priv->queue_to_mac80211[i] = i;
1446e705c121SKalle Valo atomic_set(&priv->queue_stop_count[i], 0);
1447e705c121SKalle Valo }
1448e705c121SKalle Valo
1449e705c121SKalle Valo if (iwl_init_drv(priv))
1450e705c121SKalle Valo goto out_free_eeprom;
1451e705c121SKalle Valo
1452e705c121SKalle Valo /* At this point both hw and priv are initialized. */
1453e705c121SKalle Valo
1454e705c121SKalle Valo /********************
1455e705c121SKalle Valo * 6. Setup services
1456e705c121SKalle Valo ********************/
1457e705c121SKalle Valo iwl_setup_deferred_work(priv);
1458e705c121SKalle Valo iwl_setup_rx_handlers(priv);
1459e705c121SKalle Valo
1460e705c121SKalle Valo iwl_power_initialize(priv);
1461e705c121SKalle Valo iwl_tt_initialize(priv);
1462e705c121SKalle Valo
1463e705c121SKalle Valo snprintf(priv->hw->wiphy->fw_version,
1464e705c121SKalle Valo sizeof(priv->hw->wiphy->fw_version),
1465c3745ee2SGregory Greenman "%.31s", fw->fw_version);
1466e705c121SKalle Valo
1467e705c121SKalle Valo priv->new_scan_threshold_behaviour =
1468e705c121SKalle Valo !!(ucode_flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
1469e705c121SKalle Valo
1470e705c121SKalle Valo priv->phy_calib_chain_noise_reset_cmd =
1471e705c121SKalle Valo fw->ucode_capa.standard_phy_calibration_size;
1472e705c121SKalle Valo priv->phy_calib_chain_noise_gain_cmd =
1473e705c121SKalle Valo fw->ucode_capa.standard_phy_calibration_size + 1;
1474e705c121SKalle Valo
1475e705c121SKalle Valo /* initialize all valid contexts */
1476e705c121SKalle Valo iwl_init_context(priv, ucode_flags);
1477e705c121SKalle Valo
1478e705c121SKalle Valo /**************************************************
1479e705c121SKalle Valo * This is still part of probe() in a sense...
1480e705c121SKalle Valo *
1481e705c121SKalle Valo * 7. Setup and register with mac80211 and debugfs
1482e705c121SKalle Valo **************************************************/
1483e705c121SKalle Valo if (iwlagn_mac_setup_register(priv, &fw->ucode_capa))
1484e705c121SKalle Valo goto out_destroy_workqueue;
1485e705c121SKalle Valo
148684caa1ddSGreg Kroah-Hartman iwl_dbgfs_register(priv, dbgfs_dir);
1487e705c121SKalle Valo
1488e705c121SKalle Valo return op_mode;
1489e705c121SKalle Valo
1490e705c121SKalle Valo out_destroy_workqueue:
1491e705c121SKalle Valo iwl_tt_exit(priv);
1492e705c121SKalle Valo iwl_cancel_deferred_work(priv);
1493e705c121SKalle Valo destroy_workqueue(priv->workqueue);
1494e705c121SKalle Valo priv->workqueue = NULL;
1495e705c121SKalle Valo iwl_uninit_drv(priv);
1496e705c121SKalle Valo out_free_eeprom_blob:
1497e705c121SKalle Valo kfree(priv->eeprom_blob);
1498e705c121SKalle Valo out_free_eeprom:
14991dad3e0aSLuca Coelho kfree(priv->nvm_data);
1500e705c121SKalle Valo out_free_hw:
1501e705c121SKalle Valo ieee80211_free_hw(priv->hw);
1502e705c121SKalle Valo out:
1503e705c121SKalle Valo op_mode = NULL;
1504e705c121SKalle Valo return op_mode;
1505e705c121SKalle Valo }
1506e705c121SKalle Valo
iwl_op_mode_dvm_stop(struct iwl_op_mode * op_mode)1507e705c121SKalle Valo static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
1508e705c121SKalle Valo {
1509e705c121SKalle Valo struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
1510e705c121SKalle Valo
1511e705c121SKalle Valo IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
1512e705c121SKalle Valo
1513e705c121SKalle Valo iwlagn_mac_unregister(priv);
1514e705c121SKalle Valo
1515e705c121SKalle Valo iwl_tt_exit(priv);
1516e705c121SKalle Valo
1517e705c121SKalle Valo kfree(priv->eeprom_blob);
15181dad3e0aSLuca Coelho kfree(priv->nvm_data);
1519e705c121SKalle Valo
1520e705c121SKalle Valo /*netif_stop_queue(dev); */
1521e705c121SKalle Valo
1522e705c121SKalle Valo /* ieee80211_unregister_hw calls iwlagn_mac_stop, which flushes
1523e705c121SKalle Valo * priv->workqueue... so we can't take down the workqueue
1524e705c121SKalle Valo * until now... */
1525e705c121SKalle Valo destroy_workqueue(priv->workqueue);
1526e705c121SKalle Valo priv->workqueue = NULL;
1527e705c121SKalle Valo
1528e705c121SKalle Valo iwl_uninit_drv(priv);
1529e705c121SKalle Valo
1530e705c121SKalle Valo dev_kfree_skb(priv->beacon_skb);
1531e705c121SKalle Valo
1532e705c121SKalle Valo iwl_trans_op_mode_leave(priv->trans);
1533e705c121SKalle Valo ieee80211_free_hw(priv->hw);
1534e705c121SKalle Valo }
1535e705c121SKalle Valo
1536e705c121SKalle Valo static const char * const desc_lookup_text[] = {
1537e705c121SKalle Valo "OK",
1538e705c121SKalle Valo "FAIL",
1539e705c121SKalle Valo "BAD_PARAM",
1540e705c121SKalle Valo "BAD_CHECKSUM",
1541e705c121SKalle Valo "NMI_INTERRUPT_WDG",
1542e705c121SKalle Valo "SYSASSERT",
1543e705c121SKalle Valo "FATAL_ERROR",
1544e705c121SKalle Valo "BAD_COMMAND",
1545e705c121SKalle Valo "HW_ERROR_TUNE_LOCK",
1546e705c121SKalle Valo "HW_ERROR_TEMPERATURE",
1547e705c121SKalle Valo "ILLEGAL_CHAN_FREQ",
1548e705c121SKalle Valo "VCC_NOT_STABLE",
1549e705c121SKalle Valo "FH_ERROR",
1550e705c121SKalle Valo "NMI_INTERRUPT_HOST",
1551e705c121SKalle Valo "NMI_INTERRUPT_ACTION_PT",
1552e705c121SKalle Valo "NMI_INTERRUPT_UNKNOWN",
1553e705c121SKalle Valo "UCODE_VERSION_MISMATCH",
1554e705c121SKalle Valo "HW_ERROR_ABS_LOCK",
1555e705c121SKalle Valo "HW_ERROR_CAL_LOCK_FAIL",
1556e705c121SKalle Valo "NMI_INTERRUPT_INST_ACTION_PT",
1557e705c121SKalle Valo "NMI_INTERRUPT_DATA_ACTION_PT",
1558e705c121SKalle Valo "NMI_TRM_HW_ER",
1559e705c121SKalle Valo "NMI_INTERRUPT_TRM",
1560e705c121SKalle Valo "NMI_INTERRUPT_BREAK_POINT",
1561e705c121SKalle Valo "DEBUG_0",
1562e705c121SKalle Valo "DEBUG_1",
1563e705c121SKalle Valo "DEBUG_2",
1564e705c121SKalle Valo "DEBUG_3",
1565e705c121SKalle Valo };
1566e705c121SKalle Valo
1567e705c121SKalle Valo static struct { char *name; u8 num; } advanced_lookup[] = {
1568e705c121SKalle Valo { "NMI_INTERRUPT_WDG", 0x34 },
1569e705c121SKalle Valo { "SYSASSERT", 0x35 },
1570e705c121SKalle Valo { "UCODE_VERSION_MISMATCH", 0x37 },
1571e705c121SKalle Valo { "BAD_COMMAND", 0x38 },
1572e705c121SKalle Valo { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C },
1573e705c121SKalle Valo { "FATAL_ERROR", 0x3D },
1574e705c121SKalle Valo { "NMI_TRM_HW_ERR", 0x46 },
1575e705c121SKalle Valo { "NMI_INTERRUPT_TRM", 0x4C },
1576e705c121SKalle Valo { "NMI_INTERRUPT_BREAK_POINT", 0x54 },
1577e705c121SKalle Valo { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C },
1578e705c121SKalle Valo { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 },
1579e705c121SKalle Valo { "NMI_INTERRUPT_HOST", 0x66 },
1580e705c121SKalle Valo { "NMI_INTERRUPT_ACTION_PT", 0x7C },
1581e705c121SKalle Valo { "NMI_INTERRUPT_UNKNOWN", 0x84 },
1582e705c121SKalle Valo { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 },
1583e705c121SKalle Valo { "ADVANCED_SYSASSERT", 0 },
1584e705c121SKalle Valo };
1585e705c121SKalle Valo
desc_lookup(u32 num)1586e705c121SKalle Valo static const char *desc_lookup(u32 num)
1587e705c121SKalle Valo {
1588e705c121SKalle Valo int i;
1589e705c121SKalle Valo int max = ARRAY_SIZE(desc_lookup_text);
1590e705c121SKalle Valo
1591e705c121SKalle Valo if (num < max)
1592e705c121SKalle Valo return desc_lookup_text[num];
1593e705c121SKalle Valo
1594e705c121SKalle Valo max = ARRAY_SIZE(advanced_lookup) - 1;
1595e705c121SKalle Valo for (i = 0; i < max; i++) {
1596e705c121SKalle Valo if (advanced_lookup[i].num == num)
1597e705c121SKalle Valo break;
1598e705c121SKalle Valo }
1599e705c121SKalle Valo return advanced_lookup[i].name;
1600e705c121SKalle Valo }
1601e705c121SKalle Valo
1602e705c121SKalle Valo #define ERROR_START_OFFSET (1 * sizeof(u32))
1603e705c121SKalle Valo #define ERROR_ELEM_SIZE (7 * sizeof(u32))
1604e705c121SKalle Valo
iwl_dump_nic_error_log(struct iwl_priv * priv)1605e705c121SKalle Valo static void iwl_dump_nic_error_log(struct iwl_priv *priv)
1606e705c121SKalle Valo {
1607e705c121SKalle Valo struct iwl_trans *trans = priv->trans;
1608e705c121SKalle Valo u32 base;
1609e705c121SKalle Valo struct iwl_error_event_table table;
1610e705c121SKalle Valo
1611e705c121SKalle Valo base = priv->device_pointers.error_event_table;
1612e705c121SKalle Valo if (priv->cur_ucode == IWL_UCODE_INIT) {
1613e705c121SKalle Valo if (!base)
1614e705c121SKalle Valo base = priv->fw->init_errlog_ptr;
1615e705c121SKalle Valo } else {
1616e705c121SKalle Valo if (!base)
1617e705c121SKalle Valo base = priv->fw->inst_errlog_ptr;
1618e705c121SKalle Valo }
1619e705c121SKalle Valo
1620e705c121SKalle Valo if (!iwlagn_hw_valid_rtc_data_addr(base)) {
1621e705c121SKalle Valo IWL_ERR(priv,
1622e705c121SKalle Valo "Not valid error log pointer 0x%08X for %s uCode\n",
1623e705c121SKalle Valo base,
1624e705c121SKalle Valo (priv->cur_ucode == IWL_UCODE_INIT)
1625e705c121SKalle Valo ? "Init" : "RT");
1626e705c121SKalle Valo return;
1627e705c121SKalle Valo }
1628e705c121SKalle Valo
1629e705c121SKalle Valo /*TODO: Update dbgfs with ISR error stats obtained below */
1630e705c121SKalle Valo iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
1631e705c121SKalle Valo
1632e705c121SKalle Valo if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
1633e705c121SKalle Valo IWL_ERR(trans, "Start IWL Error Log Dump:\n");
1634e705c121SKalle Valo IWL_ERR(trans, "Status: 0x%08lX, count: %d\n",
1635e705c121SKalle Valo priv->status, table.valid);
1636e705c121SKalle Valo }
1637e705c121SKalle Valo
1638e705c121SKalle Valo IWL_ERR(priv, "0x%08X | %-28s\n", table.error_id,
1639e705c121SKalle Valo desc_lookup(table.error_id));
1640e705c121SKalle Valo IWL_ERR(priv, "0x%08X | uPc\n", table.pc);
1641e705c121SKalle Valo IWL_ERR(priv, "0x%08X | branchlink1\n", table.blink1);
1642e705c121SKalle Valo IWL_ERR(priv, "0x%08X | branchlink2\n", table.blink2);
1643e705c121SKalle Valo IWL_ERR(priv, "0x%08X | interruptlink1\n", table.ilink1);
1644e705c121SKalle Valo IWL_ERR(priv, "0x%08X | interruptlink2\n", table.ilink2);
1645e705c121SKalle Valo IWL_ERR(priv, "0x%08X | data1\n", table.data1);
1646e705c121SKalle Valo IWL_ERR(priv, "0x%08X | data2\n", table.data2);
1647e705c121SKalle Valo IWL_ERR(priv, "0x%08X | line\n", table.line);
1648e705c121SKalle Valo IWL_ERR(priv, "0x%08X | beacon time\n", table.bcon_time);
1649e705c121SKalle Valo IWL_ERR(priv, "0x%08X | tsf low\n", table.tsf_low);
1650e705c121SKalle Valo IWL_ERR(priv, "0x%08X | tsf hi\n", table.tsf_hi);
1651e705c121SKalle Valo IWL_ERR(priv, "0x%08X | time gp1\n", table.gp1);
1652e705c121SKalle Valo IWL_ERR(priv, "0x%08X | time gp2\n", table.gp2);
1653e705c121SKalle Valo IWL_ERR(priv, "0x%08X | time gp3\n", table.gp3);
1654e705c121SKalle Valo IWL_ERR(priv, "0x%08X | uCode version\n", table.ucode_ver);
1655e705c121SKalle Valo IWL_ERR(priv, "0x%08X | hw version\n", table.hw_ver);
1656e705c121SKalle Valo IWL_ERR(priv, "0x%08X | board version\n", table.brd_ver);
1657e705c121SKalle Valo IWL_ERR(priv, "0x%08X | hcmd\n", table.hcmd);
1658e705c121SKalle Valo IWL_ERR(priv, "0x%08X | isr0\n", table.isr0);
1659e705c121SKalle Valo IWL_ERR(priv, "0x%08X | isr1\n", table.isr1);
1660e705c121SKalle Valo IWL_ERR(priv, "0x%08X | isr2\n", table.isr2);
1661e705c121SKalle Valo IWL_ERR(priv, "0x%08X | isr3\n", table.isr3);
1662e705c121SKalle Valo IWL_ERR(priv, "0x%08X | isr4\n", table.isr4);
1663e705c121SKalle Valo IWL_ERR(priv, "0x%08X | isr_pref\n", table.isr_pref);
1664e705c121SKalle Valo IWL_ERR(priv, "0x%08X | wait_event\n", table.wait_event);
1665e705c121SKalle Valo IWL_ERR(priv, "0x%08X | l2p_control\n", table.l2p_control);
1666e705c121SKalle Valo IWL_ERR(priv, "0x%08X | l2p_duration\n", table.l2p_duration);
1667e705c121SKalle Valo IWL_ERR(priv, "0x%08X | l2p_mhvalid\n", table.l2p_mhvalid);
1668e705c121SKalle Valo IWL_ERR(priv, "0x%08X | l2p_addr_match\n", table.l2p_addr_match);
1669e705c121SKalle Valo IWL_ERR(priv, "0x%08X | lmpm_pmg_sel\n", table.lmpm_pmg_sel);
1670e705c121SKalle Valo IWL_ERR(priv, "0x%08X | timestamp\n", table.u_timestamp);
1671e705c121SKalle Valo IWL_ERR(priv, "0x%08X | flow_handler\n", table.flow_handler);
1672e705c121SKalle Valo }
1673e705c121SKalle Valo
1674e705c121SKalle Valo #define EVENT_START_OFFSET (4 * sizeof(u32))
1675e705c121SKalle Valo
16767cb391ffSLee Jones /*
1677e705c121SKalle Valo * iwl_print_event_log - Dump error event log to syslog
1678e705c121SKalle Valo */
iwl_print_event_log(struct iwl_priv * priv,u32 start_idx,u32 num_events,u32 mode,int pos,char ** buf,size_t bufsz)1679e705c121SKalle Valo static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
1680e705c121SKalle Valo u32 num_events, u32 mode,
1681e705c121SKalle Valo int pos, char **buf, size_t bufsz)
1682e705c121SKalle Valo {
1683e705c121SKalle Valo u32 i;
1684e705c121SKalle Valo u32 base; /* SRAM byte address of event log header */
1685e705c121SKalle Valo u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
1686e705c121SKalle Valo u32 ptr; /* SRAM byte address of log data */
1687e705c121SKalle Valo u32 ev, time, data; /* event log data */
1688e705c121SKalle Valo
1689e705c121SKalle Valo struct iwl_trans *trans = priv->trans;
1690e705c121SKalle Valo
1691e705c121SKalle Valo if (num_events == 0)
1692e705c121SKalle Valo return pos;
1693e705c121SKalle Valo
1694e705c121SKalle Valo base = priv->device_pointers.log_event_table;
1695e705c121SKalle Valo if (priv->cur_ucode == IWL_UCODE_INIT) {
1696e705c121SKalle Valo if (!base)
1697e705c121SKalle Valo base = priv->fw->init_evtlog_ptr;
1698e705c121SKalle Valo } else {
1699e705c121SKalle Valo if (!base)
1700e705c121SKalle Valo base = priv->fw->inst_evtlog_ptr;
1701e705c121SKalle Valo }
1702e705c121SKalle Valo
1703e705c121SKalle Valo if (mode == 0)
1704e705c121SKalle Valo event_size = 2 * sizeof(u32);
1705e705c121SKalle Valo else
1706e705c121SKalle Valo event_size = 3 * sizeof(u32);
1707e705c121SKalle Valo
1708e705c121SKalle Valo ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
1709e705c121SKalle Valo
1710e705c121SKalle Valo /* Make sure device is powered up for SRAM reads */
17111ed08f6fSJohannes Berg if (!iwl_trans_grab_nic_access(trans))
1712e705c121SKalle Valo return pos;
1713e705c121SKalle Valo
1714e705c121SKalle Valo /* Set starting address; reads will auto-increment */
1715e705c121SKalle Valo iwl_write32(trans, HBUS_TARG_MEM_RADDR, ptr);
1716e705c121SKalle Valo
1717e705c121SKalle Valo /* "time" is actually "data" for mode 0 (no timestamp).
1718e705c121SKalle Valo * place event id # at far right for easier visual parsing. */
1719e705c121SKalle Valo for (i = 0; i < num_events; i++) {
1720e705c121SKalle Valo ev = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
1721e705c121SKalle Valo time = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
1722e705c121SKalle Valo if (mode == 0) {
1723e705c121SKalle Valo /* data, ev */
1724e705c121SKalle Valo if (bufsz) {
1725e705c121SKalle Valo pos += scnprintf(*buf + pos, bufsz - pos,
1726e705c121SKalle Valo "EVT_LOG:0x%08x:%04u\n",
1727e705c121SKalle Valo time, ev);
1728e705c121SKalle Valo } else {
1729e705c121SKalle Valo trace_iwlwifi_dev_ucode_event(trans->dev, 0,
1730e705c121SKalle Valo time, ev);
1731e705c121SKalle Valo IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n",
1732e705c121SKalle Valo time, ev);
1733e705c121SKalle Valo }
1734e705c121SKalle Valo } else {
1735e705c121SKalle Valo data = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
1736e705c121SKalle Valo if (bufsz) {
1737e705c121SKalle Valo pos += scnprintf(*buf + pos, bufsz - pos,
1738e705c121SKalle Valo "EVT_LOGT:%010u:0x%08x:%04u\n",
1739e705c121SKalle Valo time, data, ev);
1740e705c121SKalle Valo } else {
1741e705c121SKalle Valo IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
1742e705c121SKalle Valo time, data, ev);
1743e705c121SKalle Valo trace_iwlwifi_dev_ucode_event(trans->dev, time,
1744e705c121SKalle Valo data, ev);
1745e705c121SKalle Valo }
1746e705c121SKalle Valo }
1747e705c121SKalle Valo }
1748e705c121SKalle Valo
1749e705c121SKalle Valo /* Allow device to power down */
17501ed08f6fSJohannes Berg iwl_trans_release_nic_access(trans);
1751e705c121SKalle Valo return pos;
1752e705c121SKalle Valo }
1753e705c121SKalle Valo
17547cb391ffSLee Jones /*
1755e705c121SKalle Valo * iwl_print_last_event_logs - Dump the newest # of event log to syslog
1756e705c121SKalle Valo */
iwl_print_last_event_logs(struct iwl_priv * priv,u32 capacity,u32 num_wraps,u32 next_entry,u32 size,u32 mode,int pos,char ** buf,size_t bufsz)1757e705c121SKalle Valo static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
1758e705c121SKalle Valo u32 num_wraps, u32 next_entry,
1759e705c121SKalle Valo u32 size, u32 mode,
1760e705c121SKalle Valo int pos, char **buf, size_t bufsz)
1761e705c121SKalle Valo {
1762e705c121SKalle Valo /*
1763e705c121SKalle Valo * display the newest DEFAULT_LOG_ENTRIES entries
1764e705c121SKalle Valo * i.e the entries just before the next ont that uCode would fill.
1765e705c121SKalle Valo */
1766e705c121SKalle Valo if (num_wraps) {
1767e705c121SKalle Valo if (next_entry < size) {
1768e705c121SKalle Valo pos = iwl_print_event_log(priv,
1769e705c121SKalle Valo capacity - (size - next_entry),
1770e705c121SKalle Valo size - next_entry, mode,
1771e705c121SKalle Valo pos, buf, bufsz);
1772e705c121SKalle Valo pos = iwl_print_event_log(priv, 0,
1773e705c121SKalle Valo next_entry, mode,
1774e705c121SKalle Valo pos, buf, bufsz);
1775e705c121SKalle Valo } else
1776e705c121SKalle Valo pos = iwl_print_event_log(priv, next_entry - size,
1777e705c121SKalle Valo size, mode, pos, buf, bufsz);
1778e705c121SKalle Valo } else {
1779e705c121SKalle Valo if (next_entry < size) {
1780e705c121SKalle Valo pos = iwl_print_event_log(priv, 0, next_entry,
1781e705c121SKalle Valo mode, pos, buf, bufsz);
1782e705c121SKalle Valo } else {
1783e705c121SKalle Valo pos = iwl_print_event_log(priv, next_entry - size,
1784e705c121SKalle Valo size, mode, pos, buf, bufsz);
1785e705c121SKalle Valo }
1786e705c121SKalle Valo }
1787e705c121SKalle Valo return pos;
1788e705c121SKalle Valo }
1789e705c121SKalle Valo
1790e705c121SKalle Valo #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20)
1791e705c121SKalle Valo
iwl_dump_nic_event_log(struct iwl_priv * priv,bool full_log,char ** buf)1792e705c121SKalle Valo int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
1793e705c121SKalle Valo char **buf)
1794e705c121SKalle Valo {
1795e705c121SKalle Valo u32 base; /* SRAM byte address of event log header */
1796e705c121SKalle Valo u32 capacity; /* event log capacity in # entries */
1797e705c121SKalle Valo u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
1798e705c121SKalle Valo u32 num_wraps; /* # times uCode wrapped to top of log */
1799e705c121SKalle Valo u32 next_entry; /* index of next entry to be written by uCode */
1800e705c121SKalle Valo u32 size; /* # entries that we'll print */
1801e705c121SKalle Valo u32 logsize;
1802e705c121SKalle Valo int pos = 0;
1803e705c121SKalle Valo size_t bufsz = 0;
1804e705c121SKalle Valo struct iwl_trans *trans = priv->trans;
1805e705c121SKalle Valo
1806e705c121SKalle Valo base = priv->device_pointers.log_event_table;
1807e705c121SKalle Valo if (priv->cur_ucode == IWL_UCODE_INIT) {
1808e705c121SKalle Valo logsize = priv->fw->init_evtlog_size;
1809e705c121SKalle Valo if (!base)
1810e705c121SKalle Valo base = priv->fw->init_evtlog_ptr;
1811e705c121SKalle Valo } else {
1812e705c121SKalle Valo logsize = priv->fw->inst_evtlog_size;
1813e705c121SKalle Valo if (!base)
1814e705c121SKalle Valo base = priv->fw->inst_evtlog_ptr;
1815e705c121SKalle Valo }
1816e705c121SKalle Valo
1817e705c121SKalle Valo if (!iwlagn_hw_valid_rtc_data_addr(base)) {
1818e705c121SKalle Valo IWL_ERR(priv,
1819e705c121SKalle Valo "Invalid event log pointer 0x%08X for %s uCode\n",
1820e705c121SKalle Valo base,
1821e705c121SKalle Valo (priv->cur_ucode == IWL_UCODE_INIT)
1822e705c121SKalle Valo ? "Init" : "RT");
1823e705c121SKalle Valo return -EINVAL;
1824e705c121SKalle Valo }
1825e705c121SKalle Valo
1826e705c121SKalle Valo /* event log header */
1827e705c121SKalle Valo capacity = iwl_trans_read_mem32(trans, base);
1828e705c121SKalle Valo mode = iwl_trans_read_mem32(trans, base + (1 * sizeof(u32)));
1829e705c121SKalle Valo num_wraps = iwl_trans_read_mem32(trans, base + (2 * sizeof(u32)));
1830e705c121SKalle Valo next_entry = iwl_trans_read_mem32(trans, base + (3 * sizeof(u32)));
1831e705c121SKalle Valo
1832e705c121SKalle Valo if (capacity > logsize) {
1833e705c121SKalle Valo IWL_ERR(priv, "Log capacity %d is bogus, limit to %d "
1834e705c121SKalle Valo "entries\n", capacity, logsize);
1835e705c121SKalle Valo capacity = logsize;
1836e705c121SKalle Valo }
1837e705c121SKalle Valo
1838e705c121SKalle Valo if (next_entry > logsize) {
1839e705c121SKalle Valo IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
1840e705c121SKalle Valo next_entry, logsize);
1841e705c121SKalle Valo next_entry = logsize;
1842e705c121SKalle Valo }
1843e705c121SKalle Valo
1844e705c121SKalle Valo size = num_wraps ? capacity : next_entry;
1845e705c121SKalle Valo
1846e705c121SKalle Valo /* bail out if nothing in log */
1847e705c121SKalle Valo if (size == 0) {
1848e705c121SKalle Valo IWL_ERR(trans, "Start IWL Event Log Dump: nothing in log\n");
1849e705c121SKalle Valo return pos;
1850e705c121SKalle Valo }
1851e705c121SKalle Valo
1852ec4156a9SSara Sharon if (!(iwl_have_debug_level(IWL_DL_FW)) && !full_log)
1853e705c121SKalle Valo size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
1854e705c121SKalle Valo ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
1855e705c121SKalle Valo IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n",
1856e705c121SKalle Valo size);
1857e705c121SKalle Valo
1858e705c121SKalle Valo #ifdef CONFIG_IWLWIFI_DEBUG
1859e705c121SKalle Valo if (buf) {
1860e705c121SKalle Valo if (full_log)
1861e705c121SKalle Valo bufsz = capacity * 48;
1862e705c121SKalle Valo else
1863e705c121SKalle Valo bufsz = size * 48;
1864e705c121SKalle Valo *buf = kmalloc(bufsz, GFP_KERNEL);
1865e705c121SKalle Valo if (!*buf)
1866e705c121SKalle Valo return -ENOMEM;
1867e705c121SKalle Valo }
1868ec4156a9SSara Sharon if (iwl_have_debug_level(IWL_DL_FW) || full_log) {
1869e705c121SKalle Valo /*
1870e705c121SKalle Valo * if uCode has wrapped back to top of log,
1871e705c121SKalle Valo * start at the oldest entry,
1872e705c121SKalle Valo * i.e the next one that uCode would fill.
1873e705c121SKalle Valo */
1874e705c121SKalle Valo if (num_wraps)
1875e705c121SKalle Valo pos = iwl_print_event_log(priv, next_entry,
1876e705c121SKalle Valo capacity - next_entry, mode,
1877e705c121SKalle Valo pos, buf, bufsz);
1878e705c121SKalle Valo /* (then/else) start at top of log */
1879e705c121SKalle Valo pos = iwl_print_event_log(priv, 0,
1880e705c121SKalle Valo next_entry, mode, pos, buf, bufsz);
1881e705c121SKalle Valo } else
1882e705c121SKalle Valo pos = iwl_print_last_event_logs(priv, capacity, num_wraps,
1883e705c121SKalle Valo next_entry, size, mode,
1884e705c121SKalle Valo pos, buf, bufsz);
1885e705c121SKalle Valo #else
1886e705c121SKalle Valo pos = iwl_print_last_event_logs(priv, capacity, num_wraps,
1887e705c121SKalle Valo next_entry, size, mode,
1888e705c121SKalle Valo pos, buf, bufsz);
1889e705c121SKalle Valo #endif
1890e705c121SKalle Valo return pos;
1891e705c121SKalle Valo }
1892e705c121SKalle Valo
iwlagn_fw_error(struct iwl_priv * priv,bool ondemand)1893e705c121SKalle Valo static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
1894e705c121SKalle Valo {
1895e705c121SKalle Valo unsigned int reload_msec;
1896e705c121SKalle Valo unsigned long reload_jiffies;
1897e705c121SKalle Valo
1898ec4156a9SSara Sharon if (iwl_have_debug_level(IWL_DL_FW))
1899e705c121SKalle Valo iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS);
1900e705c121SKalle Valo
1901e705c121SKalle Valo /* uCode is no longer loaded. */
1902e705c121SKalle Valo priv->ucode_loaded = false;
1903e705c121SKalle Valo
1904e705c121SKalle Valo /* Set the FW error flag -- cleared on iwl_down */
1905e705c121SKalle Valo set_bit(STATUS_FW_ERROR, &priv->status);
1906e705c121SKalle Valo
1907e705c121SKalle Valo iwl_abort_notification_waits(&priv->notif_wait);
1908e705c121SKalle Valo
1909e705c121SKalle Valo /* Keep the restart process from trying to send host
1910e705c121SKalle Valo * commands by clearing the ready bit */
1911e705c121SKalle Valo clear_bit(STATUS_READY, &priv->status);
1912e705c121SKalle Valo
1913e705c121SKalle Valo if (!ondemand) {
1914e705c121SKalle Valo /*
1915e705c121SKalle Valo * If firmware keep reloading, then it indicate something
1916e705c121SKalle Valo * serious wrong and firmware having problem to recover
1917e705c121SKalle Valo * from it. Instead of keep trying which will fill the syslog
1918e705c121SKalle Valo * and hang the system, let's just stop it
1919e705c121SKalle Valo */
1920e705c121SKalle Valo reload_jiffies = jiffies;
1921e705c121SKalle Valo reload_msec = jiffies_to_msecs((long) reload_jiffies -
1922e705c121SKalle Valo (long) priv->reload_jiffies);
1923e705c121SKalle Valo priv->reload_jiffies = reload_jiffies;
1924e705c121SKalle Valo if (reload_msec <= IWL_MIN_RELOAD_DURATION) {
1925e705c121SKalle Valo priv->reload_count++;
1926e705c121SKalle Valo if (priv->reload_count >= IWL_MAX_CONTINUE_RELOAD_CNT) {
1927e705c121SKalle Valo IWL_ERR(priv, "BUG_ON, Stop restarting\n");
1928e705c121SKalle Valo return;
1929e705c121SKalle Valo }
1930e705c121SKalle Valo } else
1931e705c121SKalle Valo priv->reload_count = 0;
1932e705c121SKalle Valo }
1933e705c121SKalle Valo
1934e705c121SKalle Valo if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
19353b37f4c9SJohannes Berg if (iwlwifi_mod_params.fw_restart) {
1936ec4156a9SSara Sharon IWL_DEBUG_FW(priv,
1937e705c121SKalle Valo "Restarting adapter due to uCode error.\n");
1938e705c121SKalle Valo queue_work(priv->workqueue, &priv->restart);
1939e705c121SKalle Valo } else
1940ec4156a9SSara Sharon IWL_DEBUG_FW(priv,
1941e705c121SKalle Valo "Detected FW error, but not restarting\n");
1942e705c121SKalle Valo }
1943e705c121SKalle Valo }
1944e705c121SKalle Valo
iwl_nic_error(struct iwl_op_mode * op_mode,bool sync)1945b8221b0fSJohannes Berg static void iwl_nic_error(struct iwl_op_mode *op_mode, bool sync)
1946e705c121SKalle Valo {
1947e705c121SKalle Valo struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
1948e705c121SKalle Valo
1949e705c121SKalle Valo IWL_ERR(priv, "Loaded firmware version: %s\n",
1950e705c121SKalle Valo priv->fw->fw_version);
1951e705c121SKalle Valo
1952e705c121SKalle Valo iwl_dump_nic_error_log(priv);
1953e705c121SKalle Valo iwl_dump_nic_event_log(priv, false, NULL);
1954e705c121SKalle Valo
1955e705c121SKalle Valo iwlagn_fw_error(priv, false);
1956e705c121SKalle Valo }
1957e705c121SKalle Valo
iwl_cmd_queue_full(struct iwl_op_mode * op_mode)1958e705c121SKalle Valo static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode)
1959e705c121SKalle Valo {
1960e705c121SKalle Valo struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
1961e705c121SKalle Valo
1962e705c121SKalle Valo if (!iwl_check_for_ct_kill(priv)) {
1963e705c121SKalle Valo IWL_ERR(priv, "Restarting adapter queue is full\n");
1964e705c121SKalle Valo iwlagn_fw_error(priv, false);
1965e705c121SKalle Valo }
1966e705c121SKalle Valo }
1967e705c121SKalle Valo
1968e705c121SKalle Valo #define EEPROM_RF_CONFIG_TYPE_MAX 0x3
1969e705c121SKalle Valo
iwl_nic_config(struct iwl_op_mode * op_mode)1970e705c121SKalle Valo static void iwl_nic_config(struct iwl_op_mode *op_mode)
1971e705c121SKalle Valo {
1972e705c121SKalle Valo struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
1973e705c121SKalle Valo
1974e705c121SKalle Valo /* SKU Control */
1975e705c121SKalle Valo iwl_trans_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
197655c6d8f8SMike Golant CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP_DASH,
197755c6d8f8SMike Golant CSR_HW_REV_STEP_DASH(priv->trans->hw_rev));
1978e705c121SKalle Valo
1979e705c121SKalle Valo /* write radio config values to register */
1980e705c121SKalle Valo if (priv->nvm_data->radio_cfg_type <= EEPROM_RF_CONFIG_TYPE_MAX) {
1981e705c121SKalle Valo u32 reg_val =
1982e705c121SKalle Valo priv->nvm_data->radio_cfg_type <<
1983e705c121SKalle Valo CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE |
1984e705c121SKalle Valo priv->nvm_data->radio_cfg_step <<
1985e705c121SKalle Valo CSR_HW_IF_CONFIG_REG_POS_PHY_STEP |
1986e705c121SKalle Valo priv->nvm_data->radio_cfg_dash <<
1987e705c121SKalle Valo CSR_HW_IF_CONFIG_REG_POS_PHY_DASH;
1988e705c121SKalle Valo
1989e705c121SKalle Valo iwl_trans_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
1990e705c121SKalle Valo CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE |
1991e705c121SKalle Valo CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP |
1992e705c121SKalle Valo CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH,
1993e705c121SKalle Valo reg_val);
1994e705c121SKalle Valo
1995e705c121SKalle Valo IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n",
1996e705c121SKalle Valo priv->nvm_data->radio_cfg_type,
1997e705c121SKalle Valo priv->nvm_data->radio_cfg_step,
1998e705c121SKalle Valo priv->nvm_data->radio_cfg_dash);
1999e705c121SKalle Valo } else {
2000e705c121SKalle Valo WARN_ON(1);
2001e705c121SKalle Valo }
2002e705c121SKalle Valo
2003e705c121SKalle Valo /* set CSR_HW_CONFIG_REG for uCode use */
2004e705c121SKalle Valo iwl_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG,
2005e705c121SKalle Valo CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
2006e705c121SKalle Valo CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
2007e705c121SKalle Valo
2008e705c121SKalle Valo /* W/A : NIC is stuck in a reset state after Early PCIe power off
2009e705c121SKalle Valo * (PCIe power is lost before PERST# is asserted),
2010e705c121SKalle Valo * causing ME FW to lose ownership and not being able to obtain it back.
2011e705c121SKalle Valo */
2012e705c121SKalle Valo iwl_set_bits_mask_prph(priv->trans, APMG_PS_CTRL_REG,
2013e705c121SKalle Valo APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
2014e705c121SKalle Valo ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
2015e705c121SKalle Valo
2016e705c121SKalle Valo if (priv->lib->nic_config)
2017e705c121SKalle Valo priv->lib->nic_config(priv);
2018e705c121SKalle Valo }
2019e705c121SKalle Valo
iwl_wimax_active(struct iwl_op_mode * op_mode)2020e705c121SKalle Valo static void iwl_wimax_active(struct iwl_op_mode *op_mode)
2021e705c121SKalle Valo {
2022e705c121SKalle Valo struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
2023e705c121SKalle Valo
2024e705c121SKalle Valo clear_bit(STATUS_READY, &priv->status);
2025e705c121SKalle Valo IWL_ERR(priv, "RF is used by WiMAX\n");
2026e705c121SKalle Valo }
2027e705c121SKalle Valo
iwl_stop_sw_queue(struct iwl_op_mode * op_mode,int queue)2028e705c121SKalle Valo static void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue)
2029e705c121SKalle Valo {
2030e705c121SKalle Valo struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
2031e705c121SKalle Valo int mq = priv->queue_to_mac80211[queue];
2032e705c121SKalle Valo
2033e705c121SKalle Valo if (WARN_ON_ONCE(mq == IWL_INVALID_MAC80211_QUEUE))
2034e705c121SKalle Valo return;
2035e705c121SKalle Valo
2036e705c121SKalle Valo if (atomic_inc_return(&priv->queue_stop_count[mq]) > 1) {
2037e705c121SKalle Valo IWL_DEBUG_TX_QUEUES(priv,
2038e705c121SKalle Valo "queue %d (mac80211 %d) already stopped\n",
2039e705c121SKalle Valo queue, mq);
2040e705c121SKalle Valo return;
2041e705c121SKalle Valo }
2042e705c121SKalle Valo
2043e705c121SKalle Valo set_bit(mq, &priv->transport_queue_stop);
2044e705c121SKalle Valo ieee80211_stop_queue(priv->hw, mq);
2045e705c121SKalle Valo }
2046e705c121SKalle Valo
iwl_wake_sw_queue(struct iwl_op_mode * op_mode,int queue)2047e705c121SKalle Valo static void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue)
2048e705c121SKalle Valo {
2049e705c121SKalle Valo struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
2050e705c121SKalle Valo int mq = priv->queue_to_mac80211[queue];
2051e705c121SKalle Valo
2052e705c121SKalle Valo if (WARN_ON_ONCE(mq == IWL_INVALID_MAC80211_QUEUE))
2053e705c121SKalle Valo return;
2054e705c121SKalle Valo
2055e705c121SKalle Valo if (atomic_dec_return(&priv->queue_stop_count[mq]) > 0) {
2056e705c121SKalle Valo IWL_DEBUG_TX_QUEUES(priv,
2057e705c121SKalle Valo "queue %d (mac80211 %d) already awake\n",
2058e705c121SKalle Valo queue, mq);
2059e705c121SKalle Valo return;
2060e705c121SKalle Valo }
2061e705c121SKalle Valo
2062e705c121SKalle Valo clear_bit(mq, &priv->transport_queue_stop);
2063e705c121SKalle Valo
2064e705c121SKalle Valo if (!priv->passive_no_rx)
2065e705c121SKalle Valo ieee80211_wake_queue(priv->hw, mq);
2066e705c121SKalle Valo }
2067e705c121SKalle Valo
iwlagn_lift_passive_no_rx(struct iwl_priv * priv)2068e705c121SKalle Valo void iwlagn_lift_passive_no_rx(struct iwl_priv *priv)
2069e705c121SKalle Valo {
2070e705c121SKalle Valo int mq;
2071e705c121SKalle Valo
2072e705c121SKalle Valo if (!priv->passive_no_rx)
2073e705c121SKalle Valo return;
2074e705c121SKalle Valo
2075e705c121SKalle Valo for (mq = 0; mq < IWLAGN_FIRST_AMPDU_QUEUE; mq++) {
2076e705c121SKalle Valo if (!test_bit(mq, &priv->transport_queue_stop)) {
2077e705c121SKalle Valo IWL_DEBUG_TX_QUEUES(priv, "Wake queue %d\n", mq);
2078e705c121SKalle Valo ieee80211_wake_queue(priv->hw, mq);
2079e705c121SKalle Valo } else {
2080e705c121SKalle Valo IWL_DEBUG_TX_QUEUES(priv, "Don't wake queue %d\n", mq);
2081e705c121SKalle Valo }
2082e705c121SKalle Valo }
2083e705c121SKalle Valo
2084e705c121SKalle Valo priv->passive_no_rx = false;
2085e705c121SKalle Valo }
2086e705c121SKalle Valo
iwl_free_skb(struct iwl_op_mode * op_mode,struct sk_buff * skb)2087e705c121SKalle Valo static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
2088e705c121SKalle Valo {
2089e705c121SKalle Valo struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
2090e705c121SKalle Valo struct ieee80211_tx_info *info;
2091e705c121SKalle Valo
2092e705c121SKalle Valo info = IEEE80211_SKB_CB(skb);
2093e705c121SKalle Valo iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]);
2094e705c121SKalle Valo ieee80211_free_txskb(priv->hw, skb);
2095e705c121SKalle Valo }
2096e705c121SKalle Valo
iwl_set_hw_rfkill_state(struct iwl_op_mode * op_mode,bool state)2097e705c121SKalle Valo static bool iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
2098e705c121SKalle Valo {
2099e705c121SKalle Valo struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
2100e705c121SKalle Valo
2101e705c121SKalle Valo if (state)
2102e705c121SKalle Valo set_bit(STATUS_RF_KILL_HW, &priv->status);
2103e705c121SKalle Valo else
2104e705c121SKalle Valo clear_bit(STATUS_RF_KILL_HW, &priv->status);
2105e705c121SKalle Valo
2106e705c121SKalle Valo wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
2107e705c121SKalle Valo
2108e705c121SKalle Valo return false;
2109e705c121SKalle Valo }
2110e705c121SKalle Valo
2111e705c121SKalle Valo static const struct iwl_op_mode_ops iwl_dvm_ops = {
2112e705c121SKalle Valo .start = iwl_op_mode_dvm_start,
2113e705c121SKalle Valo .stop = iwl_op_mode_dvm_stop,
2114e705c121SKalle Valo .rx = iwl_rx_dispatch,
2115e705c121SKalle Valo .queue_full = iwl_stop_sw_queue,
2116e705c121SKalle Valo .queue_not_full = iwl_wake_sw_queue,
2117e705c121SKalle Valo .hw_rf_kill = iwl_set_hw_rfkill_state,
2118e705c121SKalle Valo .free_skb = iwl_free_skb,
2119e705c121SKalle Valo .nic_error = iwl_nic_error,
2120e705c121SKalle Valo .cmd_queue_full = iwl_cmd_queue_full,
2121e705c121SKalle Valo .nic_config = iwl_nic_config,
2122e705c121SKalle Valo .wimax_active = iwl_wimax_active,
2123e705c121SKalle Valo };
2124e705c121SKalle Valo
2125e705c121SKalle Valo /*****************************************************************************
2126e705c121SKalle Valo *
2127e705c121SKalle Valo * driver and module entry point
2128e705c121SKalle Valo *
2129e705c121SKalle Valo *****************************************************************************/
iwl_init(void)2130e705c121SKalle Valo static int __init iwl_init(void)
2131e705c121SKalle Valo {
2132e705c121SKalle Valo
2133e705c121SKalle Valo int ret;
2134e705c121SKalle Valo
2135e705c121SKalle Valo ret = iwlagn_rate_control_register();
2136e705c121SKalle Valo if (ret) {
2137e705c121SKalle Valo pr_err("Unable to register rate control algorithm: %d\n", ret);
2138e705c121SKalle Valo return ret;
2139e705c121SKalle Valo }
2140e705c121SKalle Valo
2141e705c121SKalle Valo ret = iwl_opmode_register("iwldvm", &iwl_dvm_ops);
2142e705c121SKalle Valo if (ret) {
2143e705c121SKalle Valo pr_err("Unable to register op_mode: %d\n", ret);
2144e705c121SKalle Valo iwlagn_rate_control_unregister();
2145e705c121SKalle Valo }
2146e705c121SKalle Valo
2147e705c121SKalle Valo return ret;
2148e705c121SKalle Valo }
2149e705c121SKalle Valo module_init(iwl_init);
2150e705c121SKalle Valo
iwl_exit(void)2151e705c121SKalle Valo static void __exit iwl_exit(void)
2152e705c121SKalle Valo {
2153e705c121SKalle Valo iwl_opmode_deregister("iwldvm");
2154e705c121SKalle Valo iwlagn_rate_control_unregister();
2155e705c121SKalle Valo }
2156e705c121SKalle Valo module_exit(iwl_exit);
2157