aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/ops.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c83
1 files changed, 54 insertions, 29 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index 97dfba50c682..2dffc3600ed3 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -84,15 +84,8 @@
84#include "time-event.h" 84#include "time-event.h"
85#include "iwl-fw-error-dump.h" 85#include "iwl-fw-error-dump.h"
86 86
87/*
88 * module name, copyright, version, etc.
89 */
90#define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux" 87#define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux"
91
92#define DRV_VERSION IWLWIFI_VERSION
93
94MODULE_DESCRIPTION(DRV_DESCRIPTION); 88MODULE_DESCRIPTION(DRV_DESCRIPTION);
95MODULE_VERSION(DRV_VERSION);
96MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); 89MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
97MODULE_LICENSE("GPL"); 90MODULE_LICENSE("GPL");
98 91
@@ -100,6 +93,7 @@ static const struct iwl_op_mode_ops iwl_mvm_ops;
100 93
101struct iwl_mvm_mod_params iwlmvm_mod_params = { 94struct iwl_mvm_mod_params iwlmvm_mod_params = {
102 .power_scheme = IWL_POWER_SCHEME_BPS, 95 .power_scheme = IWL_POWER_SCHEME_BPS,
96 .tfd_q_hang_detect = true
103 /* rest of fields are 0 by default */ 97 /* rest of fields are 0 by default */
104}; 98};
105 99
@@ -109,6 +103,10 @@ MODULE_PARM_DESC(init_dbg,
109module_param_named(power_scheme, iwlmvm_mod_params.power_scheme, int, S_IRUGO); 103module_param_named(power_scheme, iwlmvm_mod_params.power_scheme, int, S_IRUGO);
110MODULE_PARM_DESC(power_scheme, 104MODULE_PARM_DESC(power_scheme,
111 "power management scheme: 1-active, 2-balanced, 3-low power, default: 2"); 105 "power management scheme: 1-active, 2-balanced, 3-low power, default: 2");
106module_param_named(tfd_q_hang_detect, iwlmvm_mod_params.tfd_q_hang_detect,
107 bool, S_IRUGO);
108MODULE_PARM_DESC(tfd_q_hang_detect,
109 "TFD queues hang detection (default: true");
112 110
113/* 111/*
114 * module init and exit functions 112 * module init and exit functions
@@ -146,13 +144,14 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
146 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 144 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
147 u8 radio_cfg_type, radio_cfg_step, radio_cfg_dash; 145 u8 radio_cfg_type, radio_cfg_step, radio_cfg_dash;
148 u32 reg_val = 0; 146 u32 reg_val = 0;
147 u32 phy_config = iwl_mvm_get_phy_config(mvm);
149 148
150 radio_cfg_type = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_TYPE) >> 149 radio_cfg_type = (phy_config & FW_PHY_CFG_RADIO_TYPE) >>
151 FW_PHY_CFG_RADIO_TYPE_POS; 150 FW_PHY_CFG_RADIO_TYPE_POS;
152 radio_cfg_step = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_STEP) >> 151 radio_cfg_step = (phy_config & FW_PHY_CFG_RADIO_STEP) >>
153 FW_PHY_CFG_RADIO_STEP_POS; 152 FW_PHY_CFG_RADIO_STEP_POS;
154 radio_cfg_dash = (mvm->fw->phy_config & FW_PHY_CFG_RADIO_DASH) >> 153 radio_cfg_dash = (phy_config & FW_PHY_CFG_RADIO_DASH) >>
155 FW_PHY_CFG_RADIO_DASH_POS; 154 FW_PHY_CFG_RADIO_DASH_POS;
156 155
157 /* SKU control */ 156 /* SKU control */
158 reg_val |= CSR_HW_REV_STEP(mvm->trans->hw_rev) << 157 reg_val |= CSR_HW_REV_STEP(mvm->trans->hw_rev) <<
@@ -240,6 +239,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
240 239
241 RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), 240 RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false),
242 RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, true), 241 RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, true),
242 RX_HANDLER(SCAN_ITERATION_COMPLETE,
243 iwl_mvm_rx_scan_offload_iter_complete_notif, false),
243 RX_HANDLER(SCAN_OFFLOAD_COMPLETE, 244 RX_HANDLER(SCAN_OFFLOAD_COMPLETE,
244 iwl_mvm_rx_scan_offload_complete_notif, true), 245 iwl_mvm_rx_scan_offload_complete_notif, true),
245 RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_scan_offload_results, 246 RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_scan_offload_results,
@@ -274,6 +275,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
274 CMD(MGMT_MCAST_KEY), 275 CMD(MGMT_MCAST_KEY),
275 CMD(TX_CMD), 276 CMD(TX_CMD),
276 CMD(TXPATH_FLUSH), 277 CMD(TXPATH_FLUSH),
278 CMD(SHARED_MEM_CFG),
277 CMD(MAC_CONTEXT_CMD), 279 CMD(MAC_CONTEXT_CMD),
278 CMD(TIME_EVENT_CMD), 280 CMD(TIME_EVENT_CMD),
279 CMD(TIME_EVENT_NOTIFICATION), 281 CMD(TIME_EVENT_NOTIFICATION),
@@ -476,17 +478,19 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
476 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DW_BC_TABLE) 478 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_DW_BC_TABLE)
477 trans_cfg.bc_table_dword = true; 479 trans_cfg.bc_table_dword = true;
478 480
479 if (!iwlwifi_mod_params.wd_disable)
480 trans_cfg.queue_watchdog_timeout = cfg->base_params->wd_timeout;
481 else
482 trans_cfg.queue_watchdog_timeout = IWL_WATCHDOG_DISABLED;
483
484 trans_cfg.command_names = iwl_mvm_cmd_strings; 481 trans_cfg.command_names = iwl_mvm_cmd_strings;
485 482
486 trans_cfg.cmd_queue = IWL_MVM_CMD_QUEUE; 483 trans_cfg.cmd_queue = IWL_MVM_CMD_QUEUE;
487 trans_cfg.cmd_fifo = IWL_MVM_TX_FIFO_CMD; 484 trans_cfg.cmd_fifo = IWL_MVM_TX_FIFO_CMD;
488 trans_cfg.scd_set_active = true; 485 trans_cfg.scd_set_active = true;
489 486
487 trans_cfg.sdio_adma_addr = fw->sdio_adma_addr;
488
489 /* Set a short watchdog for the command queue */
490 trans_cfg.cmd_q_wdg_timeout =
491 iwlmvm_mod_params.tfd_q_hang_detect ? IWL_DEF_WD_TIMEOUT :
492 IWL_WATCHDOG_DISABLED;
493
490 snprintf(mvm->hw->wiphy->fw_version, 494 snprintf(mvm->hw->wiphy->fw_version,
491 sizeof(mvm->hw->wiphy->fw_version), 495 sizeof(mvm->hw->wiphy->fw_version),
492 "%s", fw->fw_version); 496 "%s", fw->fw_version);
@@ -517,10 +521,15 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
517 min_backoff = calc_min_backoff(trans, cfg); 521 min_backoff = calc_min_backoff(trans, cfg);
518 iwl_mvm_tt_initialize(mvm, min_backoff); 522 iwl_mvm_tt_initialize(mvm, min_backoff);
519 /* set the nvm_file_name according to priority */ 523 /* set the nvm_file_name according to priority */
520 if (iwlwifi_mod_params.nvm_file) 524 if (iwlwifi_mod_params.nvm_file) {
521 mvm->nvm_file_name = iwlwifi_mod_params.nvm_file; 525 mvm->nvm_file_name = iwlwifi_mod_params.nvm_file;
522 else 526 } else {
523 mvm->nvm_file_name = mvm->cfg->default_nvm_file; 527 if ((trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) &&
528 (CSR_HW_REV_STEP(trans->hw_rev) == SILICON_A_STEP))
529 mvm->nvm_file_name = mvm->cfg->default_nvm_file_8000A;
530 else
531 mvm->nvm_file_name = mvm->cfg->default_nvm_file;
532 }
524 533
525 if (WARN(cfg->no_power_up_nic_in_init && !mvm->nvm_file_name, 534 if (WARN(cfg->no_power_up_nic_in_init && !mvm->nvm_file_name,
526 "not allowing power-up and not having nvm_file\n")) 535 "not allowing power-up and not having nvm_file\n"))
@@ -559,6 +568,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
559 if (!mvm->scan_cmd) 568 if (!mvm->scan_cmd)
560 goto out_free; 569 goto out_free;
561 570
571 /* Set EBS as successful as long as not stated otherwise by the FW. */
572 mvm->last_ebs_successful = true;
573
562 err = iwl_mvm_mac_setup_register(mvm); 574 err = iwl_mvm_mac_setup_register(mvm);
563 if (err) 575 if (err)
564 goto out_free; 576 goto out_free;
@@ -817,9 +829,20 @@ static void iwl_mvm_fw_error_dump_wk(struct work_struct *work)
817 struct iwl_mvm *mvm = 829 struct iwl_mvm *mvm =
818 container_of(work, struct iwl_mvm, fw_error_dump_wk); 830 container_of(work, struct iwl_mvm, fw_error_dump_wk);
819 831
832 if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_FW_DBG_COLLECT))
833 return;
834
820 mutex_lock(&mvm->mutex); 835 mutex_lock(&mvm->mutex);
821 iwl_mvm_fw_error_dump(mvm); 836 iwl_mvm_fw_error_dump(mvm);
837
838 /* start recording again if the firmware is not crashed */
839 WARN_ON_ONCE((!test_bit(STATUS_FW_ERROR, &mvm->trans->status)) &&
840 mvm->fw->dbg_dest_tlv &&
841 iwl_mvm_start_fw_dbg_conf(mvm, mvm->fw_dbg_conf));
842
822 mutex_unlock(&mvm->mutex); 843 mutex_unlock(&mvm->mutex);
844
845 iwl_mvm_unref(mvm, IWL_MVM_REF_FW_DBG_COLLECT);
823} 846}
824 847
825void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) 848void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
@@ -855,7 +878,10 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
855 * If WoWLAN fw asserted, don't restart either, mac80211 878 * If WoWLAN fw asserted, don't restart either, mac80211
856 * can't recover this since we're already half suspended. 879 * can't recover this since we're already half suspended.
857 */ 880 */
858 if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { 881 if (!mvm->restart_fw && fw_error) {
882 schedule_work(&mvm->fw_error_dump_wk);
883 } else if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART,
884 &mvm->status)) {
859 struct iwl_mvm_reprobe *reprobe; 885 struct iwl_mvm_reprobe *reprobe;
860 886
861 IWL_ERR(mvm, 887 IWL_ERR(mvm,
@@ -879,16 +905,13 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
879 reprobe->dev = mvm->trans->dev; 905 reprobe->dev = mvm->trans->dev;
880 INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk); 906 INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk);
881 schedule_work(&reprobe->work); 907 schedule_work(&reprobe->work);
882 } else if (mvm->cur_ucode == IWL_UCODE_REGULAR && 908 } else if (mvm->cur_ucode == IWL_UCODE_REGULAR) {
883 (!fw_error || mvm->restart_fw)) {
884 /* don't let the transport/FW power down */ 909 /* don't let the transport/FW power down */
885 iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); 910 iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
886 911
887 if (fw_error && mvm->restart_fw > 0) 912 if (fw_error && mvm->restart_fw > 0)
888 mvm->restart_fw--; 913 mvm->restart_fw--;
889 ieee80211_restart_hw(mvm->hw); 914 ieee80211_restart_hw(mvm->hw);
890 } else if (fw_error) {
891 schedule_work(&mvm->fw_error_dump_wk);
892 } 915 }
893} 916}
894 917
@@ -1031,7 +1054,8 @@ static void iwl_mvm_set_wowlan_data(struct iwl_mvm *mvm,
1031out: 1054out:
1032 rcu_read_unlock(); 1055 rcu_read_unlock();
1033} 1056}
1034static int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode) 1057
1058int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
1035{ 1059{
1036 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 1060 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
1037 u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE; 1061 u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE;
@@ -1047,6 +1071,7 @@ static int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
1047 }; 1071 };
1048 struct iwl_d3_manager_config d3_cfg_cmd = { 1072 struct iwl_d3_manager_config d3_cfg_cmd = {
1049 .min_sleep_time = cpu_to_le32(1000), 1073 .min_sleep_time = cpu_to_le32(1000),
1074 .wakeup_flags = cpu_to_le32(IWL_WAKEUP_D3_CONFIG_FW_ERROR),
1050 }; 1075 };
1051 1076
1052 IWL_DEBUG_RPM(mvm, "MVM entering D0i3\n"); 1077 IWL_DEBUG_RPM(mvm, "MVM entering D0i3\n");
@@ -1146,7 +1171,7 @@ void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq)
1146 1171
1147 if (mvm->d0i3_offloading && qos_seq) { 1172 if (mvm->d0i3_offloading && qos_seq) {
1148 /* update qos seq numbers if offloading was enabled */ 1173 /* update qos seq numbers if offloading was enabled */
1149 mvm_ap_sta = (struct iwl_mvm_sta *)sta->drv_priv; 1174 mvm_ap_sta = iwl_mvm_sta_from_mac80211(sta);
1150 for (i = 0; i < IWL_MAX_TID_COUNT; i++) { 1175 for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
1151 u16 seq = le16_to_cpu(qos_seq[i]); 1176 u16 seq = le16_to_cpu(qos_seq[i]);
1152 /* firmware stores last-used one, we store next one */ 1177 /* firmware stores last-used one, we store next one */
@@ -1245,7 +1270,7 @@ out:
1245 return ret; 1270 return ret;
1246} 1271}
1247 1272
1248static int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode) 1273int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode)
1249{ 1274{
1250 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 1275 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
1251 1276