iwlwifi: dbg: support debug recording suspend resume command
Support the new DBGC_SUSPEND_RESUME command to change the recording state. Signed-off-by: Shahar S Matityahu <shahar.s.matityahu@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
parent
203c83d3b2
commit
576058330f
6 changed files with 87 additions and 55 deletions
|
@ -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 @@
|
||||||
* 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 {
|
||||||
* &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 {
|
||||||
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 {
|
||||||
}; /* 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)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
iwl_fw_dbg_stop_recording(fwrt->trans, ¶ms);
|
if (iwl_fw_dbg_stop_restart_recording(fwrt, ¶ms, 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)
|
||||||
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, ¶ms);
|
iwl_fw_dbg_stop_restart_recording(fwrt, ¶ms, 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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
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,
|
||||||
*/
|
*/
|
||||||
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,
|
static int iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
|
||||||
struct iwl_fw_dbg_params *params)
|
struct iwl_fw_dbg_params *params)
|
||||||
{
|
{
|
||||||
/* if the FW crashed or not debug monitor cfg was given, there is
|
if (!params)
|
||||||
* no point in stopping
|
return -EIO;
|
||||||
*/
|
|
||||||
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,
|
|
||||||
struct iwl_fw_dbg_params *params)
|
|
||||||
{
|
|
||||||
if (WARN_ON(!params))
|
|
||||||
return;
|
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
_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 {
|
||||||
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,
|
||||||
* 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[] = {
|
||||||
* 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),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue