ath10k: Add WMI diag fw logging support for WCN3990

Integrated WiFi chipset ex:WCN399x supports fw logging
using WMI copy engine and shared mem DIAG based fw logging.
By default shared mem DIAG based fw logging is enabled.
To support WMI copy engine based fw logging add QMI
control message to enable WMI copy engine based fw logging.

Enable WMI based fw logging using fw_diag_log module parameter.

insmod ath10k_core.ko fw_diag_log=1

DIAG utility(https://github.com/andersson/diag) implements extraction
of diagnostics related messages between application processor and
various subsystems while shared mem DIAG based fw logging is enabled.

Testing: Tested on WCN3990/QCA6174 HW
Tested FW: WLAN.HL.3.1-00959-QCAHLSWMTPLZ-1

Signed-off-by: Govind Singh <govinds@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
Govind Singh 2019-06-03 18:14:52 +03:00 committed by Kalle Valo
parent 47ed1b4e5d
commit d9e4769896
6 changed files with 86 additions and 0 deletions

View File

@ -32,6 +32,7 @@ static unsigned int ath10k_cryptmode_param;
static bool uart_print;
static bool skip_otp;
static bool rawmode;
static bool fw_diag_log;
unsigned long ath10k_coredump_mask = BIT(ATH10K_FW_CRASH_DUMP_REGISTERS) |
BIT(ATH10K_FW_CRASH_DUMP_CE_DATA);
@ -42,6 +43,7 @@ module_param_named(cryptmode, ath10k_cryptmode_param, uint, 0644);
module_param(uart_print, bool, 0644);
module_param(skip_otp, bool, 0644);
module_param(rawmode, bool, 0644);
module_param(fw_diag_log, bool, 0644);
module_param_named(coredump_mask, ath10k_coredump_mask, ulong, 0444);
MODULE_PARM_DESC(debug_mask, "Debugging mask");
@ -50,6 +52,7 @@ MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software");
MODULE_PARM_DESC(rawmode, "Use raw 802.11 frame datapath");
MODULE_PARM_DESC(coredump_mask, "Bitfield of what to include in firmware crash file");
MODULE_PARM_DESC(fw_diag_log, "Diag based fw log debugging");
static const struct ath10k_hw_params ath10k_hw_params_list[] = {
{
@ -2779,6 +2782,12 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
if (status)
goto err_hif_stop;
status = ath10k_hif_set_target_log_mode(ar, fw_diag_log);
if (status && status != -EOPNOTSUPP) {
ath10k_warn(ar, "set traget log mode faileds: %d\n", status);
goto err_hif_stop;
}
return 0;
err_hif_stop:

View File

@ -645,6 +645,7 @@ struct ath10k_debug {
u32 nf_cal_period;
void *cal_data;
u32 enable_extd_tx_stats;
u8 fw_dbglog_mode;
};
enum ath10k_state {

View File

@ -12,6 +12,12 @@
#include "bmi.h"
#include "debug.h"
/* Types of fw logging mode */
enum ath_dbg_mode {
ATH10K_ENABLE_FW_LOG_DIAG,
ATH10K_ENABLE_FW_LOG_CE,
};
struct ath10k_hif_sg_item {
u16 transfer_id;
void *transfer_context; /* NULL = tx completion callback not called */
@ -88,6 +94,7 @@ struct ath10k_hif_ops {
int (*get_target_info)(struct ath10k *ar,
struct bmi_target_info *target_info);
int (*set_target_log_mode)(struct ath10k *ar, u8 fw_log_mode);
};
static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
@ -230,4 +237,12 @@ static inline int ath10k_hif_get_target_info(struct ath10k *ar,
return ar->hif.ops->get_target_info(ar, tgt_info);
}
static inline int ath10k_hif_set_target_log_mode(struct ath10k *ar,
u8 fw_log_mode)
{
if (!ar->hif.ops->set_target_log_mode)
return -EOPNOTSUPP;
return ar->hif.ops->set_target_log_mode(ar, fw_log_mode);
}
#endif /* _HIF_H_ */

View File

@ -620,6 +620,51 @@ out:
return ret;
}
int ath10k_qmi_set_fw_log_mode(struct ath10k *ar, u8 fw_log_mode)
{
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
struct wlfw_ini_resp_msg_v01 resp = {};
struct ath10k_qmi *qmi = ar_snoc->qmi;
struct wlfw_ini_req_msg_v01 req = {};
struct qmi_txn txn;
int ret;
req.enablefwlog_valid = 1;
req.enablefwlog = fw_log_mode;
ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_ini_resp_msg_v01_ei,
&resp);
if (ret < 0)
goto out;
ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
QMI_WLFW_INI_REQ_V01,
WLFW_INI_REQ_MSG_V01_MAX_MSG_LEN,
wlfw_ini_req_msg_v01_ei, &req);
if (ret < 0) {
qmi_txn_cancel(&txn);
ath10k_err(ar, "fail to send fw log reqest: %d\n", ret);
goto out;
}
ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
if (ret < 0)
goto out;
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
ath10k_err(ar, "fw log request rejectedr: %d\n",
resp.resp.error);
ret = -EINVAL;
goto out;
}
ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi fw log request completed, mode: %d\n",
fw_log_mode);
return 0;
out:
return ret;
}
static int
ath10k_qmi_ind_register_send_sync_msg(struct ath10k_qmi *qmi)
{

View File

@ -114,5 +114,6 @@ int ath10k_qmi_wlan_disable(struct ath10k *ar);
int ath10k_qmi_register_service_notifier(struct notifier_block *nb);
int ath10k_qmi_init(struct ath10k *ar, u32 msa_size);
int ath10k_qmi_deinit(struct ath10k *ar);
int ath10k_qmi_set_fw_log_mode(struct ath10k *ar, u8 fw_log_mode);
#endif /* ATH10K_QMI_H */

View File

@ -1050,6 +1050,19 @@ err_wlan_enable:
return ret;
}
static int ath10k_snoc_hif_set_target_log_mode(struct ath10k *ar,
u8 fw_log_mode)
{
u8 fw_dbg_mode;
if (fw_log_mode)
fw_dbg_mode = ATH10K_ENABLE_FW_LOG_CE;
else
fw_dbg_mode = ATH10K_ENABLE_FW_LOG_DIAG;
return ath10k_qmi_set_fw_log_mode(ar, fw_dbg_mode);
}
#ifdef CONFIG_PM
static int ath10k_snoc_hif_suspend(struct ath10k *ar)
{
@ -1103,6 +1116,8 @@ static const struct ath10k_hif_ops ath10k_snoc_hif_ops = {
.send_complete_check = ath10k_snoc_hif_send_complete_check,
.get_free_queue_number = ath10k_snoc_hif_get_free_queue_number,
.get_target_info = ath10k_snoc_hif_get_target_info,
.set_target_log_mode = ath10k_snoc_hif_set_target_log_mode,
#ifdef CONFIG_PM
.suspend = ath10k_snoc_hif_suspend,
.resume = ath10k_snoc_hif_resume,