提交 42da1cc7 编写于 作者: C Cheng Wang 提交者: Kalle Valo

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: NCheng Wang <quic_chengwan@quicinc.com>
Signed-off-by: NKalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20211220121053.357087-1-quic_chengwan@quicinc.com
上级 d943fdad
......@@ -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,
},
};
......
......@@ -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 {
......
......@@ -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);
......
......@@ -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);
......
......@@ -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 */
......
......@@ -7525,6 +7525,13 @@ static void ath11k_wmi_event_wow_wakeup_host(struct ath11k_base *ab, struct sk_b
complete(&ab->wow.wakeup_completed);
}
static void
ath11k_wmi_diag_event(struct ath11k_base *ab,
struct sk_buff *skb)
{
trace_ath11k_wmi_diag(ab, skb->data, skb->len);
}
static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
{
struct wmi_cmd_hdr *cmd_hdr;
......@@ -7647,6 +7654,9 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
case WMI_RFKILL_STATE_CHANGE_EVENTID:
ath11k_rfkill_state_change_event(ab, skb);
break;
case WMI_DIAG_EVENTID:
ath11k_wmi_diag_event(ab, skb);
break;
/* TODO: Add remaining events */
default:
ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册