Linux Audio

Check our new training course

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