0001
0002
0003
0004
0005
0006 #include <linux/completion.h>
0007 #include <linux/device.h>
0008 #include <linux/debugfs.h>
0009 #include <linux/idr.h>
0010 #include <linux/kernel.h>
0011 #include <linux/of.h>
0012 #include <linux/of_address.h>
0013 #include <linux/module.h>
0014 #include <linux/net.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/qcom_scm.h>
0017 #include <linux/string.h>
0018 #include <net/sock.h>
0019
0020 #include "debug.h"
0021 #include "snoc.h"
0022
0023 #define ATH10K_QMI_CLIENT_ID 0x4b4e454c
0024 #define ATH10K_QMI_TIMEOUT 30
0025
0026 static int ath10k_qmi_map_msa_permission(struct ath10k_qmi *qmi,
0027 struct ath10k_msa_mem_info *mem_info)
0028 {
0029 struct qcom_scm_vmperm dst_perms[3];
0030 struct ath10k *ar = qmi->ar;
0031 unsigned int src_perms;
0032 u32 perm_count;
0033 int ret;
0034
0035 src_perms = BIT(QCOM_SCM_VMID_HLOS);
0036
0037 dst_perms[0].vmid = QCOM_SCM_VMID_MSS_MSA;
0038 dst_perms[0].perm = QCOM_SCM_PERM_RW;
0039 dst_perms[1].vmid = QCOM_SCM_VMID_WLAN;
0040 dst_perms[1].perm = QCOM_SCM_PERM_RW;
0041
0042 if (mem_info->secure) {
0043 perm_count = 2;
0044 } else {
0045 dst_perms[2].vmid = QCOM_SCM_VMID_WLAN_CE;
0046 dst_perms[2].perm = QCOM_SCM_PERM_RW;
0047 perm_count = 3;
0048 }
0049
0050 ret = qcom_scm_assign_mem(mem_info->addr, mem_info->size,
0051 &src_perms, dst_perms, perm_count);
0052 if (ret < 0)
0053 ath10k_err(ar, "failed to assign msa map permissions: %d\n", ret);
0054
0055 return ret;
0056 }
0057
0058 static int ath10k_qmi_unmap_msa_permission(struct ath10k_qmi *qmi,
0059 struct ath10k_msa_mem_info *mem_info)
0060 {
0061 struct qcom_scm_vmperm dst_perms;
0062 struct ath10k *ar = qmi->ar;
0063 unsigned int src_perms;
0064 int ret;
0065
0066 src_perms = BIT(QCOM_SCM_VMID_MSS_MSA) | BIT(QCOM_SCM_VMID_WLAN);
0067
0068 if (!mem_info->secure)
0069 src_perms |= BIT(QCOM_SCM_VMID_WLAN_CE);
0070
0071 dst_perms.vmid = QCOM_SCM_VMID_HLOS;
0072 dst_perms.perm = QCOM_SCM_PERM_RW;
0073
0074 ret = qcom_scm_assign_mem(mem_info->addr, mem_info->size,
0075 &src_perms, &dst_perms, 1);
0076 if (ret < 0)
0077 ath10k_err(ar, "failed to unmap msa permissions: %d\n", ret);
0078
0079 return ret;
0080 }
0081
0082 static int ath10k_qmi_setup_msa_permissions(struct ath10k_qmi *qmi)
0083 {
0084 int ret;
0085 int i;
0086
0087 if (qmi->msa_fixed_perm)
0088 return 0;
0089
0090 for (i = 0; i < qmi->nr_mem_region; i++) {
0091 ret = ath10k_qmi_map_msa_permission(qmi, &qmi->mem_region[i]);
0092 if (ret)
0093 goto err_unmap;
0094 }
0095
0096 return 0;
0097
0098 err_unmap:
0099 for (i--; i >= 0; i--)
0100 ath10k_qmi_unmap_msa_permission(qmi, &qmi->mem_region[i]);
0101 return ret;
0102 }
0103
0104 static void ath10k_qmi_remove_msa_permission(struct ath10k_qmi *qmi)
0105 {
0106 int i;
0107
0108 if (qmi->msa_fixed_perm)
0109 return;
0110
0111 for (i = 0; i < qmi->nr_mem_region; i++)
0112 ath10k_qmi_unmap_msa_permission(qmi, &qmi->mem_region[i]);
0113 }
0114
0115 static int ath10k_qmi_msa_mem_info_send_sync_msg(struct ath10k_qmi *qmi)
0116 {
0117 struct wlfw_msa_info_resp_msg_v01 resp = {};
0118 struct wlfw_msa_info_req_msg_v01 req = {};
0119 struct ath10k *ar = qmi->ar;
0120 phys_addr_t max_mapped_addr;
0121 struct qmi_txn txn;
0122 int ret;
0123 int i;
0124
0125 req.msa_addr = ar->msa.paddr;
0126 req.size = ar->msa.mem_size;
0127
0128 ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
0129 wlfw_msa_info_resp_msg_v01_ei, &resp);
0130 if (ret < 0)
0131 goto out;
0132
0133 ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
0134 QMI_WLFW_MSA_INFO_REQ_V01,
0135 WLFW_MSA_INFO_REQ_MSG_V01_MAX_MSG_LEN,
0136 wlfw_msa_info_req_msg_v01_ei, &req);
0137 if (ret < 0) {
0138 qmi_txn_cancel(&txn);
0139 ath10k_err(ar, "failed to send msa mem info req: %d\n", ret);
0140 goto out;
0141 }
0142
0143 ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
0144 if (ret < 0)
0145 goto out;
0146
0147 if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
0148 ath10k_err(ar, "msa info req rejected: %d\n", resp.resp.error);
0149 ret = -EINVAL;
0150 goto out;
0151 }
0152
0153 if (resp.mem_region_info_len > QMI_WLFW_MAX_MEM_REG_V01) {
0154 ath10k_err(ar, "invalid memory region length received: %d\n",
0155 resp.mem_region_info_len);
0156 ret = -EINVAL;
0157 goto out;
0158 }
0159
0160 max_mapped_addr = ar->msa.paddr + ar->msa.mem_size;
0161 qmi->nr_mem_region = resp.mem_region_info_len;
0162 for (i = 0; i < resp.mem_region_info_len; i++) {
0163 if (resp.mem_region_info[i].size > ar->msa.mem_size ||
0164 resp.mem_region_info[i].region_addr > max_mapped_addr ||
0165 resp.mem_region_info[i].region_addr < ar->msa.paddr ||
0166 resp.mem_region_info[i].size +
0167 resp.mem_region_info[i].region_addr > max_mapped_addr) {
0168 ath10k_err(ar, "received out of range memory region address 0x%llx with size 0x%x, aborting\n",
0169 resp.mem_region_info[i].region_addr,
0170 resp.mem_region_info[i].size);
0171 ret = -EINVAL;
0172 goto fail_unwind;
0173 }
0174 qmi->mem_region[i].addr = resp.mem_region_info[i].region_addr;
0175 qmi->mem_region[i].size = resp.mem_region_info[i].size;
0176 qmi->mem_region[i].secure = resp.mem_region_info[i].secure_flag;
0177 ath10k_dbg(ar, ATH10K_DBG_QMI,
0178 "qmi msa mem region %d addr 0x%pa size 0x%x flag 0x%08x\n",
0179 i, &qmi->mem_region[i].addr,
0180 qmi->mem_region[i].size,
0181 qmi->mem_region[i].secure);
0182 }
0183
0184 ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi msa mem info request completed\n");
0185 return 0;
0186
0187 fail_unwind:
0188 memset(&qmi->mem_region[0], 0, sizeof(qmi->mem_region[0]) * i);
0189 out:
0190 return ret;
0191 }
0192
0193 static int ath10k_qmi_msa_ready_send_sync_msg(struct ath10k_qmi *qmi)
0194 {
0195 struct wlfw_msa_ready_resp_msg_v01 resp = {};
0196 struct wlfw_msa_ready_req_msg_v01 req = {};
0197 struct ath10k *ar = qmi->ar;
0198 struct qmi_txn txn;
0199 int ret;
0200
0201 ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
0202 wlfw_msa_ready_resp_msg_v01_ei, &resp);
0203 if (ret < 0)
0204 goto out;
0205
0206 ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
0207 QMI_WLFW_MSA_READY_REQ_V01,
0208 WLFW_MSA_READY_REQ_MSG_V01_MAX_MSG_LEN,
0209 wlfw_msa_ready_req_msg_v01_ei, &req);
0210 if (ret < 0) {
0211 qmi_txn_cancel(&txn);
0212 ath10k_err(ar, "failed to send msa mem ready request: %d\n", ret);
0213 goto out;
0214 }
0215
0216 ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
0217 if (ret < 0)
0218 goto out;
0219
0220 if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
0221 ath10k_err(ar, "msa ready request rejected: %d\n", resp.resp.error);
0222 ret = -EINVAL;
0223 }
0224
0225 ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi msa mem ready request completed\n");
0226 return 0;
0227
0228 out:
0229 return ret;
0230 }
0231
0232 static int ath10k_qmi_bdf_dnld_send_sync(struct ath10k_qmi *qmi)
0233 {
0234 struct wlfw_bdf_download_resp_msg_v01 resp = {};
0235 struct wlfw_bdf_download_req_msg_v01 *req;
0236 struct ath10k *ar = qmi->ar;
0237 unsigned int remaining;
0238 struct qmi_txn txn;
0239 const u8 *temp;
0240 int ret;
0241
0242 req = kzalloc(sizeof(*req), GFP_KERNEL);
0243 if (!req)
0244 return -ENOMEM;
0245
0246 temp = ar->normal_mode_fw.board_data;
0247 remaining = ar->normal_mode_fw.board_len;
0248
0249 while (remaining) {
0250 req->valid = 1;
0251 req->file_id_valid = 1;
0252 req->file_id = 0;
0253 req->total_size_valid = 1;
0254 req->total_size = ar->normal_mode_fw.board_len;
0255 req->seg_id_valid = 1;
0256 req->data_valid = 1;
0257 req->end_valid = 1;
0258
0259 if (remaining > QMI_WLFW_MAX_DATA_SIZE_V01) {
0260 req->data_len = QMI_WLFW_MAX_DATA_SIZE_V01;
0261 } else {
0262 req->data_len = remaining;
0263 req->end = 1;
0264 }
0265
0266 memcpy(req->data, temp, req->data_len);
0267
0268 ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
0269 wlfw_bdf_download_resp_msg_v01_ei,
0270 &resp);
0271 if (ret < 0)
0272 goto out;
0273
0274 ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
0275 QMI_WLFW_BDF_DOWNLOAD_REQ_V01,
0276 WLFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN,
0277 wlfw_bdf_download_req_msg_v01_ei, req);
0278 if (ret < 0) {
0279 qmi_txn_cancel(&txn);
0280 goto out;
0281 }
0282
0283 ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
0284
0285 if (ret < 0)
0286 goto out;
0287
0288
0289
0290
0291
0292
0293
0294 if (resp.resp.result != QMI_RESULT_SUCCESS_V01 &&
0295 !(req->end == 1 &&
0296 resp.resp.result == QMI_ERR_MALFORMED_MSG_V01)) {
0297 ath10k_err(ar, "failed to download board data file: %d\n",
0298 resp.resp.error);
0299 ret = -EINVAL;
0300 goto out;
0301 }
0302
0303 remaining -= req->data_len;
0304 temp += req->data_len;
0305 req->seg_id++;
0306 }
0307
0308 ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi bdf download request completed\n");
0309
0310 kfree(req);
0311 return 0;
0312
0313 out:
0314 kfree(req);
0315 return ret;
0316 }
0317
0318 static int ath10k_qmi_send_cal_report_req(struct ath10k_qmi *qmi)
0319 {
0320 struct wlfw_cal_report_resp_msg_v01 resp = {};
0321 struct wlfw_cal_report_req_msg_v01 req = {};
0322 struct ath10k *ar = qmi->ar;
0323 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
0324 struct qmi_txn txn;
0325 int i, j = 0;
0326 int ret;
0327
0328 if (ar_snoc->xo_cal_supported) {
0329 req.xo_cal_data_valid = 1;
0330 req.xo_cal_data = ar_snoc->xo_cal_data;
0331 }
0332
0333 ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_cal_report_resp_msg_v01_ei,
0334 &resp);
0335 if (ret < 0)
0336 goto out;
0337
0338 for (i = 0; i < QMI_WLFW_MAX_NUM_CAL_V01; i++) {
0339 if (qmi->cal_data[i].total_size &&
0340 qmi->cal_data[i].data) {
0341 req.meta_data[j] = qmi->cal_data[i].cal_id;
0342 j++;
0343 }
0344 }
0345 req.meta_data_len = j;
0346
0347 ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
0348 QMI_WLFW_CAL_REPORT_REQ_V01,
0349 WLFW_CAL_REPORT_REQ_MSG_V01_MAX_MSG_LEN,
0350 wlfw_cal_report_req_msg_v01_ei, &req);
0351 if (ret < 0) {
0352 qmi_txn_cancel(&txn);
0353 ath10k_err(ar, "failed to send calibration request: %d\n", ret);
0354 goto out;
0355 }
0356
0357 ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
0358 if (ret < 0)
0359 goto out;
0360
0361 if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
0362 ath10k_err(ar, "calibration request rejected: %d\n", resp.resp.error);
0363 ret = -EINVAL;
0364 goto out;
0365 }
0366
0367 ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi cal report request completed\n");
0368 return 0;
0369
0370 out:
0371 return ret;
0372 }
0373
0374 static int
0375 ath10k_qmi_mode_send_sync_msg(struct ath10k *ar, enum wlfw_driver_mode_enum_v01 mode)
0376 {
0377 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
0378 struct ath10k_qmi *qmi = ar_snoc->qmi;
0379 struct wlfw_wlan_mode_resp_msg_v01 resp = {};
0380 struct wlfw_wlan_mode_req_msg_v01 req = {};
0381 struct qmi_txn txn;
0382 int ret;
0383
0384 ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
0385 wlfw_wlan_mode_resp_msg_v01_ei,
0386 &resp);
0387 if (ret < 0)
0388 goto out;
0389
0390 req.mode = mode;
0391 req.hw_debug_valid = 1;
0392 req.hw_debug = 0;
0393
0394 ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
0395 QMI_WLFW_WLAN_MODE_REQ_V01,
0396 WLFW_WLAN_MODE_REQ_MSG_V01_MAX_MSG_LEN,
0397 wlfw_wlan_mode_req_msg_v01_ei, &req);
0398 if (ret < 0) {
0399 qmi_txn_cancel(&txn);
0400 ath10k_err(ar, "failed to send wlan mode %d request: %d\n", mode, ret);
0401 goto out;
0402 }
0403
0404 ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
0405 if (ret < 0)
0406 goto out;
0407
0408 if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
0409 ath10k_err(ar, "more request rejected: %d\n", resp.resp.error);
0410 ret = -EINVAL;
0411 goto out;
0412 }
0413
0414 ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi wlan mode req completed: %d\n", mode);
0415 return 0;
0416
0417 out:
0418 return ret;
0419 }
0420
0421 static int
0422 ath10k_qmi_cfg_send_sync_msg(struct ath10k *ar,
0423 struct ath10k_qmi_wlan_enable_cfg *config,
0424 const char *version)
0425 {
0426 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
0427 struct ath10k_qmi *qmi = ar_snoc->qmi;
0428 struct wlfw_wlan_cfg_resp_msg_v01 resp = {};
0429 struct wlfw_wlan_cfg_req_msg_v01 *req;
0430 struct qmi_txn txn;
0431 int ret;
0432 u32 i;
0433
0434 req = kzalloc(sizeof(*req), GFP_KERNEL);
0435 if (!req)
0436 return -ENOMEM;
0437
0438 ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
0439 wlfw_wlan_cfg_resp_msg_v01_ei,
0440 &resp);
0441 if (ret < 0)
0442 goto out;
0443
0444 req->host_version_valid = 0;
0445
0446 req->tgt_cfg_valid = 1;
0447 if (config->num_ce_tgt_cfg > QMI_WLFW_MAX_NUM_CE_V01)
0448 req->tgt_cfg_len = QMI_WLFW_MAX_NUM_CE_V01;
0449 else
0450 req->tgt_cfg_len = config->num_ce_tgt_cfg;
0451 for (i = 0; i < req->tgt_cfg_len; i++) {
0452 req->tgt_cfg[i].pipe_num = config->ce_tgt_cfg[i].pipe_num;
0453 req->tgt_cfg[i].pipe_dir = config->ce_tgt_cfg[i].pipe_dir;
0454 req->tgt_cfg[i].nentries = config->ce_tgt_cfg[i].nentries;
0455 req->tgt_cfg[i].nbytes_max = config->ce_tgt_cfg[i].nbytes_max;
0456 req->tgt_cfg[i].flags = config->ce_tgt_cfg[i].flags;
0457 }
0458
0459 req->svc_cfg_valid = 1;
0460 if (config->num_ce_svc_pipe_cfg > QMI_WLFW_MAX_NUM_SVC_V01)
0461 req->svc_cfg_len = QMI_WLFW_MAX_NUM_SVC_V01;
0462 else
0463 req->svc_cfg_len = config->num_ce_svc_pipe_cfg;
0464 for (i = 0; i < req->svc_cfg_len; i++) {
0465 req->svc_cfg[i].service_id = config->ce_svc_cfg[i].service_id;
0466 req->svc_cfg[i].pipe_dir = config->ce_svc_cfg[i].pipe_dir;
0467 req->svc_cfg[i].pipe_num = config->ce_svc_cfg[i].pipe_num;
0468 }
0469
0470 req->shadow_reg_valid = 1;
0471 if (config->num_shadow_reg_cfg >
0472 QMI_WLFW_MAX_NUM_SHADOW_REG_V01)
0473 req->shadow_reg_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V01;
0474 else
0475 req->shadow_reg_len = config->num_shadow_reg_cfg;
0476
0477 memcpy(req->shadow_reg, config->shadow_reg_cfg,
0478 sizeof(struct wlfw_shadow_reg_cfg_s_v01) * req->shadow_reg_len);
0479
0480 ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
0481 QMI_WLFW_WLAN_CFG_REQ_V01,
0482 WLFW_WLAN_CFG_REQ_MSG_V01_MAX_MSG_LEN,
0483 wlfw_wlan_cfg_req_msg_v01_ei, req);
0484 if (ret < 0) {
0485 qmi_txn_cancel(&txn);
0486 ath10k_err(ar, "failed to send config request: %d\n", ret);
0487 goto out;
0488 }
0489
0490 ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
0491 if (ret < 0)
0492 goto out;
0493
0494 if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
0495 ath10k_err(ar, "config request rejected: %d\n", resp.resp.error);
0496 ret = -EINVAL;
0497 goto out;
0498 }
0499
0500 ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi config request completed\n");
0501 kfree(req);
0502 return 0;
0503
0504 out:
0505 kfree(req);
0506 return ret;
0507 }
0508
0509 int ath10k_qmi_wlan_enable(struct ath10k *ar,
0510 struct ath10k_qmi_wlan_enable_cfg *config,
0511 enum wlfw_driver_mode_enum_v01 mode,
0512 const char *version)
0513 {
0514 int ret;
0515
0516 ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi mode %d config %p\n",
0517 mode, config);
0518
0519 ret = ath10k_qmi_cfg_send_sync_msg(ar, config, version);
0520 if (ret) {
0521 ath10k_err(ar, "failed to send qmi config: %d\n", ret);
0522 return ret;
0523 }
0524
0525 ret = ath10k_qmi_mode_send_sync_msg(ar, mode);
0526 if (ret) {
0527 ath10k_err(ar, "failed to send qmi mode: %d\n", ret);
0528 return ret;
0529 }
0530
0531 return 0;
0532 }
0533
0534 int ath10k_qmi_wlan_disable(struct ath10k *ar)
0535 {
0536 return ath10k_qmi_mode_send_sync_msg(ar, QMI_WLFW_OFF_V01);
0537 }
0538
0539 static int ath10k_qmi_cap_send_sync_msg(struct ath10k_qmi *qmi)
0540 {
0541 struct wlfw_cap_resp_msg_v01 *resp;
0542 struct wlfw_cap_req_msg_v01 req = {};
0543 struct ath10k *ar = qmi->ar;
0544 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
0545 struct qmi_txn txn;
0546 int ret;
0547
0548 resp = kzalloc(sizeof(*resp), GFP_KERNEL);
0549 if (!resp)
0550 return -ENOMEM;
0551
0552 ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_cap_resp_msg_v01_ei, resp);
0553 if (ret < 0)
0554 goto out;
0555
0556 ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
0557 QMI_WLFW_CAP_REQ_V01,
0558 WLFW_CAP_REQ_MSG_V01_MAX_MSG_LEN,
0559 wlfw_cap_req_msg_v01_ei, &req);
0560 if (ret < 0) {
0561 qmi_txn_cancel(&txn);
0562 ath10k_err(ar, "failed to send capability request: %d\n", ret);
0563 goto out;
0564 }
0565
0566 ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
0567 if (ret < 0)
0568 goto out;
0569
0570 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
0571 ath10k_err(ar, "capability req rejected: %d\n", resp->resp.error);
0572 ret = -EINVAL;
0573 goto out;
0574 }
0575
0576 if (resp->chip_info_valid) {
0577 qmi->chip_info.chip_id = resp->chip_info.chip_id;
0578 qmi->chip_info.chip_family = resp->chip_info.chip_family;
0579 } else {
0580 qmi->chip_info.chip_id = 0xFF;
0581 }
0582
0583 if (resp->board_info_valid)
0584 qmi->board_info.board_id = resp->board_info.board_id;
0585 else
0586 qmi->board_info.board_id = 0xFF;
0587
0588 if (resp->soc_info_valid)
0589 qmi->soc_info.soc_id = resp->soc_info.soc_id;
0590
0591 if (resp->fw_version_info_valid) {
0592 qmi->fw_version = resp->fw_version_info.fw_version;
0593 strscpy(qmi->fw_build_timestamp, resp->fw_version_info.fw_build_timestamp,
0594 sizeof(qmi->fw_build_timestamp));
0595 }
0596
0597 if (resp->fw_build_id_valid)
0598 strscpy(qmi->fw_build_id, resp->fw_build_id,
0599 MAX_BUILD_ID_LEN + 1);
0600
0601 if (!test_bit(ATH10K_SNOC_FLAG_REGISTERED, &ar_snoc->flags)) {
0602 ath10k_info(ar, "qmi chip_id 0x%x chip_family 0x%x board_id 0x%x soc_id 0x%x",
0603 qmi->chip_info.chip_id, qmi->chip_info.chip_family,
0604 qmi->board_info.board_id, qmi->soc_info.soc_id);
0605 ath10k_info(ar, "qmi fw_version 0x%x fw_build_timestamp %s fw_build_id %s",
0606 qmi->fw_version, qmi->fw_build_timestamp, qmi->fw_build_id);
0607 }
0608
0609 kfree(resp);
0610 return 0;
0611
0612 out:
0613 kfree(resp);
0614 return ret;
0615 }
0616
0617 static int ath10k_qmi_host_cap_send_sync(struct ath10k_qmi *qmi)
0618 {
0619 struct wlfw_host_cap_resp_msg_v01 resp = {};
0620 struct wlfw_host_cap_req_msg_v01 req = {};
0621 struct qmi_elem_info *req_ei;
0622 struct ath10k *ar = qmi->ar;
0623 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
0624 struct qmi_txn txn;
0625 int ret;
0626
0627 req.daemon_support_valid = 1;
0628 req.daemon_support = 0;
0629
0630 ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_host_cap_resp_msg_v01_ei,
0631 &resp);
0632 if (ret < 0)
0633 goto out;
0634
0635 if (test_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags))
0636 req_ei = wlfw_host_cap_8bit_req_msg_v01_ei;
0637 else
0638 req_ei = wlfw_host_cap_req_msg_v01_ei;
0639
0640 ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
0641 QMI_WLFW_HOST_CAP_REQ_V01,
0642 WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN,
0643 req_ei, &req);
0644 if (ret < 0) {
0645 qmi_txn_cancel(&txn);
0646 ath10k_err(ar, "failed to send host capability request: %d\n", ret);
0647 goto out;
0648 }
0649
0650 ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
0651 if (ret < 0)
0652 goto out;
0653
0654
0655 if (resp.resp.result != QMI_RESULT_SUCCESS_V01 &&
0656 resp.resp.error != QMI_ERR_NOT_SUPPORTED_V01) {
0657 ath10k_err(ar, "host capability request rejected: %d\n", resp.resp.error);
0658 ret = -EINVAL;
0659 goto out;
0660 }
0661
0662 ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi host capability request completed\n");
0663 return 0;
0664
0665 out:
0666 return ret;
0667 }
0668
0669 int ath10k_qmi_set_fw_log_mode(struct ath10k *ar, u8 fw_log_mode)
0670 {
0671 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
0672 struct wlfw_ini_resp_msg_v01 resp = {};
0673 struct ath10k_qmi *qmi = ar_snoc->qmi;
0674 struct wlfw_ini_req_msg_v01 req = {};
0675 struct qmi_txn txn;
0676 int ret;
0677
0678 req.enablefwlog_valid = 1;
0679 req.enablefwlog = fw_log_mode;
0680
0681 ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_ini_resp_msg_v01_ei,
0682 &resp);
0683 if (ret < 0)
0684 goto out;
0685
0686 ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
0687 QMI_WLFW_INI_REQ_V01,
0688 WLFW_INI_REQ_MSG_V01_MAX_MSG_LEN,
0689 wlfw_ini_req_msg_v01_ei, &req);
0690 if (ret < 0) {
0691 qmi_txn_cancel(&txn);
0692 ath10k_err(ar, "failed to send fw log request: %d\n", ret);
0693 goto out;
0694 }
0695
0696 ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
0697 if (ret < 0)
0698 goto out;
0699
0700 if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
0701 ath10k_err(ar, "fw log request rejected: %d\n",
0702 resp.resp.error);
0703 ret = -EINVAL;
0704 goto out;
0705 }
0706 ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi fw log request completed, mode: %d\n",
0707 fw_log_mode);
0708 return 0;
0709
0710 out:
0711 return ret;
0712 }
0713
0714 static int
0715 ath10k_qmi_ind_register_send_sync_msg(struct ath10k_qmi *qmi)
0716 {
0717 struct wlfw_ind_register_resp_msg_v01 resp = {};
0718 struct wlfw_ind_register_req_msg_v01 req = {};
0719 struct ath10k *ar = qmi->ar;
0720 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
0721 struct qmi_txn txn;
0722 int ret;
0723
0724 req.client_id_valid = 1;
0725 req.client_id = ATH10K_QMI_CLIENT_ID;
0726 req.fw_ready_enable_valid = 1;
0727 req.fw_ready_enable = 1;
0728 req.msa_ready_enable_valid = 1;
0729 req.msa_ready_enable = 1;
0730
0731 if (ar_snoc->xo_cal_supported) {
0732 req.xo_cal_enable_valid = 1;
0733 req.xo_cal_enable = 1;
0734 }
0735
0736 ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
0737 wlfw_ind_register_resp_msg_v01_ei, &resp);
0738 if (ret < 0)
0739 goto out;
0740
0741 ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
0742 QMI_WLFW_IND_REGISTER_REQ_V01,
0743 WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN,
0744 wlfw_ind_register_req_msg_v01_ei, &req);
0745 if (ret < 0) {
0746 qmi_txn_cancel(&txn);
0747 ath10k_err(ar, "failed to send indication registered request: %d\n", ret);
0748 goto out;
0749 }
0750
0751 ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
0752 if (ret < 0)
0753 goto out;
0754
0755 if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
0756 ath10k_err(ar, "indication request rejected: %d\n", resp.resp.error);
0757 ret = -EINVAL;
0758 goto out;
0759 }
0760
0761 if (resp.fw_status_valid) {
0762 if (resp.fw_status & QMI_WLFW_FW_READY_V01)
0763 qmi->fw_ready = true;
0764 }
0765 ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi indication register request completed\n");
0766 return 0;
0767
0768 out:
0769 return ret;
0770 }
0771
0772 static void ath10k_qmi_event_server_arrive(struct ath10k_qmi *qmi)
0773 {
0774 struct ath10k *ar = qmi->ar;
0775 int ret;
0776
0777 ret = ath10k_qmi_ind_register_send_sync_msg(qmi);
0778 if (ret)
0779 return;
0780
0781 if (qmi->fw_ready) {
0782 ath10k_snoc_fw_indication(ar, ATH10K_QMI_EVENT_FW_READY_IND);
0783 return;
0784 }
0785
0786 ret = ath10k_qmi_host_cap_send_sync(qmi);
0787 if (ret)
0788 return;
0789
0790 ret = ath10k_qmi_msa_mem_info_send_sync_msg(qmi);
0791 if (ret)
0792 return;
0793
0794
0795
0796
0797
0798
0799 msleep(20);
0800
0801 ret = ath10k_qmi_setup_msa_permissions(qmi);
0802 if (ret)
0803 return;
0804
0805 ret = ath10k_qmi_msa_ready_send_sync_msg(qmi);
0806 if (ret)
0807 goto err_setup_msa;
0808
0809 ret = ath10k_qmi_cap_send_sync_msg(qmi);
0810 if (ret)
0811 goto err_setup_msa;
0812
0813 return;
0814
0815 err_setup_msa:
0816 ath10k_qmi_remove_msa_permission(qmi);
0817 }
0818
0819 static int ath10k_qmi_fetch_board_file(struct ath10k_qmi *qmi)
0820 {
0821 struct ath10k *ar = qmi->ar;
0822 int ret;
0823
0824 ar->hif.bus = ATH10K_BUS_SNOC;
0825 ar->id.qmi_ids_valid = true;
0826 ar->id.qmi_board_id = qmi->board_info.board_id;
0827 ar->id.qmi_chip_id = qmi->chip_info.chip_id;
0828 ar->hw_params.fw.dir = WCN3990_HW_1_0_FW_DIR;
0829
0830 ret = ath10k_core_check_dt(ar);
0831 if (ret)
0832 ath10k_dbg(ar, ATH10K_DBG_QMI, "DT bdf variant name not set.\n");
0833
0834 return ath10k_core_fetch_board_file(qmi->ar, ATH10K_BD_IE_BOARD);
0835 }
0836
0837 static int
0838 ath10k_qmi_driver_event_post(struct ath10k_qmi *qmi,
0839 enum ath10k_qmi_driver_event_type type,
0840 void *data)
0841 {
0842 struct ath10k_qmi_driver_event *event;
0843
0844 event = kzalloc(sizeof(*event), GFP_ATOMIC);
0845 if (!event)
0846 return -ENOMEM;
0847
0848 event->type = type;
0849 event->data = data;
0850
0851 spin_lock(&qmi->event_lock);
0852 list_add_tail(&event->list, &qmi->event_list);
0853 spin_unlock(&qmi->event_lock);
0854
0855 queue_work(qmi->event_wq, &qmi->event_work);
0856
0857 return 0;
0858 }
0859
0860 static void ath10k_qmi_event_server_exit(struct ath10k_qmi *qmi)
0861 {
0862 struct ath10k *ar = qmi->ar;
0863 struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
0864
0865 ath10k_qmi_remove_msa_permission(qmi);
0866 ath10k_core_free_board_files(ar);
0867 if (!test_bit(ATH10K_SNOC_FLAG_UNREGISTERING, &ar_snoc->flags) &&
0868 !test_bit(ATH10K_SNOC_FLAG_MODEM_STOPPED, &ar_snoc->flags))
0869 ath10k_snoc_fw_crashed_dump(ar);
0870
0871 ath10k_snoc_fw_indication(ar, ATH10K_QMI_EVENT_FW_DOWN_IND);
0872 ath10k_dbg(ar, ATH10K_DBG_QMI, "wifi fw qmi service disconnected\n");
0873 }
0874
0875 static void ath10k_qmi_event_msa_ready(struct ath10k_qmi *qmi)
0876 {
0877 int ret;
0878
0879 ret = ath10k_qmi_fetch_board_file(qmi);
0880 if (ret)
0881 goto out;
0882
0883 ret = ath10k_qmi_bdf_dnld_send_sync(qmi);
0884 if (ret)
0885 goto out;
0886
0887 ret = ath10k_qmi_send_cal_report_req(qmi);
0888
0889 out:
0890 return;
0891 }
0892
0893 static int ath10k_qmi_event_fw_ready_ind(struct ath10k_qmi *qmi)
0894 {
0895 struct ath10k *ar = qmi->ar;
0896
0897 ath10k_dbg(ar, ATH10K_DBG_QMI, "wifi fw ready event received\n");
0898 ath10k_snoc_fw_indication(ar, ATH10K_QMI_EVENT_FW_READY_IND);
0899
0900 return 0;
0901 }
0902
0903 static void ath10k_qmi_fw_ready_ind(struct qmi_handle *qmi_hdl,
0904 struct sockaddr_qrtr *sq,
0905 struct qmi_txn *txn, const void *data)
0906 {
0907 struct ath10k_qmi *qmi = container_of(qmi_hdl, struct ath10k_qmi, qmi_hdl);
0908
0909 ath10k_qmi_driver_event_post(qmi, ATH10K_QMI_EVENT_FW_READY_IND, NULL);
0910 }
0911
0912 static void ath10k_qmi_msa_ready_ind(struct qmi_handle *qmi_hdl,
0913 struct sockaddr_qrtr *sq,
0914 struct qmi_txn *txn, const void *data)
0915 {
0916 struct ath10k_qmi *qmi = container_of(qmi_hdl, struct ath10k_qmi, qmi_hdl);
0917
0918 ath10k_qmi_driver_event_post(qmi, ATH10K_QMI_EVENT_MSA_READY_IND, NULL);
0919 }
0920
0921 static const struct qmi_msg_handler qmi_msg_handler[] = {
0922 {
0923 .type = QMI_INDICATION,
0924 .msg_id = QMI_WLFW_FW_READY_IND_V01,
0925 .ei = wlfw_fw_ready_ind_msg_v01_ei,
0926 .decoded_size = sizeof(struct wlfw_fw_ready_ind_msg_v01),
0927 .fn = ath10k_qmi_fw_ready_ind,
0928 },
0929 {
0930 .type = QMI_INDICATION,
0931 .msg_id = QMI_WLFW_MSA_READY_IND_V01,
0932 .ei = wlfw_msa_ready_ind_msg_v01_ei,
0933 .decoded_size = sizeof(struct wlfw_msa_ready_ind_msg_v01),
0934 .fn = ath10k_qmi_msa_ready_ind,
0935 },
0936 {}
0937 };
0938
0939 static int ath10k_qmi_new_server(struct qmi_handle *qmi_hdl,
0940 struct qmi_service *service)
0941 {
0942 struct ath10k_qmi *qmi = container_of(qmi_hdl, struct ath10k_qmi, qmi_hdl);
0943 struct sockaddr_qrtr *sq = &qmi->sq;
0944 struct ath10k *ar = qmi->ar;
0945 int ret;
0946
0947 sq->sq_family = AF_QIPCRTR;
0948 sq->sq_node = service->node;
0949 sq->sq_port = service->port;
0950
0951 ath10k_dbg(ar, ATH10K_DBG_QMI, "wifi fw qmi service found\n");
0952
0953 ret = kernel_connect(qmi_hdl->sock, (struct sockaddr *)&qmi->sq,
0954 sizeof(qmi->sq), 0);
0955 if (ret) {
0956 ath10k_err(ar, "failed to connect to a remote QMI service port\n");
0957 return ret;
0958 }
0959
0960 ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi wifi fw qmi service connected\n");
0961 ath10k_qmi_driver_event_post(qmi, ATH10K_QMI_EVENT_SERVER_ARRIVE, NULL);
0962
0963 return ret;
0964 }
0965
0966 static void ath10k_qmi_del_server(struct qmi_handle *qmi_hdl,
0967 struct qmi_service *service)
0968 {
0969 struct ath10k_qmi *qmi =
0970 container_of(qmi_hdl, struct ath10k_qmi, qmi_hdl);
0971
0972 qmi->fw_ready = false;
0973
0974
0975
0976
0977
0978
0979
0980 if (qmi->state == ATH10K_QMI_STATE_INIT_DONE)
0981 ath10k_qmi_driver_event_post(qmi, ATH10K_QMI_EVENT_SERVER_EXIT,
0982 NULL);
0983 }
0984
0985 static const struct qmi_ops ath10k_qmi_ops = {
0986 .new_server = ath10k_qmi_new_server,
0987 .del_server = ath10k_qmi_del_server,
0988 };
0989
0990 static void ath10k_qmi_driver_event_work(struct work_struct *work)
0991 {
0992 struct ath10k_qmi *qmi = container_of(work, struct ath10k_qmi,
0993 event_work);
0994 struct ath10k_qmi_driver_event *event;
0995 struct ath10k *ar = qmi->ar;
0996
0997 spin_lock(&qmi->event_lock);
0998 while (!list_empty(&qmi->event_list)) {
0999 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
1027 int 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
1070 err_qmi_lookup:
1071 destroy_workqueue(qmi->event_wq);
1072
1073 err_release_qmi_handle:
1074 qmi_handle_release(&qmi->qmi_hdl);
1075
1076 err:
1077 kfree(qmi);
1078 return ret;
1079 }
1080
1081 int 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 }