1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 5 */ 6 7 #include <linux/module.h> 8 #include <linux/soc/qcom/qmi.h> 9 10 #include "bus.h" 11 #include "debug.h" 12 #include "main.h" 13 #include "qmi.h" 14 #include "genl.h" 15 16 #define WLFW_SERVICE_INS_ID_V01 1 17 #define WLFW_CLIENT_ID 0x4b4e454c 18 #define BDF_FILE_NAME_PREFIX "bdwlan" 19 #define ELF_BDF_FILE_NAME "bdwlan.elf" 20 #define ELF_BDF_FILE_NAME_GF "bdwlang.elf" 21 #define ELF_BDF_FILE_NAME_PREFIX "bdwlan.e" 22 #define ELF_BDF_FILE_NAME_GF_PREFIX "bdwlang.e" 23 #define BIN_BDF_FILE_NAME "bdwlan.bin" 24 #define BIN_BDF_FILE_NAME_GF "bdwlang.bin" 25 #define BIN_BDF_FILE_NAME_PREFIX "bdwlan.b" 26 #define BIN_BDF_FILE_NAME_GF_PREFIX "bdwlang.b" 27 #define REGDB_FILE_NAME "regdb.bin" 28 #define HDS_FILE_NAME "hds.bin" 29 #define CHIP_ID_GF_MASK 0x10 30 31 #define CONN_ROAM_FILE_NAME "wlan-connection-roaming" 32 #define INI_EXT ".ini" 33 #define INI_FILE_NAME_LEN 100 34 35 #define QDSS_TRACE_CONFIG_FILE "qdss_trace_config" 36 #ifdef CONFIG_CNSS2_DEBUG 37 #define QDSS_DEBUG_FILE_STR "debug_" 38 #else 39 #define QDSS_DEBUG_FILE_STR "" 40 #endif 41 #define HW_V1_NUMBER "v1" 42 #define HW_V2_NUMBER "v2" 43 #define CE_MSI_NAME "CE" 44 45 #define QMI_WLFW_TIMEOUT_MS (plat_priv->ctrl_params.qmi_timeout) 46 #define QMI_WLFW_TIMEOUT_JF msecs_to_jiffies(QMI_WLFW_TIMEOUT_MS) 47 #define COEX_TIMEOUT QMI_WLFW_TIMEOUT_JF 48 #define IMS_TIMEOUT QMI_WLFW_TIMEOUT_JF 49 50 #define QMI_WLFW_MAX_RECV_BUF_SIZE SZ_8K 51 #define IMSPRIVATE_SERVICE_MAX_MSG_LEN SZ_8K 52 #define DMS_QMI_MAX_MSG_LEN SZ_256 53 #define MAX_SHADOW_REG_RESERVED 2 54 #define MAX_NUM_SHADOW_REG_V3 (QMI_WLFW_MAX_NUM_SHADOW_REG_V3_USAGE_V01 - \ 55 MAX_SHADOW_REG_RESERVED) 56 57 #define QMI_WLFW_MAC_READY_TIMEOUT_MS 50 58 #define QMI_WLFW_MAC_READY_MAX_RETRY 200 59 60 enum nm_modem_bit { 61 SLEEP_CLOCK_SELECT_INTERNAL_BIT = BIT(1), 62 HOST_CSTATE_BIT = BIT(2), 63 }; 64 65 #ifdef CONFIG_CNSS2_DEBUG 66 static bool ignore_qmi_failure; 67 #define CNSS_QMI_ASSERT() CNSS_ASSERT(ignore_qmi_failure) 68 void cnss_ignore_qmi_failure(bool ignore) 69 { 70 ignore_qmi_failure = ignore; 71 } 72 #else 73 #define CNSS_QMI_ASSERT() do { } while (0) 74 void cnss_ignore_qmi_failure(bool ignore) { } 75 #endif 76 77 static char *cnss_qmi_mode_to_str(enum cnss_driver_mode mode) 78 { 79 switch (mode) { 80 case CNSS_MISSION: 81 return "MISSION"; 82 case CNSS_FTM: 83 return "FTM"; 84 case CNSS_EPPING: 85 return "EPPING"; 86 case CNSS_WALTEST: 87 return "WALTEST"; 88 case CNSS_OFF: 89 return "OFF"; 90 case CNSS_CCPM: 91 return "CCPM"; 92 case CNSS_QVIT: 93 return "QVIT"; 94 case CNSS_CALIBRATION: 95 return "CALIBRATION"; 96 default: 97 return "UNKNOWN"; 98 } 99 } 100 101 static int qmi_send_wait(struct qmi_handle *qmi, void *req, void *rsp, 102 struct qmi_elem_info *req_ei, 103 struct qmi_elem_info *rsp_ei, 104 int req_id, size_t req_len, 105 unsigned long timeout) 106 { 107 struct qmi_txn txn; 108 int ret; 109 char *err_msg; 110 struct qmi_response_type_v01 *resp = rsp; 111 112 ret = qmi_txn_init(qmi, &txn, rsp_ei, rsp); 113 if (ret < 0) { 114 err_msg = "Qmi fail: fail to init txn,"; 115 goto out; 116 } 117 118 ret = qmi_send_request(qmi, NULL, &txn, req_id, 119 req_len, req_ei, req); 120 if (ret < 0) { 121 qmi_txn_cancel(&txn); 122 err_msg = "Qmi fail: fail to send req,"; 123 goto out; 124 } 125 126 ret = qmi_txn_wait(&txn, timeout); 127 if (ret < 0) { 128 err_msg = "Qmi fail: wait timeout,"; 129 goto out; 130 } else if (resp->result != QMI_RESULT_SUCCESS_V01) { 131 err_msg = "Qmi fail: request rejected,"; 132 cnss_pr_err("Qmi fail: respons with error:%d\n", 133 resp->error); 134 ret = -resp->result; 135 goto out; 136 } 137 138 cnss_pr_dbg("req %x success\n", req_id); 139 return 0; 140 out: 141 cnss_pr_err("%s req %x, ret %d\n", err_msg, req_id, ret); 142 return ret; 143 } 144 145 static int cnss_wlfw_ind_register_send_sync(struct cnss_plat_data *plat_priv) 146 { 147 struct wlfw_ind_register_req_msg_v01 *req; 148 struct wlfw_ind_register_resp_msg_v01 *resp; 149 struct qmi_txn txn; 150 int ret = 0; 151 152 cnss_pr_dbg("Sending indication register message, state: 0x%lx\n", 153 plat_priv->driver_state); 154 155 req = kzalloc(sizeof(*req), GFP_KERNEL); 156 if (!req) 157 return -ENOMEM; 158 159 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 160 if (!resp) { 161 kfree(req); 162 return -ENOMEM; 163 } 164 165 req->client_id_valid = 1; 166 req->client_id = WLFW_CLIENT_ID; 167 req->request_mem_enable_valid = 1; 168 req->request_mem_enable = 1; 169 req->fw_mem_ready_enable_valid = 1; 170 req->fw_mem_ready_enable = 1; 171 /* fw_ready indication is replaced by fw_init_done in HST/HSP */ 172 req->fw_init_done_enable_valid = 1; 173 req->fw_init_done_enable = 1; 174 req->pin_connect_result_enable_valid = 1; 175 req->pin_connect_result_enable = 1; 176 req->cal_done_enable_valid = 1; 177 req->cal_done_enable = 1; 178 req->qdss_trace_req_mem_enable_valid = 1; 179 req->qdss_trace_req_mem_enable = 1; 180 req->qdss_trace_save_enable_valid = 1; 181 req->qdss_trace_save_enable = 1; 182 req->qdss_trace_free_enable_valid = 1; 183 req->qdss_trace_free_enable = 1; 184 req->respond_get_info_enable_valid = 1; 185 req->respond_get_info_enable = 1; 186 req->wfc_call_twt_config_enable_valid = 1; 187 req->wfc_call_twt_config_enable = 1; 188 189 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 190 wlfw_ind_register_resp_msg_v01_ei, resp); 191 if (ret < 0) { 192 cnss_pr_err("Failed to initialize txn for indication register request, err: %d\n", 193 ret); 194 goto out; 195 } 196 197 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 198 QMI_WLFW_IND_REGISTER_REQ_V01, 199 WLFW_IND_REGISTER_REQ_MSG_V01_MAX_MSG_LEN, 200 wlfw_ind_register_req_msg_v01_ei, req); 201 if (ret < 0) { 202 qmi_txn_cancel(&txn); 203 cnss_pr_err("Failed to send indication register request, err: %d\n", 204 ret); 205 goto out; 206 } 207 208 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 209 if (ret < 0) { 210 cnss_pr_err("Failed to wait for response of indication register request, err: %d\n", 211 ret); 212 goto out; 213 } 214 215 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 216 cnss_pr_err("Indication register request failed, result: %d, err: %d\n", 217 resp->resp.result, resp->resp.error); 218 ret = -resp->resp.result; 219 goto out; 220 } 221 222 if (resp->fw_status_valid) { 223 if (resp->fw_status & QMI_WLFW_ALREADY_REGISTERED_V01) { 224 ret = -EALREADY; 225 goto qmi_registered; 226 } 227 } 228 229 kfree(req); 230 kfree(resp); 231 return 0; 232 233 out: 234 CNSS_QMI_ASSERT(); 235 236 qmi_registered: 237 kfree(req); 238 kfree(resp); 239 return ret; 240 } 241 242 static void cnss_wlfw_host_cap_parse_mlo(struct cnss_plat_data *plat_priv, 243 struct wlfw_host_cap_req_msg_v01 *req) 244 { 245 if (plat_priv->device_id == KIWI_DEVICE_ID || 246 plat_priv->device_id == MANGO_DEVICE_ID || 247 plat_priv->device_id == PEACH_DEVICE_ID) { 248 req->mlo_capable_valid = 1; 249 req->mlo_capable = 1; 250 req->mlo_chip_id_valid = 1; 251 req->mlo_chip_id = 0; 252 req->mlo_group_id_valid = 1; 253 req->mlo_group_id = 0; 254 req->max_mlo_peer_valid = 1; 255 /* Max peer number generally won't change for the same device 256 * but needs to be synced with host driver. 257 */ 258 req->max_mlo_peer = 32; 259 req->mlo_num_chips_valid = 1; 260 req->mlo_num_chips = 1; 261 req->mlo_chip_info_valid = 1; 262 req->mlo_chip_info[0].chip_id = 0; 263 req->mlo_chip_info[0].num_local_links = 2; 264 req->mlo_chip_info[0].hw_link_id[0] = 0; 265 req->mlo_chip_info[0].hw_link_id[1] = 1; 266 req->mlo_chip_info[0].valid_mlo_link_id[0] = 1; 267 req->mlo_chip_info[0].valid_mlo_link_id[1] = 1; 268 } 269 } 270 271 static int cnss_wlfw_host_cap_send_sync(struct cnss_plat_data *plat_priv) 272 { 273 struct wlfw_host_cap_req_msg_v01 *req; 274 struct wlfw_host_cap_resp_msg_v01 *resp; 275 struct qmi_txn txn; 276 int ret = 0; 277 u64 iova_start = 0, iova_size = 0, 278 iova_ipa_start = 0, iova_ipa_size = 0; 279 u64 feature_list = 0; 280 281 cnss_pr_dbg("Sending host capability message, state: 0x%lx\n", 282 plat_priv->driver_state); 283 284 req = kzalloc(sizeof(*req), GFP_KERNEL); 285 if (!req) 286 return -ENOMEM; 287 288 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 289 if (!resp) { 290 kfree(req); 291 return -ENOMEM; 292 } 293 294 req->num_clients_valid = 1; 295 req->num_clients = 1; 296 cnss_pr_dbg("Number of clients is %d\n", req->num_clients); 297 298 req->wake_msi = cnss_bus_get_wake_irq(plat_priv); 299 if (req->wake_msi) { 300 cnss_pr_dbg("WAKE MSI base data is %d\n", req->wake_msi); 301 req->wake_msi_valid = 1; 302 } 303 304 req->bdf_support_valid = 1; 305 req->bdf_support = 1; 306 307 req->m3_support_valid = 1; 308 req->m3_support = 1; 309 310 req->m3_cache_support_valid = 1; 311 req->m3_cache_support = 1; 312 313 req->cal_done_valid = 1; 314 req->cal_done = plat_priv->cal_done; 315 cnss_pr_dbg("Calibration done is %d\n", plat_priv->cal_done); 316 317 if (plat_priv->sleep_clk) { 318 req->nm_modem_valid = 1; 319 /* Notify firmware about the sleep clock selection, 320 * nm_modem_bit[1] is used for this purpose. 321 */ 322 req->nm_modem |= SLEEP_CLOCK_SELECT_INTERNAL_BIT; 323 } 324 325 if (cnss_bus_is_smmu_s1_enabled(plat_priv) && 326 !cnss_bus_get_iova(plat_priv, &iova_start, &iova_size) && 327 !cnss_bus_get_iova_ipa(plat_priv, &iova_ipa_start, 328 &iova_ipa_size)) { 329 req->ddr_range_valid = 1; 330 req->ddr_range[0].start = iova_start; 331 req->ddr_range[0].size = iova_size + iova_ipa_size; 332 cnss_pr_dbg("Sending iova starting 0x%llx with size 0x%llx\n", 333 req->ddr_range[0].start, req->ddr_range[0].size); 334 } 335 336 req->host_build_type_valid = 1; 337 req->host_build_type = cnss_get_host_build_type(); 338 339 cnss_wlfw_host_cap_parse_mlo(plat_priv, req); 340 341 ret = cnss_get_feature_list(plat_priv, &feature_list); 342 if (!ret) { 343 req->feature_list_valid = 1; 344 req->feature_list = feature_list; 345 cnss_pr_dbg("Sending feature list 0x%llx\n", 346 req->feature_list); 347 } 348 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 349 wlfw_host_cap_resp_msg_v01_ei, resp); 350 if (ret < 0) { 351 cnss_pr_err("Failed to initialize txn for host capability request, err: %d\n", 352 ret); 353 goto out; 354 } 355 356 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 357 QMI_WLFW_HOST_CAP_REQ_V01, 358 WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN, 359 wlfw_host_cap_req_msg_v01_ei, req); 360 if (ret < 0) { 361 qmi_txn_cancel(&txn); 362 cnss_pr_err("Failed to send host capability request, err: %d\n", 363 ret); 364 goto out; 365 } 366 367 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 368 if (ret < 0) { 369 cnss_pr_err("Failed to wait for response of host capability request, err: %d\n", 370 ret); 371 goto out; 372 } 373 374 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 375 cnss_pr_err("Host capability request failed, result: %d, err: %d\n", 376 resp->resp.result, resp->resp.error); 377 ret = -resp->resp.result; 378 goto out; 379 } 380 381 kfree(req); 382 kfree(resp); 383 return 0; 384 385 out: 386 CNSS_QMI_ASSERT(); 387 kfree(req); 388 kfree(resp); 389 return ret; 390 } 391 392 int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv) 393 { 394 struct wlfw_respond_mem_req_msg_v01 *req; 395 struct wlfw_respond_mem_resp_msg_v01 *resp; 396 struct qmi_txn txn; 397 struct cnss_fw_mem *fw_mem = plat_priv->fw_mem; 398 int ret = 0, i; 399 400 cnss_pr_dbg("Sending respond memory message, state: 0x%lx\n", 401 plat_priv->driver_state); 402 403 req = kzalloc(sizeof(*req), GFP_KERNEL); 404 if (!req) 405 return -ENOMEM; 406 407 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 408 if (!resp) { 409 kfree(req); 410 return -ENOMEM; 411 } 412 413 if (plat_priv->fw_mem_seg_len > QMI_WLFW_MAX_NUM_MEM_SEG_V01) { 414 cnss_pr_err("Invalid seg len %u\n", plat_priv->fw_mem_seg_len); 415 ret = -EINVAL; 416 goto out; 417 } 418 419 req->mem_seg_len = plat_priv->fw_mem_seg_len; 420 for (i = 0; i < req->mem_seg_len; i++) { 421 if (!fw_mem[i].pa || !fw_mem[i].size) { 422 if (fw_mem[i].type == 0) { 423 cnss_pr_err("Invalid memory for FW type, segment = %d\n", 424 i); 425 ret = -EINVAL; 426 goto out; 427 } 428 cnss_pr_err("Memory for FW is not available for type: %u\n", 429 fw_mem[i].type); 430 ret = -ENOMEM; 431 goto out; 432 } 433 434 cnss_pr_dbg("Memory for FW, va: 0x%pK, pa: %pa, size: 0x%zx, type: %u\n", 435 fw_mem[i].va, &fw_mem[i].pa, 436 fw_mem[i].size, fw_mem[i].type); 437 438 req->mem_seg[i].addr = fw_mem[i].pa; 439 req->mem_seg[i].size = fw_mem[i].size; 440 req->mem_seg[i].type = fw_mem[i].type; 441 } 442 443 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 444 wlfw_respond_mem_resp_msg_v01_ei, resp); 445 if (ret < 0) { 446 cnss_pr_err("Failed to initialize txn for respond memory request, err: %d\n", 447 ret); 448 goto out; 449 } 450 451 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 452 QMI_WLFW_RESPOND_MEM_REQ_V01, 453 WLFW_RESPOND_MEM_REQ_MSG_V01_MAX_MSG_LEN, 454 wlfw_respond_mem_req_msg_v01_ei, req); 455 if (ret < 0) { 456 qmi_txn_cancel(&txn); 457 cnss_pr_err("Failed to send respond memory request, err: %d\n", 458 ret); 459 goto out; 460 } 461 462 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 463 if (ret < 0) { 464 cnss_pr_err("Failed to wait for response of respond memory request, err: %d\n", 465 ret); 466 goto out; 467 } 468 469 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 470 cnss_pr_err("Respond memory request failed, result: %d, err: %d\n", 471 resp->resp.result, resp->resp.error); 472 ret = -resp->resp.result; 473 goto out; 474 } 475 476 kfree(req); 477 kfree(resp); 478 return 0; 479 480 out: 481 CNSS_QMI_ASSERT(); 482 kfree(req); 483 kfree(resp); 484 return ret; 485 } 486 487 int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv) 488 { 489 struct wlfw_cap_req_msg_v01 *req; 490 struct wlfw_cap_resp_msg_v01 *resp; 491 struct qmi_txn txn; 492 char *fw_build_timestamp; 493 int ret = 0, i; 494 495 cnss_pr_dbg("Sending target capability message, state: 0x%lx\n", 496 plat_priv->driver_state); 497 498 req = kzalloc(sizeof(*req), GFP_KERNEL); 499 if (!req) 500 return -ENOMEM; 501 502 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 503 if (!resp) { 504 kfree(req); 505 return -ENOMEM; 506 } 507 508 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 509 wlfw_cap_resp_msg_v01_ei, resp); 510 if (ret < 0) { 511 cnss_pr_err("Failed to initialize txn for target capability request, err: %d\n", 512 ret); 513 goto out; 514 } 515 516 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 517 QMI_WLFW_CAP_REQ_V01, 518 WLFW_CAP_REQ_MSG_V01_MAX_MSG_LEN, 519 wlfw_cap_req_msg_v01_ei, req); 520 if (ret < 0) { 521 qmi_txn_cancel(&txn); 522 cnss_pr_err("Failed to send respond target capability request, err: %d\n", 523 ret); 524 goto out; 525 } 526 527 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 528 if (ret < 0) { 529 cnss_pr_err("Failed to wait for response of target capability request, err: %d\n", 530 ret); 531 goto out; 532 } 533 534 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 535 cnss_pr_err("Target capability request failed, result: %d, err: %d\n", 536 resp->resp.result, resp->resp.error); 537 ret = -resp->resp.result; 538 goto out; 539 } 540 541 if (resp->chip_info_valid) { 542 plat_priv->chip_info.chip_id = resp->chip_info.chip_id; 543 plat_priv->chip_info.chip_family = resp->chip_info.chip_family; 544 } 545 if (resp->board_info_valid) 546 plat_priv->board_info.board_id = resp->board_info.board_id; 547 else 548 plat_priv->board_info.board_id = 0xFF; 549 if (resp->soc_info_valid) 550 plat_priv->soc_info.soc_id = resp->soc_info.soc_id; 551 if (resp->fw_version_info_valid) { 552 plat_priv->fw_version_info.fw_version = 553 resp->fw_version_info.fw_version; 554 fw_build_timestamp = resp->fw_version_info.fw_build_timestamp; 555 fw_build_timestamp[QMI_WLFW_MAX_TIMESTAMP_LEN] = '\0'; 556 strlcpy(plat_priv->fw_version_info.fw_build_timestamp, 557 resp->fw_version_info.fw_build_timestamp, 558 QMI_WLFW_MAX_TIMESTAMP_LEN + 1); 559 } 560 if (resp->fw_build_id_valid) { 561 resp->fw_build_id[QMI_WLFW_MAX_BUILD_ID_LEN] = '\0'; 562 strlcpy(plat_priv->fw_build_id, resp->fw_build_id, 563 QMI_WLFW_MAX_BUILD_ID_LEN + 1); 564 } 565 /* FW will send aop retention volatage for qca6490 */ 566 if (resp->voltage_mv_valid) { 567 plat_priv->cpr_info.voltage = resp->voltage_mv; 568 cnss_pr_dbg("Voltage for CPR: %dmV\n", 569 plat_priv->cpr_info.voltage); 570 cnss_update_cpr_info(plat_priv); 571 } 572 if (resp->time_freq_hz_valid) { 573 plat_priv->device_freq_hz = resp->time_freq_hz; 574 cnss_pr_dbg("Device frequency is %d HZ\n", 575 plat_priv->device_freq_hz); 576 } 577 if (resp->otp_version_valid) 578 plat_priv->otp_version = resp->otp_version; 579 if (resp->dev_mem_info_valid) { 580 for (i = 0; i < QMI_WLFW_MAX_DEV_MEM_NUM_V01; i++) { 581 plat_priv->dev_mem_info[i].start = 582 resp->dev_mem_info[i].start; 583 plat_priv->dev_mem_info[i].size = 584 resp->dev_mem_info[i].size; 585 cnss_pr_buf("Device memory info[%d]: start = 0x%llx, size = 0x%llx\n", 586 i, plat_priv->dev_mem_info[i].start, 587 plat_priv->dev_mem_info[i].size); 588 } 589 } 590 if (resp->fw_caps_valid) { 591 plat_priv->fw_pcie_gen_switch = 592 !!(resp->fw_caps & QMI_WLFW_HOST_PCIE_GEN_SWITCH_V01); 593 plat_priv->fw_aux_uc_support = 594 !!(resp->fw_caps & QMI_WLFW_AUX_UC_SUPPORT_V01); 595 cnss_pr_dbg("FW aux uc support capability: %d\n", 596 plat_priv->fw_aux_uc_support); 597 plat_priv->fw_caps = resp->fw_caps; 598 } 599 600 if (resp->hang_data_length_valid && 601 resp->hang_data_length && 602 resp->hang_data_length <= WLFW_MAX_HANG_EVENT_DATA_SIZE) 603 plat_priv->hang_event_data_len = resp->hang_data_length; 604 else 605 plat_priv->hang_event_data_len = 0; 606 607 if (resp->hang_data_addr_offset_valid) 608 plat_priv->hang_data_addr_offset = resp->hang_data_addr_offset; 609 else 610 plat_priv->hang_data_addr_offset = 0; 611 612 if (resp->hwid_bitmap_valid) 613 plat_priv->hwid_bitmap = resp->hwid_bitmap; 614 615 if (resp->ol_cpr_cfg_valid) 616 cnss_aop_ol_cpr_cfg_setup(plat_priv, &resp->ol_cpr_cfg); 617 618 /* Disable WLAN PDC in AOP firmware for boards which support on chip PMIC 619 * so AOP will ignore SW_CTRL changes and do not update regulator votes. 620 **/ 621 for (i = 0; i < plat_priv->on_chip_pmic_devices_count; i++) { 622 if (plat_priv->board_info.board_id == 623 plat_priv->on_chip_pmic_board_ids[i]) { 624 cnss_pr_dbg("Disabling WLAN PDC for board_id: %02x\n", 625 plat_priv->board_info.board_id); 626 ret = cnss_aop_send_msg(plat_priv, 627 "{class: wlan_pdc, ss: rf, res: pdc, enable: 0}"); 628 if (ret < 0) 629 cnss_pr_dbg("Failed to Send AOP Msg"); 630 break; 631 } 632 } 633 634 cnss_pr_dbg("Target capability: chip_id: 0x%x, chip_family: 0x%x, board_id: 0x%x, soc_id: 0x%x, otp_version: 0x%x\n", 635 plat_priv->chip_info.chip_id, 636 plat_priv->chip_info.chip_family, 637 plat_priv->board_info.board_id, plat_priv->soc_info.soc_id, 638 plat_priv->otp_version); 639 cnss_pr_dbg("fw_version: 0x%x, fw_build_timestamp: %s, fw_build_id: %s, hwid_bitmap:0x%x\n", 640 plat_priv->fw_version_info.fw_version, 641 plat_priv->fw_version_info.fw_build_timestamp, 642 plat_priv->fw_build_id, 643 plat_priv->hwid_bitmap); 644 cnss_pr_dbg("Hang event params, Length: 0x%x, Offset Address: 0x%x\n", 645 plat_priv->hang_event_data_len, 646 plat_priv->hang_data_addr_offset); 647 648 kfree(req); 649 kfree(resp); 650 return 0; 651 652 out: 653 CNSS_QMI_ASSERT(); 654 kfree(req); 655 kfree(resp); 656 return ret; 657 } 658 659 static char *cnss_bdf_type_to_str(enum cnss_bdf_type bdf_type) 660 { 661 switch (bdf_type) { 662 case CNSS_BDF_BIN: 663 case CNSS_BDF_ELF: 664 return "BDF"; 665 case CNSS_BDF_REGDB: 666 return "REGDB"; 667 case CNSS_BDF_HDS: 668 return "HDS"; 669 default: 670 return "UNKNOWN"; 671 } 672 } 673 674 static int cnss_get_bdf_file_name(struct cnss_plat_data *plat_priv, 675 u32 bdf_type, char *filename, 676 u32 filename_len) 677 { 678 char filename_tmp[MAX_FIRMWARE_NAME_LEN]; 679 int ret = 0; 680 681 switch (bdf_type) { 682 case CNSS_BDF_ELF: 683 /* Board ID will be equal or less than 0xFF in GF mask case */ 684 if (plat_priv->board_info.board_id == 0xFF) { 685 if (plat_priv->chip_info.chip_id & CHIP_ID_GF_MASK) 686 snprintf(filename_tmp, filename_len, 687 ELF_BDF_FILE_NAME_GF); 688 else 689 snprintf(filename_tmp, filename_len, 690 ELF_BDF_FILE_NAME); 691 } else if (plat_priv->board_info.board_id < 0xFF) { 692 if (plat_priv->chip_info.chip_id & CHIP_ID_GF_MASK) 693 snprintf(filename_tmp, filename_len, 694 ELF_BDF_FILE_NAME_GF_PREFIX "%02x", 695 plat_priv->board_info.board_id); 696 else 697 snprintf(filename_tmp, filename_len, 698 ELF_BDF_FILE_NAME_PREFIX "%02x", 699 plat_priv->board_info.board_id); 700 } else { 701 snprintf(filename_tmp, filename_len, 702 BDF_FILE_NAME_PREFIX "%02x.e%02x", 703 plat_priv->board_info.board_id >> 8 & 0xFF, 704 plat_priv->board_info.board_id & 0xFF); 705 } 706 break; 707 case CNSS_BDF_BIN: 708 if (plat_priv->board_info.board_id == 0xFF) { 709 if (plat_priv->chip_info.chip_id & CHIP_ID_GF_MASK) 710 snprintf(filename_tmp, filename_len, 711 BIN_BDF_FILE_NAME_GF); 712 else 713 snprintf(filename_tmp, filename_len, 714 BIN_BDF_FILE_NAME); 715 } else if (plat_priv->board_info.board_id < 0xFF) { 716 if (plat_priv->chip_info.chip_id & CHIP_ID_GF_MASK) 717 snprintf(filename_tmp, filename_len, 718 BIN_BDF_FILE_NAME_GF_PREFIX "%02x", 719 plat_priv->board_info.board_id); 720 else 721 snprintf(filename_tmp, filename_len, 722 BIN_BDF_FILE_NAME_PREFIX "%02x", 723 plat_priv->board_info.board_id); 724 } else { 725 snprintf(filename_tmp, filename_len, 726 BDF_FILE_NAME_PREFIX "%02x.b%02x", 727 plat_priv->board_info.board_id >> 8 & 0xFF, 728 plat_priv->board_info.board_id & 0xFF); 729 } 730 break; 731 case CNSS_BDF_REGDB: 732 snprintf(filename_tmp, filename_len, REGDB_FILE_NAME); 733 break; 734 case CNSS_BDF_HDS: 735 snprintf(filename_tmp, filename_len, HDS_FILE_NAME); 736 break; 737 default: 738 cnss_pr_err("Invalid BDF type: %d\n", 739 plat_priv->ctrl_params.bdf_type); 740 ret = -EINVAL; 741 break; 742 } 743 744 if (!ret) 745 cnss_bus_add_fw_prefix_name(plat_priv, filename, filename_tmp); 746 747 return ret; 748 } 749 750 int cnss_wlfw_ini_file_send_sync(struct cnss_plat_data *plat_priv, 751 enum wlfw_ini_file_type_v01 file_type) 752 { 753 struct wlfw_ini_file_download_req_msg_v01 *req; 754 struct wlfw_ini_file_download_resp_msg_v01 *resp; 755 struct qmi_txn txn; 756 int ret = 0; 757 const struct firmware *fw; 758 char filename[INI_FILE_NAME_LEN] = {0}; 759 char tmp_filename[INI_FILE_NAME_LEN] = {0}; 760 const u8 *temp; 761 unsigned int remaining; 762 bool backup_supported = false; 763 764 req = kzalloc(sizeof(*req), GFP_KERNEL); 765 if (!req) 766 return -ENOMEM; 767 768 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 769 if (!resp) { 770 kfree(req); 771 return -ENOMEM; 772 } 773 774 switch (file_type) { 775 case WLFW_CONN_ROAM_INI_V01: 776 snprintf(tmp_filename, sizeof(tmp_filename), 777 CONN_ROAM_FILE_NAME); 778 backup_supported = true; 779 break; 780 default: 781 cnss_pr_err("Invalid file type: %u\n", file_type); 782 ret = -EINVAL; 783 goto err_req_fw; 784 } 785 786 snprintf(filename, sizeof(filename), "%s%s", tmp_filename, INI_EXT); 787 /* Fetch the file */ 788 ret = firmware_request_nowarn(&fw, filename, &plat_priv->plat_dev->dev); 789 if (ret) { 790 if (!backup_supported) 791 goto err_req_fw; 792 793 snprintf(filename, sizeof(filename), 794 "%s-%s%s", tmp_filename, "backup", INI_EXT); 795 796 ret = firmware_request_nowarn(&fw, filename, 797 &plat_priv->plat_dev->dev); 798 if (ret) 799 goto err_req_fw; 800 } 801 802 temp = fw->data; 803 remaining = fw->size; 804 805 cnss_pr_dbg("Downloading INI file: %s, size: %u\n", filename, 806 remaining); 807 808 while (remaining) { 809 req->file_type_valid = 1; 810 req->file_type = file_type; 811 req->total_size_valid = 1; 812 req->total_size = remaining; 813 req->seg_id_valid = 1; 814 req->data_valid = 1; 815 req->end_valid = 1; 816 817 if (remaining > QMI_WLFW_MAX_DATA_SIZE_V01) { 818 req->data_len = QMI_WLFW_MAX_DATA_SIZE_V01; 819 } else { 820 req->data_len = remaining; 821 req->end = 1; 822 } 823 824 memcpy(req->data, temp, req->data_len); 825 826 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 827 wlfw_ini_file_download_resp_msg_v01_ei, 828 resp); 829 if (ret < 0) { 830 cnss_pr_err("Failed to initialize txn for INI file download request, err: %d\n", 831 ret); 832 goto err; 833 } 834 835 ret = qmi_send_request 836 (&plat_priv->qmi_wlfw, NULL, &txn, 837 QMI_WLFW_INI_FILE_DOWNLOAD_REQ_V01, 838 WLFW_INI_FILE_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN, 839 wlfw_ini_file_download_req_msg_v01_ei, req); 840 if (ret < 0) { 841 qmi_txn_cancel(&txn); 842 cnss_pr_err("Failed to send INI File download request, err: %d\n", 843 ret); 844 goto err; 845 } 846 847 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 848 if (ret < 0) { 849 cnss_pr_err("Failed to wait for response of INI File download request, err: %d\n", 850 ret); 851 goto err; 852 } 853 854 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 855 cnss_pr_err("INI file download request failed, result: %d, err: %d\n", 856 resp->resp.result, resp->resp.error); 857 ret = -resp->resp.result; 858 goto err; 859 } 860 861 remaining -= req->data_len; 862 temp += req->data_len; 863 req->seg_id++; 864 } 865 866 release_firmware(fw); 867 868 kfree(req); 869 kfree(resp); 870 return 0; 871 872 err: 873 release_firmware(fw); 874 err_req_fw: 875 kfree(req); 876 kfree(resp); 877 878 return ret; 879 } 880 881 int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv, 882 u32 bdf_type) 883 { 884 struct wlfw_bdf_download_req_msg_v01 *req; 885 struct wlfw_bdf_download_resp_msg_v01 *resp; 886 struct qmi_txn txn; 887 char filename[MAX_FIRMWARE_NAME_LEN]; 888 const struct firmware *fw_entry = NULL; 889 const u8 *temp; 890 unsigned int remaining; 891 int ret = 0; 892 893 cnss_pr_dbg("Sending QMI_WLFW_BDF_DOWNLOAD_REQ_V01 message for bdf_type: %d (%s), state: 0x%lx\n", 894 bdf_type, cnss_bdf_type_to_str(bdf_type), plat_priv->driver_state); 895 896 req = kzalloc(sizeof(*req), GFP_KERNEL); 897 if (!req) 898 return -ENOMEM; 899 900 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 901 if (!resp) { 902 kfree(req); 903 return -ENOMEM; 904 } 905 906 ret = cnss_get_bdf_file_name(plat_priv, bdf_type, 907 filename, sizeof(filename)); 908 if (ret) 909 goto err_req_fw; 910 911 if (bdf_type == CNSS_BDF_REGDB) 912 ret = cnss_request_firmware_direct(plat_priv, &fw_entry, 913 filename); 914 else 915 ret = firmware_request_nowarn(&fw_entry, filename, 916 &plat_priv->plat_dev->dev); 917 918 if (ret) { 919 cnss_pr_err("Failed to load %s: %s, ret: %d\n", 920 cnss_bdf_type_to_str(bdf_type), filename, ret); 921 goto err_req_fw; 922 } 923 924 temp = fw_entry->data; 925 remaining = fw_entry->size; 926 927 cnss_pr_dbg("Downloading %s: %s, size: %u\n", 928 cnss_bdf_type_to_str(bdf_type), filename, remaining); 929 930 while (remaining) { 931 req->valid = 1; 932 req->file_id_valid = 1; 933 req->file_id = plat_priv->board_info.board_id; 934 req->total_size_valid = 1; 935 req->total_size = remaining; 936 req->seg_id_valid = 1; 937 req->data_valid = 1; 938 req->end_valid = 1; 939 req->bdf_type_valid = 1; 940 req->bdf_type = bdf_type; 941 942 if (remaining > QMI_WLFW_MAX_DATA_SIZE_V01) { 943 req->data_len = QMI_WLFW_MAX_DATA_SIZE_V01; 944 } else { 945 req->data_len = remaining; 946 req->end = 1; 947 } 948 949 memcpy(req->data, temp, req->data_len); 950 951 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 952 wlfw_bdf_download_resp_msg_v01_ei, resp); 953 if (ret < 0) { 954 cnss_pr_err("Failed to initialize txn for QMI_WLFW_BDF_DOWNLOAD_REQ_V01 request for %s, error: %d\n", 955 cnss_bdf_type_to_str(bdf_type), ret); 956 goto err_send; 957 } 958 959 ret = qmi_send_request 960 (&plat_priv->qmi_wlfw, NULL, &txn, 961 QMI_WLFW_BDF_DOWNLOAD_REQ_V01, 962 WLFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN, 963 wlfw_bdf_download_req_msg_v01_ei, req); 964 if (ret < 0) { 965 qmi_txn_cancel(&txn); 966 cnss_pr_err("Failed to send QMI_WLFW_BDF_DOWNLOAD_REQ_V01 request for %s, error: %d\n", 967 cnss_bdf_type_to_str(bdf_type), ret); 968 goto err_send; 969 } 970 971 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 972 if (ret < 0) { 973 cnss_pr_err("Timeout while waiting for FW response for QMI_WLFW_BDF_DOWNLOAD_REQ_V01 request for %s, err: %d\n", 974 cnss_bdf_type_to_str(bdf_type), ret); 975 goto err_send; 976 } 977 978 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 979 cnss_pr_err("FW response for QMI_WLFW_BDF_DOWNLOAD_REQ_V01 request for %s failed, result: %d, err: %d\n", 980 cnss_bdf_type_to_str(bdf_type), resp->resp.result, 981 resp->resp.error); 982 ret = -resp->resp.result; 983 goto err_send; 984 } 985 986 remaining -= req->data_len; 987 temp += req->data_len; 988 req->seg_id++; 989 } 990 991 release_firmware(fw_entry); 992 993 if (resp->host_bdf_data_valid) { 994 /* QCA6490 enable S3E regulator for IPA configuration only */ 995 if (!(resp->host_bdf_data & QMI_WLFW_HW_XPA_V01)) 996 cnss_enable_int_pow_amp_vreg(plat_priv); 997 998 plat_priv->cbc_file_download = 999 resp->host_bdf_data & QMI_WLFW_CBC_FILE_DOWNLOAD_V01; 1000 cnss_pr_info("Host BDF config: HW_XPA: %d CalDB: %d\n", 1001 resp->host_bdf_data & QMI_WLFW_HW_XPA_V01, 1002 plat_priv->cbc_file_download); 1003 } 1004 kfree(req); 1005 kfree(resp); 1006 return 0; 1007 1008 err_send: 1009 release_firmware(fw_entry); 1010 err_req_fw: 1011 if (!(bdf_type == CNSS_BDF_REGDB || 1012 test_bit(CNSS_IN_REBOOT, &plat_priv->driver_state) || 1013 ret == -EAGAIN)) 1014 CNSS_QMI_ASSERT(); 1015 kfree(req); 1016 kfree(resp); 1017 return ret; 1018 } 1019 1020 int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv) 1021 { 1022 struct wlfw_m3_info_req_msg_v01 *req; 1023 struct wlfw_m3_info_resp_msg_v01 *resp; 1024 struct qmi_txn txn; 1025 struct cnss_fw_mem *m3_mem = &plat_priv->m3_mem; 1026 int ret = 0; 1027 1028 cnss_pr_dbg("Sending M3 information message, state: 0x%lx\n", 1029 plat_priv->driver_state); 1030 1031 req = kzalloc(sizeof(*req), GFP_KERNEL); 1032 if (!req) 1033 return -ENOMEM; 1034 1035 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 1036 if (!resp) { 1037 kfree(req); 1038 return -ENOMEM; 1039 } 1040 1041 if (!m3_mem->pa || !m3_mem->size) { 1042 cnss_pr_err("Memory for M3 is not available\n"); 1043 ret = -ENOMEM; 1044 goto out; 1045 } 1046 1047 cnss_pr_dbg("M3 memory, va: 0x%pK, pa: %pa, size: 0x%zx\n", 1048 m3_mem->va, &m3_mem->pa, m3_mem->size); 1049 1050 req->addr = plat_priv->m3_mem.pa; 1051 req->size = plat_priv->m3_mem.size; 1052 1053 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 1054 wlfw_m3_info_resp_msg_v01_ei, resp); 1055 if (ret < 0) { 1056 cnss_pr_err("Failed to initialize txn for M3 information request, err: %d\n", 1057 ret); 1058 goto out; 1059 } 1060 1061 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 1062 QMI_WLFW_M3_INFO_REQ_V01, 1063 WLFW_M3_INFO_REQ_MSG_V01_MAX_MSG_LEN, 1064 wlfw_m3_info_req_msg_v01_ei, req); 1065 if (ret < 0) { 1066 qmi_txn_cancel(&txn); 1067 cnss_pr_err("Failed to send M3 information request, err: %d\n", 1068 ret); 1069 goto out; 1070 } 1071 1072 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 1073 if (ret < 0) { 1074 cnss_pr_err("Failed to wait for response of M3 information request, err: %d\n", 1075 ret); 1076 goto out; 1077 } 1078 1079 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 1080 cnss_pr_err("M3 information request failed, result: %d, err: %d\n", 1081 resp->resp.result, resp->resp.error); 1082 ret = -resp->resp.result; 1083 goto out; 1084 } 1085 1086 kfree(req); 1087 kfree(resp); 1088 return 0; 1089 1090 out: 1091 CNSS_QMI_ASSERT(); 1092 kfree(req); 1093 kfree(resp); 1094 return ret; 1095 } 1096 1097 int cnss_wlfw_aux_dnld_send_sync(struct cnss_plat_data *plat_priv) 1098 { 1099 struct wlfw_aux_uc_info_req_msg_v01 *req; 1100 struct wlfw_aux_uc_info_resp_msg_v01 *resp; 1101 struct qmi_txn txn; 1102 struct cnss_fw_mem *aux_mem = &plat_priv->aux_mem; 1103 int ret = 0; 1104 1105 cnss_pr_dbg("Sending QMI_WLFW_AUX_UC_INFO_REQ_V01 message, state: 0x%lx\n", 1106 plat_priv->driver_state); 1107 1108 req = kzalloc(sizeof(*req), GFP_KERNEL); 1109 if (!req) 1110 return -ENOMEM; 1111 1112 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 1113 if (!resp) { 1114 kfree(req); 1115 return -ENOMEM; 1116 } 1117 1118 if (!aux_mem->pa || !aux_mem->size) { 1119 cnss_pr_err("Memory for AUX is not available\n"); 1120 ret = -ENOMEM; 1121 goto out; 1122 } 1123 1124 cnss_pr_dbg("AUX memory, va: 0x%pK, pa: %pa, size: 0x%zx\n", 1125 aux_mem->va, &aux_mem->pa, aux_mem->size); 1126 1127 req->addr = plat_priv->aux_mem.pa; 1128 req->size = plat_priv->aux_mem.size; 1129 1130 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 1131 wlfw_aux_uc_info_resp_msg_v01_ei, resp); 1132 if (ret < 0) { 1133 cnss_pr_err("Failed to initialize txn for QMI_WLFW_AUX_UC_INFO_REQ_V01 request, err: %d\n", 1134 ret); 1135 goto out; 1136 } 1137 1138 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 1139 QMI_WLFW_AUX_UC_INFO_REQ_V01, 1140 WLFW_AUX_UC_INFO_REQ_MSG_V01_MAX_MSG_LEN, 1141 wlfw_aux_uc_info_req_msg_v01_ei, req); 1142 if (ret < 0) { 1143 qmi_txn_cancel(&txn); 1144 cnss_pr_err("Failed to send QMI_WLFW_AUX_UC_INFO_REQ_V01 request, err: %d\n", 1145 ret); 1146 goto out; 1147 } 1148 1149 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 1150 if (ret < 0) { 1151 cnss_pr_err("Failed to wait for response of QMI_WLFW_AUX_UC_INFO_REQ_V01 request, err: %d\n", 1152 ret); 1153 goto out; 1154 } 1155 1156 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 1157 cnss_pr_err("QMI_WLFW_AUX_UC_INFO_REQ_V01 request failed, result: %d, err: %d\n", 1158 resp->resp.result, resp->resp.error); 1159 ret = -resp->resp.result; 1160 goto out; 1161 } 1162 1163 kfree(req); 1164 kfree(resp); 1165 return 0; 1166 1167 out: 1168 CNSS_QMI_ASSERT(); 1169 kfree(req); 1170 kfree(resp); 1171 return ret; 1172 } 1173 1174 int cnss_wlfw_wlan_mac_req_send_sync(struct cnss_plat_data *plat_priv, 1175 u8 *mac, u32 mac_len) 1176 { 1177 struct wlfw_mac_addr_req_msg_v01 req; 1178 struct wlfw_mac_addr_resp_msg_v01 resp = {0}; 1179 struct qmi_txn txn; 1180 int ret; 1181 1182 if (!plat_priv || !mac || mac_len != QMI_WLFW_MAC_ADDR_SIZE_V01) 1183 return -EINVAL; 1184 1185 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 1186 wlfw_mac_addr_resp_msg_v01_ei, &resp); 1187 if (ret < 0) { 1188 cnss_pr_err("Failed to initialize txn for mac req, err: %d\n", 1189 ret); 1190 ret = -EIO; 1191 goto out; 1192 } 1193 1194 cnss_pr_dbg("Sending WLAN mac req [%pM], state: 0x%lx\n", 1195 mac, plat_priv->driver_state); 1196 memcpy(req.mac_addr, mac, mac_len); 1197 req.mac_addr_valid = 1; 1198 1199 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 1200 QMI_WLFW_MAC_ADDR_REQ_V01, 1201 WLFW_MAC_ADDR_REQ_MSG_V01_MAX_MSG_LEN, 1202 wlfw_mac_addr_req_msg_v01_ei, &req); 1203 if (ret < 0) { 1204 qmi_txn_cancel(&txn); 1205 cnss_pr_err("Failed to send mac req, err: %d\n", ret); 1206 ret = -EIO; 1207 goto out; 1208 } 1209 1210 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 1211 if (ret < 0) { 1212 cnss_pr_err("Failed to wait for resp of mac req, err: %d\n", 1213 ret); 1214 ret = -EIO; 1215 goto out; 1216 } 1217 1218 if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { 1219 cnss_pr_err("WLAN mac req failed, result: %d, err: %d\n", 1220 resp.resp.result); 1221 ret = -resp.resp.result; 1222 } 1223 out: 1224 return ret; 1225 } 1226 1227 int cnss_wlfw_qdss_data_send_sync(struct cnss_plat_data *plat_priv, char *file_name, 1228 u32 total_size) 1229 { 1230 int ret = 0; 1231 struct wlfw_qdss_trace_data_req_msg_v01 *req; 1232 struct wlfw_qdss_trace_data_resp_msg_v01 *resp; 1233 unsigned char *p_qdss_trace_data_temp, *p_qdss_trace_data = NULL; 1234 unsigned int remaining; 1235 struct qmi_txn txn; 1236 1237 cnss_pr_dbg("%s\n", __func__); 1238 1239 req = kzalloc(sizeof(*req), GFP_KERNEL); 1240 if (!req) 1241 return -ENOMEM; 1242 1243 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 1244 if (!resp) { 1245 kfree(req); 1246 return -ENOMEM; 1247 } 1248 1249 p_qdss_trace_data = kzalloc(total_size, GFP_KERNEL); 1250 if (!p_qdss_trace_data) { 1251 ret = ENOMEM; 1252 goto end; 1253 } 1254 1255 remaining = total_size; 1256 p_qdss_trace_data_temp = p_qdss_trace_data; 1257 while (remaining && resp->end == 0) { 1258 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 1259 wlfw_qdss_trace_data_resp_msg_v01_ei, resp); 1260 1261 if (ret < 0) { 1262 cnss_pr_err("Fail to init txn for QDSS trace resp %d\n", 1263 ret); 1264 goto fail; 1265 } 1266 1267 ret = qmi_send_request 1268 (&plat_priv->qmi_wlfw, NULL, &txn, 1269 QMI_WLFW_QDSS_TRACE_DATA_REQ_V01, 1270 WLFW_QDSS_TRACE_DATA_REQ_MSG_V01_MAX_MSG_LEN, 1271 wlfw_qdss_trace_data_req_msg_v01_ei, req); 1272 1273 if (ret < 0) { 1274 qmi_txn_cancel(&txn); 1275 cnss_pr_err("Fail to send QDSS trace data req %d\n", 1276 ret); 1277 goto fail; 1278 } 1279 1280 ret = qmi_txn_wait(&txn, plat_priv->ctrl_params.qmi_timeout); 1281 1282 if (ret < 0) { 1283 cnss_pr_err("QDSS trace resp wait failed with rc %d\n", 1284 ret); 1285 goto fail; 1286 } else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 1287 cnss_pr_err("QMI QDSS trace request rejected, result:%d error:%d\n", 1288 resp->resp.result, resp->resp.error); 1289 ret = -resp->resp.result; 1290 goto fail; 1291 } else { 1292 ret = 0; 1293 } 1294 1295 cnss_pr_dbg("%s: response total size %d data len %d", 1296 __func__, resp->total_size, resp->data_len); 1297 1298 if ((resp->total_size_valid == 1 && 1299 resp->total_size == total_size) && 1300 (resp->seg_id_valid == 1 && resp->seg_id == req->seg_id) && 1301 (resp->data_valid == 1 && 1302 resp->data_len <= QMI_WLFW_MAX_DATA_SIZE_V01) && 1303 resp->data_len <= remaining) { 1304 memcpy(p_qdss_trace_data_temp, 1305 resp->data, resp->data_len); 1306 } else { 1307 cnss_pr_err("%s: Unmatched qdss trace data, Expect total_size %u, seg_id %u, Recv total_size_valid %u, total_size %u, seg_id_valid %u, seg_id %u, data_len_valid %u, data_len %u", 1308 __func__, 1309 total_size, req->seg_id, 1310 resp->total_size_valid, 1311 resp->total_size, 1312 resp->seg_id_valid, 1313 resp->seg_id, 1314 resp->data_valid, 1315 resp->data_len); 1316 ret = -1; 1317 goto fail; 1318 } 1319 1320 remaining -= resp->data_len; 1321 p_qdss_trace_data_temp += resp->data_len; 1322 req->seg_id++; 1323 } 1324 1325 if (remaining == 0 && (resp->end_valid && resp->end)) { 1326 ret = cnss_genl_send_msg(p_qdss_trace_data, 1327 CNSS_GENL_MSG_TYPE_QDSS, file_name, 1328 total_size); 1329 if (ret < 0) { 1330 cnss_pr_err("Fail to save QDSS trace data: %d\n", 1331 ret); 1332 ret = -1; 1333 goto fail; 1334 } 1335 } else { 1336 cnss_pr_err("%s: QDSS trace file corrupted: remaining %u, end_valid %u, end %u", 1337 __func__, 1338 remaining, resp->end_valid, resp->end); 1339 ret = -1; 1340 goto fail; 1341 } 1342 1343 fail: 1344 kfree(p_qdss_trace_data); 1345 1346 end: 1347 kfree(req); 1348 kfree(resp); 1349 return ret; 1350 } 1351 1352 void cnss_get_qdss_cfg_filename(struct cnss_plat_data *plat_priv, 1353 char *filename, u32 filename_len) 1354 { 1355 char filename_tmp[MAX_FIRMWARE_NAME_LEN]; 1356 char *debug_str = QDSS_DEBUG_FILE_STR; 1357 1358 if (plat_priv->device_id == KIWI_DEVICE_ID || 1359 plat_priv->device_id == MANGO_DEVICE_ID || 1360 plat_priv->device_id == PEACH_DEVICE_ID) 1361 debug_str = ""; 1362 1363 if (plat_priv->device_version.major_version == FW_V2_NUMBER) 1364 snprintf(filename_tmp, filename_len, QDSS_TRACE_CONFIG_FILE 1365 "_%s%s.cfg", debug_str, HW_V2_NUMBER); 1366 else 1367 snprintf(filename_tmp, filename_len, QDSS_TRACE_CONFIG_FILE 1368 "_%s%s.cfg", debug_str, HW_V1_NUMBER); 1369 1370 cnss_bus_add_fw_prefix_name(plat_priv, filename, filename_tmp); 1371 } 1372 1373 int cnss_wlfw_qdss_dnld_send_sync(struct cnss_plat_data *plat_priv) 1374 { 1375 struct wlfw_qdss_trace_config_download_req_msg_v01 *req; 1376 struct wlfw_qdss_trace_config_download_resp_msg_v01 *resp; 1377 struct qmi_txn txn; 1378 const struct firmware *fw_entry = NULL; 1379 const u8 *temp; 1380 char qdss_cfg_filename[MAX_FIRMWARE_NAME_LEN]; 1381 unsigned int remaining; 1382 int ret = 0; 1383 1384 cnss_pr_dbg("Sending QDSS config download message, state: 0x%lx\n", 1385 plat_priv->driver_state); 1386 1387 req = kzalloc(sizeof(*req), GFP_KERNEL); 1388 if (!req) 1389 return -ENOMEM; 1390 1391 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 1392 if (!resp) { 1393 kfree(req); 1394 return -ENOMEM; 1395 } 1396 1397 cnss_get_qdss_cfg_filename(plat_priv, qdss_cfg_filename, sizeof(qdss_cfg_filename)); 1398 ret = cnss_request_firmware_direct(plat_priv, &fw_entry, 1399 qdss_cfg_filename); 1400 if (ret) { 1401 cnss_pr_dbg("Unable to load %s\n", 1402 qdss_cfg_filename); 1403 goto err_req_fw; 1404 } 1405 1406 temp = fw_entry->data; 1407 remaining = fw_entry->size; 1408 1409 cnss_pr_dbg("Downloading QDSS: %s, size: %u\n", 1410 qdss_cfg_filename, remaining); 1411 1412 while (remaining) { 1413 req->total_size_valid = 1; 1414 req->total_size = remaining; 1415 req->seg_id_valid = 1; 1416 req->data_valid = 1; 1417 req->end_valid = 1; 1418 1419 if (remaining > QMI_WLFW_MAX_DATA_SIZE_V01) { 1420 req->data_len = QMI_WLFW_MAX_DATA_SIZE_V01; 1421 } else { 1422 req->data_len = remaining; 1423 req->end = 1; 1424 } 1425 1426 memcpy(req->data, temp, req->data_len); 1427 1428 ret = qmi_txn_init 1429 (&plat_priv->qmi_wlfw, &txn, 1430 wlfw_qdss_trace_config_download_resp_msg_v01_ei, 1431 resp); 1432 if (ret < 0) { 1433 cnss_pr_err("Failed to initialize txn for QDSS download request, err: %d\n", 1434 ret); 1435 goto err_send; 1436 } 1437 1438 ret = qmi_send_request 1439 (&plat_priv->qmi_wlfw, NULL, &txn, 1440 QMI_WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_V01, 1441 WLFW_QDSS_TRACE_CONFIG_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN, 1442 wlfw_qdss_trace_config_download_req_msg_v01_ei, req); 1443 if (ret < 0) { 1444 qmi_txn_cancel(&txn); 1445 cnss_pr_err("Failed to send respond QDSS download request, err: %d\n", 1446 ret); 1447 goto err_send; 1448 } 1449 1450 ret = qmi_txn_wait(&txn, plat_priv->ctrl_params.qmi_timeout); 1451 if (ret < 0) { 1452 cnss_pr_err("Failed to wait for response of QDSS download request, err: %d\n", 1453 ret); 1454 goto err_send; 1455 } 1456 1457 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 1458 cnss_pr_err("QDSS download request failed, result: %d, err: %d\n", 1459 resp->resp.result, resp->resp.error); 1460 ret = -resp->resp.result; 1461 goto err_send; 1462 } 1463 1464 remaining -= req->data_len; 1465 temp += req->data_len; 1466 req->seg_id++; 1467 } 1468 1469 release_firmware(fw_entry); 1470 kfree(req); 1471 kfree(resp); 1472 return 0; 1473 1474 err_send: 1475 release_firmware(fw_entry); 1476 err_req_fw: 1477 1478 kfree(req); 1479 kfree(resp); 1480 return ret; 1481 } 1482 1483 static int wlfw_send_qdss_trace_mode_req 1484 (struct cnss_plat_data *plat_priv, 1485 enum wlfw_qdss_trace_mode_enum_v01 mode, 1486 unsigned long long option) 1487 { 1488 int rc = 0; 1489 int tmp = 0; 1490 struct wlfw_qdss_trace_mode_req_msg_v01 *req; 1491 struct wlfw_qdss_trace_mode_resp_msg_v01 *resp; 1492 struct qmi_txn txn; 1493 1494 if (!plat_priv) 1495 return -ENODEV; 1496 1497 req = kzalloc(sizeof(*req), GFP_KERNEL); 1498 if (!req) 1499 return -ENOMEM; 1500 1501 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 1502 if (!resp) { 1503 kfree(req); 1504 return -ENOMEM; 1505 } 1506 1507 req->mode_valid = 1; 1508 req->mode = mode; 1509 req->option_valid = 1; 1510 req->option = option; 1511 1512 tmp = plat_priv->hw_trc_override; 1513 1514 req->hw_trc_disable_override_valid = 1; 1515 req->hw_trc_disable_override = 1516 (tmp > QMI_PARAM_DISABLE_V01 ? QMI_PARAM_DISABLE_V01 : 1517 (tmp < 0 ? QMI_PARAM_INVALID_V01 : tmp)); 1518 1519 cnss_pr_dbg("%s: mode %u, option %llu, hw_trc_disable_override: %u", 1520 __func__, mode, option, req->hw_trc_disable_override); 1521 1522 rc = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 1523 wlfw_qdss_trace_mode_resp_msg_v01_ei, resp); 1524 if (rc < 0) { 1525 cnss_pr_err("Fail to init txn for QDSS Mode resp %d\n", 1526 rc); 1527 goto out; 1528 } 1529 1530 rc = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 1531 QMI_WLFW_QDSS_TRACE_MODE_REQ_V01, 1532 WLFW_QDSS_TRACE_MODE_REQ_MSG_V01_MAX_MSG_LEN, 1533 wlfw_qdss_trace_mode_req_msg_v01_ei, req); 1534 if (rc < 0) { 1535 qmi_txn_cancel(&txn); 1536 cnss_pr_err("Fail to send QDSS Mode req %d\n", rc); 1537 goto out; 1538 } 1539 1540 rc = qmi_txn_wait(&txn, plat_priv->ctrl_params.qmi_timeout); 1541 if (rc < 0) { 1542 cnss_pr_err("QDSS Mode resp wait failed with rc %d\n", 1543 rc); 1544 goto out; 1545 } else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 1546 cnss_pr_err("QMI QDSS Mode request rejected, result:%d error:%d\n", 1547 resp->resp.result, resp->resp.error); 1548 rc = -resp->resp.result; 1549 goto out; 1550 } 1551 1552 kfree(resp); 1553 kfree(req); 1554 return rc; 1555 out: 1556 kfree(resp); 1557 kfree(req); 1558 CNSS_QMI_ASSERT(); 1559 return rc; 1560 } 1561 1562 int wlfw_qdss_trace_start(struct cnss_plat_data *plat_priv) 1563 { 1564 return wlfw_send_qdss_trace_mode_req(plat_priv, 1565 QMI_WLFW_QDSS_TRACE_ON_V01, 0); 1566 } 1567 1568 int wlfw_qdss_trace_stop(struct cnss_plat_data *plat_priv, unsigned long long option) 1569 { 1570 return wlfw_send_qdss_trace_mode_req(plat_priv, QMI_WLFW_QDSS_TRACE_OFF_V01, 1571 option); 1572 } 1573 1574 int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv, 1575 enum cnss_driver_mode mode) 1576 { 1577 struct wlfw_wlan_mode_req_msg_v01 *req; 1578 struct wlfw_wlan_mode_resp_msg_v01 *resp; 1579 struct qmi_txn txn; 1580 int ret = 0; 1581 1582 if (!plat_priv) 1583 return -ENODEV; 1584 1585 cnss_pr_dbg("Sending mode message, mode: %s(%d), state: 0x%lx\n", 1586 cnss_qmi_mode_to_str(mode), mode, plat_priv->driver_state); 1587 1588 if (mode == CNSS_OFF && 1589 test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) { 1590 cnss_pr_dbg("Recovery is in progress, ignore mode off request\n"); 1591 return 0; 1592 } 1593 1594 req = kzalloc(sizeof(*req), GFP_KERNEL); 1595 if (!req) 1596 return -ENOMEM; 1597 1598 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 1599 if (!resp) { 1600 kfree(req); 1601 return -ENOMEM; 1602 } 1603 1604 req->mode = (enum wlfw_driver_mode_enum_v01)mode; 1605 req->hw_debug_valid = 1; 1606 req->hw_debug = 0; 1607 1608 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 1609 wlfw_wlan_mode_resp_msg_v01_ei, resp); 1610 if (ret < 0) { 1611 cnss_pr_err("Failed to initialize txn for mode request, mode: %s(%d), err: %d\n", 1612 cnss_qmi_mode_to_str(mode), mode, ret); 1613 goto out; 1614 } 1615 1616 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 1617 QMI_WLFW_WLAN_MODE_REQ_V01, 1618 WLFW_WLAN_MODE_REQ_MSG_V01_MAX_MSG_LEN, 1619 wlfw_wlan_mode_req_msg_v01_ei, req); 1620 if (ret < 0) { 1621 qmi_txn_cancel(&txn); 1622 cnss_pr_err("Failed to send mode request, mode: %s(%d), err: %d\n", 1623 cnss_qmi_mode_to_str(mode), mode, ret); 1624 goto out; 1625 } 1626 1627 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 1628 if (ret < 0) { 1629 cnss_pr_err("Failed to wait for response of mode request, mode: %s(%d), err: %d\n", 1630 cnss_qmi_mode_to_str(mode), mode, ret); 1631 goto out; 1632 } 1633 1634 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 1635 cnss_pr_err("Mode request failed, mode: %s(%d), result: %d, err: %d\n", 1636 cnss_qmi_mode_to_str(mode), mode, resp->resp.result, 1637 resp->resp.error); 1638 ret = -resp->resp.result; 1639 goto out; 1640 } 1641 1642 kfree(req); 1643 kfree(resp); 1644 return 0; 1645 1646 out: 1647 if (mode == CNSS_OFF) { 1648 cnss_pr_dbg("WLFW service is disconnected while sending mode off request\n"); 1649 ret = 0; 1650 } else { 1651 CNSS_QMI_ASSERT(); 1652 } 1653 kfree(req); 1654 kfree(resp); 1655 return ret; 1656 } 1657 1658 int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv, 1659 struct cnss_wlan_enable_cfg *config, 1660 const char *host_version) 1661 { 1662 struct wlfw_wlan_cfg_req_msg_v01 *req; 1663 struct wlfw_wlan_cfg_resp_msg_v01 *resp; 1664 struct qmi_txn txn; 1665 u32 i, ce_id, num_vectors, user_base_data, base_vector; 1666 int ret = 0; 1667 1668 if (!plat_priv) 1669 return -ENODEV; 1670 1671 cnss_pr_dbg("Sending WLAN config message, state: 0x%lx\n", 1672 plat_priv->driver_state); 1673 1674 req = kzalloc(sizeof(*req), GFP_KERNEL); 1675 if (!req) 1676 return -ENOMEM; 1677 1678 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 1679 if (!resp) { 1680 kfree(req); 1681 return -ENOMEM; 1682 } 1683 1684 req->host_version_valid = 1; 1685 strlcpy(req->host_version, host_version, 1686 QMI_WLFW_MAX_STR_LEN_V01 + 1); 1687 1688 req->tgt_cfg_valid = 1; 1689 if (config->num_ce_tgt_cfg > QMI_WLFW_MAX_NUM_CE_V01) 1690 req->tgt_cfg_len = QMI_WLFW_MAX_NUM_CE_V01; 1691 else 1692 req->tgt_cfg_len = config->num_ce_tgt_cfg; 1693 for (i = 0; i < req->tgt_cfg_len; i++) { 1694 req->tgt_cfg[i].pipe_num = config->ce_tgt_cfg[i].pipe_num; 1695 req->tgt_cfg[i].pipe_dir = config->ce_tgt_cfg[i].pipe_dir; 1696 req->tgt_cfg[i].nentries = config->ce_tgt_cfg[i].nentries; 1697 req->tgt_cfg[i].nbytes_max = config->ce_tgt_cfg[i].nbytes_max; 1698 req->tgt_cfg[i].flags = config->ce_tgt_cfg[i].flags; 1699 } 1700 1701 req->svc_cfg_valid = 1; 1702 if (config->num_ce_svc_pipe_cfg > QMI_WLFW_MAX_NUM_SVC_V01) 1703 req->svc_cfg_len = QMI_WLFW_MAX_NUM_SVC_V01; 1704 else 1705 req->svc_cfg_len = config->num_ce_svc_pipe_cfg; 1706 for (i = 0; i < req->svc_cfg_len; i++) { 1707 req->svc_cfg[i].service_id = config->ce_svc_cfg[i].service_id; 1708 req->svc_cfg[i].pipe_dir = config->ce_svc_cfg[i].pipe_dir; 1709 req->svc_cfg[i].pipe_num = config->ce_svc_cfg[i].pipe_num; 1710 } 1711 1712 if (plat_priv->device_id != KIWI_DEVICE_ID && 1713 plat_priv->device_id != MANGO_DEVICE_ID && 1714 plat_priv->device_id != PEACH_DEVICE_ID) { 1715 if (plat_priv->device_id == QCN7605_DEVICE_ID && 1716 config->num_shadow_reg_cfg) { 1717 req->shadow_reg_valid = 1; 1718 if (config->num_shadow_reg_cfg > 1719 QMI_WLFW_MAX_NUM_SHADOW_REG_V01) 1720 req->shadow_reg_len = 1721 QMI_WLFW_MAX_NUM_SHADOW_REG_V01; 1722 else 1723 req->shadow_reg_len = 1724 config->num_shadow_reg_cfg; 1725 memcpy(req->shadow_reg, config->shadow_reg_cfg, 1726 sizeof(struct wlfw_shadow_reg_cfg_s_v01) * 1727 req->shadow_reg_len); 1728 } else { 1729 req->shadow_reg_v2_valid = 1; 1730 1731 if (config->num_shadow_reg_v2_cfg > 1732 QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01) 1733 req->shadow_reg_v2_len = 1734 QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01; 1735 else 1736 req->shadow_reg_v2_len = 1737 config->num_shadow_reg_v2_cfg; 1738 1739 memcpy(req->shadow_reg_v2, config->shadow_reg_v2_cfg, 1740 sizeof(struct wlfw_shadow_reg_v2_cfg_s_v01) * 1741 req->shadow_reg_v2_len); 1742 } 1743 } else { 1744 req->shadow_reg_v3_valid = 1; 1745 if (config->num_shadow_reg_v3_cfg > 1746 MAX_NUM_SHADOW_REG_V3) 1747 req->shadow_reg_v3_len = MAX_NUM_SHADOW_REG_V3; 1748 else 1749 req->shadow_reg_v3_len = config->num_shadow_reg_v3_cfg; 1750 1751 plat_priv->num_shadow_regs_v3 = req->shadow_reg_v3_len; 1752 1753 cnss_pr_dbg("Shadow reg v3 len: %d\n", 1754 plat_priv->num_shadow_regs_v3); 1755 1756 memcpy(req->shadow_reg_v3, config->shadow_reg_v3_cfg, 1757 sizeof(struct wlfw_shadow_reg_v3_cfg_s_v01) * 1758 req->shadow_reg_v3_len); 1759 } 1760 1761 if (config->rri_over_ddr_cfg_valid) { 1762 req->rri_over_ddr_cfg_valid = 1; 1763 req->rri_over_ddr_cfg.base_addr_low = 1764 config->rri_over_ddr_cfg.base_addr_low; 1765 req->rri_over_ddr_cfg.base_addr_high = 1766 config->rri_over_ddr_cfg.base_addr_high; 1767 } 1768 if (config->send_msi_ce) { 1769 ret = cnss_bus_get_msi_assignment(plat_priv, 1770 CE_MSI_NAME, 1771 &num_vectors, 1772 &user_base_data, 1773 &base_vector); 1774 if (!ret) { 1775 req->msi_cfg_valid = 1; 1776 req->msi_cfg_len = QMI_WLFW_MAX_NUM_CE_V01; 1777 for (ce_id = 0; ce_id < QMI_WLFW_MAX_NUM_CE_V01; 1778 ce_id++) { 1779 req->msi_cfg[ce_id].ce_id = ce_id; 1780 req->msi_cfg[ce_id].msi_vector = 1781 (ce_id % num_vectors) + base_vector; 1782 } 1783 } 1784 } 1785 1786 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 1787 wlfw_wlan_cfg_resp_msg_v01_ei, resp); 1788 if (ret < 0) { 1789 cnss_pr_err("Failed to initialize txn for WLAN config request, err: %d\n", 1790 ret); 1791 goto out; 1792 } 1793 1794 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 1795 QMI_WLFW_WLAN_CFG_REQ_V01, 1796 WLFW_WLAN_CFG_REQ_MSG_V01_MAX_MSG_LEN, 1797 wlfw_wlan_cfg_req_msg_v01_ei, req); 1798 if (ret < 0) { 1799 qmi_txn_cancel(&txn); 1800 cnss_pr_err("Failed to send WLAN config request, err: %d\n", 1801 ret); 1802 goto out; 1803 } 1804 1805 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 1806 if (ret < 0) { 1807 cnss_pr_err("Failed to wait for response of WLAN config request, err: %d\n", 1808 ret); 1809 goto out; 1810 } 1811 1812 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 1813 cnss_pr_err("WLAN config request failed, result: %d, err: %d\n", 1814 resp->resp.result, resp->resp.error); 1815 ret = -resp->resp.result; 1816 goto out; 1817 } 1818 1819 kfree(req); 1820 kfree(resp); 1821 return 0; 1822 1823 out: 1824 CNSS_QMI_ASSERT(); 1825 kfree(req); 1826 kfree(resp); 1827 return ret; 1828 } 1829 1830 int cnss_wlfw_athdiag_read_send_sync(struct cnss_plat_data *plat_priv, 1831 u32 offset, u32 mem_type, 1832 u32 data_len, u8 *data) 1833 { 1834 struct wlfw_athdiag_read_req_msg_v01 *req; 1835 struct wlfw_athdiag_read_resp_msg_v01 *resp; 1836 struct qmi_txn txn; 1837 int ret = 0; 1838 1839 if (!plat_priv) 1840 return -ENODEV; 1841 1842 if (!data || data_len == 0 || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) { 1843 cnss_pr_err("Invalid parameters for athdiag read: data %pK, data_len %u\n", 1844 data, data_len); 1845 return -EINVAL; 1846 } 1847 1848 cnss_pr_dbg("athdiag read: state 0x%lx, offset %x, mem_type %x, data_len %u\n", 1849 plat_priv->driver_state, offset, mem_type, data_len); 1850 1851 req = kzalloc(sizeof(*req), GFP_KERNEL); 1852 if (!req) 1853 return -ENOMEM; 1854 1855 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 1856 if (!resp) { 1857 kfree(req); 1858 return -ENOMEM; 1859 } 1860 1861 req->offset = offset; 1862 req->mem_type = mem_type; 1863 req->data_len = data_len; 1864 1865 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 1866 wlfw_athdiag_read_resp_msg_v01_ei, resp); 1867 if (ret < 0) { 1868 cnss_pr_err("Failed to initialize txn for athdiag read request, err: %d\n", 1869 ret); 1870 goto out; 1871 } 1872 1873 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 1874 QMI_WLFW_ATHDIAG_READ_REQ_V01, 1875 WLFW_ATHDIAG_READ_REQ_MSG_V01_MAX_MSG_LEN, 1876 wlfw_athdiag_read_req_msg_v01_ei, req); 1877 if (ret < 0) { 1878 qmi_txn_cancel(&txn); 1879 cnss_pr_err("Failed to send athdiag read request, err: %d\n", 1880 ret); 1881 goto out; 1882 } 1883 1884 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 1885 if (ret < 0) { 1886 cnss_pr_err("Failed to wait for response of athdiag read request, err: %d\n", 1887 ret); 1888 goto out; 1889 } 1890 1891 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 1892 cnss_pr_err("Athdiag read request failed, result: %d, err: %d\n", 1893 resp->resp.result, resp->resp.error); 1894 ret = -resp->resp.result; 1895 goto out; 1896 } 1897 1898 if (!resp->data_valid || resp->data_len != data_len) { 1899 cnss_pr_err("athdiag read data is invalid, data_valid = %u, data_len = %u\n", 1900 resp->data_valid, resp->data_len); 1901 ret = -EINVAL; 1902 goto out; 1903 } 1904 1905 memcpy(data, resp->data, resp->data_len); 1906 1907 kfree(req); 1908 kfree(resp); 1909 return 0; 1910 1911 out: 1912 kfree(req); 1913 kfree(resp); 1914 return ret; 1915 } 1916 1917 int cnss_wlfw_athdiag_write_send_sync(struct cnss_plat_data *plat_priv, 1918 u32 offset, u32 mem_type, 1919 u32 data_len, u8 *data) 1920 { 1921 struct wlfw_athdiag_write_req_msg_v01 *req; 1922 struct wlfw_athdiag_write_resp_msg_v01 *resp; 1923 struct qmi_txn txn; 1924 int ret = 0; 1925 1926 if (!plat_priv) 1927 return -ENODEV; 1928 1929 if (!data || data_len == 0 || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) { 1930 cnss_pr_err("Invalid parameters for athdiag write: data %pK, data_len %u\n", 1931 data, data_len); 1932 return -EINVAL; 1933 } 1934 1935 cnss_pr_dbg("athdiag write: state 0x%lx, offset %x, mem_type %x, data_len %u, data %pK\n", 1936 plat_priv->driver_state, offset, mem_type, data_len, data); 1937 1938 req = kzalloc(sizeof(*req), GFP_KERNEL); 1939 if (!req) 1940 return -ENOMEM; 1941 1942 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 1943 if (!resp) { 1944 kfree(req); 1945 return -ENOMEM; 1946 } 1947 1948 req->offset = offset; 1949 req->mem_type = mem_type; 1950 req->data_len = data_len; 1951 memcpy(req->data, data, data_len); 1952 1953 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 1954 wlfw_athdiag_write_resp_msg_v01_ei, resp); 1955 if (ret < 0) { 1956 cnss_pr_err("Failed to initialize txn for athdiag write request, err: %d\n", 1957 ret); 1958 goto out; 1959 } 1960 1961 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 1962 QMI_WLFW_ATHDIAG_WRITE_REQ_V01, 1963 WLFW_ATHDIAG_WRITE_REQ_MSG_V01_MAX_MSG_LEN, 1964 wlfw_athdiag_write_req_msg_v01_ei, req); 1965 if (ret < 0) { 1966 qmi_txn_cancel(&txn); 1967 cnss_pr_err("Failed to send athdiag write request, err: %d\n", 1968 ret); 1969 goto out; 1970 } 1971 1972 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 1973 if (ret < 0) { 1974 cnss_pr_err("Failed to wait for response of athdiag write request, err: %d\n", 1975 ret); 1976 goto out; 1977 } 1978 1979 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 1980 cnss_pr_err("Athdiag write request failed, result: %d, err: %d\n", 1981 resp->resp.result, resp->resp.error); 1982 ret = -resp->resp.result; 1983 goto out; 1984 } 1985 1986 kfree(req); 1987 kfree(resp); 1988 return 0; 1989 1990 out: 1991 kfree(req); 1992 kfree(resp); 1993 return ret; 1994 } 1995 1996 int cnss_wlfw_ini_send_sync(struct cnss_plat_data *plat_priv, 1997 u8 fw_log_mode) 1998 { 1999 struct wlfw_ini_req_msg_v01 *req; 2000 struct wlfw_ini_resp_msg_v01 *resp; 2001 struct qmi_txn txn; 2002 int ret = 0; 2003 2004 if (!plat_priv) 2005 return -ENODEV; 2006 2007 cnss_pr_dbg("Sending ini sync request, state: 0x%lx, fw_log_mode: %d\n", 2008 plat_priv->driver_state, fw_log_mode); 2009 2010 req = kzalloc(sizeof(*req), GFP_KERNEL); 2011 if (!req) 2012 return -ENOMEM; 2013 2014 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 2015 if (!resp) { 2016 kfree(req); 2017 return -ENOMEM; 2018 } 2019 2020 req->enablefwlog_valid = 1; 2021 req->enablefwlog = fw_log_mode; 2022 2023 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 2024 wlfw_ini_resp_msg_v01_ei, resp); 2025 if (ret < 0) { 2026 cnss_pr_err("Failed to initialize txn for ini request, fw_log_mode: %d, err: %d\n", 2027 fw_log_mode, ret); 2028 goto out; 2029 } 2030 2031 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 2032 QMI_WLFW_INI_REQ_V01, 2033 WLFW_INI_REQ_MSG_V01_MAX_MSG_LEN, 2034 wlfw_ini_req_msg_v01_ei, req); 2035 if (ret < 0) { 2036 qmi_txn_cancel(&txn); 2037 cnss_pr_err("Failed to send ini request, fw_log_mode: %d, err: %d\n", 2038 fw_log_mode, ret); 2039 goto out; 2040 } 2041 2042 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 2043 if (ret < 0) { 2044 cnss_pr_err("Failed to wait for response of ini request, fw_log_mode: %d, err: %d\n", 2045 fw_log_mode, ret); 2046 goto out; 2047 } 2048 2049 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 2050 cnss_pr_err("Ini request failed, fw_log_mode: %d, result: %d, err: %d\n", 2051 fw_log_mode, resp->resp.result, resp->resp.error); 2052 ret = -resp->resp.result; 2053 goto out; 2054 } 2055 2056 kfree(req); 2057 kfree(resp); 2058 return 0; 2059 2060 out: 2061 kfree(req); 2062 kfree(resp); 2063 return ret; 2064 } 2065 2066 int cnss_wlfw_send_pcie_gen_speed_sync(struct cnss_plat_data *plat_priv) 2067 { 2068 struct wlfw_pcie_gen_switch_req_msg_v01 req; 2069 struct wlfw_pcie_gen_switch_resp_msg_v01 resp = {0}; 2070 struct qmi_txn txn; 2071 int ret = 0; 2072 2073 if (!plat_priv) 2074 return -ENODEV; 2075 2076 if (plat_priv->pcie_gen_speed == QMI_PCIE_GEN_SPEED_INVALID_V01 || 2077 !plat_priv->fw_pcie_gen_switch) { 2078 cnss_pr_dbg("PCIE Gen speed not setup\n"); 2079 return 0; 2080 } 2081 2082 cnss_pr_dbg("Sending PCIE Gen speed: %d state: 0x%lx\n", 2083 plat_priv->pcie_gen_speed, plat_priv->driver_state); 2084 req.pcie_speed = (enum wlfw_pcie_gen_speed_v01) 2085 plat_priv->pcie_gen_speed; 2086 2087 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 2088 wlfw_pcie_gen_switch_resp_msg_v01_ei, &resp); 2089 if (ret < 0) { 2090 cnss_pr_err("Failed to initialize txn for PCIE speed switch err: %d\n", 2091 ret); 2092 goto out; 2093 } 2094 2095 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 2096 QMI_WLFW_PCIE_GEN_SWITCH_REQ_V01, 2097 WLFW_PCIE_GEN_SWITCH_REQ_MSG_V01_MAX_MSG_LEN, 2098 wlfw_pcie_gen_switch_req_msg_v01_ei, &req); 2099 if (ret < 0) { 2100 qmi_txn_cancel(&txn); 2101 cnss_pr_err("Failed to send PCIE speed switch, err: %d\n", ret); 2102 goto out; 2103 } 2104 2105 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 2106 if (ret < 0) { 2107 cnss_pr_err("Failed to wait for PCIE Gen switch resp, err: %d\n", 2108 ret); 2109 goto out; 2110 } 2111 2112 if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { 2113 cnss_pr_err("PCIE Gen Switch req failed, Speed: %d, result: %d, err: %d\n", 2114 plat_priv->pcie_gen_speed, resp.resp.result, 2115 resp.resp.error); 2116 ret = -resp.resp.result; 2117 } 2118 out: 2119 /* Reset PCIE Gen speed after one time use */ 2120 plat_priv->pcie_gen_speed = QMI_PCIE_GEN_SPEED_INVALID_V01; 2121 return ret; 2122 } 2123 2124 int cnss_wlfw_antenna_switch_send_sync(struct cnss_plat_data *plat_priv) 2125 { 2126 struct wlfw_antenna_switch_req_msg_v01 *req; 2127 struct wlfw_antenna_switch_resp_msg_v01 *resp; 2128 struct qmi_txn txn; 2129 int ret = 0; 2130 2131 if (!plat_priv) 2132 return -ENODEV; 2133 2134 cnss_pr_dbg("Sending antenna switch sync request, state: 0x%lx\n", 2135 plat_priv->driver_state); 2136 2137 req = kzalloc(sizeof(*req), GFP_KERNEL); 2138 if (!req) 2139 return -ENOMEM; 2140 2141 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 2142 if (!resp) { 2143 kfree(req); 2144 return -ENOMEM; 2145 } 2146 2147 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 2148 wlfw_antenna_switch_resp_msg_v01_ei, resp); 2149 if (ret < 0) { 2150 cnss_pr_err("Failed to initialize txn for antenna switch request, err: %d\n", 2151 ret); 2152 goto out; 2153 } 2154 2155 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 2156 QMI_WLFW_ANTENNA_SWITCH_REQ_V01, 2157 WLFW_ANTENNA_SWITCH_REQ_MSG_V01_MAX_MSG_LEN, 2158 wlfw_antenna_switch_req_msg_v01_ei, req); 2159 if (ret < 0) { 2160 qmi_txn_cancel(&txn); 2161 cnss_pr_err("Failed to send antenna switch request, err: %d\n", 2162 ret); 2163 goto out; 2164 } 2165 2166 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 2167 if (ret < 0) { 2168 cnss_pr_err("Failed to wait for response of antenna switch request, err: %d\n", 2169 ret); 2170 goto out; 2171 } 2172 2173 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 2174 cnss_pr_dbg("Antenna switch request failed, result: %d, err: %d\n", 2175 resp->resp.result, resp->resp.error); 2176 ret = -resp->resp.result; 2177 goto out; 2178 } 2179 2180 if (resp->antenna_valid) 2181 plat_priv->antenna = resp->antenna; 2182 2183 cnss_pr_dbg("Antenna valid: %u, antenna 0x%llx\n", 2184 resp->antenna_valid, resp->antenna); 2185 2186 kfree(req); 2187 kfree(resp); 2188 return 0; 2189 2190 out: 2191 kfree(req); 2192 kfree(resp); 2193 return ret; 2194 } 2195 2196 int cnss_wlfw_antenna_grant_send_sync(struct cnss_plat_data *plat_priv) 2197 { 2198 struct wlfw_antenna_grant_req_msg_v01 *req; 2199 struct wlfw_antenna_grant_resp_msg_v01 *resp; 2200 struct qmi_txn txn; 2201 int ret = 0; 2202 2203 if (!plat_priv) 2204 return -ENODEV; 2205 2206 cnss_pr_dbg("Sending antenna grant sync request, state: 0x%lx, grant 0x%llx\n", 2207 plat_priv->driver_state, plat_priv->grant); 2208 2209 req = kzalloc(sizeof(*req), GFP_KERNEL); 2210 if (!req) 2211 return -ENOMEM; 2212 2213 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 2214 if (!resp) { 2215 kfree(req); 2216 return -ENOMEM; 2217 } 2218 2219 req->grant_valid = 1; 2220 req->grant = plat_priv->grant; 2221 2222 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 2223 wlfw_antenna_grant_resp_msg_v01_ei, resp); 2224 if (ret < 0) { 2225 cnss_pr_err("Failed to initialize txn for antenna grant request, err: %d\n", 2226 ret); 2227 goto out; 2228 } 2229 2230 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 2231 QMI_WLFW_ANTENNA_GRANT_REQ_V01, 2232 WLFW_ANTENNA_GRANT_REQ_MSG_V01_MAX_MSG_LEN, 2233 wlfw_antenna_grant_req_msg_v01_ei, req); 2234 if (ret < 0) { 2235 qmi_txn_cancel(&txn); 2236 cnss_pr_err("Failed to send antenna grant request, err: %d\n", 2237 ret); 2238 goto out; 2239 } 2240 2241 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 2242 if (ret < 0) { 2243 cnss_pr_err("Failed to wait for response of antenna grant request, err: %d\n", 2244 ret); 2245 goto out; 2246 } 2247 2248 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 2249 cnss_pr_err("Antenna grant request failed, result: %d, err: %d\n", 2250 resp->resp.result, resp->resp.error); 2251 ret = -resp->resp.result; 2252 goto out; 2253 } 2254 2255 kfree(req); 2256 kfree(resp); 2257 return 0; 2258 2259 out: 2260 kfree(req); 2261 kfree(resp); 2262 return ret; 2263 } 2264 2265 int cnss_wlfw_qdss_trace_mem_info_send_sync(struct cnss_plat_data *plat_priv) 2266 { 2267 struct wlfw_qdss_trace_mem_info_req_msg_v01 *req; 2268 struct wlfw_qdss_trace_mem_info_resp_msg_v01 *resp; 2269 struct qmi_txn txn; 2270 struct cnss_fw_mem *qdss_mem = plat_priv->qdss_mem; 2271 int ret = 0; 2272 int i; 2273 2274 cnss_pr_dbg("Sending QDSS trace mem info, state: 0x%lx\n", 2275 plat_priv->driver_state); 2276 2277 req = kzalloc(sizeof(*req), GFP_KERNEL); 2278 if (!req) 2279 return -ENOMEM; 2280 2281 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 2282 if (!resp) { 2283 kfree(req); 2284 return -ENOMEM; 2285 } 2286 2287 if (plat_priv->qdss_mem_seg_len > QMI_WLFW_MAX_NUM_MEM_SEG_V01) { 2288 cnss_pr_err("Invalid seg len %u\n", plat_priv->qdss_mem_seg_len); 2289 ret = -EINVAL; 2290 goto out; 2291 } 2292 2293 req->mem_seg_len = plat_priv->qdss_mem_seg_len; 2294 for (i = 0; i < req->mem_seg_len; i++) { 2295 cnss_pr_dbg("Memory for FW, va: 0x%pK, pa: %pa, size: 0x%zx, type: %u\n", 2296 qdss_mem[i].va, &qdss_mem[i].pa, 2297 qdss_mem[i].size, qdss_mem[i].type); 2298 2299 req->mem_seg[i].addr = qdss_mem[i].pa; 2300 req->mem_seg[i].size = qdss_mem[i].size; 2301 req->mem_seg[i].type = qdss_mem[i].type; 2302 } 2303 2304 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 2305 wlfw_qdss_trace_mem_info_resp_msg_v01_ei, resp); 2306 if (ret < 0) { 2307 cnss_pr_err("Fail to initialize txn for QDSS trace mem request: err %d\n", 2308 ret); 2309 goto out; 2310 } 2311 2312 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 2313 QMI_WLFW_QDSS_TRACE_MEM_INFO_REQ_V01, 2314 WLFW_QDSS_TRACE_MEM_INFO_REQ_MSG_V01_MAX_MSG_LEN, 2315 wlfw_qdss_trace_mem_info_req_msg_v01_ei, req); 2316 if (ret < 0) { 2317 qmi_txn_cancel(&txn); 2318 cnss_pr_err("Fail to send QDSS trace mem info request: err %d\n", 2319 ret); 2320 goto out; 2321 } 2322 2323 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 2324 if (ret < 0) { 2325 cnss_pr_err("Fail to wait for response of QDSS trace mem info request, err %d\n", 2326 ret); 2327 goto out; 2328 } 2329 2330 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 2331 cnss_pr_err("QDSS trace mem info request failed, result: %d, err: %d\n", 2332 resp->resp.result, resp->resp.error); 2333 ret = -resp->resp.result; 2334 goto out; 2335 } 2336 2337 kfree(req); 2338 kfree(resp); 2339 return 0; 2340 2341 out: 2342 kfree(req); 2343 kfree(resp); 2344 return ret; 2345 } 2346 2347 int cnss_wlfw_send_host_wfc_call_status(struct cnss_plat_data *plat_priv, 2348 struct cnss_wfc_cfg cfg) 2349 { 2350 struct wlfw_wfc_call_status_req_msg_v01 *req; 2351 struct wlfw_wfc_call_status_resp_msg_v01 *resp; 2352 struct qmi_txn txn; 2353 int ret = 0; 2354 2355 if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) { 2356 cnss_pr_err("Drop host WFC indication as FW not initialized\n"); 2357 return -EINVAL; 2358 } 2359 req = kzalloc(sizeof(*req), GFP_KERNEL); 2360 if (!req) 2361 return -ENOMEM; 2362 2363 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 2364 if (!resp) { 2365 kfree(req); 2366 return -ENOMEM; 2367 } 2368 2369 req->wfc_call_active_valid = 1; 2370 req->wfc_call_active = cfg.mode; 2371 2372 cnss_pr_dbg("CNSS->FW: WFC_CALL_REQ: state: 0x%lx\n", 2373 plat_priv->driver_state); 2374 2375 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 2376 wlfw_wfc_call_status_resp_msg_v01_ei, resp); 2377 if (ret < 0) { 2378 cnss_pr_err("CNSS->FW: WFC_CALL_REQ: QMI Txn Init: Err %d\n", 2379 ret); 2380 goto out; 2381 } 2382 2383 cnss_pr_dbg("Send WFC Mode: %d\n", cfg.mode); 2384 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 2385 QMI_WLFW_WFC_CALL_STATUS_REQ_V01, 2386 WLFW_WFC_CALL_STATUS_REQ_MSG_V01_MAX_MSG_LEN, 2387 wlfw_wfc_call_status_req_msg_v01_ei, req); 2388 if (ret < 0) { 2389 qmi_txn_cancel(&txn); 2390 cnss_pr_err("CNSS->FW: WFC_CALL_REQ: QMI Send Err: %d\n", 2391 ret); 2392 goto out; 2393 } 2394 2395 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 2396 if (ret < 0) { 2397 cnss_pr_err("FW->CNSS: WFC_CALL_RSP: QMI Wait Err: %d\n", 2398 ret); 2399 goto out; 2400 } 2401 2402 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 2403 cnss_pr_err("FW->CNSS: WFC_CALL_RSP: Result: %d Err: %d\n", 2404 resp->resp.result, resp->resp.error); 2405 ret = -EINVAL; 2406 goto out; 2407 } 2408 ret = 0; 2409 out: 2410 kfree(req); 2411 kfree(resp); 2412 return ret; 2413 2414 } 2415 static int cnss_wlfw_wfc_call_status_send_sync 2416 (struct cnss_plat_data *plat_priv, 2417 const struct ims_private_service_wfc_call_status_ind_msg_v01 *ind_msg) 2418 { 2419 struct wlfw_wfc_call_status_req_msg_v01 *req; 2420 struct wlfw_wfc_call_status_resp_msg_v01 *resp; 2421 struct qmi_txn txn; 2422 int ret = 0; 2423 2424 if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) { 2425 cnss_pr_err("Drop IMS WFC indication as FW not initialized\n"); 2426 return -EINVAL; 2427 } 2428 req = kzalloc(sizeof(*req), GFP_KERNEL); 2429 if (!req) 2430 return -ENOMEM; 2431 2432 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 2433 if (!resp) { 2434 kfree(req); 2435 return -ENOMEM; 2436 } 2437 2438 /** 2439 * WFC Call r1 design has CNSS as pass thru using opaque hex buffer. 2440 * But in r2 update QMI structure is expanded and as an effect qmi 2441 * decoded structures have padding. Thus we cannot use buffer design. 2442 * For backward compatibility for r1 design copy only wfc_call_active 2443 * value in hex buffer. 2444 */ 2445 req->wfc_call_status_len = sizeof(ind_msg->wfc_call_active); 2446 req->wfc_call_status[0] = ind_msg->wfc_call_active; 2447 2448 /* wfc_call_active is mandatory in IMS indication */ 2449 req->wfc_call_active_valid = 1; 2450 req->wfc_call_active = ind_msg->wfc_call_active; 2451 req->all_wfc_calls_held_valid = ind_msg->all_wfc_calls_held_valid; 2452 req->all_wfc_calls_held = ind_msg->all_wfc_calls_held; 2453 req->is_wfc_emergency_valid = ind_msg->is_wfc_emergency_valid; 2454 req->is_wfc_emergency = ind_msg->is_wfc_emergency; 2455 req->twt_ims_start_valid = ind_msg->twt_ims_start_valid; 2456 req->twt_ims_start = ind_msg->twt_ims_start; 2457 req->twt_ims_int_valid = ind_msg->twt_ims_int_valid; 2458 req->twt_ims_int = ind_msg->twt_ims_int; 2459 req->media_quality_valid = ind_msg->media_quality_valid; 2460 req->media_quality = 2461 (enum wlfw_wfc_media_quality_v01)ind_msg->media_quality; 2462 2463 cnss_pr_dbg("CNSS->FW: WFC_CALL_REQ: state: 0x%lx\n", 2464 plat_priv->driver_state); 2465 2466 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 2467 wlfw_wfc_call_status_resp_msg_v01_ei, resp); 2468 if (ret < 0) { 2469 cnss_pr_err("CNSS->FW: WFC_CALL_REQ: QMI Txn Init: Err %d\n", 2470 ret); 2471 goto out; 2472 } 2473 2474 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 2475 QMI_WLFW_WFC_CALL_STATUS_REQ_V01, 2476 WLFW_WFC_CALL_STATUS_REQ_MSG_V01_MAX_MSG_LEN, 2477 wlfw_wfc_call_status_req_msg_v01_ei, req); 2478 if (ret < 0) { 2479 qmi_txn_cancel(&txn); 2480 cnss_pr_err("CNSS->FW: WFC_CALL_REQ: QMI Send Err: %d\n", 2481 ret); 2482 goto out; 2483 } 2484 2485 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 2486 if (ret < 0) { 2487 cnss_pr_err("FW->CNSS: WFC_CALL_RSP: QMI Wait Err: %d\n", 2488 ret); 2489 goto out; 2490 } 2491 2492 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 2493 cnss_pr_err("FW->CNSS: WFC_CALL_RSP: Result: %d Err: %d\n", 2494 resp->resp.result, resp->resp.error); 2495 ret = -resp->resp.result; 2496 goto out; 2497 } 2498 ret = 0; 2499 out: 2500 kfree(req); 2501 kfree(resp); 2502 return ret; 2503 } 2504 2505 int cnss_wlfw_dynamic_feature_mask_send_sync(struct cnss_plat_data *plat_priv) 2506 { 2507 struct wlfw_dynamic_feature_mask_req_msg_v01 *req; 2508 struct wlfw_dynamic_feature_mask_resp_msg_v01 *resp; 2509 struct qmi_txn txn; 2510 int ret = 0; 2511 2512 cnss_pr_dbg("Sending dynamic feature mask 0x%llx, state: 0x%lx\n", 2513 plat_priv->dynamic_feature, 2514 plat_priv->driver_state); 2515 2516 req = kzalloc(sizeof(*req), GFP_KERNEL); 2517 if (!req) 2518 return -ENOMEM; 2519 2520 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 2521 if (!resp) { 2522 kfree(req); 2523 return -ENOMEM; 2524 } 2525 2526 req->mask_valid = 1; 2527 req->mask = plat_priv->dynamic_feature; 2528 2529 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 2530 wlfw_dynamic_feature_mask_resp_msg_v01_ei, resp); 2531 if (ret < 0) { 2532 cnss_pr_err("Fail to initialize txn for dynamic feature mask request: err %d\n", 2533 ret); 2534 goto out; 2535 } 2536 2537 ret = qmi_send_request 2538 (&plat_priv->qmi_wlfw, NULL, &txn, 2539 QMI_WLFW_DYNAMIC_FEATURE_MASK_REQ_V01, 2540 WLFW_DYNAMIC_FEATURE_MASK_REQ_MSG_V01_MAX_MSG_LEN, 2541 wlfw_dynamic_feature_mask_req_msg_v01_ei, req); 2542 if (ret < 0) { 2543 qmi_txn_cancel(&txn); 2544 cnss_pr_err("Fail to send dynamic feature mask request: err %d\n", 2545 ret); 2546 goto out; 2547 } 2548 2549 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 2550 if (ret < 0) { 2551 cnss_pr_err("Fail to wait for response of dynamic feature mask request, err %d\n", 2552 ret); 2553 goto out; 2554 } 2555 2556 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 2557 cnss_pr_err("Dynamic feature mask request failed, result: %d, err: %d\n", 2558 resp->resp.result, resp->resp.error); 2559 ret = -resp->resp.result; 2560 goto out; 2561 } 2562 2563 out: 2564 kfree(req); 2565 kfree(resp); 2566 return ret; 2567 } 2568 2569 int cnss_wlfw_get_info_send_sync(struct cnss_plat_data *plat_priv, int type, 2570 void *cmd, int cmd_len) 2571 { 2572 struct wlfw_get_info_req_msg_v01 *req; 2573 struct wlfw_get_info_resp_msg_v01 *resp; 2574 struct qmi_txn txn; 2575 int ret = 0; 2576 2577 cnss_pr_buf("Sending get info message, type: %d, cmd length: %d, state: 0x%lx\n", 2578 type, cmd_len, plat_priv->driver_state); 2579 2580 if (cmd_len > QMI_WLFW_MAX_DATA_SIZE_V01) 2581 return -EINVAL; 2582 2583 req = kzalloc(sizeof(*req), GFP_KERNEL); 2584 if (!req) 2585 return -ENOMEM; 2586 2587 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 2588 if (!resp) { 2589 kfree(req); 2590 return -ENOMEM; 2591 } 2592 2593 req->type = type; 2594 req->data_len = cmd_len; 2595 memcpy(req->data, cmd, req->data_len); 2596 2597 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 2598 wlfw_get_info_resp_msg_v01_ei, resp); 2599 if (ret < 0) { 2600 cnss_pr_err("Failed to initialize txn for get info request, err: %d\n", 2601 ret); 2602 goto out; 2603 } 2604 2605 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 2606 QMI_WLFW_GET_INFO_REQ_V01, 2607 WLFW_GET_INFO_REQ_MSG_V01_MAX_MSG_LEN, 2608 wlfw_get_info_req_msg_v01_ei, req); 2609 if (ret < 0) { 2610 qmi_txn_cancel(&txn); 2611 cnss_pr_err("Failed to send get info request, err: %d\n", 2612 ret); 2613 goto out; 2614 } 2615 2616 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 2617 if (ret < 0) { 2618 cnss_pr_err("Failed to wait for response of get info request, err: %d\n", 2619 ret); 2620 goto out; 2621 } 2622 2623 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 2624 cnss_pr_err("Get info request failed, result: %d, err: %d\n", 2625 resp->resp.result, resp->resp.error); 2626 ret = -resp->resp.result; 2627 goto out; 2628 } 2629 2630 kfree(req); 2631 kfree(resp); 2632 return 0; 2633 2634 out: 2635 kfree(req); 2636 kfree(resp); 2637 return ret; 2638 } 2639 2640 unsigned int cnss_get_qmi_timeout(struct cnss_plat_data *plat_priv) 2641 { 2642 return QMI_WLFW_TIMEOUT_MS; 2643 } 2644 2645 static void cnss_wlfw_request_mem_ind_cb(struct qmi_handle *qmi_wlfw, 2646 struct sockaddr_qrtr *sq, 2647 struct qmi_txn *txn, const void *data) 2648 { 2649 struct cnss_plat_data *plat_priv = 2650 container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw); 2651 const struct wlfw_request_mem_ind_msg_v01 *ind_msg = data; 2652 int i; 2653 2654 cnss_pr_dbg("Received QMI WLFW request memory indication\n"); 2655 2656 if (!txn) { 2657 cnss_pr_err("Spurious indication\n"); 2658 return; 2659 } 2660 2661 if (ind_msg->mem_seg_len > QMI_WLFW_MAX_NUM_MEM_SEG_V01) { 2662 cnss_pr_err("Invalid seg len %u\n", ind_msg->mem_seg_len); 2663 return; 2664 } 2665 2666 plat_priv->fw_mem_seg_len = ind_msg->mem_seg_len; 2667 for (i = 0; i < plat_priv->fw_mem_seg_len; i++) { 2668 cnss_pr_dbg("FW requests for memory, size: 0x%x, type: %u\n", 2669 ind_msg->mem_seg[i].size, ind_msg->mem_seg[i].type); 2670 plat_priv->fw_mem[i].type = ind_msg->mem_seg[i].type; 2671 plat_priv->fw_mem[i].size = ind_msg->mem_seg[i].size; 2672 if (!plat_priv->fw_mem[i].va && 2673 plat_priv->fw_mem[i].type == CNSS_MEM_TYPE_DDR) 2674 plat_priv->fw_mem[i].attrs |= 2675 DMA_ATTR_FORCE_CONTIGUOUS; 2676 if (plat_priv->fw_mem[i].type == CNSS_MEM_CAL_V01) 2677 plat_priv->cal_mem = &plat_priv->fw_mem[i]; 2678 } 2679 2680 cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_REQUEST_MEM, 2681 0, NULL); 2682 } 2683 2684 static void cnss_wlfw_fw_mem_ready_ind_cb(struct qmi_handle *qmi_wlfw, 2685 struct sockaddr_qrtr *sq, 2686 struct qmi_txn *txn, const void *data) 2687 { 2688 struct cnss_plat_data *plat_priv = 2689 container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw); 2690 2691 cnss_pr_dbg("Received QMI WLFW FW memory ready indication\n"); 2692 2693 if (!txn) { 2694 cnss_pr_err("Spurious indication\n"); 2695 return; 2696 } 2697 2698 cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_FW_MEM_READY, 2699 0, NULL); 2700 } 2701 2702 /** 2703 * cnss_wlfw_fw_ready_ind_cb: FW ready indication handler (Helium arch) 2704 * 2705 * This event is not required for HST/ HSP as FW calibration done is 2706 * provided in QMI_WLFW_CAL_DONE_IND_V01 2707 */ 2708 static void cnss_wlfw_fw_ready_ind_cb(struct qmi_handle *qmi_wlfw, 2709 struct sockaddr_qrtr *sq, 2710 struct qmi_txn *txn, const void *data) 2711 { 2712 struct cnss_plat_data *plat_priv = 2713 container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw); 2714 struct cnss_cal_info *cal_info; 2715 2716 if (!txn) { 2717 cnss_pr_err("Spurious indication\n"); 2718 return; 2719 } 2720 2721 if (plat_priv->device_id == QCA6390_DEVICE_ID || 2722 plat_priv->device_id == QCA6490_DEVICE_ID) { 2723 cnss_pr_dbg("Ignore FW Ready Indication for HST/HSP"); 2724 return; 2725 } 2726 2727 cnss_pr_dbg("Received QMI WLFW FW ready indication.\n"); 2728 cal_info = kzalloc(sizeof(*cal_info), GFP_KERNEL); 2729 if (!cal_info) 2730 return; 2731 2732 cal_info->cal_status = CNSS_CAL_DONE; 2733 cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE, 2734 0, cal_info); 2735 } 2736 2737 static void cnss_wlfw_fw_init_done_ind_cb(struct qmi_handle *qmi_wlfw, 2738 struct sockaddr_qrtr *sq, 2739 struct qmi_txn *txn, const void *data) 2740 { 2741 struct cnss_plat_data *plat_priv = 2742 container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw); 2743 2744 cnss_pr_dbg("Received QMI WLFW FW initialization done indication\n"); 2745 2746 if (!txn) { 2747 cnss_pr_err("Spurious indication\n"); 2748 return; 2749 } 2750 2751 cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_FW_READY, 0, NULL); 2752 } 2753 2754 static void cnss_wlfw_pin_result_ind_cb(struct qmi_handle *qmi_wlfw, 2755 struct sockaddr_qrtr *sq, 2756 struct qmi_txn *txn, const void *data) 2757 { 2758 struct cnss_plat_data *plat_priv = 2759 container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw); 2760 const struct wlfw_pin_connect_result_ind_msg_v01 *ind_msg = data; 2761 2762 cnss_pr_dbg("Received QMI WLFW pin connect result indication\n"); 2763 2764 if (!txn) { 2765 cnss_pr_err("Spurious indication\n"); 2766 return; 2767 } 2768 2769 if (ind_msg->pwr_pin_result_valid) 2770 plat_priv->pin_result.fw_pwr_pin_result = 2771 ind_msg->pwr_pin_result; 2772 if (ind_msg->phy_io_pin_result_valid) 2773 plat_priv->pin_result.fw_phy_io_pin_result = 2774 ind_msg->phy_io_pin_result; 2775 if (ind_msg->rf_pin_result_valid) 2776 plat_priv->pin_result.fw_rf_pin_result = ind_msg->rf_pin_result; 2777 2778 cnss_pr_dbg("Pin connect Result: pwr_pin: 0x%x phy_io_pin: 0x%x rf_io_pin: 0x%x\n", 2779 ind_msg->pwr_pin_result, ind_msg->phy_io_pin_result, 2780 ind_msg->rf_pin_result); 2781 } 2782 2783 int cnss_wlfw_cal_report_req_send_sync(struct cnss_plat_data *plat_priv, 2784 u32 cal_file_download_size) 2785 { 2786 struct wlfw_cal_report_req_msg_v01 req = {0}; 2787 struct wlfw_cal_report_resp_msg_v01 resp = {0}; 2788 struct qmi_txn txn; 2789 int ret = 0; 2790 2791 cnss_pr_dbg("Sending cal file report request. File size: %d, state: 0x%lx\n", 2792 cal_file_download_size, plat_priv->driver_state); 2793 req.cal_file_download_size_valid = 1; 2794 req.cal_file_download_size = cal_file_download_size; 2795 2796 ret = qmi_txn_init(&plat_priv->qmi_wlfw, &txn, 2797 wlfw_cal_report_resp_msg_v01_ei, &resp); 2798 if (ret < 0) { 2799 cnss_pr_err("Failed to initialize txn for Cal Report request, err: %d\n", 2800 ret); 2801 goto out; 2802 } 2803 ret = qmi_send_request(&plat_priv->qmi_wlfw, NULL, &txn, 2804 QMI_WLFW_CAL_REPORT_REQ_V01, 2805 WLFW_CAL_REPORT_REQ_MSG_V01_MAX_MSG_LEN, 2806 wlfw_cal_report_req_msg_v01_ei, &req); 2807 if (ret < 0) { 2808 qmi_txn_cancel(&txn); 2809 cnss_pr_err("Failed to send Cal Report request, err: %d\n", 2810 ret); 2811 goto out; 2812 } 2813 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 2814 if (ret < 0) { 2815 cnss_pr_err("Failed to wait for response of Cal Report request, err: %d\n", 2816 ret); 2817 goto out; 2818 } 2819 if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { 2820 cnss_pr_err("Cal Report request failed, result: %d, err: %d\n", 2821 resp.resp.result, resp.resp.error); 2822 ret = -resp.resp.result; 2823 goto out; 2824 } 2825 out: 2826 return ret; 2827 } 2828 2829 static void cnss_wlfw_cal_done_ind_cb(struct qmi_handle *qmi_wlfw, 2830 struct sockaddr_qrtr *sq, 2831 struct qmi_txn *txn, const void *data) 2832 { 2833 struct cnss_plat_data *plat_priv = 2834 container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw); 2835 const struct wlfw_cal_done_ind_msg_v01 *ind = data; 2836 struct cnss_cal_info *cal_info; 2837 2838 cnss_pr_dbg("Received Cal done indication. File size: %d\n", 2839 ind->cal_file_upload_size); 2840 cnss_pr_info("Calibration took %d ms\n", 2841 jiffies_to_msecs(jiffies - plat_priv->cal_time)); 2842 if (!txn) { 2843 cnss_pr_err("Spurious indication\n"); 2844 return; 2845 } 2846 if (ind->cal_file_upload_size_valid) 2847 plat_priv->cal_file_size = ind->cal_file_upload_size; 2848 cal_info = kzalloc(sizeof(*cal_info), GFP_KERNEL); 2849 if (!cal_info) 2850 return; 2851 2852 cal_info->cal_status = CNSS_CAL_DONE; 2853 cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE, 2854 0, cal_info); 2855 } 2856 2857 static void cnss_wlfw_qdss_trace_req_mem_ind_cb(struct qmi_handle *qmi_wlfw, 2858 struct sockaddr_qrtr *sq, 2859 struct qmi_txn *txn, 2860 const void *data) 2861 { 2862 struct cnss_plat_data *plat_priv = 2863 container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw); 2864 const struct wlfw_qdss_trace_req_mem_ind_msg_v01 *ind_msg = data; 2865 int i; 2866 2867 cnss_pr_dbg("Received QMI WLFW QDSS trace request mem indication\n"); 2868 2869 if (!txn) { 2870 cnss_pr_err("Spurious indication\n"); 2871 return; 2872 } 2873 2874 if (plat_priv->qdss_mem_seg_len) { 2875 cnss_pr_err("Ignore double allocation for QDSS trace, current len %u\n", 2876 plat_priv->qdss_mem_seg_len); 2877 return; 2878 } 2879 2880 if (ind_msg->mem_seg_len > QMI_WLFW_MAX_NUM_MEM_SEG_V01) { 2881 cnss_pr_err("Invalid seg len %u\n", ind_msg->mem_seg_len); 2882 return; 2883 } 2884 2885 plat_priv->qdss_mem_seg_len = ind_msg->mem_seg_len; 2886 for (i = 0; i < plat_priv->qdss_mem_seg_len; i++) { 2887 cnss_pr_dbg("QDSS requests for memory, size: 0x%x, type: %u\n", 2888 ind_msg->mem_seg[i].size, ind_msg->mem_seg[i].type); 2889 plat_priv->qdss_mem[i].type = ind_msg->mem_seg[i].type; 2890 plat_priv->qdss_mem[i].size = ind_msg->mem_seg[i].size; 2891 } 2892 2893 cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_MEM, 2894 0, NULL); 2895 } 2896 2897 /** 2898 * cnss_wlfw_fw_mem_file_save_ind_cb: Save given FW mem to filesystem 2899 * 2900 * QDSS_TRACE_SAVE_IND feature is overloaded to provide any host allocated 2901 * fw memory segment for dumping to file system. Only one type of mem can be 2902 * saved per indication and is provided in mem seg index 0. 2903 * 2904 * Return: None 2905 */ 2906 static void cnss_wlfw_fw_mem_file_save_ind_cb(struct qmi_handle *qmi_wlfw, 2907 struct sockaddr_qrtr *sq, 2908 struct qmi_txn *txn, 2909 const void *data) 2910 { 2911 struct cnss_plat_data *plat_priv = 2912 container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw); 2913 const struct wlfw_qdss_trace_save_ind_msg_v01 *ind_msg = data; 2914 struct cnss_qmi_event_fw_mem_file_save_data *event_data; 2915 int i = 0; 2916 2917 if (!txn || !data) { 2918 cnss_pr_err("Spurious indication\n"); 2919 return; 2920 } 2921 cnss_pr_dbg_buf("QMI fw_mem_file_save: source: %d mem_seg: %d type: %u len: %u\n", 2922 ind_msg->source, ind_msg->mem_seg_valid, 2923 ind_msg->mem_seg[0].type, ind_msg->mem_seg_len); 2924 2925 event_data = kzalloc(sizeof(*event_data), GFP_KERNEL); 2926 if (!event_data) 2927 return; 2928 2929 event_data->mem_type = ind_msg->mem_seg[0].type; 2930 event_data->mem_seg_len = ind_msg->mem_seg_len; 2931 event_data->total_size = ind_msg->total_size; 2932 2933 if (ind_msg->mem_seg_valid) { 2934 if (ind_msg->mem_seg_len > QMI_WLFW_MAX_STR_LEN_V01) { 2935 cnss_pr_err("Invalid seg len indication\n"); 2936 goto free_event_data; 2937 } 2938 for (i = 0; i < ind_msg->mem_seg_len; i++) { 2939 event_data->mem_seg[i].addr = ind_msg->mem_seg[i].addr; 2940 event_data->mem_seg[i].size = ind_msg->mem_seg[i].size; 2941 if (event_data->mem_type != ind_msg->mem_seg[i].type) { 2942 cnss_pr_err("FW Mem file save ind cannot have multiple mem types\n"); 2943 goto free_event_data; 2944 } 2945 cnss_pr_dbg_buf("seg-%d: addr 0x%llx size 0x%x\n", 2946 i, ind_msg->mem_seg[i].addr, 2947 ind_msg->mem_seg[i].size); 2948 } 2949 } 2950 2951 if (ind_msg->file_name_valid) 2952 strlcpy(event_data->file_name, ind_msg->file_name, 2953 QMI_WLFW_MAX_STR_LEN_V01 + 1); 2954 if (ind_msg->source == 1) { 2955 if (!ind_msg->file_name_valid) 2956 strlcpy(event_data->file_name, "qdss_trace_wcss_etb", 2957 QMI_WLFW_MAX_STR_LEN_V01 + 1); 2958 cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_DATA, 2959 0, event_data); 2960 } else { 2961 if (event_data->mem_type == QMI_WLFW_MEM_QDSS_V01) { 2962 if (!ind_msg->file_name_valid) 2963 strlcpy(event_data->file_name, "qdss_trace_ddr", 2964 QMI_WLFW_MAX_STR_LEN_V01 + 1); 2965 } else { 2966 if (!ind_msg->file_name_valid) 2967 strlcpy(event_data->file_name, "fw_mem_dump", 2968 QMI_WLFW_MAX_STR_LEN_V01 + 1); 2969 } 2970 2971 cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_FW_MEM_FILE_SAVE, 2972 0, event_data); 2973 } 2974 2975 return; 2976 2977 free_event_data: 2978 kfree(event_data); 2979 } 2980 2981 static void cnss_wlfw_qdss_trace_free_ind_cb(struct qmi_handle *qmi_wlfw, 2982 struct sockaddr_qrtr *sq, 2983 struct qmi_txn *txn, 2984 const void *data) 2985 { 2986 struct cnss_plat_data *plat_priv = 2987 container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw); 2988 2989 cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_QDSS_TRACE_FREE, 2990 0, NULL); 2991 } 2992 2993 static void cnss_wlfw_respond_get_info_ind_cb(struct qmi_handle *qmi_wlfw, 2994 struct sockaddr_qrtr *sq, 2995 struct qmi_txn *txn, 2996 const void *data) 2997 { 2998 struct cnss_plat_data *plat_priv = 2999 container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw); 3000 const struct wlfw_respond_get_info_ind_msg_v01 *ind_msg = data; 3001 3002 cnss_pr_buf("Received QMI WLFW respond get info indication\n"); 3003 3004 if (!txn) { 3005 cnss_pr_err("Spurious indication\n"); 3006 return; 3007 } 3008 3009 cnss_pr_buf("Extract message with event length: %d, type: %d, is last: %d, seq no: %d\n", 3010 ind_msg->data_len, ind_msg->type, 3011 ind_msg->is_last, ind_msg->seq_no); 3012 3013 if (plat_priv->get_info_cb_ctx && plat_priv->get_info_cb) 3014 plat_priv->get_info_cb(plat_priv->get_info_cb_ctx, 3015 (void *)ind_msg->data, 3016 ind_msg->data_len); 3017 } 3018 3019 static int cnss_ims_wfc_call_twt_cfg_send_sync 3020 (struct cnss_plat_data *plat_priv, 3021 const struct wlfw_wfc_call_twt_config_ind_msg_v01 *ind_msg) 3022 { 3023 struct ims_private_service_wfc_call_twt_config_req_msg_v01 *req; 3024 struct ims_private_service_wfc_call_twt_config_rsp_msg_v01 *resp; 3025 struct qmi_txn txn; 3026 int ret = 0; 3027 3028 if (!test_bit(CNSS_IMS_CONNECTED, &plat_priv->driver_state)) { 3029 cnss_pr_err("Drop FW WFC indication as IMS QMI not connected\n"); 3030 return -EINVAL; 3031 } 3032 3033 req = kzalloc(sizeof(*req), GFP_KERNEL); 3034 if (!req) 3035 return -ENOMEM; 3036 3037 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 3038 if (!resp) { 3039 kfree(req); 3040 return -ENOMEM; 3041 } 3042 3043 req->twt_sta_start_valid = ind_msg->twt_sta_start_valid; 3044 req->twt_sta_start = ind_msg->twt_sta_start; 3045 req->twt_sta_int_valid = ind_msg->twt_sta_int_valid; 3046 req->twt_sta_int = ind_msg->twt_sta_int; 3047 req->twt_sta_upo_valid = ind_msg->twt_sta_upo_valid; 3048 req->twt_sta_upo = ind_msg->twt_sta_upo; 3049 req->twt_sta_sp_valid = ind_msg->twt_sta_sp_valid; 3050 req->twt_sta_sp = ind_msg->twt_sta_sp; 3051 req->twt_sta_dl_valid = req->twt_sta_dl_valid; 3052 req->twt_sta_dl = req->twt_sta_dl; 3053 req->twt_sta_config_changed_valid = 3054 ind_msg->twt_sta_config_changed_valid; 3055 req->twt_sta_config_changed = ind_msg->twt_sta_config_changed; 3056 3057 cnss_pr_dbg("CNSS->IMS: TWT_CFG_REQ: state: 0x%lx\n", 3058 plat_priv->driver_state); 3059 3060 ret = 3061 qmi_txn_init(&plat_priv->ims_qmi, &txn, 3062 ims_private_service_wfc_call_twt_config_rsp_msg_v01_ei, 3063 resp); 3064 if (ret < 0) { 3065 cnss_pr_err("CNSS->IMS: TWT_CFG_REQ: QMI Txn Init Err: %d\n", 3066 ret); 3067 goto out; 3068 } 3069 3070 ret = 3071 qmi_send_request(&plat_priv->ims_qmi, NULL, &txn, 3072 QMI_IMS_PRIVATE_SERVICE_WFC_CALL_TWT_CONFIG_REQ_V01, 3073 IMS_PRIVATE_SERVICE_WFC_CALL_TWT_CONFIG_REQ_MSG_V01_MAX_MSG_LEN, 3074 ims_private_service_wfc_call_twt_config_req_msg_v01_ei, req); 3075 if (ret < 0) { 3076 qmi_txn_cancel(&txn); 3077 cnss_pr_err("CNSS->IMS: TWT_CFG_REQ: QMI Send Err: %d\n", ret); 3078 goto out; 3079 } 3080 3081 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 3082 if (ret < 0) { 3083 cnss_pr_err("IMS->CNSS: TWT_CFG_RSP: QMI Wait Err: %d\n", ret); 3084 goto out; 3085 } 3086 3087 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 3088 cnss_pr_err("IMS->CNSS: TWT_CFG_RSP: Result: %d Err: %d\n", 3089 resp->resp.result, resp->resp.error); 3090 ret = -resp->resp.result; 3091 goto out; 3092 } 3093 ret = 0; 3094 out: 3095 kfree(req); 3096 kfree(resp); 3097 return ret; 3098 } 3099 3100 int cnss_process_twt_cfg_ind_event(struct cnss_plat_data *plat_priv, 3101 void *data) 3102 { 3103 int ret; 3104 struct wlfw_wfc_call_twt_config_ind_msg_v01 *ind_msg = data; 3105 3106 ret = cnss_ims_wfc_call_twt_cfg_send_sync(plat_priv, ind_msg); 3107 kfree(data); 3108 return ret; 3109 } 3110 3111 static void cnss_wlfw_process_twt_cfg_ind(struct qmi_handle *qmi_wlfw, 3112 struct sockaddr_qrtr *sq, 3113 struct qmi_txn *txn, 3114 const void *data) 3115 { 3116 struct cnss_plat_data *plat_priv = 3117 container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw); 3118 const struct wlfw_wfc_call_twt_config_ind_msg_v01 *ind_msg = data; 3119 struct wlfw_wfc_call_twt_config_ind_msg_v01 *event_data; 3120 3121 if (!txn) { 3122 cnss_pr_err("FW->CNSS: TWT_CFG_IND: Spurious indication\n"); 3123 return; 3124 } 3125 3126 if (!ind_msg) { 3127 cnss_pr_err("FW->CNSS: TWT_CFG_IND: Invalid indication\n"); 3128 return; 3129 } 3130 cnss_pr_dbg("FW->CNSS: TWT_CFG_IND: %x %llx, %x %x, %x %x, %x %x, %x %x, %x %x\n", 3131 ind_msg->twt_sta_start_valid, ind_msg->twt_sta_start, 3132 ind_msg->twt_sta_int_valid, ind_msg->twt_sta_int, 3133 ind_msg->twt_sta_upo_valid, ind_msg->twt_sta_upo, 3134 ind_msg->twt_sta_sp_valid, ind_msg->twt_sta_sp, 3135 ind_msg->twt_sta_dl_valid, ind_msg->twt_sta_dl, 3136 ind_msg->twt_sta_config_changed_valid, 3137 ind_msg->twt_sta_config_changed); 3138 3139 event_data = kmemdup(ind_msg, sizeof(*event_data), GFP_KERNEL); 3140 if (!event_data) 3141 return; 3142 cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_WLFW_TWT_CFG_IND, 0, 3143 event_data); 3144 } 3145 3146 static struct qmi_msg_handler qmi_wlfw_msg_handlers[] = { 3147 { 3148 .type = QMI_INDICATION, 3149 .msg_id = QMI_WLFW_REQUEST_MEM_IND_V01, 3150 .ei = wlfw_request_mem_ind_msg_v01_ei, 3151 .decoded_size = sizeof(struct wlfw_request_mem_ind_msg_v01), 3152 .fn = cnss_wlfw_request_mem_ind_cb 3153 }, 3154 { 3155 .type = QMI_INDICATION, 3156 .msg_id = QMI_WLFW_FW_MEM_READY_IND_V01, 3157 .ei = wlfw_fw_mem_ready_ind_msg_v01_ei, 3158 .decoded_size = sizeof(struct wlfw_fw_mem_ready_ind_msg_v01), 3159 .fn = cnss_wlfw_fw_mem_ready_ind_cb 3160 }, 3161 { 3162 .type = QMI_INDICATION, 3163 .msg_id = QMI_WLFW_FW_READY_IND_V01, 3164 .ei = wlfw_fw_ready_ind_msg_v01_ei, 3165 .decoded_size = sizeof(struct wlfw_fw_ready_ind_msg_v01), 3166 .fn = cnss_wlfw_fw_ready_ind_cb 3167 }, 3168 { 3169 .type = QMI_INDICATION, 3170 .msg_id = QMI_WLFW_FW_INIT_DONE_IND_V01, 3171 .ei = wlfw_fw_init_done_ind_msg_v01_ei, 3172 .decoded_size = sizeof(struct wlfw_fw_init_done_ind_msg_v01), 3173 .fn = cnss_wlfw_fw_init_done_ind_cb 3174 }, 3175 { 3176 .type = QMI_INDICATION, 3177 .msg_id = QMI_WLFW_PIN_CONNECT_RESULT_IND_V01, 3178 .ei = wlfw_pin_connect_result_ind_msg_v01_ei, 3179 .decoded_size = 3180 sizeof(struct wlfw_pin_connect_result_ind_msg_v01), 3181 .fn = cnss_wlfw_pin_result_ind_cb 3182 }, 3183 { 3184 .type = QMI_INDICATION, 3185 .msg_id = QMI_WLFW_CAL_DONE_IND_V01, 3186 .ei = wlfw_cal_done_ind_msg_v01_ei, 3187 .decoded_size = sizeof(struct wlfw_cal_done_ind_msg_v01), 3188 .fn = cnss_wlfw_cal_done_ind_cb 3189 }, 3190 { 3191 .type = QMI_INDICATION, 3192 .msg_id = QMI_WLFW_QDSS_TRACE_REQ_MEM_IND_V01, 3193 .ei = wlfw_qdss_trace_req_mem_ind_msg_v01_ei, 3194 .decoded_size = 3195 sizeof(struct wlfw_qdss_trace_req_mem_ind_msg_v01), 3196 .fn = cnss_wlfw_qdss_trace_req_mem_ind_cb 3197 }, 3198 { 3199 .type = QMI_INDICATION, 3200 .msg_id = QMI_WLFW_QDSS_TRACE_SAVE_IND_V01, 3201 .ei = wlfw_qdss_trace_save_ind_msg_v01_ei, 3202 .decoded_size = 3203 sizeof(struct wlfw_qdss_trace_save_ind_msg_v01), 3204 .fn = cnss_wlfw_fw_mem_file_save_ind_cb 3205 }, 3206 { 3207 .type = QMI_INDICATION, 3208 .msg_id = QMI_WLFW_QDSS_TRACE_FREE_IND_V01, 3209 .ei = wlfw_qdss_trace_free_ind_msg_v01_ei, 3210 .decoded_size = 3211 sizeof(struct wlfw_qdss_trace_free_ind_msg_v01), 3212 .fn = cnss_wlfw_qdss_trace_free_ind_cb 3213 }, 3214 { 3215 .type = QMI_INDICATION, 3216 .msg_id = QMI_WLFW_RESPOND_GET_INFO_IND_V01, 3217 .ei = wlfw_respond_get_info_ind_msg_v01_ei, 3218 .decoded_size = 3219 sizeof(struct wlfw_respond_get_info_ind_msg_v01), 3220 .fn = cnss_wlfw_respond_get_info_ind_cb 3221 }, 3222 { 3223 .type = QMI_INDICATION, 3224 .msg_id = QMI_WLFW_WFC_CALL_TWT_CONFIG_IND_V01, 3225 .ei = wlfw_wfc_call_twt_config_ind_msg_v01_ei, 3226 .decoded_size = 3227 sizeof(struct wlfw_wfc_call_twt_config_ind_msg_v01), 3228 .fn = cnss_wlfw_process_twt_cfg_ind 3229 }, 3230 {} 3231 }; 3232 3233 static int cnss_wlfw_connect_to_server(struct cnss_plat_data *plat_priv, 3234 void *data) 3235 { 3236 struct cnss_qmi_event_server_arrive_data *event_data = data; 3237 struct qmi_handle *qmi_wlfw = &plat_priv->qmi_wlfw; 3238 struct sockaddr_qrtr sq = { 0 }; 3239 int ret = 0; 3240 3241 if (!event_data) 3242 return -EINVAL; 3243 3244 sq.sq_family = AF_QIPCRTR; 3245 sq.sq_node = event_data->node; 3246 sq.sq_port = event_data->port; 3247 3248 ret = kernel_connect(qmi_wlfw->sock, (struct sockaddr *)&sq, 3249 sizeof(sq), 0); 3250 if (ret < 0) { 3251 cnss_pr_err("Failed to connect to QMI WLFW remote service port\n"); 3252 goto out; 3253 } 3254 3255 set_bit(CNSS_QMI_WLFW_CONNECTED, &plat_priv->driver_state); 3256 3257 cnss_pr_info("QMI WLFW service connected, state: 0x%lx\n", 3258 plat_priv->driver_state); 3259 3260 kfree(data); 3261 return 0; 3262 3263 out: 3264 CNSS_QMI_ASSERT(); 3265 kfree(data); 3266 return ret; 3267 } 3268 3269 int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv, void *data) 3270 { 3271 int ret = 0; 3272 3273 if (!plat_priv) 3274 return -ENODEV; 3275 3276 if (test_bit(CNSS_QMI_WLFW_CONNECTED, &plat_priv->driver_state)) { 3277 cnss_pr_err("Unexpected WLFW server arrive\n"); 3278 CNSS_ASSERT(0); 3279 return -EINVAL; 3280 } 3281 3282 cnss_ignore_qmi_failure(false); 3283 3284 ret = cnss_wlfw_connect_to_server(plat_priv, data); 3285 if (ret < 0) 3286 goto out; 3287 3288 ret = cnss_wlfw_ind_register_send_sync(plat_priv); 3289 if (ret < 0) { 3290 if (ret == -EALREADY) 3291 ret = 0; 3292 goto out; 3293 } 3294 3295 ret = cnss_wlfw_host_cap_send_sync(plat_priv); 3296 if (ret < 0) 3297 goto out; 3298 3299 return 0; 3300 3301 out: 3302 return ret; 3303 } 3304 3305 int cnss_wlfw_server_exit(struct cnss_plat_data *plat_priv) 3306 { 3307 int ret; 3308 3309 if (!plat_priv) 3310 return -ENODEV; 3311 3312 clear_bit(CNSS_QMI_WLFW_CONNECTED, &plat_priv->driver_state); 3313 3314 cnss_pr_info("QMI WLFW service disconnected, state: 0x%lx\n", 3315 plat_priv->driver_state); 3316 3317 cnss_qmi_deinit(plat_priv); 3318 3319 clear_bit(CNSS_QMI_DEL_SERVER, &plat_priv->driver_state); 3320 3321 ret = cnss_qmi_init(plat_priv); 3322 if (ret < 0) { 3323 cnss_pr_err("QMI WLFW service registraton failed, ret\n", ret); 3324 CNSS_ASSERT(0); 3325 } 3326 return 0; 3327 } 3328 3329 static int wlfw_new_server(struct qmi_handle *qmi_wlfw, 3330 struct qmi_service *service) 3331 { 3332 struct cnss_plat_data *plat_priv = 3333 container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw); 3334 struct cnss_qmi_event_server_arrive_data *event_data; 3335 3336 if (plat_priv && test_bit(CNSS_QMI_DEL_SERVER, &plat_priv->driver_state)) { 3337 cnss_pr_info("WLFW server delete in progress, Ignore server arrive, state: 0x%lx\n", 3338 plat_priv->driver_state); 3339 return 0; 3340 } 3341 3342 cnss_pr_dbg("WLFW server arriving: node %u port %u\n", 3343 service->node, service->port); 3344 3345 event_data = kzalloc(sizeof(*event_data), GFP_KERNEL); 3346 if (!event_data) 3347 return -ENOMEM; 3348 3349 event_data->node = service->node; 3350 event_data->port = service->port; 3351 3352 cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_SERVER_ARRIVE, 3353 0, event_data); 3354 3355 return 0; 3356 } 3357 3358 static void wlfw_del_server(struct qmi_handle *qmi_wlfw, 3359 struct qmi_service *service) 3360 { 3361 struct cnss_plat_data *plat_priv = 3362 container_of(qmi_wlfw, struct cnss_plat_data, qmi_wlfw); 3363 3364 if (plat_priv && test_bit(CNSS_QMI_DEL_SERVER, &plat_priv->driver_state)) { 3365 cnss_pr_info("WLFW server delete in progress, Ignore server delete, state: 0x%lx\n", 3366 plat_priv->driver_state); 3367 return; 3368 } 3369 3370 cnss_pr_dbg("WLFW server exiting\n"); 3371 3372 if (plat_priv) { 3373 cnss_ignore_qmi_failure(true); 3374 set_bit(CNSS_QMI_DEL_SERVER, &plat_priv->driver_state); 3375 } 3376 3377 cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_SERVER_EXIT, 3378 0, NULL); 3379 } 3380 3381 static struct qmi_ops qmi_wlfw_ops = { 3382 .new_server = wlfw_new_server, 3383 .del_server = wlfw_del_server, 3384 }; 3385 3386 static int cnss_qmi_add_lookup(struct cnss_plat_data *plat_priv) 3387 { 3388 unsigned int id = WLFW_SERVICE_INS_ID_V01; 3389 3390 /* In order to support dual wlan card attach case, 3391 * need separate qmi service instance id for each dev 3392 */ 3393 if (cnss_is_dual_wlan_enabled() && plat_priv->qrtr_node_id != 0 && 3394 plat_priv->wlfw_service_instance_id != 0) 3395 id = plat_priv->wlfw_service_instance_id; 3396 3397 return qmi_add_lookup(&plat_priv->qmi_wlfw, WLFW_SERVICE_ID_V01, 3398 WLFW_SERVICE_VERS_V01, id); 3399 } 3400 3401 int cnss_qmi_init(struct cnss_plat_data *plat_priv) 3402 { 3403 int ret = 0; 3404 cnss_get_qrtr_info(plat_priv); 3405 3406 ret = qmi_handle_init(&plat_priv->qmi_wlfw, 3407 QMI_WLFW_MAX_RECV_BUF_SIZE, 3408 &qmi_wlfw_ops, qmi_wlfw_msg_handlers); 3409 if (ret < 0) { 3410 cnss_pr_err("Failed to initialize WLFW QMI handle, err: %d\n", 3411 ret); 3412 goto out; 3413 } 3414 3415 ret = cnss_qmi_add_lookup(plat_priv); 3416 if (ret < 0) 3417 cnss_pr_err("Failed to add WLFW QMI lookup, err: %d\n", ret); 3418 3419 out: 3420 return ret; 3421 } 3422 3423 void cnss_qmi_deinit(struct cnss_plat_data *plat_priv) 3424 { 3425 qmi_handle_release(&plat_priv->qmi_wlfw); 3426 } 3427 3428 int cnss_qmi_get_dms_mac(struct cnss_plat_data *plat_priv) 3429 { 3430 struct dms_get_mac_address_req_msg_v01 req; 3431 struct dms_get_mac_address_resp_msg_v01 resp; 3432 struct qmi_txn txn; 3433 int ret = 0; 3434 3435 if (!test_bit(CNSS_QMI_DMS_CONNECTED, &plat_priv->driver_state)) { 3436 cnss_pr_err("DMS QMI connection not established\n"); 3437 return -EINVAL; 3438 } 3439 cnss_pr_dbg("Requesting DMS MAC address"); 3440 3441 memset(&resp, 0, sizeof(resp)); 3442 ret = qmi_txn_init(&plat_priv->qmi_dms, &txn, 3443 dms_get_mac_address_resp_msg_v01_ei, &resp); 3444 if (ret < 0) { 3445 cnss_pr_err("Failed to initialize txn for dms, err: %d\n", 3446 ret); 3447 goto out; 3448 } 3449 req.device = DMS_DEVICE_MAC_WLAN_V01; 3450 ret = qmi_send_request(&plat_priv->qmi_dms, NULL, &txn, 3451 QMI_DMS_GET_MAC_ADDRESS_REQ_V01, 3452 DMS_GET_MAC_ADDRESS_REQ_MSG_V01_MAX_MSG_LEN, 3453 dms_get_mac_address_req_msg_v01_ei, &req); 3454 if (ret < 0) { 3455 qmi_txn_cancel(&txn); 3456 cnss_pr_err("Failed to send QMI_DMS_GET_MAC_ADDRESS_REQ_V01, err: %d\n", 3457 ret); 3458 goto out; 3459 } 3460 ret = qmi_txn_wait(&txn, QMI_WLFW_TIMEOUT_JF); 3461 if (ret < 0) { 3462 cnss_pr_err("Failed to wait for QMI_DMS_GET_MAC_ADDRESS_RESP_V01, err: %d\n", 3463 ret); 3464 goto out; 3465 } 3466 3467 if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { 3468 cnss_pr_err("QMI_DMS_GET_MAC_ADDRESS_REQ_V01 failed, result: %d, err: %d\n", 3469 resp.resp.result, resp.resp.error); 3470 ret = -resp.resp.result; 3471 goto out; 3472 } 3473 if (!resp.mac_address_valid || 3474 resp.mac_address_len != QMI_WLFW_MAC_ADDR_SIZE_V01) { 3475 cnss_pr_err("Invalid MAC address received from DMS\n"); 3476 plat_priv->dms.mac_valid = false; 3477 goto out; 3478 } 3479 plat_priv->dms.mac_valid = true; 3480 memcpy(plat_priv->dms.mac, resp.mac_address, QMI_WLFW_MAC_ADDR_SIZE_V01); 3481 cnss_pr_info("Received DMS MAC: [%pM]\n", plat_priv->dms.mac); 3482 out: 3483 return ret; 3484 } 3485 3486 static int cnss_dms_connect_to_server(struct cnss_plat_data *plat_priv, 3487 unsigned int node, unsigned int port) 3488 { 3489 struct qmi_handle *qmi_dms = &plat_priv->qmi_dms; 3490 struct sockaddr_qrtr sq = {0}; 3491 int ret = 0; 3492 3493 sq.sq_family = AF_QIPCRTR; 3494 sq.sq_node = node; 3495 sq.sq_port = port; 3496 3497 ret = kernel_connect(qmi_dms->sock, (struct sockaddr *)&sq, 3498 sizeof(sq), 0); 3499 if (ret < 0) { 3500 cnss_pr_err("Failed to connect to QMI DMS remote service Node: %d Port: %d\n", 3501 node, port); 3502 goto out; 3503 } 3504 3505 set_bit(CNSS_QMI_DMS_CONNECTED, &plat_priv->driver_state); 3506 cnss_pr_info("QMI DMS service connected, state: 0x%lx\n", 3507 plat_priv->driver_state); 3508 out: 3509 return ret; 3510 } 3511 3512 static int dms_new_server(struct qmi_handle *qmi_dms, 3513 struct qmi_service *service) 3514 { 3515 struct cnss_plat_data *plat_priv = 3516 container_of(qmi_dms, struct cnss_plat_data, qmi_dms); 3517 3518 if (!service) 3519 return -EINVAL; 3520 3521 return cnss_dms_connect_to_server(plat_priv, service->node, 3522 service->port); 3523 } 3524 3525 static void cnss_dms_server_exit_work(struct work_struct *work) 3526 { 3527 int ret; 3528 struct cnss_plat_data *plat_priv = cnss_get_plat_priv(NULL); 3529 3530 cnss_dms_deinit(plat_priv); 3531 3532 cnss_pr_info("QMI DMS Server Exit"); 3533 clear_bit(CNSS_DMS_DEL_SERVER, &plat_priv->driver_state); 3534 3535 ret = cnss_dms_init(plat_priv); 3536 if (ret < 0) 3537 cnss_pr_err("QMI DMS service registraton failed, ret\n", ret); 3538 } 3539 3540 static DECLARE_WORK(cnss_dms_del_work, cnss_dms_server_exit_work); 3541 3542 static void dms_del_server(struct qmi_handle *qmi_dms, 3543 struct qmi_service *service) 3544 { 3545 struct cnss_plat_data *plat_priv = 3546 container_of(qmi_dms, struct cnss_plat_data, qmi_dms); 3547 3548 if (!plat_priv) 3549 return; 3550 3551 if (test_bit(CNSS_DMS_DEL_SERVER, &plat_priv->driver_state)) { 3552 cnss_pr_info("DMS server delete or cnss remove in progress, Ignore server delete: 0x%lx\n", 3553 plat_priv->driver_state); 3554 return; 3555 } 3556 3557 set_bit(CNSS_DMS_DEL_SERVER, &plat_priv->driver_state); 3558 clear_bit(CNSS_QMI_DMS_CONNECTED, &plat_priv->driver_state); 3559 cnss_pr_info("QMI DMS service disconnected, state: 0x%lx\n", 3560 plat_priv->driver_state); 3561 schedule_work(&cnss_dms_del_work); 3562 } 3563 3564 void cnss_cancel_dms_work(void) 3565 { 3566 cancel_work_sync(&cnss_dms_del_work); 3567 } 3568 3569 static struct qmi_ops qmi_dms_ops = { 3570 .new_server = dms_new_server, 3571 .del_server = dms_del_server, 3572 }; 3573 3574 int cnss_dms_init(struct cnss_plat_data *plat_priv) 3575 { 3576 int ret = 0; 3577 3578 ret = qmi_handle_init(&plat_priv->qmi_dms, DMS_QMI_MAX_MSG_LEN, 3579 &qmi_dms_ops, NULL); 3580 if (ret < 0) { 3581 cnss_pr_err("Failed to initialize DMS handle, err: %d\n", ret); 3582 goto out; 3583 } 3584 3585 ret = qmi_add_lookup(&plat_priv->qmi_dms, DMS_SERVICE_ID_V01, 3586 DMS_SERVICE_VERS_V01, 0); 3587 if (ret < 0) 3588 cnss_pr_err("Failed to add DMS lookup, err: %d\n", ret); 3589 out: 3590 return ret; 3591 } 3592 3593 void cnss_dms_deinit(struct cnss_plat_data *plat_priv) 3594 { 3595 set_bit(CNSS_DMS_DEL_SERVER, &plat_priv->driver_state); 3596 qmi_handle_release(&plat_priv->qmi_dms); 3597 } 3598 3599 int coex_antenna_switch_to_wlan_send_sync_msg(struct cnss_plat_data *plat_priv) 3600 { 3601 int ret; 3602 struct coex_antenna_switch_to_wlan_req_msg_v01 *req; 3603 struct coex_antenna_switch_to_wlan_resp_msg_v01 *resp; 3604 struct qmi_txn txn; 3605 3606 if (!plat_priv) 3607 return -ENODEV; 3608 3609 cnss_pr_dbg("Sending coex antenna switch_to_wlan\n"); 3610 3611 req = kzalloc(sizeof(*req), GFP_KERNEL); 3612 if (!req) 3613 return -ENOMEM; 3614 3615 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 3616 if (!resp) { 3617 kfree(req); 3618 return -ENOMEM; 3619 } 3620 3621 req->antenna = plat_priv->antenna; 3622 3623 ret = qmi_txn_init(&plat_priv->coex_qmi, &txn, 3624 coex_antenna_switch_to_wlan_resp_msg_v01_ei, resp); 3625 if (ret < 0) { 3626 cnss_pr_err("Fail to init txn for coex antenna switch_to_wlan resp %d\n", 3627 ret); 3628 goto out; 3629 } 3630 3631 ret = qmi_send_request 3632 (&plat_priv->coex_qmi, NULL, &txn, 3633 QMI_COEX_SWITCH_ANTENNA_TO_WLAN_REQ_V01, 3634 COEX_ANTENNA_SWITCH_TO_WLAN_REQ_MSG_V01_MAX_MSG_LEN, 3635 coex_antenna_switch_to_wlan_req_msg_v01_ei, req); 3636 if (ret < 0) { 3637 qmi_txn_cancel(&txn); 3638 cnss_pr_err("Fail to send coex antenna switch_to_wlan req %d\n", 3639 ret); 3640 goto out; 3641 } 3642 3643 ret = qmi_txn_wait(&txn, COEX_TIMEOUT); 3644 if (ret < 0) { 3645 cnss_pr_err("Coex antenna switch_to_wlan resp wait failed with ret %d\n", 3646 ret); 3647 goto out; 3648 } else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 3649 cnss_pr_err("Coex antenna switch_to_wlan request rejected, result:%d error:%d\n", 3650 resp->resp.result, resp->resp.error); 3651 ret = -resp->resp.result; 3652 goto out; 3653 } 3654 3655 if (resp->grant_valid) 3656 plat_priv->grant = resp->grant; 3657 3658 cnss_pr_dbg("Coex antenna grant: 0x%llx\n", resp->grant); 3659 3660 kfree(resp); 3661 kfree(req); 3662 return 0; 3663 3664 out: 3665 kfree(resp); 3666 kfree(req); 3667 return ret; 3668 } 3669 3670 int coex_antenna_switch_to_mdm_send_sync_msg(struct cnss_plat_data *plat_priv) 3671 { 3672 int ret; 3673 struct coex_antenna_switch_to_mdm_req_msg_v01 *req; 3674 struct coex_antenna_switch_to_mdm_resp_msg_v01 *resp; 3675 struct qmi_txn txn; 3676 3677 if (!plat_priv) 3678 return -ENODEV; 3679 3680 cnss_pr_dbg("Sending coex antenna switch_to_mdm\n"); 3681 3682 req = kzalloc(sizeof(*req), GFP_KERNEL); 3683 if (!req) 3684 return -ENOMEM; 3685 3686 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 3687 if (!resp) { 3688 kfree(req); 3689 return -ENOMEM; 3690 } 3691 3692 req->antenna = plat_priv->antenna; 3693 3694 ret = qmi_txn_init(&plat_priv->coex_qmi, &txn, 3695 coex_antenna_switch_to_mdm_resp_msg_v01_ei, resp); 3696 if (ret < 0) { 3697 cnss_pr_err("Fail to init txn for coex antenna switch_to_mdm resp %d\n", 3698 ret); 3699 goto out; 3700 } 3701 3702 ret = qmi_send_request 3703 (&plat_priv->coex_qmi, NULL, &txn, 3704 QMI_COEX_SWITCH_ANTENNA_TO_MDM_REQ_V01, 3705 COEX_ANTENNA_SWITCH_TO_MDM_REQ_MSG_V01_MAX_MSG_LEN, 3706 coex_antenna_switch_to_mdm_req_msg_v01_ei, req); 3707 if (ret < 0) { 3708 qmi_txn_cancel(&txn); 3709 cnss_pr_err("Fail to send coex antenna switch_to_mdm req %d\n", 3710 ret); 3711 goto out; 3712 } 3713 3714 ret = qmi_txn_wait(&txn, COEX_TIMEOUT); 3715 if (ret < 0) { 3716 cnss_pr_err("Coex antenna switch_to_mdm resp wait failed with ret %d\n", 3717 ret); 3718 goto out; 3719 } else if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 3720 cnss_pr_err("Coex antenna switch_to_mdm request rejected, result:%d error:%d\n", 3721 resp->resp.result, resp->resp.error); 3722 ret = -resp->resp.result; 3723 goto out; 3724 } 3725 3726 kfree(resp); 3727 kfree(req); 3728 return 0; 3729 3730 out: 3731 kfree(resp); 3732 kfree(req); 3733 return ret; 3734 } 3735 3736 int cnss_send_subsys_restart_level_msg(struct cnss_plat_data *plat_priv) 3737 { 3738 int ret; 3739 struct wlfw_subsys_restart_level_req_msg_v01 req; 3740 struct wlfw_subsys_restart_level_resp_msg_v01 resp; 3741 u8 pcss_enabled; 3742 3743 if (!plat_priv) 3744 return -ENODEV; 3745 3746 if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) { 3747 cnss_pr_dbg("Can't send pcss cmd before fw ready\n"); 3748 return 0; 3749 } 3750 3751 pcss_enabled = plat_priv->recovery_pcss_enabled; 3752 cnss_pr_dbg("Sending pcss recovery status: %d\n", pcss_enabled); 3753 3754 req.restart_level_type_valid = 1; 3755 req.restart_level_type = pcss_enabled; 3756 3757 ret = qmi_send_wait(&plat_priv->qmi_wlfw, &req, &resp, 3758 wlfw_subsys_restart_level_req_msg_v01_ei, 3759 wlfw_subsys_restart_level_resp_msg_v01_ei, 3760 QMI_WLFW_SUBSYS_RESTART_LEVEL_REQ_V01, 3761 WLFW_SUBSYS_RESTART_LEVEL_REQ_MSG_V01_MAX_MSG_LEN, 3762 QMI_WLFW_TIMEOUT_JF); 3763 3764 if (ret < 0) 3765 cnss_pr_err("pcss recovery setting failed with ret %d\n", ret); 3766 return ret; 3767 } 3768 3769 static int coex_new_server(struct qmi_handle *qmi, 3770 struct qmi_service *service) 3771 { 3772 struct cnss_plat_data *plat_priv = 3773 container_of(qmi, struct cnss_plat_data, coex_qmi); 3774 struct sockaddr_qrtr sq = { 0 }; 3775 int ret = 0; 3776 3777 cnss_pr_dbg("COEX server arrive: node %u port %u\n", 3778 service->node, service->port); 3779 3780 sq.sq_family = AF_QIPCRTR; 3781 sq.sq_node = service->node; 3782 sq.sq_port = service->port; 3783 ret = kernel_connect(qmi->sock, (struct sockaddr *)&sq, sizeof(sq), 0); 3784 if (ret < 0) { 3785 cnss_pr_err("Fail to connect to remote service port\n"); 3786 return ret; 3787 } 3788 3789 set_bit(CNSS_COEX_CONNECTED, &plat_priv->driver_state); 3790 cnss_pr_dbg("COEX Server Connected: 0x%lx\n", 3791 plat_priv->driver_state); 3792 return 0; 3793 } 3794 3795 static void coex_del_server(struct qmi_handle *qmi, 3796 struct qmi_service *service) 3797 { 3798 struct cnss_plat_data *plat_priv = 3799 container_of(qmi, struct cnss_plat_data, coex_qmi); 3800 3801 cnss_pr_dbg("COEX server exit\n"); 3802 3803 clear_bit(CNSS_COEX_CONNECTED, &plat_priv->driver_state); 3804 } 3805 3806 static struct qmi_ops coex_qmi_ops = { 3807 .new_server = coex_new_server, 3808 .del_server = coex_del_server, 3809 }; 3810 3811 int cnss_register_coex_service(struct cnss_plat_data *plat_priv) 3812 { int ret; 3813 3814 ret = qmi_handle_init(&plat_priv->coex_qmi, 3815 COEX_SERVICE_MAX_MSG_LEN, 3816 &coex_qmi_ops, NULL); 3817 if (ret < 0) 3818 return ret; 3819 3820 ret = qmi_add_lookup(&plat_priv->coex_qmi, COEX_SERVICE_ID_V01, 3821 COEX_SERVICE_VERS_V01, 0); 3822 return ret; 3823 } 3824 3825 void cnss_unregister_coex_service(struct cnss_plat_data *plat_priv) 3826 { 3827 qmi_handle_release(&plat_priv->coex_qmi); 3828 } 3829 3830 /* IMS Service */ 3831 int ims_subscribe_for_indication_send_async(struct cnss_plat_data *plat_priv) 3832 { 3833 int ret; 3834 struct ims_private_service_subscribe_for_indications_req_msg_v01 *req; 3835 struct qmi_txn *txn; 3836 3837 if (!plat_priv) 3838 return -ENODEV; 3839 3840 cnss_pr_dbg("Sending ASYNC ims subscribe for indication\n"); 3841 3842 req = kzalloc(sizeof(*req), GFP_KERNEL); 3843 if (!req) 3844 return -ENOMEM; 3845 3846 req->wfc_call_status_valid = 1; 3847 req->wfc_call_status = 1; 3848 3849 txn = &plat_priv->txn; 3850 ret = qmi_txn_init(&plat_priv->ims_qmi, txn, NULL, NULL); 3851 if (ret < 0) { 3852 cnss_pr_err("Fail to init txn for ims subscribe for indication resp %d\n", 3853 ret); 3854 goto out; 3855 } 3856 3857 ret = qmi_send_request 3858 (&plat_priv->ims_qmi, NULL, txn, 3859 QMI_IMS_PRIVATE_SERVICE_SUBSCRIBE_FOR_INDICATIONS_REQ_V01, 3860 IMS_PRIVATE_SERVICE_SUBSCRIBE_FOR_INDICATIONS_REQ_MSG_V01_MAX_MSG_LEN, 3861 ims_private_service_subscribe_for_indications_req_msg_v01_ei, req); 3862 if (ret < 0) { 3863 qmi_txn_cancel(txn); 3864 cnss_pr_err("Fail to send ims subscribe for indication req %d\n", 3865 ret); 3866 goto out; 3867 } 3868 3869 kfree(req); 3870 return 0; 3871 3872 out: 3873 kfree(req); 3874 return ret; 3875 } 3876 3877 static void ims_subscribe_for_indication_resp_cb(struct qmi_handle *qmi, 3878 struct sockaddr_qrtr *sq, 3879 struct qmi_txn *txn, 3880 const void *data) 3881 { 3882 const 3883 struct ims_private_service_subscribe_for_indications_rsp_msg_v01 *resp = 3884 data; 3885 3886 cnss_pr_dbg("Received IMS subscribe indication response\n"); 3887 3888 if (!txn) { 3889 cnss_pr_err("spurious response\n"); 3890 return; 3891 } 3892 3893 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { 3894 cnss_pr_err("IMS subscribe for indication request rejected, result:%d error:%d\n", 3895 resp->resp.result, resp->resp.error); 3896 txn->result = -resp->resp.result; 3897 } 3898 } 3899 3900 int cnss_process_wfc_call_ind_event(struct cnss_plat_data *plat_priv, 3901 void *data) 3902 { 3903 int ret; 3904 struct ims_private_service_wfc_call_status_ind_msg_v01 *ind_msg = data; 3905 3906 ret = cnss_wlfw_wfc_call_status_send_sync(plat_priv, ind_msg); 3907 kfree(data); 3908 return ret; 3909 } 3910 3911 static void 3912 cnss_ims_process_wfc_call_ind_cb(struct qmi_handle *ims_qmi, 3913 struct sockaddr_qrtr *sq, 3914 struct qmi_txn *txn, const void *data) 3915 { 3916 struct cnss_plat_data *plat_priv = 3917 container_of(ims_qmi, struct cnss_plat_data, ims_qmi); 3918 const 3919 struct ims_private_service_wfc_call_status_ind_msg_v01 *ind_msg = data; 3920 struct ims_private_service_wfc_call_status_ind_msg_v01 *event_data; 3921 3922 if (!txn) { 3923 cnss_pr_err("IMS->CNSS: WFC_CALL_IND: Spurious indication\n"); 3924 return; 3925 } 3926 3927 if (!ind_msg) { 3928 cnss_pr_err("IMS->CNSS: WFC_CALL_IND: Invalid indication\n"); 3929 return; 3930 } 3931 cnss_pr_dbg("IMS->CNSS: WFC_CALL_IND: %x, %x %x, %x %x, %x %llx, %x %x, %x %x\n", 3932 ind_msg->wfc_call_active, ind_msg->all_wfc_calls_held_valid, 3933 ind_msg->all_wfc_calls_held, 3934 ind_msg->is_wfc_emergency_valid, ind_msg->is_wfc_emergency, 3935 ind_msg->twt_ims_start_valid, ind_msg->twt_ims_start, 3936 ind_msg->twt_ims_int_valid, ind_msg->twt_ims_int, 3937 ind_msg->media_quality_valid, ind_msg->media_quality); 3938 3939 event_data = kmemdup(ind_msg, sizeof(*event_data), GFP_KERNEL); 3940 if (!event_data) 3941 return; 3942 cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_IMS_WFC_CALL_IND, 3943 0, event_data); 3944 } 3945 3946 static struct qmi_msg_handler qmi_ims_msg_handlers[] = { 3947 { 3948 .type = QMI_RESPONSE, 3949 .msg_id = 3950 QMI_IMS_PRIVATE_SERVICE_SUBSCRIBE_FOR_INDICATIONS_REQ_V01, 3951 .ei = 3952 ims_private_service_subscribe_for_indications_rsp_msg_v01_ei, 3953 .decoded_size = sizeof(struct 3954 ims_private_service_subscribe_for_indications_rsp_msg_v01), 3955 .fn = ims_subscribe_for_indication_resp_cb 3956 }, 3957 { 3958 .type = QMI_INDICATION, 3959 .msg_id = QMI_IMS_PRIVATE_SERVICE_WFC_CALL_STATUS_IND_V01, 3960 .ei = ims_private_service_wfc_call_status_ind_msg_v01_ei, 3961 .decoded_size = 3962 sizeof(struct ims_private_service_wfc_call_status_ind_msg_v01), 3963 .fn = cnss_ims_process_wfc_call_ind_cb 3964 }, 3965 {} 3966 }; 3967 3968 static int ims_new_server(struct qmi_handle *qmi, 3969 struct qmi_service *service) 3970 { 3971 struct cnss_plat_data *plat_priv = 3972 container_of(qmi, struct cnss_plat_data, ims_qmi); 3973 struct sockaddr_qrtr sq = { 0 }; 3974 int ret = 0; 3975 3976 cnss_pr_dbg("IMS server arrive: node %u port %u\n", 3977 service->node, service->port); 3978 3979 sq.sq_family = AF_QIPCRTR; 3980 sq.sq_node = service->node; 3981 sq.sq_port = service->port; 3982 ret = kernel_connect(qmi->sock, (struct sockaddr *)&sq, sizeof(sq), 0); 3983 if (ret < 0) { 3984 cnss_pr_err("Fail to connect to remote service port\n"); 3985 return ret; 3986 } 3987 3988 set_bit(CNSS_IMS_CONNECTED, &plat_priv->driver_state); 3989 cnss_pr_dbg("IMS Server Connected: 0x%lx\n", 3990 plat_priv->driver_state); 3991 3992 ret = ims_subscribe_for_indication_send_async(plat_priv); 3993 return ret; 3994 } 3995 3996 static void ims_del_server(struct qmi_handle *qmi, 3997 struct qmi_service *service) 3998 { 3999 struct cnss_plat_data *plat_priv = 4000 container_of(qmi, struct cnss_plat_data, ims_qmi); 4001 4002 cnss_pr_dbg("IMS server exit\n"); 4003 4004 clear_bit(CNSS_IMS_CONNECTED, &plat_priv->driver_state); 4005 } 4006 4007 static struct qmi_ops ims_qmi_ops = { 4008 .new_server = ims_new_server, 4009 .del_server = ims_del_server, 4010 }; 4011 4012 int cnss_register_ims_service(struct cnss_plat_data *plat_priv) 4013 { int ret; 4014 4015 ret = qmi_handle_init(&plat_priv->ims_qmi, 4016 IMSPRIVATE_SERVICE_MAX_MSG_LEN, 4017 &ims_qmi_ops, qmi_ims_msg_handlers); 4018 if (ret < 0) 4019 return ret; 4020 4021 ret = qmi_add_lookup(&plat_priv->ims_qmi, IMSPRIVATE_SERVICE_ID_V01, 4022 IMSPRIVATE_SERVICE_VERS_V01, 0); 4023 return ret; 4024 } 4025 4026 void cnss_unregister_ims_service(struct cnss_plat_data *plat_priv) 4027 { 4028 qmi_handle_release(&plat_priv->ims_qmi); 4029 } 4030