Index: backports-20200415-4.4.60-9de9a9b19d3f/drivers/net/wireless/ath/ath11k/core.c =================================================================== --- backports-20200415-4.4.60-9de9a9b19d3f.orig/drivers/net/wireless/ath/ath11k/core.c +++ backports-20200415-4.4.60-9de9a9b19d3f/drivers/net/wireless/ath/ath11k/core.c @@ -643,6 +643,9 @@ int ath11k_core_qmi_firmware_ready(struc #endif ath11k_ahb_ext_irq_enable(ab); + + ath11k_config_qdss(ab); + mutex_unlock(&ab->core_lock); return 0; Index: backports-20200415-4.4.60-9de9a9b19d3f/drivers/net/wireless/ath/ath11k/core.h =================================================================== --- backports-20200415-4.4.60-9de9a9b19d3f.orig/drivers/net/wireless/ath/ath11k/core.h +++ backports-20200415-4.4.60-9de9a9b19d3f/drivers/net/wireless/ath/ath11k/core.h @@ -879,6 +879,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); void ath11k_core_halt(struct ath11k *ar); Index: backports-20200415-4.4.60-9de9a9b19d3f/drivers/net/wireless/ath/ath11k/qmi.c =================================================================== --- backports-20200415-4.4.60-9de9a9b19d3f.orig/drivers/net/wireless/ath/ath11k/qmi.c +++ backports-20200415-4.4.60-9de9a9b19d3f/drivers/net/wireless/ath/ath11k/qmi.c @@ -14,6 +14,194 @@ unsigned int enable_cold_boot_cal = 1; module_param(enable_cold_boot_cal, uint, 0644); MODULE_PARM_DESC(enable_cold_boot_cal, "cold boot calibration enable:1 disable:0"); +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, @@ -1504,6 +1692,150 @@ 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", 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; @@ -1587,7 +1919,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; @@ -2114,6 +2451,27 @@ void ath11k_qmi_firmware_stop(struct ath } } +int ath11k_config_qdss(struct ath11k_base *ab) +{ + int ret; + + 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) { Index: backports-20200415-4.4.60-9de9a9b19d3f/drivers/net/wireless/ath/ath11k/qmi.h =================================================================== --- backports-20200415-4.4.60-9de9a9b19d3f.orig/drivers/net/wireless/ath/ath11k/qmi.h +++ backports-20200415-4.4.60-9de9a9b19d3f/drivers/net/wireless/ath/ath11k/qmi.h @@ -26,6 +26,8 @@ #define ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01 32 #define ATH11K_QMI_CALDB_SIZE 0x480000 #define ATH11K_QMI_DEFAULT_CAL_FILE_NAME "caldata.bin" +#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 @@ -122,7 +124,51 @@ struct ath11k_qmi { struct target_info target; }; -#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 @@ -160,13 +206,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 @@ -197,6 +245,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 { @@ -449,5 +503,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