cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

qmi.c (27883B)


      1// SPDX-License-Identifier: ISC
      2/*
      3 * Copyright (c) 2018 The Linux Foundation. All rights reserved.
      4 */
      5
      6#include <linux/completion.h>
      7#include <linux/device.h>
      8#include <linux/debugfs.h>
      9#include <linux/idr.h>
     10#include <linux/kernel.h>
     11#include <linux/of.h>
     12#include <linux/of_address.h>
     13#include <linux/module.h>
     14#include <linux/net.h>
     15#include <linux/platform_device.h>
     16#include <linux/qcom_scm.h>
     17#include <linux/string.h>
     18#include <net/sock.h>
     19
     20#include "debug.h"
     21#include "snoc.h"
     22
     23#define ATH10K_QMI_CLIENT_ID		0x4b4e454c
     24#define ATH10K_QMI_TIMEOUT		30
     25
     26static int ath10k_qmi_map_msa_permission(struct ath10k_qmi *qmi,
     27					 struct ath10k_msa_mem_info *mem_info)
     28{
     29	struct qcom_scm_vmperm dst_perms[3];
     30	struct ath10k *ar = qmi->ar;
     31	unsigned int src_perms;
     32	u32 perm_count;
     33	int ret;
     34
     35	src_perms = BIT(QCOM_SCM_VMID_HLOS);
     36
     37	dst_perms[0].vmid = QCOM_SCM_VMID_MSS_MSA;
     38	dst_perms[0].perm = QCOM_SCM_PERM_RW;
     39	dst_perms[1].vmid = QCOM_SCM_VMID_WLAN;
     40	dst_perms[1].perm = QCOM_SCM_PERM_RW;
     41
     42	if (mem_info->secure) {
     43		perm_count = 2;
     44	} else {
     45		dst_perms[2].vmid = QCOM_SCM_VMID_WLAN_CE;
     46		dst_perms[2].perm = QCOM_SCM_PERM_RW;
     47		perm_count = 3;
     48	}
     49
     50	ret = qcom_scm_assign_mem(mem_info->addr, mem_info->size,
     51				  &src_perms, dst_perms, perm_count);
     52	if (ret < 0)
     53		ath10k_err(ar, "failed to assign msa map permissions: %d\n", ret);
     54
     55	return ret;
     56}
     57
     58static int ath10k_qmi_unmap_msa_permission(struct ath10k_qmi *qmi,
     59					   struct ath10k_msa_mem_info *mem_info)
     60{
     61	struct qcom_scm_vmperm dst_perms;
     62	struct ath10k *ar = qmi->ar;
     63	unsigned int src_perms;
     64	int ret;
     65
     66	src_perms = BIT(QCOM_SCM_VMID_MSS_MSA) | BIT(QCOM_SCM_VMID_WLAN);
     67
     68	if (!mem_info->secure)
     69		src_perms |= BIT(QCOM_SCM_VMID_WLAN_CE);
     70
     71	dst_perms.vmid = QCOM_SCM_VMID_HLOS;
     72	dst_perms.perm = QCOM_SCM_PERM_RW;
     73
     74	ret = qcom_scm_assign_mem(mem_info->addr, mem_info->size,
     75				  &src_perms, &dst_perms, 1);
     76	if (ret < 0)
     77		ath10k_err(ar, "failed to unmap msa permissions: %d\n", ret);
     78
     79	return ret;
     80}
     81
     82static int ath10k_qmi_setup_msa_permissions(struct ath10k_qmi *qmi)
     83{
     84	int ret;
     85	int i;
     86
     87	if (qmi->msa_fixed_perm)
     88		return 0;
     89
     90	for (i = 0; i < qmi->nr_mem_region; i++) {
     91		ret = ath10k_qmi_map_msa_permission(qmi, &qmi->mem_region[i]);
     92		if (ret)
     93			goto err_unmap;
     94	}
     95
     96	return 0;
     97
     98err_unmap:
     99	for (i--; i >= 0; i--)
    100		ath10k_qmi_unmap_msa_permission(qmi, &qmi->mem_region[i]);
    101	return ret;
    102}
    103
    104static void ath10k_qmi_remove_msa_permission(struct ath10k_qmi *qmi)
    105{
    106	int i;
    107
    108	if (qmi->msa_fixed_perm)
    109		return;
    110
    111	for (i = 0; i < qmi->nr_mem_region; i++)
    112		ath10k_qmi_unmap_msa_permission(qmi, &qmi->mem_region[i]);
    113}
    114
    115static int ath10k_qmi_msa_mem_info_send_sync_msg(struct ath10k_qmi *qmi)
    116{
    117	struct wlfw_msa_info_resp_msg_v01 resp = {};
    118	struct wlfw_msa_info_req_msg_v01 req = {};
    119	struct ath10k *ar = qmi->ar;
    120	phys_addr_t max_mapped_addr;
    121	struct qmi_txn txn;
    122	int ret;
    123	int i;
    124
    125	req.msa_addr = ar->msa.paddr;
    126	req.size = ar->msa.mem_size;
    127
    128	ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
    129			   wlfw_msa_info_resp_msg_v01_ei, &resp);
    130	if (ret < 0)
    131		goto out;
    132
    133	ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
    134			       QMI_WLFW_MSA_INFO_REQ_V01,
    135			       WLFW_MSA_INFO_REQ_MSG_V01_MAX_MSG_LEN,
    136			       wlfw_msa_info_req_msg_v01_ei, &req);
    137	if (ret < 0) {
    138		qmi_txn_cancel(&txn);
    139		ath10k_err(ar, "failed to send msa mem info req: %d\n", ret);
    140		goto out;
    141	}
    142
    143	ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
    144	if (ret < 0)
    145		goto out;
    146
    147	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
    148		ath10k_err(ar, "msa info req rejected: %d\n", resp.resp.error);
    149		ret = -EINVAL;
    150		goto out;
    151	}
    152
    153	if (resp.mem_region_info_len > QMI_WLFW_MAX_MEM_REG_V01) {
    154		ath10k_err(ar, "invalid memory region length received: %d\n",
    155			   resp.mem_region_info_len);
    156		ret = -EINVAL;
    157		goto out;
    158	}
    159
    160	max_mapped_addr = ar->msa.paddr + ar->msa.mem_size;
    161	qmi->nr_mem_region = resp.mem_region_info_len;
    162	for (i = 0; i < resp.mem_region_info_len; i++) {
    163		if (resp.mem_region_info[i].size > ar->msa.mem_size ||
    164		    resp.mem_region_info[i].region_addr > max_mapped_addr ||
    165		    resp.mem_region_info[i].region_addr < ar->msa.paddr ||
    166		    resp.mem_region_info[i].size +
    167		    resp.mem_region_info[i].region_addr > max_mapped_addr) {
    168			ath10k_err(ar, "received out of range memory region address 0x%llx with size 0x%x, aborting\n",
    169				   resp.mem_region_info[i].region_addr,
    170				   resp.mem_region_info[i].size);
    171			ret = -EINVAL;
    172			goto fail_unwind;
    173		}
    174		qmi->mem_region[i].addr = resp.mem_region_info[i].region_addr;
    175		qmi->mem_region[i].size = resp.mem_region_info[i].size;
    176		qmi->mem_region[i].secure = resp.mem_region_info[i].secure_flag;
    177		ath10k_dbg(ar, ATH10K_DBG_QMI,
    178			   "qmi msa mem region %d addr 0x%pa size 0x%x flag 0x%08x\n",
    179			   i, &qmi->mem_region[i].addr,
    180			   qmi->mem_region[i].size,
    181			   qmi->mem_region[i].secure);
    182	}
    183
    184	ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi msa mem info request completed\n");
    185	return 0;
    186
    187fail_unwind:
    188	memset(&qmi->mem_region[0], 0, sizeof(qmi->mem_region[0]) * i);
    189out:
    190	return ret;
    191}
    192
    193static int ath10k_qmi_msa_ready_send_sync_msg(struct ath10k_qmi *qmi)
    194{
    195	struct wlfw_msa_ready_resp_msg_v01 resp = {};
    196	struct wlfw_msa_ready_req_msg_v01 req = {};
    197	struct ath10k *ar = qmi->ar;
    198	struct qmi_txn txn;
    199	int ret;
    200
    201	ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
    202			   wlfw_msa_ready_resp_msg_v01_ei, &resp);
    203	if (ret < 0)
    204		goto out;
    205
    206	ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
    207			       QMI_WLFW_MSA_READY_REQ_V01,
    208			       WLFW_MSA_READY_REQ_MSG_V01_MAX_MSG_LEN,
    209			       wlfw_msa_ready_req_msg_v01_ei, &req);
    210	if (ret < 0) {
    211		qmi_txn_cancel(&txn);
    212		ath10k_err(ar, "failed to send msa mem ready request: %d\n", ret);
    213		goto out;
    214	}
    215
    216	ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
    217	if (ret < 0)
    218		goto out;
    219
    220	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
    221		ath10k_err(ar, "msa ready request rejected: %d\n", resp.resp.error);
    222		ret = -EINVAL;
    223	}
    224
    225	ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi msa mem ready request completed\n");
    226	return 0;
    227
    228out:
    229	return ret;
    230}
    231
    232static int ath10k_qmi_bdf_dnld_send_sync(struct ath10k_qmi *qmi)
    233{
    234	struct wlfw_bdf_download_resp_msg_v01 resp = {};
    235	struct wlfw_bdf_download_req_msg_v01 *req;
    236	struct ath10k *ar = qmi->ar;
    237	unsigned int remaining;
    238	struct qmi_txn txn;
    239	const u8 *temp;
    240	int ret;
    241
    242	req = kzalloc(sizeof(*req), GFP_KERNEL);
    243	if (!req)
    244		return -ENOMEM;
    245
    246	temp = ar->normal_mode_fw.board_data;
    247	remaining = ar->normal_mode_fw.board_len;
    248
    249	while (remaining) {
    250		req->valid = 1;
    251		req->file_id_valid = 1;
    252		req->file_id = 0;
    253		req->total_size_valid = 1;
    254		req->total_size = ar->normal_mode_fw.board_len;
    255		req->seg_id_valid = 1;
    256		req->data_valid = 1;
    257		req->end_valid = 1;
    258
    259		if (remaining > QMI_WLFW_MAX_DATA_SIZE_V01) {
    260			req->data_len = QMI_WLFW_MAX_DATA_SIZE_V01;
    261		} else {
    262			req->data_len = remaining;
    263			req->end = 1;
    264		}
    265
    266		memcpy(req->data, temp, req->data_len);
    267
    268		ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
    269				   wlfw_bdf_download_resp_msg_v01_ei,
    270				   &resp);
    271		if (ret < 0)
    272			goto out;
    273
    274		ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
    275				       QMI_WLFW_BDF_DOWNLOAD_REQ_V01,
    276				       WLFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN,
    277				       wlfw_bdf_download_req_msg_v01_ei, req);
    278		if (ret < 0) {
    279			qmi_txn_cancel(&txn);
    280			goto out;
    281		}
    282
    283		ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
    284
    285		if (ret < 0)
    286			goto out;
    287
    288		/* end = 1 triggers a CRC check on the BDF.  If this fails, we
    289		 * get a QMI_ERR_MALFORMED_MSG_V01 error, but the FW is still
    290		 * willing to use the BDF.  For some platforms, all the valid
    291		 * released BDFs fail this CRC check, so attempt to detect this
    292		 * scenario and treat it as non-fatal.
    293		 */
    294		if (resp.resp.result != QMI_RESULT_SUCCESS_V01 &&
    295		    !(req->end == 1 &&
    296		      resp.resp.result == QMI_ERR_MALFORMED_MSG_V01)) {
    297			ath10k_err(ar, "failed to download board data file: %d\n",
    298				   resp.resp.error);
    299			ret = -EINVAL;
    300			goto out;
    301		}
    302
    303		remaining -= req->data_len;
    304		temp += req->data_len;
    305		req->seg_id++;
    306	}
    307
    308	ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi bdf download request completed\n");
    309
    310	kfree(req);
    311	return 0;
    312
    313out:
    314	kfree(req);
    315	return ret;
    316}
    317
    318static int ath10k_qmi_send_cal_report_req(struct ath10k_qmi *qmi)
    319{
    320	struct wlfw_cal_report_resp_msg_v01 resp = {};
    321	struct wlfw_cal_report_req_msg_v01 req = {};
    322	struct ath10k *ar = qmi->ar;
    323	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
    324	struct qmi_txn txn;
    325	int i, j = 0;
    326	int ret;
    327
    328	if (ar_snoc->xo_cal_supported) {
    329		req.xo_cal_data_valid = 1;
    330		req.xo_cal_data = ar_snoc->xo_cal_data;
    331	}
    332
    333	ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_cal_report_resp_msg_v01_ei,
    334			   &resp);
    335	if (ret < 0)
    336		goto out;
    337
    338	for (i = 0; i < QMI_WLFW_MAX_NUM_CAL_V01; i++) {
    339		if (qmi->cal_data[i].total_size &&
    340		    qmi->cal_data[i].data) {
    341			req.meta_data[j] = qmi->cal_data[i].cal_id;
    342			j++;
    343		}
    344	}
    345	req.meta_data_len = j;
    346
    347	ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
    348			       QMI_WLFW_CAL_REPORT_REQ_V01,
    349			       WLFW_CAL_REPORT_REQ_MSG_V01_MAX_MSG_LEN,
    350			       wlfw_cal_report_req_msg_v01_ei, &req);
    351	if (ret < 0) {
    352		qmi_txn_cancel(&txn);
    353		ath10k_err(ar, "failed to send calibration request: %d\n", ret);
    354		goto out;
    355	}
    356
    357	ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
    358	if (ret < 0)
    359		goto out;
    360
    361	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
    362		ath10k_err(ar, "calibration request rejected: %d\n", resp.resp.error);
    363		ret = -EINVAL;
    364		goto out;
    365	}
    366
    367	ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi cal report request completed\n");
    368	return 0;
    369
    370out:
    371	return ret;
    372}
    373
    374static int
    375ath10k_qmi_mode_send_sync_msg(struct ath10k *ar, enum wlfw_driver_mode_enum_v01 mode)
    376{
    377	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
    378	struct ath10k_qmi *qmi = ar_snoc->qmi;
    379	struct wlfw_wlan_mode_resp_msg_v01 resp = {};
    380	struct wlfw_wlan_mode_req_msg_v01 req = {};
    381	struct qmi_txn txn;
    382	int ret;
    383
    384	ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
    385			   wlfw_wlan_mode_resp_msg_v01_ei,
    386			   &resp);
    387	if (ret < 0)
    388		goto out;
    389
    390	req.mode = mode;
    391	req.hw_debug_valid = 1;
    392	req.hw_debug = 0;
    393
    394	ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
    395			       QMI_WLFW_WLAN_MODE_REQ_V01,
    396			       WLFW_WLAN_MODE_REQ_MSG_V01_MAX_MSG_LEN,
    397			       wlfw_wlan_mode_req_msg_v01_ei, &req);
    398	if (ret < 0) {
    399		qmi_txn_cancel(&txn);
    400		ath10k_err(ar, "failed to send wlan mode %d request: %d\n", mode, ret);
    401		goto out;
    402	}
    403
    404	ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
    405	if (ret < 0)
    406		goto out;
    407
    408	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
    409		ath10k_err(ar, "more request rejected: %d\n", resp.resp.error);
    410		ret = -EINVAL;
    411		goto out;
    412	}
    413
    414	ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi wlan mode req completed: %d\n", mode);
    415	return 0;
    416
    417out:
    418	return ret;
    419}
    420
    421static int
    422ath10k_qmi_cfg_send_sync_msg(struct ath10k *ar,
    423			     struct ath10k_qmi_wlan_enable_cfg *config,
    424			     const char *version)
    425{
    426	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
    427	struct ath10k_qmi *qmi = ar_snoc->qmi;
    428	struct wlfw_wlan_cfg_resp_msg_v01 resp = {};
    429	struct wlfw_wlan_cfg_req_msg_v01 *req;
    430	struct qmi_txn txn;
    431	int ret;
    432	u32 i;
    433
    434	req = kzalloc(sizeof(*req), GFP_KERNEL);
    435	if (!req)
    436		return -ENOMEM;
    437
    438	ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
    439			   wlfw_wlan_cfg_resp_msg_v01_ei,
    440			   &resp);
    441	if (ret < 0)
    442		goto out;
    443
    444	req->host_version_valid = 0;
    445
    446	req->tgt_cfg_valid = 1;
    447	if (config->num_ce_tgt_cfg > QMI_WLFW_MAX_NUM_CE_V01)
    448		req->tgt_cfg_len = QMI_WLFW_MAX_NUM_CE_V01;
    449	else
    450		req->tgt_cfg_len = config->num_ce_tgt_cfg;
    451	for (i = 0; i < req->tgt_cfg_len; i++) {
    452		req->tgt_cfg[i].pipe_num = config->ce_tgt_cfg[i].pipe_num;
    453		req->tgt_cfg[i].pipe_dir = config->ce_tgt_cfg[i].pipe_dir;
    454		req->tgt_cfg[i].nentries = config->ce_tgt_cfg[i].nentries;
    455		req->tgt_cfg[i].nbytes_max = config->ce_tgt_cfg[i].nbytes_max;
    456		req->tgt_cfg[i].flags = config->ce_tgt_cfg[i].flags;
    457	}
    458
    459	req->svc_cfg_valid = 1;
    460	if (config->num_ce_svc_pipe_cfg > QMI_WLFW_MAX_NUM_SVC_V01)
    461		req->svc_cfg_len = QMI_WLFW_MAX_NUM_SVC_V01;
    462	else
    463		req->svc_cfg_len = config->num_ce_svc_pipe_cfg;
    464	for (i = 0; i < req->svc_cfg_len; i++) {
    465		req->svc_cfg[i].service_id = config->ce_svc_cfg[i].service_id;
    466		req->svc_cfg[i].pipe_dir = config->ce_svc_cfg[i].pipe_dir;
    467		req->svc_cfg[i].pipe_num = config->ce_svc_cfg[i].pipe_num;
    468	}
    469
    470	req->shadow_reg_valid = 1;
    471	if (config->num_shadow_reg_cfg >
    472	    QMI_WLFW_MAX_NUM_SHADOW_REG_V01)
    473		req->shadow_reg_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V01;
    474	else
    475		req->shadow_reg_len = config->num_shadow_reg_cfg;
    476
    477	memcpy(req->shadow_reg, config->shadow_reg_cfg,
    478	       sizeof(struct wlfw_shadow_reg_cfg_s_v01) * req->shadow_reg_len);
    479
    480	ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
    481			       QMI_WLFW_WLAN_CFG_REQ_V01,
    482			       WLFW_WLAN_CFG_REQ_MSG_V01_MAX_MSG_LEN,
    483			       wlfw_wlan_cfg_req_msg_v01_ei, req);
    484	if (ret < 0) {
    485		qmi_txn_cancel(&txn);
    486		ath10k_err(ar, "failed to send config request: %d\n", ret);
    487		goto out;
    488	}
    489
    490	ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
    491	if (ret < 0)
    492		goto out;
    493
    494	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
    495		ath10k_err(ar, "config request rejected: %d\n", resp.resp.error);
    496		ret = -EINVAL;
    497		goto out;
    498	}
    499
    500	ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi config request completed\n");
    501	kfree(req);
    502	return 0;
    503
    504out:
    505	kfree(req);
    506	return ret;
    507}
    508
    509int ath10k_qmi_wlan_enable(struct ath10k *ar,
    510			   struct ath10k_qmi_wlan_enable_cfg *config,
    511			   enum wlfw_driver_mode_enum_v01 mode,
    512			   const char *version)
    513{
    514	int ret;
    515
    516	ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi mode %d config %p\n",
    517		   mode, config);
    518
    519	ret = ath10k_qmi_cfg_send_sync_msg(ar, config, version);
    520	if (ret) {
    521		ath10k_err(ar, "failed to send qmi config: %d\n", ret);
    522		return ret;
    523	}
    524
    525	ret = ath10k_qmi_mode_send_sync_msg(ar, mode);
    526	if (ret) {
    527		ath10k_err(ar, "failed to send qmi mode: %d\n", ret);
    528		return ret;
    529	}
    530
    531	return 0;
    532}
    533
    534int ath10k_qmi_wlan_disable(struct ath10k *ar)
    535{
    536	return ath10k_qmi_mode_send_sync_msg(ar, QMI_WLFW_OFF_V01);
    537}
    538
    539static int ath10k_qmi_cap_send_sync_msg(struct ath10k_qmi *qmi)
    540{
    541	struct wlfw_cap_resp_msg_v01 *resp;
    542	struct wlfw_cap_req_msg_v01 req = {};
    543	struct ath10k *ar = qmi->ar;
    544	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
    545	struct qmi_txn txn;
    546	int ret;
    547
    548	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
    549	if (!resp)
    550		return -ENOMEM;
    551
    552	ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_cap_resp_msg_v01_ei, resp);
    553	if (ret < 0)
    554		goto out;
    555
    556	ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
    557			       QMI_WLFW_CAP_REQ_V01,
    558			       WLFW_CAP_REQ_MSG_V01_MAX_MSG_LEN,
    559			       wlfw_cap_req_msg_v01_ei, &req);
    560	if (ret < 0) {
    561		qmi_txn_cancel(&txn);
    562		ath10k_err(ar, "failed to send capability request: %d\n", ret);
    563		goto out;
    564	}
    565
    566	ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
    567	if (ret < 0)
    568		goto out;
    569
    570	if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
    571		ath10k_err(ar, "capability req rejected: %d\n", resp->resp.error);
    572		ret = -EINVAL;
    573		goto out;
    574	}
    575
    576	if (resp->chip_info_valid) {
    577		qmi->chip_info.chip_id = resp->chip_info.chip_id;
    578		qmi->chip_info.chip_family = resp->chip_info.chip_family;
    579	} else {
    580		qmi->chip_info.chip_id = 0xFF;
    581	}
    582
    583	if (resp->board_info_valid)
    584		qmi->board_info.board_id = resp->board_info.board_id;
    585	else
    586		qmi->board_info.board_id = 0xFF;
    587
    588	if (resp->soc_info_valid)
    589		qmi->soc_info.soc_id = resp->soc_info.soc_id;
    590
    591	if (resp->fw_version_info_valid) {
    592		qmi->fw_version = resp->fw_version_info.fw_version;
    593		strlcpy(qmi->fw_build_timestamp, resp->fw_version_info.fw_build_timestamp,
    594			sizeof(qmi->fw_build_timestamp));
    595	}
    596
    597	if (resp->fw_build_id_valid)
    598		strlcpy(qmi->fw_build_id, resp->fw_build_id,
    599			MAX_BUILD_ID_LEN + 1);
    600
    601	if (!test_bit(ATH10K_SNOC_FLAG_REGISTERED, &ar_snoc->flags)) {
    602		ath10k_info(ar, "qmi chip_id 0x%x chip_family 0x%x board_id 0x%x soc_id 0x%x",
    603			    qmi->chip_info.chip_id, qmi->chip_info.chip_family,
    604			    qmi->board_info.board_id, qmi->soc_info.soc_id);
    605		ath10k_info(ar, "qmi fw_version 0x%x fw_build_timestamp %s fw_build_id %s",
    606			    qmi->fw_version, qmi->fw_build_timestamp, qmi->fw_build_id);
    607	}
    608
    609	kfree(resp);
    610	return 0;
    611
    612out:
    613	kfree(resp);
    614	return ret;
    615}
    616
    617static int ath10k_qmi_host_cap_send_sync(struct ath10k_qmi *qmi)
    618{
    619	struct wlfw_host_cap_resp_msg_v01 resp = {};
    620	struct wlfw_host_cap_req_msg_v01 req = {};
    621	struct qmi_elem_info *req_ei;
    622	struct ath10k *ar = qmi->ar;
    623	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
    624	struct qmi_txn txn;
    625	int ret;
    626
    627	req.daemon_support_valid = 1;
    628	req.daemon_support = 0;
    629
    630	ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_host_cap_resp_msg_v01_ei,
    631			   &resp);
    632	if (ret < 0)
    633		goto out;
    634
    635	if (test_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags))
    636		req_ei = wlfw_host_cap_8bit_req_msg_v01_ei;
    637	else
    638		req_ei = wlfw_host_cap_req_msg_v01_ei;
    639
    640	ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
    641			       QMI_WLFW_HOST_CAP_REQ_V01,
    642			       WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN,
    643			       req_ei, &req);
    644	if (ret < 0) {
    645		qmi_txn_cancel(&txn);
    646		ath10k_err(ar, "failed to send host capability request: %d\n", ret);
    647		goto out;
    648	}
    649
    650	ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
    651	if (ret < 0)
    652		goto out;
    653
    654	/* older FW didn't support this request, which is not fatal */
    655	if (resp.resp.result != QMI_RESULT_SUCCESS_V01 &&
    656	    resp.resp.error != QMI_ERR_NOT_SUPPORTED_V01) {
    657		ath10k_err(ar, "host capability request rejected: %d\n", resp.resp.error);
    658		ret = -EINVAL;
    659		goto out;
    660	}
    661
    662	ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi host capability request completed\n");
    663	return 0;
    664
    665out:
    666	return ret;
    667}
    668
    669int ath10k_qmi_set_fw_log_mode(struct ath10k *ar, u8 fw_log_mode)
    670{
    671	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
    672	struct wlfw_ini_resp_msg_v01 resp = {};
    673	struct ath10k_qmi *qmi = ar_snoc->qmi;
    674	struct wlfw_ini_req_msg_v01 req = {};
    675	struct qmi_txn txn;
    676	int ret;
    677
    678	req.enablefwlog_valid = 1;
    679	req.enablefwlog = fw_log_mode;
    680
    681	ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_ini_resp_msg_v01_ei,
    682			   &resp);
    683	if (ret < 0)
    684		goto out;
    685
    686	ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
    687			       QMI_WLFW_INI_REQ_V01,
    688			       WLFW_INI_REQ_MSG_V01_MAX_MSG_LEN,
    689			       wlfw_ini_req_msg_v01_ei, &req);
    690	if (ret < 0) {
    691		qmi_txn_cancel(&txn);
    692		ath10k_err(ar, "failed to send fw log request: %d\n", ret);
    693		goto out;
    694	}
    695
    696	ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
    697	if (ret < 0)
    698		goto out;
    699
    700	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
    701		ath10k_err(ar, "fw log request rejected: %d\n",
    702			   resp.resp.error);
    703		ret = -EINVAL;
    704		goto out;
    705	}
    706	ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi fw log request completed, mode: %d\n",
    707		   fw_log_mode);
    708	return 0;
    709
    710out:
    711	return ret;
    712}
    713
    714static int
    715ath10k_qmi_ind_register_send_sync_msg(struct ath10k_qmi *qmi)
    716{
    717	struct wlfw_ind_register_resp_msg_v01 resp = {};
    718	struct wlfw_ind_register_req_msg_v01 req = {};
    719	struct ath10k *ar = qmi->ar;
    720	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
    721	struct qmi_txn txn;
    722	int ret;
    723
    724	req.client_id_valid = 1;
    725	req.client_id = ATH10K_QMI_CLIENT_ID;
    726	req.fw_ready_enable_valid = 1;
    727	req.fw_ready_enable = 1;
    728	req.msa_ready_enable_valid = 1;
    729	req.msa_ready_enable = 1;
    730
    731	if (ar_snoc->xo_cal_supported) {
    732		req.xo_cal_enable_valid = 1;
    733		req.xo_cal_enable = 1;
    734	}
    735
    736	ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
    737			   wlfw_ind_register_resp_msg_v01_ei, &resp);
    738	if (ret < 0)
    739		goto out;
    740
    741	ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
    742			       QMI_WLFW_IND_REGISTER_REQ_V01,
    743			       WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN,
    744			       wlfw_ind_register_req_msg_v01_ei, &req);
    745	if (ret < 0) {
    746		qmi_txn_cancel(&txn);
    747		ath10k_err(ar, "failed to send indication registered request: %d\n", ret);
    748		goto out;
    749	}
    750
    751	ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
    752	if (ret < 0)
    753		goto out;
    754
    755	if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
    756		ath10k_err(ar, "indication request rejected: %d\n", resp.resp.error);
    757		ret = -EINVAL;
    758		goto out;
    759	}
    760
    761	if (resp.fw_status_valid) {
    762		if (resp.fw_status & QMI_WLFW_FW_READY_V01)
    763			qmi->fw_ready = true;
    764	}
    765	ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi indication register request completed\n");
    766	return 0;
    767
    768out:
    769	return ret;
    770}
    771
    772static void ath10k_qmi_event_server_arrive(struct ath10k_qmi *qmi)
    773{
    774	struct ath10k *ar = qmi->ar;
    775	int ret;
    776
    777	ret = ath10k_qmi_ind_register_send_sync_msg(qmi);
    778	if (ret)
    779		return;
    780
    781	if (qmi->fw_ready) {
    782		ath10k_snoc_fw_indication(ar, ATH10K_QMI_EVENT_FW_READY_IND);
    783		return;
    784	}
    785
    786	ret = ath10k_qmi_host_cap_send_sync(qmi);
    787	if (ret)
    788		return;
    789
    790	ret = ath10k_qmi_msa_mem_info_send_sync_msg(qmi);
    791	if (ret)
    792		return;
    793
    794	/*
    795	 * HACK: sleep for a while inbetween receiving the msa info response
    796	 * and the XPU update to prevent SDM845 from crashing due to a security
    797	 * violation, when running MPSS.AT.4.0.c2-01184-SDM845_GEN_PACK-1.
    798	 */
    799	msleep(20);
    800
    801	ret = ath10k_qmi_setup_msa_permissions(qmi);
    802	if (ret)
    803		return;
    804
    805	ret = ath10k_qmi_msa_ready_send_sync_msg(qmi);
    806	if (ret)
    807		goto err_setup_msa;
    808
    809	ret = ath10k_qmi_cap_send_sync_msg(qmi);
    810	if (ret)
    811		goto err_setup_msa;
    812
    813	return;
    814
    815err_setup_msa:
    816	ath10k_qmi_remove_msa_permission(qmi);
    817}
    818
    819static int ath10k_qmi_fetch_board_file(struct ath10k_qmi *qmi)
    820{
    821	struct ath10k *ar = qmi->ar;
    822	int ret;
    823
    824	ar->hif.bus = ATH10K_BUS_SNOC;
    825	ar->id.qmi_ids_valid = true;
    826	ar->id.qmi_board_id = qmi->board_info.board_id;
    827	ar->id.qmi_chip_id = qmi->chip_info.chip_id;
    828	ar->hw_params.fw.dir = WCN3990_HW_1_0_FW_DIR;
    829
    830	ret = ath10k_core_check_dt(ar);
    831	if (ret)
    832		ath10k_dbg(ar, ATH10K_DBG_QMI, "DT bdf variant name not set.\n");
    833
    834	return ath10k_core_fetch_board_file(qmi->ar, ATH10K_BD_IE_BOARD);
    835}
    836
    837static int
    838ath10k_qmi_driver_event_post(struct ath10k_qmi *qmi,
    839			     enum ath10k_qmi_driver_event_type type,
    840			     void *data)
    841{
    842	struct ath10k_qmi_driver_event *event;
    843
    844	event = kzalloc(sizeof(*event), GFP_ATOMIC);
    845	if (!event)
    846		return -ENOMEM;
    847
    848	event->type = type;
    849	event->data = data;
    850
    851	spin_lock(&qmi->event_lock);
    852	list_add_tail(&event->list, &qmi->event_list);
    853	spin_unlock(&qmi->event_lock);
    854
    855	queue_work(qmi->event_wq, &qmi->event_work);
    856
    857	return 0;
    858}
    859
    860static void ath10k_qmi_event_server_exit(struct ath10k_qmi *qmi)
    861{
    862	struct ath10k *ar = qmi->ar;
    863	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
    864
    865	ath10k_qmi_remove_msa_permission(qmi);
    866	ath10k_core_free_board_files(ar);
    867	if (!test_bit(ATH10K_SNOC_FLAG_UNREGISTERING, &ar_snoc->flags) &&
    868	    !test_bit(ATH10K_SNOC_FLAG_MODEM_STOPPED, &ar_snoc->flags))
    869		ath10k_snoc_fw_crashed_dump(ar);
    870
    871	ath10k_snoc_fw_indication(ar, ATH10K_QMI_EVENT_FW_DOWN_IND);
    872	ath10k_dbg(ar, ATH10K_DBG_QMI, "wifi fw qmi service disconnected\n");
    873}
    874
    875static void ath10k_qmi_event_msa_ready(struct ath10k_qmi *qmi)
    876{
    877	int ret;
    878
    879	ret = ath10k_qmi_fetch_board_file(qmi);
    880	if (ret)
    881		goto out;
    882
    883	ret = ath10k_qmi_bdf_dnld_send_sync(qmi);
    884	if (ret)
    885		goto out;
    886
    887	ret = ath10k_qmi_send_cal_report_req(qmi);
    888
    889out:
    890	return;
    891}
    892
    893static int ath10k_qmi_event_fw_ready_ind(struct ath10k_qmi *qmi)
    894{
    895	struct ath10k *ar = qmi->ar;
    896
    897	ath10k_dbg(ar, ATH10K_DBG_QMI, "wifi fw ready event received\n");
    898	ath10k_snoc_fw_indication(ar, ATH10K_QMI_EVENT_FW_READY_IND);
    899
    900	return 0;
    901}
    902
    903static void ath10k_qmi_fw_ready_ind(struct qmi_handle *qmi_hdl,
    904				    struct sockaddr_qrtr *sq,
    905				    struct qmi_txn *txn, const void *data)
    906{
    907	struct ath10k_qmi *qmi = container_of(qmi_hdl, struct ath10k_qmi, qmi_hdl);
    908
    909	ath10k_qmi_driver_event_post(qmi, ATH10K_QMI_EVENT_FW_READY_IND, NULL);
    910}
    911
    912static void ath10k_qmi_msa_ready_ind(struct qmi_handle *qmi_hdl,
    913				     struct sockaddr_qrtr *sq,
    914				     struct qmi_txn *txn, const void *data)
    915{
    916	struct ath10k_qmi *qmi = container_of(qmi_hdl, struct ath10k_qmi, qmi_hdl);
    917
    918	ath10k_qmi_driver_event_post(qmi, ATH10K_QMI_EVENT_MSA_READY_IND, NULL);
    919}
    920
    921static const struct qmi_msg_handler qmi_msg_handler[] = {
    922	{
    923		.type = QMI_INDICATION,
    924		.msg_id = QMI_WLFW_FW_READY_IND_V01,
    925		.ei = wlfw_fw_ready_ind_msg_v01_ei,
    926		.decoded_size = sizeof(struct wlfw_fw_ready_ind_msg_v01),
    927		.fn = ath10k_qmi_fw_ready_ind,
    928	},
    929	{
    930		.type = QMI_INDICATION,
    931		.msg_id = QMI_WLFW_MSA_READY_IND_V01,
    932		.ei = wlfw_msa_ready_ind_msg_v01_ei,
    933		.decoded_size = sizeof(struct wlfw_msa_ready_ind_msg_v01),
    934		.fn = ath10k_qmi_msa_ready_ind,
    935	},
    936	{}
    937};
    938
    939static int ath10k_qmi_new_server(struct qmi_handle *qmi_hdl,
    940				 struct qmi_service *service)
    941{
    942	struct ath10k_qmi *qmi = container_of(qmi_hdl, struct ath10k_qmi, qmi_hdl);
    943	struct sockaddr_qrtr *sq = &qmi->sq;
    944	struct ath10k *ar = qmi->ar;
    945	int ret;
    946
    947	sq->sq_family = AF_QIPCRTR;
    948	sq->sq_node = service->node;
    949	sq->sq_port = service->port;
    950
    951	ath10k_dbg(ar, ATH10K_DBG_QMI, "wifi fw qmi service found\n");
    952
    953	ret = kernel_connect(qmi_hdl->sock, (struct sockaddr *)&qmi->sq,
    954			     sizeof(qmi->sq), 0);
    955	if (ret) {
    956		ath10k_err(ar, "failed to connect to a remote QMI service port\n");
    957		return ret;
    958	}
    959
    960	ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi wifi fw qmi service connected\n");
    961	ath10k_qmi_driver_event_post(qmi, ATH10K_QMI_EVENT_SERVER_ARRIVE, NULL);
    962
    963	return ret;
    964}
    965
    966static void ath10k_qmi_del_server(struct qmi_handle *qmi_hdl,
    967				  struct qmi_service *service)
    968{
    969	struct ath10k_qmi *qmi =
    970		container_of(qmi_hdl, struct ath10k_qmi, qmi_hdl);
    971
    972	qmi->fw_ready = false;
    973
    974	/*
    975	 * The del_server event is to be processed only if coming from
    976	 * the qmi server. The qmi infrastructure sends del_server, when
    977	 * any client releases the qmi handle. In this case do not process
    978	 * this del_server event.
    979	 */
    980	if (qmi->state == ATH10K_QMI_STATE_INIT_DONE)
    981		ath10k_qmi_driver_event_post(qmi, ATH10K_QMI_EVENT_SERVER_EXIT,
    982					     NULL);
    983}
    984
    985static const struct qmi_ops ath10k_qmi_ops = {
    986	.new_server = ath10k_qmi_new_server,
    987	.del_server = ath10k_qmi_del_server,
    988};
    989
    990static void ath10k_qmi_driver_event_work(struct work_struct *work)
    991{
    992	struct ath10k_qmi *qmi = container_of(work, struct ath10k_qmi,
    993					      event_work);
    994	struct ath10k_qmi_driver_event *event;
    995	struct ath10k *ar = qmi->ar;
    996
    997	spin_lock(&qmi->event_lock);
    998	while (!list_empty(&qmi->event_list)) {
    999		event = list_first_entry(&qmi->event_list,
   1000					 struct ath10k_qmi_driver_event, list);
   1001		list_del(&event->list);
   1002		spin_unlock(&qmi->event_lock);
   1003
   1004		switch (event->type) {
   1005		case ATH10K_QMI_EVENT_SERVER_ARRIVE:
   1006			ath10k_qmi_event_server_arrive(qmi);
   1007			break;
   1008		case ATH10K_QMI_EVENT_SERVER_EXIT:
   1009			ath10k_qmi_event_server_exit(qmi);
   1010			break;
   1011		case ATH10K_QMI_EVENT_FW_READY_IND:
   1012			ath10k_qmi_event_fw_ready_ind(qmi);
   1013			break;
   1014		case ATH10K_QMI_EVENT_MSA_READY_IND:
   1015			ath10k_qmi_event_msa_ready(qmi);
   1016			break;
   1017		default:
   1018			ath10k_warn(ar, "invalid event type: %d", event->type);
   1019			break;
   1020		}
   1021		kfree(event);
   1022		spin_lock(&qmi->event_lock);
   1023	}
   1024	spin_unlock(&qmi->event_lock);
   1025}
   1026
   1027int ath10k_qmi_init(struct ath10k *ar, u32 msa_size)
   1028{
   1029	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
   1030	struct device *dev = ar->dev;
   1031	struct ath10k_qmi *qmi;
   1032	int ret;
   1033
   1034	qmi = kzalloc(sizeof(*qmi), GFP_KERNEL);
   1035	if (!qmi)
   1036		return -ENOMEM;
   1037
   1038	qmi->ar = ar;
   1039	ar_snoc->qmi = qmi;
   1040
   1041	if (of_property_read_bool(dev->of_node, "qcom,msa-fixed-perm"))
   1042		qmi->msa_fixed_perm = true;
   1043
   1044	ret = qmi_handle_init(&qmi->qmi_hdl,
   1045			      WLFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN,
   1046			      &ath10k_qmi_ops, qmi_msg_handler);
   1047	if (ret)
   1048		goto err;
   1049
   1050	qmi->event_wq = alloc_workqueue("ath10k_qmi_driver_event",
   1051					WQ_UNBOUND, 1);
   1052	if (!qmi->event_wq) {
   1053		ath10k_err(ar, "failed to allocate workqueue\n");
   1054		ret = -EFAULT;
   1055		goto err_release_qmi_handle;
   1056	}
   1057
   1058	INIT_LIST_HEAD(&qmi->event_list);
   1059	spin_lock_init(&qmi->event_lock);
   1060	INIT_WORK(&qmi->event_work, ath10k_qmi_driver_event_work);
   1061
   1062	ret = qmi_add_lookup(&qmi->qmi_hdl, WLFW_SERVICE_ID_V01,
   1063			     WLFW_SERVICE_VERS_V01, 0);
   1064	if (ret)
   1065		goto err_qmi_lookup;
   1066
   1067	qmi->state = ATH10K_QMI_STATE_INIT_DONE;
   1068	return 0;
   1069
   1070err_qmi_lookup:
   1071	destroy_workqueue(qmi->event_wq);
   1072
   1073err_release_qmi_handle:
   1074	qmi_handle_release(&qmi->qmi_hdl);
   1075
   1076err:
   1077	kfree(qmi);
   1078	return ret;
   1079}
   1080
   1081int ath10k_qmi_deinit(struct ath10k *ar)
   1082{
   1083	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
   1084	struct ath10k_qmi *qmi = ar_snoc->qmi;
   1085
   1086	qmi->state = ATH10K_QMI_STATE_DEINIT;
   1087	qmi_handle_release(&qmi->qmi_hdl);
   1088	cancel_work_sync(&qmi->event_work);
   1089	destroy_workqueue(qmi->event_wq);
   1090	kfree(qmi);
   1091	ar_snoc->qmi = NULL;
   1092
   1093	return 0;
   1094}