1 /* 2 * Copyright (c) 2015-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include "targcfg.h" 21 #include "qdf_lock.h" 22 #include "qdf_status.h" 23 #include "qdf_status.h" 24 #include <qdf_atomic.h> /* qdf_atomic_read */ 25 #include <targaddrs.h> 26 #include "hif_io32.h" 27 #include <hif.h> 28 #include <target_type.h> 29 #include "regtable.h" 30 #define ATH_MODULE_NAME hif 31 #include <a_debug.h> 32 #include "hif_main.h" 33 #include "hif_hw_version.h" 34 #if (defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \ 35 defined(HIF_IPCI)) 36 #include "ce_tasklet.h" 37 #include "ce_api.h" 38 #endif 39 #include "qdf_trace.h" 40 #include "qdf_status.h" 41 #include "hif_debug.h" 42 #include "mp_dev.h" 43 #if defined(QCA_WIFI_QCA8074) || defined(QCA_WIFI_QCA6018) || \ 44 defined(QCA_WIFI_QCA5018) || defined(QCA_WIFI_QCA9574) || \ 45 defined(QCA_WIFI_QCA5332) 46 #include "hal_api.h" 47 #endif 48 #include "hif_napi.h" 49 #include "hif_unit_test_suspend_i.h" 50 #include "qdf_module.h" 51 #ifdef HIF_CE_LOG_INFO 52 #include <qdf_notifier.h> 53 #include <qdf_hang_event_notifier.h> 54 #endif 55 #include <linux/cpumask.h> 56 57 #if defined(HIF_IPCI) && defined(FEATURE_HAL_DELAYED_REG_WRITE) 58 #include <pld_common.h> 59 #endif 60 61 void hif_dump(struct hif_opaque_softc *hif_ctx, uint8_t cmd_id, bool start) 62 { 63 hif_trigger_dump(hif_ctx, cmd_id, start); 64 } 65 66 /** 67 * hif_get_target_id(): hif_get_target_id 68 * 69 * Return the virtual memory base address to the caller 70 * 71 * @scn: hif_softc 72 * 73 * Return: A_target_id_t 74 */ 75 A_target_id_t hif_get_target_id(struct hif_softc *scn) 76 { 77 return scn->mem; 78 } 79 80 /** 81 * hif_get_targetdef(): hif_get_targetdef 82 * @scn: scn 83 * 84 * Return: void * 85 */ 86 void *hif_get_targetdef(struct hif_opaque_softc *hif_ctx) 87 { 88 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 89 90 return scn->targetdef; 91 } 92 93 #ifdef FORCE_WAKE 94 void hif_srng_init_phase(struct hif_opaque_softc *hif_ctx, 95 bool init_phase) 96 { 97 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 98 99 if (ce_srng_based(scn)) 100 hal_set_init_phase(scn->hal_soc, init_phase); 101 } 102 #endif /* FORCE_WAKE */ 103 104 #ifdef HIF_IPCI 105 void hif_shutdown_notifier_cb(void *hif_ctx) 106 { 107 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 108 109 scn->recovery = true; 110 } 111 #endif 112 113 /** 114 * hif_vote_link_down(): unvote for link up 115 * 116 * Call hif_vote_link_down to release a previous request made using 117 * hif_vote_link_up. A hif_vote_link_down call should only be made 118 * after a corresponding hif_vote_link_up, otherwise you could be 119 * negating a vote from another source. When no votes are present 120 * hif will not guarantee the linkstate after hif_bus_suspend. 121 * 122 * SYNCHRONIZE WITH hif_vote_link_up by only calling in MC thread 123 * and initialization deinitialization sequencences. 124 * 125 * Return: n/a 126 */ 127 void hif_vote_link_down(struct hif_opaque_softc *hif_ctx) 128 { 129 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 130 131 QDF_BUG(scn); 132 if (scn->linkstate_vote == 0) 133 QDF_DEBUG_PANIC("linkstate_vote(%d) has already been 0", 134 scn->linkstate_vote); 135 136 scn->linkstate_vote--; 137 hif_info("Down_linkstate_vote %d", scn->linkstate_vote); 138 if (scn->linkstate_vote == 0) 139 hif_bus_prevent_linkdown(scn, false); 140 } 141 142 /** 143 * hif_vote_link_up(): vote to prevent bus from suspending 144 * 145 * Makes hif guarantee that fw can message the host normally 146 * durring suspend. 147 * 148 * SYNCHRONIZE WITH hif_vote_link_up by only calling in MC thread 149 * and initialization deinitialization sequencences. 150 * 151 * Return: n/a 152 */ 153 void hif_vote_link_up(struct hif_opaque_softc *hif_ctx) 154 { 155 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 156 157 QDF_BUG(scn); 158 scn->linkstate_vote++; 159 hif_info("Up_linkstate_vote %d", scn->linkstate_vote); 160 if (scn->linkstate_vote == 1) 161 hif_bus_prevent_linkdown(scn, true); 162 } 163 164 /** 165 * hif_can_suspend_link(): query if hif is permitted to suspend the link 166 * 167 * Hif will ensure that the link won't be suspended if the upperlayers 168 * don't want it to. 169 * 170 * SYNCHRONIZATION: MC thread is stopped before bus suspend thus 171 * we don't need extra locking to ensure votes dont change while 172 * we are in the process of suspending or resuming. 173 * 174 * Return: false if hif will guarantee link up durring suspend. 175 */ 176 bool hif_can_suspend_link(struct hif_opaque_softc *hif_ctx) 177 { 178 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 179 180 QDF_BUG(scn); 181 return scn->linkstate_vote == 0; 182 } 183 184 /** 185 * hif_hia_item_address(): hif_hia_item_address 186 * @target_type: target_type 187 * @item_offset: item_offset 188 * 189 * Return: n/a 190 */ 191 uint32_t hif_hia_item_address(uint32_t target_type, uint32_t item_offset) 192 { 193 switch (target_type) { 194 case TARGET_TYPE_AR6002: 195 return AR6002_HOST_INTEREST_ADDRESS + item_offset; 196 case TARGET_TYPE_AR6003: 197 return AR6003_HOST_INTEREST_ADDRESS + item_offset; 198 case TARGET_TYPE_AR6004: 199 return AR6004_HOST_INTEREST_ADDRESS + item_offset; 200 case TARGET_TYPE_AR6006: 201 return AR6006_HOST_INTEREST_ADDRESS + item_offset; 202 case TARGET_TYPE_AR9888: 203 return AR9888_HOST_INTEREST_ADDRESS + item_offset; 204 case TARGET_TYPE_AR6320: 205 case TARGET_TYPE_AR6320V2: 206 return AR6320_HOST_INTEREST_ADDRESS + item_offset; 207 case TARGET_TYPE_ADRASTEA: 208 /* ADRASTEA doesn't have a host interest address */ 209 ASSERT(0); 210 return 0; 211 case TARGET_TYPE_AR900B: 212 return AR900B_HOST_INTEREST_ADDRESS + item_offset; 213 case TARGET_TYPE_QCA9984: 214 return QCA9984_HOST_INTEREST_ADDRESS + item_offset; 215 case TARGET_TYPE_QCA9888: 216 return QCA9888_HOST_INTEREST_ADDRESS + item_offset; 217 218 default: 219 ASSERT(0); 220 return 0; 221 } 222 } 223 224 /** 225 * hif_max_num_receives_reached() - check max receive is reached 226 * @scn: HIF Context 227 * @count: unsigned int. 228 * 229 * Output check status as bool 230 * 231 * Return: bool 232 */ 233 bool hif_max_num_receives_reached(struct hif_softc *scn, unsigned int count) 234 { 235 if (QDF_IS_EPPING_ENABLED(hif_get_conparam(scn))) 236 return count > 120; 237 else 238 return count > MAX_NUM_OF_RECEIVES; 239 } 240 241 /** 242 * init_buffer_count() - initial buffer count 243 * @maxSize: qdf_size_t 244 * 245 * routine to modify the initial buffer count to be allocated on an os 246 * platform basis. Platform owner will need to modify this as needed 247 * 248 * Return: qdf_size_t 249 */ 250 qdf_size_t init_buffer_count(qdf_size_t maxSize) 251 { 252 return maxSize; 253 } 254 255 /** 256 * hif_save_htc_htt_config_endpoint() - save htt_tx_endpoint 257 * @hif_ctx: hif context 258 * @htc_htt_tx_endpoint: htt_tx_endpoint 259 * 260 * Return: void 261 */ 262 void hif_save_htc_htt_config_endpoint(struct hif_opaque_softc *hif_ctx, 263 int htc_htt_tx_endpoint) 264 { 265 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 266 267 if (!scn) { 268 hif_err("scn or scn->hif_sc is NULL!"); 269 return; 270 } 271 272 scn->htc_htt_tx_endpoint = htc_htt_tx_endpoint; 273 } 274 qdf_export_symbol(hif_save_htc_htt_config_endpoint); 275 276 static const struct qwlan_hw qwlan_hw_list[] = { 277 { 278 .id = AR6320_REV1_VERSION, 279 .subid = 0, 280 .name = "QCA6174_REV1", 281 }, 282 { 283 .id = AR6320_REV1_1_VERSION, 284 .subid = 0x1, 285 .name = "QCA6174_REV1_1", 286 }, 287 { 288 .id = AR6320_REV1_3_VERSION, 289 .subid = 0x2, 290 .name = "QCA6174_REV1_3", 291 }, 292 { 293 .id = AR6320_REV2_1_VERSION, 294 .subid = 0x4, 295 .name = "QCA6174_REV2_1", 296 }, 297 { 298 .id = AR6320_REV2_1_VERSION, 299 .subid = 0x5, 300 .name = "QCA6174_REV2_2", 301 }, 302 { 303 .id = AR6320_REV3_VERSION, 304 .subid = 0x6, 305 .name = "QCA6174_REV2.3", 306 }, 307 { 308 .id = AR6320_REV3_VERSION, 309 .subid = 0x8, 310 .name = "QCA6174_REV3", 311 }, 312 { 313 .id = AR6320_REV3_VERSION, 314 .subid = 0x9, 315 .name = "QCA6174_REV3_1", 316 }, 317 { 318 .id = AR6320_REV3_2_VERSION, 319 .subid = 0xA, 320 .name = "AR6320_REV3_2_VERSION", 321 }, 322 { 323 .id = QCA6390_V1, 324 .subid = 0x0, 325 .name = "QCA6390_V1", 326 }, 327 { 328 .id = QCA6490_V1, 329 .subid = 0x0, 330 .name = "QCA6490_V1", 331 }, 332 { 333 .id = WCN3990_v1, 334 .subid = 0x0, 335 .name = "WCN3990_V1", 336 }, 337 { 338 .id = WCN3990_v2, 339 .subid = 0x0, 340 .name = "WCN3990_V2", 341 }, 342 { 343 .id = WCN3990_v2_1, 344 .subid = 0x0, 345 .name = "WCN3990_V2.1", 346 }, 347 { 348 .id = WCN3998, 349 .subid = 0x0, 350 .name = "WCN3998", 351 }, 352 { 353 .id = QCA9379_REV1_VERSION, 354 .subid = 0xC, 355 .name = "QCA9379_REV1", 356 }, 357 { 358 .id = QCA9379_REV1_VERSION, 359 .subid = 0xD, 360 .name = "QCA9379_REV1_1", 361 }, 362 { 363 .id = MANGO_V1, 364 .subid = 0xF, 365 .name = "MANGO_V1", 366 }, 367 { 368 .id = KIWI_V1, 369 .subid = 0, 370 .name = "KIWI_V1", 371 }, 372 { 373 .id = KIWI_V2, 374 .subid = 0, 375 .name = "KIWI_V2", 376 }, 377 { 378 .id = WCN6750_V1, 379 .subid = 0, 380 .name = "WCN6750_V1", 381 }, 382 { 383 .id = QCA6490_v2_1, 384 .subid = 0, 385 .name = "QCA6490", 386 }, 387 { 388 .id = QCA6490_v2, 389 .subid = 0, 390 .name = "QCA6490", 391 }, 392 { 393 .id = WCN3990_v2_2, 394 .subid = 0, 395 .name = "WCN3990_v2_2", 396 } 397 }; 398 399 /** 400 * hif_get_hw_name(): get a human readable name for the hardware 401 * @info: Target Info 402 * 403 * Return: human readable name for the underlying wifi hardware. 404 */ 405 static const char *hif_get_hw_name(struct hif_target_info *info) 406 { 407 int i; 408 409 hif_debug("target version = %d, target revision = %d", 410 info->target_version, 411 info->target_revision); 412 413 if (info->hw_name) 414 return info->hw_name; 415 416 for (i = 0; i < ARRAY_SIZE(qwlan_hw_list); i++) { 417 if (info->target_version == qwlan_hw_list[i].id && 418 info->target_revision == qwlan_hw_list[i].subid) { 419 return qwlan_hw_list[i].name; 420 } 421 } 422 423 info->hw_name = qdf_mem_malloc(64); 424 if (!info->hw_name) 425 return "Unknown Device (nomem)"; 426 427 i = qdf_snprint(info->hw_name, 64, "HW_VERSION=%x.", 428 info->target_version); 429 if (i < 0) 430 return "Unknown Device (snprintf failure)"; 431 else 432 return info->hw_name; 433 } 434 435 /** 436 * hif_get_hw_info(): hif_get_hw_info 437 * @scn: scn 438 * @version: version 439 * @revision: revision 440 * 441 * Return: n/a 442 */ 443 void hif_get_hw_info(struct hif_opaque_softc *scn, u32 *version, u32 *revision, 444 const char **target_name) 445 { 446 struct hif_target_info *info = hif_get_target_info_handle(scn); 447 struct hif_softc *sc = HIF_GET_SOFTC(scn); 448 449 if (sc->bus_type == QDF_BUS_TYPE_USB) 450 hif_usb_get_hw_info(sc); 451 452 *version = info->target_version; 453 *revision = info->target_revision; 454 *target_name = hif_get_hw_name(info); 455 } 456 457 /** 458 * hif_get_dev_ba(): API to get device base address. 459 * @scn: scn 460 * @version: version 461 * @revision: revision 462 * 463 * Return: n/a 464 */ 465 void *hif_get_dev_ba(struct hif_opaque_softc *hif_handle) 466 { 467 struct hif_softc *scn = (struct hif_softc *)hif_handle; 468 469 return scn->mem; 470 } 471 qdf_export_symbol(hif_get_dev_ba); 472 473 /** 474 * hif_get_dev_ba_ce(): API to get device ce base address. 475 * @scn: scn 476 * 477 * Return: dev mem base address for CE 478 */ 479 void *hif_get_dev_ba_ce(struct hif_opaque_softc *hif_handle) 480 { 481 struct hif_softc *scn = (struct hif_softc *)hif_handle; 482 483 return scn->mem_ce; 484 } 485 486 qdf_export_symbol(hif_get_dev_ba_ce); 487 488 uint32_t hif_get_soc_version(struct hif_opaque_softc *hif_handle) 489 { 490 struct hif_softc *scn = (struct hif_softc *)hif_handle; 491 492 return scn->target_info.soc_version; 493 } 494 495 qdf_export_symbol(hif_get_soc_version); 496 497 /** 498 * hif_get_dev_ba_cmem(): API to get device ce base address. 499 * @scn: scn 500 * 501 * Return: dev mem base address for CMEM 502 */ 503 void *hif_get_dev_ba_cmem(struct hif_opaque_softc *hif_handle) 504 { 505 struct hif_softc *scn = (struct hif_softc *)hif_handle; 506 507 return scn->mem_cmem; 508 } 509 510 qdf_export_symbol(hif_get_dev_ba_cmem); 511 512 #ifdef FEATURE_RUNTIME_PM 513 void hif_runtime_prevent_linkdown(struct hif_softc *scn, bool is_get) 514 { 515 if (is_get) 516 qdf_runtime_pm_prevent_suspend(&scn->prevent_linkdown_lock); 517 else 518 qdf_runtime_pm_allow_suspend(&scn->prevent_linkdown_lock); 519 } 520 521 static inline 522 void hif_rtpm_lock_init(struct hif_softc *scn) 523 { 524 qdf_runtime_lock_init(&scn->prevent_linkdown_lock); 525 } 526 527 static inline 528 void hif_rtpm_lock_deinit(struct hif_softc *scn) 529 { 530 qdf_runtime_lock_deinit(&scn->prevent_linkdown_lock); 531 } 532 #else 533 static inline 534 void hif_rtpm_lock_init(struct hif_softc *scn) 535 { 536 } 537 538 static inline 539 void hif_rtpm_lock_deinit(struct hif_softc *scn) 540 { 541 } 542 #endif 543 544 #ifdef WLAN_CE_INTERRUPT_THRESHOLD_CONFIG 545 /** 546 * hif_get_cfg_from_psoc() - Retrieve ini cfg from psoc 547 * @scn: hif context 548 * @psoc: psoc objmgr handle 549 * 550 * Return: None 551 */ 552 static inline 553 void hif_get_cfg_from_psoc(struct hif_softc *scn, 554 struct wlan_objmgr_psoc *psoc) 555 { 556 if (psoc) { 557 scn->ini_cfg.ce_status_ring_timer_threshold = 558 cfg_get(psoc, 559 CFG_CE_STATUS_RING_TIMER_THRESHOLD); 560 scn->ini_cfg.ce_status_ring_batch_count_threshold = 561 cfg_get(psoc, 562 CFG_CE_STATUS_RING_BATCH_COUNT_THRESHOLD); 563 } 564 } 565 #else 566 static inline 567 void hif_get_cfg_from_psoc(struct hif_softc *scn, 568 struct wlan_objmgr_psoc *psoc) 569 { 570 } 571 #endif /* WLAN_CE_INTERRUPT_THRESHOLD_CONFIG */ 572 573 #if defined(HIF_CE_LOG_INFO) || defined(HIF_BUS_LOG_INFO) 574 /** 575 * hif_recovery_notifier_cb - Recovery notifier callback to log 576 * hang event data 577 * @block: notifier block 578 * @state: state 579 * @data: notifier data 580 * 581 * Return: status 582 */ 583 static 584 int hif_recovery_notifier_cb(struct notifier_block *block, unsigned long state, 585 void *data) 586 { 587 struct qdf_notifer_data *notif_data = data; 588 qdf_notif_block *notif_block; 589 struct hif_softc *hif_handle; 590 bool bus_id_invalid; 591 592 if (!data || !block) 593 return -EINVAL; 594 595 notif_block = qdf_container_of(block, qdf_notif_block, notif_block); 596 597 hif_handle = notif_block->priv_data; 598 if (!hif_handle) 599 return -EINVAL; 600 601 bus_id_invalid = hif_log_bus_info(hif_handle, notif_data->hang_data, 602 ¬if_data->offset); 603 if (bus_id_invalid) 604 return NOTIFY_STOP_MASK; 605 606 hif_log_ce_info(hif_handle, notif_data->hang_data, 607 ¬if_data->offset); 608 609 return 0; 610 } 611 612 /** 613 * hif_register_recovery_notifier - Register hif recovery notifier 614 * @hif_handle: hif handle 615 * 616 * Return: status 617 */ 618 static 619 QDF_STATUS hif_register_recovery_notifier(struct hif_softc *hif_handle) 620 { 621 qdf_notif_block *hif_notifier; 622 623 if (!hif_handle) 624 return QDF_STATUS_E_FAILURE; 625 626 hif_notifier = &hif_handle->hif_recovery_notifier; 627 628 hif_notifier->notif_block.notifier_call = hif_recovery_notifier_cb; 629 hif_notifier->priv_data = hif_handle; 630 return qdf_hang_event_register_notifier(hif_notifier); 631 } 632 633 /** 634 * hif_unregister_recovery_notifier - Un-register hif recovery notifier 635 * @hif_handle: hif handle 636 * 637 * Return: status 638 */ 639 static 640 QDF_STATUS hif_unregister_recovery_notifier(struct hif_softc *hif_handle) 641 { 642 qdf_notif_block *hif_notifier = &hif_handle->hif_recovery_notifier; 643 644 return qdf_hang_event_unregister_notifier(hif_notifier); 645 } 646 #else 647 static inline 648 QDF_STATUS hif_register_recovery_notifier(struct hif_softc *hif_handle) 649 { 650 return QDF_STATUS_SUCCESS; 651 } 652 653 static inline 654 QDF_STATUS hif_unregister_recovery_notifier(struct hif_softc *hif_handle) 655 { 656 return QDF_STATUS_SUCCESS; 657 } 658 #endif 659 660 #ifdef HIF_CPU_PERF_AFFINE_MASK 661 /** 662 * __hif_cpu_hotplug_notify() - CPU hotplug event handler 663 * @cpu: CPU Id of the CPU generating the event 664 * @cpu_up: true if the CPU is online 665 * 666 * Return: None 667 */ 668 static void __hif_cpu_hotplug_notify(void *context, 669 uint32_t cpu, bool cpu_up) 670 { 671 struct hif_softc *scn = context; 672 673 if (!scn) 674 return; 675 if (hif_is_driver_unloading(scn) || hif_is_recovery_in_progress(scn)) 676 return; 677 678 if (cpu_up) { 679 hif_config_irq_set_perf_affinity_hint(GET_HIF_OPAQUE_HDL(scn)); 680 hif_debug("Setting affinity for online CPU: %d", cpu); 681 } else { 682 hif_debug("Skip setting affinity for offline CPU: %d", cpu); 683 } 684 } 685 686 /** 687 * hif_cpu_hotplug_notify - cpu core up/down notification 688 * handler 689 * @cpu: CPU generating the event 690 * @cpu_up: true if the CPU is online 691 * 692 * Return: None 693 */ 694 static void hif_cpu_hotplug_notify(void *context, uint32_t cpu, bool cpu_up) 695 { 696 struct qdf_op_sync *op_sync; 697 698 if (qdf_op_protect(&op_sync)) 699 return; 700 701 __hif_cpu_hotplug_notify(context, cpu, cpu_up); 702 703 qdf_op_unprotect(op_sync); 704 } 705 706 static void hif_cpu_online_cb(void *context, uint32_t cpu) 707 { 708 hif_cpu_hotplug_notify(context, cpu, true); 709 } 710 711 static void hif_cpu_before_offline_cb(void *context, uint32_t cpu) 712 { 713 hif_cpu_hotplug_notify(context, cpu, false); 714 } 715 716 static void hif_cpuhp_register(struct hif_softc *scn) 717 { 718 if (!scn) { 719 hif_info_high("cannot register hotplug notifiers"); 720 return; 721 } 722 qdf_cpuhp_register(&scn->cpuhp_event_handle, 723 scn, 724 hif_cpu_online_cb, 725 hif_cpu_before_offline_cb); 726 } 727 728 static void hif_cpuhp_unregister(struct hif_softc *scn) 729 { 730 if (!scn) { 731 hif_info_high("cannot unregister hotplug notifiers"); 732 return; 733 } 734 qdf_cpuhp_unregister(&scn->cpuhp_event_handle); 735 } 736 737 #else 738 static void hif_cpuhp_register(struct hif_softc *scn) 739 { 740 } 741 742 static void hif_cpuhp_unregister(struct hif_softc *scn) 743 { 744 } 745 #endif /* ifdef HIF_CPU_PERF_AFFINE_MASK */ 746 747 #ifdef HIF_DETECTION_LATENCY_ENABLE 748 749 void hif_tasklet_latency(struct hif_softc *scn, bool from_timer) 750 { 751 qdf_time_t ce2_tasklet_sched_time = 752 scn->latency_detect.ce2_tasklet_sched_time; 753 qdf_time_t ce2_tasklet_exec_time = 754 scn->latency_detect.ce2_tasklet_exec_time; 755 qdf_time_t curr_jiffies = qdf_system_ticks(); 756 uint32_t detect_latency_threshold = 757 scn->latency_detect.detect_latency_threshold; 758 int cpu_id = qdf_get_cpu(); 759 760 /* 2 kinds of check here. 761 * from_timer==true: check if tasklet stall 762 * from_timer==false: check tasklet execute comes late 763 */ 764 765 if ((from_timer ? 766 qdf_system_time_after(ce2_tasklet_sched_time, 767 ce2_tasklet_exec_time) : 768 qdf_system_time_after(ce2_tasklet_exec_time, 769 ce2_tasklet_sched_time)) && 770 qdf_system_time_after( 771 curr_jiffies, 772 ce2_tasklet_sched_time + 773 qdf_system_msecs_to_ticks(detect_latency_threshold))) { 774 hif_err("tasklet ce2 latency: from_timer %d, curr_jiffies %lu, ce2_tasklet_sched_time %lu,ce2_tasklet_exec_time %lu, detect_latency_threshold %ums detect_latency_timer_timeout %ums, cpu_id %d, called: %ps", 775 from_timer, curr_jiffies, ce2_tasklet_sched_time, 776 ce2_tasklet_exec_time, detect_latency_threshold, 777 scn->latency_detect.detect_latency_timer_timeout, 778 cpu_id, (void *)_RET_IP_); 779 goto latency; 780 } 781 return; 782 783 latency: 784 qdf_trigger_self_recovery(NULL, QDF_TASKLET_CREDIT_LATENCY_DETECT); 785 } 786 787 void hif_credit_latency(struct hif_softc *scn, bool from_timer) 788 { 789 qdf_time_t credit_request_time = 790 scn->latency_detect.credit_request_time; 791 qdf_time_t credit_report_time = 792 scn->latency_detect.credit_report_time; 793 qdf_time_t curr_jiffies = qdf_system_ticks(); 794 uint32_t detect_latency_threshold = 795 scn->latency_detect.detect_latency_threshold; 796 int cpu_id = qdf_get_cpu(); 797 798 /* 2 kinds of check here. 799 * from_timer==true: check if credit report stall 800 * from_timer==false: check credit report comes late 801 */ 802 803 if ((from_timer ? 804 qdf_system_time_after(credit_request_time, 805 credit_report_time) : 806 qdf_system_time_after(credit_report_time, 807 credit_request_time)) && 808 qdf_system_time_after( 809 curr_jiffies, 810 credit_request_time + 811 qdf_system_msecs_to_ticks(detect_latency_threshold))) { 812 hif_err("credit report latency: from timer %d, curr_jiffies %lu, credit_request_time %lu,credit_report_time %lu, detect_latency_threshold %ums, detect_latency_timer_timeout %ums, cpu_id %d, called: %ps", 813 from_timer, curr_jiffies, credit_request_time, 814 credit_report_time, detect_latency_threshold, 815 scn->latency_detect.detect_latency_timer_timeout, 816 cpu_id, (void *)_RET_IP_); 817 goto latency; 818 } 819 return; 820 821 latency: 822 qdf_trigger_self_recovery(NULL, QDF_TASKLET_CREDIT_LATENCY_DETECT); 823 } 824 825 /** 826 * hif_check_detection_latency(): to check if latency for tasklet/credit 827 * 828 * @scn: hif context 829 * @from_timer: if called from timer handler 830 * @bitmap_type: indicate if check tasklet or credit 831 * 832 * Return: none 833 */ 834 void hif_check_detection_latency(struct hif_softc *scn, 835 bool from_timer, 836 uint32_t bitmap_type) 837 { 838 if (QDF_GLOBAL_MISSION_MODE != hif_get_conparam(scn)) 839 return; 840 841 if (!scn->latency_detect.enable_detection) 842 return; 843 844 if (bitmap_type & BIT(HIF_DETECT_TASKLET)) 845 hif_tasklet_latency(scn, from_timer); 846 847 if (bitmap_type & BIT(HIF_DETECT_CREDIT)) 848 hif_credit_latency(scn, from_timer); 849 } 850 851 static void hif_latency_detect_timeout_handler(void *arg) 852 { 853 struct hif_softc *scn = (struct hif_softc *)arg; 854 int next_cpu; 855 856 hif_check_detection_latency(scn, true, 857 BIT(HIF_DETECT_TASKLET) | 858 BIT(HIF_DETECT_CREDIT)); 859 860 /* it need to make sure timer start on a differnt cpu, 861 * so it can detect the tasklet schedule stall, but there 862 * is still chance that, after timer has been started, then 863 * irq/tasklet happens on the same cpu, then tasklet will 864 * execute before softirq timer, if this tasklet stall, the 865 * timer can't detect it, we can accept this as a limition, 866 * if tasklet stall, anyway other place will detect it, just 867 * a little later. 868 */ 869 next_cpu = cpumask_any_but( 870 cpu_active_mask, 871 scn->latency_detect.ce2_tasklet_sched_cpuid); 872 873 if (qdf_unlikely(next_cpu >= nr_cpu_ids)) { 874 hif_debug("start timer on local"); 875 /* it doesn't found a available cpu, start on local cpu*/ 876 qdf_timer_mod( 877 &scn->latency_detect.detect_latency_timer, 878 scn->latency_detect.detect_latency_timer_timeout); 879 } else { 880 qdf_timer_start_on( 881 &scn->latency_detect.detect_latency_timer, 882 scn->latency_detect.detect_latency_timer_timeout, 883 next_cpu); 884 } 885 } 886 887 static void hif_latency_detect_timer_init(struct hif_softc *scn) 888 { 889 if (!scn) { 890 hif_info_high("scn is null"); 891 return; 892 } 893 894 if (QDF_GLOBAL_MISSION_MODE != hif_get_conparam(scn)) 895 return; 896 897 scn->latency_detect.detect_latency_timer_timeout = 898 DETECTION_TIMER_TIMEOUT; 899 scn->latency_detect.detect_latency_threshold = 900 DETECTION_LATENCY_THRESHOLD; 901 902 hif_info("timer timeout %u, latency threshold %u", 903 scn->latency_detect.detect_latency_timer_timeout, 904 scn->latency_detect.detect_latency_threshold); 905 906 scn->latency_detect.is_timer_started = false; 907 908 qdf_timer_init(NULL, 909 &scn->latency_detect.detect_latency_timer, 910 &hif_latency_detect_timeout_handler, 911 scn, 912 QDF_TIMER_TYPE_SW_SPIN); 913 } 914 915 static void hif_latency_detect_timer_deinit(struct hif_softc *scn) 916 { 917 if (QDF_GLOBAL_MISSION_MODE != hif_get_conparam(scn)) 918 return; 919 920 hif_info("deinit timer"); 921 qdf_timer_free(&scn->latency_detect.detect_latency_timer); 922 } 923 924 void hif_latency_detect_timer_start(struct hif_opaque_softc *hif_ctx) 925 { 926 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 927 928 if (QDF_GLOBAL_MISSION_MODE != hif_get_conparam(scn)) 929 return; 930 931 hif_debug_rl("start timer"); 932 if (scn->latency_detect.is_timer_started) { 933 hif_info("timer has been started"); 934 return; 935 } 936 937 qdf_timer_start(&scn->latency_detect.detect_latency_timer, 938 scn->latency_detect.detect_latency_timer_timeout); 939 scn->latency_detect.is_timer_started = true; 940 } 941 942 void hif_latency_detect_timer_stop(struct hif_opaque_softc *hif_ctx) 943 { 944 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 945 946 if (QDF_GLOBAL_MISSION_MODE != hif_get_conparam(scn)) 947 return; 948 949 hif_debug_rl("stop timer"); 950 951 qdf_timer_sync_cancel(&scn->latency_detect.detect_latency_timer); 952 scn->latency_detect.is_timer_started = false; 953 } 954 955 void hif_latency_detect_credit_record_time( 956 enum hif_credit_exchange_type type, 957 struct hif_opaque_softc *hif_ctx) 958 { 959 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 960 961 if (!scn) { 962 hif_err("Could not do runtime put, scn is null"); 963 return; 964 } 965 966 if (QDF_GLOBAL_MISSION_MODE != hif_get_conparam(scn)) 967 return; 968 969 if (HIF_REQUEST_CREDIT == type) 970 scn->latency_detect.credit_request_time = qdf_system_ticks(); 971 else if (HIF_PROCESS_CREDIT_REPORT == type) 972 scn->latency_detect.credit_report_time = qdf_system_ticks(); 973 974 hif_check_detection_latency(scn, false, BIT(HIF_DETECT_CREDIT)); 975 } 976 977 void hif_set_enable_detection(struct hif_opaque_softc *hif_ctx, bool value) 978 { 979 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 980 981 if (!scn) { 982 hif_err("Could not do runtime put, scn is null"); 983 return; 984 } 985 986 if (QDF_GLOBAL_MISSION_MODE != hif_get_conparam(scn)) 987 return; 988 989 scn->latency_detect.enable_detection = value; 990 } 991 #else 992 static void hif_latency_detect_timer_init(struct hif_softc *scn) 993 {} 994 995 static void hif_latency_detect_timer_deinit(struct hif_softc *scn) 996 {} 997 #endif 998 struct hif_opaque_softc *hif_open(qdf_device_t qdf_ctx, 999 uint32_t mode, 1000 enum qdf_bus_type bus_type, 1001 struct hif_driver_state_callbacks *cbk, 1002 struct wlan_objmgr_psoc *psoc) 1003 { 1004 struct hif_softc *scn; 1005 QDF_STATUS status = QDF_STATUS_SUCCESS; 1006 int bus_context_size = hif_bus_get_context_size(bus_type); 1007 1008 if (bus_context_size == 0) { 1009 hif_err("context size 0 not allowed"); 1010 return NULL; 1011 } 1012 1013 scn = (struct hif_softc *)qdf_mem_malloc(bus_context_size); 1014 if (!scn) 1015 return GET_HIF_OPAQUE_HDL(scn); 1016 1017 scn->qdf_dev = qdf_ctx; 1018 scn->hif_con_param = mode; 1019 qdf_atomic_init(&scn->active_tasklet_cnt); 1020 1021 qdf_atomic_init(&scn->active_grp_tasklet_cnt); 1022 qdf_atomic_init(&scn->link_suspended); 1023 qdf_atomic_init(&scn->tasklet_from_intr); 1024 hif_system_pm_set_state_on(GET_HIF_OPAQUE_HDL(scn)); 1025 qdf_mem_copy(&scn->callbacks, cbk, 1026 sizeof(struct hif_driver_state_callbacks)); 1027 scn->bus_type = bus_type; 1028 1029 hif_allow_ep_vote_access(GET_HIF_OPAQUE_HDL(scn)); 1030 hif_get_cfg_from_psoc(scn, psoc); 1031 1032 hif_set_event_hist_mask(GET_HIF_OPAQUE_HDL(scn)); 1033 status = hif_bus_open(scn, bus_type); 1034 if (status != QDF_STATUS_SUCCESS) { 1035 hif_err("hif_bus_open error = %d, bus_type = %d", 1036 status, bus_type); 1037 qdf_mem_free(scn); 1038 scn = NULL; 1039 goto out; 1040 } 1041 1042 hif_rtpm_lock_init(scn); 1043 1044 hif_cpuhp_register(scn); 1045 hif_latency_detect_timer_init(scn); 1046 1047 out: 1048 return GET_HIF_OPAQUE_HDL(scn); 1049 } 1050 1051 #ifdef ADRASTEA_RRI_ON_DDR 1052 /** 1053 * hif_uninit_rri_on_ddr(): free consistent memory allocated for rri 1054 * @scn: hif context 1055 * 1056 * Return: none 1057 */ 1058 void hif_uninit_rri_on_ddr(struct hif_softc *scn) 1059 { 1060 if (scn->vaddr_rri_on_ddr) 1061 qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev, 1062 (CE_COUNT * sizeof(uint32_t)), 1063 scn->vaddr_rri_on_ddr, 1064 scn->paddr_rri_on_ddr, 0); 1065 scn->vaddr_rri_on_ddr = NULL; 1066 } 1067 #endif 1068 1069 /** 1070 * hif_close(): hif_close 1071 * @hif_ctx: hif_ctx 1072 * 1073 * Return: n/a 1074 */ 1075 void hif_close(struct hif_opaque_softc *hif_ctx) 1076 { 1077 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1078 1079 if (!scn) { 1080 hif_err("hif_opaque_softc is NULL"); 1081 return; 1082 } 1083 1084 hif_latency_detect_timer_deinit(scn); 1085 1086 if (scn->athdiag_procfs_inited) { 1087 athdiag_procfs_remove(); 1088 scn->athdiag_procfs_inited = false; 1089 } 1090 1091 if (scn->target_info.hw_name) { 1092 char *hw_name = scn->target_info.hw_name; 1093 1094 scn->target_info.hw_name = "ErrUnloading"; 1095 qdf_mem_free(hw_name); 1096 } 1097 1098 hif_uninit_rri_on_ddr(scn); 1099 hif_cleanup_static_buf_to_target(scn); 1100 hif_cpuhp_unregister(scn); 1101 hif_rtpm_lock_deinit(scn); 1102 1103 hif_bus_close(scn); 1104 1105 qdf_mem_free(scn); 1106 } 1107 1108 /** 1109 * hif_get_num_active_grp_tasklets() - get the number of active 1110 * datapath group tasklets pending to be completed. 1111 * @scn: HIF context 1112 * 1113 * Returns: the number of datapath group tasklets which are active 1114 */ 1115 static inline int hif_get_num_active_grp_tasklets(struct hif_softc *scn) 1116 { 1117 return qdf_atomic_read(&scn->active_grp_tasklet_cnt); 1118 } 1119 1120 #if (defined(QCA_WIFI_QCA8074) || defined(QCA_WIFI_QCA6018) || \ 1121 defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390) || \ 1122 defined(QCA_WIFI_QCN9000) || defined(QCA_WIFI_QCA6490) || \ 1123 defined(QCA_WIFI_QCA6750) || defined(QCA_WIFI_QCA5018) || \ 1124 defined(QCA_WIFI_KIWI) || defined(QCA_WIFI_QCN9224) || \ 1125 defined(QCA_WIFI_QCA9574)) || defined(QCA_WIFI_QCA5332) 1126 /** 1127 * hif_get_num_pending_work() - get the number of entries in 1128 * the workqueue pending to be completed. 1129 * @scn: HIF context 1130 * 1131 * Returns: the number of tasklets which are active 1132 */ 1133 static inline int hif_get_num_pending_work(struct hif_softc *scn) 1134 { 1135 return hal_get_reg_write_pending_work(scn->hal_soc); 1136 } 1137 #else 1138 1139 static inline int hif_get_num_pending_work(struct hif_softc *scn) 1140 { 1141 return 0; 1142 } 1143 #endif 1144 1145 QDF_STATUS hif_try_complete_tasks(struct hif_softc *scn) 1146 { 1147 uint32_t task_drain_wait_cnt = 0; 1148 int tasklet = 0, grp_tasklet = 0, work = 0; 1149 1150 while ((tasklet = hif_get_num_active_tasklets(scn)) || 1151 (grp_tasklet = hif_get_num_active_grp_tasklets(scn)) || 1152 (work = hif_get_num_pending_work(scn))) { 1153 if (++task_drain_wait_cnt > HIF_TASK_DRAIN_WAIT_CNT) { 1154 hif_err("pending tasklets %d grp tasklets %d work %d", 1155 tasklet, grp_tasklet, work); 1156 return QDF_STATUS_E_FAULT; 1157 } 1158 hif_info("waiting for tasklets %d grp tasklets %d work %d", 1159 tasklet, grp_tasklet, work); 1160 msleep(10); 1161 } 1162 1163 return QDF_STATUS_SUCCESS; 1164 } 1165 1166 #if defined(HIF_IPCI) && defined(FEATURE_HAL_DELAYED_REG_WRITE) 1167 QDF_STATUS hif_try_prevent_ep_vote_access(struct hif_opaque_softc *hif_ctx) 1168 { 1169 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1170 uint32_t work_drain_wait_cnt = 0; 1171 uint32_t wait_cnt = 0; 1172 int work = 0; 1173 1174 qdf_atomic_set(&scn->dp_ep_vote_access, 1175 HIF_EP_VOTE_ACCESS_DISABLE); 1176 qdf_atomic_set(&scn->ep_vote_access, 1177 HIF_EP_VOTE_ACCESS_DISABLE); 1178 1179 while ((work = hif_get_num_pending_work(scn))) { 1180 if (++work_drain_wait_cnt > HIF_WORK_DRAIN_WAIT_CNT) { 1181 qdf_atomic_set(&scn->dp_ep_vote_access, 1182 HIF_EP_VOTE_ACCESS_ENABLE); 1183 qdf_atomic_set(&scn->ep_vote_access, 1184 HIF_EP_VOTE_ACCESS_ENABLE); 1185 hif_err("timeout wait for pending work %d ", work); 1186 return QDF_STATUS_E_FAULT; 1187 } 1188 qdf_sleep(10); 1189 } 1190 1191 if (pld_is_pci_ep_awake(scn->qdf_dev->dev) == -ENOTSUPP) 1192 return QDF_STATUS_SUCCESS; 1193 1194 while (pld_is_pci_ep_awake(scn->qdf_dev->dev)) { 1195 if (++wait_cnt > HIF_EP_WAKE_RESET_WAIT_CNT) { 1196 hif_err("Release EP vote is not proceed by Fw"); 1197 return QDF_STATUS_E_FAULT; 1198 } 1199 qdf_sleep(5); 1200 } 1201 1202 return QDF_STATUS_SUCCESS; 1203 } 1204 1205 void hif_set_ep_intermediate_vote_access(struct hif_opaque_softc *hif_ctx) 1206 { 1207 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1208 uint8_t vote_access; 1209 1210 vote_access = qdf_atomic_read(&scn->ep_vote_access); 1211 1212 if (vote_access != HIF_EP_VOTE_ACCESS_DISABLE) 1213 hif_info("EP vote changed from:%u to intermediate state", 1214 vote_access); 1215 1216 if (QDF_IS_STATUS_ERROR(hif_try_prevent_ep_vote_access(hif_ctx))) 1217 QDF_BUG(0); 1218 1219 qdf_atomic_set(&scn->ep_vote_access, 1220 HIF_EP_VOTE_INTERMEDIATE_ACCESS); 1221 } 1222 1223 void hif_allow_ep_vote_access(struct hif_opaque_softc *hif_ctx) 1224 { 1225 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1226 1227 qdf_atomic_set(&scn->dp_ep_vote_access, 1228 HIF_EP_VOTE_ACCESS_ENABLE); 1229 qdf_atomic_set(&scn->ep_vote_access, 1230 HIF_EP_VOTE_ACCESS_ENABLE); 1231 } 1232 1233 void hif_set_ep_vote_access(struct hif_opaque_softc *hif_ctx, 1234 uint8_t type, uint8_t access) 1235 { 1236 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1237 1238 if (type == HIF_EP_VOTE_DP_ACCESS) 1239 qdf_atomic_set(&scn->dp_ep_vote_access, access); 1240 else 1241 qdf_atomic_set(&scn->ep_vote_access, access); 1242 } 1243 1244 uint8_t hif_get_ep_vote_access(struct hif_opaque_softc *hif_ctx, 1245 uint8_t type) 1246 { 1247 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1248 1249 if (type == HIF_EP_VOTE_DP_ACCESS) 1250 return qdf_atomic_read(&scn->dp_ep_vote_access); 1251 else 1252 return qdf_atomic_read(&scn->ep_vote_access); 1253 } 1254 #endif 1255 1256 #if (defined(QCA_WIFI_QCA8074) || defined(QCA_WIFI_QCA6018) || \ 1257 defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390) || \ 1258 defined(QCA_WIFI_QCN9000) || defined(QCA_WIFI_QCA6490) || \ 1259 defined(QCA_WIFI_QCA6750) || defined(QCA_WIFI_QCA5018) || \ 1260 defined(QCA_WIFI_KIWI) || defined(QCA_WIFI_QCN9224) || \ 1261 defined(QCA_WIFI_QCA9574)) || defined(QCA_WIFI_QCA5332) 1262 static QDF_STATUS hif_hal_attach(struct hif_softc *scn) 1263 { 1264 if (ce_srng_based(scn)) { 1265 scn->hal_soc = hal_attach( 1266 hif_softc_to_hif_opaque_softc(scn), 1267 scn->qdf_dev); 1268 if (!scn->hal_soc) 1269 return QDF_STATUS_E_FAILURE; 1270 } 1271 1272 return QDF_STATUS_SUCCESS; 1273 } 1274 1275 static QDF_STATUS hif_hal_detach(struct hif_softc *scn) 1276 { 1277 if (ce_srng_based(scn)) { 1278 hal_detach(scn->hal_soc); 1279 scn->hal_soc = NULL; 1280 } 1281 1282 return QDF_STATUS_SUCCESS; 1283 } 1284 #else 1285 static QDF_STATUS hif_hal_attach(struct hif_softc *scn) 1286 { 1287 return QDF_STATUS_SUCCESS; 1288 } 1289 1290 static QDF_STATUS hif_hal_detach(struct hif_softc *scn) 1291 { 1292 return QDF_STATUS_SUCCESS; 1293 } 1294 #endif 1295 1296 int hif_init_dma_mask(struct device *dev, enum qdf_bus_type bus_type) 1297 { 1298 int ret; 1299 1300 switch (bus_type) { 1301 case QDF_BUS_TYPE_IPCI: 1302 ret = qdf_set_dma_coherent_mask(dev, 1303 DMA_COHERENT_MASK_DEFAULT); 1304 if (ret) { 1305 hif_err("Failed to set dma mask error = %d", ret); 1306 return ret; 1307 } 1308 1309 break; 1310 default: 1311 /* Follow the existing sequence for other targets */ 1312 break; 1313 } 1314 1315 return 0; 1316 } 1317 1318 /** 1319 * hif_enable(): hif_enable 1320 * @hif_ctx: hif_ctx 1321 * @dev: dev 1322 * @bdev: bus dev 1323 * @bid: bus ID 1324 * @bus_type: bus type 1325 * @type: enable type 1326 * 1327 * Return: QDF_STATUS 1328 */ 1329 QDF_STATUS hif_enable(struct hif_opaque_softc *hif_ctx, struct device *dev, 1330 void *bdev, 1331 const struct hif_bus_id *bid, 1332 enum qdf_bus_type bus_type, 1333 enum hif_enable_type type) 1334 { 1335 QDF_STATUS status; 1336 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1337 1338 if (!scn) { 1339 hif_err("hif_ctx = NULL"); 1340 return QDF_STATUS_E_NULL_VALUE; 1341 } 1342 1343 status = hif_enable_bus(scn, dev, bdev, bid, type); 1344 if (status != QDF_STATUS_SUCCESS) { 1345 hif_err("hif_enable_bus error = %d", status); 1346 return status; 1347 } 1348 1349 status = hif_hal_attach(scn); 1350 if (status != QDF_STATUS_SUCCESS) { 1351 hif_err("hal attach failed"); 1352 goto disable_bus; 1353 } 1354 1355 if (hif_bus_configure(scn)) { 1356 hif_err("Target probe failed"); 1357 status = QDF_STATUS_E_FAILURE; 1358 goto hal_detach; 1359 } 1360 1361 hif_ut_suspend_init(scn); 1362 hif_register_recovery_notifier(scn); 1363 hif_latency_detect_timer_start(hif_ctx); 1364 1365 /* 1366 * Flag to avoid potential unallocated memory access from MSI 1367 * interrupt handler which could get scheduled as soon as MSI 1368 * is enabled, i.e to take care of the race due to the order 1369 * in where MSI is enabled before the memory, that will be 1370 * in interrupt handlers, is allocated. 1371 */ 1372 1373 scn->hif_init_done = true; 1374 1375 hif_debug("OK"); 1376 1377 return QDF_STATUS_SUCCESS; 1378 1379 hal_detach: 1380 hif_hal_detach(scn); 1381 disable_bus: 1382 hif_disable_bus(scn); 1383 return status; 1384 } 1385 1386 void hif_disable(struct hif_opaque_softc *hif_ctx, enum hif_disable_type type) 1387 { 1388 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1389 1390 if (!scn) 1391 return; 1392 1393 hif_set_enable_detection(hif_ctx, false); 1394 hif_latency_detect_timer_stop(hif_ctx); 1395 1396 hif_unregister_recovery_notifier(scn); 1397 1398 hif_nointrs(scn); 1399 if (scn->hif_init_done == false) 1400 hif_shutdown_device(hif_ctx); 1401 else 1402 hif_stop(hif_ctx); 1403 1404 hif_hal_detach(scn); 1405 1406 hif_disable_bus(scn); 1407 1408 hif_wlan_disable(scn); 1409 1410 scn->notice_send = false; 1411 1412 hif_debug("X"); 1413 } 1414 1415 #ifdef CE_TASKLET_DEBUG_ENABLE 1416 void hif_enable_ce_latency_stats(struct hif_opaque_softc *hif_ctx, uint8_t val) 1417 { 1418 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1419 1420 if (!scn) 1421 return; 1422 1423 scn->ce_latency_stats = val; 1424 } 1425 #endif 1426 1427 void hif_display_stats(struct hif_opaque_softc *hif_ctx) 1428 { 1429 hif_display_bus_stats(hif_ctx); 1430 } 1431 1432 qdf_export_symbol(hif_display_stats); 1433 1434 void hif_clear_stats(struct hif_opaque_softc *hif_ctx) 1435 { 1436 hif_clear_bus_stats(hif_ctx); 1437 } 1438 1439 /** 1440 * hif_crash_shutdown_dump_bus_register() - dump bus registers 1441 * @hif_ctx: hif_ctx 1442 * 1443 * Return: n/a 1444 */ 1445 #if defined(TARGET_RAMDUMP_AFTER_KERNEL_PANIC) && defined(WLAN_FEATURE_BMI) 1446 1447 static void hif_crash_shutdown_dump_bus_register(void *hif_ctx) 1448 { 1449 struct hif_opaque_softc *scn = hif_ctx; 1450 1451 if (hif_check_soc_status(scn)) 1452 return; 1453 1454 if (hif_dump_registers(scn)) 1455 hif_err("Failed to dump bus registers!"); 1456 } 1457 1458 /** 1459 * hif_crash_shutdown(): hif_crash_shutdown 1460 * 1461 * This function is called by the platform driver to dump CE registers 1462 * 1463 * @hif_ctx: hif_ctx 1464 * 1465 * Return: n/a 1466 */ 1467 void hif_crash_shutdown(struct hif_opaque_softc *hif_ctx) 1468 { 1469 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1470 1471 if (!hif_ctx) 1472 return; 1473 1474 if (scn->bus_type == QDF_BUS_TYPE_SNOC) { 1475 hif_warn("RAM dump disabled for bustype %d", scn->bus_type); 1476 return; 1477 } 1478 1479 if (TARGET_STATUS_RESET == scn->target_status) { 1480 hif_warn("Target is already asserted, ignore!"); 1481 return; 1482 } 1483 1484 if (hif_is_load_or_unload_in_progress(scn)) { 1485 hif_err("Load/unload is in progress, ignore!"); 1486 return; 1487 } 1488 1489 hif_crash_shutdown_dump_bus_register(hif_ctx); 1490 hif_set_target_status(hif_ctx, TARGET_STATUS_RESET); 1491 1492 if (ol_copy_ramdump(hif_ctx)) 1493 goto out; 1494 1495 hif_info("RAM dump collecting completed!"); 1496 1497 out: 1498 return; 1499 } 1500 #else 1501 void hif_crash_shutdown(struct hif_opaque_softc *hif_ctx) 1502 { 1503 hif_debug("Collecting target RAM dump disabled"); 1504 } 1505 #endif /* TARGET_RAMDUMP_AFTER_KERNEL_PANIC */ 1506 1507 #ifdef QCA_WIFI_3_0 1508 /** 1509 * hif_check_fw_reg(): hif_check_fw_reg 1510 * @scn: scn 1511 * @state: 1512 * 1513 * Return: int 1514 */ 1515 int hif_check_fw_reg(struct hif_opaque_softc *scn) 1516 { 1517 return 0; 1518 } 1519 #endif 1520 1521 /** 1522 * hif_read_phy_mem_base(): hif_read_phy_mem_base 1523 * @scn: scn 1524 * @phy_mem_base: physical mem base 1525 * 1526 * Return: n/a 1527 */ 1528 void hif_read_phy_mem_base(struct hif_softc *scn, qdf_dma_addr_t *phy_mem_base) 1529 { 1530 *phy_mem_base = scn->mem_pa; 1531 } 1532 qdf_export_symbol(hif_read_phy_mem_base); 1533 1534 /** 1535 * hif_get_device_type(): hif_get_device_type 1536 * @device_id: device_id 1537 * @revision_id: revision_id 1538 * @hif_type: returned hif_type 1539 * @target_type: returned target_type 1540 * 1541 * Return: int 1542 */ 1543 int hif_get_device_type(uint32_t device_id, 1544 uint32_t revision_id, 1545 uint32_t *hif_type, uint32_t *target_type) 1546 { 1547 int ret = 0; 1548 1549 switch (device_id) { 1550 case ADRASTEA_DEVICE_ID_P2_E12: 1551 1552 *hif_type = HIF_TYPE_ADRASTEA; 1553 *target_type = TARGET_TYPE_ADRASTEA; 1554 break; 1555 1556 case AR9888_DEVICE_ID: 1557 *hif_type = HIF_TYPE_AR9888; 1558 *target_type = TARGET_TYPE_AR9888; 1559 break; 1560 1561 case AR6320_DEVICE_ID: 1562 switch (revision_id) { 1563 case AR6320_FW_1_1: 1564 case AR6320_FW_1_3: 1565 *hif_type = HIF_TYPE_AR6320; 1566 *target_type = TARGET_TYPE_AR6320; 1567 break; 1568 1569 case AR6320_FW_2_0: 1570 case AR6320_FW_3_0: 1571 case AR6320_FW_3_2: 1572 *hif_type = HIF_TYPE_AR6320V2; 1573 *target_type = TARGET_TYPE_AR6320V2; 1574 break; 1575 1576 default: 1577 hif_err("dev_id = 0x%x, rev_id = 0x%x", 1578 device_id, revision_id); 1579 ret = -ENODEV; 1580 goto end; 1581 } 1582 break; 1583 1584 case AR9887_DEVICE_ID: 1585 *hif_type = HIF_TYPE_AR9888; 1586 *target_type = TARGET_TYPE_AR9888; 1587 hif_info(" *********** AR9887 **************"); 1588 break; 1589 1590 case QCA9984_DEVICE_ID: 1591 *hif_type = HIF_TYPE_QCA9984; 1592 *target_type = TARGET_TYPE_QCA9984; 1593 hif_info(" *********** QCA9984 *************"); 1594 break; 1595 1596 case QCA9888_DEVICE_ID: 1597 *hif_type = HIF_TYPE_QCA9888; 1598 *target_type = TARGET_TYPE_QCA9888; 1599 hif_info(" *********** QCA9888 *************"); 1600 break; 1601 1602 case AR900B_DEVICE_ID: 1603 *hif_type = HIF_TYPE_AR900B; 1604 *target_type = TARGET_TYPE_AR900B; 1605 hif_info(" *********** AR900B *************"); 1606 break; 1607 1608 case QCA8074_DEVICE_ID: 1609 *hif_type = HIF_TYPE_QCA8074; 1610 *target_type = TARGET_TYPE_QCA8074; 1611 hif_info(" *********** QCA8074 *************"); 1612 break; 1613 1614 case QCA6290_EMULATION_DEVICE_ID: 1615 case QCA6290_DEVICE_ID: 1616 *hif_type = HIF_TYPE_QCA6290; 1617 *target_type = TARGET_TYPE_QCA6290; 1618 hif_info(" *********** QCA6290EMU *************"); 1619 break; 1620 1621 case QCN9000_DEVICE_ID: 1622 *hif_type = HIF_TYPE_QCN9000; 1623 *target_type = TARGET_TYPE_QCN9000; 1624 hif_info(" *********** QCN9000 *************"); 1625 break; 1626 1627 case QCN9224_DEVICE_ID: 1628 *hif_type = HIF_TYPE_QCN9224; 1629 *target_type = TARGET_TYPE_QCN9224; 1630 hif_info(" *********** QCN9224 *************"); 1631 break; 1632 1633 case QCN6122_DEVICE_ID: 1634 *hif_type = HIF_TYPE_QCN6122; 1635 *target_type = TARGET_TYPE_QCN6122; 1636 hif_info(" *********** QCN6122 *************"); 1637 break; 1638 1639 case QCN7605_DEVICE_ID: 1640 case QCN7605_COMPOSITE: 1641 case QCN7605_STANDALONE: 1642 case QCN7605_STANDALONE_V2: 1643 case QCN7605_COMPOSITE_V2: 1644 *hif_type = HIF_TYPE_QCN7605; 1645 *target_type = TARGET_TYPE_QCN7605; 1646 hif_info(" *********** QCN7605 *************"); 1647 break; 1648 1649 case QCA6390_DEVICE_ID: 1650 case QCA6390_EMULATION_DEVICE_ID: 1651 *hif_type = HIF_TYPE_QCA6390; 1652 *target_type = TARGET_TYPE_QCA6390; 1653 hif_info(" *********** QCA6390 *************"); 1654 break; 1655 1656 case QCA6490_DEVICE_ID: 1657 case QCA6490_EMULATION_DEVICE_ID: 1658 *hif_type = HIF_TYPE_QCA6490; 1659 *target_type = TARGET_TYPE_QCA6490; 1660 hif_info(" *********** QCA6490 *************"); 1661 break; 1662 1663 case QCA6750_DEVICE_ID: 1664 case QCA6750_EMULATION_DEVICE_ID: 1665 *hif_type = HIF_TYPE_QCA6750; 1666 *target_type = TARGET_TYPE_QCA6750; 1667 hif_info(" *********** QCA6750 *************"); 1668 break; 1669 1670 case KIWI_DEVICE_ID: 1671 *hif_type = HIF_TYPE_KIWI; 1672 *target_type = TARGET_TYPE_KIWI; 1673 hif_info(" *********** KIWI *************"); 1674 break; 1675 1676 case MANGO_DEVICE_ID: 1677 *hif_type = HIF_TYPE_MANGO; 1678 *target_type = TARGET_TYPE_MANGO; 1679 hif_info(" *********** MANGO *************"); 1680 break; 1681 1682 case QCA8074V2_DEVICE_ID: 1683 *hif_type = HIF_TYPE_QCA8074V2; 1684 *target_type = TARGET_TYPE_QCA8074V2; 1685 hif_info(" *********** QCA8074V2 *************"); 1686 break; 1687 1688 case QCA6018_DEVICE_ID: 1689 case RUMIM2M_DEVICE_ID_NODE0: 1690 case RUMIM2M_DEVICE_ID_NODE1: 1691 case RUMIM2M_DEVICE_ID_NODE2: 1692 case RUMIM2M_DEVICE_ID_NODE3: 1693 case RUMIM2M_DEVICE_ID_NODE4: 1694 case RUMIM2M_DEVICE_ID_NODE5: 1695 *hif_type = HIF_TYPE_QCA6018; 1696 *target_type = TARGET_TYPE_QCA6018; 1697 hif_info(" *********** QCA6018 *************"); 1698 break; 1699 1700 case QCA5018_DEVICE_ID: 1701 *hif_type = HIF_TYPE_QCA5018; 1702 *target_type = TARGET_TYPE_QCA5018; 1703 hif_info(" *********** qca5018 *************"); 1704 break; 1705 1706 case QCA5332_DEVICE_ID: 1707 *hif_type = HIF_TYPE_QCA5332; 1708 *target_type = TARGET_TYPE_QCA5332; 1709 hif_info(" *********** QCA5332 *************"); 1710 break; 1711 1712 case QCA9574_DEVICE_ID: 1713 *hif_type = HIF_TYPE_QCA9574; 1714 *target_type = TARGET_TYPE_QCA9574; 1715 hif_info(" *********** QCA9574 *************"); 1716 break; 1717 1718 default: 1719 hif_err("Unsupported device ID = 0x%x!", device_id); 1720 ret = -ENODEV; 1721 break; 1722 } 1723 1724 if (*target_type == TARGET_TYPE_UNKNOWN) { 1725 hif_err("Unsupported target_type!"); 1726 ret = -ENODEV; 1727 } 1728 end: 1729 return ret; 1730 } 1731 1732 /** 1733 * hif_get_bus_type() - return the bus type 1734 * 1735 * Return: enum qdf_bus_type 1736 */ 1737 enum qdf_bus_type hif_get_bus_type(struct hif_opaque_softc *hif_hdl) 1738 { 1739 struct hif_softc *scn = HIF_GET_SOFTC(hif_hdl); 1740 1741 return scn->bus_type; 1742 } 1743 1744 /** 1745 * Target info and ini parameters are global to the driver 1746 * Hence these structures are exposed to all the modules in 1747 * the driver and they don't need to maintains multiple copies 1748 * of the same info, instead get the handle from hif and 1749 * modify them in hif 1750 */ 1751 1752 /** 1753 * hif_get_ini_handle() - API to get hif_config_param handle 1754 * @hif_ctx: HIF Context 1755 * 1756 * Return: pointer to hif_config_info 1757 */ 1758 struct hif_config_info *hif_get_ini_handle(struct hif_opaque_softc *hif_ctx) 1759 { 1760 struct hif_softc *sc = HIF_GET_SOFTC(hif_ctx); 1761 1762 return &sc->hif_config; 1763 } 1764 1765 /** 1766 * hif_get_target_info_handle() - API to get hif_target_info handle 1767 * @hif_ctx: HIF context 1768 * 1769 * Return: Pointer to hif_target_info 1770 */ 1771 struct hif_target_info *hif_get_target_info_handle( 1772 struct hif_opaque_softc *hif_ctx) 1773 { 1774 struct hif_softc *sc = HIF_GET_SOFTC(hif_ctx); 1775 1776 return &sc->target_info; 1777 1778 } 1779 qdf_export_symbol(hif_get_target_info_handle); 1780 1781 #ifdef RECEIVE_OFFLOAD 1782 void hif_offld_flush_cb_register(struct hif_opaque_softc *scn, 1783 void (offld_flush_handler)(void *)) 1784 { 1785 if (hif_napi_enabled(scn, -1)) 1786 hif_napi_rx_offld_flush_cb_register(scn, offld_flush_handler); 1787 else 1788 hif_err("NAPI not enabled"); 1789 } 1790 qdf_export_symbol(hif_offld_flush_cb_register); 1791 1792 void hif_offld_flush_cb_deregister(struct hif_opaque_softc *scn) 1793 { 1794 if (hif_napi_enabled(scn, -1)) 1795 hif_napi_rx_offld_flush_cb_deregister(scn); 1796 else 1797 hif_err("NAPI not enabled"); 1798 } 1799 qdf_export_symbol(hif_offld_flush_cb_deregister); 1800 1801 int hif_get_rx_ctx_id(int ctx_id, struct hif_opaque_softc *hif_hdl) 1802 { 1803 if (hif_napi_enabled(hif_hdl, -1)) 1804 return NAPI_PIPE2ID(ctx_id); 1805 else 1806 return ctx_id; 1807 } 1808 #else /* RECEIVE_OFFLOAD */ 1809 int hif_get_rx_ctx_id(int ctx_id, struct hif_opaque_softc *hif_hdl) 1810 { 1811 return 0; 1812 } 1813 qdf_export_symbol(hif_get_rx_ctx_id); 1814 #endif /* RECEIVE_OFFLOAD */ 1815 1816 #if defined(FEATURE_LRO) 1817 1818 /** 1819 * hif_get_lro_info - Returns LRO instance for instance ID 1820 * @ctx_id: LRO instance ID 1821 * @hif_hdl: HIF Context 1822 * 1823 * Return: Pointer to LRO instance. 1824 */ 1825 void *hif_get_lro_info(int ctx_id, struct hif_opaque_softc *hif_hdl) 1826 { 1827 void *data; 1828 1829 if (hif_napi_enabled(hif_hdl, -1)) 1830 data = hif_napi_get_lro_info(hif_hdl, ctx_id); 1831 else 1832 data = hif_ce_get_lro_ctx(hif_hdl, ctx_id); 1833 1834 return data; 1835 } 1836 #endif 1837 1838 /** 1839 * hif_get_target_status - API to get target status 1840 * @hif_ctx: HIF Context 1841 * 1842 * Return: enum hif_target_status 1843 */ 1844 enum hif_target_status hif_get_target_status(struct hif_opaque_softc *hif_ctx) 1845 { 1846 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1847 1848 return scn->target_status; 1849 } 1850 qdf_export_symbol(hif_get_target_status); 1851 1852 /** 1853 * hif_set_target_status() - API to set target status 1854 * @hif_ctx: HIF Context 1855 * @status: Target Status 1856 * 1857 * Return: void 1858 */ 1859 void hif_set_target_status(struct hif_opaque_softc *hif_ctx, enum 1860 hif_target_status status) 1861 { 1862 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1863 1864 scn->target_status = status; 1865 } 1866 1867 /** 1868 * hif_init_ini_config() - API to initialize HIF configuration parameters 1869 * @hif_ctx: HIF Context 1870 * @cfg: HIF Configuration 1871 * 1872 * Return: void 1873 */ 1874 void hif_init_ini_config(struct hif_opaque_softc *hif_ctx, 1875 struct hif_config_info *cfg) 1876 { 1877 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1878 1879 qdf_mem_copy(&scn->hif_config, cfg, sizeof(struct hif_config_info)); 1880 } 1881 1882 /** 1883 * hif_get_conparam() - API to get driver mode in HIF 1884 * @scn: HIF Context 1885 * 1886 * Return: driver mode of operation 1887 */ 1888 uint32_t hif_get_conparam(struct hif_softc *scn) 1889 { 1890 if (!scn) 1891 return 0; 1892 1893 return scn->hif_con_param; 1894 } 1895 1896 /** 1897 * hif_get_callbacks_handle() - API to get callbacks Handle 1898 * @scn: HIF Context 1899 * 1900 * Return: pointer to HIF Callbacks 1901 */ 1902 struct hif_driver_state_callbacks *hif_get_callbacks_handle( 1903 struct hif_softc *scn) 1904 { 1905 return &scn->callbacks; 1906 } 1907 1908 /** 1909 * hif_is_driver_unloading() - API to query upper layers if driver is unloading 1910 * @scn: HIF Context 1911 * 1912 * Return: True/False 1913 */ 1914 bool hif_is_driver_unloading(struct hif_softc *scn) 1915 { 1916 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn); 1917 1918 if (cbk && cbk->is_driver_unloading) 1919 return cbk->is_driver_unloading(cbk->context); 1920 1921 return false; 1922 } 1923 1924 /** 1925 * hif_is_load_or_unload_in_progress() - API to query upper layers if 1926 * load/unload in progress 1927 * @scn: HIF Context 1928 * 1929 * Return: True/False 1930 */ 1931 bool hif_is_load_or_unload_in_progress(struct hif_softc *scn) 1932 { 1933 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn); 1934 1935 if (cbk && cbk->is_load_unload_in_progress) 1936 return cbk->is_load_unload_in_progress(cbk->context); 1937 1938 return false; 1939 } 1940 1941 /** 1942 * hif_is_recovery_in_progress() - API to query upper layers if recovery in 1943 * progress 1944 * @scn: HIF Context 1945 * 1946 * Return: True/False 1947 */ 1948 bool hif_is_recovery_in_progress(struct hif_softc *scn) 1949 { 1950 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn); 1951 1952 if (cbk && cbk->is_recovery_in_progress) 1953 return cbk->is_recovery_in_progress(cbk->context); 1954 1955 return false; 1956 } 1957 1958 #if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \ 1959 defined(HIF_IPCI) 1960 1961 /** 1962 * hif_update_pipe_callback() - API to register pipe specific callbacks 1963 * @osc: Opaque softc 1964 * @pipeid: pipe id 1965 * @callbacks: callbacks to register 1966 * 1967 * Return: void 1968 */ 1969 1970 void hif_update_pipe_callback(struct hif_opaque_softc *osc, 1971 u_int8_t pipeid, 1972 struct hif_msg_callbacks *callbacks) 1973 { 1974 struct hif_softc *scn = HIF_GET_SOFTC(osc); 1975 struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); 1976 struct HIF_CE_pipe_info *pipe_info; 1977 1978 QDF_BUG(pipeid < CE_COUNT_MAX); 1979 1980 hif_debug("pipeid: %d", pipeid); 1981 1982 pipe_info = &hif_state->pipe_info[pipeid]; 1983 1984 qdf_mem_copy(&pipe_info->pipe_callbacks, 1985 callbacks, sizeof(pipe_info->pipe_callbacks)); 1986 } 1987 qdf_export_symbol(hif_update_pipe_callback); 1988 1989 /** 1990 * hif_is_target_ready() - API to query if target is in ready state 1991 * progress 1992 * @scn: HIF Context 1993 * 1994 * Return: True/False 1995 */ 1996 bool hif_is_target_ready(struct hif_softc *scn) 1997 { 1998 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn); 1999 2000 if (cbk && cbk->is_target_ready) 2001 return cbk->is_target_ready(cbk->context); 2002 /* 2003 * if callback is not registered then there is no way to determine 2004 * if target is ready. In-such case return true to indicate that 2005 * target is ready. 2006 */ 2007 return true; 2008 } 2009 qdf_export_symbol(hif_is_target_ready); 2010 2011 int hif_get_bandwidth_level(struct hif_opaque_softc *hif_handle) 2012 { 2013 struct hif_softc *scn = HIF_GET_SOFTC(hif_handle); 2014 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn); 2015 2016 if (cbk && cbk->get_bandwidth_level) 2017 return cbk->get_bandwidth_level(cbk->context); 2018 2019 return 0; 2020 } 2021 2022 qdf_export_symbol(hif_get_bandwidth_level); 2023 2024 #ifdef DP_MEM_PRE_ALLOC 2025 void *hif_mem_alloc_consistent_unaligned(struct hif_softc *scn, 2026 qdf_size_t size, 2027 qdf_dma_addr_t *paddr, 2028 uint32_t ring_type, 2029 uint8_t *is_mem_prealloc) 2030 { 2031 void *vaddr = NULL; 2032 struct hif_driver_state_callbacks *cbk = 2033 hif_get_callbacks_handle(scn); 2034 2035 *is_mem_prealloc = false; 2036 if (cbk && cbk->prealloc_get_consistent_mem_unaligned) { 2037 vaddr = cbk->prealloc_get_consistent_mem_unaligned(size, 2038 paddr, 2039 ring_type); 2040 if (vaddr) { 2041 *is_mem_prealloc = true; 2042 goto end; 2043 } 2044 } 2045 2046 vaddr = qdf_mem_alloc_consistent(scn->qdf_dev, 2047 scn->qdf_dev->dev, 2048 size, 2049 paddr); 2050 end: 2051 dp_info("%s va_unaligned %pK pa_unaligned %pK size %d ring_type %d", 2052 *is_mem_prealloc ? "pre-alloc" : "dynamic-alloc", vaddr, 2053 (void *)*paddr, (int)size, ring_type); 2054 2055 return vaddr; 2056 } 2057 2058 void hif_mem_free_consistent_unaligned(struct hif_softc *scn, 2059 qdf_size_t size, 2060 void *vaddr, 2061 qdf_dma_addr_t paddr, 2062 qdf_dma_context_t memctx, 2063 uint8_t is_mem_prealloc) 2064 { 2065 struct hif_driver_state_callbacks *cbk = 2066 hif_get_callbacks_handle(scn); 2067 2068 if (is_mem_prealloc) { 2069 if (cbk && cbk->prealloc_put_consistent_mem_unaligned) { 2070 cbk->prealloc_put_consistent_mem_unaligned(vaddr); 2071 } else { 2072 dp_warn("dp_prealloc_put_consistent_unligned NULL"); 2073 QDF_BUG(0); 2074 } 2075 } else { 2076 qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev, 2077 size, vaddr, paddr, memctx); 2078 } 2079 } 2080 #endif 2081 2082 /** 2083 * hif_batch_send() - API to access hif specific function 2084 * ce_batch_send. 2085 * @osc: HIF Context 2086 * @msdu : list of msdus to be sent 2087 * @transfer_id : transfer id 2088 * @len : donwloaded length 2089 * 2090 * Return: list of msds not sent 2091 */ 2092 qdf_nbuf_t hif_batch_send(struct hif_opaque_softc *osc, qdf_nbuf_t msdu, 2093 uint32_t transfer_id, u_int32_t len, uint32_t sendhead) 2094 { 2095 void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE); 2096 2097 if (!ce_tx_hdl) 2098 return NULL; 2099 2100 return ce_batch_send((struct CE_handle *)ce_tx_hdl, msdu, transfer_id, 2101 len, sendhead); 2102 } 2103 qdf_export_symbol(hif_batch_send); 2104 2105 /** 2106 * hif_update_tx_ring() - API to access hif specific function 2107 * ce_update_tx_ring. 2108 * @osc: HIF Context 2109 * @num_htt_cmpls : number of htt compl received. 2110 * 2111 * Return: void 2112 */ 2113 void hif_update_tx_ring(struct hif_opaque_softc *osc, u_int32_t num_htt_cmpls) 2114 { 2115 void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE); 2116 2117 ce_update_tx_ring(ce_tx_hdl, num_htt_cmpls); 2118 } 2119 qdf_export_symbol(hif_update_tx_ring); 2120 2121 2122 /** 2123 * hif_send_single() - API to access hif specific function 2124 * ce_send_single. 2125 * @osc: HIF Context 2126 * @msdu : msdu to be sent 2127 * @transfer_id: transfer id 2128 * @len : downloaded length 2129 * 2130 * Return: msdu sent status 2131 */ 2132 QDF_STATUS hif_send_single(struct hif_opaque_softc *osc, qdf_nbuf_t msdu, 2133 uint32_t transfer_id, u_int32_t len) 2134 { 2135 void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE); 2136 2137 if (!ce_tx_hdl) 2138 return QDF_STATUS_E_NULL_VALUE; 2139 2140 return ce_send_single((struct CE_handle *)ce_tx_hdl, msdu, transfer_id, 2141 len); 2142 } 2143 qdf_export_symbol(hif_send_single); 2144 #endif 2145 2146 /** 2147 * hif_reg_write() - API to access hif specific function 2148 * hif_write32_mb. 2149 * @hif_ctx : HIF Context 2150 * @offset : offset on which value has to be written 2151 * @value : value to be written 2152 * 2153 * Return: None 2154 */ 2155 void hif_reg_write(struct hif_opaque_softc *hif_ctx, uint32_t offset, 2156 uint32_t value) 2157 { 2158 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 2159 2160 hif_write32_mb(scn, scn->mem + offset, value); 2161 2162 } 2163 qdf_export_symbol(hif_reg_write); 2164 2165 /** 2166 * hif_reg_read() - API to access hif specific function 2167 * hif_read32_mb. 2168 * @hif_ctx : HIF Context 2169 * @offset : offset from which value has to be read 2170 * 2171 * Return: Read value 2172 */ 2173 uint32_t hif_reg_read(struct hif_opaque_softc *hif_ctx, uint32_t offset) 2174 { 2175 2176 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 2177 2178 return hif_read32_mb(scn, scn->mem + offset); 2179 } 2180 qdf_export_symbol(hif_reg_read); 2181 2182 /** 2183 * hif_ramdump_handler(): generic ramdump handler 2184 * @scn: struct hif_opaque_softc 2185 * 2186 * Return: None 2187 */ 2188 void hif_ramdump_handler(struct hif_opaque_softc *scn) 2189 { 2190 if (hif_get_bus_type(scn) == QDF_BUS_TYPE_USB) 2191 hif_usb_ramdump_handler(scn); 2192 } 2193 2194 hif_pm_wake_irq_type hif_pm_get_wake_irq_type(struct hif_opaque_softc *hif_ctx) 2195 { 2196 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 2197 2198 return scn->wake_irq_type; 2199 } 2200 2201 irqreturn_t hif_wake_interrupt_handler(int irq, void *context) 2202 { 2203 struct hif_softc *scn = context; 2204 2205 hif_info("wake interrupt received on irq %d", irq); 2206 2207 hif_rtpm_set_monitor_wake_intr(0); 2208 hif_rtpm_request_resume(); 2209 2210 if (scn->initial_wakeup_cb) 2211 scn->initial_wakeup_cb(scn->initial_wakeup_priv); 2212 2213 if (hif_is_ut_suspended(scn)) 2214 hif_ut_fw_resume(scn); 2215 2216 qdf_pm_system_wakeup(); 2217 2218 return IRQ_HANDLED; 2219 } 2220 2221 void hif_set_initial_wakeup_cb(struct hif_opaque_softc *hif_ctx, 2222 void (*callback)(void *), 2223 void *priv) 2224 { 2225 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 2226 2227 scn->initial_wakeup_cb = callback; 2228 scn->initial_wakeup_priv = priv; 2229 } 2230 2231 void hif_set_ce_service_max_yield_time(struct hif_opaque_softc *hif, 2232 uint32_t ce_service_max_yield_time) 2233 { 2234 struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif); 2235 2236 hif_ctx->ce_service_max_yield_time = 2237 ce_service_max_yield_time * 1000; 2238 } 2239 2240 unsigned long long 2241 hif_get_ce_service_max_yield_time(struct hif_opaque_softc *hif) 2242 { 2243 struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif); 2244 2245 return hif_ctx->ce_service_max_yield_time; 2246 } 2247 2248 void hif_set_ce_service_max_rx_ind_flush(struct hif_opaque_softc *hif, 2249 uint8_t ce_service_max_rx_ind_flush) 2250 { 2251 struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif); 2252 2253 if (ce_service_max_rx_ind_flush == 0 || 2254 ce_service_max_rx_ind_flush > MSG_FLUSH_NUM) 2255 hif_ctx->ce_service_max_rx_ind_flush = MSG_FLUSH_NUM; 2256 else 2257 hif_ctx->ce_service_max_rx_ind_flush = 2258 ce_service_max_rx_ind_flush; 2259 } 2260 2261 #ifdef SYSTEM_PM_CHECK 2262 void __hif_system_pm_set_state(struct hif_opaque_softc *hif, 2263 enum hif_system_pm_state state) 2264 { 2265 struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif); 2266 2267 qdf_atomic_set(&hif_ctx->sys_pm_state, state); 2268 } 2269 2270 int32_t hif_system_pm_get_state(struct hif_opaque_softc *hif) 2271 { 2272 struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif); 2273 2274 return qdf_atomic_read(&hif_ctx->sys_pm_state); 2275 } 2276 2277 int hif_system_pm_state_check(struct hif_opaque_softc *hif) 2278 { 2279 struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif); 2280 int32_t sys_pm_state; 2281 2282 if (!hif_ctx) { 2283 hif_err("hif context is null"); 2284 return -EFAULT; 2285 } 2286 2287 sys_pm_state = qdf_atomic_read(&hif_ctx->sys_pm_state); 2288 if (sys_pm_state == HIF_SYSTEM_PM_STATE_BUS_SUSPENDING || 2289 sys_pm_state == HIF_SYSTEM_PM_STATE_BUS_SUSPENDED) { 2290 hif_info("Triggering system wakeup"); 2291 qdf_pm_system_wakeup(); 2292 return -EAGAIN; 2293 } 2294 2295 return 0; 2296 } 2297 #endif 2298