Commit 57605833 authored by Shahar S Matityahu's avatar Shahar S Matityahu Committed by Luca Coelho

iwlwifi: dbg: support debug recording suspend resume command

Support the new DBGC_SUSPEND_RESUME command to change the recording state.
Signed-off-by: default avatarShahar S Matityahu <shahar.s.matityahu@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 203c83d3
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright (C) 2018 Intel Corporation * Copyright (C) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -80,6 +80,13 @@ enum iwl_debug_cmds { ...@@ -80,6 +80,13 @@ enum iwl_debug_cmds {
* &struct iwl_dbg_mem_access_rsp * &struct iwl_dbg_mem_access_rsp
*/ */
UMAC_RD_WR = 0x1, UMAC_RD_WR = 0x1,
/**
* @DBGC_SUSPEND_RESUME:
* DBGC suspend/resume commad. Uses a single dword as data:
* 0 - resume DBGC recording
* 1 - suspend DBGC recording
*/
DBGC_SUSPEND_RESUME = 0x7,
/** /**
* @MFU_ASSERT_DUMP_NTF: * @MFU_ASSERT_DUMP_NTF:
* &struct iwl_mfu_assert_dump_notif * &struct iwl_mfu_assert_dump_notif
...@@ -102,6 +109,16 @@ enum { ...@@ -102,6 +109,16 @@ enum {
FW_ERR_FATAL = 0xFF FW_ERR_FATAL = 0xFF
}; };
/** enum iwl_dbg_suspend_resume_cmds - dbgc suspend resume operations
* dbgc suspend resume command operations
* @DBGC_RESUME_CMD: resume dbgc recording
* @DBGC_SUSPEND_CMD: stop dbgc recording
*/
enum iwl_dbg_suspend_resume_cmds {
DBGC_RESUME_CMD,
DBGC_SUSPEND_CMD,
};
/** /**
* struct iwl_error_resp - FW error indication * struct iwl_error_resp - FW error indication
* ( REPLY_ERROR = 0x2 ) * ( REPLY_ERROR = 0x2 )
...@@ -380,4 +397,13 @@ struct iwl_ldbg_config_cmd { ...@@ -380,4 +397,13 @@ struct iwl_ldbg_config_cmd {
}; /* LDBG_CFG_BODY_API_U_VER_2 (partially) */ }; /* LDBG_CFG_BODY_API_U_VER_2 (partially) */
} __packed; /* LDBG_CFG_CMD_API_S_VER_2 */ } __packed; /* LDBG_CFG_CMD_API_S_VER_2 */
/**
* struct iwl_dbg_suspend_resume_cmd - dbgc suspend resume command
* @operation: suspend or resume operation, uses
* &enum iwl_dbg_suspend_resume_cmds
*/
struct iwl_dbg_suspend_resume_cmd {
__le32 operation;
} __packed;
#endif /* __iwl_fw_api_debug_h__ */ #endif /* __iwl_fw_api_debug_h__ */
...@@ -2372,7 +2372,10 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx) ...@@ -2372,7 +2372,10 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
goto out; goto out;
} }
iwl_fw_dbg_stop_recording(fwrt->trans, &params); if (iwl_fw_dbg_stop_restart_recording(fwrt, &params, true)) {
IWL_ERR(fwrt, "Failed to stop DBGC recording, aborting dump\n");
goto out;
}
IWL_DEBUG_FW_INFO(fwrt, "WRT: data collection start\n"); IWL_DEBUG_FW_INFO(fwrt, "WRT: data collection start\n");
if (fwrt->trans->dbg.ini_valid) if (fwrt->trans->dbg.ini_valid)
...@@ -2381,7 +2384,7 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx) ...@@ -2381,7 +2384,7 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
iwl_fw_error_dump(fwrt); iwl_fw_error_dump(fwrt);
IWL_DEBUG_FW_INFO(fwrt, "WRT: data collection done\n"); IWL_DEBUG_FW_INFO(fwrt, "WRT: data collection done\n");
iwl_fw_dbg_restart_recording(fwrt, &params); iwl_fw_dbg_stop_restart_recording(fwrt, &params, false);
out: out:
clear_bit(wk_idx, &fwrt->dump.active_wks); clear_bit(wk_idx, &fwrt->dump.active_wks);
...@@ -2870,7 +2873,7 @@ void iwl_fw_dbg_stop_sync(struct iwl_fw_runtime *fwrt) ...@@ -2870,7 +2873,7 @@ void iwl_fw_dbg_stop_sync(struct iwl_fw_runtime *fwrt)
for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++)
iwl_fw_dbg_collect_sync(fwrt, i); iwl_fw_dbg_collect_sync(fwrt, i);
iwl_fw_dbg_stop_recording(fwrt->trans, NULL); iwl_fw_dbg_stop_restart_recording(fwrt, NULL, true);
} }
IWL_EXPORT_SYMBOL(iwl_fw_dbg_stop_sync); IWL_EXPORT_SYMBOL(iwl_fw_dbg_stop_sync);
...@@ -2938,8 +2941,24 @@ void iwl_fw_error_print_fseq_regs(struct iwl_fw_runtime *fwrt) ...@@ -2938,8 +2941,24 @@ void iwl_fw_error_print_fseq_regs(struct iwl_fw_runtime *fwrt)
} }
IWL_EXPORT_SYMBOL(iwl_fw_error_print_fseq_regs); IWL_EXPORT_SYMBOL(iwl_fw_error_print_fseq_regs);
static void _iwl_fw_dbg_stop_recording(struct iwl_trans *trans, static int iwl_fw_dbg_suspend_resume_hcmd(struct iwl_trans *trans, bool suspend)
struct iwl_fw_dbg_params *params) {
struct iwl_dbg_suspend_resume_cmd cmd = {
.operation = suspend ?
cpu_to_le32(DBGC_SUSPEND_CMD) :
cpu_to_le32(DBGC_RESUME_CMD),
};
struct iwl_host_cmd hcmd = {
.id = WIDE_ID(DEBUG_GROUP, DBGC_SUSPEND_RESUME),
.data[0] = &cmd,
.len[0] = sizeof(cmd),
};
return iwl_trans_send_cmd(trans, &hcmd);
}
static void iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
struct iwl_fw_dbg_params *params)
{ {
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) { if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100); iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
...@@ -2957,37 +2976,13 @@ static void _iwl_fw_dbg_stop_recording(struct iwl_trans *trans, ...@@ -2957,37 +2976,13 @@ static void _iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
*/ */
usleep_range(700, 1000); usleep_range(700, 1000);
iwl_write_umac_prph(trans, DBGC_OUT_CTRL, 0); iwl_write_umac_prph(trans, DBGC_OUT_CTRL, 0);
#ifdef CONFIG_IWLWIFI_DEBUGFS
trans->dbg.rec_on = false;
#endif
}
void iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
struct iwl_fw_dbg_params *params)
{
/* if the FW crashed or not debug monitor cfg was given, there is
* no point in stopping
*/
if (test_bit(STATUS_FW_ERROR, &trans->status) ||
(!trans->dbg.dest_tlv &&
trans->dbg.ini_dest == IWL_FW_INI_LOCATION_INVALID))
return;
if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
IWL_ERR(trans,
"WRT: unsupported device family %d for debug stop recording\n",
trans->cfg->device_family);
return;
}
_iwl_fw_dbg_stop_recording(trans, params);
} }
IWL_EXPORT_SYMBOL(iwl_fw_dbg_stop_recording);
static void _iwl_fw_dbg_restart_recording(struct iwl_trans *trans, static int iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
struct iwl_fw_dbg_params *params) struct iwl_fw_dbg_params *params)
{ {
if (WARN_ON(!params)) if (!params)
return; return -EIO;
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) { if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100); iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
...@@ -2997,28 +2992,40 @@ static void _iwl_fw_dbg_restart_recording(struct iwl_trans *trans, ...@@ -2997,28 +2992,40 @@ static void _iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, params->in_sample); iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, params->in_sample);
iwl_write_umac_prph(trans, DBGC_OUT_CTRL, params->out_ctrl); iwl_write_umac_prph(trans, DBGC_OUT_CTRL, params->out_ctrl);
} }
return 0;
} }
void iwl_fw_dbg_restart_recording(struct iwl_fw_runtime *fwrt, int iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_params *params) struct iwl_fw_dbg_params *params,
bool stop)
{ {
int ret = 0;
/* if the FW crashed or not debug monitor cfg was given, there is /* if the FW crashed or not debug monitor cfg was given, there is
* no point in restarting * no point in changing the recording state
*/ */
if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status) || if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status) ||
(!fwrt->trans->dbg.dest_tlv && (!fwrt->trans->dbg.dest_tlv &&
fwrt->trans->dbg.ini_dest == IWL_FW_INI_LOCATION_INVALID)) fwrt->trans->dbg.ini_dest == IWL_FW_INI_LOCATION_INVALID))
return; return 0;
if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) { if (fw_has_capa(&fwrt->fw->ucode_capa,
IWL_ERR(fwrt, IWL_UCODE_TLV_CAPA_DBG_SUSPEND_RESUME_CMD_SUPP))
"WRT: unsupported device family %d for debug restart recording\n", ret = iwl_fw_dbg_suspend_resume_hcmd(fwrt->trans, stop);
fwrt->trans->cfg->device_family); else if (stop)
return; iwl_fw_dbg_stop_recording(fwrt->trans, params);
} else
_iwl_fw_dbg_restart_recording(fwrt->trans, params); ret = iwl_fw_dbg_restart_recording(fwrt->trans, params);
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
iwl_fw_set_dbg_rec_on(fwrt); if (!ret) {
if (stop)
fwrt->trans->dbg.rec_on = false;
else
iwl_fw_set_dbg_rec_on(fwrt);
}
#endif #endif
return ret;
} }
IWL_EXPORT_SYMBOL(iwl_fw_dbg_restart_recording); IWL_EXPORT_SYMBOL(iwl_fw_dbg_stop_restart_recording);
...@@ -262,12 +262,9 @@ _iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt, ...@@ -262,12 +262,9 @@ _iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt,
_iwl_fw_dbg_trigger_simple_stop((fwrt), (wdev), \ _iwl_fw_dbg_trigger_simple_stop((fwrt), (wdev), \
iwl_fw_dbg_get_trigger((fwrt)->fw,\ iwl_fw_dbg_get_trigger((fwrt)->fw,\
(trig))) (trig)))
int iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
void iwl_fw_dbg_stop_recording(struct iwl_trans *trans, struct iwl_fw_dbg_params *params,
struct iwl_fw_dbg_params *params); bool stop);
void iwl_fw_dbg_restart_recording(struct iwl_fw_runtime *fwrt,
struct iwl_fw_dbg_params *params);
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
static inline void iwl_fw_set_dbg_rec_on(struct iwl_fw_runtime *fwrt) static inline void iwl_fw_set_dbg_rec_on(struct iwl_fw_runtime *fwrt)
......
...@@ -465,6 +465,7 @@ enum iwl_ucode_tlv_capa { ...@@ -465,6 +465,7 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_LED_CMD_SUPPORT = (__force iwl_ucode_tlv_capa_t)88, IWL_UCODE_TLV_CAPA_LED_CMD_SUPPORT = (__force iwl_ucode_tlv_capa_t)88,
IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT = (__force iwl_ucode_tlv_capa_t)89, IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT = (__force iwl_ucode_tlv_capa_t)89,
IWL_UCODE_TLV_CAPA_CSI_REPORTING = (__force iwl_ucode_tlv_capa_t)90, IWL_UCODE_TLV_CAPA_CSI_REPORTING = (__force iwl_ucode_tlv_capa_t)90,
IWL_UCODE_TLV_CAPA_DBG_SUSPEND_RESUME_CMD_SUPP = (__force iwl_ucode_tlv_capa_t)92,
/* set 3 */ /* set 3 */
IWL_UCODE_TLV_CAPA_MLME_OFFLOAD = (__force iwl_ucode_tlv_capa_t)96, IWL_UCODE_TLV_CAPA_MLME_OFFLOAD = (__force iwl_ucode_tlv_capa_t)96,
......
...@@ -1083,7 +1083,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, ...@@ -1083,7 +1083,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
* recording automatically. * recording automatically.
*/ */
if (mvm->trans->cfg->device_family < IWL_DEVICE_FAMILY_9000) if (mvm->trans->cfg->device_family < IWL_DEVICE_FAMILY_9000)
iwl_fw_dbg_stop_recording(mvm->trans, NULL); iwl_fw_dbg_stop_restart_recording(&mvm->fwrt, NULL, true);
/* must be last -- this switches firmware state */ /* must be last -- this switches firmware state */
ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd); ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd);
......
...@@ -465,6 +465,7 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = { ...@@ -465,6 +465,7 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
* Access is done through binary search * Access is done through binary search
*/ */
static const struct iwl_hcmd_names iwl_mvm_debug_names[] = { static const struct iwl_hcmd_names iwl_mvm_debug_names[] = {
HCMD_NAME(DBGC_SUSPEND_RESUME),
HCMD_NAME(MFU_ASSERT_DUMP_NTF), HCMD_NAME(MFU_ASSERT_DUMP_NTF),
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment