root/drivers/net/wireless/ath/ath10k/qmi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ath10k_qmi_map_msa_permission
  2. ath10k_qmi_unmap_msa_permission
  3. ath10k_qmi_setup_msa_permissions
  4. ath10k_qmi_remove_msa_permission
  5. ath10k_qmi_msa_mem_info_send_sync_msg
  6. ath10k_qmi_msa_ready_send_sync_msg
  7. ath10k_qmi_bdf_dnld_send_sync
  8. ath10k_qmi_send_cal_report_req
  9. ath10k_qmi_mode_send_sync_msg
  10. ath10k_qmi_cfg_send_sync_msg
  11. ath10k_qmi_wlan_enable
  12. ath10k_qmi_wlan_disable
  13. ath10k_qmi_cap_send_sync_msg
  14. ath10k_qmi_host_cap_send_sync
  15. ath10k_qmi_set_fw_log_mode
  16. ath10k_qmi_ind_register_send_sync_msg
  17. ath10k_qmi_event_server_arrive
  18. ath10k_qmi_fetch_board_file
  19. ath10k_qmi_driver_event_post
  20. ath10k_qmi_event_server_exit
  21. ath10k_qmi_event_msa_ready
  22. ath10k_qmi_event_fw_ready_ind
  23. ath10k_qmi_fw_ready_ind
  24. ath10k_qmi_msa_ready_ind
  25. ath10k_qmi_new_server
  26. ath10k_qmi_del_server
  27. ath10k_qmi_driver_event_work
  28. ath10k_qmi_setup_msa_resources
  29. ath10k_qmi_init
  30. ath10k_qmi_deinit

   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 
  26 static 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 
  58 static 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 
  82 static 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 
  95 err_unmap:
  96         for (i--; i >= 0; i--)
  97                 ath10k_qmi_unmap_msa_permission(qmi, &qmi->mem_region[i]);
  98         return ret;
  99 }
 100 
 101 static 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 
 109 static 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 
 168 out:
 169         return ret;
 170 }
 171 
 172 static 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 
 207 out:
 208         return ret;
 209 }
 210 
 211 static 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 
 284 out:
 285         kfree(req);
 286         return ret;
 287 }
 288 
 289 static 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 
 335 out:
 336         return ret;
 337 }
 338 
 339 static int
 340 ath10k_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 
 382 out:
 383         return ret;
 384 }
 385 
 386 static int
 387 ath10k_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 
 469 out:
 470         kfree(req);
 471         return ret;
 472 }
 473 
 474 int 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 
 499 int ath10k_qmi_wlan_disable(struct ath10k *ar)
 500 {
 501         return ath10k_qmi_mode_send_sync_msg(ar, QMI_WLFW_OFF_V01);
 502 }
 503 
 504 static 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 
 575 out:
 576         kfree(resp);
 577         return ret;
 578 }
 579 
 580 static 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 qmi_elem_info *req_ei;
 585         struct ath10k *ar = qmi->ar;
 586         struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
 587         struct qmi_txn txn;
 588         int ret;
 589 
 590         req.daemon_support_valid = 1;
 591         req.daemon_support = 0;
 592 
 593         ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_host_cap_resp_msg_v01_ei,
 594                            &resp);
 595         if (ret < 0)
 596                 goto out;
 597 
 598         if (test_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags))
 599                 req_ei = wlfw_host_cap_8bit_req_msg_v01_ei;
 600         else
 601                 req_ei = wlfw_host_cap_req_msg_v01_ei;
 602 
 603         ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
 604                                QMI_WLFW_HOST_CAP_REQ_V01,
 605                                WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN,
 606                                req_ei, &req);
 607         if (ret < 0) {
 608                 qmi_txn_cancel(&txn);
 609                 ath10k_err(ar, "failed to send host capability request: %d\n", ret);
 610                 goto out;
 611         }
 612 
 613         ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
 614         if (ret < 0)
 615                 goto out;
 616 
 617         if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
 618                 ath10k_err(ar, "host capability request rejected: %d\n", resp.resp.error);
 619                 ret = -EINVAL;
 620                 goto out;
 621         }
 622 
 623         ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi host capability request completed\n");
 624         return 0;
 625 
 626 out:
 627         return ret;
 628 }
 629 
 630 int ath10k_qmi_set_fw_log_mode(struct ath10k *ar, u8 fw_log_mode)
 631 {
 632         struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
 633         struct wlfw_ini_resp_msg_v01 resp = {};
 634         struct ath10k_qmi *qmi = ar_snoc->qmi;
 635         struct wlfw_ini_req_msg_v01 req = {};
 636         struct qmi_txn txn;
 637         int ret;
 638 
 639         req.enablefwlog_valid = 1;
 640         req.enablefwlog = fw_log_mode;
 641 
 642         ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_ini_resp_msg_v01_ei,
 643                            &resp);
 644         if (ret < 0)
 645                 goto out;
 646 
 647         ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
 648                                QMI_WLFW_INI_REQ_V01,
 649                                WLFW_INI_REQ_MSG_V01_MAX_MSG_LEN,
 650                                wlfw_ini_req_msg_v01_ei, &req);
 651         if (ret < 0) {
 652                 qmi_txn_cancel(&txn);
 653                 ath10k_err(ar, "fail to send fw log reqest: %d\n", ret);
 654                 goto out;
 655         }
 656 
 657         ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
 658         if (ret < 0)
 659                 goto out;
 660 
 661         if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
 662                 ath10k_err(ar, "fw log request rejectedr: %d\n",
 663                            resp.resp.error);
 664                 ret = -EINVAL;
 665                 goto out;
 666         }
 667         ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi fw log request completed, mode: %d\n",
 668                    fw_log_mode);
 669         return 0;
 670 
 671 out:
 672         return ret;
 673 }
 674 
 675 static int
 676 ath10k_qmi_ind_register_send_sync_msg(struct ath10k_qmi *qmi)
 677 {
 678         struct wlfw_ind_register_resp_msg_v01 resp = {};
 679         struct wlfw_ind_register_req_msg_v01 req = {};
 680         struct ath10k *ar = qmi->ar;
 681         struct qmi_txn txn;
 682         int ret;
 683 
 684         req.client_id_valid = 1;
 685         req.client_id = ATH10K_QMI_CLIENT_ID;
 686         req.fw_ready_enable_valid = 1;
 687         req.fw_ready_enable = 1;
 688         req.msa_ready_enable_valid = 1;
 689         req.msa_ready_enable = 1;
 690 
 691         ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
 692                            wlfw_ind_register_resp_msg_v01_ei, &resp);
 693         if (ret < 0)
 694                 goto out;
 695 
 696         ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
 697                                QMI_WLFW_IND_REGISTER_REQ_V01,
 698                                WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN,
 699                                wlfw_ind_register_req_msg_v01_ei, &req);
 700         if (ret < 0) {
 701                 qmi_txn_cancel(&txn);
 702                 ath10k_err(ar, "failed to send indication registered request: %d\n", ret);
 703                 goto out;
 704         }
 705 
 706         ret = qmi_txn_wait(&txn, ATH10K_QMI_TIMEOUT * HZ);
 707         if (ret < 0)
 708                 goto out;
 709 
 710         if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
 711                 ath10k_err(ar, "indication request rejected: %d\n", resp.resp.error);
 712                 ret = -EINVAL;
 713                 goto out;
 714         }
 715 
 716         if (resp.fw_status_valid) {
 717                 if (resp.fw_status & QMI_WLFW_FW_READY_V01)
 718                         qmi->fw_ready = true;
 719         }
 720         ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi indication register request completed\n");
 721         return 0;
 722 
 723 out:
 724         return ret;
 725 }
 726 
 727 static void ath10k_qmi_event_server_arrive(struct ath10k_qmi *qmi)
 728 {
 729         struct ath10k *ar = qmi->ar;
 730         int ret;
 731 
 732         ret = ath10k_qmi_ind_register_send_sync_msg(qmi);
 733         if (ret)
 734                 return;
 735 
 736         if (qmi->fw_ready) {
 737                 ath10k_snoc_fw_indication(ar, ATH10K_QMI_EVENT_FW_READY_IND);
 738                 return;
 739         }
 740 
 741         ret = ath10k_qmi_host_cap_send_sync(qmi);
 742         if (ret)
 743                 return;
 744 
 745         ret = ath10k_qmi_msa_mem_info_send_sync_msg(qmi);
 746         if (ret)
 747                 return;
 748 
 749         ret = ath10k_qmi_setup_msa_permissions(qmi);
 750         if (ret)
 751                 return;
 752 
 753         ret = ath10k_qmi_msa_ready_send_sync_msg(qmi);
 754         if (ret)
 755                 goto err_setup_msa;
 756 
 757         ret = ath10k_qmi_cap_send_sync_msg(qmi);
 758         if (ret)
 759                 goto err_setup_msa;
 760 
 761         return;
 762 
 763 err_setup_msa:
 764         ath10k_qmi_remove_msa_permission(qmi);
 765 }
 766 
 767 static int ath10k_qmi_fetch_board_file(struct ath10k_qmi *qmi)
 768 {
 769         struct ath10k *ar = qmi->ar;
 770 
 771         ar->hif.bus = ATH10K_BUS_SNOC;
 772         ar->id.qmi_ids_valid = true;
 773         ar->id.qmi_board_id = qmi->board_info.board_id;
 774         ar->hw_params.fw.dir = WCN3990_HW_1_0_FW_DIR;
 775 
 776         return ath10k_core_fetch_board_file(qmi->ar, ATH10K_BD_IE_BOARD);
 777 }
 778 
 779 static int
 780 ath10k_qmi_driver_event_post(struct ath10k_qmi *qmi,
 781                              enum ath10k_qmi_driver_event_type type,
 782                              void *data)
 783 {
 784         struct ath10k_qmi_driver_event *event;
 785 
 786         event = kzalloc(sizeof(*event), GFP_ATOMIC);
 787         if (!event)
 788                 return -ENOMEM;
 789 
 790         event->type = type;
 791         event->data = data;
 792 
 793         spin_lock(&qmi->event_lock);
 794         list_add_tail(&event->list, &qmi->event_list);
 795         spin_unlock(&qmi->event_lock);
 796 
 797         queue_work(qmi->event_wq, &qmi->event_work);
 798 
 799         return 0;
 800 }
 801 
 802 static void ath10k_qmi_event_server_exit(struct ath10k_qmi *qmi)
 803 {
 804         struct ath10k *ar = qmi->ar;
 805 
 806         ath10k_qmi_remove_msa_permission(qmi);
 807         ath10k_core_free_board_files(ar);
 808         ath10k_snoc_fw_indication(ar, ATH10K_QMI_EVENT_FW_DOWN_IND);
 809         ath10k_dbg(ar, ATH10K_DBG_QMI, "wifi fw qmi service disconnected\n");
 810 }
 811 
 812 static void ath10k_qmi_event_msa_ready(struct ath10k_qmi *qmi)
 813 {
 814         int ret;
 815 
 816         ret = ath10k_qmi_fetch_board_file(qmi);
 817         if (ret)
 818                 goto out;
 819 
 820         ret = ath10k_qmi_bdf_dnld_send_sync(qmi);
 821         if (ret)
 822                 goto out;
 823 
 824         ret = ath10k_qmi_send_cal_report_req(qmi);
 825 
 826 out:
 827         return;
 828 }
 829 
 830 static int ath10k_qmi_event_fw_ready_ind(struct ath10k_qmi *qmi)
 831 {
 832         struct ath10k *ar = qmi->ar;
 833 
 834         ath10k_dbg(ar, ATH10K_DBG_QMI, "wifi fw ready event received\n");
 835         ath10k_snoc_fw_indication(ar, ATH10K_QMI_EVENT_FW_READY_IND);
 836 
 837         return 0;
 838 }
 839 
 840 static void ath10k_qmi_fw_ready_ind(struct qmi_handle *qmi_hdl,
 841                                     struct sockaddr_qrtr *sq,
 842                                     struct qmi_txn *txn, const void *data)
 843 {
 844         struct ath10k_qmi *qmi = container_of(qmi_hdl, struct ath10k_qmi, qmi_hdl);
 845 
 846         ath10k_qmi_driver_event_post(qmi, ATH10K_QMI_EVENT_FW_READY_IND, NULL);
 847 }
 848 
 849 static void ath10k_qmi_msa_ready_ind(struct qmi_handle *qmi_hdl,
 850                                      struct sockaddr_qrtr *sq,
 851                                      struct qmi_txn *txn, const void *data)
 852 {
 853         struct ath10k_qmi *qmi = container_of(qmi_hdl, struct ath10k_qmi, qmi_hdl);
 854 
 855         ath10k_qmi_driver_event_post(qmi, ATH10K_QMI_EVENT_MSA_READY_IND, NULL);
 856 }
 857 
 858 static struct qmi_msg_handler qmi_msg_handler[] = {
 859         {
 860                 .type = QMI_INDICATION,
 861                 .msg_id = QMI_WLFW_FW_READY_IND_V01,
 862                 .ei = wlfw_fw_ready_ind_msg_v01_ei,
 863                 .decoded_size = sizeof(struct wlfw_fw_ready_ind_msg_v01),
 864                 .fn = ath10k_qmi_fw_ready_ind,
 865         },
 866         {
 867                 .type = QMI_INDICATION,
 868                 .msg_id = QMI_WLFW_MSA_READY_IND_V01,
 869                 .ei = wlfw_msa_ready_ind_msg_v01_ei,
 870                 .decoded_size = sizeof(struct wlfw_msa_ready_ind_msg_v01),
 871                 .fn = ath10k_qmi_msa_ready_ind,
 872         },
 873         {}
 874 };
 875 
 876 static int ath10k_qmi_new_server(struct qmi_handle *qmi_hdl,
 877                                  struct qmi_service *service)
 878 {
 879         struct ath10k_qmi *qmi = container_of(qmi_hdl, struct ath10k_qmi, qmi_hdl);
 880         struct sockaddr_qrtr *sq = &qmi->sq;
 881         struct ath10k *ar = qmi->ar;
 882         int ret;
 883 
 884         sq->sq_family = AF_QIPCRTR;
 885         sq->sq_node = service->node;
 886         sq->sq_port = service->port;
 887 
 888         ath10k_dbg(ar, ATH10K_DBG_QMI, "wifi fw qmi service found\n");
 889 
 890         ret = kernel_connect(qmi_hdl->sock, (struct sockaddr *)&qmi->sq,
 891                              sizeof(qmi->sq), 0);
 892         if (ret) {
 893                 ath10k_err(ar, "failed to connect to a remote QMI service port\n");
 894                 return ret;
 895         }
 896 
 897         ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi wifi fw qmi service connected\n");
 898         ath10k_qmi_driver_event_post(qmi, ATH10K_QMI_EVENT_SERVER_ARRIVE, NULL);
 899 
 900         return ret;
 901 }
 902 
 903 static void ath10k_qmi_del_server(struct qmi_handle *qmi_hdl,
 904                                   struct qmi_service *service)
 905 {
 906         struct ath10k_qmi *qmi =
 907                 container_of(qmi_hdl, struct ath10k_qmi, qmi_hdl);
 908 
 909         qmi->fw_ready = false;
 910         ath10k_qmi_driver_event_post(qmi, ATH10K_QMI_EVENT_SERVER_EXIT, NULL);
 911 }
 912 
 913 static struct qmi_ops ath10k_qmi_ops = {
 914         .new_server = ath10k_qmi_new_server,
 915         .del_server = ath10k_qmi_del_server,
 916 };
 917 
 918 static void ath10k_qmi_driver_event_work(struct work_struct *work)
 919 {
 920         struct ath10k_qmi *qmi = container_of(work, struct ath10k_qmi,
 921                                               event_work);
 922         struct ath10k_qmi_driver_event *event;
 923         struct ath10k *ar = qmi->ar;
 924 
 925         spin_lock(&qmi->event_lock);
 926         while (!list_empty(&qmi->event_list)) {
 927                 event = list_first_entry(&qmi->event_list,
 928                                          struct ath10k_qmi_driver_event, list);
 929                 list_del(&event->list);
 930                 spin_unlock(&qmi->event_lock);
 931 
 932                 switch (event->type) {
 933                 case ATH10K_QMI_EVENT_SERVER_ARRIVE:
 934                         ath10k_qmi_event_server_arrive(qmi);
 935                         break;
 936                 case ATH10K_QMI_EVENT_SERVER_EXIT:
 937                         ath10k_qmi_event_server_exit(qmi);
 938                         break;
 939                 case ATH10K_QMI_EVENT_FW_READY_IND:
 940                         ath10k_qmi_event_fw_ready_ind(qmi);
 941                         break;
 942                 case ATH10K_QMI_EVENT_MSA_READY_IND:
 943                         ath10k_qmi_event_msa_ready(qmi);
 944                         break;
 945                 default:
 946                         ath10k_warn(ar, "invalid event type: %d", event->type);
 947                         break;
 948                 }
 949                 kfree(event);
 950                 spin_lock(&qmi->event_lock);
 951         }
 952         spin_unlock(&qmi->event_lock);
 953 }
 954 
 955 static int ath10k_qmi_setup_msa_resources(struct ath10k_qmi *qmi, u32 msa_size)
 956 {
 957         struct ath10k *ar = qmi->ar;
 958         struct device *dev = ar->dev;
 959         struct device_node *node;
 960         struct resource r;
 961         int ret;
 962 
 963         node = of_parse_phandle(dev->of_node, "memory-region", 0);
 964         if (node) {
 965                 ret = of_address_to_resource(node, 0, &r);
 966                 if (ret) {
 967                         dev_err(dev, "failed to resolve msa fixed region\n");
 968                         return ret;
 969                 }
 970                 of_node_put(node);
 971 
 972                 qmi->msa_pa = r.start;
 973                 qmi->msa_mem_size = resource_size(&r);
 974                 qmi->msa_va = devm_memremap(dev, qmi->msa_pa, qmi->msa_mem_size,
 975                                             MEMREMAP_WT);
 976                 if (IS_ERR(qmi->msa_va)) {
 977                         dev_err(dev, "failed to map memory region: %pa\n", &r.start);
 978                         return PTR_ERR(qmi->msa_va);
 979                 }
 980         } else {
 981                 qmi->msa_va = dmam_alloc_coherent(dev, msa_size,
 982                                                   &qmi->msa_pa, GFP_KERNEL);
 983                 if (!qmi->msa_va) {
 984                         ath10k_err(ar, "failed to allocate dma memory for msa region\n");
 985                         return -ENOMEM;
 986                 }
 987                 qmi->msa_mem_size = msa_size;
 988         }
 989 
 990         ath10k_dbg(ar, ATH10K_DBG_QMI, "msa pa: %pad , msa va: 0x%p\n",
 991                    &qmi->msa_pa,
 992                    qmi->msa_va);
 993 
 994         return 0;
 995 }
 996 
 997 int ath10k_qmi_init(struct ath10k *ar, u32 msa_size)
 998 {
 999         struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
1000         struct ath10k_qmi *qmi;
1001         int ret;
1002 
1003         qmi = kzalloc(sizeof(*qmi), GFP_KERNEL);
1004         if (!qmi)
1005                 return -ENOMEM;
1006 
1007         qmi->ar = ar;
1008         ar_snoc->qmi = qmi;
1009 
1010         ret = ath10k_qmi_setup_msa_resources(qmi, msa_size);
1011         if (ret)
1012                 goto err;
1013 
1014         ret = qmi_handle_init(&qmi->qmi_hdl,
1015                               WLFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN,
1016                               &ath10k_qmi_ops, qmi_msg_handler);
1017         if (ret)
1018                 goto err;
1019 
1020         qmi->event_wq = alloc_workqueue("ath10k_qmi_driver_event",
1021                                         WQ_UNBOUND, 1);
1022         if (!qmi->event_wq) {
1023                 ath10k_err(ar, "failed to allocate workqueue\n");
1024                 ret = -EFAULT;
1025                 goto err_release_qmi_handle;
1026         }
1027 
1028         INIT_LIST_HEAD(&qmi->event_list);
1029         spin_lock_init(&qmi->event_lock);
1030         INIT_WORK(&qmi->event_work, ath10k_qmi_driver_event_work);
1031 
1032         ret = qmi_add_lookup(&qmi->qmi_hdl, WLFW_SERVICE_ID_V01,
1033                              WLFW_SERVICE_VERS_V01, 0);
1034         if (ret)
1035                 goto err_qmi_lookup;
1036 
1037         return 0;
1038 
1039 err_qmi_lookup:
1040         destroy_workqueue(qmi->event_wq);
1041 
1042 err_release_qmi_handle:
1043         qmi_handle_release(&qmi->qmi_hdl);
1044 
1045 err:
1046         kfree(qmi);
1047         return ret;
1048 }
1049 
1050 int ath10k_qmi_deinit(struct ath10k *ar)
1051 {
1052         struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
1053         struct ath10k_qmi *qmi = ar_snoc->qmi;
1054 
1055         qmi_handle_release(&qmi->qmi_hdl);
1056         cancel_work_sync(&qmi->event_work);
1057         destroy_workqueue(qmi->event_wq);
1058         kfree(qmi);
1059         ar_snoc->qmi = NULL;
1060 
1061         return 0;
1062 }

/* [<][>][^][v][top][bottom][index][help] */