blob: cbcb031beb77288e5c174c283aa41d2b1d0bcfe2 [file] [log] [blame]
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/elf.h>
#include "qmi.h"
#include "core.h"
#include "debug.h"
#include "hif.h"
#include <linux/of.h>
#include <linux/firmware.h>
#include <linux/devcoredump.h>
#include <linux/of_address.h>
#define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02
#define HOST_CSTATE_BIT 0x04
bool ath11k_cold_boot_cal = 1;
EXPORT_SYMBOL(ath11k_cold_boot_cal);
module_param_named(cold_boot_cal, ath11k_cold_boot_cal, bool, 0644);
MODULE_PARM_DESC(cold_boot_cal,
"Decrease the channel switch time but increase the driver load time (Default: true)");
unsigned int fwmem_mode = ATH11K_QMI_TARGET_MEM_MODE_256M;
module_param_named(fwmem_mode, fwmem_mode, uint, 0644);
MODULE_PARM_DESC(fwmem_mode, "Firmware mem mode (applicable only for qcn9074)");
extern char *country_code;
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,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x10,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
num_clients_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_host_cap_req_msg_v01,
num_clients),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x11,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
wake_msi_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_host_cap_req_msg_v01,
wake_msi),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x12,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
gpios_valid),
},
{
.data_type = QMI_DATA_LEN,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x12,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
gpios_len),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = QMI_WLFW_MAX_NUM_GPIO_V01,
.elem_size = sizeof(u32),
.array_type = VAR_LEN_ARRAY,
.tlv_type = 0x12,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
gpios),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x13,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
nm_modem_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_host_cap_req_msg_v01,
nm_modem),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x14,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
bdf_support_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x14,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
bdf_support),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x15,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
bdf_cache_support_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x15,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
bdf_cache_support),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x16,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
m3_support_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x16,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
m3_support),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x17,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
m3_cache_support_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x17,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
m3_cache_support),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x18,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
cal_filesys_support_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x18,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
cal_filesys_support),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x19,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
cal_cache_support_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x19,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
cal_cache_support),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1A,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
cal_done_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1A,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
cal_done),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1B,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
mem_bucket_valid),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x1B,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
mem_bucket),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1C,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
mem_cfg_mode_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1C,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
mem_cfg_mode),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1D,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
cal_duration_valid),
},
{
.data_type = QMI_UNSIGNED_2_BYTE,
.elem_len = 1,
.elem_size = sizeof(u16),
.array_type = NO_ARRAY,
.tlv_type = 0x1D,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
cal_duration),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_host_cap_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_host_cap_resp_msg_v01, resp),
.ei_array = qmi_response_type_v01_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x20,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
m3_dump_upload_req_enable_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x20,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
m3_dump_upload_req_enable),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_ind_register_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_ind_register_req_msg_v01,
fw_ready_enable_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_ind_register_req_msg_v01,
fw_ready_enable),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x11,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
initiate_cal_download_enable_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x11,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
initiate_cal_download_enable),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x12,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
initiate_cal_update_enable_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x12,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
initiate_cal_update_enable),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x13,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
msa_ready_enable_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_ind_register_req_msg_v01,
msa_ready_enable),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x14,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
pin_connect_result_enable_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x14,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
pin_connect_result_enable),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x15,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
client_id_valid),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x15,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
client_id),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x16,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
request_mem_enable_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x16,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
request_mem_enable),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x17,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
fw_mem_ready_enable_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x17,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
fw_mem_ready_enable),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x18,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
fw_init_done_enable_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x18,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
fw_init_done_enable),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x19,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
rejuvenate_enable_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x19,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
rejuvenate_enable),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1A,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
xo_cal_enable_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1A,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
xo_cal_enable),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1B,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
cal_done_enable_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1B,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
cal_done_enable),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1C,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
qdss_trace_req_mem_enable_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1C,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
qdss_trace_req_mem_enable),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1D,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
qdss_trace_save_enable_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1D,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
qdss_trace_save_enable),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1E,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
qdss_trace_free_enable_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1E,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
qdss_trace_free_enable),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1F,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
respond_get_info_enable_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1F,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
respond_get_info_enable),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x20,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
m3_dump_upload_req_enable_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x20,
.offset = offsetof(struct qmi_wlanfw_ind_register_req_msg_v01,
m3_dump_upload_req_enable),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_ind_register_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_ind_register_resp_msg_v01,
resp),
.ei_array = qmi_response_type_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_ind_register_resp_msg_v01,
fw_status_valid),
},
{
.data_type = QMI_UNSIGNED_8_BYTE,
.elem_len = 1,
.elem_size = sizeof(u64),
.array_type = NO_ARRAY,
.tlv_type = 0x10,
.offset = offsetof(struct qmi_wlanfw_ind_register_resp_msg_v01,
fw_status),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_mem_cfg_s_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_8_BYTE,
.elem_len = 1,
.elem_size = sizeof(u64),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_mem_cfg_s_v01, offset),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_mem_cfg_s_v01, size),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_mem_cfg_s_v01, secure_flag),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_mem_seg_s_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_mem_seg_s_v01,
size),
},
{
.data_type = QMI_SIGNED_4_BYTE_ENUM,
.elem_len = 1,
.elem_size = sizeof(enum qmi_wlanfw_mem_type_enum_v01),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_mem_seg_s_v01, type),
},
{
.data_type = QMI_DATA_LEN,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_mem_seg_s_v01, mem_cfg_len),
},
{
.data_type = QMI_STRUCT,
.elem_len = QMI_WLANFW_MAX_NUM_MEM_CFG_V01,
.elem_size = sizeof(struct qmi_wlanfw_mem_cfg_s_v01),
.array_type = VAR_LEN_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_mem_seg_s_v01, mem_cfg),
.ei_array = qmi_wlanfw_mem_cfg_s_v01_ei,
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_request_mem_ind_msg_v01_ei[] = {
{
.data_type = QMI_DATA_LEN,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x01,
.offset = offsetof(struct qmi_wlanfw_request_mem_ind_msg_v01,
mem_seg_len),
},
{
.data_type = QMI_STRUCT,
.elem_len = ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01,
.elem_size = sizeof(struct qmi_wlanfw_mem_seg_s_v01),
.array_type = VAR_LEN_ARRAY,
.tlv_type = 0x01,
.offset = offsetof(struct qmi_wlanfw_request_mem_ind_msg_v01,
mem_seg),
.ei_array = qmi_wlanfw_mem_seg_s_v01_ei,
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_mem_seg_resp_s_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_8_BYTE,
.elem_len = 1,
.elem_size = sizeof(u64),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_mem_seg_resp_s_v01, addr),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_mem_seg_resp_s_v01, size),
},
{
.data_type = QMI_SIGNED_4_BYTE_ENUM,
.elem_len = 1,
.elem_size = sizeof(enum qmi_wlanfw_mem_type_enum_v01),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_mem_seg_resp_s_v01, type),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_mem_seg_resp_s_v01, restore),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_respond_mem_req_msg_v01_ei[] = {
{
.data_type = QMI_DATA_LEN,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x01,
.offset = offsetof(struct qmi_wlanfw_respond_mem_req_msg_v01,
mem_seg_len),
},
{
.data_type = QMI_STRUCT,
.elem_len = ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01,
.elem_size = sizeof(struct qmi_wlanfw_mem_seg_resp_s_v01),
.array_type = VAR_LEN_ARRAY,
.tlv_type = 0x01,
.offset = offsetof(struct qmi_wlanfw_respond_mem_req_msg_v01,
mem_seg),
.ei_array = qmi_wlanfw_mem_seg_resp_s_v01_ei,
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_respond_mem_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_respond_mem_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_cap_req_msg_v01_ei[] = {
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_device_info_req_msg_v01_ei[] = {
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
struct qmi_elem_info qmi_wlanfw_device_info_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_device_info_resp_msg_v01,
resp),
.ei_array = qmi_response_type_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_device_info_resp_msg_v01,
bar_addr_valid),
},
{
.data_type = QMI_UNSIGNED_8_BYTE,
.elem_len = 1,
.elem_size = sizeof(u64),
.array_type = NO_ARRAY,
.tlv_type = 0x10,
.offset = offsetof(struct qmi_wlanfw_device_info_resp_msg_v01,
bar_addr),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x11,
.offset = offsetof(struct qmi_wlanfw_device_info_resp_msg_v01,
bar_size_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_device_info_resp_msg_v01,
bar_size),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_rf_chip_info_s_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_rf_chip_info_s_v01,
chip_id),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_rf_chip_info_s_v01,
chip_family),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_rf_board_info_s_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_rf_board_info_s_v01,
board_id),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_soc_info_s_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_soc_info_s_v01, soc_id),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_fw_version_info_s_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_fw_version_info_s_v01,
fw_version),
},
{
.data_type = QMI_STRING,
.elem_len = ATH11K_QMI_WLANFW_MAX_TIMESTAMP_LEN_V01 + 1,
.elem_size = sizeof(char),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_fw_version_info_s_v01,
fw_build_timestamp),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_cap_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_cap_resp_msg_v01, resp),
.ei_array = qmi_response_type_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_cap_resp_msg_v01,
chip_info_valid),
},
{
.data_type = QMI_STRUCT,
.elem_len = 1,
.elem_size = sizeof(struct qmi_wlanfw_rf_chip_info_s_v01),
.array_type = NO_ARRAY,
.tlv_type = 0x10,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
chip_info),
.ei_array = qmi_wlanfw_rf_chip_info_s_v01_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x11,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
board_info_valid),
},
{
.data_type = QMI_STRUCT,
.elem_len = 1,
.elem_size = sizeof(struct qmi_wlanfw_rf_board_info_s_v01),
.array_type = NO_ARRAY,
.tlv_type = 0x11,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
board_info),
.ei_array = qmi_wlanfw_rf_board_info_s_v01_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x12,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
soc_info_valid),
},
{
.data_type = QMI_STRUCT,
.elem_len = 1,
.elem_size = sizeof(struct qmi_wlanfw_soc_info_s_v01),
.array_type = NO_ARRAY,
.tlv_type = 0x12,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
soc_info),
.ei_array = qmi_wlanfw_soc_info_s_v01_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x13,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
fw_version_info_valid),
},
{
.data_type = QMI_STRUCT,
.elem_len = 1,
.elem_size = sizeof(struct qmi_wlanfw_fw_version_info_s_v01),
.array_type = NO_ARRAY,
.tlv_type = 0x13,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
fw_version_info),
.ei_array = qmi_wlanfw_fw_version_info_s_v01_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x14,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
fw_build_id_valid),
},
{
.data_type = QMI_STRING,
.elem_len = ATH11K_QMI_WLANFW_MAX_BUILD_ID_LEN_V01 + 1,
.elem_size = sizeof(char),
.array_type = NO_ARRAY,
.tlv_type = 0x14,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
fw_build_id),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x15,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
num_macs_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x15,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
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,
},
};
static struct qmi_elem_info qmi_wlanfw_bdf_download_req_msg_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x01,
.offset = offsetof(struct qmi_wlanfw_bdf_download_req_msg_v01,
valid),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x10,
.offset = offsetof(struct qmi_wlanfw_bdf_download_req_msg_v01,
file_id_valid),
},
{
.data_type = QMI_SIGNED_4_BYTE_ENUM,
.elem_len = 1,
.elem_size = sizeof(enum qmi_wlanfw_cal_temp_id_enum_v01),
.array_type = NO_ARRAY,
.tlv_type = 0x10,
.offset = offsetof(struct qmi_wlanfw_bdf_download_req_msg_v01,
file_id),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x11,
.offset = offsetof(struct qmi_wlanfw_bdf_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 = 0x11,
.offset = offsetof(struct qmi_wlanfw_bdf_download_req_msg_v01,
total_size),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x12,
.offset = offsetof(struct qmi_wlanfw_bdf_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 = 0x12,
.offset = offsetof(struct qmi_wlanfw_bdf_download_req_msg_v01,
seg_id),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x13,
.offset = offsetof(struct qmi_wlanfw_bdf_download_req_msg_v01,
data_valid),
},
{
.data_type = QMI_DATA_LEN,
.elem_len = 1,
.elem_size = sizeof(u16),
.array_type = NO_ARRAY,
.tlv_type = 0x13,
.offset = offsetof(struct qmi_wlanfw_bdf_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 = 0x13,
.offset = offsetof(struct qmi_wlanfw_bdf_download_req_msg_v01,
data),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x14,
.offset = offsetof(struct qmi_wlanfw_bdf_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 = 0x14,
.offset = offsetof(struct qmi_wlanfw_bdf_download_req_msg_v01,
end),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x15,
.offset = offsetof(struct qmi_wlanfw_bdf_download_req_msg_v01,
bdf_type_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x15,
.offset = offsetof(struct qmi_wlanfw_bdf_download_req_msg_v01,
bdf_type),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_bdf_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_bdf_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_m3_info_req_msg_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_8_BYTE,
.elem_len = 1,
.elem_size = sizeof(u64),
.array_type = NO_ARRAY,
.tlv_type = 0x01,
.offset = offsetof(struct qmi_wlanfw_m3_info_req_msg_v01, addr),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x02,
.offset = offsetof(struct qmi_wlanfw_m3_info_req_msg_v01, size),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_m3_info_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_m3_info_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_ce_tgt_pipe_cfg_s_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_ce_tgt_pipe_cfg_s_v01,
pipe_num),
},
{
.data_type = QMI_SIGNED_4_BYTE_ENUM,
.elem_len = 1,
.elem_size = sizeof(enum qmi_wlanfw_pipedir_enum_v01),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_ce_tgt_pipe_cfg_s_v01,
pipe_dir),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_ce_tgt_pipe_cfg_s_v01,
nentries),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_ce_tgt_pipe_cfg_s_v01,
nbytes_max),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_ce_tgt_pipe_cfg_s_v01,
flags),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_ce_svc_pipe_cfg_s_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_ce_svc_pipe_cfg_s_v01,
service_id),
},
{
.data_type = QMI_SIGNED_4_BYTE_ENUM,
.elem_len = 1,
.elem_size = sizeof(enum qmi_wlanfw_pipedir_enum_v01),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_ce_svc_pipe_cfg_s_v01,
pipe_dir),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_ce_svc_pipe_cfg_s_v01,
pipe_num),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_shadow_reg_cfg_s_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_2_BYTE,
.elem_len = 1,
.elem_size = sizeof(u16),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_shadow_reg_cfg_s_v01, id),
},
{
.data_type = QMI_UNSIGNED_2_BYTE,
.elem_len = 1,
.elem_size = sizeof(u16),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_shadow_reg_cfg_s_v01,
offset),
},
{
.data_type = QMI_EOTI,
.array_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_shadow_reg_v2_cfg_s_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct qmi_wlanfw_shadow_reg_v2_cfg_s_v01,
addr),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_wlan_mode_req_msg_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x01,
.offset = offsetof(struct qmi_wlanfw_wlan_mode_req_msg_v01,
mode),
},
{
.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_mode_req_msg_v01,
hw_debug_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_mode_req_msg_v01,
hw_debug),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_wlan_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_wlan_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_wlan_cfg_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_cfg_req_msg_v01,
host_version_valid),
},
{
.data_type = QMI_STRING,
.elem_len = QMI_WLANFW_MAX_STR_LEN_V01 + 1,
.elem_size = sizeof(char),
.array_type = NO_ARRAY,
.tlv_type = 0x10,
.offset = offsetof(struct qmi_wlanfw_wlan_cfg_req_msg_v01,
host_version),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x11,
.offset = offsetof(struct qmi_wlanfw_wlan_cfg_req_msg_v01,
tgt_cfg_valid),
},
{
.data_type = QMI_DATA_LEN,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x11,
.offset = offsetof(struct qmi_wlanfw_wlan_cfg_req_msg_v01,
tgt_cfg_len),
},
{
.data_type = QMI_STRUCT,
.elem_len = QMI_WLANFW_MAX_NUM_CE_V01,
.elem_size = sizeof(
struct qmi_wlanfw_ce_tgt_pipe_cfg_s_v01),
.array_type = VAR_LEN_ARRAY,
.tlv_type = 0x11,
.offset = offsetof(struct qmi_wlanfw_wlan_cfg_req_msg_v01,
tgt_cfg),
.ei_array = qmi_wlanfw_ce_tgt_pipe_cfg_s_v01_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x12,
.offset = offsetof(struct qmi_wlanfw_wlan_cfg_req_msg_v01,
svc_cfg_valid),
},
{
.data_type = QMI_DATA_LEN,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x12,
.offset = offsetof(struct qmi_wlanfw_wlan_cfg_req_msg_v01,
svc_cfg_len),
},
{
.data_type = QMI_STRUCT,
.elem_len = QMI_WLANFW_MAX_NUM_SVC_V01,
.elem_size = sizeof(struct qmi_wlanfw_ce_svc_pipe_cfg_s_v01),
.array_type = VAR_LEN_ARRAY,
.tlv_type = 0x12,
.offset = offsetof(struct qmi_wlanfw_wlan_cfg_req_msg_v01,
svc_cfg),
.ei_array = qmi_wlanfw_ce_svc_pipe_cfg_s_v01_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x13,
.offset = offsetof(struct qmi_wlanfw_wlan_cfg_req_msg_v01,
shadow_reg_valid),
},
{
.data_type = QMI_DATA_LEN,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x13,
.offset = offsetof(struct qmi_wlanfw_wlan_cfg_req_msg_v01,
shadow_reg_len),
},
{
.data_type = QMI_STRUCT,
.elem_len = QMI_WLANFW_MAX_NUM_SHADOW_REG_V01,
.elem_size = sizeof(struct qmi_wlanfw_shadow_reg_cfg_s_v01),
.array_type = VAR_LEN_ARRAY,
.tlv_type = 0x13,
.offset = offsetof(struct qmi_wlanfw_wlan_cfg_req_msg_v01,
shadow_reg),
.ei_array = qmi_wlanfw_shadow_reg_cfg_s_v01_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x14,
.offset = offsetof(struct qmi_wlanfw_wlan_cfg_req_msg_v01,
shadow_reg_v2_valid),
},
{
.data_type = QMI_DATA_LEN,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x14,
.offset = offsetof(struct qmi_wlanfw_wlan_cfg_req_msg_v01,
shadow_reg_v2_len),
},
{
.data_type = QMI_STRUCT,
.elem_len = QMI_WLANFW_MAX_NUM_SHADOW_REG_V2_V01,
.elem_size = sizeof(struct qmi_wlanfw_shadow_reg_v2_cfg_s_v01),
.array_type = VAR_LEN_ARRAY,
.tlv_type = 0x14,
.offset = offsetof(struct qmi_wlanfw_wlan_cfg_req_msg_v01,
shadow_reg_v2),
.ei_array = qmi_wlanfw_shadow_reg_v2_cfg_s_v01_ei,
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_wlan_cfg_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_cfg_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_mem_ready_ind_msg_v01_ei[] = {
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
},
};
static struct qmi_elem_info qmi_wlanfw_fw_ready_ind_msg_v01_ei[] = {
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
},
};
static struct qmi_elem_info qmi_wlanfw_cold_boot_cal_done_ind_msg_v01_ei[] = {
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
},
};
static struct qmi_elem_info qmi_wlanfw_m3_dump_upload_req_ind_msg_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x01,
.offset = offsetof(struct qmi_wlanfw_m3_dump_upload_req_ind_msg_v01,
pdev_id),
},
{
.data_type = QMI_UNSIGNED_8_BYTE,
.elem_len = 1,
.elem_size = sizeof(u64),
.array_type = NO_ARRAY,
.tlv_type = 0x02,
.offset = offsetof(struct qmi_wlanfw_m3_dump_upload_req_ind_msg_v01,
addr),
},
{
.data_type = QMI_UNSIGNED_8_BYTE,
.elem_len = 1,
.elem_size = sizeof(u64),
.array_type = NO_ARRAY,
.tlv_type = 0x03,
.offset = offsetof(struct qmi_wlanfw_m3_dump_upload_req_ind_msg_v01,
size),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_m3_dump_upload_done_req_msg_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x01,
.offset = offsetof(struct
qmi_wlanfw_m3_dump_upload_done_req_msg_v01,
pdev_id),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x02,
.offset = offsetof(struct
qmi_wlanfw_m3_dump_upload_done_req_msg_v01,
status),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static struct qmi_elem_info qmi_wlanfw_m3_dump_upload_done_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_m3_dump_upload_done_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,
},
};
struct qmi_elem_info qmi_wlanfw_qdss_trace_save_ind_msg_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x01,
.offset = offsetof(struct
qmi_wlanfw_qdss_trace_save_ind_msg_v01,
source),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x02,
.offset = offsetof(struct
qmi_wlanfw_qdss_trace_save_ind_msg_v01,
total_size),
},
{
.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_save_ind_msg_v01,
mem_seg_valid),
},
{
.data_type = QMI_DATA_LEN,
.elem_len = 1,
.elem_size = sizeof(u8),
.array_type = NO_ARRAY,
.tlv_type = 0x10,
.offset = offsetof(struct
qmi_wlanfw_qdss_trace_save_ind_msg_v01,
mem_seg_len),
},
{
.data_type = QMI_STRUCT,
.elem_len = ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01,
.elem_size = sizeof(struct qmi_wlanfw_mem_seg_resp_s_v01),
.array_type = VAR_LEN_ARRAY,
.tlv_type = 0x10,
.offset = offsetof(struct
qmi_wlanfw_qdss_trace_save_ind_msg_v01,
mem_seg),
.ei_array = qmi_wlanfw_mem_seg_resp_s_v01_ei,
},
{
.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_save_ind_msg_v01,
file_name_valid),
},
{
.data_type = QMI_STRING,
.elem_len = QMI_WLANFW_MAX_STR_LEN_V01 + 1,
.elem_size = sizeof(char),
.array_type = NO_ARRAY,
.tlv_type = 0x11,
.offset = offsetof(struct
qmi_wlanfw_qdss_trace_save_ind_msg_v01,
file_name),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
struct qmi_elem_info wlfw_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 wlfw_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 wlfw_ini_req_msg_v01,
enablefwlog),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
struct qmi_elem_info wlfw_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 wlfw_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,
},
};
struct qmi_elem_info qmi_wlanfw_mem_read_req_msg_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x01,
.offset = offsetof(struct qmi_wlanfw_mem_read_req_msg_v01,
offset),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x02,
.offset = offsetof(struct qmi_wlanfw_mem_read_req_msg_v01,
mem_type),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x03,
.offset = offsetof(struct qmi_wlanfw_mem_read_req_msg_v01,
data_len),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
struct qmi_elem_info qmi_wlanfw_mem_read_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_mem_read_resp_msg_v01,
resp),
.ei_array = qmi_response_type_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_mem_read_resp_msg_v01,
data_valid),
},
{
.data_type = QMI_DATA_LEN,
.elem_len = 1,
.elem_size = sizeof(u16),
.array_type = NO_ARRAY,
.tlv_type = 0x10,
.offset = offsetof(struct
qmi_wlanfw_mem_read_resp_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 = 0x10,
.offset = offsetof(struct
qmi_wlanfw_mem_read_resp_msg_v01,
data),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
struct qmi_elem_info qmi_wlanfw_mem_write_req_msg_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x01,
.offset = offsetof(struct
qmi_wlanfw_mem_write_req_msg_v01,
offset),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x02,
.offset = offsetof(struct
qmi_wlanfw_mem_write_req_msg_v01,
mem_type),
},
{
.data_type = QMI_DATA_LEN,
.elem_len = 1,
.elem_size = sizeof(u16),
.array_type = NO_ARRAY,
.tlv_type = 0x03,
.offset = offsetof(struct
qmi_wlanfw_mem_write_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 = 0x03,
.offset = offsetof(struct
qmi_wlanfw_mem_write_req_msg_v01,
data),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
struct qmi_elem_info qmi_wlanfw_mem_write_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_mem_write_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,
},
};
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 = mode == QMI_WLANFW_QDSS_TRACE_OFF_V01 ?
QMI_WLANFW_QDSS_STOP_ALL_TRACE : 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);
qmi_txn_cancel(&txn);
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_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;
struct qmi_wlanfw_host_cap_resp_msg_v01 resp;
struct qmi_txn txn = {};
int ret = 0;
memset(&req, 0, sizeof(req));
memset(&resp, 0, sizeof(resp));
req.num_clients_valid = 1;
req.num_clients = 1;
req.mem_cfg_mode = ab->qmi.target_mem_mode;
req.mem_cfg_mode_valid = 1;
req.bdf_support_valid = 1;
req.bdf_support = 1;
if (ab->bus_params.m3_fw_support) {
req.m3_support_valid = 1;
req.m3_support = 1;
req.m3_cache_support_valid = 1;
req.m3_cache_support = 1;
} else {
req.m3_support_valid = 0;
req.m3_support = 0;
req.m3_cache_support_valid = 0;
req.m3_cache_support = 0;
}
req.cal_done_valid = 1;
req.cal_done = ab->qmi.cal_done;
if (ab->hw_params.internal_sleep_clock) {
req.nm_modem_valid = 1;
/* Notify firmware that this is non-qualcomm platform. */
req.nm_modem |= HOST_CSTATE_BIT;
/* Notify firmware about the sleep clock selection,
* nm_modem_bit[1] is used for this purpose. Host driver on
* non-qualcomm platforms should select internal sleep
* clock.
*/
req.nm_modem |= SLEEP_CLOCK_SELECT_INTERNAL_BIT;
}
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_host_cap_resp_msg_v01_ei, &resp);
if (ret < 0)
goto out;
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_HOST_CAP_REQ_V01,
QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN,
qmi_wlanfw_host_cap_req_msg_v01_ei, &req);
if (ret < 0) {
ath11k_warn(ab, "Failed to send host capability 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, "Host capability request failed, result: %d, err: %d\n",
resp.resp.result, resp.resp.error);
ret = -EINVAL;
goto out;
}
out:
return ret;
}
static int ath11k_qmi_fw_ind_register_send(struct ath11k_base *ab)
{
struct qmi_wlanfw_ind_register_req_msg_v01 *req;
struct qmi_wlanfw_ind_register_resp_msg_v01 *resp;
struct qmi_handle *handle = &ab->qmi.handle;
struct qmi_txn txn;
int ret;
req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
resp = kzalloc(sizeof(*resp), GFP_KERNEL);
if (!resp) {
ret = -ENOMEM;
goto resp_out;
}
req->client_id_valid = 1;
req->client_id = QMI_WLANFW_CLIENT_ID;
req->fw_ready_enable_valid = 1;
req->fw_ready_enable = 1;
req->request_mem_enable_valid = 1;
req->request_mem_enable = 1;
req->fw_mem_ready_enable_valid = 1;
req->fw_mem_ready_enable = 1;
req->cal_done_enable_valid = 1;
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;
req->m3_dump_upload_req_enable_valid = 1;
req->m3_dump_upload_req_enable = 1;
ret = qmi_txn_init(handle, &txn,
qmi_wlanfw_ind_register_resp_msg_v01_ei, resp);
if (ret < 0)
goto out;
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_IND_REGISTER_REQ_V01,
QMI_WLANFW_IND_REGISTER_REQ_MSG_V01_MAX_LEN,
qmi_wlanfw_ind_register_req_msg_v01_ei, req);
if (ret < 0) {
ath11k_warn(ab, "Failed to send indication register request, err = %d\n",
ret);
goto out;
}
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
if (ret < 0) {
ath11k_warn(ab, "failed to register fw indication %d\n", ret);
goto out;
}
if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
ath11k_warn(ab, "FW Ind register request failed, result: %d, err: %d\n",
resp->resp.result, resp->resp.error);
ret = -EINVAL;
goto out;
}
out:
kfree(resp);
resp_out:
kfree(req);
return ret;
}
static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
{
struct qmi_wlanfw_respond_mem_req_msg_v01 *req;
struct qmi_wlanfw_respond_mem_resp_msg_v01 resp;
struct qmi_txn txn = {};
int ret = 0, i;
bool delayed;
req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
memset(&resp, 0, sizeof(resp));
/* For QCA6390 by default FW requests a block of ~4M contiguous
* DMA memory, it's hard to allocate from OS. So host returns
* failure to FW and FW will then request mulitple blocks of small
* chunk size memory.
*/
if (!ab->bus_params.fixed_mem_region && ab->qmi.target_mem_delayed) {
delayed = true;
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi delays mem_request %d\n",
ab->qmi.mem_seg_count);
memset(req, 0, sizeof(*req));
} else {
delayed = false;
req->mem_seg_len = ab->qmi.mem_seg_count;
for (i = 0; i < req->mem_seg_len ; i++) {
req->mem_seg[i].addr = ab->qmi.target_mem[i].paddr;
req->mem_seg[i].size = ab->qmi.target_mem[i].size;
req->mem_seg[i].type = ab->qmi.target_mem[i].type;
ath11k_dbg(ab, ATH11K_DBG_QMI,
"qmi req mem_seg[%d] 0x%llx %u %u\n", i,
(u64)ab->qmi.target_mem[i].paddr,
ab->qmi.target_mem[i].size,
ab->qmi.target_mem[i].type);
}
}
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_respond_mem_resp_msg_v01_ei, &resp);
if (ret < 0)
goto out;
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_RESPOND_MEM_REQ_V01,
QMI_WLANFW_RESPOND_MEM_REQ_MSG_V01_MAX_LEN,
qmi_wlanfw_respond_mem_req_msg_v01_ei, req);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to respond memory request, err = %d\n",
ret);
goto out;
}
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
if (ret < 0) {
ath11k_warn(ab, "qmi failed memory request, err = %d\n", ret);
goto out;
}
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
/* the error response is expected when
* target_mem_delayed is true.
*/
if (delayed && resp.resp.error == 0)
goto out;
ath11k_warn(ab, "Respond mem req failed, result: %d, err: %d\n",
resp.resp.result, resp.resp.error);
ret = -EINVAL;
goto out;
}
out:
kfree(req);
return ret;
}
static void ath11k_qmi_free_target_mem_chunk(struct ath11k_base *ab)
{
int i;
for (i = 0; i < ab->qmi.mem_seg_count; i++) {
if (!ab->qmi.target_mem[i].vaddr)
continue;
if (ab->bus_params.fixed_mem_region) {
iounmap(ab->qmi.target_mem[i].vaddr);
} else {
dma_free_coherent(ab->dev,
ab->qmi.target_mem[i].size,
ab->qmi.target_mem[i].vaddr,
ab->qmi.target_mem[i].paddr);
}
ab->qmi.target_mem[i].vaddr = NULL;
}
if (ab->bus_params.fixed_mem_region && ab->qmi.qdss_mem[0].vaddr) {
iounmap(ab->qmi.qdss_mem[0].vaddr);
ab->qmi.qdss_mem[0].vaddr = NULL;
}
}
static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
{
int i;
struct target_mem_chunk *chunk;
ab->qmi.target_mem_delayed = false;
for (i = 0; i < ab->qmi.mem_seg_count; i++) {
chunk = &ab->qmi.target_mem[i];
/*
* Ignore the memory request from FW if size is more than 2MB
* if host sends failure, FW reqesut for 2MB segments in mode-0
* and 1MB segments in mode-1 and mode-2
*/
if (chunk->size > 2*1024*1024) {
ab->qmi.target_mem_delayed = true;
return 0;
}
/*
* FW reloads in coldboot/FWrecovery.
* in such case, no need to allocate memory for FW again.
*/
if (chunk->vaddr) {
if (chunk->prev_type != chunk->type ||
chunk->prev_size != chunk->size) {
dma_free_coherent(ab->dev,
ab->qmi.target_mem[i].size,
ab->qmi.target_mem[i].vaddr,
ab->qmi.target_mem[i].paddr);
ab->qmi.target_mem[i].vaddr = NULL;
} else {
continue;
}
}
chunk->vaddr = dma_alloc_coherent(ab->dev,
chunk->size,
&chunk->paddr,
GFP_KERNEL);
if (!chunk->vaddr) {
if (ab->qmi.mem_seg_count <= ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT) {
ath11k_dbg(ab, ATH11K_DBG_QMI,
"qmi dma allocation failed (%d B type %u), will try later with small size\n",
chunk->size,
chunk->type);
ath11k_qmi_free_target_mem_chunk(ab);
ab->qmi.target_mem_delayed = true;
return 0;
}
ath11k_err(ab, "failed to alloc memory, size: 0x%x, type: %u\n",
chunk->size,
chunk->type);
return -EINVAL;
}
chunk->prev_type = chunk->type;
chunk->prev_size = chunk->size;
}
return 0;
}
#define ATH11K_HOST_DDR_M3_OFFSET 0x2D00000
#define ATH11K_HOST_DDR_QDSS_OFFSET 0x2E00000
#define ATH11K_HOST_DDR_CALDB_OFFSET 0x2F00000
#define ATH11K_HOST_AFC_QCN6122_MEM_OFFSET 0xD8000
static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab)
{
struct device *dev = ab->dev;
int i, idx;
u32 addr = 0;
u32 location[3];
for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) {
switch (ab->qmi.target_mem[i].type) {
case HOST_DDR_REGION_TYPE:
/* This is HACK
* QCN9074 Firmware needs contiguous 60MB HOST DDR memory
* use reserve memory from bootargs x86
* HACK reserve memory using memmap=60M$0x70000000
*/
if (ath11k_host_ddr_addr) {
addr = ath11k_host_ddr_addr;
} else if (of_property_read_u32(dev->of_node, "base-addr", &addr)) {
ath11k_warn(ab, "qmi fail to get base-addr in dt\n");
return -EINVAL;
}
ab->qmi.target_mem[idx].paddr = (phys_addr_t)addr;
ab->qmi.target_mem[idx].vaddr =
ioremap(ab->qmi.target_mem[idx].paddr,
ab->qmi.target_mem[i].size);
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
idx++;
break;
case BDF_MEM_REGION_TYPE:
if (!of_property_read_u32_array(dev->of_node, "qcom,bdf-addr", location,
ARRAY_SIZE(location))) {
ab->hw_params.bdf_addr = location[ab->qmi.target_mem_mode];
}
ab->qmi.target_mem[idx].paddr = ab->hw_params.bdf_addr;
ab->qmi.target_mem[idx].vaddr = NULL;
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
idx++;
break;
case CALDB_MEM_REGION_TYPE:
if (ath11k_host_ddr_addr) {
addr = ath11k_host_ddr_addr +
ATH11K_HOST_DDR_CALDB_OFFSET;
} else if (of_property_read_u32(dev->of_node, "qcom,caldb-addr", &addr)) {
ath11k_warn(ab, "qmi fail to get caldb-addr in dt\n");
}
if (!ab->enable_cold_boot_cal ||
!ab->hw_params.cold_boot_calib) {
ab->qmi.target_mem[idx].paddr = 0;
ab->qmi.target_mem[idx].vaddr = NULL;
} else {
ab->qmi.target_mem[idx].paddr = (u32)addr;
ab->qmi.target_mem[idx].vaddr =
ioremap(ab->qmi.target_mem[idx].paddr,
ab->qmi.target_mem[i].size);
}
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
idx++;
break;
case M3_DUMP_REGION_TYPE:
if (!ab->qmi.target_mem[i].size) {
ath11k_info(ab, "qmi mem size is zero\n");
return -EINVAL;
}
if (ab->qmi.target_mem[i].size > ATH11K_QMI_M3_DUMP_SIZE) {
ath11k_warn(ab, "qmi mem size is low to dump m3 ssr\n");
return -EINVAL;
}
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
if (ath11k_host_ddr_addr) {
addr = ath11k_host_ddr_addr +
ATH11K_HOST_DDR_M3_OFFSET;
} else if (of_property_read_u32(dev->of_node, "m3-dump-addr", &addr)) {
addr = ab->hw_params.m3_addr;
}
ab->qmi.target_mem[idx].paddr = (phys_addr_t)addr;
ab->qmi.target_mem[idx].vaddr =
ioremap(ab->qmi.target_mem[idx].paddr,
ab->qmi.target_mem[i].size);
idx++;
break;
case AFC_REGION_TYPE:
if (ab->qmi.target_mem[i].size != AFC_MEM_SIZE) {
ath11k_warn(ab, "AFC mem request for lesser size 0x%x\n",
(unsigned int)ab->qmi.target_mem[i].size);
return -EINVAL;
}
if (ab->userpd_id) {
/* For QCN6122, AFC_REGION_TYPE needs to be
* allocated from within the M3_DUMP_REGION.
* This is because QCN6122 cannot access memory
* regions allocated outside FW reserved memory
*/
if (of_property_read_u32(dev->of_node, "m3-dump-addr", &addr))
addr = ab->hw_params.m3_addr;
ab->qmi.target_mem[idx].paddr =
(phys_addr_t)(addr + ATH11K_HOST_AFC_QCN6122_MEM_OFFSET);
ab->qmi.target_mem[idx].vaddr =
ioremap(ab->qmi.target_mem[idx].paddr,
ab->qmi.target_mem[idx].size);
} else {
ab->qmi.target_mem[idx].vaddr =
dma_alloc_coherent(ab->dev, ab->qmi.target_mem[i].size,
&ab->qmi.target_mem[idx].paddr,
GFP_KERNEL);
if (!ab->qmi.target_mem[idx].vaddr) {
ath11k_warn(ab, "AFC mem allocation failed\n");
ab->qmi.target_mem[idx].paddr = 0;
return -ENOMEM;
}
}
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
idx++;
break;
default:
ath11k_warn(ab, "qmi ignore invalid mem req type %d\n",
ab->qmi.target_mem[i].type);
break;
}
}
ab->qmi.mem_seg_count = idx;
return 0;
}
static int ath11k_qmi_request_device_info(struct ath11k_base *ab)
{
struct qmi_wlanfw_device_info_req_msg_v01 req;
struct qmi_wlanfw_device_info_resp_msg_v01 resp;
struct qmi_txn txn = {};
void *bar_addr_va = NULL;
int ret = 0;
/*device info message only supported for internal-PCI devices */
if (ab->hw_rev != ATH11K_HW_QCN6122)
return 0;
memset(&req, 0, sizeof(req));
memset(&resp, 0, sizeof(resp));
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_device_info_resp_msg_v01_ei, &resp);
if (ret < 0)
goto out;
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_DEVICE_INFO_REQ_V01,
QMI_WLANFW_DEVICE_INFO_REQ_MSG_V01,
qmi_wlanfw_device_info_req_msg_v01_ei, &req);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to send target device info request, err = %d\n",
ret);
goto out;
}
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
if (ret < 0) {
ath11k_warn(ab, "qmi failed target device info request %d\n", ret);
goto out;
}
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
ath11k_warn(ab, "qmi device info req failed, result: %d, err: %d\n",
resp.resp.result, resp.resp.error);
ret = -EINVAL;
goto out;
}
if (!resp.bar_addr_valid || !resp.bar_size_valid) {
ath11k_warn(ab, "qmi device info response invalid, result: %d, err: %d\n",
resp.resp.result, resp.resp.error);
ret = -EINVAL;
goto out;
}
if (!resp.bar_addr ||
resp.bar_size != QCN6122_DEVICE_BAR_SIZE) {
ath11k_warn(ab, "qmi device info invalid addr and size, result: %d, err: %d\n",
resp.resp.result, resp.resp.error);
ret = -EINVAL;
goto out;
}
bar_addr_va = ioremap_nocache(resp.bar_addr, resp.bar_size);
if (!bar_addr_va) {
ath11k_warn(ab, "qmi device info ioremap failed\n");
ab->mem_pa = 0;
ab->mem_len = 0;
ret = -EIO;
goto out;
}
ab->mem = bar_addr_va;
ab->mem_pa = resp.bar_addr;
ab->mem_len = resp.bar_size;
ath11k_dbg(ab, ATH11K_DBG_QMI, "Device BAR Info pa: 0x%llx, va: 0x%p, size: 0x%lx\n",
(u64)ab->mem_pa, ab->mem, ab->mem_len);
ath11k_hif_config_static_window(ab);
return 0;
out:
return ret;
}
static int ath11k_qmi_request_target_cap(struct ath11k_base *ab)
{
struct device *dev = ab->dev;
struct qmi_wlanfw_cap_req_msg_v01 req;
struct qmi_wlanfw_cap_resp_msg_v01 resp;
struct qmi_txn txn = {};
unsigned int board_id;
int ret = 0;
int r;
memset(&req, 0, sizeof(req));
memset(&resp, 0, sizeof(resp));
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_cap_resp_msg_v01_ei, &resp);
if (ret < 0)
goto out;
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_CAP_REQ_V01,
QMI_WLANFW_CAP_REQ_MSG_V01_MAX_LEN,
qmi_wlanfw_cap_req_msg_v01_ei, &req);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to send target cap request, err = %d\n",
ret);
goto out;
}
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
if (ret < 0) {
ath11k_warn(ab, "qmi failed target cap request %d\n", ret);
goto out;
}
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
ath11k_warn(ab, "qmi targetcap req failed, result: %d, err: %d\n",
resp.resp.result, resp.resp.error);
ret = -EINVAL;
goto out;
}
if (resp.chip_info_valid) {
ab->qmi.target.chip_id = resp.chip_info.chip_id;
ab->qmi.target.chip_family = resp.chip_info.chip_family;
}
if (resp.num_macs_valid)
ab->qmi.target.num_macs = resp.num_macs;
if (!of_property_read_u32(dev->of_node, "qcom,board_id", &board_id) && board_id != 0xFF) {
ab->qmi.target.board_id = board_id;
} else if (resp.board_info_valid) {
ab->qmi.target.board_id = resp.board_info.board_id;
} else {
ab->qmi.target.board_id = 0xFF;
}
if (resp.soc_info_valid)
ab->qmi.target.soc_id = resp.soc_info.soc_id;
if (resp.fw_version_info_valid) {
ab->qmi.target.fw_version = resp.fw_version_info.fw_version;
strlcpy(ab->qmi.target.fw_build_timestamp,
resp.fw_version_info.fw_build_timestamp,
sizeof(ab->qmi.target.fw_build_timestamp));
}
if (resp.fw_build_id_valid)
strlcpy(ab->qmi.target.fw_build_id, resp.fw_build_id,
sizeof(ab->qmi.target.fw_build_id));
ath11k_info(ab, "chip_id 0x%x chip_family 0x%x board_id 0x%x soc_id 0x%x\n",
ab->qmi.target.chip_id, ab->qmi.target.chip_family,
ab->qmi.target.board_id, ab->qmi.target.soc_id);
ath11k_info(ab, "fw_version 0x%x fw_build_timestamp %s fw_build_id %s",
ab->qmi.target.fw_version,
ab->qmi.target.fw_build_timestamp,
ab->qmi.target.fw_build_id);
r = ath11k_core_check_dt(ab);
if (r)
ath11k_dbg(ab, ATH11K_DBG_QMI, "DT bdf variant name not set.\n");
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");
}
out:
return ret;
}
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;
u32 remaining;
int ret;
req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
memset(&resp, 0, sizeof(resp));
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;
}
}
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->data_valid = 1;
req->bdf_type = type;
req->bdf_type_valid = 1;
req->end_valid = 1;
req->end = 0;
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;
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;
}
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, "qmi BDF download failed, result: %d, err: %d\n",
resp.resp.result, resp.resp.error);
ret = -EINVAL;
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:
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)
{
char filename[ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE];
const struct firmware *fw_entry;
struct ath11k_board_data bd;
u32 fw_size, file_type;
const 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 fetch bdf\n");
return ret;
}
fw_size = bd.len;
fw_size = min_t(u32, ab->hw_params.fw.board_size, bd.len);
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;
}
/* Load caldata */
if(ab->bus_params.fixed_bdf_addr) {
snprintf(filename, sizeof(filename),
"%s", ATH11K_DEFAULT_CAL_FILE);
if (ab->userpd_id) {
snprintf(filename, sizeof(filename), "%s%d%s",
ATH11K_QMI_DEF_CAL_FILE_PREFIX,
ab->userpd_id,
ATH11K_QMI_DEF_CAL_FILE_SUFFIX);
}
} 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);
}
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;
}
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;
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;
}
ath11k_info(ab, "qmi caldata downloaded: type: %u\n", file_type);
out_qmi_cal:
if (file_type == ATH11K_QMI_FILE_TYPE_CALDATA)
release_firmware(fw_entry);
out:
ath11k_core_free_bdf(ab, &bd);
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi BDF downloaded\n");
return 0;
}
static int ath11k_qmi_m3_load(struct ath11k_base *ab)
{
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
const struct firmware *fw;
char path[100];
int ret;
if (m3_mem->vaddr || m3_mem->size)
return 0;
fw = ath11k_core_firmware_request(ab, ATH11K_M3_FILE);
if (IS_ERR(fw)) {
ret = PTR_ERR(fw);
ath11k_core_create_firmware_path(ab, ATH11K_M3_FILE,
path, sizeof(path));
ath11k_err(ab, "failed to load %s: %d\n", path, ret);
return ret;
}
m3_mem->vaddr = dma_alloc_coherent(ab->dev,
fw->size, &m3_mem->paddr,
GFP_KERNEL);
if (!m3_mem->vaddr) {
ath11k_err(ab, "failed to allocate memory for M3 with size %zu\n",
fw->size);
release_firmware(fw);
return -ENOMEM;
}
memcpy(m3_mem->vaddr, fw->data, fw->size);
m3_mem->size = fw->size;
release_firmware(fw);
return 0;
}
static void ath11k_qmi_m3_free(struct ath11k_base *ab)
{
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
if (!ab->bus_params.m3_fw_support || !m3_mem->vaddr)
return;
dma_free_coherent(ab->dev, m3_mem->size,
m3_mem->vaddr, m3_mem->paddr);
m3_mem->vaddr = NULL;
}
static int ath11k_qmi_wlanfw_m3_info_send(struct ath11k_base *ab)
{
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
struct qmi_wlanfw_m3_info_req_msg_v01 req;
struct qmi_wlanfw_m3_info_resp_msg_v01 resp;
struct qmi_txn txn = {};
int ret = 0;
memset(&req, 0, sizeof(req));
memset(&resp, 0, sizeof(resp));
if (ab->bus_params.m3_fw_support) {
ret = ath11k_qmi_m3_load(ab);
if (ret) {
ath11k_err(ab, "failed to load m3 firmware: %d", ret);
return ret;
}
req.addr = m3_mem->paddr;
req.size = m3_mem->size;
} else {
req.addr = 0;
req.size = 0;
}
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_m3_info_resp_msg_v01_ei, &resp);
if (ret < 0)
goto out;
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_M3_INFO_REQ_V01,
QMI_WLANFW_M3_INFO_REQ_MSG_V01_MAX_MSG_LEN,
qmi_wlanfw_m3_info_req_msg_v01_ei, &req);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to send M3 information request, err = %d\n",
ret);
goto out;
}
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
if (ret < 0) {
ath11k_warn(ab, "qmi failed M3 information request %d\n", ret);
goto out;
}
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
ath11k_warn(ab, "qmi M3 info request failed, result: %d, err: %d\n",
resp.resp.result, resp.resp.error);
ret = -EINVAL;
goto out;
}
out:
return ret;
}
static int ath11k_qmi_wlanfw_mode_send(struct ath11k_base *ab,
u32 mode)
{
struct qmi_wlanfw_wlan_mode_req_msg_v01 req;
struct qmi_wlanfw_wlan_mode_resp_msg_v01 resp;
struct qmi_txn txn = {};
int ret = 0;
memset(&req, 0, sizeof(req));
memset(&resp, 0, sizeof(resp));
req.mode = mode;
req.hw_debug_valid = 1;
req.hw_debug = 0;
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_wlan_mode_resp_msg_v01_ei, &resp);
if (ret < 0)
goto out;
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_WLAN_MODE_REQ_V01,
QMI_WLANFW_WLAN_MODE_REQ_MSG_V01_MAX_LEN,
qmi_wlanfw_wlan_mode_req_msg_v01_ei, &req);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to send mode request, mode: %d, err = %d\n",
mode, ret);
goto out;
}
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
if (ret < 0) {
if (mode == ATH11K_FIRMWARE_MODE_OFF && ret == -ENETRESET) {
ath11k_warn(ab, "WLFW service is dis-connected\n");
return 0;
}
ath11k_warn(ab, "qmi failed set mode request, mode: %d, err = %d\n",
mode, ret);
goto out;
}
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
ath11k_warn(ab, "Mode request failed, mode: %d, result: %d err: %d\n",
mode, resp.resp.result, resp.resp.error);
ret = -EINVAL;
goto out;
}
out:
return ret;
}
static int ath11k_qmi_wlanfw_wlan_cfg_send(struct ath11k_base *ab)
{
struct qmi_wlanfw_wlan_cfg_req_msg_v01 *req;
struct qmi_wlanfw_wlan_cfg_resp_msg_v01 resp;
struct ce_pipe_config *ce_cfg;
struct service_to_pipe *svc_cfg;
struct qmi_txn txn = {};
int ret = 0, pipe_num;
ce_cfg = (struct ce_pipe_config *)ab->qmi.ce_cfg.tgt_ce;
svc_cfg = (struct service_to_pipe *)ab->qmi.ce_cfg.svc_to_ce_map;
req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
memset(&resp, 0, sizeof(resp));
req->host_version_valid = 1;
strlcpy(req->host_version, ATH11K_HOST_VERSION_STRING,
sizeof(req->host_version));
req->tgt_cfg_valid = 1;
/* This is number of CE configs */
req->tgt_cfg_len = ab->qmi.ce_cfg.tgt_ce_len;
for (pipe_num = 0; pipe_num < req->tgt_cfg_len ; pipe_num++) {
req->tgt_cfg[pipe_num].pipe_num = ce_cfg[pipe_num].pipenum;
req->tgt_cfg[pipe_num].pipe_dir = ce_cfg[pipe_num].pipedir;
req->tgt_cfg[pipe_num].nentries = ce_cfg[pipe_num].nentries;
req->tgt_cfg[pipe_num].nbytes_max = ce_cfg[pipe_num].nbytes_max;
req->tgt_cfg[pipe_num].flags = ce_cfg[pipe_num].flags;
}
req->svc_cfg_valid = 1;
/* This is number of Service/CE configs */
req->svc_cfg_len = ab->qmi.ce_cfg.svc_to_ce_map_len;
for (pipe_num = 0; pipe_num < req->svc_cfg_len; pipe_num++) {
req->svc_cfg[pipe_num].service_id = svc_cfg[pipe_num].service_id;
req->svc_cfg[pipe_num].pipe_dir = svc_cfg[pipe_num].pipedir;
req->svc_cfg[pipe_num].pipe_num = svc_cfg[pipe_num].pipenum;
}
req->shadow_reg_valid = 0;
/* set shadow v2 configuration */
if (ab->hw_params.supports_shadow_regs) {
req->shadow_reg_v2_valid = 1;
req->shadow_reg_v2_len = min_t(u32,
ab->qmi.ce_cfg.shadow_reg_v2_len,
QMI_WLANFW_MAX_NUM_SHADOW_REG_V2_V01);
memcpy(&req->shadow_reg_v2, ab->qmi.ce_cfg.shadow_reg_v2,
sizeof(u32) * req->shadow_reg_v2_len);
} else {
req->shadow_reg_v2_valid = 0;
}
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_wlan_cfg_resp_msg_v01_ei, &resp);
if (ret < 0)
goto out;
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_WLAN_CFG_REQ_V01,
QMI_WLANFW_WLAN_CFG_REQ_MSG_V01_MAX_LEN,
qmi_wlanfw_wlan_cfg_req_msg_v01_ei, req);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to send wlan config request, err = %d\n",
ret);
goto out;
}
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
if (ret < 0) {
ath11k_warn(ab, "qmi failed wlan config request, err = %d\n", ret);
goto out;
}
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
ath11k_warn(ab, "qmi wlan config request failed, result: %d, err: %d\n",
resp.resp.result, resp.resp.error);
ret = -EINVAL;
goto out;
}
out:
kfree(req);
return ret;
}
void ath11k_qmi_firmware_stop(struct ath11k_base *ab)
{
int ret;
ret = ath11k_qmi_wlanfw_mode_send(ab, ATH11K_FIRMWARE_MODE_OFF);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to send wlan mode off\n");
return;
}
}
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;
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;
}
int ath11k_qmi_firmware_start(struct ath11k_base *ab,
u32 mode)
{
int ret;
ret = ath11k_qmi_wlanfw_wlan_cfg_send(ab);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to send wlan cfg:%d\n", ret);
return ret;
}
ret = ath11k_qmi_wlanfw_mode_send(ab, mode);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to send wlan fw mode:%d\n", ret);
return ret;
}
return 0;
}
int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab)
{
int timeout;
if (ab->enable_cold_boot_cal == 0 ||
ab->hw_params.cold_boot_calib == 0)
return 0;
ath11k_dbg(ab, ATH11K_DBG_QMI, "wait for cold boot done\n");
timeout = wait_event_timeout(ab->qmi.cold_boot_waitq, (ab->qmi.cal_done == 1),
ATH11K_COLD_BOOT_FW_RESET_DELAY);
if (timeout <= 0) {
ath11k_warn(ab, "Coldboot Calibration timed out\n");
return -ETIMEDOUT;
}
/* reset the firmware */
ath11k_hif_power_down(ab);
ath11k_hif_power_up(ab);
ath11k_dbg(ab, ATH11K_DBG_QMI, "exit wait for cold boot done\n");
return 0;
}
EXPORT_SYMBOL(ath11k_qmi_fwreset_from_cold_boot);
static int ath11k_qmi_process_coldboot_calibration(struct ath11k_base *ab)
{
int timeout;
int ret;
ret = ath11k_qmi_wlanfw_mode_send(ab, ATH11K_FIRMWARE_MODE_COLD_BOOT);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to send wlan fw mode:%d\n", ret);
return ret;
}
ath11k_dbg(ab, ATH11K_DBG_QMI, "Coldboot calibration wait started\n");
timeout = wait_event_timeout(ab->qmi.cold_boot_waitq,
(ab->qmi.cal_done == 1),
ATH11K_COLD_BOOT_FW_RESET_DELAY);
if (timeout <= 0) {
ath11k_warn(ab, "Coldboot Calibration failed - wait ended\n");
return 0;
}
ath11k_dbg(ab, ATH11K_DBG_QMI, "Coldboot calibration done\n");
return 0;
}
static int ath11k_qmi_m3_dump_upload_done_ind_send(struct ath11k_base *ab,
u32 pdev_id, int status)
{
struct qmi_wlanfw_m3_dump_upload_done_req_msg_v01 *req;
struct qmi_wlanfw_m3_dump_upload_done_resp_msg_v01 *resp;
struct qmi_txn txn = {};
int ret = 0;
req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
resp = kzalloc(sizeof(*resp), GFP_KERNEL);
if (!resp) {
kfree(req);
return -ENOMEM;
}
req->pdev_id = pdev_id;
req->status = status;
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_m3_dump_upload_done_resp_msg_v01_ei, resp);
if (ret < 0)
goto out;
ret =
qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLFW_M3_DUMP_UPLOAD_DONE_REQ_V01,
QMI_WLANFW_M3_DUMP_UPLOAD_DONE_REQ_MSG_V01_MAX_MSG_LEN,
qmi_wlanfw_m3_dump_upload_done_req_msg_v01_ei, req);
if (ret < 0) {
qmi_txn_cancel(&txn);
ath11k_warn(ab, "Failed to send M3 dump upload done 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, "qmi M3 upload done req failed, result: %d, err: %d\n",
resp->resp.result, resp->resp.error);
ret = -EINVAL;
goto out;
}
ath11k_info(ab, "qmi m3 dump uploaded\n");
out:
kfree(req);
kfree(resp);
return ret;
}
static void ath11k_qmi_event_m3_dump_upload_req(struct ath11k_qmi *qmi,
void *data)
{
struct ath11k_base *ab = qmi->ab;
struct target_mem_chunk *target_mem = ab->qmi.target_mem;
struct ath11k_qmi_m3_dump_upload_req_data *event_data = data;
struct ath11k_qmi_m3_dump_data *m3_dump_data;
void *dump;
int i, ret = 0;
m3_dump_data = kzalloc(sizeof(*m3_dump_data), GFP_KERNEL);
if (!m3_dump_data)
return;
dump = vzalloc(event_data->size);
if (!dump) {
kfree(m3_dump_data);
return;
}
for (i = 0; i < ab->qmi.mem_seg_count; i++) {
if (target_mem[i].paddr == event_data->addr &&
event_data->size <= target_mem[i].size)
break;
}
if (i == ab->qmi.mem_seg_count) {
ath11k_warn(ab, "qmi invalid paddr from firmware for M3 dump\n");
ret = -EINVAL;
vfree(dump);
goto send_resp;
}
m3_dump_data->addr = target_mem[i].vaddr;
m3_dump_data->size = event_data->size;
m3_dump_data->pdev_id = event_data->pdev_id;
m3_dump_data->timestamp = ktime_to_ms(ktime_get());
memcpy(dump, m3_dump_data->addr, m3_dump_data->size);
dev_coredumpv(ab->dev, dump, le32_to_cpu(m3_dump_data->size),
GFP_KERNEL);
send_resp:
ret = ath11k_qmi_m3_dump_upload_done_ind_send(ab, event_data->pdev_id, ret);
if (ret < 0)
ath11k_warn(ab, "qmi M3 dump upload done failed\n");
kfree(m3_dump_data);
return;
}
static void ath11k_qmi_event_qdss_trace_save_hdlr(struct ath11k_qmi *qmi,
void *data)
{
struct ath11k_qmi_event_qdss_trace_save_data *event_data = data;
struct ath11k_base *ab = qmi->ab;
if (!ab->qmi.qdss_mem_seg_len) {
ath11k_warn(ab, "Memory for QDSS trace is not available\n");
return;
}
ath11k_coredump_qdss_dump(ab, event_data);
ab->qmi.qdss_mem_seg_len = 0;
ab->is_qdss_tracing = false;
}
static int
ath11k_qmi_driver_event_post(struct ath11k_qmi *qmi,
enum ath11k_qmi_event_type type,
void *data)
{
struct ath11k_qmi_driver_event *event;
event = kzalloc(sizeof(*event), GFP_ATOMIC);
if (!event)
return -ENOMEM;
event->type = type;
event->data = data;
spin_lock(&qmi->event_lock);
list_add_tail(&event->list, &qmi->event_list);
spin_unlock(&qmi->event_lock);
queue_work(qmi->event_wq, &qmi->event_work);
return 0;
}
static int ath11k_qmi_event_server_arrive(struct ath11k_qmi *qmi)
{
struct ath11k_base *ab = qmi->ab;
int ret;
ret = ath11k_qmi_fw_ind_register_send(ab);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to send FW indication QMI:%d\n", ret);
return ret;
}
ret = ath11k_qmi_host_cap_send(ab);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to send host cap QMI:%d\n", ret);
return ret;
}
return ret;
}
static int ath11k_qmi_event_mem_request(struct ath11k_qmi *qmi)
{
struct ath11k_base *ab = qmi->ab;
int ret;
ret = ath11k_qmi_respond_fw_mem_request(ab);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to respond fw mem req:%d\n", ret);
return ret;
}
return ret;
}
int ath11k_qmi_pci_alloc_qdss_mem(struct ath11k_qmi *qmi)
{
struct ath11k_base *ab = qmi->ab;
struct device *dev = ab->dev;
int i;
u32 addr = 0;
if (ab->qmi.qdss_mem_seg_len > 1) {
ath11k_warn(ab, "%s: FW requests %d segments, max allowed is 1\n",
__func__, ab->qmi.qdss_mem_seg_len);
return -EINVAL;
}
for (i = 0; i < ab->qmi.qdss_mem_seg_len; i++) {
switch (ab->qmi.qdss_mem[i].type) {
case QDSS_ETR_MEM_REGION_TYPE:
if (ab->qmi.qdss_mem[i].size > QMI_Q6_QDSS_ETR_SIZE_QCN9074) {
ath11k_warn(ab, "%s: FW requests more memory 0x%x\n",
__func__, ab->qmi.qdss_mem[i].size);
return -ENOMEM;
}
if (ath11k_host_ddr_addr) {
addr = ath11k_host_ddr_addr +
ATH11K_HOST_DDR_QDSS_OFFSET;
} else if (of_property_read_u32(dev->of_node,
"etr-addr", &addr)) {
ath11k_warn(ab, "qmi fail to get etr-addr in dt\n");
return -ENOMEM;
}
ab->qmi.qdss_mem[i].paddr = (phys_addr_t)addr;
ab->qmi.qdss_mem[i].vaddr =
ioremap(ab->qmi.qdss_mem[i].paddr,
ab->qmi.qdss_mem[i].size);
if (!ab->qmi.qdss_mem[i].vaddr) {
ath11k_warn(ab, "WARNING etr-addr remap failed\n");
return -ENOMEM;
}
break;
default:
ath11k_warn(ab, "qmi ignore invalid qdss mem req type %d\n",
ab->qmi.qdss_mem[i].type);
return -ENOMEM;
}
}
return 0;
}
static
struct device_node *ath11k_get_etr_dev_node(struct ath11k_base *ab)
{
struct device_node *dev_node = NULL;
if (ab->userpd_id) {
if (ab->userpd_id == QCN6122_USERPD_0)
dev_node = of_find_node_by_name(NULL,
"q6_qcn6122_etr_1");
else if (ab->userpd_id == QCN6122_USERPD_1)
dev_node = of_find_node_by_name(NULL,
"q6_qcn6122_etr_2");
} else {
dev_node = of_find_node_by_name(NULL, "q6_etr_dump");
}
return dev_node;
}
int ath11k_qmi_qdss_mem_alloc(struct ath11k_qmi *qmi)
{
int ret, i;
struct ath11k_base *ab = qmi->ab;
struct device_node *dev_node = NULL;
struct resource q6_etr;
if (ab->bus_params.fixed_bdf_addr) {
dev_node = ath11k_get_etr_dev_node(ab);
if (!dev_node) {
ath11k_err(ab, "No q6_etr_dump available in dts\n");
return -ENOMEM;
}
ret = of_address_to_resource(dev_node, 0, &q6_etr);
if (ret) {
ath11k_err(ab, "Failed to get resource for q6_etr_dump\n");
return -EINVAL;
}
for (i = 0; i < ab->qmi.qdss_mem_seg_len; i++) {
ab->qmi.qdss_mem[i].vaddr = NULL;
ab->qmi.qdss_mem[i].paddr = q6_etr.start;
ab->qmi.qdss_mem[i].size = resource_size(&q6_etr);
ab->qmi.qdss_mem[i].type = QDSS_ETR_MEM_REGION_TYPE;
if (ab->hw_rev == ATH11K_HW_QCN6122) {
ab->qmi.qdss_mem[i].vaddr =
ioremap(ab->qmi.qdss_mem[i].paddr,
ab->qmi.qdss_mem[i].size);
if (!ab->qmi.qdss_mem[i].vaddr) {
ath11k_err(ab, "Error: etr-addr remap failed\n");
return -ENOMEM;
}
}
ath11k_dbg(ab, ATH11K_DBG_QMI, "QDSS mem addr pa 0x%x va 0x%p, size 0x%x",
(unsigned int)ab->qmi.qdss_mem[i].paddr,
ab->qmi.qdss_mem[i].vaddr,
(unsigned int)ab->qmi.qdss_mem[i].size);
}
} else {
ret = ath11k_qmi_pci_alloc_qdss_mem(qmi);
}
return ret;
}
int ath11k_qmi_qdss_trace_mem_info_send_sync(struct ath11k_base *ab)
{
struct qmi_wlanfw_respond_mem_req_msg_v01 *req;
struct qmi_wlanfw_respond_mem_resp_msg_v01 resp;
struct qmi_txn txn = {};
int ret = 0, i;
req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
memset(&resp, 0, sizeof(resp));
req->mem_seg_len = ab->qmi.qdss_mem_seg_len;
for (i = 0; i < req->mem_seg_len ; i++) {
req->mem_seg[i].addr = ab->qmi.qdss_mem[i].paddr;
req->mem_seg[i].size = ab->qmi.qdss_mem[i].size;
req->mem_seg[i].type = ab->qmi.qdss_mem[i].type;
}
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_respond_mem_resp_msg_v01_ei, &resp);
if (ret < 0) {
ath11k_warn(ab, "Fail to initialize txn for QDSS trace mem request: err %d\n",
ret);
goto out;
}
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLFW_QDSS_TRACE_MEM_INFO_REQ_V01,
QMI_WLANFW_RESPOND_MEM_REQ_MSG_V01_MAX_LEN,
qmi_wlanfw_respond_mem_req_msg_v01_ei, req);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to respond memory 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 memory request, err = %d\n", ret);
goto out;
}
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
ath11k_warn(ab, "Respond mem req failed, result: %d, err: %d\n",
resp.resp.result, resp.resp.error);
ret = -EINVAL;
goto out;
}
out:
kfree(req);
return ret;
}
static void ath11k_qmi_event_qdss_trace_req_mem_hdlr(struct ath11k_qmi *qmi)
{
int ret = 0;
struct ath11k_base *ab = qmi->ab;
ret = ath11k_qmi_qdss_mem_alloc(qmi);
if (ret < 0) {
ath11k_err(ab, "failed to allocate memory for qdss:%d\n", ret);
return;
}
ret = ath11k_qmi_qdss_trace_mem_info_send_sync(ab);
if (ret < 0) {
ath11k_warn(ab,
"qdss trace mem info send sync failed:%d\n", ret);
return;
}
/* After qdss_trace_mem_info(QMI_WLFW_QDSS_TRACE_MEM_INFO_REQ_V01),
* the firmware will take one second at max
* for its configuration. We shouldn't send qdss_trace request
* before that.
*/
msleep(1000);
ret = ath11k_send_qdss_trace_mode_req(ab, QMI_WLANFW_QDSS_TRACE_ON_V01);
if (ret < 0) {
ath11k_warn(ab, "Failed to enable QDSS trace: %d\n", ret);
return;
}
ab->is_qdss_tracing = true;
ath11k_dbg(ab, ATH11K_DBG_QMI, "QDSS configuration is completed and trace started\n");
}
static int ath11k_qmi_event_load_bdf(struct ath11k_qmi *qmi)
{
struct ath11k_base *ab = qmi->ab;
int ret;
ret = ath11k_qmi_request_target_cap(ab);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to req target capabilities:%d\n", ret);
return ret;
}
ret = ath11k_qmi_request_device_info(ab);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to req device info %d\n", ret);
return ret;
}
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;
}
ret = ath11k_qmi_wlanfw_m3_info_send(ab);
if (ret < 0) {
ath11k_warn(ab, "qmi failed to send m3 info req:%d\n", ret);
return ret;
}
return ret;
}
static void ath11k_qmi_msg_mem_request_cb(struct qmi_handle *qmi_hdl,
struct sockaddr_qrtr *sq,
struct qmi_txn *txn,
const void *data)
{
struct ath11k_qmi *qmi = container_of(qmi_hdl, struct ath11k_qmi, handle);
struct ath11k_base *ab = qmi->ab;
const struct qmi_wlanfw_request_mem_ind_msg_v01 *msg = data;
int i, ret;
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware request memory request\n");
if (msg->mem_seg_len == 0 ||
msg->mem_seg_len > ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01)
ath11k_warn(ab, "Invalid memory segment length: %u\n",
msg->mem_seg_len);
ab->qmi.mem_seg_count = msg->mem_seg_len;
for (i = 0; i < qmi->mem_seg_count ; i++) {
ab->qmi.target_mem[i].type = msg->mem_seg[i].type;
ab->qmi.target_mem[i].size = msg->mem_seg[i].size;
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi mem seg type %d size %d\n",
msg->mem_seg[i].type, msg->mem_seg[i].size);
}
if (ab->bus_params.fixed_mem_region) {
ret = ath11k_qmi_assign_target_mem_chunk(ab);
if (ret) {
ath11k_warn(ab, "qmi failed to assign target memory: %d\n",
ret);
return;
}
} else {
ret = ath11k_qmi_alloc_target_mem_chunk(ab);
if (ret) {
ath11k_warn(ab, "qmi failed to alloc target memory: %d\n",
ret);
return;
}
}
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_REQUEST_MEM, NULL);
}
static void ath11k_qmi_msg_mem_ready_cb(struct qmi_handle *qmi_hdl,
struct sockaddr_qrtr *sq,
struct qmi_txn *txn,
const void *decoded)
{
struct ath11k_qmi *qmi = container_of(qmi_hdl, struct ath11k_qmi, handle);
struct ath11k_base *ab = qmi->ab;
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware memory ready indication\n");
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_FW_MEM_READY, NULL);
}
static void ath11k_qmi_msg_fw_ready_cb(struct qmi_handle *qmi_hdl,
struct sockaddr_qrtr *sq,
struct qmi_txn *txn,
const void *decoded)
{
struct ath11k_qmi *qmi = container_of(qmi_hdl, struct ath11k_qmi, handle);
struct ath11k_base *ab = qmi->ab;
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware ready\n");
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_FW_READY, NULL);
}
static void ath11k_qmi_msg_cold_boot_cal_done_cb(struct qmi_handle *qmi_hdl,
struct sockaddr_qrtr *sq,
struct qmi_txn *txn,
const void *decoded)
{
struct ath11k_qmi *qmi = container_of(qmi_hdl,
struct ath11k_qmi, handle);
struct ath11k_base *ab = qmi->ab;
ab->qmi.cal_done = 1;
wake_up(&ab->qmi.cold_boot_waitq);
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi cold boot calibration done\n");
}
static void ath11k_qmi_m3_dump_upload_req_ind_cb(struct qmi_handle *qmi_hdl,
struct sockaddr_qrtr *sq,
struct qmi_txn *txn,
const void *data)
{
struct ath11k_qmi *qmi = container_of(qmi_hdl, struct ath11k_qmi, handle);
struct ath11k_base *ab = qmi->ab;
const struct qmi_wlanfw_m3_dump_upload_req_ind_msg_v01 *msg = data;
struct ath11k_qmi_m3_dump_upload_req_data *event_data;
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi m3 dump memory request\n");
event_data = kzalloc(sizeof(*event_data), GFP_KERNEL);
if (!event_data)
return;
event_data->pdev_id = msg->pdev_id;
event_data->addr = msg->addr;
event_data->size = msg->size;
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_M3_DUMP_UPLOAD_REQ,
event_data);
}
static void ath11k_wlfw_qdss_trace_req_mem_ind_cb(struct qmi_handle *qmi_hdl,
struct sockaddr_qrtr *sq,
struct qmi_txn *txn,
const void *data)
{
struct ath11k_qmi *qmi = container_of(qmi_hdl,
struct ath11k_qmi,
handle);
struct ath11k_base *ab = qmi->ab;
const struct qmi_wlanfw_request_mem_ind_msg_v01 *msg = data;
int i;
ath11k_dbg(ab, ATH11K_DBG_QMI, "qdss trace request memory from firmware\n");
ab->qmi.qdss_mem_seg_len = msg->mem_seg_len;
if (msg->mem_seg_len > 1) {
ath11k_warn(ab, "%s: FW requests %d segments, overwriting it with 1",
__func__, msg->mem_seg_len);
ab->qmi.qdss_mem_seg_len = 1;
}
for (i = 0; i < ab->qmi.qdss_mem_seg_len; i++) {
ab->qmi.qdss_mem[i].type = msg->mem_seg[i].type;
ab->qmi.qdss_mem[i].size = msg->mem_seg[i].size;
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi mem seg type %d size %d\n",
msg->mem_seg[i].type, msg->mem_seg[i].size);
}
ath11k_qmi_driver_event_post(qmi,
ATH11K_QMI_EVENT_QDSS_TRACE_REQ_MEM,
NULL);
}
static void ath11k_wlfw_qdss_trace_save_ind_cb(struct qmi_handle *qmi_hdl,
struct sockaddr_qrtr *sq,
struct qmi_txn *txn,
const void *data)
{
struct ath11k_qmi *qmi = container_of(qmi_hdl,
struct ath11k_qmi,
handle);
struct ath11k_base *ab = qmi->ab;
const struct qmi_wlanfw_qdss_trace_save_ind_msg_v01 *ind_msg = data;
struct ath11k_qmi_event_qdss_trace_save_data *event_data;
int i = 0;
if (ind_msg->source == 1)
return;
ath11k_dbg(ab, ATH11K_DBG_QMI, "Received qdss trace save indication\n");
event_data = kzalloc(sizeof(*event_data), GFP_KERNEL);
if (!event_data)
return;
if (ind_msg->mem_seg_valid) {
if (ind_msg->mem_seg_len > QDSS_TRACE_SEG_LEN_MAX) {
ath11k_err(ab, "Invalid seg len %u\n",
ind_msg->mem_seg_len);
goto free_event_data;
}
event_data->mem_seg_len = ind_msg->mem_seg_len;
for (i = 0; i < ind_msg->mem_seg_len; i++) {
event_data->mem_seg[i].addr = ind_msg->mem_seg[i].addr;
event_data->mem_seg[i].size = ind_msg->mem_seg[i].size;
}
}
event_data->total_size = ind_msg->total_size;
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_QDSS_TRACE_SAVE,
event_data);
return;
free_event_data:
kfree(event_data);
}
int ath11k_qmi_mem_read(struct ath11k_base *ab, u32 mem_addr, void *mem_value,size_t count)
{
struct qmi_wlanfw_mem_read_req_msg_v01 *req;
struct qmi_wlanfw_mem_read_resp_msg_v01 *resp;
struct qmi_txn txn = {};
int ret = 0;
req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
resp = kzalloc(sizeof(*resp), GFP_KERNEL);
if (!resp) {
kfree(req);
return -ENOMEM;
}
req->offset = mem_addr;
/* Firmware uses mem type to map to various memory regions.
* If this is set to 0, firmware uses automatic mapping of regions.
* i.e, if mem address is given and mem_type is 0, firmware will
* find under which memory region that address belongs
*/
req->mem_type = QMI_MEM_REGION_TYPE;
req->data_len = count;
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_mem_read_resp_msg_v01_ei, resp);
if (ret < 0)
goto out;
ret =
qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_MEM_READ_REQ_V01,
QMI_WLANFW_MEM_READ_REQ_MSG_V01_MAX_MSG_LEN,
qmi_wlanfw_mem_read_req_msg_v01_ei, req);
if (ret < 0) {
qmi_txn_cancel(&txn);
ath11k_warn(ab, "Failed to send mem read 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, "qmi mem read req failed, result: %d, err: %d\n",
resp->resp.result, resp->resp.error);
ret = -EINVAL;
goto out;
}
if (!resp->data_valid || resp->data_len != req->data_len) {
ath11k_warn(ab, "qmi mem read is invalid\n");
ret = -EINVAL;
goto out;
}
memcpy(mem_value, resp->data, resp->data_len);
out:
kfree(req);
kfree(resp);
return ret;
}
int ath11k_qmi_mem_write(struct ath11k_base *ab, u32 mem_addr, void* mem_value, size_t count)
{
struct qmi_wlanfw_mem_write_req_msg_v01 *req;
struct qmi_wlanfw_mem_write_resp_msg_v01 *resp;
struct qmi_txn txn = {};
int ret = 0;
req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
resp = kzalloc(sizeof(*resp), GFP_KERNEL);
if (!resp) {
kfree(req);
return -ENOMEM;
}
req->offset = mem_addr;
req->mem_type = QMI_MEM_REGION_TYPE;
req->data_len = count;
memcpy(req->data, mem_value, req->data_len);
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_mem_write_resp_msg_v01_ei, resp);
if (ret < 0)
goto out;
ret =
qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_MEM_WRITE_REQ_V01,
QMI_WLANFW_MEM_WRITE_REQ_MSG_V01_MAX_MSG_LEN,
qmi_wlanfw_mem_write_req_msg_v01_ei, req);
if (ret < 0) {
qmi_txn_cancel(&txn);
ath11k_warn(ab, "Failed to send mem write 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, "qmi mem write req failed, result: %d, err: %d\n",
resp->resp.result, resp->resp.error);
ret = -EINVAL;
goto out;
}
out:
kfree(req);
kfree(resp);
return ret;
}
static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = {
{
.type = QMI_INDICATION,
.msg_id = QMI_WLFW_REQUEST_MEM_IND_V01,
.ei = qmi_wlanfw_request_mem_ind_msg_v01_ei,
.decoded_size = sizeof(struct qmi_wlanfw_request_mem_ind_msg_v01),
.fn = ath11k_qmi_msg_mem_request_cb,
},
{
.type = QMI_INDICATION,
.msg_id = QMI_WLFW_FW_MEM_READY_IND_V01,
.ei = qmi_wlanfw_mem_ready_ind_msg_v01_ei,
.decoded_size = sizeof(struct qmi_wlanfw_fw_mem_ready_ind_msg_v01),
.fn = ath11k_qmi_msg_mem_ready_cb,
},
{
.type = QMI_INDICATION,
.msg_id = QMI_WLFW_FW_READY_IND_V01,
.ei = qmi_wlanfw_fw_ready_ind_msg_v01_ei,
.decoded_size = sizeof(struct qmi_wlanfw_fw_ready_ind_msg_v01),
.fn = ath11k_qmi_msg_fw_ready_cb,
},
{
.type = QMI_INDICATION,
.msg_id = QMI_WLFW_COLD_BOOT_CAL_DONE_IND_V01,
.ei = qmi_wlanfw_cold_boot_cal_done_ind_msg_v01_ei,
.decoded_size =
sizeof(struct qmi_wlanfw_fw_cold_cal_done_ind_msg_v01),
.fn = ath11k_qmi_msg_cold_boot_cal_done_cb,
},
{
.type = QMI_INDICATION,
.msg_id = QMI_WLFW_M3_DUMP_UPLOAD_REQ_IND_V01,
.ei = qmi_wlanfw_m3_dump_upload_req_ind_msg_v01_ei,
.decoded_size =
sizeof(struct qmi_wlanfw_m3_dump_upload_req_ind_msg_v01),
.fn = ath11k_qmi_m3_dump_upload_req_ind_cb,
},
{
.type = QMI_INDICATION,
.msg_id = QMI_WLFW_QDSS_TRACE_REQ_MEM_IND_V01,
.ei = qmi_wlanfw_request_mem_ind_msg_v01_ei,
.decoded_size =
sizeof(struct qmi_wlanfw_request_mem_ind_msg_v01),
.fn = ath11k_wlfw_qdss_trace_req_mem_ind_cb,
},
{
.type = QMI_INDICATION,
.msg_id = QMI_WLFW_QDSS_TRACE_SAVE_IND_V01,
.ei = qmi_wlanfw_qdss_trace_save_ind_msg_v01_ei,
.decoded_size =
sizeof(struct qmi_wlanfw_qdss_trace_save_ind_msg_v01),
.fn = ath11k_wlfw_qdss_trace_save_ind_cb,
},
};
static int ath11k_qmi_ops_new_server(struct qmi_handle *qmi_hdl,
struct qmi_service *service)
{
struct ath11k_qmi *qmi = container_of(qmi_hdl, struct ath11k_qmi, handle);
struct ath11k_base *ab = qmi->ab;
struct sockaddr_qrtr *sq = &qmi->sq;
int ret;
sq->sq_family = AF_QIPCRTR;
sq->sq_node = service->node;
sq->sq_port = service->port;
ret = kernel_connect(qmi_hdl->sock, (struct sockaddr *)sq,
sizeof(*sq), 0);
if (ret) {
ath11k_warn(ab, "qmi failed to connect to remote service %d\n", ret);
return ret;
}
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi wifi fw qmi service connected\n");
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_SERVER_ARRIVE, NULL);
return ret;
}
static void ath11k_qmi_ops_del_server(struct qmi_handle *qmi_hdl,
struct qmi_service *service)
{
struct ath11k_qmi *qmi = container_of(qmi_hdl, struct ath11k_qmi, handle);
struct ath11k_base *ab = qmi->ab;
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi wifi fw del server\n");
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_SERVER_EXIT, NULL);
}
static const struct qmi_ops ath11k_qmi_ops = {
.new_server = ath11k_qmi_ops_new_server,
.del_server = ath11k_qmi_ops_del_server,
};
static int ath11k_wait_for_gic_msi(struct ath11k_base *ab)
{
int timeout;
if (ab->hw_rev != ATH11K_HW_QCN6122)
return 0;
timeout = wait_event_timeout(ab->ipci.gic_msi_waitq,
(ab->ipci.gic_enabled == 1),
ATH11K_RCV_GIC_MSI_HDLR_DELAY);
if (timeout <= 0) {
ath11k_warn(ab, "Receive gic msi handler timed out\n");
return -ETIMEDOUT;
}
return 0;
}
static void ath11k_qmi_driver_event_work(struct work_struct *work)
{
struct ath11k_qmi *qmi = container_of(work, struct ath11k_qmi,
event_work);
struct ath11k_qmi_driver_event *event;
struct ath11k_base *ab = qmi->ab;
int ret;
spin_lock(&qmi->event_lock);
while (!list_empty(&qmi->event_list)) {
event = list_first_entry(&qmi->event_list,
struct ath11k_qmi_driver_event, list);
list_del(&event->list);
spin_unlock(&qmi->event_lock);
if (test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags))
return;
switch (event->type) {
case ATH11K_QMI_EVENT_SERVER_ARRIVE:
ret = ath11k_qmi_event_server_arrive(qmi);
if (ret < 0)
set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags);
break;
case ATH11K_QMI_EVENT_SERVER_EXIT:
set_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags);
set_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
break;
case ATH11K_QMI_EVENT_REQUEST_MEM:
ret = ath11k_qmi_event_mem_request(qmi);
if (ret < 0)
set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags);
break;
case ATH11K_QMI_EVENT_FW_MEM_READY:
ret = ath11k_qmi_event_load_bdf(qmi);
if (ret < 0)
set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags);
break;
case ATH11K_QMI_EVENT_FW_READY:
clear_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags);
if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) {
ath11k_hal_dump_srng_stats(ab);
queue_work(ab->workqueue, &ab->restart_work);
break;
}
if (ab->enable_cold_boot_cal && ab->qmi.cal_done == 0 &&
ab->hw_params.cold_boot_calib) {
ath11k_qmi_process_coldboot_calibration(ab);
} else {
clear_bit(ATH11K_FLAG_CRASH_FLUSH,
&ab->dev_flags);
clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
ret = ath11k_wait_for_gic_msi(ab);
if (ret) {
ath11k_warn(ab,
"Failed to get qgic handler for dev %d ret: %d\n",
ab->hw_rev, ret);
break;
}
ath11k_core_qmi_firmware_ready(ab);
set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags);
if (country_code)
ath11k_reg_update_cc(ab, country_code);
}
break;
case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE:
break;
case ATH11K_QMI_EVENT_M3_DUMP_UPLOAD_REQ:
ath11k_qmi_event_m3_dump_upload_req(qmi, event->data);
break;
case ATH11K_QMI_EVENT_QDSS_TRACE_REQ_MEM:
ath11k_qmi_event_qdss_trace_req_mem_hdlr(qmi);
break;
case ATH11K_QMI_EVENT_QDSS_TRACE_SAVE:
ath11k_qmi_event_qdss_trace_save_hdlr(qmi, event->data);
break;
default:
ath11k_warn(ab, "invalid event type: %d", event->type);
break;
}
kfree(event);
spin_lock(&qmi->event_lock);
}
spin_unlock(&qmi->event_lock);
}
int ath11k_enable_fwlog(struct ath11k_base *ab)
{
struct wlfw_ini_req_msg_v01 *req;
struct wlfw_ini_resp_msg_v01 resp;
struct qmi_txn txn = {};
int ret = 0;
req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
memset(&resp, 0, sizeof(resp));
req->enablefwlog_valid = 1;
req->enablefwlog = 1;
ret = qmi_txn_init(&ab->qmi.handle, &txn,
wlfw_ini_resp_msg_v01_ei, &resp);
if (ret < 0)
goto out;
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLFW_INI_REQ_V01,
WLFW_INI_REQ_MSG_V01_MAX_MSG_LEN,
wlfw_ini_req_msg_v01_ei, req);
if (ret < 0) {
ath11k_warn(ab, "Failed to send init request for enabling fwlog = %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, "fwlog enable wait for resp failed: %d\n", ret);
goto out;
}
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
ath11k_warn(ab, "fwlog enable request failed, result: %d, err: %d\n",
resp.resp.result, resp.resp.error);
ret = -EINVAL;
goto out;
}
out:
kfree(req);
return ret;
}
int ath11k_qmi_init_service(struct ath11k_base *ab)
{
int ret;
memset(&ab->qmi.target, 0, sizeof(struct target_info));
memset(&ab->qmi.target_mem, 0, sizeof(struct target_mem_chunk));
ab->qmi.ab = ab;
ab->qmi.target_mem_mode = ATH11K_QMI_TARGET_MEM_MODE;
if (ab->hw_params.fwmem_mode_change) {
ab->qmi.target_mem_mode = fwmem_mode;
if (ab->qmi.target_mem_mode == ATH11K_QMI_TARGET_MEM_MODE_256M &&
ath11k_ftm_mode)
ab->enable_cold_boot_cal = 1;
else if(ab->qmi.target_mem_mode == ATH11K_QMI_TARGET_MEM_MODE_256M)
ab->enable_cold_boot_cal = 0;
}
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi target mem mode %d\n", ab->qmi.target_mem_mode);
ret = qmi_handle_init(&ab->qmi.handle, ATH11K_QMI_RESP_LEN_MAX,
&ath11k_qmi_ops, ath11k_qmi_msg_handlers);
if (ret < 0) {
ath11k_warn(ab, "failed to initialize qmi handle\n");
return ret;
}
ab->qmi.event_wq = alloc_workqueue("ath11k_qmi_driver_event",
WQ_UNBOUND, 1);
if (!ab->qmi.event_wq) {
ath11k_err(ab, "failed to allocate workqueue\n");
return -EFAULT;
}
INIT_LIST_HEAD(&ab->qmi.event_list);
spin_lock_init(&ab->qmi.event_lock);
INIT_WORK(&ab->qmi.event_work, ath11k_qmi_driver_event_work);
ret = qmi_add_lookup(&ab->qmi.handle, ATH11K_QMI_WLFW_SERVICE_ID_V01,
ATH11K_QMI_WLFW_SERVICE_VERS_V01,
ab->qmi.service_ins_id);
if (ret < 0) {
ath11k_warn(ab, "failed to add qmi lookup\n");
destroy_workqueue(ab->qmi.event_wq);
return ret;
}
init_waitqueue_head(&ab->ipci.gic_msi_waitq);
return ret;
}
void ath11k_qmi_deinit_service(struct ath11k_base *ab)
{
qmi_handle_release(&ab->qmi.handle);
cancel_work_sync(&ab->qmi.event_work);
destroy_workqueue(ab->qmi.event_wq);
ath11k_qmi_m3_free(ab);
ath11k_qmi_free_target_mem_chunk(ab);
}
EXPORT_SYMBOL(ath11k_qmi_deinit_service);