wlan-ap-Telecominfraproject/feeds/wifi-ax/mac80211/patches/qca/038-ath11k-Adding-support-for-QDSS.patch
John Crispin 8cd26b4b50 ipq807x: update to 11.4-CS
Signed-off-by: John Crispin <john@phrozen.org>
2021-09-14 09:16:23 +02:00

529 lines
14 KiB
Diff

--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -915,6 +915,9 @@ int ath11k_core_qmi_firmware_ready(struc
}
#endif
ath11k_hif_irq_enable(ab);
+
+ ath11k_config_qdss(ab);
+
mutex_unlock(&ab->core_lock);
return 0;
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -928,6 +928,7 @@ struct ath11k_base *ath11k_core_alloc(st
void ath11k_core_free(struct ath11k_base *ath11k);
int ath11k_core_fetch_bdf(struct ath11k_base *ath11k,
struct ath11k_board_data *bd);
+int ath11k_config_qdss(struct ath11k_base *ab);
void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd);
int ath11k_core_check_dt(struct ath11k_base *ath11k);
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -20,6 +20,194 @@ module_param_named(cold_boot_cal, ath11k
MODULE_PARM_DESC(cold_boot_cal,
"Decrease the channel switch time but increase the driver load time (Default: true)");
+unsigned int enable_qdss_trace = 1;
+module_param(enable_qdss_trace, uint, 0644);
+MODULE_PARM_DESC(enable_qdss_trace, "qdss trace enable:1 disable:0");
+
+static struct qmi_elem_info qmi_wlanfw_qdss_trace_config_download_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_qdss_trace_config_download_req_msg_v01,
+ total_size_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u32),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct
+ qmi_wlanfw_qdss_trace_config_download_req_msg_v01,
+ total_size),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct
+ qmi_wlanfw_qdss_trace_config_download_req_msg_v01,
+ seg_id_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u32),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct
+ qmi_wlanfw_qdss_trace_config_download_req_msg_v01,
+ seg_id),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct
+ qmi_wlanfw_qdss_trace_config_download_req_msg_v01,
+ data_valid),
+ },
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(u16),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct
+ qmi_wlanfw_qdss_trace_config_download_req_msg_v01,
+ data_len),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = QMI_WLANFW_MAX_DATA_SIZE_V01,
+ .elem_size = sizeof(u8),
+ .array_type = VAR_LEN_ARRAY,
+ .tlv_type = 0x12,
+ .offset = offsetof(struct
+ qmi_wlanfw_qdss_trace_config_download_req_msg_v01,
+ data),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct
+ qmi_wlanfw_qdss_trace_config_download_req_msg_v01,
+ end_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x13,
+ .offset = offsetof(struct
+ qmi_wlanfw_qdss_trace_config_download_req_msg_v01,
+ end),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .array_type = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+static struct qmi_elem_info qmi_wlanfw_qdss_trace_config_download_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_qdss_trace_config_download_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 struct qmi_elem_info qmi_wlanfw_qdss_trace_mode_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_qdss_trace_mode_req_msg_v01,
+ mode_valid),
+ },
+ {
+ .data_type = QMI_SIGNED_4_BYTE_ENUM,
+ .elem_len = 1,
+ .elem_size = sizeof(enum wlfw_qdss_trace_mode_enum_v01),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x10,
+ .offset = offsetof(struct
+ qmi_wlanfw_qdss_trace_mode_req_msg_v01,
+ mode),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct
+ qmi_wlanfw_qdss_trace_mode_req_msg_v01,
+ option_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_8_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u64),
+ .array_type = NO_ARRAY,
+ .tlv_type = 0x11,
+ .offset = offsetof(struct
+ qmi_wlanfw_qdss_trace_mode_req_msg_v01,
+ option),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .array_type = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+static struct qmi_elem_info qmi_wlanfw_qdss_trace_mode_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_qdss_trace_mode_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 struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = {
{
.data_type = QMI_OPT_FLAG,
@@ -1510,6 +1698,156 @@ static struct qmi_elem_info qmi_wlanfw_c
},
};
+int wlfw_send_qdss_trace_config_download_req(struct ath11k_base *ab,
+ const u8 *buffer, unsigned int file_len)
+{
+ int ret = 0;
+ struct qmi_wlanfw_qdss_trace_config_download_req_msg_v01 *req;
+ struct qmi_wlanfw_qdss_trace_config_download_resp_msg_v01 resp;
+ struct qmi_txn txn = {};
+ const u8 *temp = buffer;
+ unsigned int remaining;
+
+ req = kzalloc(sizeof(*req), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ memset(&resp, 0, sizeof(resp));
+
+ remaining = file_len;
+ while (remaining) {
+ req->total_size_valid = 1;
+ req->total_size = file_len;
+ req->seg_id_valid = 1;
+ req->data_valid = 1;
+ req->end_valid = 1;
+
+ if (remaining > QMI_WLANFW_MAX_DATA_SIZE_V01) {
+ req->data_len = QMI_WLANFW_MAX_DATA_SIZE_V01;
+ } else {
+ req->data_len = remaining;
+ req->end = 1;
+ }
+ memcpy(req->data, temp, req->data_len);
+
+ ret = qmi_txn_init(&ab->qmi.handle, &txn,
+ qmi_wlanfw_qdss_trace_config_download_resp_msg_v01_ei,
+ &resp);
+ if (ret < 0)
+ goto out;
+
+ ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
+ QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_V01,
+ QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_MSG_V01_MAX_LEN,
+ qmi_wlanfw_qdss_trace_config_download_req_msg_v01_ei, req);
+ if (ret < 0) {
+ ath11k_warn(ab, "Failed to send QDSS config download request,err = %d\n", ret);
+ goto out;
+ }
+
+ ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
+ if (ret < 0)
+ goto out;
+
+ if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+ ath11k_warn(ab, "QDSS config download request failed, result: %d, err: %d\n",
+ resp.resp.result, resp.resp.error);
+ ret = -EINVAL;
+ goto out;
+ }
+ remaining -= req->data_len;
+ temp += req->data_len;
+ req->seg_id++;
+ }
+
+out:
+ kfree(req);
+ return ret;
+}
+
+int ath11k_send_qdss_trace_mode_req(struct ath11k_base *ab,
+ enum wlfw_qdss_trace_mode_enum_v01 mode)
+{
+ int ret = 0;
+ struct qmi_txn txn = {};
+ struct qmi_wlanfw_qdss_trace_mode_req_msg_v01 req;
+ struct qmi_wlanfw_qdss_trace_mode_resp_msg_v01 resp;
+
+ memset(&req, 0, sizeof(req));
+ memset(&resp, 0, sizeof(resp));
+
+ req.mode_valid = 1;
+ req.mode = mode;
+ req.option_valid = 1;
+ req.option = 0;
+
+ ret = qmi_txn_init(&ab->qmi.handle, &txn,
+ qmi_wlanfw_qdss_trace_mode_resp_msg_v01_ei, &resp);
+ if (ret < 0)
+ goto out;
+
+ ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
+ QMI_WLANFW_QDSS_TRACE_MODE_REQ_V01,
+ QMI_WLANFW_QDSS_TRACE_MODE_REQ_MSG_V01_MAX_LEN,
+ qmi_wlanfw_qdss_trace_mode_req_msg_v01_ei, &req);
+ if (ret < 0) {
+ ath11k_warn(ab, "Failed to send QDSS trace mode request,err = %d\n", ret);
+ goto out;
+ }
+
+ ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
+ if (ret < 0)
+ goto out;
+
+ if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+ ath11k_warn(ab, "QDSS trace more request failed, result: %d, err: %d\n",
+ resp.resp.result, resp.resp.error);
+ ret = -EINVAL;
+ goto out;
+ }
+out:
+ return ret;
+}
+
+static int ath11k_qmi_enable_qdss_trace(struct ath11k_base *ab,
+ enum wlfw_qdss_trace_mode_enum_v01 mode)
+{
+ return ath11k_send_qdss_trace_mode_req(ab, mode);
+}
+
+static int ath11k_qmi_send_qdss_config(struct ath11k_base *ab)
+{
+ struct device *dev = ab->dev;
+ const struct firmware *fw_entry;
+ char filename[ATH11K_QMI_MAX_QDSS_CONFIG_FILE_NAME_SIZE];
+ int ret;
+
+ snprintf(filename, sizeof(filename),
+ "%s/%s/%s", ATH11K_FW_DIR, ab->hw_params.fw.dir, ATH11K_QMI_DEFAULT_QDSS_CONFIG_FILE_NAME);
+ ret = request_firmware(&fw_entry, filename, dev);
+ if (ret) {
+ /* for backward compatability */
+ snprintf(filename, sizeof(filename),
+ "%s", ATH11K_QMI_DEFAULT_QDSS_CONFIG_FILE_NAME);
+ ret = request_firmware(&fw_entry, filename, dev);
+ if (ret) {
+ ath11k_warn(ab, "qmi failed to load QDSS config: %s\n", filename);
+ return ret;
+ }
+ }
+
+ ret = wlfw_send_qdss_trace_config_download_req(ab, fw_entry->data,
+ fw_entry->size);
+ if (ret < 0) {
+ ath11k_warn(ab, "qmi failed to load QDSS config to FW: %d\n", ret);
+ goto out;
+ }
+out:
+ release_firmware(fw_entry);
+
+ return ret;
+}
+
static int ath11k_qmi_host_cap_send(struct ath11k_base *ab)
{
struct qmi_wlanfw_host_cap_req_msg_v01 req;
@@ -1615,7 +1953,12 @@ static int ath11k_qmi_fw_ind_register_se
req->cal_done_enable = 1;
req->fw_init_done_enable_valid = 1;
req->fw_init_done_enable = 1;
-
+ req->qdss_trace_req_mem_enable_valid = 1;
+ req->qdss_trace_req_mem_enable = 1;
+ req->qdss_trace_save_enable_valid = 1;
+ req->qdss_trace_save_enable = 1;
+ req->qdss_trace_free_enable_valid = 1;
+ req->qdss_trace_free_enable = 1;
req->pin_connect_result_enable_valid = 0;
req->pin_connect_result_enable = 0;
@@ -2382,6 +2725,31 @@ void ath11k_qmi_firmware_stop(struct ath
}
}
+int ath11k_config_qdss(struct ath11k_base *ab)
+{
+ int ret;
+
+ /* Disabling qdss trace for FTM as it causes hig evt latency in FW */
+ if (ab->fw_mode == ATH11K_FIRMWARE_MODE_FTM)
+ return 0;
+
+ if (enable_qdss_trace) {
+ ret = ath11k_qmi_send_qdss_config(ab);
+ if (ret < 0) {
+ ath11k_warn(ab, "Failed to download QDSS config to FW: %d\n", ret);
+ return ret;
+ }
+ ret = ath11k_qmi_enable_qdss_trace(ab, QMI_WLANFW_QDSS_TRACE_ON_V01);
+ if (ret < 0) {
+ ath11k_warn(ab, "Failed to enable QDSS trace: %d\n", ret);
+ return ret;
+ }
+ ath11k_info(ab, "QDSS configuration is completed\n");
+ }
+
+ return 0;
+}
+
int ath11k_qmi_firmware_start(struct ath11k_base *ab,
u32 mode)
{
--- a/drivers/net/wireless/ath/ath11k/qmi.h
+++ b/drivers/net/wireless/ath/ath11k/qmi.h
@@ -30,6 +30,8 @@
#define ATH11K_QMI_CALDB_SIZE 0x480000
#define ATH11K_QMI_BDF_EXT_STR_LENGTH 0x20
#define ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT 3
+#define ATH11K_QMI_MAX_QDSS_CONFIG_FILE_NAME_SIZE 64
+#define ATH11K_QMI_DEFAULT_QDSS_CONFIG_FILE_NAME "qdss_trace_config.bin"
#define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035
#define QMI_WLFW_FW_MEM_READY_IND_V01 0x0037
@@ -138,7 +140,51 @@ struct ath11k_qmi {
wait_queue_head_t cold_boot_waitq;
};
-#define QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN 189
+#define QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_MSG_V01_MAX_LEN 6167
+#define QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_RESP_MSG_V01_MAX_LEN 7
+#define QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_V01 0x0044
+#define QMI_WLANFW_QDSS_TRACE_CONFIG_DOWNLOAD_RESP_V01 0x0044
+
+struct qmi_wlanfw_qdss_trace_config_download_req_msg_v01 {
+ u8 total_size_valid;
+ u32 total_size;
+ u8 seg_id_valid;
+ u32 seg_id;
+ u8 data_valid;
+ u32 data_len;
+ u8 data[QMI_WLANFW_MAX_DATA_SIZE_V01];
+ u8 end_valid;
+ u8 end;
+};
+
+struct qmi_wlanfw_qdss_trace_config_download_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+};
+
+#define QMI_WLANFW_QDSS_TRACE_MODE_REQ_V01 0x0045
+#define QMI_WLANFW_QDSS_TRACE_MODE_REQ_MSG_V01_MAX_LEN 18
+#define QMI_WLANFW_QDSS_TRACE_MODE_RESP_MSG_V01_MAX_LEN 7
+#define QMI_WLANFW_QDSS_TRACE_MODE_RESP_V01 0x0045
+
+enum wlfw_qdss_trace_mode_enum_v01 {
+ WLFW_QDSS_TRACE_MODE_ENUM_MIN_VAL_V01 = INT_MIN,
+ QMI_WLANFW_QDSS_TRACE_OFF_V01 = 0,
+ QMI_WLANFW_QDSS_TRACE_ON_V01 = 1,
+ WLFW_QDSS_TRACE_MODE_ENUM_MAX_VAL_V01 = INT_MAX,
+};
+
+struct qmi_wlanfw_qdss_trace_mode_req_msg_v01 {
+ u8 mode_valid;
+ enum wlfw_qdss_trace_mode_enum_v01 mode;
+ u8 option_valid;
+ u64 option;
+};
+
+struct qmi_wlanfw_qdss_trace_mode_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+};
+
+#define QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN 194
#define QMI_WLANFW_HOST_CAP_REQ_V01 0x0034
#define QMI_WLANFW_HOST_CAP_RESP_MSG_V01_MAX_LEN 7
#define QMI_WLFW_HOST_CAP_RESP_V01 0x0034
@@ -177,13 +223,15 @@ struct qmi_wlanfw_host_cap_req_msg_v01 {
u32 mem_bucket;
u8 mem_cfg_mode_valid;
u8 mem_cfg_mode;
+ u8 cal_duration_valid;
+ u16 cal_duration;
};
struct qmi_wlanfw_host_cap_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
-#define QMI_WLANFW_IND_REGISTER_REQ_MSG_V01_MAX_LEN 54
+#define QMI_WLANFW_IND_REGISTER_REQ_MSG_V01_MAX_LEN 66
#define QMI_WLANFW_IND_REGISTER_REQ_V01 0x0020
#define QMI_WLANFW_IND_REGISTER_RESP_MSG_V01_MAX_LEN 18
#define QMI_WLANFW_IND_REGISTER_RESP_V01 0x0020
@@ -214,6 +262,12 @@ struct qmi_wlanfw_ind_register_req_msg_v
u8 xo_cal_enable;
u8 cal_done_enable_valid;
u8 cal_done_enable;
+ u8 qdss_trace_req_mem_enable_valid;
+ u8 qdss_trace_req_mem_enable;
+ u8 qdss_trace_save_enable_valid;
+ u8 qdss_trace_save_enable;
+ u8 qdss_trace_free_enable_valid;
+ u8 qdss_trace_free_enable;
};
struct qmi_wlanfw_ind_register_resp_msg_v01 {
@@ -474,5 +528,11 @@ void ath11k_qmi_event_work(struct work_s
void ath11k_qmi_msg_recv_work(struct work_struct *work);
void ath11k_qmi_deinit_service(struct ath11k_base *ab);
int ath11k_qmi_init_service(struct ath11k_base *ab);
+int wlfw_send_qdss_trace_config_download_req(struct ath11k_base *ab,
+ const u8 *buffer, unsigned int len);
+
+int ath11k_send_qdss_trace_mode_req(struct ath11k_base *ab,
+ enum wlfw_qdss_trace_mode_enum_v01 mode);
+
#endif