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