mirror of
https://github.com/torvalds/linux.git
synced 2026-06-02 19:43:40 +02:00
wifi: ath12k: add support for collecting firmware log
Currently there is no way to collect firmware log because firmware does not send it to host. Also host does not handle WMI_DIAG_EVENTID which is used by firmware to upload firmware log. So add support for it by firstly enabling firmware log upload via a QMI message, and secondly processing WMI DIAG event to expose it to userspace via trace event. This change applies to both WCN7850 and QCN9274. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com> Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com> Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> Link: https://msgid.link/20240115023726.2866-1-quic_bqiang@quicinc.com
This commit is contained in:
parent
6db6e70a17
commit
9f9df1a253
|
|
@ -1954,6 +1954,50 @@ static const struct qmi_elem_info qmi_wlanfw_fw_ready_ind_msg_v01_ei[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static const struct qmi_elem_info qmi_wlanfw_wlan_ini_req_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct qmi_wlanfw_wlan_ini_req_msg_v01,
|
||||
enable_fwlog_valid),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_UNSIGNED_1_BYTE,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(u8),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x10,
|
||||
.offset = offsetof(struct qmi_wlanfw_wlan_ini_req_msg_v01,
|
||||
enable_fwlog),
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct qmi_elem_info qmi_wlanfw_wlan_ini_resp_msg_v01_ei[] = {
|
||||
{
|
||||
.data_type = QMI_STRUCT,
|
||||
.elem_len = 1,
|
||||
.elem_size = sizeof(struct qmi_response_type_v01),
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = 0x02,
|
||||
.offset = offsetof(struct qmi_wlanfw_wlan_ini_resp_msg_v01,
|
||||
resp),
|
||||
.ei_array = qmi_response_type_v01_ei,
|
||||
},
|
||||
{
|
||||
.data_type = QMI_EOTI,
|
||||
.array_type = NO_ARRAY,
|
||||
.tlv_type = QMI_COMMON_TLV_TYPE,
|
||||
},
|
||||
};
|
||||
|
||||
static void ath12k_host_cap_parse_mlo(struct ath12k_base *ab,
|
||||
struct qmi_wlanfw_host_cap_req_msg_v01 *req)
|
||||
{
|
||||
|
|
@ -2853,6 +2897,49 @@ static int ath12k_qmi_wlanfw_wlan_cfg_send(struct ath12k_base *ab)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ath12k_qmi_wlanfw_wlan_ini_send(struct ath12k_base *ab)
|
||||
{
|
||||
struct qmi_wlanfw_wlan_ini_resp_msg_v01 resp = {};
|
||||
struct qmi_wlanfw_wlan_ini_req_msg_v01 req = {};
|
||||
struct qmi_txn txn;
|
||||
int ret;
|
||||
|
||||
req.enable_fwlog_valid = true;
|
||||
req.enable_fwlog = 1;
|
||||
|
||||
ret = qmi_txn_init(&ab->qmi.handle, &txn,
|
||||
qmi_wlanfw_wlan_ini_resp_msg_v01_ei, &resp);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
|
||||
ATH12K_QMI_WLANFW_WLAN_INI_REQ_V01,
|
||||
QMI_WLANFW_WLAN_INI_REQ_MSG_V01_MAX_LEN,
|
||||
qmi_wlanfw_wlan_ini_req_msg_v01_ei, &req);
|
||||
if (ret < 0) {
|
||||
qmi_txn_cancel(&txn);
|
||||
ath12k_warn(ab, "failed to send QMI wlan ini request: %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH12K_QMI_WLANFW_TIMEOUT_MS));
|
||||
if (ret < 0) {
|
||||
ath12k_warn(ab, "failed to receive QMI wlan ini request: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
|
||||
ath12k_warn(ab, "QMI wlan ini response failure: %d %d\n",
|
||||
resp.resp.result, resp.resp.error);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ath12k_qmi_firmware_stop(struct ath12k_base *ab)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -2869,6 +2956,12 @@ int ath12k_qmi_firmware_start(struct ath12k_base *ab,
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = ath12k_qmi_wlanfw_wlan_ini_send(ab);
|
||||
if (ret < 0) {
|
||||
ath12k_warn(ab, "qmi failed to send wlan fw ini: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath12k_qmi_wlanfw_wlan_cfg_send(ab);
|
||||
if (ret < 0) {
|
||||
ath12k_warn(ab, "qmi failed to send wlan cfg:%d\n", ret);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ATH12K_QMI_H
|
||||
|
|
@ -576,6 +576,21 @@ struct qmi_wlanfw_wlan_cfg_resp_msg_v01 {
|
|||
struct qmi_response_type_v01 resp;
|
||||
};
|
||||
|
||||
#define ATH12K_QMI_WLANFW_WLAN_INI_REQ_V01 0x002F
|
||||
#define ATH12K_QMI_WLANFW_WLAN_INI_RESP_V01 0x002F
|
||||
#define QMI_WLANFW_WLAN_INI_REQ_MSG_V01_MAX_LEN 7
|
||||
#define QMI_WLANFW_WLAN_INI_RESP_MSG_V01_MAX_LEN 7
|
||||
|
||||
struct qmi_wlanfw_wlan_ini_req_msg_v01 {
|
||||
/* Must be set to true if enable_fwlog is being passed */
|
||||
u8 enable_fwlog_valid;
|
||||
u8 enable_fwlog;
|
||||
};
|
||||
|
||||
struct qmi_wlanfw_wlan_ini_resp_msg_v01 {
|
||||
struct qmi_response_type_v01 resp;
|
||||
};
|
||||
|
||||
int ath12k_qmi_firmware_start(struct ath12k_base *ab,
|
||||
u32 mode);
|
||||
void ath12k_qmi_firmware_stop(struct ath12k_base *ab);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
|
||||
/*
|
||||
* Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2021-2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#if !defined(_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
|
||||
|
|
@ -140,6 +140,33 @@ TRACE_EVENT(ath12k_htt_rxdesc,
|
|||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(ath12k_wmi_diag,
|
||||
TP_PROTO(struct ath12k_base *ab, const void *data, size_t len),
|
||||
|
||||
TP_ARGS(ab, data, len),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(device, dev_name(ab->dev))
|
||||
__string(driver, dev_driver_string(ab->dev))
|
||||
__field(u16, len)
|
||||
__dynamic_array(u8, data, len)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(device, dev_name(ab->dev));
|
||||
__assign_str(driver, dev_driver_string(ab->dev));
|
||||
__entry->len = len;
|
||||
memcpy(__get_dynamic_array(data), data, len);
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"%s %s tlv diag len %d",
|
||||
__get_str(driver),
|
||||
__get_str(device),
|
||||
__entry->len
|
||||
)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/
|
||||
|
||||
/* we don't want to use include/trace/events */
|
||||
|
|
|
|||
|
|
@ -6664,6 +6664,12 @@ static void ath12k_rfkill_state_change_event(struct ath12k_base *ab,
|
|||
kfree(tb);
|
||||
}
|
||||
|
||||
static void
|
||||
ath12k_wmi_diag_event(struct ath12k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
trace_ath12k_wmi_diag(ab, skb->data, skb->len);
|
||||
}
|
||||
|
||||
static void ath12k_wmi_op_rx(struct ath12k_base *ab, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_cmd_hdr *cmd_hdr;
|
||||
|
|
@ -6774,6 +6780,9 @@ static void ath12k_wmi_op_rx(struct ath12k_base *ab, struct sk_buff *skb)
|
|||
case WMI_VDEV_DELETE_RESP_EVENTID:
|
||||
ath12k_vdev_delete_resp_event(ab, skb);
|
||||
break;
|
||||
case WMI_DIAG_EVENTID:
|
||||
ath12k_wmi_diag_event(ab, skb);
|
||||
break;
|
||||
/* TODO: Add remaining events */
|
||||
default:
|
||||
ath12k_dbg(ab, ATH12K_DBG_WMI, "Unknown eventid: 0x%x\n", id);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user