From 554d6283ec99cfa3b0aab011c372cc229ca80585 Mon Sep 17 00:00:00 2001 From: Anilkumar Kolli Date: Wed, 9 Sep 2020 19:04:08 +0530 Subject: [PATCH 06/15] ath11k: clean up bdf download sequence No functional changes, reorder code. Signed-off-by: Anilkumar Kolli --- drivers/net/wireless/ath/ath11k/qmi.c | 238 ++++++++++++++-------------------- drivers/net/wireless/ath/ath11k/qmi.h | 2 +- 2 files changed, 95 insertions(+), 145 deletions(-) --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c @@ -1139,6 +1139,79 @@ static struct qmi_elem_info qmi_wlanfw_c num_macs), }, { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x16, + .offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01, + voltage_mv_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x16, + .offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01, + voltage_mv), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x17, + .offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01, + time_freq_hz_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x17, + .offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01, + time_freq_hz), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x18, + .offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01, + otp_version_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x18, + .offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01, + otp_version), + }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x19, + .offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01, + eeprom_read_timeout_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .array_type = NO_ARRAY, + .tlv_type = 0x19, + .offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01, + eeprom_read_timeout), + }, + { + .data_type = QMI_EOTI, .array_type = NO_ARRAY, .tlv_type = QMI_COMMON_TLV_TYPE, @@ -2271,102 +2344,83 @@ static int ath11k_qmi_request_target_cap if (r) ath11k_dbg(ab, ATH11K_DBG_QMI, "DT bdf variant name not set.\n"); -out: - return ret; -} - -static int -ath11k_qmi_prepare_bdf_download(struct ath11k_base *ab, int type, - struct qmi_wlanfw_bdf_download_req_msg_v01 *req, - void __iomem *bdf_addr) -{ - const struct firmware *fw_entry; - struct ath11k_board_data bd; - u32 fw_size; - int ret; - - switch (type) { - case ATH11K_QMI_FILE_TYPE_BDF_GOLDEN: - memset(&bd, 0, sizeof(bd)); - - ret = ath11k_core_fetch_bdf(ab, &bd); - if (ret) { - ath11k_warn(ab, "qmi failed to load BDF\n"); - return ret; - } - - fw_size = min_t(u32, ab->hw_params.fw.board_size, bd.len); - memcpy_toio(bdf_addr, bd.data, fw_size); - ath11k_core_free_bdf(ab, &bd); - break; - case ATH11K_QMI_FILE_TYPE_CALDATA: - fw_entry = ath11k_core_firmware_request(ab, ATH11K_DEFAULT_CAL_FILE); - if (IS_ERR(fw_entry)) { - ret = PTR_ERR(fw_entry); - ath11k_warn(ab, - "qmi failed to load CAL data file:%s booting with minimal performance\n",ATH11K_DEFAULT_CAL_FILE); - return 0; - } - - fw_size = min_t(u32, ab->hw_params.fw.board_size, - fw_entry->size); - - memcpy_toio(bdf_addr + ATH11K_QMI_CALDATA_OFFSET, - fw_entry->data, fw_size); - - release_firmware(fw_entry); - break; - default: - return -EINVAL; + if (resp.eeprom_read_timeout_valid) { + ab->qmi.target.eeprom_read_timeout = + resp.eeprom_read_timeout; + ath11k_info(ab, "cal data supported from eeprom\n"); } - req->total_size = fw_size; - return 0; +out: + return ret; } -static int ath11k_qmi_load_bdf_fixed_addr(struct ath11k_base *ab) +static int ath11k_qmi_load_file_target_mem(struct ath11k_base *ab, + const u8 *data, u32 len, u8 type) { struct qmi_wlanfw_bdf_download_req_msg_v01 *req; struct qmi_wlanfw_bdf_download_resp_msg_v01 resp; struct qmi_txn txn = {}; + const u8 *temp = data; void __iomem *bdf_addr = NULL; - int type, ret; + u32 remaining; + int ret; req = kzalloc(sizeof(*req), GFP_KERNEL); if (!req) return -ENOMEM; memset(&resp, 0, sizeof(resp)); - bdf_addr = ioremap(ab->hw_params.bdf_addr, ATH11K_QMI_BDF_MAX_SIZE); - if (!bdf_addr) { - ath11k_warn(ab, "qmi ioremap error for BDF\n"); - ret = -EIO; - goto out; + if (ab->bus_params.fixed_bdf_addr) { + bdf_addr = ioremap(ab->hw_params.bdf_addr, ATH11K_QMI_BDF_MAX_SIZE); + if (!bdf_addr) { + ath11k_warn(ab, "qmi ioremap error for BDF\n"); + ret = -EIO; + goto out_req; + } } - for (type = 0; type < ATH11K_QMI_MAX_FILE_TYPE; type++) { + remaining = len; + + while (remaining) { req->valid = 1; req->file_id_valid = 1; req->file_id = ab->qmi.target.board_id; req->total_size_valid = 1; + req->total_size = remaining; req->seg_id_valid = 1; - req->seg_id = type; - req->data_valid = 0; - req->data_len = ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE; - req->bdf_type = 0; - req->bdf_type_valid = 0; + req->data_valid = 1; + req->bdf_type = type; + req->bdf_type_valid = 1; req->end_valid = 1; - req->end = 1; + req->end = 0; - ret = ath11k_qmi_prepare_bdf_download(ab, type, req, bdf_addr); - if (ret < 0) - goto out_qmi_bdf; + 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; + } + + if (ab->bus_params.fixed_bdf_addr || type == ATH11K_QMI_FILE_TYPE_EEPROM) { + req->data_valid = 0; + req->end = 1; + req->data_len = ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE; + } else { + memcpy(req->data, temp, req->data_len); + } + + if (ab->bus_params.fixed_bdf_addr) { + if (type == ATH11K_QMI_FILE_TYPE_CALDATA) + bdf_addr += ATH11K_QMI_CALDATA_OFFSET; + + memcpy_toio(bdf_addr, temp, len); + } ret = qmi_txn_init(&ab->qmi.handle, &txn, qmi_wlanfw_bdf_download_resp_msg_v01_ei, &resp); if (ret < 0) - goto out_qmi_bdf; + goto out; ret = qmi_send_request(&ab->qmi.handle, NULL, &txn, QMI_WLANFW_BDF_DOWNLOAD_REQ_V01, @@ -2374,120 +2428,113 @@ static int ath11k_qmi_load_bdf_fixed_add qmi_wlanfw_bdf_download_req_msg_v01_ei, req); if (ret < 0) { qmi_txn_cancel(&txn); - goto out_qmi_bdf; + goto out; } ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS)); if (ret < 0) - goto out_qmi_bdf; + goto out; if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { ath11k_warn(ab, "qmi BDF download failed, result: %d, err: %d\n", resp.resp.result, resp.resp.error); ret = -EINVAL; - goto out_qmi_bdf; + goto out; + } + if (ab->bus_params.fixed_bdf_addr || type == ATH11K_QMI_FILE_TYPE_EEPROM) { + remaining = 0; + } else { + remaining -= req->data_len; + temp += req->data_len; + req->seg_id++; } } -out_qmi_bdf: - iounmap(bdf_addr); out: + if (ab->bus_params.fixed_bdf_addr) + iounmap(bdf_addr); +out_req: kfree(req); return ret; } static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab) { - struct qmi_wlanfw_bdf_download_req_msg_v01 *req; - struct qmi_wlanfw_bdf_download_resp_msg_v01 resp; + char filename[ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE]; + const struct firmware *fw_entry; struct ath11k_board_data bd; - unsigned int remaining; - struct qmi_txn txn = {}; - int ret; - const u8 *temp; int bdf_type; - - req = kzalloc(sizeof(*req), GFP_KERNEL); - if (!req) - return -ENOMEM; - memset(&resp, 0, sizeof(resp)); + u32 fw_size, file_type; + u8 *tmp; + int ret = 0; memset(&bd, 0, sizeof(bd)); ret = ath11k_core_fetch_bdf(ab, &bd); if (ret) { - ath11k_warn(ab, "qmi failed to load bdf:\n"); - goto out; + ath11k_warn(ab, "qmi failed to fetch bdf\n"); + return ret; } - temp = bd.data; - remaining = bd.len; - - if (bd.len >= SELFMAG && memcmp(bd.data, ELFMAG, SELFMAG) == 0) - bdf_type = ATH11K_QMI_BDF_TYPE_ELF; - else - bdf_type = ATH11K_QMI_BDF_TYPE_BIN; + fw_size = bd.len; + fw_size = min_t(u32, ab->hw_params.fw.board_size, bd.len); - ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi bdf_type %d\n", bdf_type); - while (remaining) { - req->valid = 1; - req->file_id_valid = 1; - req->file_id = ab->qmi.target.board_id; - req->total_size_valid = 1; - req->total_size = bd.len; - req->seg_id_valid = 1; - req->data_valid = 1; - req->data_len = ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE; - req->bdf_type = bdf_type; - req->bdf_type_valid = 1; - req->end_valid = 1; - req->end = 0; + file_type = ATH11K_QMI_FILE_TYPE_BDF_GOLDEN; + ret = ath11k_qmi_load_file_target_mem(ab, bd.data, fw_size, file_type); + if (ret < 0) { + ath11k_warn(ab, "qmi failed to load bdf\n"); + goto out; + } - 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; - } + /* Load caldata */ + if(ab->bus_params.fixed_bdf_addr) { + snprintf(filename, sizeof(filename), + "%s", ATH11K_DEFAULT_CAL_FILE); + } else { + snprintf(filename, sizeof(filename), + "%s%d%s", + ATH11K_QMI_DEF_CAL_FILE_PREFIX, + ab->qmi.service_ins_id - (NODE_ID_BASE - 1), + ATH11K_QMI_DEF_CAL_FILE_SUFFIX); + } - memcpy(req->data, temp, req->data_len); + if (ab->qmi.target.eeprom_read_timeout) { + file_type = ATH11K_QMI_FILE_TYPE_EEPROM; + tmp = filename; + fw_size = ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE; + goto send_qmi_req; + } - ret = qmi_txn_init(&ab->qmi.handle, &txn, - qmi_wlanfw_bdf_download_resp_msg_v01_ei, - &resp); - if (ret < 0) - goto out_qmi_bdf; + file_type = ATH11K_QMI_FILE_TYPE_CALDATA; + fw_entry = ath11k_core_firmware_request(ab, filename); + if (IS_ERR(fw_entry)) { + ret = PTR_ERR(fw_entry); + ath11k_warn(ab, + "qmi failed to load CAL data file:%s\n", + filename); + goto out; + } + fw_size = min_t(u32, ab->hw_params.fw.board_size, fw_entry->size); + tmp = fw_entry->data; - ret = qmi_send_request(&ab->qmi.handle, NULL, &txn, - QMI_WLANFW_BDF_DOWNLOAD_REQ_V01, - QMI_WLANFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_LEN, - qmi_wlanfw_bdf_download_req_msg_v01_ei, req); - if (ret < 0) { - qmi_txn_cancel(&txn); - goto out_qmi_bdf; - } +send_qmi_req: + ret = ath11k_qmi_load_file_target_mem(ab, tmp, fw_size, file_type); + if (ret < 0) { + ath11k_warn(ab, "qmi failed to load caldata\n"); + goto out_qmi_cal; + } - ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS)); - if (ret < 0) - goto out_qmi_bdf; + ath11k_info(ab, "qmi caldata downloaded: type: %u\n", file_type); - if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { - ath11k_warn(ab, "qmi BDF download failed, result: %d, err: %d\n", - resp.resp.result, resp.resp.error); - ret = resp.resp.result; - goto out_qmi_bdf; - } - remaining -= req->data_len; - temp += req->data_len; - req->seg_id++; - } +out_qmi_cal: + if (file_type == ATH11K_QMI_FILE_TYPE_CALDATA) + release_firmware(fw_entry); -out_qmi_bdf: +out: ath11k_core_free_bdf(ab, &bd); + ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi BDF downloaded\n"); -out: - kfree(req); - return ret; + return 0; } static int ath11k_qmi_m3_load(struct ath11k_base *ab) @@ -2884,10 +2931,7 @@ static int ath11k_qmi_event_load_bdf(str return ret; } - if (ab->bus_params.fixed_bdf_addr) - ret = ath11k_qmi_load_bdf_fixed_addr(ab); - else - ret = ath11k_qmi_load_bdf_qmi(ab); + ret = ath11k_qmi_load_bdf_qmi(ab); if (ret < 0) { ath11k_warn(ab, "qmi failed to load board data file:%d\n", ret); return ret; --- a/drivers/net/wireless/ath/ath11k/qmi.h +++ b/drivers/net/wireless/ath/ath11k/qmi.h @@ -12,7 +12,7 @@ #include #define ATH11K_HOST_VERSION_STRING "WIN" -#define ATH11K_QMI_WLANFW_TIMEOUT_MS 5000 +#define ATH11K_QMI_WLANFW_TIMEOUT_MS 10000 #define ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE 64 #define ATH11K_QMI_CALDB_ADDRESS 0x4BA00000 #define ATH11K_QMI_BDF_MAX_SIZE (256 * 1024) @@ -47,7 +47,8 @@ struct ath11k_base; enum ath11k_qmi_file_type { ATH11K_QMI_FILE_TYPE_BDF_GOLDEN, - ATH11K_QMI_FILE_TYPE_CALDATA, + ATH11K_QMI_FILE_TYPE_CALDATA = 2, + ATH11K_QMI_FILE_TYPE_EEPROM, ATH11K_QMI_MAX_FILE_TYPE, }; @@ -108,6 +109,7 @@ struct target_info { u32 board_id; u32 soc_id; u32 fw_version; + u32 eeprom_read_timeout; char fw_build_timestamp[ATH11K_QMI_WLANFW_MAX_TIMESTAMP_LEN_V01 + 1]; char fw_build_id[ATH11K_QMI_WLANFW_MAX_BUILD_ID_LEN_V01 + 1]; char bdf_ext[ATH11K_QMI_BDF_EXT_STR_LENGTH]; @@ -184,7 +186,7 @@ struct qmi_wlanfw_qdss_trace_mode_resp_m struct qmi_response_type_v01 resp; }; -#define QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN 194 +#define QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN 261 #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 @@ -342,7 +344,7 @@ struct qmi_wlanfw_fw_cold_cal_done_ind_m }; #define QMI_WLANFW_CAP_REQ_MSG_V01_MAX_LEN 0 -#define QMI_WLANFW_CAP_RESP_MSG_V01_MAX_LEN 207 +#define QMI_WLANFW_CAP_RESP_MSG_V01_MAX_LEN 235 #define QMI_WLANFW_CAP_REQ_V01 0x0024 #define QMI_WLANFW_CAP_RESP_V01 0x0024 @@ -423,6 +425,14 @@ struct qmi_wlanfw_cap_resp_msg_v01 { char fw_build_id[ATH11K_QMI_WLANFW_MAX_BUILD_ID_LEN_V01 + 1]; u8 num_macs_valid; u8 num_macs; + u8 voltage_mv_valid; + u32 voltage_mv; + u8 time_freq_hz_valid; + u32 time_freq_hz; + u8 otp_version_valid; + u32 otp_version; + u8 eeprom_read_timeout_valid; + u32 eeprom_read_timeout; }; struct qmi_wlanfw_cap_req_msg_v01 { --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h @@ -74,8 +74,11 @@ #define ATH11K_BOARD_API2_FILE "board-2.bin" #define ATH11K_DEFAULT_BOARD_FILE "board.bin" #define ATH11K_DEFAULT_CAL_FILE "caldata.bin" +#define ATH11K_QMI_DEF_CAL_FILE_PREFIX "caldata_" +#define ATH11K_QMI_DEF_CAL_FILE_SUFFIX ".bin" #define ATH11K_AMSS_FILE "amss.bin" #define ATH11K_M3_FILE "m3.bin" +#define NODE_ID_BASE 0x27 enum ath11k_hw_rate_cck { ATH11K_HW_RATE_CCK_LP_11M = 0,