// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/elf.h>
#include "qmi.h"
#include "core.h"
#include "debug.h"
#include <linux/of.h>
#include <linux/firmware.h>
#include <linux/of_address.h>
#include <linux/ioport.h>
#define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02
#define HOST_CSTATE_BIT 0x04
#define PLATFORM_CAP_PCIE_GLOBAL_RESET 0x08
#define ATH12K_QMI_MAX_CHUNK_SIZE 2097152
static const struct qmi_elem_info wlfw_host_mlo_chip_info_s_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct wlfw_host_mlo_chip_info_s_v01,
chip_id),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct wlfw_host_mlo_chip_info_s_v01,
num_local_links),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = QMI_WLFW_MAX_NUM_MLO_LINKS_PER_CHIP_V01,
.elem_size = sizeof (u8),
.array_type = STATIC_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct wlfw_host_mlo_chip_info_s_v01,
hw_link_id),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = QMI_WLFW_MAX_NUM_MLO_LINKS_PER_CHIP_V01,
.elem_size = sizeof (u8),
.array_type = STATIC_ARRAY,
.tlv_type = 0,
.offset = offsetof(struct wlfw_host_mlo_chip_info_s_v01,
valid_mlo_link_id),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static const 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_duraiton),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1E,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
platform_name_valid),
},
{
.data_type = QMI_STRING,
.elem_len = QMI_WLANFW_MAX_PLATFORM_NAME_LEN_V01 + 1,
.elem_size = sizeof (char ),
.array_type = NO_ARRAY,
.tlv_type = 0x1E,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
platform_name),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1F,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
ddr_range_valid),
},
{
.data_type = QMI_STRUCT,
.elem_len = QMI_WLANFW_MAX_HOST_DDR_RANGE_SIZE_V01,
.elem_size = sizeof (struct qmi_wlanfw_host_ddr_range),
.array_type = STATIC_ARRAY,
.tlv_type = 0x1F,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
ddr_range),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x20,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
host_build_type_valid),
},
{
.data_type = QMI_SIGNED_4_BYTE_ENUM,
.elem_len = 1,
.elem_size = sizeof (enum qmi_wlanfw_host_build_type),
.array_type = NO_ARRAY,
.tlv_type = 0x20,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
host_build_type),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x21,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
mlo_capable_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x21,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
mlo_capable),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x22,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
mlo_chip_id_valid),
},
{
.data_type = QMI_UNSIGNED_2_BYTE,
.elem_len = 1,
.elem_size = sizeof (u16),
.array_type = NO_ARRAY,
.tlv_type = 0x22,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
mlo_chip_id),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x23,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
mlo_group_id_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x23,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
mlo_group_id),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x24,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
max_mlo_peer_valid),
},
{
.data_type = QMI_UNSIGNED_2_BYTE,
.elem_len = 1,
.elem_size = sizeof (u16),
.array_type = NO_ARRAY,
.tlv_type = 0x24,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
max_mlo_peer),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x25,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
mlo_num_chips_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x25,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
mlo_num_chips),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x26,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
mlo_chip_info_valid),
},
{
.data_type = QMI_STRUCT,
.elem_len = QMI_WLFW_MAX_NUM_MLO_CHIPS_V01,
.elem_size = sizeof (struct wlfw_host_mlo_chip_info_s_v01),
.array_type = STATIC_ARRAY,
.tlv_type = 0x26,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
mlo_chip_info),
.ei_array = wlfw_host_mlo_chip_info_s_v01_ei,
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x27,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
feature_list_valid),
},
{
.data_type = QMI_UNSIGNED_8_BYTE,
.elem_len = 1,
.elem_size = sizeof (u64),
.array_type = NO_ARRAY,
.tlv_type = 0x27,
.offset = offsetof(struct qmi_wlanfw_host_cap_req_msg_v01,
feature_list),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static const 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_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static const struct qmi_elem_info qmi_wlanfw_phy_cap_req_msg_v01_ei[] = {
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static const struct qmi_elem_info qmi_wlanfw_phy_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_phy_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_phy_cap_resp_msg_v01,
num_phy_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_phy_cap_resp_msg_v01,
num_phy),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x11,
.offset = offsetof(struct qmi_wlanfw_phy_cap_resp_msg_v01,
board_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_phy_cap_resp_msg_v01,
board_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_phy_cap_resp_msg_v01,
single_chip_mlo_support_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_phy_cap_resp_msg_v01,
single_chip_mlo_support),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static const 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_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static const 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 const 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 const 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 const 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 = ATH12K_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 const 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 const 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 = ATH12K_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 const 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 const 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 const 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 const 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 const 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 const struct qmi_elem_info qmi_wlanfw_dev_mem_info_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_dev_mem_info_s_v01,
start),
},
{
.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_dev_mem_info_s_v01,
size),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static const 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 = ATH12K_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 const 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 = ATH12K_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_caldata_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_caldata_read_timeout),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1A,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
fw_caps_valid),
},
{
.data_type = QMI_UNSIGNED_8_BYTE,
.elem_len = 1,
.elem_size = sizeof (u64),
.array_type = NO_ARRAY,
.tlv_type = 0x1A,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01, fw_caps),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1B,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
rd_card_chain_cap_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_cap_resp_msg_v01,
rd_card_chain_cap),
},
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x1C,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01,
dev_mem_info_valid),
},
{
.data_type = QMI_STRUCT,
.elem_len = ATH12K_QMI_WLFW_MAX_DEV_MEM_NUM_V01,
.elem_size = sizeof (struct qmi_wlanfw_dev_mem_info_s_v01),
.array_type = STATIC_ARRAY,
.tlv_type = 0x1C,
.offset = offsetof(struct qmi_wlanfw_cap_resp_msg_v01, dev_mem),
.ei_array = qmi_wlanfw_dev_mem_info_s_v01_ei,
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static const 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 const 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 const 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 const 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 const 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 const 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 const 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 const struct qmi_elem_info qmi_wlanfw_shadow_reg_v3_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_v3_cfg_s_v01,
addr),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static const 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 const 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 const 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 = 0x17,
.offset = offsetof(struct qmi_wlanfw_wlan_cfg_req_msg_v01,
shadow_reg_v3_valid),
},
{
.data_type = QMI_DATA_LEN,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x17,
.offset = offsetof(struct qmi_wlanfw_wlan_cfg_req_msg_v01,
shadow_reg_v3_len),
},
{
.data_type = QMI_STRUCT,
.elem_len = QMI_WLANFW_MAX_NUM_SHADOW_REG_V3_V01,
.elem_size = sizeof (struct qmi_wlanfw_shadow_reg_v3_cfg_s_v01),
.array_type = VAR_LEN_ARRAY,
.tlv_type = 0x17,
.offset = offsetof(struct qmi_wlanfw_wlan_cfg_req_msg_v01,
shadow_reg_v3),
.ei_array = qmi_wlanfw_shadow_reg_v3_cfg_s_v01_ei,
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static const 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 const struct qmi_elem_info qmi_wlanfw_mem_ready_ind_msg_v01_ei[] = {
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
},
};
static const struct qmi_elem_info qmi_wlanfw_fw_ready_ind_msg_v01_ei[] = {
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
},
};
static const struct qmi_elem_info qmi_wlanfw_wlan_ini_req_msg_v01_ei[] = {
{
.data_type = QMI_OPT_FLAG,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x10,
.offset = offsetof(struct qmi_wlanfw_wlan_ini_req_msg_v01,
enable_fwlog_valid),
},
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
.elem_size = sizeof (u8),
.array_type = NO_ARRAY,
.tlv_type = 0x10,
.offset = offsetof(struct qmi_wlanfw_wlan_ini_req_msg_v01,
enable_fwlog),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static const struct qmi_elem_info qmi_wlanfw_wlan_ini_resp_msg_v01_ei[] = {
{
.data_type = QMI_STRUCT,
.elem_len = 1,
.elem_size = sizeof (struct qmi_response_type_v01),
.array_type = NO_ARRAY,
.tlv_type = 0x02,
.offset = offsetof(struct qmi_wlanfw_wlan_ini_resp_msg_v01,
resp),
.ei_array = qmi_response_type_v01_ei,
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static void ath12k_host_cap_hw_link_id_init(struct ath12k_hw_group *ag)
{
struct ath12k_base *ab, *partner_ab;
int i, j, hw_id_base;
for (i = 0; i < ag->num_devices; i++) {
hw_id_base = 0;
ab = ag->ab[i];
for (j = 0; j < ag->num_devices; j++) {
partner_ab = ag->ab[j];
if (partner_ab->wsi_info.index >= ab->wsi_info.index)
continue ;
hw_id_base += partner_ab->qmi.num_radios;
}
ab->wsi_info.hw_link_id_base = hw_id_base;
}
ag->hw_link_id_init_done = true ;
}
static int ath12k_host_cap_parse_mlo(struct ath12k_base *ab,
struct qmi_wlanfw_host_cap_req_msg_v01 *req)
{
struct wlfw_host_mlo_chip_info_s_v01 *info;
struct ath12k_hw_group *ag = ab->ag;
struct ath12k_base *partner_ab;
u8 hw_link_id = 0;
int i, j, ret;
if (!ag->mlo_capable) {
ath12k_dbg(ab, ATH12K_DBG_QMI,
"MLO is disabled hence skip QMI MLO cap" );
return 0;
}
if (!ab->qmi.num_radios || ab->qmi.num_radios == U8_MAX) {
ag->mlo_capable = false ;
ath12k_dbg(ab, ATH12K_DBG_QMI,
"skip QMI MLO cap due to invalid num_radio %d\n" ,
ab->qmi.num_radios);
return 0;
}
if (ab->device_id == ATH12K_INVALID_DEVICE_ID) {
ath12k_err(ab, "failed to send MLO cap due to invalid device id\n" );
return -EINVAL;
}
req->mlo_capable_valid = 1;
req->mlo_capable = 1;
req->mlo_chip_id_valid = 1;
req->mlo_chip_id = ab->device_id;
req->mlo_group_id_valid = 1;
req->mlo_group_id = ag->id;
req->max_mlo_peer_valid = 1;
/* Max peer number generally won't change for the same device
* but needs to be synced with host driver.
*/
req->max_mlo_peer = ab->hw_params->max_mlo_peer;
req->mlo_num_chips_valid = 1;
req->mlo_num_chips = ag->num_devices;
ath12k_dbg(ab, ATH12K_DBG_QMI, "mlo capability advertisement device_id %d group_id %d num_devices %d" ,
req->mlo_chip_id, req->mlo_group_id, req->mlo_num_chips);
mutex_lock(&ag->mutex);
if (!ag->hw_link_id_init_done)
ath12k_host_cap_hw_link_id_init(ag);
for (i = 0; i < ag->num_devices; i++) {
info = &req->mlo_chip_info[i];
partner_ab = ag->ab[i];
if (partner_ab->device_id == ATH12K_INVALID_DEVICE_ID) {
ath12k_err(ab, "failed to send MLO cap due to invalid partner device id\n" );
ret = -EINVAL;
goto device_cleanup;
}
info->chip_id = partner_ab->device_id;
info->num_local_links = partner_ab->qmi.num_radios;
ath12k_dbg(ab, ATH12K_DBG_QMI, "mlo device id %d num_link %d\n" ,
info->chip_id, info->num_local_links);
for (j = 0; j < info->num_local_links; j++) {
info->hw_link_id[j] = partner_ab->wsi_info.hw_link_id_base + j;
info->valid_mlo_link_id[j] = 1;
ath12k_dbg(ab, ATH12K_DBG_QMI, "mlo hw_link_id %d\n" ,
info->hw_link_id[j]);
hw_link_id++;
}
}
if (hw_link_id <= 0)
ag->mlo_capable = false ;
req->mlo_chip_info_valid = 1;
mutex_unlock(&ag->mutex);
return 0;
device_cleanup:
for (i = i - 1; i >= 0; i--) {
info = &req->mlo_chip_info[i];
memset(info, 0, sizeof (*info));
}
req->mlo_num_chips = 0;
req->mlo_num_chips_valid = 0;
req->max_mlo_peer = 0;
req->max_mlo_peer_valid = 0;
req->mlo_group_id = 0;
req->mlo_group_id_valid = 0;
req->mlo_chip_id = 0;
req->mlo_chip_id_valid = 0;
req->mlo_capable = 0;
req->mlo_capable_valid = 0;
ag->mlo_capable = false ;
mutex_unlock(&ag->mutex);
return ret;
}
/* clang stack usage explodes if this is inlined */
static noinline_for_stack
int ath12k_qmi_host_cap_send(struct ath12k_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;
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->hw_params->fw.m3_loader == ath12k_m3_fw_loader_driver) {
req.m3_support_valid = 1;
req.m3_support = 1;
req.m3_cache_support_valid = 1;
req.m3_cache_support = 1;
}
req.cal_done_valid = 1;
req.cal_done = ab->qmi.cal_done;
if (ab->hw_params->qmi_cnss_feature_bitmap) {
req.feature_list_valid = 1;
req.feature_list = ab->hw_params->qmi_cnss_feature_bitmap;
}
/* BRINGUP: here we are piggybacking a lot of stuff using
* internal_sleep_clock, should it be split?
*/
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;
req.nm_modem |= PLATFORM_CAP_PCIE_GLOBAL_RESET;
}
ret = ath12k_host_cap_parse_mlo(ab, &req);
if (ret < 0)
goto out;
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) {
qmi_txn_cancel(&txn);
ath12k_warn(ab, "Failed to send host capability request,err = %d\n" , ret);
goto out;
}
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH12K_QMI_WLANFW_TIMEOUT_MS));
if (ret < 0)
goto out;
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
ath12k_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 void ath12k_qmi_phy_cap_send(struct ath12k_base *ab)
{
struct qmi_wlanfw_phy_cap_req_msg_v01 req = {};
struct qmi_wlanfw_phy_cap_resp_msg_v01 resp = {};
struct qmi_txn txn;
int ret;
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_phy_cap_resp_msg_v01_ei, &resp);
if (ret < 0)
goto out;
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_PHY_CAP_REQ_V01,
QMI_WLANFW_PHY_CAP_REQ_MSG_V01_MAX_LEN,
qmi_wlanfw_phy_cap_req_msg_v01_ei, &req);
if (ret < 0) {
qmi_txn_cancel(&txn);
ath12k_warn(ab, "failed to send phy capability request: %d\n" , ret);
goto out;
}
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH12K_QMI_WLANFW_TIMEOUT_MS));
if (ret < 0)
goto out;
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
ret = -EOPNOTSUPP;
goto out;
}
if (resp.single_chip_mlo_support_valid && resp.single_chip_mlo_support)
ab->single_chip_mlo_support = true ;
if (!resp.num_phy_valid) {
ret = -ENODATA;
goto out;
}
ab->qmi.num_radios = resp.num_phy;
ath12k_dbg(ab, ATH12K_DBG_QMI,
"phy capability resp valid %d single_chip_mlo_support %d valid %d num_phy %d valid %d board_id %d\n" ,
resp.single_chip_mlo_support_valid, resp.single_chip_mlo_support,
resp.num_phy_valid, resp.num_phy,
resp.board_id_valid, resp.board_id);
return ;
out:
/* If PHY capability not advertised then rely on default num link */
ab->qmi.num_radios = ab->hw_params->def_num_link;
ath12k_dbg(ab, ATH12K_DBG_QMI,
"no valid response from PHY capability, choose default num_phy %d\n" ,
ab->qmi.num_radios);
}
static int ath12k_qmi_fw_ind_register_send(struct ath12k_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->pin_connect_result_enable_valid = 0;
req->pin_connect_result_enable = 0;
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) {
qmi_txn_cancel(&txn);
ath12k_warn(ab, "Failed to send indication register request, err = %d\n" ,
ret);
goto out;
}
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH12K_QMI_WLANFW_TIMEOUT_MS));
if (ret < 0) {
ath12k_warn(ab, "failed to register fw indication %d\n" , ret);
goto out;
}
if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
ath12k_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;
}
/* clang stack usage explodes if this is inlined */
static noinline_for_stack
int ath12k_qmi_respond_fw_mem_request(struct ath12k_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;
/* Some targets by default request a block of big contiguous
* DMA memory, it's hard to allocate from kernel. So host returns
* failure to firmware and firmware then request multiple blocks of
* small chunk size memory.
*/
if (!test_bit(ATH12K_FLAG_FIXED_MEM_REGION, &ab->dev_flags) &&
ab->qmi.target_mem_delayed) {
delayed = true ;
ath12k_dbg(ab, ATH12K_DBG_QMI, "qmi delays mem_request %d\n" ,
ab->qmi.mem_seg_count);
} 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;
ath12k_dbg(ab, ATH12K_DBG_QMI,
"qmi req mem_seg[%d] %pad %u %u\n" , i,
&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) {
qmi_txn_cancel(&txn);
ath12k_warn(ab, "qmi failed to respond memory request, err = %d\n" ,
ret);
goto out;
}
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH12K_QMI_WLANFW_TIMEOUT_MS));
if (ret < 0) {
ath12k_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;
ath12k_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;
}
void ath12k_qmi_reset_mlo_mem(struct ath12k_hw_group *ag)
{
struct target_mem_chunk *mlo_chunk;
int i;
lockdep_assert_held(&ag->mutex);
if (!ag->mlo_mem.init_done || ag->num_started)
return ;
for (i = 0; i < ARRAY_SIZE(ag->mlo_mem.chunk); i++) {
mlo_chunk = &ag->mlo_mem.chunk[i];
if (mlo_chunk->v.addr)
/* TODO: Mode 0 recovery is the default mode hence resetting the
* whole memory region for now. Once Mode 1 support is added, this
* needs to be handled properly
*/
memset(mlo_chunk->v.addr, 0, mlo_chunk->size);
}
}
static void ath12k_qmi_free_mlo_mem_chunk(struct ath12k_base *ab,
struct target_mem_chunk *chunk,
int idx)
{
struct ath12k_hw_group *ag = ab->ag;
struct target_mem_chunk *mlo_chunk;
bool fixed_mem;
lockdep_assert_held(&ag->mutex);
if (!ag->mlo_mem.init_done || ag->num_started)
return ;
if (idx >= ARRAY_SIZE(ag->mlo_mem.chunk)) {
ath12k_warn(ab, "invalid index for MLO memory chunk free: %d\n" , idx);
return ;
}
fixed_mem = test_bit(ATH12K_FLAG_FIXED_MEM_REGION, &ab->dev_flags);
mlo_chunk = &ag->mlo_mem.chunk[idx];
if (fixed_mem && mlo_chunk->v.ioaddr) {
iounmap(mlo_chunk->v.ioaddr);
mlo_chunk->v.ioaddr = NULL;
} else if (mlo_chunk->v.addr) {
dma_free_coherent(ab->dev,
mlo_chunk->size,
mlo_chunk->v.addr,
mlo_chunk->paddr);
mlo_chunk->v.addr = NULL;
}
mlo_chunk->paddr = 0;
mlo_chunk->size = 0;
if (fixed_mem)
chunk->v.ioaddr = NULL;
else
chunk->v.addr = NULL;
chunk->paddr = 0;
chunk->size = 0;
}
static void ath12k_qmi_free_target_mem_chunk(struct ath12k_base *ab)
{
struct ath12k_hw_group *ag = ab->ag;
int i, mlo_idx;
for (i = 0, mlo_idx = 0; i < ab->qmi.mem_seg_count; i++) {
if (ab->qmi.target_mem[i].type == MLO_GLOBAL_MEM_REGION_TYPE) {
ath12k_qmi_free_mlo_mem_chunk(ab,
&ab->qmi.target_mem[i],
mlo_idx++);
} else {
if (test_bit(ATH12K_FLAG_FIXED_MEM_REGION, &ab->dev_flags) &&
ab->qmi.target_mem[i].v.ioaddr) {
iounmap(ab->qmi.target_mem[i].v.ioaddr);
ab->qmi.target_mem[i].v.ioaddr = NULL;
} else {
if (!ab->qmi.target_mem[i].v.addr)
continue ;
dma_free_coherent(ab->dev,
ab->qmi.target_mem[i].prev_size,
ab->qmi.target_mem[i].v.addr,
ab->qmi.target_mem[i].paddr);
ab->qmi.target_mem[i].v.addr = NULL;
}
}
}
if (!ag->num_started && ag->mlo_mem.init_done) {
ag->mlo_mem.init_done = false ;
ag->mlo_mem.mlo_mem_size = 0;
}
}
static int ath12k_qmi_alloc_chunk(struct ath12k_base *ab,
struct target_mem_chunk *chunk)
{
/* Firmware reloads in recovery/resume.
* In such cases, no need to allocate memory for FW again.
*/
if (chunk->v.addr) {
if (chunk->prev_type == chunk->type &&
chunk->prev_size == chunk->size)
goto this_chunk_done;
/* cannot reuse the existing chunk */
dma_free_coherent(ab->dev, chunk->prev_size,
chunk->v.addr, chunk->paddr);
chunk->v.addr = NULL;
}
chunk->v.addr = dma_alloc_coherent(ab->dev,
chunk->size,
&chunk->paddr,
GFP_KERNEL | __GFP_NOWARN);
if (!chunk->v.addr) {
if (chunk->size > ATH12K_QMI_MAX_CHUNK_SIZE) {
ab->qmi.target_mem_delayed = true ;
ath12k_warn(ab,
"qmi dma allocation failed (%d B type %u), will try later with small size\n" ,
chunk->size,
chunk->type);
ath12k_qmi_free_target_mem_chunk(ab);
return -EAGAIN;
}
ath12k_warn(ab, "memory allocation failure for %u size: %d\n" ,
chunk->type, chunk->size);
return -ENOMEM;
}
chunk->prev_type = chunk->type;
chunk->prev_size = chunk->size;
this_chunk_done:
return 0;
}
static int ath12k_qmi_alloc_target_mem_chunk(struct ath12k_base *ab)
{
struct target_mem_chunk *chunk, *mlo_chunk;
struct ath12k_hw_group *ag = ab->ag;
int i, mlo_idx, ret;
int mlo_size = 0;
mutex_lock(&ag->mutex);
if (!ag->mlo_mem.init_done) {
memset(ag->mlo_mem.chunk, 0, sizeof (ag->mlo_mem.chunk));
ag->mlo_mem.init_done = true ;
}
ab->qmi.target_mem_delayed = false ;
for (i = 0, mlo_idx = 0; i < ab->qmi.mem_seg_count; i++) {
chunk = &ab->qmi.target_mem[i];
/* Allocate memory for the region and the functionality supported
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5 C=97 H=93 G=94
¤ Dauer der Verarbeitung: 0.25 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland