* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications 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
* it under the terms of version 2 of the GNU General Public License as
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* &struct iwl_dbg_mem_access_rsp
*/
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:
* &struct iwl_mfu_assert_dump_notif
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
* ( REPLY_ERROR = 0x2 )
}; /* LDBG_CFG_BODY_API_U_VER_2 (partially) */
} __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__ */
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");
if (fwrt->trans->dbg.ini_valid)
iwl_fw_error_dump(fwrt);
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:
clear_bit(wk_idx, &fwrt->dump.active_wks);
for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; 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_error_print_fseq_regs);
-static void _iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
- struct iwl_fw_dbg_params *params)
+static int iwl_fw_dbg_suspend_resume_hcmd(struct iwl_trans *trans, bool suspend)
+{
+ 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) {
iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
*/
usleep_range(700, 1000);
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,
- struct iwl_fw_dbg_params *params)
+static int iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
+ struct iwl_fw_dbg_params *params)
{
- if (WARN_ON(!params))
- return;
+ if (!params)
+ return -EIO;
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
iwl_clear_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
iwl_write_umac_prph(trans, DBGC_IN_SAMPLE, params->in_sample);
iwl_write_umac_prph(trans, DBGC_OUT_CTRL, params->out_ctrl);
}
+
+ return 0;
}
-void iwl_fw_dbg_restart_recording(struct iwl_fw_runtime *fwrt,
- struct iwl_fw_dbg_params *params)
+int iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
+ struct iwl_fw_dbg_params *params,
+ bool stop)
{
+ int ret = 0;
+
/* 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) ||
(!fwrt->trans->dbg.dest_tlv &&
fwrt->trans->dbg.ini_dest == IWL_FW_INI_LOCATION_INVALID))
- return;
+ return 0;
- if (fwrt->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
- IWL_ERR(fwrt,
- "WRT: unsupported device family %d for debug restart recording\n",
- fwrt->trans->cfg->device_family);
- return;
- }
- _iwl_fw_dbg_restart_recording(fwrt->trans, params);
+ if (fw_has_capa(&fwrt->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_DBG_SUSPEND_RESUME_CMD_SUPP))
+ ret = iwl_fw_dbg_suspend_resume_hcmd(fwrt->trans, stop);
+ else if (stop)
+ iwl_fw_dbg_stop_recording(fwrt->trans, params);
+ else
+ ret = iwl_fw_dbg_restart_recording(fwrt->trans, params);
#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
+
+ return ret;
}
-IWL_EXPORT_SYMBOL(iwl_fw_dbg_restart_recording);
+IWL_EXPORT_SYMBOL(iwl_fw_dbg_stop_restart_recording);