linux/drivers/net/wireless/ath/ath10k/qmi.c
<<
>>
Prefs
   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}
1056