diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/dvm/lib.c')
| -rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/lib.c | 75 |
1 files changed, 42 insertions, 33 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index 6ff46605ad4..2191621d69c 100644 --- a/drivers/net/wireless/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -19,7 +19,7 @@ * USA * * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. + * in the file called COPYING. * * Contact Information: * Intel Linux Wireless <ilw@linux.intel.com> @@ -29,7 +29,6 @@ #include <linux/etherdevice.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/sched.h> #include <net/mac80211.h> @@ -82,7 +81,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) else tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; - return iwl_dvm_send_cmd_pdu(priv, tx_ant_cfg_cmd, CMD_SYNC, + return iwl_dvm_send_cmd_pdu(priv, tx_ant_cfg_cmd, 0, sizeof(tx_power_cmd), &tx_power_cmd); } @@ -136,13 +135,12 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, * 1. acquire mutex before calling * 2. make sure rf is on and not in exit state */ -int iwlagn_txfifo_flush(struct iwl_priv *priv) +int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk) { struct iwl_txfifo_flush_cmd flush_cmd; struct iwl_host_cmd cmd = { .id = REPLY_TXFIFO_FLUSH, .len = { sizeof(struct iwl_txfifo_flush_cmd), }, - .flags = CMD_SYNC, .data = { &flush_cmd, }, }; @@ -162,6 +160,9 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv) if (priv->nvm_data->sku_cap_11n_enable) flush_cmd.queue_control |= IWL_AGG_TX_QUEUE_MSK; + if (scd_q_msk) + flush_cmd.queue_control = cpu_to_le32(scd_q_msk); + IWL_DEBUG_INFO(priv, "queue control: 0x%x\n", flush_cmd.queue_control); flush_cmd.flush_control = cpu_to_le16(IWL_DROP_ALL); @@ -173,12 +174,12 @@ void iwlagn_dev_txfifo_flush(struct iwl_priv *priv) { mutex_lock(&priv->mutex); ieee80211_stop_queues(priv->hw); - if (iwlagn_txfifo_flush(priv)) { + if (iwlagn_txfifo_flush(priv, 0)) { IWL_ERR(priv, "flush request fail\n"); goto done; } IWL_DEBUG_INFO(priv, "wait transmit/flush all frames\n"); - iwl_trans_wait_tx_queue_empty(priv->trans); + iwl_trans_wait_tx_queue_empty(priv->trans, 0xffffffff); done: ieee80211_wake_queues(priv->hw); mutex_unlock(&priv->mutex); @@ -251,23 +252,23 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) != sizeof(basic.bt3_lookup_table)); - if (priv->cfg->bt_params) { + if (priv->lib->bt_params) { /* * newer generation of devices (2000 series and newer) * use the version 2 of the bt command * we need to make sure sending the host command * with correct data structure to avoid uCode assert */ - if (priv->cfg->bt_params->bt_session_2) { + if (priv->lib->bt_params->bt_session_2) { bt_cmd_v2.prio_boost = cpu_to_le32( - priv->cfg->bt_params->bt_prio_boost); + priv->lib->bt_params->bt_prio_boost); bt_cmd_v2.tx_prio_boost = 0; bt_cmd_v2.rx_prio_boost = 0; } else { /* older version only has 8 bits */ - WARN_ON(priv->cfg->bt_params->bt_prio_boost & ~0xFF); + WARN_ON(priv->lib->bt_params->bt_prio_boost & ~0xFF); bt_cmd_v1.prio_boost = - priv->cfg->bt_params->bt_prio_boost; + priv->lib->bt_params->bt_prio_boost; bt_cmd_v1.tx_prio_boost = 0; bt_cmd_v1.rx_prio_boost = 0; } @@ -327,16 +328,16 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) priv->bt_full_concurrent ? "full concurrency" : "3-wire"); - if (priv->cfg->bt_params->bt_session_2) { + if (priv->lib->bt_params->bt_session_2) { memcpy(&bt_cmd_v2.basic, &basic, sizeof(basic)); ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, - CMD_SYNC, sizeof(bt_cmd_v2), &bt_cmd_v2); + 0, sizeof(bt_cmd_v2), &bt_cmd_v2); } else { memcpy(&bt_cmd_v1.basic, &basic, sizeof(basic)); ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG, - CMD_SYNC, sizeof(bt_cmd_v1), &bt_cmd_v1); + 0, sizeof(bt_cmd_v1), &bt_cmd_v1); } if (ret) IWL_ERR(priv, "failed to send BT Coex Config\n"); @@ -755,8 +756,8 @@ static bool is_single_rx_stream(struct iwl_priv *priv) */ static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) { - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist && + if (priv->lib->bt_params && + priv->lib->bt_params->advanced_bt_coexist && (priv->bt_full_concurrent || priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { /* @@ -827,8 +828,8 @@ void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) else active_chains = priv->nvm_data->valid_rx_ant; - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist && + if (priv->lib->bt_params && + priv->lib->bt_params->advanced_bt_coexist && (priv->bt_full_concurrent || priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { /* @@ -1042,7 +1043,6 @@ int iwlagn_send_patterns(struct iwl_priv *priv, struct iwl_host_cmd cmd = { .id = REPLY_WOWLAN_PATTERNS, .dataflags[0] = IWL_HCMD_DFL_NOCOPY, - .flags = CMD_SYNC, }; int i, err; @@ -1084,7 +1084,14 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan) struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; struct iwlagn_wowlan_kek_kck_material_cmd kek_kck_cmd; struct iwlagn_wowlan_tkip_params_cmd tkip_cmd = {}; - struct iwlagn_d3_config_cmd d3_cfg_cmd = {}; + struct iwlagn_d3_config_cmd d3_cfg_cmd = { + /* + * Program the minimum sleep time to 10 seconds, as many + * platforms have issues processing a wakeup signal while + * still being in the process of suspending. + */ + .min_sleep_time = cpu_to_le32(10 * 1000 * 1000), + }; struct wowlan_key_data key_data = { .ctx = ctx, .bssid = ctx->active.bssid_addr, @@ -1192,7 +1199,6 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan) if (key_data.use_rsc_tsc) { struct iwl_host_cmd rsc_tsc_cmd = { .id = REPLY_WOWLAN_TSC_RSC_PARAMS, - .flags = CMD_SYNC, .data[0] = key_data.rsc_tsc, .dataflags[0] = IWL_HCMD_DFL_NOCOPY, .len[0] = sizeof(*key_data.rsc_tsc), @@ -1206,7 +1212,7 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan) if (key_data.use_tkip) { ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WOWLAN_TKIP_PARAMS, - CMD_SYNC, sizeof(tkip_cmd), + 0, sizeof(tkip_cmd), &tkip_cmd); if (ret) goto out; @@ -1222,20 +1228,20 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan) ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WOWLAN_KEK_KCK_MATERIAL, - CMD_SYNC, sizeof(kek_kck_cmd), + 0, sizeof(kek_kck_cmd), &kek_kck_cmd); if (ret) goto out; } } - ret = iwl_dvm_send_cmd_pdu(priv, REPLY_D3_CONFIG, CMD_SYNC, + ret = iwl_dvm_send_cmd_pdu(priv, REPLY_D3_CONFIG, 0, sizeof(d3_cfg_cmd), &d3_cfg_cmd); if (ret) goto out; ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WOWLAN_WAKEUP_FILTER, - CMD_SYNC, sizeof(wakeup_filter_cmd), + 0, sizeof(wakeup_filter_cmd), &wakeup_filter_cmd); if (ret) goto out; @@ -1262,6 +1268,15 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) } /* + * This can happen upon FW ASSERT: we clear the STATUS_FW_ERROR flag + * in iwl_down but cancel the workers only later. + */ + if (!priv->ucode_loaded) { + IWL_ERR(priv, "Fw not loaded - dropping CMD: %x\n", cmd->id); + return -EIO; + } + + /* * Synchronous commands from this op-mode must hold * the mutex, this ensures we don't try to send two * (or more) synchronous commands at a time. @@ -1269,12 +1284,6 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) if (!(cmd->flags & CMD_ASYNC)) lockdep_assert_held(&priv->mutex); - if (priv->ucode_owner == IWL_OWNERSHIP_TM && - !(cmd->flags & CMD_ON_DEMAND)) { - IWL_DEBUG_HC(priv, "tm own the uCode, no regular hcmd send\n"); - return -EIO; - } - return iwl_trans_send_cmd(priv->trans, cmd); } |
