Commit 42da1cc7 authored by Cheng Wang's avatar Cheng Wang Committed by Kalle Valo
Browse files

ath11k: add support of firmware logging for WCN6855



Host enables WMI firmware logging feature via QMI message.
Host receives firmware logging messages on WMI_DIAG_EVENTID, then
sends logging messages to user space via event tracing infrastructure.

Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1

Signed-off-by: default avatarCheng Wang <quic_chengwan@quicinc.com>
Signed-off-by: default avatarKalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20211220121053.357087-1-quic_chengwan@quicinc.com
parent d943fdad
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.alloc_cacheable_memory = true,
		.wakeup_mhi = false,
		.supports_rssi_stats = false,
		.fw_wmi_diag_event = false,
	},
	{
		.hw_rev = ATH11K_HW_IPQ6018_HW10,
@@ -159,6 +160,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.alloc_cacheable_memory = true,
		.wakeup_mhi = false,
		.supports_rssi_stats = false,
		.fw_wmi_diag_event = false,
	},
	{
		.name = "qca6390 hw2.0",
@@ -221,6 +223,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.alloc_cacheable_memory = false,
		.wakeup_mhi = true,
		.supports_rssi_stats = true,
		.fw_wmi_diag_event = true,
	},
	{
		.name = "qcn9074 hw1.0",
@@ -283,6 +286,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.alloc_cacheable_memory = true,
		.wakeup_mhi = false,
		.supports_rssi_stats = false,
		.fw_wmi_diag_event = false,
	},
	{
		.name = "wcn6855 hw2.0",
@@ -345,6 +349,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.alloc_cacheable_memory = false,
		.wakeup_mhi = true,
		.supports_rssi_stats = true,
		.fw_wmi_diag_event = true,
	},
	{
		.name = "wcn6855 hw2.1",
@@ -406,6 +411,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
		.alloc_cacheable_memory = false,
		.wakeup_mhi = true,
		.supports_rssi_stats = true,
		.fw_wmi_diag_event = true,
	},
};

+1 −0
Original line number Diff line number Diff line
@@ -191,6 +191,7 @@ struct ath11k_hw_params {
	bool alloc_cacheable_memory;
	bool wakeup_mhi;
	bool supports_rssi_stats;
	bool fw_wmi_diag_event;
};

struct ath11k_hw_ops {
+94 −0
Original line number Diff line number Diff line
@@ -1584,6 +1584,50 @@ static struct qmi_elem_info qmi_wlanfw_cold_boot_cal_done_ind_msg_v01_ei[] = {
	},
};

static 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,
					   enablefwlog_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,
					   enablefwlog),
	},
	{
		.data_type	= QMI_EOTI,
		.array_type	= NO_ARRAY,
		.tlv_type	= QMI_COMMON_TLV_TYPE,
	},
};

static 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 int ath11k_qmi_host_cap_send(struct ath11k_base *ab)
{
	struct qmi_wlanfw_host_cap_req_msg_v01 req;
@@ -2504,6 +2548,48 @@ static int ath11k_qmi_wlanfw_wlan_cfg_send(struct ath11k_base *ab)
	return ret;
}

static int ath11k_qmi_wlanfw_wlan_ini_send(struct ath11k_base *ab, bool enable)
{
	int ret;
	struct qmi_txn txn;
	struct qmi_wlanfw_wlan_ini_req_msg_v01 req = {};
	struct qmi_wlanfw_wlan_ini_resp_msg_v01 resp = {};

	req.enablefwlog_valid = true;
	req.enablefwlog = enable ? 1 : 0;

	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,
			       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) {
		ath11k_warn(ab, "qmi failed to send wlan ini request, err = %d\n",
			    ret);
		qmi_txn_cancel(&txn);
		goto out;
	}

	ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
	if (ret < 0) {
		ath11k_warn(ab, "qmi failed wlan ini request, err = %d\n", ret);
		goto out;
	}

	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
		ath11k_warn(ab, "qmi wlan ini request failed, result: %d, err: %d\n",
			    resp.resp.result, resp.resp.error);
		ret = -EINVAL;
	}

out:
	return ret;
}

void ath11k_qmi_firmware_stop(struct ath11k_base *ab)
{
	int ret;
@@ -2524,6 +2610,14 @@ int ath11k_qmi_firmware_start(struct ath11k_base *ab,

	ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware start\n");

	if (ab->hw_params.fw_wmi_diag_event) {
		ret = ath11k_qmi_wlanfw_wlan_ini_send(ab, true);
		if (ret < 0) {
			ath11k_warn(ab, "qmi failed to send wlan fw ini:%d\n", ret);
			return ret;
		}
	}

	ret = ath11k_qmi_wlanfw_wlan_cfg_send(ab);
	if (ret < 0) {
		ath11k_warn(ab, "qmi failed to send wlan cfg: %d\n", ret);
+12 −0
Original line number Diff line number Diff line
@@ -428,10 +428,12 @@ struct qmi_wlanfw_m3_info_resp_msg_v01 {
#define QMI_WLANFW_WLAN_MODE_RESP_MSG_V01_MAX_LEN	7
#define QMI_WLANFW_WLAN_CFG_REQ_MSG_V01_MAX_LEN		803
#define QMI_WLANFW_WLAN_CFG_RESP_MSG_V01_MAX_LEN	7
#define QMI_WLANFW_WLAN_INI_REQ_MSG_V01_MAX_LEN		4
#define QMI_WLANFW_WLAN_MODE_REQ_V01			0x0022
#define QMI_WLANFW_WLAN_MODE_RESP_V01			0x0022
#define QMI_WLANFW_WLAN_CFG_REQ_V01			0x0023
#define QMI_WLANFW_WLAN_CFG_RESP_V01			0x0023
#define QMI_WLANFW_WLAN_INI_REQ_V01			0x002F
#define QMI_WLANFW_MAX_STR_LEN_V01			16
#define QMI_WLANFW_MAX_NUM_CE_V01			12
#define QMI_WLANFW_MAX_NUM_SVC_V01			24
@@ -473,6 +475,16 @@ struct qmi_wlanfw_wlan_cfg_resp_msg_v01 {
	struct qmi_response_type_v01 resp;
};

struct qmi_wlanfw_wlan_ini_req_msg_v01 {
	/* Must be set to true if enablefwlog is being passed */
	u8 enablefwlog_valid;
	u8 enablefwlog;
};

struct qmi_wlanfw_wlan_ini_resp_msg_v01 {
	struct qmi_response_type_v01 resp;
};

int ath11k_qmi_firmware_start(struct ath11k_base *ab,
			      u32 mode);
void ath11k_qmi_firmware_stop(struct ath11k_base *ab);
+28 −0
Original line number Diff line number Diff line
@@ -280,6 +280,34 @@ TRACE_EVENT(ath11k_log_dbg_dump,
		__get_str(msg)
	)
);

TRACE_EVENT(ath11k_wmi_diag,
	    TP_PROTO(struct ath11k_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 */
Loading