OSDN Git Service

ath11k: add support of firmware logging for WCN6855
authorCheng Wang <quic_chengwan@quicinc.com>
Mon, 20 Dec 2021 12:10:53 +0000 (20:10 +0800)
committerKalle Valo <quic_kvalo@quicinc.com>
Wed, 22 Dec 2021 06:03:13 +0000 (08:03 +0200)
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: Cheng Wang <quic_chengwan@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20211220121053.357087-1-quic_chengwan@quicinc.com
drivers/net/wireless/ath/ath11k/core.c
drivers/net/wireless/ath/ath11k/hw.h
drivers/net/wireless/ath/ath11k/qmi.c
drivers/net/wireless/ath/ath11k/qmi.h
drivers/net/wireless/ath/ath11k/trace.h
drivers/net/wireless/ath/ath11k/wmi.c

index 08ba8d7..293563b 100644 (file)
@@ -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,
        },
 };
 
index 059b9f9..29934b3 100644 (file)
@@ -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 {
index 4c21d48..65d3c6b 100644 (file)
@@ -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 @@ out:
        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);
index 983b0b1..ba2eff4 100644 (file)
@@ -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);
index 02003dc..a02e547 100644 (file)
@@ -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 */
index 747e152..6b68ccf 100644 (file)
@@ -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);