summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
diff options
context:
space:
mode:
authorJames Morris <james.l.morris@oracle.com>2017-11-29 12:47:41 +1100
committerJames Morris <james.l.morris@oracle.com>2017-11-29 12:47:41 +1100
commitcf40a76e7d5874bb25f4404eecc58a2e033af885 (patch)
tree8fd81cbea03c87b3d41d7ae5b1d11eadd35d6ef5 /drivers/net/wireless/intel/iwlwifi/mvm/ops.c
parentab5348c9c23cd253f5902980d2d8fe067dc24c82 (diff)
parent4fbd8d194f06c8a3fd2af1ce560ddb31f7ec8323 (diff)
Merge tag 'v4.15-rc1' into next-seccomp
Linux 4.15-rc1
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/ops.c')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c188
1 files changed, 71 insertions, 117 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 4d1188b8736a..7078b7e458be 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -82,11 +82,11 @@
#include "iwl-io.h"
#include "iwl-prph.h"
#include "rs.h"
-#include "fw-api-scan.h"
+#include "fw/api/scan.h"
#include "time-event.h"
-#include "fw-dbg.h"
#include "fw-api.h"
-#include "fw-api-scan.h"
+#include "fw/api/scan.h"
+#include "fw/acpi.h"
#define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux"
MODULE_DESCRIPTION(DRV_DESCRIPTION);
@@ -257,8 +257,6 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
RX_HANDLER_ASYNC_LOCKED),
RX_HANDLER(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics,
RX_HANDLER_ASYNC_LOCKED),
- RX_HANDLER(ANTENNA_COUPLING_NOTIFICATION,
- iwl_mvm_rx_ant_coupling_notif, RX_HANDLER_ASYNC_LOCKED),
RX_HANDLER(BA_WINDOW_STATUS_NOTIFICATION_ID,
iwl_mvm_window_status_notif, RX_HANDLER_SYNC),
@@ -326,7 +324,6 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(INIT_COMPLETE_NOTIF),
HCMD_NAME(PHY_CONTEXT_CMD),
HCMD_NAME(DBG_CFG),
- HCMD_NAME(ANTENNA_COUPLING_NOTIFICATION),
HCMD_NAME(SCAN_CFG_CMD),
HCMD_NAME(SCAN_REQ_UMAC),
HCMD_NAME(SCAN_ABORT_UMAC),
@@ -351,13 +348,13 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(BINDING_CONTEXT_CMD),
HCMD_NAME(TIME_QUOTA_CMD),
HCMD_NAME(NON_QOS_TX_COUNTER_CMD),
+ HCMD_NAME(LEDS_CMD),
HCMD_NAME(LQ_CMD),
HCMD_NAME(FW_PAGING_BLOCK_CMD),
HCMD_NAME(SCAN_OFFLOAD_REQUEST_CMD),
HCMD_NAME(SCAN_OFFLOAD_ABORT_CMD),
HCMD_NAME(HOT_SPOT_CMD),
HCMD_NAME(SCAN_OFFLOAD_PROFILES_QUERY_CMD),
- HCMD_NAME(BT_COEX_UPDATE_CORUN_LUT),
HCMD_NAME(BT_COEX_UPDATE_REDUCED_TXP),
HCMD_NAME(BT_COEX_CI),
HCMD_NAME(PHY_CONFIGURATION_CMD),
@@ -388,6 +385,7 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(SCAN_ITERATION_COMPLETE_UMAC),
HCMD_NAME(REPLY_RX_PHY_CMD),
HCMD_NAME(REPLY_RX_MPDU_CMD),
+ HCMD_NAME(FRAME_RELEASE),
HCMD_NAME(BA_NOTIF),
HCMD_NAME(MCC_UPDATE_CMD),
HCMD_NAME(MCC_CHUB_UPDATE_CMD),
@@ -426,8 +424,6 @@ static const struct iwl_hcmd_names iwl_mvm_system_names[] = {
* Access is done through binary search
*/
static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = {
- HCMD_NAME(LINK_QUALITY_MEASUREMENT_CMD),
- HCMD_NAME(LINK_QUALITY_MEASUREMENT_COMPLETE_NOTIF),
HCMD_NAME(CHANNEL_SWITCH_NOA_NOTIF),
};
@@ -493,25 +489,26 @@ static const struct iwl_hcmd_arr iwl_mvm_groups[] = {
static void iwl_mvm_async_handlers_wk(struct work_struct *wk);
static void iwl_mvm_d0i3_exit_work(struct work_struct *wk);
-static u32 calc_min_backoff(struct iwl_trans *trans, const struct iwl_cfg *cfg)
+static u32 iwl_mvm_min_backoff(struct iwl_mvm *mvm)
{
- const struct iwl_pwr_tx_backoff *pwr_tx_backoff = cfg->pwr_tx_backoffs;
+ const struct iwl_pwr_tx_backoff *backoff = mvm->cfg->pwr_tx_backoffs;
+ u64 dflt_pwr_limit;
- if (!pwr_tx_backoff)
+ if (!backoff)
return 0;
- while (pwr_tx_backoff->pwr) {
- if (trans->dflt_pwr_limit >= pwr_tx_backoff->pwr)
- return pwr_tx_backoff->backoff;
+ dflt_pwr_limit = iwl_acpi_get_pwr_limit(mvm->dev);
- pwr_tx_backoff++;
+ while (backoff->pwr) {
+ if (dflt_pwr_limit >= backoff->pwr)
+ return backoff->backoff;
+
+ backoff++;
}
return 0;
}
-static void iwl_mvm_fw_error_dump_wk(struct work_struct *work);
-
static void iwl_mvm_tx_unblock_dwork(struct work_struct *work)
{
struct iwl_mvm *mvm =
@@ -535,6 +532,34 @@ unlock:
mutex_unlock(&mvm->mutex);
}
+static int iwl_mvm_fwrt_dump_start(void *ctx)
+{
+ struct iwl_mvm *mvm = ctx;
+ int ret;
+
+ ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_FW_DBG_COLLECT);
+ if (ret)
+ return ret;
+
+ mutex_lock(&mvm->mutex);
+
+ return 0;
+}
+
+static void iwl_mvm_fwrt_dump_end(void *ctx)
+{
+ struct iwl_mvm *mvm = ctx;
+
+ mutex_unlock(&mvm->mutex);
+
+ iwl_mvm_unref(mvm, IWL_MVM_REF_FW_DBG_COLLECT);
+}
+
+static const struct iwl_fw_runtime_ops iwl_mvm_fwrt_ops = {
+ .dump_start = iwl_mvm_fwrt_dump_start,
+ .dump_end = iwl_mvm_fwrt_dump_end,
+};
+
static struct iwl_op_mode *
iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
const struct iwl_fw *fw, struct dentry *dbgfs_dir)
@@ -580,6 +605,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mvm->fw = fw;
mvm->hw = hw;
+ iwl_fw_runtime_init(&mvm->fwrt, trans, fw, &iwl_mvm_fwrt_ops, mvm);
+
mvm->init_status = 0;
if (iwl_mvm_has_new_rx_api(mvm)) {
@@ -596,32 +623,15 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mvm->fw_restart = iwlwifi_mod_params.fw_restart ? -1 : 0;
- if (!iwl_mvm_is_dqa_supported(mvm)) {
- mvm->last_agg_queue = mvm->cfg->base_params->num_of_queues - 1;
-
- if (mvm->cfg->base_params->num_of_queues == 16) {
- mvm->aux_queue = 11;
- mvm->first_agg_queue = 12;
- BUILD_BUG_ON(BITS_PER_BYTE *
- sizeof(mvm->hw_queue_to_mac80211[0]) < 12);
- } else {
- mvm->aux_queue = 15;
- mvm->first_agg_queue = 16;
- BUILD_BUG_ON(BITS_PER_BYTE *
- sizeof(mvm->hw_queue_to_mac80211[0]) < 16);
- }
- } else {
- mvm->aux_queue = IWL_MVM_DQA_AUX_QUEUE;
- mvm->probe_queue = IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
- mvm->p2p_dev_queue = IWL_MVM_DQA_P2P_DEVICE_QUEUE;
- mvm->first_agg_queue = IWL_MVM_DQA_MIN_DATA_QUEUE;
- mvm->last_agg_queue = IWL_MVM_DQA_MAX_DATA_QUEUE;
- }
+ mvm->aux_queue = IWL_MVM_DQA_AUX_QUEUE;
+ mvm->probe_queue = IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
+ mvm->p2p_dev_queue = IWL_MVM_DQA_P2P_DEVICE_QUEUE;
+
mvm->sf_state = SF_UNINIT;
- if (iwl_mvm_has_new_tx_api(mvm))
- mvm->cur_ucode = IWL_UCODE_REGULAR;
+ if (iwl_mvm_has_unified_ucode(mvm))
+ iwl_fw_set_current_image(&mvm->fwrt, IWL_UCODE_REGULAR);
else
- mvm->cur_ucode = IWL_UCODE_INIT;
+ iwl_fw_set_current_image(&mvm->fwrt, IWL_UCODE_INIT);
mvm->drop_bcn_ap_mode = true;
mutex_init(&mvm->mutex);
@@ -635,9 +645,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
INIT_WORK(&mvm->async_handlers_wk, iwl_mvm_async_handlers_wk);
INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk);
- INIT_WORK(&mvm->sta_drained_wk, iwl_mvm_sta_drained_wk);
INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work);
- INIT_DELAYED_WORK(&mvm->fw_dump_wk, iwl_mvm_fw_error_dump_wk);
INIT_DELAYED_WORK(&mvm->tdls_cs.dwork, iwl_mvm_tdls_ch_switch_work);
INIT_DELAYED_WORK(&mvm->scan_timeout_dwork, iwl_mvm_scan_timeout_wk);
INIT_WORK(&mvm->add_stream_wk, iwl_mvm_add_new_dqa_stream_wk);
@@ -688,17 +696,13 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
trans_cfg.command_groups = iwl_mvm_groups;
trans_cfg.command_groups_size = ARRAY_SIZE(iwl_mvm_groups);
- if (iwl_mvm_is_dqa_supported(mvm))
- trans_cfg.cmd_queue = IWL_MVM_DQA_CMD_QUEUE;
- else
- trans_cfg.cmd_queue = IWL_MVM_CMD_QUEUE;
+ trans_cfg.cmd_queue = IWL_MVM_DQA_CMD_QUEUE;
trans_cfg.cmd_fifo = IWL_MVM_TX_FIFO_CMD;
trans_cfg.scd_set_active = true;
trans_cfg.cb_data_offs = offsetof(struct ieee80211_tx_info,
driver_data[2]);
- trans_cfg.sdio_adma_addr = fw->sdio_adma_addr;
trans_cfg.sw_csum_tx = IWL_MVM_SW_TX_CSUM_OFFLOAD;
/* Set a short watchdog for the command queue */
@@ -749,7 +753,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
iwl_mvm_stop_device(mvm);
iwl_mvm_unref(mvm, IWL_MVM_REF_INIT_UCODE);
mutex_unlock(&mvm->mutex);
- /* returns 0 if successful, 1 if success but in rfkill */
if (err < 0) {
IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err);
goto out_free;
@@ -769,7 +772,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
goto out_free;
mvm->hw_registered = true;
- min_backoff = calc_min_backoff(trans, cfg);
+ min_backoff = iwl_mvm_min_backoff(mvm);
iwl_mvm_thermal_initialize(mvm, min_backoff);
err = iwl_mvm_dbgfs_register(mvm, dbgfs_dir);
@@ -800,7 +803,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
iwl_mvm_leds_exit(mvm);
iwl_mvm_thermal_exit(mvm);
out_free:
- flush_delayed_work(&mvm->fw_dump_wk);
+ iwl_fw_flush_dump(&mvm->fwrt);
if (iwlmvm_mod_params.init_dbg)
return op_mode;
@@ -920,7 +923,7 @@ static inline void iwl_mvm_rx_check_trigger(struct iwl_mvm *mvm,
trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_FW_NOTIF);
cmds_trig = (void *)trig->data;
- if (!iwl_fw_dbg_trigger_check_stop(mvm, NULL, trig))
+ if (!iwl_fw_dbg_trigger_check_stop(&mvm->fwrt, NULL, trig))
return;
for (i = 0; i < ARRAY_SIZE(cmds_trig->cmds); i++) {
@@ -932,9 +935,9 @@ static inline void iwl_mvm_rx_check_trigger(struct iwl_mvm *mvm,
cmds_trig->cmds[i].group_id != pkt->hdr.group_id)
continue;
- iwl_mvm_fw_dbg_collect_trig(mvm, trig,
- "CMD 0x%02x.%02x received",
- pkt->hdr.group_id, pkt->hdr.cmd);
+ iwl_fw_dbg_collect_trig(&mvm->fwrt, trig,
+ "CMD 0x%02x.%02x received",
+ pkt->hdr.group_id, pkt->hdr.cmd);
break;
}
}
@@ -980,8 +983,10 @@ static void iwl_mvm_rx_common(struct iwl_mvm *mvm,
list_add_tail(&entry->list, &mvm->async_handlers_list);
spin_unlock(&mvm->async_handlers_lock);
schedule_work(&mvm->async_handlers_wk);
- break;
+ return;
}
+
+ iwl_fwrt_handle_notification(&mvm->fwrt, rxb);
}
static void iwl_mvm_rx(struct iwl_op_mode *op_mode,
@@ -1114,7 +1119,7 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state)
static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
{
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
- bool calibrating = ACCESS_ONCE(mvm->calibrating);
+ bool calibrating = READ_ONCE(mvm->calibrating);
if (state)
set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
@@ -1131,7 +1136,7 @@ static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
* Stop the device if we run OPERATIONAL firmware or if we are in the
* middle of the calibrations.
*/
- return state && (mvm->cur_ucode != IWL_UCODE_INIT || calibrating);
+ return state && (mvm->fwrt.cur_fw_img != IWL_UCODE_INIT || calibrating);
}
static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
@@ -1160,57 +1165,6 @@ static void iwl_mvm_reprobe_wk(struct work_struct *wk)
module_put(THIS_MODULE);
}
-static void iwl_mvm_fw_error_dump_wk(struct work_struct *work)
-{
- struct iwl_mvm *mvm =
- container_of(work, struct iwl_mvm, fw_dump_wk.work);
-
- if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_FW_DBG_COLLECT))
- return;
-
- mutex_lock(&mvm->mutex);
-
- if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
- /* stop recording */
- iwl_set_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100);
-
- iwl_mvm_fw_error_dump(mvm);
-
- /* start recording again if the firmware is not crashed */
- if (!test_bit(STATUS_FW_ERROR, &mvm->trans->status) &&
- mvm->fw->dbg_dest_tlv) {
- iwl_clear_bits_prph(mvm->trans,
- MON_BUFF_SAMPLE_CTL, 0x100);
- iwl_clear_bits_prph(mvm->trans,
- MON_BUFF_SAMPLE_CTL, 0x1);
- iwl_set_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x1);
- }
- } else {
- u32 in_sample = iwl_read_prph(mvm->trans, DBGC_IN_SAMPLE);
- u32 out_ctrl = iwl_read_prph(mvm->trans, DBGC_OUT_CTRL);
-
- /* stop recording */
- iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 0);
- udelay(100);
- iwl_write_prph(mvm->trans, DBGC_OUT_CTRL, 0);
- /* wait before we collect the data till the DBGC stop */
- udelay(500);
-
- iwl_mvm_fw_error_dump(mvm);
-
- /* start recording again if the firmware is not crashed */
- if (!test_bit(STATUS_FW_ERROR, &mvm->trans->status) &&
- mvm->fw->dbg_dest_tlv) {
- iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, in_sample);
- iwl_write_prph(mvm->trans, DBGC_OUT_CTRL, out_ctrl);
- }
- }
-
- mutex_unlock(&mvm->mutex);
-
- iwl_mvm_unref(mvm, IWL_MVM_REF_FW_DBG_COLLECT);
-}
-
void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
{
iwl_abort_notification_waits(&mvm->notif_wait);
@@ -1234,10 +1188,9 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
* can't recover this since we're already half suspended.
*/
if (!mvm->fw_restart && fw_error) {
- iwl_mvm_fw_dbg_collect_desc(mvm, &iwl_mvm_dump_desc_assert,
- NULL);
- } else if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART,
- &mvm->status)) {
+ iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert,
+ NULL);
+ } else if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
struct iwl_mvm_reprobe *reprobe;
IWL_ERR(mvm,
@@ -1261,13 +1214,14 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
reprobe->dev = mvm->trans->dev;
INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk);
schedule_work(&reprobe->work);
- } else if (mvm->cur_ucode == IWL_UCODE_REGULAR &&
+ } else if (mvm->fwrt.cur_fw_img == IWL_UCODE_REGULAR &&
mvm->hw_registered) {
/* don't let the transport/FW power down */
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
if (fw_error && mvm->fw_restart > 0)
mvm->fw_restart--;
+ set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);
ieee80211_restart_hw(mvm->hw);
}
}
@@ -1439,7 +1393,7 @@ int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
IWL_DEBUG_RPM(mvm, "MVM entering D0i3\n");
- if (WARN_ON_ONCE(mvm->cur_ucode != IWL_UCODE_REGULAR))
+ if (WARN_ON_ONCE(mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR))
return -EINVAL;
set_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
@@ -1665,7 +1619,7 @@ int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm)
IWL_DEBUG_RPM(mvm, "MVM exiting D0i3\n");
- if (WARN_ON_ONCE(mvm->cur_ucode != IWL_UCODE_REGULAR))
+ if (WARN_ON_ONCE(mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR))
return -EINVAL;
mutex_lock(&mvm->d0i3_suspend_mutex);