2019-11-23 09:58:40 +02:00
|
|
|
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
2024-02-23 17:20:33 +02:00
|
|
|
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
2019-11-23 09:58:40 +02:00
|
|
|
*/
|
|
|
|
|
2020-09-29 20:15:29 +03:00
|
|
|
#include <linux/elf.h>
|
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
#include "qmi.h"
|
|
|
|
#include "core.h"
|
|
|
|
#include "debug.h"
|
2023-07-26 19:40:31 +05:30
|
|
|
#include "hif.h"
|
2019-11-23 09:58:40 +02:00
|
|
|
#include <linux/of.h>
|
2021-12-14 17:39:43 +02:00
|
|
|
#include <linux/of_address.h>
|
|
|
|
#include <linux/ioport.h>
|
2019-11-23 09:58:40 +02:00
|
|
|
#include <linux/firmware.h>
|
2022-04-29 22:34:58 +05:30
|
|
|
#include <linux/of_irq.h>
|
2019-11-23 09:58:40 +02:00
|
|
|
|
2020-08-14 10:10:29 +03:00
|
|
|
#define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02
|
|
|
|
#define HOST_CSTATE_BIT 0x04
|
2021-10-11 13:56:02 +08:00
|
|
|
#define PLATFORM_CAP_PCIE_GLOBAL_RESET 0x08
|
2022-10-10 11:32:37 +08:00
|
|
|
#define PLATFORM_CAP_PCIE_PME_D3COLD 0x10
|
2020-08-14 10:10:29 +03:00
|
|
|
|
2022-03-09 16:54:25 +05:30
|
|
|
#define FW_BUILD_ID_MASK "QC_IMAGE_VERSION_STRING="
|
|
|
|
|
2020-10-16 20:58:31 +05:30
|
|
|
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)");
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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_EOTI,
|
|
|
|
.array_type = NO_ARRAY,
|
|
|
|
.tlv_type = QMI_COMMON_TLV_TYPE,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_host_cap_resp_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_ind_register_req_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_ind_register_resp_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_mem_cfg_s_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_mem_seg_s_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_request_mem_ind_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_mem_seg_resp_s_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_respond_mem_req_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_respond_mem_resp_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_cap_req_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.data_type = QMI_EOTI,
|
|
|
|
.array_type = NO_ARRAY,
|
|
|
|
.tlv_type = QMI_COMMON_TLV_TYPE,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_device_info_req_msg_v01_ei[] = {
|
2022-04-29 22:34:58 +05:30
|
|
|
{
|
|
|
|
.data_type = QMI_EOTI,
|
|
|
|
.array_type = NO_ARRAY,
|
|
|
|
.tlv_type = QMI_COMMON_TLV_TYPE,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlfw_device_info_resp_msg_v01_ei[] = {
|
2022-04-29 22:34:58 +05:30
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_rf_chip_info_s_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_rf_board_info_s_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_soc_info_s_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_fw_version_info_s_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_cap_resp_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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),
|
|
|
|
},
|
2021-09-28 12:05:39 +03:00
|
|
|
{
|
|
|
|
.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),
|
|
|
|
},
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.data_type = QMI_EOTI,
|
|
|
|
.array_type = NO_ARRAY,
|
|
|
|
.tlv_type = QMI_COMMON_TLV_TYPE,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_bdf_download_req_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_bdf_download_resp_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_m3_info_req_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_m3_info_resp_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_ce_tgt_pipe_cfg_s_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_ce_svc_pipe_cfg_s_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_shadow_reg_cfg_s_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_shadow_reg_v2_cfg_s_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_wlan_mode_req_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_wlan_mode_resp_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_wlan_cfg_req_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_wlan_cfg_resp_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_mem_ready_ind_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.data_type = QMI_EOTI,
|
|
|
|
.array_type = NO_ARRAY,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_fw_ready_ind_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.data_type = QMI_EOTI,
|
|
|
|
.array_type = NO_ARRAY,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_cold_boot_cal_done_ind_msg_v01_ei[] = {
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
.data_type = QMI_EOTI,
|
|
|
|
.array_type = NO_ARRAY,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_wlan_ini_req_msg_v01_ei[] = {
|
2021-12-20 20:10:53 +08:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
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 qmi_wlanfw_wlan_ini_req_msg_v01,
|
|
|
|
enablefwlog),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.data_type = QMI_EOTI,
|
|
|
|
.array_type = NO_ARRAY,
|
|
|
|
.tlv_type = QMI_COMMON_TLV_TYPE,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlanfw_wlan_ini_resp_msg_v01_ei[] = {
|
2021-12-20 20:10:53 +08:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2022-09-14 17:23:03 -07:00
|
|
|
static const struct qmi_elem_info qmi_wlfw_fw_init_done_ind_msg_v01_ei[] = {
|
2022-08-31 09:04:19 +03:00
|
|
|
{
|
|
|
|
.data_type = QMI_EOTI,
|
|
|
|
.array_type = NO_ARRAY,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
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;
|
2021-11-02 18:22:38 +05:30
|
|
|
struct qmi_txn txn;
|
2019-11-23 09:58:40 +02:00
|
|
|
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;
|
|
|
|
|
2022-04-29 22:34:55 +05:30
|
|
|
if (ab->hw_params.m3_fw_support) {
|
2020-08-14 10:10:20 +03:00
|
|
|
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;
|
|
|
|
}
|
2019-11-23 09:58:40 +02:00
|
|
|
|
|
|
|
req.cal_done_valid = 1;
|
|
|
|
req.cal_done = ab->qmi.cal_done;
|
|
|
|
|
2020-08-14 10:10:29 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-10-11 13:56:02 +08:00
|
|
|
if (ab->hw_params.global_reset)
|
|
|
|
req.nm_modem |= PLATFORM_CAP_PCIE_GLOBAL_RESET;
|
|
|
|
|
2022-10-10 11:32:37 +08:00
|
|
|
req.nm_modem |= PLATFORM_CAP_PCIE_PME_D3COLD;
|
|
|
|
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "host cap request\n");
|
2021-02-22 09:35:49 +02:00
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
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) {
|
2021-11-02 18:22:38 +05:30
|
|
|
qmi_txn_cancel(&txn);
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to send host capability request: %d\n", ret);
|
2019-11-23 09:58:40 +02:00
|
|
|
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) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "host capability request failed: %d %d\n",
|
2019-11-23 09:58:40 +02:00
|
|
|
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;
|
2020-11-24 17:59:16 +02:00
|
|
|
int ret;
|
2019-11-23 09:58:40 +02:00
|
|
|
|
|
|
|
req = kzalloc(sizeof(*req), GFP_KERNEL);
|
|
|
|
if (!req)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
resp = kzalloc(sizeof(*resp), GFP_KERNEL);
|
2020-11-24 17:59:16 +02:00
|
|
|
if (!resp) {
|
|
|
|
ret = -ENOMEM;
|
2019-11-23 09:58:40 +02:00
|
|
|
goto resp_out;
|
2020-11-24 17:59:16 +02:00
|
|
|
}
|
2019-11-23 09:58:40 +02:00
|
|
|
|
|
|
|
req->client_id_valid = 1;
|
|
|
|
req->client_id = QMI_WLANFW_CLIENT_ID;
|
|
|
|
req->fw_ready_enable_valid = 1;
|
|
|
|
req->fw_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;
|
|
|
|
|
2022-04-29 22:34:59 +05:30
|
|
|
/* WCN6750 doesn't request for DDR memory via QMI,
|
|
|
|
* instead it uses a fixed 12MB reserved memory
|
|
|
|
* region in DDR.
|
|
|
|
*/
|
|
|
|
if (!ab->hw_params.fixed_fw_mem) {
|
|
|
|
req->request_mem_enable_valid = 1;
|
|
|
|
req->request_mem_enable = 1;
|
|
|
|
req->fw_mem_ready_enable_valid = 1;
|
|
|
|
req->fw_mem_ready_enable = 1;
|
|
|
|
}
|
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
ret = qmi_txn_init(handle, &txn,
|
|
|
|
qmi_wlanfw_ind_register_resp_msg_v01_ei, resp);
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "indication register request\n");
|
2021-02-22 09:35:49 +02:00
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
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) {
|
2021-11-02 18:22:38 +05:30
|
|
|
qmi_txn_cancel(&txn);
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to send indication register request: %d\n",
|
2019-11-23 09:58:40 +02:00
|
|
|
ret);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
|
|
|
|
if (ret < 0) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to register fw indication: %d\n", ret);
|
2019-11-23 09:58:40 +02:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "firmware indication register request failed: %d %d\n",
|
2019-11-23 09:58:40 +02:00
|
|
|
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;
|
2021-11-02 18:22:38 +05:30
|
|
|
struct qmi_txn txn;
|
2019-11-23 09:58:40 +02:00
|
|
|
int ret = 0, i;
|
2020-12-17 09:04:57 +02:00
|
|
|
bool delayed;
|
2019-11-23 09:58:40 +02:00
|
|
|
|
|
|
|
req = kzalloc(sizeof(*req), GFP_KERNEL);
|
|
|
|
if (!req)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
memset(&resp, 0, sizeof(resp));
|
|
|
|
|
2020-08-14 10:10:26 +03:00
|
|
|
/* For QCA6390 by default FW requests a block of ~4M contiguous
|
|
|
|
* DMA memory, it's hard to allocate from OS. So host returns
|
2022-09-09 07:55:35 -07:00
|
|
|
* failure to FW and FW will then request multiple blocks of small
|
2020-08-14 10:10:26 +03:00
|
|
|
* chunk size memory.
|
|
|
|
*/
|
2022-04-29 22:34:55 +05:30
|
|
|
if (!(ab->hw_params.fixed_mem_region ||
|
2021-12-14 17:39:43 +02:00
|
|
|
test_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags)) &&
|
|
|
|
ab->qmi.target_mem_delayed) {
|
2020-12-17 09:04:57 +02:00
|
|
|
delayed = true;
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "delays mem_request %d\n",
|
2020-08-14 10:10:26 +03:00
|
|
|
ab->qmi.mem_seg_count);
|
|
|
|
memset(req, 0, sizeof(*req));
|
|
|
|
} else {
|
2020-12-17 09:04:57 +02:00
|
|
|
delayed = false;
|
2020-08-14 10:10:26 +03:00
|
|
|
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;
|
2021-02-11 13:05:49 +02:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI,
|
2023-06-09 17:24:28 +03:00
|
|
|
"req mem_seg[%d] %pad %u %u\n", i,
|
2021-02-21 19:27:54 +01:00
|
|
|
&ab->qmi.target_mem[i].paddr,
|
2021-02-11 13:05:49 +02:00
|
|
|
ab->qmi.target_mem[i].size,
|
|
|
|
ab->qmi.target_mem[i].type);
|
2020-08-14 10:10:26 +03:00
|
|
|
}
|
|
|
|
}
|
2019-11-23 09:58:40 +02:00
|
|
|
|
|
|
|
ret = qmi_txn_init(&ab->qmi.handle, &txn,
|
|
|
|
qmi_wlanfw_respond_mem_resp_msg_v01_ei, &resp);
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "respond memory request delayed %i\n",
|
2021-02-22 09:35:49 +02:00
|
|
|
delayed);
|
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
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) {
|
2021-11-02 18:22:38 +05:30
|
|
|
qmi_txn_cancel(&txn);
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to respond qmi memory request: %d\n",
|
2019-11-23 09:58:40 +02:00
|
|
|
ret);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
|
|
|
|
if (ret < 0) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to wait qmi memory request: %d\n", ret);
|
2019-11-23 09:58:40 +02:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
|
2020-12-17 09:04:57 +02:00
|
|
|
/* the error response is expected when
|
|
|
|
* target_mem_delayed is true.
|
|
|
|
*/
|
|
|
|
if (delayed && resp.resp.error == 0)
|
|
|
|
goto out;
|
|
|
|
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "qmi respond memory request failed: %d %d\n",
|
2019-11-23 09:58:40 +02:00
|
|
|
resp.resp.result, resp.resp.error);
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
out:
|
|
|
|
kfree(req);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-08-14 10:10:21 +03:00
|
|
|
static void ath11k_qmi_free_target_mem_chunk(struct ath11k_base *ab)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ab->qmi.mem_seg_count; i++) {
|
2022-04-29 22:34:55 +05:30
|
|
|
if ((ab->hw_params.fixed_mem_region ||
|
2021-12-14 17:39:43 +02:00
|
|
|
test_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags)) &&
|
|
|
|
ab->qmi.target_mem[i].iaddr)
|
|
|
|
iounmap(ab->qmi.target_mem[i].iaddr);
|
|
|
|
|
2020-08-14 10:10:21 +03:00
|
|
|
if (!ab->qmi.target_mem[i].vaddr)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
dma_free_coherent(ab->dev,
|
wifi: ath11k: fix warning in dma_free_coherent() of memory chunks while recovery
Commit 26f3a021b37c ("ath11k: allocate smaller chunks of memory for
firmware") and commit f6f92968e1e5 ("ath11k: qmi: try to allocate a
big block of DMA memory first") change ath11k to allocate the memory
chunks for target twice while wlan load. It fails for the 1st time
because of large memory and then changed to allocate many small chunks
for the 2nd time sometimes as below log.
1st time failed:
[10411.640620] ath11k_pci 0000:05:00.0: qmi firmware request memory request
[10411.640625] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 6881280
[10411.640630] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 3784704
[10411.640658] ath11k_pci 0000:05:00.0: qmi dma allocation failed (6881280 B type 1), will try later with small size
[10411.640671] ath11k_pci 0000:05:00.0: qmi delays mem_request 2
[10411.640677] ath11k_pci 0000:05:00.0: qmi respond memory request delayed 1
2nd time success:
[10411.642004] ath11k_pci 0000:05:00.0: qmi firmware request memory request
[10411.642008] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642012] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642014] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642016] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642018] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642020] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642022] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642024] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642027] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642029] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642031] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 458752
[10411.642033] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 131072
[10411.642035] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288
[10411.642037] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288
[10411.642039] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288
[10411.642041] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288
[10411.642043] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288
[10411.642045] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288
[10411.642047] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 491520
[10411.642049] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
And then commit 5962f370ce41 ("ath11k: Reuse the available memory after
firmware reload") skip the ath11k_qmi_free_resource() which frees the
memory chunks while recovery, after that, when run recovery test on
WCN6855, a warning happened every time as below and finally leads fail
for recovery.
[ 159.570318] BUG: Bad page state in process kworker/u16:5 pfn:33300
[ 159.570320] page:0000000096ffdbb9 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x33300
[ 159.570324] flags: 0xfffffc0000000(node=0|zone=1|lastcpupid=0x1fffff)
[ 159.570329] raw: 000fffffc0000000 0000000000000000 dead000000000122 0000000000000000
[ 159.570332] raw: 0000000000000000 0000000000000000 00000001ffffffff 0000000000000000
[ 159.570334] page dumped because: nonzero _refcount
[ 159.570440] firewire_ohci syscopyarea sysfillrect psmouse sdhci_pci ahci sysimgblt firewire_core fb_sys_fops libahci crc_itu_t cqhci drm sdhci e1000e wmi video
[ 159.570460] CPU: 2 PID: 217 Comm: kworker/u16:5 Kdump: loaded Tainted: G B 5.19.0-rc1-wt-ath+ #3
[ 159.570465] Hardware name: LENOVO 418065C/418065C, BIOS 83ET63WW (1.33 ) 07/29/2011
[ 159.570467] Workqueue: qmi_msg_handler qmi_data_ready_work [qmi_helpers]
[ 159.570475] Call Trace:
[ 159.570476] <TASK>
[ 159.570478] dump_stack_lvl+0x49/0x5f
[ 159.570486] dump_stack+0x10/0x12
[ 159.570493] bad_page+0xab/0xf0
[ 159.570502] check_free_page_bad+0x66/0x70
[ 159.570511] __free_pages_ok+0x530/0x9a0
[ 159.570517] ? __dev_printk+0x58/0x6b
[ 159.570525] ? _dev_printk+0x56/0x72
[ 159.570534] ? qmi_decode+0x119/0x470 [qmi_helpers]
[ 159.570543] __free_pages+0x91/0xd0
[ 159.570548] dma_free_contiguous+0x50/0x60
[ 159.570556] dma_direct_free+0xe5/0x140
[ 159.570564] dma_free_attrs+0x35/0x50
[ 159.570570] ath11k_qmi_msg_mem_request_cb+0x2ae/0x3c0 [ath11k]
[ 159.570620] qmi_invoke_handler+0xac/0xe0 [qmi_helpers]
[ 159.570630] qmi_handle_message+0x6d/0x180 [qmi_helpers]
[ 159.570643] qmi_data_ready_work+0x2ca/0x440 [qmi_helpers]
[ 159.570656] process_one_work+0x227/0x440
[ 159.570667] worker_thread+0x31/0x3d0
[ 159.570676] ? process_one_work+0x440/0x440
[ 159.570685] kthread+0xfe/0x130
[ 159.570692] ? kthread_complete_and_exit+0x20/0x20
[ 159.570701] ret_from_fork+0x22/0x30
[ 159.570712] </TASK>
The reason is because when wlan start to recovery, the type, size and
count is not same for the 1st and 2nd QMI_WLFW_REQUEST_MEM_IND message,
Then it leads the parameter size is not correct for the dma_free_coherent().
For the chunk[1], the actual dma size is 524288 which allocate in the
2nd time of the initial wlan load phase, and the size which pass to
dma_free_coherent() is 3784704 which is got in the 1st time of recovery
phase, then warning above happened.
Change to use prev_size of struct target_mem_chunk for the paramter of
dma_free_coherent() since prev_size is the real size of last load/recovery.
Also change to check both type and size of struct target_mem_chunk to
reuse the memory to avoid mismatch buffer size for target. Then the
warning disappear and recovery success. When the 1st QMI_WLFW_REQUEST_MEM_IND
for recovery arrived, the trunk[0] is freed in ath11k_qmi_alloc_target_mem_chunk()
and then dma_alloc_coherent() failed caused by large size, and then
trunk[1] is freed in ath11k_qmi_free_target_mem_chunk(), the left 18
trunks will be reuse for the 2nd QMI_WLFW_REQUEST_MEM_IND message.
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3
Fixes: 5962f370ce41 ("ath11k: Reuse the available memory after firmware reload")
Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20220928073832.16251-1-quic_wgong@quicinc.com
2022-09-28 03:38:32 -04:00
|
|
|
ab->qmi.target_mem[i].prev_size,
|
2020-08-14 10:10:21 +03:00
|
|
|
ab->qmi.target_mem[i].vaddr,
|
|
|
|
ab->qmi.target_mem[i].paddr);
|
|
|
|
ab->qmi.target_mem[i].vaddr = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
|
2020-08-14 10:10:21 +03:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct target_mem_chunk *chunk;
|
|
|
|
|
2020-12-17 09:04:57 +02:00
|
|
|
ab->qmi.target_mem_delayed = false;
|
|
|
|
|
2020-08-14 10:10:21 +03:00
|
|
|
for (i = 0; i < ab->qmi.mem_seg_count; i++) {
|
|
|
|
chunk = &ab->qmi.target_mem[i];
|
2022-05-09 14:57:32 +03:00
|
|
|
|
|
|
|
/* Firmware reloads in coldboot/firmware recovery.
|
|
|
|
* in such case, no need to allocate memory for FW again.
|
|
|
|
*/
|
|
|
|
if (chunk->vaddr) {
|
wifi: ath11k: fix warning in dma_free_coherent() of memory chunks while recovery
Commit 26f3a021b37c ("ath11k: allocate smaller chunks of memory for
firmware") and commit f6f92968e1e5 ("ath11k: qmi: try to allocate a
big block of DMA memory first") change ath11k to allocate the memory
chunks for target twice while wlan load. It fails for the 1st time
because of large memory and then changed to allocate many small chunks
for the 2nd time sometimes as below log.
1st time failed:
[10411.640620] ath11k_pci 0000:05:00.0: qmi firmware request memory request
[10411.640625] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 6881280
[10411.640630] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 3784704
[10411.640658] ath11k_pci 0000:05:00.0: qmi dma allocation failed (6881280 B type 1), will try later with small size
[10411.640671] ath11k_pci 0000:05:00.0: qmi delays mem_request 2
[10411.640677] ath11k_pci 0000:05:00.0: qmi respond memory request delayed 1
2nd time success:
[10411.642004] ath11k_pci 0000:05:00.0: qmi firmware request memory request
[10411.642008] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642012] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642014] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642016] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642018] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642020] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642022] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642024] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642027] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642029] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642031] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 458752
[10411.642033] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 131072
[10411.642035] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288
[10411.642037] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288
[10411.642039] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288
[10411.642041] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288
[10411.642043] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288
[10411.642045] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288
[10411.642047] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 491520
[10411.642049] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
And then commit 5962f370ce41 ("ath11k: Reuse the available memory after
firmware reload") skip the ath11k_qmi_free_resource() which frees the
memory chunks while recovery, after that, when run recovery test on
WCN6855, a warning happened every time as below and finally leads fail
for recovery.
[ 159.570318] BUG: Bad page state in process kworker/u16:5 pfn:33300
[ 159.570320] page:0000000096ffdbb9 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x33300
[ 159.570324] flags: 0xfffffc0000000(node=0|zone=1|lastcpupid=0x1fffff)
[ 159.570329] raw: 000fffffc0000000 0000000000000000 dead000000000122 0000000000000000
[ 159.570332] raw: 0000000000000000 0000000000000000 00000001ffffffff 0000000000000000
[ 159.570334] page dumped because: nonzero _refcount
[ 159.570440] firewire_ohci syscopyarea sysfillrect psmouse sdhci_pci ahci sysimgblt firewire_core fb_sys_fops libahci crc_itu_t cqhci drm sdhci e1000e wmi video
[ 159.570460] CPU: 2 PID: 217 Comm: kworker/u16:5 Kdump: loaded Tainted: G B 5.19.0-rc1-wt-ath+ #3
[ 159.570465] Hardware name: LENOVO 418065C/418065C, BIOS 83ET63WW (1.33 ) 07/29/2011
[ 159.570467] Workqueue: qmi_msg_handler qmi_data_ready_work [qmi_helpers]
[ 159.570475] Call Trace:
[ 159.570476] <TASK>
[ 159.570478] dump_stack_lvl+0x49/0x5f
[ 159.570486] dump_stack+0x10/0x12
[ 159.570493] bad_page+0xab/0xf0
[ 159.570502] check_free_page_bad+0x66/0x70
[ 159.570511] __free_pages_ok+0x530/0x9a0
[ 159.570517] ? __dev_printk+0x58/0x6b
[ 159.570525] ? _dev_printk+0x56/0x72
[ 159.570534] ? qmi_decode+0x119/0x470 [qmi_helpers]
[ 159.570543] __free_pages+0x91/0xd0
[ 159.570548] dma_free_contiguous+0x50/0x60
[ 159.570556] dma_direct_free+0xe5/0x140
[ 159.570564] dma_free_attrs+0x35/0x50
[ 159.570570] ath11k_qmi_msg_mem_request_cb+0x2ae/0x3c0 [ath11k]
[ 159.570620] qmi_invoke_handler+0xac/0xe0 [qmi_helpers]
[ 159.570630] qmi_handle_message+0x6d/0x180 [qmi_helpers]
[ 159.570643] qmi_data_ready_work+0x2ca/0x440 [qmi_helpers]
[ 159.570656] process_one_work+0x227/0x440
[ 159.570667] worker_thread+0x31/0x3d0
[ 159.570676] ? process_one_work+0x440/0x440
[ 159.570685] kthread+0xfe/0x130
[ 159.570692] ? kthread_complete_and_exit+0x20/0x20
[ 159.570701] ret_from_fork+0x22/0x30
[ 159.570712] </TASK>
The reason is because when wlan start to recovery, the type, size and
count is not same for the 1st and 2nd QMI_WLFW_REQUEST_MEM_IND message,
Then it leads the parameter size is not correct for the dma_free_coherent().
For the chunk[1], the actual dma size is 524288 which allocate in the
2nd time of the initial wlan load phase, and the size which pass to
dma_free_coherent() is 3784704 which is got in the 1st time of recovery
phase, then warning above happened.
Change to use prev_size of struct target_mem_chunk for the paramter of
dma_free_coherent() since prev_size is the real size of last load/recovery.
Also change to check both type and size of struct target_mem_chunk to
reuse the memory to avoid mismatch buffer size for target. Then the
warning disappear and recovery success. When the 1st QMI_WLFW_REQUEST_MEM_IND
for recovery arrived, the trunk[0] is freed in ath11k_qmi_alloc_target_mem_chunk()
and then dma_alloc_coherent() failed caused by large size, and then
trunk[1] is freed in ath11k_qmi_free_target_mem_chunk(), the left 18
trunks will be reuse for the 2nd QMI_WLFW_REQUEST_MEM_IND message.
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3
Fixes: 5962f370ce41 ("ath11k: Reuse the available memory after firmware reload")
Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20220928073832.16251-1-quic_wgong@quicinc.com
2022-09-28 03:38:32 -04:00
|
|
|
if (chunk->prev_type == chunk->type &&
|
2022-05-09 14:57:32 +03:00
|
|
|
chunk->prev_size == chunk->size)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* cannot reuse the existing chunk */
|
wifi: ath11k: fix warning in dma_free_coherent() of memory chunks while recovery
Commit 26f3a021b37c ("ath11k: allocate smaller chunks of memory for
firmware") and commit f6f92968e1e5 ("ath11k: qmi: try to allocate a
big block of DMA memory first") change ath11k to allocate the memory
chunks for target twice while wlan load. It fails for the 1st time
because of large memory and then changed to allocate many small chunks
for the 2nd time sometimes as below log.
1st time failed:
[10411.640620] ath11k_pci 0000:05:00.0: qmi firmware request memory request
[10411.640625] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 6881280
[10411.640630] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 3784704
[10411.640658] ath11k_pci 0000:05:00.0: qmi dma allocation failed (6881280 B type 1), will try later with small size
[10411.640671] ath11k_pci 0000:05:00.0: qmi delays mem_request 2
[10411.640677] ath11k_pci 0000:05:00.0: qmi respond memory request delayed 1
2nd time success:
[10411.642004] ath11k_pci 0000:05:00.0: qmi firmware request memory request
[10411.642008] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642012] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642014] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642016] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642018] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642020] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642022] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642024] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642027] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642029] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
[10411.642031] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 458752
[10411.642033] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 131072
[10411.642035] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288
[10411.642037] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288
[10411.642039] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288
[10411.642041] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288
[10411.642043] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288
[10411.642045] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288
[10411.642047] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 491520
[10411.642049] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288
And then commit 5962f370ce41 ("ath11k: Reuse the available memory after
firmware reload") skip the ath11k_qmi_free_resource() which frees the
memory chunks while recovery, after that, when run recovery test on
WCN6855, a warning happened every time as below and finally leads fail
for recovery.
[ 159.570318] BUG: Bad page state in process kworker/u16:5 pfn:33300
[ 159.570320] page:0000000096ffdbb9 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x33300
[ 159.570324] flags: 0xfffffc0000000(node=0|zone=1|lastcpupid=0x1fffff)
[ 159.570329] raw: 000fffffc0000000 0000000000000000 dead000000000122 0000000000000000
[ 159.570332] raw: 0000000000000000 0000000000000000 00000001ffffffff 0000000000000000
[ 159.570334] page dumped because: nonzero _refcount
[ 159.570440] firewire_ohci syscopyarea sysfillrect psmouse sdhci_pci ahci sysimgblt firewire_core fb_sys_fops libahci crc_itu_t cqhci drm sdhci e1000e wmi video
[ 159.570460] CPU: 2 PID: 217 Comm: kworker/u16:5 Kdump: loaded Tainted: G B 5.19.0-rc1-wt-ath+ #3
[ 159.570465] Hardware name: LENOVO 418065C/418065C, BIOS 83ET63WW (1.33 ) 07/29/2011
[ 159.570467] Workqueue: qmi_msg_handler qmi_data_ready_work [qmi_helpers]
[ 159.570475] Call Trace:
[ 159.570476] <TASK>
[ 159.570478] dump_stack_lvl+0x49/0x5f
[ 159.570486] dump_stack+0x10/0x12
[ 159.570493] bad_page+0xab/0xf0
[ 159.570502] check_free_page_bad+0x66/0x70
[ 159.570511] __free_pages_ok+0x530/0x9a0
[ 159.570517] ? __dev_printk+0x58/0x6b
[ 159.570525] ? _dev_printk+0x56/0x72
[ 159.570534] ? qmi_decode+0x119/0x470 [qmi_helpers]
[ 159.570543] __free_pages+0x91/0xd0
[ 159.570548] dma_free_contiguous+0x50/0x60
[ 159.570556] dma_direct_free+0xe5/0x140
[ 159.570564] dma_free_attrs+0x35/0x50
[ 159.570570] ath11k_qmi_msg_mem_request_cb+0x2ae/0x3c0 [ath11k]
[ 159.570620] qmi_invoke_handler+0xac/0xe0 [qmi_helpers]
[ 159.570630] qmi_handle_message+0x6d/0x180 [qmi_helpers]
[ 159.570643] qmi_data_ready_work+0x2ca/0x440 [qmi_helpers]
[ 159.570656] process_one_work+0x227/0x440
[ 159.570667] worker_thread+0x31/0x3d0
[ 159.570676] ? process_one_work+0x440/0x440
[ 159.570685] kthread+0xfe/0x130
[ 159.570692] ? kthread_complete_and_exit+0x20/0x20
[ 159.570701] ret_from_fork+0x22/0x30
[ 159.570712] </TASK>
The reason is because when wlan start to recovery, the type, size and
count is not same for the 1st and 2nd QMI_WLFW_REQUEST_MEM_IND message,
Then it leads the parameter size is not correct for the dma_free_coherent().
For the chunk[1], the actual dma size is 524288 which allocate in the
2nd time of the initial wlan load phase, and the size which pass to
dma_free_coherent() is 3784704 which is got in the 1st time of recovery
phase, then warning above happened.
Change to use prev_size of struct target_mem_chunk for the paramter of
dma_free_coherent() since prev_size is the real size of last load/recovery.
Also change to check both type and size of struct target_mem_chunk to
reuse the memory to avoid mismatch buffer size for target. Then the
warning disappear and recovery success. When the 1st QMI_WLFW_REQUEST_MEM_IND
for recovery arrived, the trunk[0] is freed in ath11k_qmi_alloc_target_mem_chunk()
and then dma_alloc_coherent() failed caused by large size, and then
trunk[1] is freed in ath11k_qmi_free_target_mem_chunk(), the left 18
trunks will be reuse for the 2nd QMI_WLFW_REQUEST_MEM_IND message.
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3
Fixes: 5962f370ce41 ("ath11k: Reuse the available memory after firmware reload")
Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20220928073832.16251-1-quic_wgong@quicinc.com
2022-09-28 03:38:32 -04:00
|
|
|
dma_free_coherent(ab->dev, chunk->prev_size,
|
2022-05-09 14:57:32 +03:00
|
|
|
chunk->vaddr, chunk->paddr);
|
|
|
|
chunk->vaddr = NULL;
|
|
|
|
}
|
|
|
|
|
2020-08-14 10:10:21 +03:00
|
|
|
chunk->vaddr = dma_alloc_coherent(ab->dev,
|
|
|
|
chunk->size,
|
|
|
|
&chunk->paddr,
|
2021-09-28 12:05:43 +03:00
|
|
|
GFP_KERNEL | __GFP_NOWARN);
|
2020-08-14 10:10:21 +03:00
|
|
|
if (!chunk->vaddr) {
|
2021-02-16 09:16:03 +02:00
|
|
|
if (ab->qmi.mem_seg_count <= ATH11K_QMI_FW_MEM_REQ_SEGMENT_CNT) {
|
2020-12-17 09:04:57 +02:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI,
|
2023-06-09 17:24:28 +03:00
|
|
|
"dma allocation failed (%d B type %u), will try later with small size\n",
|
2020-12-17 09:04:57 +02:00
|
|
|
chunk->size,
|
|
|
|
chunk->type);
|
|
|
|
ath11k_qmi_free_target_mem_chunk(ab);
|
|
|
|
ab->qmi.target_mem_delayed = true;
|
|
|
|
return 0;
|
|
|
|
}
|
2021-02-22 09:35:56 +02:00
|
|
|
|
|
|
|
ath11k_err(ab, "failed to allocate dma memory for qmi (%d B type %u)\n",
|
2020-08-14 10:10:21 +03:00
|
|
|
chunk->size,
|
|
|
|
chunk->type);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2022-05-09 14:57:32 +03:00
|
|
|
chunk->prev_type = chunk->type;
|
|
|
|
chunk->prev_size = chunk->size;
|
2020-08-14 10:10:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab)
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
2021-12-14 17:39:43 +02:00
|
|
|
struct device *dev = ab->dev;
|
|
|
|
struct device_node *hremote_node = NULL;
|
|
|
|
struct resource res;
|
|
|
|
u32 host_ddr_sz;
|
|
|
|
int i, idx, ret;
|
2019-11-23 09:58:40 +02:00
|
|
|
|
|
|
|
for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) {
|
|
|
|
switch (ab->qmi.target_mem[i].type) {
|
2021-12-14 17:39:43 +02:00
|
|
|
case HOST_DDR_REGION_TYPE:
|
|
|
|
hremote_node = of_parse_phandle(dev->of_node, "memory-region", 0);
|
|
|
|
if (!hremote_node) {
|
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI,
|
2023-06-09 17:24:28 +03:00
|
|
|
"fail to get hremote_node\n");
|
2022-01-12 10:15:11 +02:00
|
|
|
return -ENODEV;
|
2021-12-14 17:39:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = of_address_to_resource(hremote_node, 0, &res);
|
2022-01-10 16:24:13 +02:00
|
|
|
of_node_put(hremote_node);
|
2021-12-14 17:39:43 +02:00
|
|
|
if (ret) {
|
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI,
|
2023-06-09 17:24:28 +03:00
|
|
|
"fail to get reg from hremote\n");
|
2021-12-14 17:39:43 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (res.end - res.start + 1 < ab->qmi.target_mem[i].size) {
|
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI,
|
2023-06-09 17:24:28 +03:00
|
|
|
"fail to assign memory of sz\n");
|
2021-12-14 17:39:43 +02:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ab->qmi.target_mem[idx].paddr = res.start;
|
|
|
|
ab->qmi.target_mem[idx].iaddr =
|
|
|
|
ioremap(ab->qmi.target_mem[idx].paddr,
|
|
|
|
ab->qmi.target_mem[i].size);
|
2023-06-13 12:19:40 +03:00
|
|
|
if (!ab->qmi.target_mem[idx].iaddr)
|
|
|
|
return -EIO;
|
|
|
|
|
2021-12-14 17:39:43 +02:00
|
|
|
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
|
|
|
|
host_ddr_sz = ab->qmi.target_mem[i].size;
|
|
|
|
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
|
|
|
|
idx++;
|
|
|
|
break;
|
2019-11-23 09:58:40 +02:00
|
|
|
case BDF_MEM_REGION_TYPE:
|
2020-06-16 17:00:48 +03:00
|
|
|
ab->qmi.target_mem[idx].paddr = ab->hw_params.bdf_addr;
|
2020-08-14 10:10:21 +03:00
|
|
|
ab->qmi.target_mem[idx].vaddr = NULL;
|
2019-11-23 09:58:40 +02:00
|
|
|
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 (ab->qmi.target_mem[i].size > ATH11K_QMI_CALDB_SIZE) {
|
|
|
|
ath11k_warn(ab, "qmi mem size is low to load caldata\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2020-10-16 20:58:31 +05:30
|
|
|
|
2023-07-26 19:40:30 +05:30
|
|
|
if (ath11k_core_coldboot_cal_support(ab)) {
|
2021-12-14 17:39:43 +02:00
|
|
|
if (hremote_node) {
|
|
|
|
ab->qmi.target_mem[idx].paddr =
|
|
|
|
res.start + host_ddr_sz;
|
|
|
|
ab->qmi.target_mem[idx].iaddr =
|
|
|
|
ioremap(ab->qmi.target_mem[idx].paddr,
|
|
|
|
ab->qmi.target_mem[i].size);
|
2023-06-13 12:19:40 +03:00
|
|
|
if (!ab->qmi.target_mem[idx].iaddr)
|
|
|
|
return -EIO;
|
2021-12-14 17:39:43 +02:00
|
|
|
} else {
|
|
|
|
ab->qmi.target_mem[idx].paddr =
|
|
|
|
ATH11K_QMI_CALDB_ADDRESS;
|
|
|
|
}
|
2020-10-16 20:58:31 +05:30
|
|
|
} else {
|
|
|
|
ab->qmi.target_mem[idx].paddr = 0;
|
|
|
|
ab->qmi.target_mem[idx].vaddr = NULL;
|
|
|
|
}
|
2019-11-23 09:58:40 +02:00
|
|
|
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;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-04-29 22:34:58 +05:30
|
|
|
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 __iomem *bar_addr_va;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* device info message req is only sent for hybrid bus devices */
|
|
|
|
if (!ab->hw_params.hybrid_bus_type)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
ret = qmi_txn_init(&ab->qmi.handle, &txn,
|
|
|
|
qmi_wlfw_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_MAX_LEN,
|
|
|
|
qmi_wlanfw_device_info_req_msg_v01_ei, &req);
|
|
|
|
if (ret < 0) {
|
|
|
|
qmi_txn_cancel(&txn);
|
|
|
|
ath11k_warn(ab, "failed to send qmi target device info request: %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 wait qmi target device info request: %d\n",
|
|
|
|
ret);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
|
|
|
|
ath11k_warn(ab, "qmi device info request failed: %d %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: %d %d\n",
|
|
|
|
resp.resp.result, resp.resp.error);
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!resp.bar_addr ||
|
|
|
|
resp.bar_size != ATH11K_QMI_DEVICE_BAR_SIZE) {
|
|
|
|
ath11k_warn(ab, "qmi device info invalid address and size: %llu %u\n",
|
|
|
|
resp.bar_addr, resp.bar_size);
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
bar_addr_va = devm_ioremap(ab->dev, resp.bar_addr, resp.bar_size);
|
|
|
|
|
|
|
|
if (!bar_addr_va) {
|
|
|
|
ath11k_warn(ab, "qmi device info ioremap failed\n");
|
|
|
|
ab->mem_len = 0;
|
|
|
|
ret = -EIO;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ab->mem = bar_addr_va;
|
|
|
|
ab->mem_len = resp.bar_size;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
out:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
static int ath11k_qmi_request_target_cap(struct ath11k_base *ab)
|
|
|
|
{
|
|
|
|
struct qmi_wlanfw_cap_req_msg_v01 req;
|
|
|
|
struct qmi_wlanfw_cap_resp_msg_v01 resp;
|
2021-11-02 18:22:38 +05:30
|
|
|
struct qmi_txn txn;
|
2019-11-23 09:58:40 +02:00
|
|
|
int ret = 0;
|
2020-10-15 15:15:01 +02:00
|
|
|
int r;
|
2022-03-09 16:54:25 +05:30
|
|
|
char *fw_build_id;
|
|
|
|
int fw_build_id_mask_len;
|
2019-11-23 09:58:40 +02:00
|
|
|
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
memset(&resp, 0, sizeof(resp));
|
|
|
|
|
2021-09-28 12:05:39 +03:00
|
|
|
ret = qmi_txn_init(&ab->qmi.handle, &txn, qmi_wlanfw_cap_resp_msg_v01_ei,
|
|
|
|
&resp);
|
2019-11-23 09:58:40 +02:00
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "target cap request\n");
|
2021-02-22 09:35:49 +02:00
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
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) {
|
2021-11-02 18:22:38 +05:30
|
|
|
qmi_txn_cancel(&txn);
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to send qmi cap request: %d\n",
|
2019-11-23 09:58:40 +02:00
|
|
|
ret);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
|
|
|
|
if (ret < 0) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to wait qmi cap request: %d\n", ret);
|
2019-11-23 09:58:40 +02:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "qmi cap request failed: %d %d\n",
|
2019-11-23 09:58:40 +02:00
|
|
|
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.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;
|
2022-06-02 18:43:50 +05:30
|
|
|
strscpy(ab->qmi.target.fw_build_timestamp,
|
2019-11-23 09:58:40 +02:00
|
|
|
resp.fw_version_info.fw_build_timestamp,
|
|
|
|
sizeof(ab->qmi.target.fw_build_timestamp));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resp.fw_build_id_valid)
|
2022-06-02 18:43:50 +05:30
|
|
|
strscpy(ab->qmi.target.fw_build_id, resp.fw_build_id,
|
2019-11-23 09:58:40 +02:00
|
|
|
sizeof(ab->qmi.target.fw_build_id));
|
|
|
|
|
2021-09-28 12:05:39 +03:00
|
|
|
if (resp.eeprom_read_timeout_valid) {
|
|
|
|
ab->qmi.target.eeprom_caldata =
|
|
|
|
resp.eeprom_read_timeout;
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "cal data supported from eeprom\n");
|
2021-09-28 12:05:39 +03:00
|
|
|
}
|
|
|
|
|
2022-03-09 16:54:25 +05:30
|
|
|
fw_build_id = ab->qmi.target.fw_build_id;
|
|
|
|
fw_build_id_mask_len = strlen(FW_BUILD_ID_MASK);
|
|
|
|
if (!strncmp(fw_build_id, FW_BUILD_ID_MASK, fw_build_id_mask_len))
|
|
|
|
fw_build_id = fw_build_id + fw_build_id_mask_len;
|
|
|
|
|
2020-06-16 17:00:53 +03:00
|
|
|
ath11k_info(ab, "chip_id 0x%x chip_family 0x%x board_id 0x%x soc_id 0x%x\n",
|
2019-11-23 09:58:40 +02:00
|
|
|
ab->qmi.target.chip_id, ab->qmi.target.chip_family,
|
|
|
|
ab->qmi.target.board_id, ab->qmi.target.soc_id);
|
|
|
|
|
2020-06-16 17:00:53 +03:00
|
|
|
ath11k_info(ab, "fw_version 0x%x fw_build_timestamp %s fw_build_id %s",
|
2019-11-23 09:58:40 +02:00
|
|
|
ab->qmi.target.fw_version,
|
|
|
|
ab->qmi.target.fw_build_timestamp,
|
2022-03-09 16:54:25 +05:30
|
|
|
fw_build_id);
|
2019-11-23 09:58:40 +02:00
|
|
|
|
2022-03-23 11:14:17 +02:00
|
|
|
r = ath11k_core_check_smbios(ab);
|
|
|
|
if (r)
|
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "SMBIOS bdf variant name not set.\n");
|
|
|
|
|
2020-10-15 15:15:01 +02:00
|
|
|
r = ath11k_core_check_dt(ab);
|
|
|
|
if (r)
|
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "DT bdf variant name not set.\n");
|
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
out:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-09-28 12:05:39 +03:00
|
|
|
static int ath11k_qmi_load_file_target_mem(struct ath11k_base *ab,
|
|
|
|
const u8 *data, u32 len, u8 type)
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
struct qmi_wlanfw_bdf_download_req_msg_v01 *req;
|
|
|
|
struct qmi_wlanfw_bdf_download_resp_msg_v01 resp;
|
2021-11-02 18:22:38 +05:30
|
|
|
struct qmi_txn txn;
|
2021-09-28 12:05:39 +03:00
|
|
|
const u8 *temp = data;
|
2019-11-23 09:58:40 +02:00
|
|
|
void __iomem *bdf_addr = NULL;
|
2021-09-28 12:05:39 +03:00
|
|
|
int ret;
|
|
|
|
u32 remaining = len;
|
2019-11-23 09:58:40 +02:00
|
|
|
|
|
|
|
req = kzalloc(sizeof(*req), GFP_KERNEL);
|
|
|
|
if (!req)
|
|
|
|
return -ENOMEM;
|
2021-09-28 12:05:39 +03:00
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
memset(&resp, 0, sizeof(resp));
|
|
|
|
|
2022-04-29 22:34:55 +05:30
|
|
|
if (ab->hw_params.fixed_bdf_addr) {
|
2021-09-28 12:05:39 +03:00
|
|
|
bdf_addr = ioremap(ab->hw_params.bdf_addr, ab->hw_params.fw.board_size);
|
|
|
|
if (!bdf_addr) {
|
|
|
|
ath11k_warn(ab, "qmi ioremap error for bdf_addr\n");
|
|
|
|
ret = -EIO;
|
|
|
|
goto err_free_req;
|
|
|
|
}
|
2019-11-23 09:58:40 +02:00
|
|
|
}
|
|
|
|
|
2021-09-28 12:05:39 +03:00
|
|
|
while (remaining) {
|
2019-11-23 09:58:40 +02:00
|
|
|
req->valid = 1;
|
|
|
|
req->file_id_valid = 1;
|
|
|
|
req->file_id = ab->qmi.target.board_id;
|
|
|
|
req->total_size_valid = 1;
|
2021-09-28 12:05:39 +03:00
|
|
|
req->total_size = remaining;
|
2019-11-23 09:58:40 +02:00
|
|
|
req->seg_id_valid = 1;
|
2021-09-28 12:05:39 +03:00
|
|
|
req->data_valid = 1;
|
|
|
|
req->bdf_type = type;
|
|
|
|
req->bdf_type_valid = 1;
|
2019-11-23 09:58:40 +02:00
|
|
|
req->end_valid = 1;
|
2021-09-28 12:05:39 +03:00
|
|
|
req->end = 0;
|
2019-11-23 09:58:40 +02:00
|
|
|
|
2021-09-28 12:05:39 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-04-29 22:34:55 +05:30
|
|
|
if (ab->hw_params.fixed_bdf_addr ||
|
2021-09-28 12:05:39 +03:00
|
|
|
type == ATH11K_QMI_FILE_TYPE_EEPROM) {
|
2021-09-28 12:05:39 +03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2022-04-29 22:34:55 +05:30
|
|
|
if (ab->hw_params.fixed_bdf_addr) {
|
2021-09-28 12:05:39 +03:00
|
|
|
if (type == ATH11K_QMI_FILE_TYPE_CALDATA)
|
|
|
|
bdf_addr += ab->hw_params.fw.cal_offset;
|
|
|
|
|
|
|
|
memcpy_toio(bdf_addr, temp, len);
|
|
|
|
}
|
2019-11-23 09:58:40 +02:00
|
|
|
|
|
|
|
ret = qmi_txn_init(&ab->qmi.handle, &txn,
|
|
|
|
qmi_wlanfw_bdf_download_resp_msg_v01_ei,
|
|
|
|
&resp);
|
|
|
|
if (ret < 0)
|
2021-09-28 12:05:39 +03:00
|
|
|
goto err_iounmap;
|
2019-11-23 09:58:40 +02:00
|
|
|
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "bdf download req fixed addr type %d\n",
|
2021-02-22 09:35:49 +02:00
|
|
|
type);
|
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
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);
|
2021-09-28 12:05:39 +03:00
|
|
|
goto err_iounmap;
|
2019-11-23 09:58:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
|
2021-09-28 12:05:39 +03:00
|
|
|
if (ret < 0) {
|
|
|
|
ath11k_warn(ab, "failed to wait board file download request: %d\n",
|
|
|
|
ret);
|
|
|
|
goto err_iounmap;
|
|
|
|
}
|
2019-11-23 09:58:40 +02:00
|
|
|
|
|
|
|
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "board file download request failed: %d %d\n",
|
2019-11-23 09:58:40 +02:00
|
|
|
resp.resp.result, resp.resp.error);
|
|
|
|
ret = -EINVAL;
|
2021-09-28 12:05:39 +03:00
|
|
|
goto err_iounmap;
|
|
|
|
}
|
|
|
|
|
2022-04-29 22:34:55 +05:30
|
|
|
if (ab->hw_params.fixed_bdf_addr ||
|
2021-09-28 12:05:39 +03:00
|
|
|
type == ATH11K_QMI_FILE_TYPE_EEPROM) {
|
2021-09-28 12:05:39 +03:00
|
|
|
remaining = 0;
|
|
|
|
} else {
|
|
|
|
remaining -= req->data_len;
|
|
|
|
temp += req->data_len;
|
|
|
|
req->seg_id++;
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "bdf download request remaining %i\n",
|
2021-09-28 12:05:39 +03:00
|
|
|
remaining);
|
2019-11-23 09:58:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-28 12:05:39 +03:00
|
|
|
err_iounmap:
|
2022-04-29 22:34:55 +05:30
|
|
|
if (ab->hw_params.fixed_bdf_addr)
|
2021-09-28 12:05:39 +03:00
|
|
|
iounmap(bdf_addr);
|
|
|
|
|
|
|
|
err_free_req:
|
2019-11-23 09:58:40 +02:00
|
|
|
kfree(req);
|
2021-09-28 12:05:39 +03:00
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
ath11k: add regdb.bin download for regdb offload
The regdomain is self-managed type for ath11k, the regdomain info is
reported from firmware, it is not from wireless regdb. Firmware fetch
the regdomain info from board data file before. Currently most of the
regdomain info has moved to another file regdb.bin from board data
file for some chips such as QCA6390 and WCN6855, so the regdomain info
left in board data file is not enough to support the feature which need
more regdomain info.
After download regdb.bin, firmware will fetch the regdomain info from
regdb.bin instead of board data file and report to ath11k. If it does
not have the file regdb.bin, it also can initialize wlan success and
firmware then fetch regdomain info from board data file.
Add download the regdb.bin before download board data for some specific
chip which support supports_regdb in hardware parameters.
download regdb.bin log:
[430082.334162] ath11k_pci 0000:05:00.0: chip_id 0x2 chip_family 0xb board_id 0x106 soc_id 0x400c0200
[430082.334169] ath11k_pci 0000:05:00.0: fw_version 0x110c8b4c fw_build_timestamp 2021-10-25 07:41 fw_build_id QC_IMAGE_VERSION_STRING=WLAN.HSP.1.1-02892-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3
[430082.334414] ath11k_pci 0000:05:00.0: boot firmware request ath11k/WCN6855/hw2.0/regdb.bin size 24310
output of "iw reg get"
global
country US: DFS-FCC
(2402 - 2472 @ 40), (N/A, 30), (N/A)
(5170 - 5250 @ 80), (N/A, 23), (N/A), AUTO-BW
(5250 - 5330 @ 80), (N/A, 23), (0 ms), DFS, AUTO-BW
(5490 - 5730 @ 160), (N/A, 23), (0 ms), DFS
(5735 - 5835 @ 80), (N/A, 30), (N/A)
(57240 - 63720 @ 2160), (N/A, 40), (N/A)
phy#0 (self-managed)
country US: DFS-FCC
(2402 - 2472 @ 40), (6, 30), (N/A)
(5170 - 5250 @ 80), (N/A, 24), (N/A), AUTO-BW
(5250 - 5330 @ 80), (N/A, 24), (0 ms), DFS, AUTO-BW
(5490 - 5730 @ 160), (N/A, 24), (0 ms), DFS, AUTO-BW
(5735 - 5895 @ 160), (N/A, 30), (N/A), AUTO-BW
(5945 - 7125 @ 160), (N/A, 24), (N/A), NO-OUTDOOR, AUTO-BW
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1
Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20211220062355.17021-1-quic_wgong@quicinc.com
2021-12-20 01:23:55 -05:00
|
|
|
static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab,
|
|
|
|
bool regdb)
|
2020-08-14 10:10:21 +03:00
|
|
|
{
|
2021-09-28 12:05:39 +03:00
|
|
|
struct device *dev = ab->dev;
|
2021-09-28 12:05:39 +03:00
|
|
|
char filename[ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE];
|
|
|
|
const struct firmware *fw_entry;
|
2020-08-14 10:10:21 +03:00
|
|
|
struct ath11k_board_data bd;
|
2021-09-28 12:05:39 +03:00
|
|
|
u32 fw_size, file_type;
|
|
|
|
int ret = 0, bdf_type;
|
2021-09-28 12:05:39 +03:00
|
|
|
const u8 *tmp;
|
2020-08-14 10:10:21 +03:00
|
|
|
|
|
|
|
memset(&bd, 0, sizeof(bd));
|
ath11k: add regdb.bin download for regdb offload
The regdomain is self-managed type for ath11k, the regdomain info is
reported from firmware, it is not from wireless regdb. Firmware fetch
the regdomain info from board data file before. Currently most of the
regdomain info has moved to another file regdb.bin from board data
file for some chips such as QCA6390 and WCN6855, so the regdomain info
left in board data file is not enough to support the feature which need
more regdomain info.
After download regdb.bin, firmware will fetch the regdomain info from
regdb.bin instead of board data file and report to ath11k. If it does
not have the file regdb.bin, it also can initialize wlan success and
firmware then fetch regdomain info from board data file.
Add download the regdb.bin before download board data for some specific
chip which support supports_regdb in hardware parameters.
download regdb.bin log:
[430082.334162] ath11k_pci 0000:05:00.0: chip_id 0x2 chip_family 0xb board_id 0x106 soc_id 0x400c0200
[430082.334169] ath11k_pci 0000:05:00.0: fw_version 0x110c8b4c fw_build_timestamp 2021-10-25 07:41 fw_build_id QC_IMAGE_VERSION_STRING=WLAN.HSP.1.1-02892-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3
[430082.334414] ath11k_pci 0000:05:00.0: boot firmware request ath11k/WCN6855/hw2.0/regdb.bin size 24310
output of "iw reg get"
global
country US: DFS-FCC
(2402 - 2472 @ 40), (N/A, 30), (N/A)
(5170 - 5250 @ 80), (N/A, 23), (N/A), AUTO-BW
(5250 - 5330 @ 80), (N/A, 23), (0 ms), DFS, AUTO-BW
(5490 - 5730 @ 160), (N/A, 23), (0 ms), DFS
(5735 - 5835 @ 80), (N/A, 30), (N/A)
(57240 - 63720 @ 2160), (N/A, 40), (N/A)
phy#0 (self-managed)
country US: DFS-FCC
(2402 - 2472 @ 40), (6, 30), (N/A)
(5170 - 5250 @ 80), (N/A, 24), (N/A), AUTO-BW
(5250 - 5330 @ 80), (N/A, 24), (0 ms), DFS, AUTO-BW
(5490 - 5730 @ 160), (N/A, 24), (0 ms), DFS, AUTO-BW
(5735 - 5895 @ 160), (N/A, 30), (N/A), AUTO-BW
(5945 - 7125 @ 160), (N/A, 24), (N/A), NO-OUTDOOR, AUTO-BW
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1
Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20211220062355.17021-1-quic_wgong@quicinc.com
2021-12-20 01:23:55 -05:00
|
|
|
|
|
|
|
if (regdb) {
|
|
|
|
ret = ath11k_core_fetch_regdb(ab, &bd);
|
|
|
|
} else {
|
|
|
|
ret = ath11k_core_fetch_bdf(ab, &bd);
|
|
|
|
if (ret)
|
|
|
|
ath11k_warn(ab, "qmi failed to fetch board file: %d\n", ret);
|
2020-08-14 10:10:21 +03:00
|
|
|
}
|
|
|
|
|
ath11k: add regdb.bin download for regdb offload
The regdomain is self-managed type for ath11k, the regdomain info is
reported from firmware, it is not from wireless regdb. Firmware fetch
the regdomain info from board data file before. Currently most of the
regdomain info has moved to another file regdb.bin from board data
file for some chips such as QCA6390 and WCN6855, so the regdomain info
left in board data file is not enough to support the feature which need
more regdomain info.
After download regdb.bin, firmware will fetch the regdomain info from
regdb.bin instead of board data file and report to ath11k. If it does
not have the file regdb.bin, it also can initialize wlan success and
firmware then fetch regdomain info from board data file.
Add download the regdb.bin before download board data for some specific
chip which support supports_regdb in hardware parameters.
download regdb.bin log:
[430082.334162] ath11k_pci 0000:05:00.0: chip_id 0x2 chip_family 0xb board_id 0x106 soc_id 0x400c0200
[430082.334169] ath11k_pci 0000:05:00.0: fw_version 0x110c8b4c fw_build_timestamp 2021-10-25 07:41 fw_build_id QC_IMAGE_VERSION_STRING=WLAN.HSP.1.1-02892-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3
[430082.334414] ath11k_pci 0000:05:00.0: boot firmware request ath11k/WCN6855/hw2.0/regdb.bin size 24310
output of "iw reg get"
global
country US: DFS-FCC
(2402 - 2472 @ 40), (N/A, 30), (N/A)
(5170 - 5250 @ 80), (N/A, 23), (N/A), AUTO-BW
(5250 - 5330 @ 80), (N/A, 23), (0 ms), DFS, AUTO-BW
(5490 - 5730 @ 160), (N/A, 23), (0 ms), DFS
(5735 - 5835 @ 80), (N/A, 30), (N/A)
(57240 - 63720 @ 2160), (N/A, 40), (N/A)
phy#0 (self-managed)
country US: DFS-FCC
(2402 - 2472 @ 40), (6, 30), (N/A)
(5170 - 5250 @ 80), (N/A, 24), (N/A), AUTO-BW
(5250 - 5330 @ 80), (N/A, 24), (0 ms), DFS, AUTO-BW
(5490 - 5730 @ 160), (N/A, 24), (0 ms), DFS, AUTO-BW
(5735 - 5895 @ 160), (N/A, 30), (N/A), AUTO-BW
(5945 - 7125 @ 160), (N/A, 24), (N/A), NO-OUTDOOR, AUTO-BW
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1
Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20211220062355.17021-1-quic_wgong@quicinc.com
2021-12-20 01:23:55 -05:00
|
|
|
if (ret)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
if (regdb)
|
|
|
|
bdf_type = ATH11K_QMI_BDF_TYPE_REGDB;
|
|
|
|
else if (bd.len >= SELFMAG && memcmp(bd.data, ELFMAG, SELFMAG) == 0)
|
2020-09-29 20:15:29 +03:00
|
|
|
bdf_type = ATH11K_QMI_BDF_TYPE_ELF;
|
|
|
|
else
|
|
|
|
bdf_type = ATH11K_QMI_BDF_TYPE_BIN;
|
|
|
|
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "bdf_type %d\n", bdf_type);
|
2020-09-29 20:15:29 +03:00
|
|
|
|
2021-09-28 12:05:39 +03:00
|
|
|
fw_size = min_t(u32, ab->hw_params.fw.board_size, bd.len);
|
2020-08-14 10:10:21 +03:00
|
|
|
|
2021-09-28 12:05:39 +03:00
|
|
|
ret = ath11k_qmi_load_file_target_mem(ab, bd.data, fw_size, bdf_type);
|
|
|
|
if (ret < 0) {
|
|
|
|
ath11k_warn(ab, "qmi failed to load bdf file\n");
|
|
|
|
goto out;
|
|
|
|
}
|
2021-02-22 09:35:49 +02:00
|
|
|
|
ath11k: add regdb.bin download for regdb offload
The regdomain is self-managed type for ath11k, the regdomain info is
reported from firmware, it is not from wireless regdb. Firmware fetch
the regdomain info from board data file before. Currently most of the
regdomain info has moved to another file regdb.bin from board data
file for some chips such as QCA6390 and WCN6855, so the regdomain info
left in board data file is not enough to support the feature which need
more regdomain info.
After download regdb.bin, firmware will fetch the regdomain info from
regdb.bin instead of board data file and report to ath11k. If it does
not have the file regdb.bin, it also can initialize wlan success and
firmware then fetch regdomain info from board data file.
Add download the regdb.bin before download board data for some specific
chip which support supports_regdb in hardware parameters.
download regdb.bin log:
[430082.334162] ath11k_pci 0000:05:00.0: chip_id 0x2 chip_family 0xb board_id 0x106 soc_id 0x400c0200
[430082.334169] ath11k_pci 0000:05:00.0: fw_version 0x110c8b4c fw_build_timestamp 2021-10-25 07:41 fw_build_id QC_IMAGE_VERSION_STRING=WLAN.HSP.1.1-02892-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3
[430082.334414] ath11k_pci 0000:05:00.0: boot firmware request ath11k/WCN6855/hw2.0/regdb.bin size 24310
output of "iw reg get"
global
country US: DFS-FCC
(2402 - 2472 @ 40), (N/A, 30), (N/A)
(5170 - 5250 @ 80), (N/A, 23), (N/A), AUTO-BW
(5250 - 5330 @ 80), (N/A, 23), (0 ms), DFS, AUTO-BW
(5490 - 5730 @ 160), (N/A, 23), (0 ms), DFS
(5735 - 5835 @ 80), (N/A, 30), (N/A)
(57240 - 63720 @ 2160), (N/A, 40), (N/A)
phy#0 (self-managed)
country US: DFS-FCC
(2402 - 2472 @ 40), (6, 30), (N/A)
(5170 - 5250 @ 80), (N/A, 24), (N/A), AUTO-BW
(5250 - 5330 @ 80), (N/A, 24), (0 ms), DFS, AUTO-BW
(5490 - 5730 @ 160), (N/A, 24), (0 ms), DFS, AUTO-BW
(5735 - 5895 @ 160), (N/A, 30), (N/A), AUTO-BW
(5945 - 7125 @ 160), (N/A, 24), (N/A), NO-OUTDOOR, AUTO-BW
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1
Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20211220062355.17021-1-quic_wgong@quicinc.com
2021-12-20 01:23:55 -05:00
|
|
|
/* QCA6390/WCN6855 does not support cal data, skip it */
|
|
|
|
if (bdf_type == ATH11K_QMI_BDF_TYPE_ELF || bdf_type == ATH11K_QMI_BDF_TYPE_REGDB)
|
2021-09-28 12:05:39 +03:00
|
|
|
goto out;
|
2020-08-14 10:10:21 +03:00
|
|
|
|
2021-09-28 12:05:39 +03:00
|
|
|
if (ab->qmi.target.eeprom_caldata) {
|
|
|
|
file_type = ATH11K_QMI_FILE_TYPE_EEPROM;
|
|
|
|
tmp = filename;
|
|
|
|
fw_size = ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE;
|
|
|
|
} else {
|
|
|
|
file_type = ATH11K_QMI_FILE_TYPE_CALDATA;
|
|
|
|
|
|
|
|
/* cal-<bus>-<id>.bin */
|
|
|
|
snprintf(filename, sizeof(filename), "cal-%s-%s.bin",
|
|
|
|
ath11k_bus_str(ab->hif.bus), dev_name(dev));
|
|
|
|
fw_entry = ath11k_core_firmware_request(ab, filename);
|
|
|
|
if (!IS_ERR(fw_entry))
|
|
|
|
goto success;
|
|
|
|
|
|
|
|
fw_entry = ath11k_core_firmware_request(ab, ATH11K_DEFAULT_CAL_FILE);
|
|
|
|
if (IS_ERR(fw_entry)) {
|
2023-05-26 12:41:07 +03:00
|
|
|
/* Caldata may not be present during first time calibration in
|
|
|
|
* factory hence allow to boot without loading caldata in ftm mode
|
|
|
|
*/
|
|
|
|
if (ath11k_ftm_mode) {
|
|
|
|
ath11k_info(ab,
|
|
|
|
"Booting without cal data file in factory test mode\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2021-09-28 12:05:39 +03:00
|
|
|
ret = PTR_ERR(fw_entry);
|
|
|
|
ath11k_warn(ab,
|
|
|
|
"qmi failed to load CAL data file:%s\n",
|
|
|
|
filename);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
success:
|
|
|
|
fw_size = min_t(u32, ab->hw_params.fw.board_size, fw_entry->size);
|
|
|
|
tmp = fw_entry->data;
|
2021-09-28 12:05:39 +03:00
|
|
|
}
|
2020-08-14 10:10:21 +03:00
|
|
|
|
2021-09-28 12:05:39 +03:00
|
|
|
ret = ath11k_qmi_load_file_target_mem(ab, tmp, fw_size, file_type);
|
2021-09-28 12:05:39 +03:00
|
|
|
if (ret < 0) {
|
|
|
|
ath11k_warn(ab, "qmi failed to load caldata\n");
|
|
|
|
goto out_qmi_cal;
|
2020-08-14 10:10:21 +03:00
|
|
|
}
|
|
|
|
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "caldata type: %u\n", file_type);
|
2020-08-14 10:10:21 +03:00
|
|
|
|
2021-09-28 12:05:39 +03:00
|
|
|
out_qmi_cal:
|
2021-09-28 12:05:39 +03:00
|
|
|
if (!ab->qmi.target.eeprom_caldata)
|
|
|
|
release_firmware(fw_entry);
|
2020-08-14 10:10:21 +03:00
|
|
|
out:
|
2021-09-28 12:05:39 +03:00
|
|
|
ath11k_core_free_bdf(ab, &bd);
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "BDF download sequence completed\n");
|
2021-09-28 12:05:39 +03:00
|
|
|
|
2020-08-14 10:10:21 +03:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-08-14 10:10:20 +03:00
|
|
|
static int ath11k_qmi_m3_load(struct ath11k_base *ab)
|
|
|
|
{
|
|
|
|
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
|
2023-10-18 11:37:06 +03:00
|
|
|
const struct firmware *fw = NULL;
|
|
|
|
const void *m3_data;
|
2020-08-14 10:10:20 +03:00
|
|
|
char path[100];
|
2023-10-18 11:37:06 +03:00
|
|
|
size_t m3_len;
|
2020-08-14 10:10:20 +03:00
|
|
|
int ret;
|
|
|
|
|
2023-10-18 11:37:06 +03:00
|
|
|
if (m3_mem->vaddr)
|
|
|
|
/* m3 firmware buffer is already available in the DMA buffer */
|
|
|
|
return 0;
|
|
|
|
|
2023-10-18 11:37:06 +03:00
|
|
|
if (ab->fw.m3_data && ab->fw.m3_len > 0) {
|
|
|
|
/* firmware-N.bin had a m3 firmware file so use that */
|
|
|
|
m3_data = ab->fw.m3_data;
|
|
|
|
m3_len = ab->fw.m3_len;
|
|
|
|
} else {
|
|
|
|
/* No m3 file in firmware-N.bin so try to request old
|
|
|
|
* separate m3.bin.
|
|
|
|
*/
|
|
|
|
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_data = fw->data;
|
|
|
|
m3_len = fw->size;
|
2020-08-14 10:10:20 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
m3_mem->vaddr = dma_alloc_coherent(ab->dev,
|
2023-10-18 11:37:06 +03:00
|
|
|
m3_len, &m3_mem->paddr,
|
2020-08-14 10:10:20 +03:00
|
|
|
GFP_KERNEL);
|
|
|
|
if (!m3_mem->vaddr) {
|
|
|
|
ath11k_err(ab, "failed to allocate memory for M3 with size %zu\n",
|
|
|
|
fw->size);
|
2023-10-18 11:37:06 +03:00
|
|
|
ret = -ENOMEM;
|
|
|
|
goto out;
|
2020-08-14 10:10:20 +03:00
|
|
|
}
|
|
|
|
|
2023-10-18 11:37:06 +03:00
|
|
|
memcpy(m3_mem->vaddr, m3_data, m3_len);
|
|
|
|
m3_mem->size = m3_len;
|
2023-10-18 11:37:06 +03:00
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
out:
|
2020-08-14 10:10:20 +03:00
|
|
|
release_firmware(fw);
|
|
|
|
|
2023-10-18 11:37:06 +03:00
|
|
|
return ret;
|
2020-08-14 10:10:20 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void ath11k_qmi_m3_free(struct ath11k_base *ab)
|
|
|
|
{
|
|
|
|
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
|
|
|
|
|
2022-04-29 22:34:55 +05:30
|
|
|
if (!ab->hw_params.m3_fw_support || !m3_mem->vaddr)
|
2020-08-14 10:10:20 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
dma_free_coherent(ab->dev, m3_mem->size,
|
|
|
|
m3_mem->vaddr, m3_mem->paddr);
|
|
|
|
m3_mem->vaddr = NULL;
|
2022-02-14 19:53:16 +02:00
|
|
|
m3_mem->size = 0;
|
2020-08-14 10:10:20 +03:00
|
|
|
}
|
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
static int ath11k_qmi_wlanfw_m3_info_send(struct ath11k_base *ab)
|
|
|
|
{
|
2020-08-14 10:10:20 +03:00
|
|
|
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
|
2019-11-23 09:58:40 +02:00
|
|
|
struct qmi_wlanfw_m3_info_req_msg_v01 req;
|
|
|
|
struct qmi_wlanfw_m3_info_resp_msg_v01 resp;
|
2021-11-02 18:22:38 +05:30
|
|
|
struct qmi_txn txn;
|
2019-11-23 09:58:40 +02:00
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
memset(&resp, 0, sizeof(resp));
|
2020-08-14 10:10:20 +03:00
|
|
|
|
2022-04-29 22:34:55 +05:30
|
|
|
if (ab->hw_params.m3_fw_support) {
|
2020-08-14 10:10:20 +03:00
|
|
|
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;
|
|
|
|
}
|
2019-11-23 09:58:40 +02:00
|
|
|
|
|
|
|
ret = qmi_txn_init(&ab->qmi.handle, &txn,
|
|
|
|
qmi_wlanfw_m3_info_resp_msg_v01_ei, &resp);
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "m3 info req\n");
|
2021-02-22 09:35:49 +02:00
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
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) {
|
2021-11-02 18:22:38 +05:30
|
|
|
qmi_txn_cancel(&txn);
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to send m3 information request: %d\n",
|
2019-11-23 09:58:40 +02:00
|
|
|
ret);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
|
|
|
|
if (ret < 0) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to wait m3 information request: %d\n", ret);
|
2019-11-23 09:58:40 +02:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "m3 info request failed: %d %d\n",
|
2019-11-23 09:58:40 +02:00
|
|
|
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;
|
2021-11-02 18:22:38 +05:30
|
|
|
struct qmi_txn txn;
|
2019-11-23 09:58:40 +02:00
|
|
|
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;
|
|
|
|
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "wlan mode req mode %d\n", mode);
|
2021-02-22 09:35:49 +02:00
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
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) {
|
2021-11-02 18:22:38 +05:30
|
|
|
qmi_txn_cancel(&txn);
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to send wlan mode request (mode %d): %d\n",
|
2019-11-23 09:58:40 +02:00
|
|
|
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;
|
|
|
|
}
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to wait wlan mode request (mode %d): %d\n",
|
2019-11-23 09:58:40 +02:00
|
|
|
mode, ret);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "wlan mode request failed (mode: %d): %d %d\n",
|
2019-11-23 09:58:40 +02:00
|
|
|
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;
|
2021-11-02 18:22:38 +05:30
|
|
|
struct qmi_txn txn;
|
2019-11-27 14:08:50 +00:00
|
|
|
int ret = 0, pipe_num;
|
2019-11-23 09:58:40 +02:00
|
|
|
|
|
|
|
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;
|
2022-06-02 18:43:50 +05:30
|
|
|
strscpy(req->host_version, ATH11K_HOST_VERSION_STRING,
|
2019-11-23 09:58:40 +02:00
|
|
|
sizeof(req->host_version));
|
|
|
|
|
|
|
|
req->tgt_cfg_valid = 1;
|
|
|
|
/* This is number of CE configs */
|
2019-11-27 14:08:50 +00:00
|
|
|
req->tgt_cfg_len = ab->qmi.ce_cfg.tgt_ce_len;
|
2020-08-14 10:10:28 +03:00
|
|
|
for (pipe_num = 0; pipe_num < req->tgt_cfg_len ; pipe_num++) {
|
2019-11-27 14:08:50 +00:00
|
|
|
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;
|
2019-11-23 09:58:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
req->svc_cfg_valid = 1;
|
|
|
|
/* This is number of Service/CE configs */
|
2019-11-27 14:08:50 +00:00
|
|
|
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;
|
2019-11-23 09:58:40 +02:00
|
|
|
}
|
|
|
|
req->shadow_reg_valid = 0;
|
2020-10-01 12:34:44 +03:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
2019-11-23 09:58:40 +02:00
|
|
|
|
|
|
|
ret = qmi_txn_init(&ab->qmi.handle, &txn,
|
|
|
|
qmi_wlanfw_wlan_cfg_resp_msg_v01_ei, &resp);
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "wlan cfg req\n");
|
2021-02-22 09:35:49 +02:00
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
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) {
|
2021-11-02 18:22:38 +05:30
|
|
|
qmi_txn_cancel(&txn);
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to send wlan config request: %d\n",
|
2019-11-23 09:58:40 +02:00
|
|
|
ret);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
|
|
|
|
if (ret < 0) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to wait wlan config request: %d\n", ret);
|
2019-11-23 09:58:40 +02:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "wlan config request failed: %d %d\n",
|
2019-11-23 09:58:40 +02:00
|
|
|
resp.resp.result, resp.resp.error);
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
kfree(req);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-12-20 20:10:53 +08:00
|
|
|
static int ath11k_qmi_wlanfw_wlan_ini_send(struct ath11k_base *ab, bool enable)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct qmi_txn txn;
|
|
|
|
struct qmi_wlanfw_wlan_ini_req_msg_v01 req = {};
|
|
|
|
struct qmi_wlanfw_wlan_ini_resp_msg_v01 resp = {};
|
|
|
|
|
|
|
|
req.enablefwlog_valid = true;
|
|
|
|
req.enablefwlog = enable ? 1 : 0;
|
|
|
|
|
|
|
|
ret = qmi_txn_init(&ab->qmi.handle, &txn,
|
|
|
|
qmi_wlanfw_wlan_ini_resp_msg_v01_ei, &resp);
|
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
|
|
|
|
QMI_WLANFW_WLAN_INI_REQ_V01,
|
|
|
|
QMI_WLANFW_WLAN_INI_REQ_MSG_V01_MAX_LEN,
|
|
|
|
qmi_wlanfw_wlan_ini_req_msg_v01_ei, &req);
|
|
|
|
if (ret < 0) {
|
|
|
|
ath11k_warn(ab, "qmi failed to send wlan ini 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 wlan ini request, err = %d\n", ret);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
|
|
|
|
ath11k_warn(ab, "qmi wlan ini request failed, result: %d, err: %d\n",
|
|
|
|
resp.resp.result, resp.resp.error);
|
|
|
|
ret = -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
void ath11k_qmi_firmware_stop(struct ath11k_base *ab)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware stop\n");
|
2021-02-22 09:35:49 +02:00
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
ret = ath11k_qmi_wlanfw_mode_send(ab, ATH11K_FIRMWARE_MODE_OFF);
|
|
|
|
if (ret < 0) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "qmi failed to send wlan mode off: %d\n", ret);
|
2019-11-23 09:58:40 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int ath11k_qmi_firmware_start(struct ath11k_base *ab,
|
|
|
|
u32 mode)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware start\n");
|
2021-02-22 09:35:49 +02:00
|
|
|
|
2021-12-20 20:10:53 +08:00
|
|
|
if (ab->hw_params.fw_wmi_diag_event) {
|
|
|
|
ret = ath11k_qmi_wlanfw_wlan_ini_send(ab, true);
|
|
|
|
if (ret < 0) {
|
|
|
|
ath11k_warn(ab, "qmi failed to send wlan fw ini:%d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
ret = ath11k_qmi_wlanfw_wlan_cfg_send(ab);
|
|
|
|
if (ret < 0) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "qmi failed to send wlan cfg: %d\n", ret);
|
2019-11-23 09:58:40 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ath11k_qmi_wlanfw_mode_send(ab, mode);
|
|
|
|
if (ret < 0) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "qmi failed to send wlan fw mode: %d\n", ret);
|
2019-11-23 09:58:40 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-07-26 19:40:31 +05:30
|
|
|
int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab)
|
|
|
|
{
|
|
|
|
int timeout;
|
|
|
|
|
2023-07-26 19:40:32 +05:30
|
|
|
if (!ath11k_core_coldboot_cal_support(ab) ||
|
2023-07-26 19:40:31 +05:30
|
|
|
ab->hw_params.cbcal_restart_fw == 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 */
|
wifi: ath11k: support hibernation
Now that all infrastructure is in place and ath11k is fixed to handle all the
corner cases, power down the ath11k firmware during suspend and power it back
up during resume. This fixes the problem when using hibernation with ath11k PCI
devices.
For suspend, two conditions needs to be satisfied:
1. since MHI channel unprepare would be done in late suspend stage,
ath11k needs to get all QMI-dependent things done before that stage.
2. and because unprepare MHI channels requires a working MHI stack,
ath11k is not allowed to call mhi_power_down() until that finishes.
So the original suspend callback is separated into two parts: the first part
handles all QMI-dependent things in suspend callback; while the second part
powers down MHI in suspend_late callback. This is valid because kernel calls
ath11k's suspend callback before all suspend_late callbacks, making the first
condition happy. And because MHI devices are children of ath11k device
(ab->dev), kernel guarantees that ath11k's suspend_late callback is called
after QRTR's suspend_late callback, this satisfies the second condition.
Above analysis also applies to resume process. so the original resume
callback is separated into two parts: the first part powers up MHI stack
in resume_early callback, this guarantees MHI stack is working when
QRTR tries to prepare MHI channels (kernel calls QRTR's resume_early callback
after ath11k's resume_early callback, due to the child-father relationship);
the second part waits for the completion of restart, which won't fail now
since MHI channels are ready for use by QMI.
Another notable change is in power down path, we tell mhi_power_down() to not
to destroy MHI devices, making it possible for QRTR to help unprepare/prepare
MHI channels, and finally get us rid of the probe-defer issue when resume.
Also change related code due to interface changes.
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.30
Tested-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com>
Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://msgid.link/20240305021320.3367-4-quic_bqiang@quicinc.com
2024-04-08 17:41:50 +03:00
|
|
|
ath11k_hif_power_down(ab, false);
|
2023-07-26 19:40:31 +05:30
|
|
|
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);
|
|
|
|
|
2020-10-16 20:58:31 +05:30
|
|
|
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) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "qmi failed to send wlan fw mode: %d\n", ret);
|
2020-10-16 20:58:31 +05:30
|
|
|
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) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "coldboot calibration timed out\n");
|
2020-10-16 20:58:31 +05:30
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "Coldboot calibration done\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-12-08 09:52:55 +02:00
|
|
|
static int ath11k_qmi_event_mem_request(struct ath11k_qmi *qmi)
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
struct ath11k_base *ab = qmi->ab;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = ath11k_qmi_respond_fw_mem_request(ab);
|
|
|
|
if (ret < 0) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "qmi failed to respond fw mem req: %d\n", ret);
|
2020-12-08 09:52:55 +02:00
|
|
|
return ret;
|
2019-11-23 09:58:40 +02:00
|
|
|
}
|
2020-12-08 09:52:55 +02:00
|
|
|
|
|
|
|
return ret;
|
2019-11-23 09:58:40 +02:00
|
|
|
}
|
|
|
|
|
2020-12-08 09:52:55 +02:00
|
|
|
static int ath11k_qmi_event_load_bdf(struct ath11k_qmi *qmi)
|
2019-11-23 09:58:40 +02:00
|
|
|
{
|
|
|
|
struct ath11k_base *ab = qmi->ab;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = ath11k_qmi_request_target_cap(ab);
|
|
|
|
if (ret < 0) {
|
2021-03-16 09:19:24 +00:00
|
|
|
ath11k_warn(ab, "failed to request qmi target capabilities: %d\n",
|
2021-02-22 09:35:56 +02:00
|
|
|
ret);
|
2020-12-08 09:52:55 +02:00
|
|
|
return ret;
|
2019-11-23 09:58:40 +02:00
|
|
|
}
|
|
|
|
|
2022-04-29 22:34:58 +05:30
|
|
|
ret = ath11k_qmi_request_device_info(ab);
|
|
|
|
if (ret < 0) {
|
|
|
|
ath11k_warn(ab, "failed to request qmi device info: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
ath11k: add regdb.bin download for regdb offload
The regdomain is self-managed type for ath11k, the regdomain info is
reported from firmware, it is not from wireless regdb. Firmware fetch
the regdomain info from board data file before. Currently most of the
regdomain info has moved to another file regdb.bin from board data
file for some chips such as QCA6390 and WCN6855, so the regdomain info
left in board data file is not enough to support the feature which need
more regdomain info.
After download regdb.bin, firmware will fetch the regdomain info from
regdb.bin instead of board data file and report to ath11k. If it does
not have the file regdb.bin, it also can initialize wlan success and
firmware then fetch regdomain info from board data file.
Add download the regdb.bin before download board data for some specific
chip which support supports_regdb in hardware parameters.
download regdb.bin log:
[430082.334162] ath11k_pci 0000:05:00.0: chip_id 0x2 chip_family 0xb board_id 0x106 soc_id 0x400c0200
[430082.334169] ath11k_pci 0000:05:00.0: fw_version 0x110c8b4c fw_build_timestamp 2021-10-25 07:41 fw_build_id QC_IMAGE_VERSION_STRING=WLAN.HSP.1.1-02892-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3
[430082.334414] ath11k_pci 0000:05:00.0: boot firmware request ath11k/WCN6855/hw2.0/regdb.bin size 24310
output of "iw reg get"
global
country US: DFS-FCC
(2402 - 2472 @ 40), (N/A, 30), (N/A)
(5170 - 5250 @ 80), (N/A, 23), (N/A), AUTO-BW
(5250 - 5330 @ 80), (N/A, 23), (0 ms), DFS, AUTO-BW
(5490 - 5730 @ 160), (N/A, 23), (0 ms), DFS
(5735 - 5835 @ 80), (N/A, 30), (N/A)
(57240 - 63720 @ 2160), (N/A, 40), (N/A)
phy#0 (self-managed)
country US: DFS-FCC
(2402 - 2472 @ 40), (6, 30), (N/A)
(5170 - 5250 @ 80), (N/A, 24), (N/A), AUTO-BW
(5250 - 5330 @ 80), (N/A, 24), (0 ms), DFS, AUTO-BW
(5490 - 5730 @ 160), (N/A, 24), (0 ms), DFS, AUTO-BW
(5735 - 5895 @ 160), (N/A, 30), (N/A), AUTO-BW
(5945 - 7125 @ 160), (N/A, 24), (N/A), NO-OUTDOOR, AUTO-BW
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1
Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20211220062355.17021-1-quic_wgong@quicinc.com
2021-12-20 01:23:55 -05:00
|
|
|
if (ab->hw_params.supports_regdb)
|
|
|
|
ath11k_qmi_load_bdf_qmi(ab, true);
|
|
|
|
|
|
|
|
ret = ath11k_qmi_load_bdf_qmi(ab, false);
|
2019-11-23 09:58:40 +02:00
|
|
|
if (ret < 0) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to load board data file: %d\n", ret);
|
2020-12-08 09:52:55 +02:00
|
|
|
return ret;
|
2019-11-23 09:58:40 +02:00
|
|
|
}
|
|
|
|
|
2022-04-29 22:34:59 +05:30
|
|
|
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, "failed to send qmi firmware indication: %d\n",
|
|
|
|
ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ath11k_qmi_host_cap_send(ab);
|
2019-11-23 09:58:40 +02:00
|
|
|
if (ret < 0) {
|
2022-04-29 22:34:59 +05:30
|
|
|
ath11k_warn(ab, "failed to send qmi host cap: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ab->hw_params.fixed_fw_mem)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
ret = ath11k_qmi_event_load_bdf(qmi);
|
|
|
|
if (ret < 0) {
|
|
|
|
ath11k_warn(ab, "qmi failed to download BDF:%d\n", ret);
|
2020-12-08 09:52:55 +02:00
|
|
|
return ret;
|
2019-11-23 09:58:40 +02:00
|
|
|
}
|
2020-12-08 09:52:55 +02:00
|
|
|
|
|
|
|
return ret;
|
2019-11-23 09:58:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware request memory request\n");
|
2019-11-23 09:58:40 +02:00
|
|
|
|
|
|
|
if (msg->mem_seg_len == 0 ||
|
|
|
|
msg->mem_seg_len > ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01)
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "invalid memory segment length: %u\n",
|
2019-11-23 09:58:40 +02:00
|
|
|
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;
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "mem seg type %d size %d\n",
|
2019-11-23 09:58:40 +02:00
|
|
|
msg->mem_seg[i].type, msg->mem_seg[i].size);
|
|
|
|
}
|
|
|
|
|
2022-04-29 22:34:55 +05:30
|
|
|
if (ab->hw_params.fixed_mem_region ||
|
2021-12-14 17:39:43 +02:00
|
|
|
test_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags)) {
|
2020-08-14 10:10:21 +03:00
|
|
|
ret = ath11k_qmi_assign_target_mem_chunk(ab);
|
2020-08-14 10:10:26 +03:00
|
|
|
if (ret) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to assign qmi target memory: %d\n",
|
2020-08-14 10:10:26 +03:00
|
|
|
ret);
|
|
|
|
return;
|
|
|
|
}
|
2020-12-17 09:04:57 +02:00
|
|
|
} else {
|
2020-08-14 10:10:21 +03:00
|
|
|
ret = ath11k_qmi_alloc_target_mem_chunk(ab);
|
2020-08-14 10:10:26 +03:00
|
|
|
if (ret) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to allocate qmi target memory: %d\n",
|
2020-08-14 10:10:26 +03:00
|
|
|
ret);
|
|
|
|
return;
|
|
|
|
}
|
2019-11-23 09:58:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware memory ready indication\n");
|
2019-11-23 09:58:40 +02:00
|
|
|
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;
|
|
|
|
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware ready\n");
|
2022-08-31 09:04:19 +03:00
|
|
|
|
2022-08-31 09:04:20 +03:00
|
|
|
if (!ab->qmi.cal_done) {
|
|
|
|
ab->qmi.cal_done = 1;
|
|
|
|
wake_up(&ab->qmi.cold_boot_waitq);
|
|
|
|
}
|
2022-08-31 09:04:19 +03:00
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_FW_READY, NULL);
|
|
|
|
}
|
|
|
|
|
2020-10-16 20:58:31 +05:30
|
|
|
static void ath11k_qmi_msg_cold_boot_cal_done_cb(struct qmi_handle *qmi_hdl,
|
2019-11-23 09:58:40 +02:00
|
|
|
struct sockaddr_qrtr *sq,
|
|
|
|
struct qmi_txn *txn,
|
|
|
|
const void *decoded)
|
|
|
|
{
|
2020-10-16 20:58:31 +05:30
|
|
|
struct ath11k_qmi *qmi = container_of(qmi_hdl,
|
|
|
|
struct ath11k_qmi, handle);
|
|
|
|
struct ath11k_base *ab = qmi->ab;
|
|
|
|
|
2022-08-31 09:04:20 +03:00
|
|
|
ab->qmi.cal_done = 1;
|
|
|
|
wake_up(&ab->qmi.cold_boot_waitq);
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "cold boot calibration done\n");
|
2019-11-23 09:58:40 +02:00
|
|
|
}
|
|
|
|
|
2022-08-31 09:04:19 +03:00
|
|
|
static void ath11k_qmi_msg_fw_init_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;
|
|
|
|
|
|
|
|
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_FW_INIT_DONE, NULL);
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "firmware init done\n");
|
2022-08-31 09:04:19 +03:00
|
|
|
}
|
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
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,
|
2020-08-14 10:10:27 +03:00
|
|
|
.decoded_size = sizeof(struct qmi_wlanfw_request_mem_ind_msg_v01),
|
2019-11-23 09:58:40 +02:00
|
|
|
.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,
|
2020-08-14 10:10:27 +03:00
|
|
|
.decoded_size = sizeof(struct qmi_wlanfw_fw_mem_ready_ind_msg_v01),
|
2019-11-23 09:58:40 +02:00
|
|
|
.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,
|
2020-08-14 10:10:27 +03:00
|
|
|
.decoded_size = sizeof(struct qmi_wlanfw_fw_ready_ind_msg_v01),
|
2019-11-23 09:58:40 +02:00
|
|
|
.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 =
|
2020-08-14 10:10:27 +03:00
|
|
|
sizeof(struct qmi_wlanfw_fw_cold_cal_done_ind_msg_v01),
|
2019-11-23 09:58:40 +02:00
|
|
|
.fn = ath11k_qmi_msg_cold_boot_cal_done_cb,
|
|
|
|
},
|
2022-08-31 09:04:19 +03:00
|
|
|
{
|
|
|
|
.type = QMI_INDICATION,
|
|
|
|
.msg_id = QMI_WLFW_FW_INIT_DONE_IND_V01,
|
|
|
|
.ei = qmi_wlfw_fw_init_done_ind_msg_v01_ei,
|
|
|
|
.decoded_size =
|
|
|
|
sizeof(struct qmi_wlfw_fw_init_done_ind_msg_v01),
|
|
|
|
.fn = ath11k_qmi_msg_fw_init_done_cb,
|
|
|
|
},
|
2022-10-21 14:31:26 +05:30
|
|
|
|
|
|
|
/* end of list */
|
|
|
|
{},
|
2019-11-23 09:58:40 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
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) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to connect to qmi remote service: %d\n", ret);
|
2019-11-23 09:58:40 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "wifi fw qmi service connected\n");
|
2019-11-23 09:58:40 +02:00
|
|
|
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_SERVER_ARRIVE, NULL);
|
|
|
|
|
2020-12-08 09:52:55 +02:00
|
|
|
return ret;
|
2019-11-23 09:58:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2023-06-09 17:24:28 +03:00
|
|
|
ath11k_dbg(ab, ATH11K_DBG_QMI, "wifi fw del server\n");
|
2019-11-23 09:58:40 +02:00
|
|
|
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 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;
|
2020-12-08 09:52:55 +02:00
|
|
|
int ret;
|
2019-11-23 09:58:40 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2021-09-28 14:00:44 +03:00
|
|
|
if (test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags)) {
|
|
|
|
kfree(event);
|
2019-11-23 09:58:40 +02:00
|
|
|
return;
|
2021-09-28 14:00:44 +03:00
|
|
|
}
|
2019-11-23 09:58:40 +02:00
|
|
|
|
|
|
|
switch (event->type) {
|
|
|
|
case ATH11K_QMI_EVENT_SERVER_ARRIVE:
|
2020-12-08 09:52:55 +02:00
|
|
|
ret = ath11k_qmi_event_server_arrive(qmi);
|
|
|
|
if (ret < 0)
|
|
|
|
set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags);
|
2019-11-23 09:58:40 +02:00
|
|
|
break;
|
|
|
|
case ATH11K_QMI_EVENT_SERVER_EXIT:
|
|
|
|
set_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags);
|
|
|
|
set_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
|
2022-09-27 09:18:54 +03:00
|
|
|
|
|
|
|
if (!ab->is_reset)
|
|
|
|
ath11k_core_pre_reconfigure_recovery(ab);
|
2019-11-23 09:58:40 +02:00
|
|
|
break;
|
|
|
|
case ATH11K_QMI_EVENT_REQUEST_MEM:
|
2020-12-08 09:52:55 +02:00
|
|
|
ret = ath11k_qmi_event_mem_request(qmi);
|
|
|
|
if (ret < 0)
|
|
|
|
set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags);
|
2019-11-23 09:58:40 +02:00
|
|
|
break;
|
|
|
|
case ATH11K_QMI_EVENT_FW_MEM_READY:
|
2020-12-08 09:52:55 +02:00
|
|
|
ret = ath11k_qmi_event_load_bdf(qmi);
|
2022-04-29 22:34:59 +05:30
|
|
|
if (ret < 0) {
|
2020-12-08 09:52:55 +02:00
|
|
|
set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags);
|
2022-04-29 22:34:59 +05:30
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ath11k_qmi_wlanfw_m3_info_send(ab);
|
|
|
|
if (ret < 0) {
|
|
|
|
ath11k_warn(ab,
|
|
|
|
"failed to send qmi m3 info req: %d\n", ret);
|
|
|
|
set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags);
|
|
|
|
}
|
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
break;
|
2022-08-31 09:04:19 +03:00
|
|
|
case ATH11K_QMI_EVENT_FW_INIT_DONE:
|
2020-12-08 09:52:55 +02:00
|
|
|
clear_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags);
|
2019-11-23 09:58:40 +02:00
|
|
|
if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) {
|
2024-02-23 17:20:33 +02:00
|
|
|
if (ab->is_reset)
|
|
|
|
ath11k_hal_dump_srng_stats(ab);
|
2019-11-23 09:58:40 +02:00
|
|
|
queue_work(ab->workqueue, &ab->restart_work);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-07-26 19:40:30 +05:30
|
|
|
if (ab->qmi.cal_done == 0 &&
|
|
|
|
ath11k_core_coldboot_cal_support(ab)) {
|
2020-10-16 20:58:31 +05:30
|
|
|
ath11k_qmi_process_coldboot_calibration(ab);
|
|
|
|
} else {
|
|
|
|
clear_bit(ATH11K_FLAG_CRASH_FLUSH,
|
|
|
|
&ab->dev_flags);
|
|
|
|
clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
|
2022-02-17 11:56:35 +05:30
|
|
|
ret = ath11k_core_qmi_firmware_ready(ab);
|
|
|
|
if (ret) {
|
|
|
|
set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags);
|
|
|
|
break;
|
|
|
|
}
|
2020-10-16 20:58:31 +05:30
|
|
|
set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags);
|
|
|
|
}
|
2019-11-23 09:58:40 +02:00
|
|
|
|
2022-08-31 09:04:19 +03:00
|
|
|
break;
|
|
|
|
case ATH11K_QMI_EVENT_FW_READY:
|
2022-08-31 09:04:20 +03:00
|
|
|
/* For targets requiring a FW restart upon cold
|
|
|
|
* boot completion, there is no need to process
|
|
|
|
* FW ready; such targets will receive FW init
|
|
|
|
* done message after FW restart.
|
|
|
|
*/
|
|
|
|
if (ab->hw_params.cbcal_restart_fw)
|
|
|
|
break;
|
|
|
|
|
|
|
|
clear_bit(ATH11K_FLAG_CRASH_FLUSH,
|
|
|
|
&ab->dev_flags);
|
|
|
|
clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
|
|
|
|
ath11k_core_qmi_firmware_ready(ab);
|
|
|
|
set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags);
|
|
|
|
|
2019-11-23 09:58:40 +02:00
|
|
|
break;
|
|
|
|
case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE:
|
|
|
|
break;
|
|
|
|
default:
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "invalid qmi event type: %d", event->type);
|
2019-11-23 09:58:40 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
kfree(event);
|
|
|
|
spin_lock(&qmi->event_lock);
|
|
|
|
}
|
|
|
|
spin_unlock(&qmi->event_lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2021-12-13 11:53:08 +02:00
|
|
|
ab->qmi.target_mem_mode = ab->hw_params.fw_mem_mode;
|
2019-11-23 09:58:40 +02:00
|
|
|
ret = qmi_handle_init(&ab->qmi.handle, ATH11K_QMI_RESP_LEN_MAX,
|
|
|
|
&ath11k_qmi_ops, ath11k_qmi_msg_handlers);
|
|
|
|
if (ret < 0) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to initialize qmi handle: %d\n", ret);
|
2019-11-23 09:58:40 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
wifi: ath10/11/12k: Use alloc_ordered_workqueue() to create ordered workqueues
BACKGROUND
==========
When multiple work items are queued to a workqueue, their execution order
doesn't match the queueing order. They may get executed in any order and
simultaneously. When fully serialized execution - one by one in the queueing
order - is needed, an ordered workqueue should be used which can be created
with alloc_ordered_workqueue().
However, alloc_ordered_workqueue() was a later addition. Before it, an
ordered workqueue could be obtained by creating an UNBOUND workqueue with
@max_active==1. This originally was an implementation side-effect which was
broken by 4c16bd327c74 ("workqueue: restore WQ_UNBOUND/max_active==1 to be
ordered"). Because there were users that depended on the ordered execution,
5c0338c68706 ("workqueue: restore WQ_UNBOUND/max_active==1 to be ordered")
made workqueue allocation path to implicitly promote UNBOUND workqueues w/
@max_active==1 to ordered workqueues.
While this has worked okay, overloading the UNBOUND allocation interface
this way creates other issues. It's difficult to tell whether a given
workqueue actually needs to be ordered and users that legitimately want a
min concurrency level wq unexpectedly gets an ordered one instead. With
planned UNBOUND workqueue updates to improve execution locality and more
prevalence of chiplet designs which can benefit from such improvements, this
isn't a state we wanna be in forever.
This patch series audits all callsites that create an UNBOUND workqueue w/
@max_active==1 and converts them to alloc_ordered_workqueue() as necessary.
WHAT TO LOOK FOR
================
The conversions are from
alloc_workqueue(WQ_UNBOUND | flags, 1, args..)
to
alloc_ordered_workqueue(flags, args...)
which don't cause any functional changes. If you know that fully ordered
execution is not ncessary, please let me know. I'll drop the conversion and
instead add a comment noting the fact to reduce confusion while conversion
is in progress.
If you aren't fully sure, it's completely fine to let the conversion
through. The behavior will stay exactly the same and we can always
reconsider later.
As there are follow-up workqueue core changes, I'd really appreciate if the
patch can be routed through the workqueue tree w/ your acks. Thanks.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Kalle Valo <kvalo@kernel.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
2023-05-18 14:40:29 -10:00
|
|
|
ab->qmi.event_wq = alloc_ordered_workqueue("ath11k_qmi_driver_event", 0);
|
2019-11-23 09:58:40 +02:00
|
|
|
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,
|
2020-08-14 10:10:22 +03:00
|
|
|
ab->qmi.service_ins_id);
|
2019-11-23 09:58:40 +02:00
|
|
|
if (ret < 0) {
|
2021-02-22 09:35:56 +02:00
|
|
|
ath11k_warn(ab, "failed to add qmi lookup: %d\n", ret);
|
2020-07-20 17:36:44 +08:00
|
|
|
destroy_workqueue(ab->qmi.event_wq);
|
2019-11-23 09:58:40 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2020-08-14 10:10:20 +03:00
|
|
|
ath11k_qmi_m3_free(ab);
|
2020-08-14 10:10:21 +03:00
|
|
|
ath11k_qmi_free_target_mem_chunk(ab);
|
2019-11-23 09:58:40 +02:00
|
|
|
}
|
2020-12-08 09:52:55 +02:00
|
|
|
EXPORT_SYMBOL(ath11k_qmi_deinit_service);
|
2019-11-23 09:58:40 +02:00
|
|
|
|
2022-02-14 19:53:16 +02:00
|
|
|
void ath11k_qmi_free_resource(struct ath11k_base *ab)
|
|
|
|
{
|
|
|
|
ath11k_qmi_free_target_mem_chunk(ab);
|
|
|
|
ath11k_qmi_m3_free(ab);
|
|
|
|
}
|