Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Govind Singh and committed by
Kalle Valo
d9e47698 47ed1b4e

+86
+9
drivers/net/wireless/ath/ath10k/core.c
··· 32 32 static bool uart_print; 33 33 static bool skip_otp; 34 34 static bool rawmode; 35 + static bool fw_diag_log; 35 36 36 37 unsigned long ath10k_coredump_mask = BIT(ATH10K_FW_CRASH_DUMP_REGISTERS) | 37 38 BIT(ATH10K_FW_CRASH_DUMP_CE_DATA); ··· 43 42 module_param(uart_print, bool, 0644); 44 43 module_param(skip_otp, bool, 0644); 45 44 module_param(rawmode, bool, 0644); 45 + module_param(fw_diag_log, bool, 0644); 46 46 module_param_named(coredump_mask, ath10k_coredump_mask, ulong, 0444); 47 47 48 48 MODULE_PARM_DESC(debug_mask, "Debugging mask"); ··· 52 50 MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software"); 53 51 MODULE_PARM_DESC(rawmode, "Use raw 802.11 frame datapath"); 54 52 MODULE_PARM_DESC(coredump_mask, "Bitfield of what to include in firmware crash file"); 53 + MODULE_PARM_DESC(fw_diag_log, "Diag based fw log debugging"); 55 54 56 55 static const struct ath10k_hw_params ath10k_hw_params_list[] = { 57 56 { ··· 2781 2778 status = ath10k_debug_start(ar); 2782 2779 if (status) 2783 2780 goto err_hif_stop; 2781 + 2782 + status = ath10k_hif_set_target_log_mode(ar, fw_diag_log); 2783 + if (status && status != -EOPNOTSUPP) { 2784 + ath10k_warn(ar, "set traget log mode faileds: %d\n", status); 2785 + goto err_hif_stop; 2786 + } 2784 2787 2785 2788 return 0; 2786 2789
+1
drivers/net/wireless/ath/ath10k/core.h
··· 645 645 u32 nf_cal_period; 646 646 void *cal_data; 647 647 u32 enable_extd_tx_stats; 648 + u8 fw_dbglog_mode; 648 649 }; 649 650 650 651 enum ath10k_state {
+15
drivers/net/wireless/ath/ath10k/hif.h
··· 12 12 #include "bmi.h" 13 13 #include "debug.h" 14 14 15 + /* Types of fw logging mode */ 16 + enum ath_dbg_mode { 17 + ATH10K_ENABLE_FW_LOG_DIAG, 18 + ATH10K_ENABLE_FW_LOG_CE, 19 + }; 20 + 15 21 struct ath10k_hif_sg_item { 16 22 u16 transfer_id; 17 23 void *transfer_context; /* NULL = tx completion callback not called */ ··· 94 88 95 89 int (*get_target_info)(struct ath10k *ar, 96 90 struct bmi_target_info *target_info); 91 + int (*set_target_log_mode)(struct ath10k *ar, u8 fw_log_mode); 97 92 }; 98 93 99 94 static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id, ··· 237 230 return ar->hif.ops->get_target_info(ar, tgt_info); 238 231 } 239 232 233 + static inline int ath10k_hif_set_target_log_mode(struct ath10k *ar, 234 + u8 fw_log_mode) 235 + { 236 + if (!ar->hif.ops->set_target_log_mode) 237 + return -EOPNOTSUPP; 238 + 239 + return ar->hif.ops->set_target_log_mode(ar, fw_log_mode); 240 + } 240 241 #endif /* _HIF_H_ */
+45
drivers/net/wireless/ath/ath10k/qmi.c
··· 620 620 return ret; 621 621 } 622 622 623 + int ath10k_qmi_set_fw_log_mode(struct ath10k *ar, u8 fw_log_mode) 624 + { 625 + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); 626 + struct wlfw_ini_resp_msg_v01 resp = {}; 627 + struct ath10k_qmi *qmi = ar_snoc->qmi; 628 + struct wlfw_ini_req_msg_v01 req = {}; 629 + struct qmi_txn txn; 630 + int ret; 631 + 632 + req.enablefwlog_valid = 1; 633 + req.enablefwlog = fw_log_mode; 634 + 635 + ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_ini_resp_msg_v01_ei, 636 + &resp); 637 + if (ret < 0) 638 + goto out; 639 + 640 + ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn, 641 + QMI_WLFW_INI_REQ_V01, 642 + WLFW_INI_REQ_MSG_V01_MAX_MSG_LEN, 643 + wlfw_ini_req_msg_v01_ei, &req); 644 + if (ret < 0) { 645 + qmi_txn_cancel(&txn); 646 + ath10k_err(ar, "fail to send fw log reqest: %d\n", ret); 647 + goto out; 648 + } 649 + 650 + ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ); 651 + if (ret < 0) 652 + goto out; 653 + 654 + if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { 655 + ath10k_err(ar, "fw log request rejectedr: %d\n", 656 + resp.resp.error); 657 + ret = -EINVAL; 658 + goto out; 659 + } 660 + ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi fw log request completed, mode: %d\n", 661 + fw_log_mode); 662 + return 0; 663 + 664 + out: 665 + return ret; 666 + } 667 + 623 668 static int 624 669 ath10k_qmi_ind_register_send_sync_msg(struct ath10k_qmi *qmi) 625 670 {
+1
drivers/net/wireless/ath/ath10k/qmi.h
··· 114 114 int ath10k_qmi_register_service_notifier(struct notifier_block *nb); 115 115 int ath10k_qmi_init(struct ath10k *ar, u32 msa_size); 116 116 int ath10k_qmi_deinit(struct ath10k *ar); 117 + int ath10k_qmi_set_fw_log_mode(struct ath10k *ar, u8 fw_log_mode); 117 118 118 119 #endif /* ATH10K_QMI_H */
+15
drivers/net/wireless/ath/ath10k/snoc.c
··· 1050 1050 return ret; 1051 1051 } 1052 1052 1053 + static int ath10k_snoc_hif_set_target_log_mode(struct ath10k *ar, 1054 + u8 fw_log_mode) 1055 + { 1056 + u8 fw_dbg_mode; 1057 + 1058 + if (fw_log_mode) 1059 + fw_dbg_mode = ATH10K_ENABLE_FW_LOG_CE; 1060 + else 1061 + fw_dbg_mode = ATH10K_ENABLE_FW_LOG_DIAG; 1062 + 1063 + return ath10k_qmi_set_fw_log_mode(ar, fw_dbg_mode); 1064 + } 1065 + 1053 1066 #ifdef CONFIG_PM 1054 1067 static int ath10k_snoc_hif_suspend(struct ath10k *ar) 1055 1068 { ··· 1116 1103 .send_complete_check = ath10k_snoc_hif_send_complete_check, 1117 1104 .get_free_queue_number = ath10k_snoc_hif_get_free_queue_number, 1118 1105 .get_target_info = ath10k_snoc_hif_get_target_info, 1106 + .set_target_log_mode = ath10k_snoc_hif_set_target_log_mode, 1107 + 1119 1108 #ifdef CONFIG_PM 1120 1109 .suspend = ath10k_snoc_hif_suspend, 1121 1110 .resume = ath10k_snoc_hif_resume,