1 /* 2 * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "targcfg.h" 20 #include "qdf_lock.h" 21 #include "qdf_status.h" 22 #include "qdf_status.h" 23 #include <qdf_atomic.h> /* qdf_atomic_read */ 24 #include <targaddrs.h> 25 #include "hif_io32.h" 26 #include <hif.h> 27 #include <target_type.h> 28 #include "regtable.h" 29 #define ATH_MODULE_NAME hif 30 #include <a_debug.h> 31 #include "hif_main.h" 32 #include "hif_hw_version.h" 33 #if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) 34 #include "ce_tasklet.h" 35 #include "ce_api.h" 36 #endif 37 #include "qdf_trace.h" 38 #include "qdf_status.h" 39 #include "hif_debug.h" 40 #include "mp_dev.h" 41 #if defined(QCA_WIFI_QCA8074) || defined(QCA_WIFI_QCA6018) 42 #include "hal_api.h" 43 #endif 44 #include "hif_napi.h" 45 #include "hif_unit_test_suspend_i.h" 46 #include "qdf_module.h" 47 48 void hif_dump(struct hif_opaque_softc *hif_ctx, uint8_t cmd_id, bool start) 49 { 50 hif_trigger_dump(hif_ctx, cmd_id, start); 51 } 52 53 /** 54 * hif_get_target_id(): hif_get_target_id 55 * 56 * Return the virtual memory base address to the caller 57 * 58 * @scn: hif_softc 59 * 60 * Return: A_target_id_t 61 */ 62 A_target_id_t hif_get_target_id(struct hif_softc *scn) 63 { 64 return scn->mem; 65 } 66 67 /** 68 * hif_get_targetdef(): hif_get_targetdef 69 * @scn: scn 70 * 71 * Return: void * 72 */ 73 void *hif_get_targetdef(struct hif_opaque_softc *hif_ctx) 74 { 75 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 76 77 return scn->targetdef; 78 } 79 80 /** 81 * hif_vote_link_down(): unvote for link up 82 * 83 * Call hif_vote_link_down to release a previous request made using 84 * hif_vote_link_up. A hif_vote_link_down call should only be made 85 * after a corresponding hif_vote_link_up, otherwise you could be 86 * negating a vote from another source. When no votes are present 87 * hif will not guarantee the linkstate after hif_bus_suspend. 88 * 89 * SYNCHRONIZE WITH hif_vote_link_up by only calling in MC thread 90 * and initialization deinitialization sequencences. 91 * 92 * Return: n/a 93 */ 94 void hif_vote_link_down(struct hif_opaque_softc *hif_ctx) 95 { 96 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 97 98 QDF_BUG(scn); 99 scn->linkstate_vote--; 100 if (scn->linkstate_vote == 0) 101 hif_bus_prevent_linkdown(scn, false); 102 } 103 104 /** 105 * hif_vote_link_up(): vote to prevent bus from suspending 106 * 107 * Makes hif guarantee that fw can message the host normally 108 * durring suspend. 109 * 110 * SYNCHRONIZE WITH hif_vote_link_up by only calling in MC thread 111 * and initialization deinitialization sequencences. 112 * 113 * Return: n/a 114 */ 115 void hif_vote_link_up(struct hif_opaque_softc *hif_ctx) 116 { 117 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 118 119 QDF_BUG(scn); 120 scn->linkstate_vote++; 121 if (scn->linkstate_vote == 1) 122 hif_bus_prevent_linkdown(scn, true); 123 } 124 125 /** 126 * hif_can_suspend_link(): query if hif is permitted to suspend the link 127 * 128 * Hif will ensure that the link won't be suspended if the upperlayers 129 * don't want it to. 130 * 131 * SYNCHRONIZATION: MC thread is stopped before bus suspend thus 132 * we don't need extra locking to ensure votes dont change while 133 * we are in the process of suspending or resuming. 134 * 135 * Return: false if hif will guarantee link up durring suspend. 136 */ 137 bool hif_can_suspend_link(struct hif_opaque_softc *hif_ctx) 138 { 139 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 140 141 QDF_BUG(scn); 142 return scn->linkstate_vote == 0; 143 } 144 145 /** 146 * hif_hia_item_address(): hif_hia_item_address 147 * @target_type: target_type 148 * @item_offset: item_offset 149 * 150 * Return: n/a 151 */ 152 uint32_t hif_hia_item_address(uint32_t target_type, uint32_t item_offset) 153 { 154 switch (target_type) { 155 case TARGET_TYPE_AR6002: 156 return AR6002_HOST_INTEREST_ADDRESS + item_offset; 157 case TARGET_TYPE_AR6003: 158 return AR6003_HOST_INTEREST_ADDRESS + item_offset; 159 case TARGET_TYPE_AR6004: 160 return AR6004_HOST_INTEREST_ADDRESS + item_offset; 161 case TARGET_TYPE_AR6006: 162 return AR6006_HOST_INTEREST_ADDRESS + item_offset; 163 case TARGET_TYPE_AR9888: 164 return AR9888_HOST_INTEREST_ADDRESS + item_offset; 165 case TARGET_TYPE_AR6320: 166 case TARGET_TYPE_AR6320V2: 167 return AR6320_HOST_INTEREST_ADDRESS + item_offset; 168 case TARGET_TYPE_ADRASTEA: 169 /* ADRASTEA doesn't have a host interest address */ 170 ASSERT(0); 171 return 0; 172 case TARGET_TYPE_AR900B: 173 return AR900B_HOST_INTEREST_ADDRESS + item_offset; 174 case TARGET_TYPE_QCA9984: 175 return QCA9984_HOST_INTEREST_ADDRESS + item_offset; 176 case TARGET_TYPE_QCA9888: 177 return QCA9888_HOST_INTEREST_ADDRESS + item_offset; 178 case TARGET_TYPE_IPQ4019: 179 return IPQ4019_HOST_INTEREST_ADDRESS + item_offset; 180 181 default: 182 ASSERT(0); 183 return 0; 184 } 185 } 186 187 /** 188 * hif_max_num_receives_reached() - check max receive is reached 189 * @scn: HIF Context 190 * @count: unsigned int. 191 * 192 * Output check status as bool 193 * 194 * Return: bool 195 */ 196 bool hif_max_num_receives_reached(struct hif_softc *scn, unsigned int count) 197 { 198 if (QDF_IS_EPPING_ENABLED(hif_get_conparam(scn))) 199 return count > 120; 200 else 201 return count > MAX_NUM_OF_RECEIVES; 202 } 203 204 /** 205 * init_buffer_count() - initial buffer count 206 * @maxSize: qdf_size_t 207 * 208 * routine to modify the initial buffer count to be allocated on an os 209 * platform basis. Platform owner will need to modify this as needed 210 * 211 * Return: qdf_size_t 212 */ 213 qdf_size_t init_buffer_count(qdf_size_t maxSize) 214 { 215 return maxSize; 216 } 217 218 /** 219 * hif_save_htc_htt_config_endpoint() - save htt_tx_endpoint 220 * @hif_ctx: hif context 221 * @htc_htt_tx_endpoint: htt_tx_endpoint 222 * 223 * Return: void 224 */ 225 void hif_save_htc_htt_config_endpoint(struct hif_opaque_softc *hif_ctx, 226 int htc_htt_tx_endpoint) 227 { 228 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 229 230 if (!scn) { 231 HIF_ERROR("%s: error: scn or scn->hif_sc is NULL!", 232 __func__); 233 return; 234 } 235 236 scn->htc_htt_tx_endpoint = htc_htt_tx_endpoint; 237 } 238 qdf_export_symbol(hif_save_htc_htt_config_endpoint); 239 240 static const struct qwlan_hw qwlan_hw_list[] = { 241 { 242 .id = AR6320_REV1_VERSION, 243 .subid = 0, 244 .name = "QCA6174_REV1", 245 }, 246 { 247 .id = AR6320_REV1_1_VERSION, 248 .subid = 0x1, 249 .name = "QCA6174_REV1_1", 250 }, 251 { 252 .id = AR6320_REV1_3_VERSION, 253 .subid = 0x2, 254 .name = "QCA6174_REV1_3", 255 }, 256 { 257 .id = AR6320_REV2_1_VERSION, 258 .subid = 0x4, 259 .name = "QCA6174_REV2_1", 260 }, 261 { 262 .id = AR6320_REV2_1_VERSION, 263 .subid = 0x5, 264 .name = "QCA6174_REV2_2", 265 }, 266 { 267 .id = AR6320_REV3_VERSION, 268 .subid = 0x6, 269 .name = "QCA6174_REV2.3", 270 }, 271 { 272 .id = AR6320_REV3_VERSION, 273 .subid = 0x8, 274 .name = "QCA6174_REV3", 275 }, 276 { 277 .id = AR6320_REV3_VERSION, 278 .subid = 0x9, 279 .name = "QCA6174_REV3_1", 280 }, 281 { 282 .id = AR6320_REV3_2_VERSION, 283 .subid = 0xA, 284 .name = "AR6320_REV3_2_VERSION", 285 }, 286 { 287 .id = WCN3990_v1, 288 .subid = 0x0, 289 .name = "WCN3990_V1", 290 }, 291 { 292 .id = WCN3990_v2, 293 .subid = 0x0, 294 .name = "WCN3990_V2", 295 }, 296 { 297 .id = WCN3990_v2_1, 298 .subid = 0x0, 299 .name = "WCN3990_V2.1", 300 }, 301 { 302 .id = WCN3998, 303 .subid = 0x0, 304 .name = "WCN3998", 305 }, 306 { 307 .id = QCA9379_REV1_VERSION, 308 .subid = 0xC, 309 .name = "QCA9379_REV1", 310 }, 311 { 312 .id = QCA9379_REV1_VERSION, 313 .subid = 0xD, 314 .name = "QCA9379_REV1_1", 315 } 316 }; 317 318 /** 319 * hif_get_hw_name(): get a human readable name for the hardware 320 * @info: Target Info 321 * 322 * Return: human readable name for the underlying wifi hardware. 323 */ 324 static const char *hif_get_hw_name(struct hif_target_info *info) 325 { 326 int i; 327 328 if (info->hw_name) 329 return info->hw_name; 330 331 for (i = 0; i < ARRAY_SIZE(qwlan_hw_list); i++) { 332 if (info->target_version == qwlan_hw_list[i].id && 333 info->target_revision == qwlan_hw_list[i].subid) { 334 return qwlan_hw_list[i].name; 335 } 336 } 337 338 info->hw_name = qdf_mem_malloc(64); 339 if (!info->hw_name) 340 return "Unknown Device (nomem)"; 341 342 i = qdf_snprint(info->hw_name, 64, "HW_VERSION=%x.", 343 info->target_version); 344 if (i < 0) 345 return "Unknown Device (snprintf failure)"; 346 else 347 return info->hw_name; 348 } 349 350 /** 351 * hif_get_hw_info(): hif_get_hw_info 352 * @scn: scn 353 * @version: version 354 * @revision: revision 355 * 356 * Return: n/a 357 */ 358 void hif_get_hw_info(struct hif_opaque_softc *scn, u32 *version, u32 *revision, 359 const char **target_name) 360 { 361 struct hif_target_info *info = hif_get_target_info_handle(scn); 362 struct hif_softc *sc = HIF_GET_SOFTC(scn); 363 364 if (sc->bus_type == QDF_BUS_TYPE_USB) 365 hif_usb_get_hw_info(sc); 366 367 *version = info->target_version; 368 *revision = info->target_revision; 369 *target_name = hif_get_hw_name(info); 370 } 371 372 /** 373 * hif_get_dev_ba(): API to get device base address. 374 * @scn: scn 375 * @version: version 376 * @revision: revision 377 * 378 * Return: n/a 379 */ 380 void *hif_get_dev_ba(struct hif_opaque_softc *hif_handle) 381 { 382 struct hif_softc *scn = (struct hif_softc *)hif_handle; 383 384 return scn->mem; 385 } 386 qdf_export_symbol(hif_get_dev_ba); 387 /** 388 * hif_open(): hif_open 389 * @qdf_ctx: QDF Context 390 * @mode: Driver Mode 391 * @bus_type: Bus Type 392 * @cbk: CDS Callbacks 393 * 394 * API to open HIF Context 395 * 396 * Return: HIF Opaque Pointer 397 */ 398 struct hif_opaque_softc *hif_open(qdf_device_t qdf_ctx, uint32_t mode, 399 enum qdf_bus_type bus_type, 400 struct hif_driver_state_callbacks *cbk) 401 { 402 struct hif_softc *scn; 403 QDF_STATUS status = QDF_STATUS_SUCCESS; 404 int bus_context_size = hif_bus_get_context_size(bus_type); 405 406 if (bus_context_size == 0) { 407 HIF_ERROR("%s: context size 0 not allowed", __func__); 408 return NULL; 409 } 410 411 scn = (struct hif_softc *)qdf_mem_malloc(bus_context_size); 412 if (!scn) { 413 HIF_ERROR("%s: cannot alloc memory for HIF context of size:%d", 414 __func__, bus_context_size); 415 return GET_HIF_OPAQUE_HDL(scn); 416 } 417 418 scn->qdf_dev = qdf_ctx; 419 scn->hif_con_param = mode; 420 qdf_atomic_init(&scn->active_tasklet_cnt); 421 qdf_atomic_init(&scn->active_grp_tasklet_cnt); 422 qdf_atomic_init(&scn->link_suspended); 423 qdf_atomic_init(&scn->tasklet_from_intr); 424 qdf_mem_copy(&scn->callbacks, cbk, 425 sizeof(struct hif_driver_state_callbacks)); 426 scn->bus_type = bus_type; 427 status = hif_bus_open(scn, bus_type); 428 if (status != QDF_STATUS_SUCCESS) { 429 HIF_ERROR("%s: hif_bus_open error = %d, bus_type = %d", 430 __func__, status, bus_type); 431 qdf_mem_free(scn); 432 scn = NULL; 433 } 434 435 return GET_HIF_OPAQUE_HDL(scn); 436 } 437 438 #ifdef ADRASTEA_RRI_ON_DDR 439 /** 440 * hif_uninit_rri_on_ddr(): free consistent memory allocated for rri 441 * @scn: hif context 442 * 443 * Return: none 444 */ 445 void hif_uninit_rri_on_ddr(struct hif_softc *scn) 446 { 447 if (scn->vaddr_rri_on_ddr) 448 qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev, 449 (CE_COUNT * sizeof(uint32_t)), 450 scn->vaddr_rri_on_ddr, 451 scn->paddr_rri_on_ddr, 0); 452 scn->vaddr_rri_on_ddr = NULL; 453 } 454 #endif 455 456 /** 457 * hif_close(): hif_close 458 * @hif_ctx: hif_ctx 459 * 460 * Return: n/a 461 */ 462 void hif_close(struct hif_opaque_softc *hif_ctx) 463 { 464 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 465 466 if (!scn) { 467 HIF_ERROR("%s: hif_opaque_softc is NULL", __func__); 468 return; 469 } 470 471 if (scn->athdiag_procfs_inited) { 472 athdiag_procfs_remove(); 473 scn->athdiag_procfs_inited = false; 474 } 475 476 if (scn->target_info.hw_name) { 477 char *hw_name = scn->target_info.hw_name; 478 479 scn->target_info.hw_name = "ErrUnloading"; 480 qdf_mem_free(hw_name); 481 } 482 483 hif_uninit_rri_on_ddr(scn); 484 485 hif_bus_close(scn); 486 qdf_mem_free(scn); 487 } 488 489 #if defined(QCA_WIFI_QCA8074) || defined(QCA_WIFI_QCA6018) || \ 490 defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390) 491 static QDF_STATUS hif_hal_attach(struct hif_softc *scn) 492 { 493 if (ce_srng_based(scn)) { 494 scn->hal_soc = hal_attach(scn, scn->qdf_dev); 495 if (!scn->hal_soc) 496 return QDF_STATUS_E_FAILURE; 497 } 498 499 return QDF_STATUS_SUCCESS; 500 } 501 502 static QDF_STATUS hif_hal_detach(struct hif_softc *scn) 503 { 504 if (ce_srng_based(scn)) { 505 hal_detach(scn->hal_soc); 506 scn->hal_soc = NULL; 507 } 508 509 return QDF_STATUS_SUCCESS; 510 } 511 #else 512 static QDF_STATUS hif_hal_attach(struct hif_softc *scn) 513 { 514 return QDF_STATUS_SUCCESS; 515 } 516 517 static QDF_STATUS hif_hal_detach(struct hif_softc *scn) 518 { 519 return QDF_STATUS_SUCCESS; 520 } 521 #endif 522 523 /** 524 * hif_enable(): hif_enable 525 * @hif_ctx: hif_ctx 526 * @dev: dev 527 * @bdev: bus dev 528 * @bid: bus ID 529 * @bus_type: bus type 530 * @type: enable type 531 * 532 * Return: QDF_STATUS 533 */ 534 QDF_STATUS hif_enable(struct hif_opaque_softc *hif_ctx, struct device *dev, 535 void *bdev, 536 const struct hif_bus_id *bid, 537 enum qdf_bus_type bus_type, 538 enum hif_enable_type type) 539 { 540 QDF_STATUS status; 541 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 542 543 if (!scn) { 544 HIF_ERROR("%s: hif_ctx = NULL", __func__); 545 return QDF_STATUS_E_NULL_VALUE; 546 } 547 548 status = hif_enable_bus(scn, dev, bdev, bid, type); 549 if (status != QDF_STATUS_SUCCESS) { 550 HIF_ERROR("%s: hif_enable_bus error = %d", 551 __func__, status); 552 return status; 553 } 554 555 status = hif_hal_attach(scn); 556 if (status != QDF_STATUS_SUCCESS) { 557 HIF_ERROR("%s: hal attach failed", __func__); 558 goto disable_bus; 559 } 560 561 if (hif_bus_configure(scn)) { 562 HIF_ERROR("%s: Target probe failed.", __func__); 563 status = QDF_STATUS_E_FAILURE; 564 goto hal_detach; 565 } 566 567 hif_ut_suspend_init(scn); 568 569 /* 570 * Flag to avoid potential unallocated memory access from MSI 571 * interrupt handler which could get scheduled as soon as MSI 572 * is enabled, i.e to take care of the race due to the order 573 * in where MSI is enabled before the memory, that will be 574 * in interrupt handlers, is allocated. 575 */ 576 577 scn->hif_init_done = true; 578 579 HIF_DBG("%s: OK", __func__); 580 581 return QDF_STATUS_SUCCESS; 582 583 hal_detach: 584 hif_hal_detach(scn); 585 disable_bus: 586 hif_disable_bus(scn); 587 return status; 588 } 589 590 void hif_disable(struct hif_opaque_softc *hif_ctx, enum hif_disable_type type) 591 { 592 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 593 594 if (!scn) 595 return; 596 597 hif_nointrs(scn); 598 if (scn->hif_init_done == false) 599 hif_shutdown_device(hif_ctx); 600 else 601 hif_stop(hif_ctx); 602 603 hif_hal_detach(scn); 604 605 hif_disable_bus(scn); 606 607 hif_wlan_disable(scn); 608 609 scn->notice_send = false; 610 611 HIF_DBG("%s: X", __func__); 612 } 613 614 void hif_display_stats(struct hif_opaque_softc *hif_ctx) 615 { 616 hif_display_bus_stats(hif_ctx); 617 } 618 619 void hif_clear_stats(struct hif_opaque_softc *hif_ctx) 620 { 621 hif_clear_bus_stats(hif_ctx); 622 } 623 624 /** 625 * hif_crash_shutdown_dump_bus_register() - dump bus registers 626 * @hif_ctx: hif_ctx 627 * 628 * Return: n/a 629 */ 630 #if defined(TARGET_RAMDUMP_AFTER_KERNEL_PANIC) \ 631 && defined(DEBUG) 632 633 static void hif_crash_shutdown_dump_bus_register(void *hif_ctx) 634 { 635 struct hif_opaque_softc *scn = hif_ctx; 636 637 if (hif_check_soc_status(scn)) 638 return; 639 640 if (hif_dump_registers(scn)) 641 HIF_ERROR("Failed to dump bus registers!"); 642 } 643 644 /** 645 * hif_crash_shutdown(): hif_crash_shutdown 646 * 647 * This function is called by the platform driver to dump CE registers 648 * 649 * @hif_ctx: hif_ctx 650 * 651 * Return: n/a 652 */ 653 void hif_crash_shutdown(struct hif_opaque_softc *hif_ctx) 654 { 655 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 656 657 if (!hif_ctx) 658 return; 659 660 if (scn->bus_type == QDF_BUS_TYPE_SNOC) { 661 HIF_INFO_MED("%s: RAM dump disabled for bustype %d", 662 __func__, scn->bus_type); 663 return; 664 } 665 666 if (TARGET_STATUS_RESET == scn->target_status) { 667 HIF_INFO_MED("%s: Target is already asserted, ignore!", 668 __func__); 669 return; 670 } 671 672 if (hif_is_load_or_unload_in_progress(scn)) { 673 HIF_ERROR("%s: Load/unload is in progress, ignore!", __func__); 674 return; 675 } 676 677 hif_crash_shutdown_dump_bus_register(hif_ctx); 678 679 if (ol_copy_ramdump(hif_ctx)) 680 goto out; 681 682 HIF_INFO_MED("%s: RAM dump collecting completed!", __func__); 683 684 out: 685 return; 686 } 687 #else 688 void hif_crash_shutdown(struct hif_opaque_softc *hif_ctx) 689 { 690 HIF_INFO_MED("%s: Collecting target RAM dump disabled", 691 __func__); 692 } 693 #endif /* TARGET_RAMDUMP_AFTER_KERNEL_PANIC */ 694 695 #ifdef QCA_WIFI_3_0 696 /** 697 * hif_check_fw_reg(): hif_check_fw_reg 698 * @scn: scn 699 * @state: 700 * 701 * Return: int 702 */ 703 int hif_check_fw_reg(struct hif_opaque_softc *scn) 704 { 705 return 0; 706 } 707 #endif 708 709 /** 710 * hif_read_phy_mem_base(): hif_read_phy_mem_base 711 * @scn: scn 712 * @phy_mem_base: physical mem base 713 * 714 * Return: n/a 715 */ 716 void hif_read_phy_mem_base(struct hif_softc *scn, qdf_dma_addr_t *phy_mem_base) 717 { 718 *phy_mem_base = scn->mem_pa; 719 } 720 qdf_export_symbol(hif_read_phy_mem_base); 721 722 /** 723 * hif_get_device_type(): hif_get_device_type 724 * @device_id: device_id 725 * @revision_id: revision_id 726 * @hif_type: returned hif_type 727 * @target_type: returned target_type 728 * 729 * Return: int 730 */ 731 int hif_get_device_type(uint32_t device_id, 732 uint32_t revision_id, 733 uint32_t *hif_type, uint32_t *target_type) 734 { 735 int ret = 0; 736 737 switch (device_id) { 738 case ADRASTEA_DEVICE_ID_P2_E12: 739 740 *hif_type = HIF_TYPE_ADRASTEA; 741 *target_type = TARGET_TYPE_ADRASTEA; 742 break; 743 744 case AR9888_DEVICE_ID: 745 *hif_type = HIF_TYPE_AR9888; 746 *target_type = TARGET_TYPE_AR9888; 747 break; 748 749 case AR6320_DEVICE_ID: 750 switch (revision_id) { 751 case AR6320_FW_1_1: 752 case AR6320_FW_1_3: 753 *hif_type = HIF_TYPE_AR6320; 754 *target_type = TARGET_TYPE_AR6320; 755 break; 756 757 case AR6320_FW_2_0: 758 case AR6320_FW_3_0: 759 case AR6320_FW_3_2: 760 *hif_type = HIF_TYPE_AR6320V2; 761 *target_type = TARGET_TYPE_AR6320V2; 762 break; 763 764 default: 765 HIF_ERROR("%s: error - dev_id = 0x%x, rev_id = 0x%x", 766 __func__, device_id, revision_id); 767 ret = -ENODEV; 768 goto end; 769 } 770 break; 771 772 case AR9887_DEVICE_ID: 773 *hif_type = HIF_TYPE_AR9888; 774 *target_type = TARGET_TYPE_AR9888; 775 HIF_INFO(" *********** AR9887 **************"); 776 break; 777 778 case QCA9984_DEVICE_ID: 779 *hif_type = HIF_TYPE_QCA9984; 780 *target_type = TARGET_TYPE_QCA9984; 781 HIF_INFO(" *********** QCA9984 *************"); 782 break; 783 784 case QCA9888_DEVICE_ID: 785 *hif_type = HIF_TYPE_QCA9888; 786 *target_type = TARGET_TYPE_QCA9888; 787 HIF_INFO(" *********** QCA9888 *************"); 788 break; 789 790 case AR900B_DEVICE_ID: 791 *hif_type = HIF_TYPE_AR900B; 792 *target_type = TARGET_TYPE_AR900B; 793 HIF_INFO(" *********** AR900B *************"); 794 break; 795 796 case IPQ4019_DEVICE_ID: 797 *hif_type = HIF_TYPE_IPQ4019; 798 *target_type = TARGET_TYPE_IPQ4019; 799 HIF_INFO(" *********** IPQ4019 *************"); 800 break; 801 802 case QCA8074_DEVICE_ID: 803 *hif_type = HIF_TYPE_QCA8074; 804 *target_type = TARGET_TYPE_QCA8074; 805 HIF_INFO(" *********** QCA8074 *************\n"); 806 break; 807 808 case QCA6290_EMULATION_DEVICE_ID: 809 case QCA6290_DEVICE_ID: 810 *hif_type = HIF_TYPE_QCA6290; 811 *target_type = TARGET_TYPE_QCA6290; 812 HIF_INFO(" *********** QCA6290EMU *************\n"); 813 break; 814 815 case QCN7605_DEVICE_ID: 816 case QCN7605_COMPOSITE: 817 case QCN7605_STANDALONE: 818 *hif_type = HIF_TYPE_QCN7605; 819 *target_type = TARGET_TYPE_QCN7605; 820 HIF_INFO(" *********** QCN7605 *************\n"); 821 break; 822 823 case QCA6390_DEVICE_ID: 824 case QCA6390_EMULATION_DEVICE_ID: 825 *hif_type = HIF_TYPE_QCA6390; 826 *target_type = TARGET_TYPE_QCA6390; 827 HIF_INFO(" *********** QCA6390 *************\n"); 828 break; 829 830 case QCA8074V2_DEVICE_ID: 831 *hif_type = HIF_TYPE_QCA8074V2; 832 *target_type = TARGET_TYPE_QCA8074V2; 833 HIF_INFO(" *********** QCA8074V2 *************\n"); 834 break; 835 836 case QCA6018_DEVICE_ID: 837 case RUMIM2M_DEVICE_ID_NODE0: 838 case RUMIM2M_DEVICE_ID_NODE1: 839 case RUMIM2M_DEVICE_ID_NODE2: 840 case RUMIM2M_DEVICE_ID_NODE3: 841 case RUMIM2M_DEVICE_ID_NODE4: 842 case RUMIM2M_DEVICE_ID_NODE5: 843 *hif_type = HIF_TYPE_QCA6018; 844 *target_type = TARGET_TYPE_QCA6018; 845 HIF_INFO(" *********** QCA6018 *************\n"); 846 break; 847 848 default: 849 HIF_ERROR("%s: Unsupported device ID = 0x%x!", 850 __func__, device_id); 851 ret = -ENODEV; 852 break; 853 } 854 855 if (*target_type == TARGET_TYPE_UNKNOWN) { 856 HIF_ERROR("%s: Unsupported target_type!", __func__); 857 ret = -ENODEV; 858 } 859 end: 860 return ret; 861 } 862 863 /** 864 * hif_get_bus_type() - return the bus type 865 * 866 * Return: enum qdf_bus_type 867 */ 868 enum qdf_bus_type hif_get_bus_type(struct hif_opaque_softc *hif_hdl) 869 { 870 struct hif_softc *scn = HIF_GET_SOFTC(hif_hdl); 871 872 return scn->bus_type; 873 } 874 875 /** 876 * Target info and ini parameters are global to the driver 877 * Hence these structures are exposed to all the modules in 878 * the driver and they don't need to maintains multiple copies 879 * of the same info, instead get the handle from hif and 880 * modify them in hif 881 */ 882 883 /** 884 * hif_get_ini_handle() - API to get hif_config_param handle 885 * @hif_ctx: HIF Context 886 * 887 * Return: pointer to hif_config_info 888 */ 889 struct hif_config_info *hif_get_ini_handle(struct hif_opaque_softc *hif_ctx) 890 { 891 struct hif_softc *sc = HIF_GET_SOFTC(hif_ctx); 892 893 return &sc->hif_config; 894 } 895 896 /** 897 * hif_get_target_info_handle() - API to get hif_target_info handle 898 * @hif_ctx: HIF context 899 * 900 * Return: Pointer to hif_target_info 901 */ 902 struct hif_target_info *hif_get_target_info_handle( 903 struct hif_opaque_softc *hif_ctx) 904 { 905 struct hif_softc *sc = HIF_GET_SOFTC(hif_ctx); 906 907 return &sc->target_info; 908 909 } 910 qdf_export_symbol(hif_get_target_info_handle); 911 912 #ifdef RECEIVE_OFFLOAD 913 void hif_offld_flush_cb_register(struct hif_opaque_softc *scn, 914 void (offld_flush_handler)(void *)) 915 { 916 if (hif_napi_enabled(scn, -1)) 917 hif_napi_rx_offld_flush_cb_register(scn, offld_flush_handler); 918 else 919 HIF_ERROR("NAPI not enabled\n"); 920 } 921 qdf_export_symbol(hif_offld_flush_cb_register); 922 923 void hif_offld_flush_cb_deregister(struct hif_opaque_softc *scn) 924 { 925 if (hif_napi_enabled(scn, -1)) 926 hif_napi_rx_offld_flush_cb_deregister(scn); 927 else 928 HIF_ERROR("NAPI not enabled\n"); 929 } 930 qdf_export_symbol(hif_offld_flush_cb_deregister); 931 932 int hif_get_rx_ctx_id(int ctx_id, struct hif_opaque_softc *hif_hdl) 933 { 934 if (hif_napi_enabled(hif_hdl, -1)) 935 return NAPI_PIPE2ID(ctx_id); 936 else 937 return ctx_id; 938 } 939 #else /* RECEIVE_OFFLOAD */ 940 int hif_get_rx_ctx_id(int ctx_id, struct hif_opaque_softc *hif_hdl) 941 { 942 return 0; 943 } 944 qdf_export_symbol(hif_get_rx_ctx_id); 945 #endif /* RECEIVE_OFFLOAD */ 946 947 #if defined(FEATURE_LRO) 948 949 /** 950 * hif_get_lro_info - Returns LRO instance for instance ID 951 * @ctx_id: LRO instance ID 952 * @hif_hdl: HIF Context 953 * 954 * Return: Pointer to LRO instance. 955 */ 956 void *hif_get_lro_info(int ctx_id, struct hif_opaque_softc *hif_hdl) 957 { 958 void *data; 959 960 if (hif_napi_enabled(hif_hdl, -1)) 961 data = hif_napi_get_lro_info(hif_hdl, ctx_id); 962 else 963 data = hif_ce_get_lro_ctx(hif_hdl, ctx_id); 964 965 return data; 966 } 967 #endif 968 969 /** 970 * hif_get_target_status - API to get target status 971 * @hif_ctx: HIF Context 972 * 973 * Return: enum hif_target_status 974 */ 975 enum hif_target_status hif_get_target_status(struct hif_opaque_softc *hif_ctx) 976 { 977 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 978 979 return scn->target_status; 980 } 981 qdf_export_symbol(hif_get_target_status); 982 983 /** 984 * hif_set_target_status() - API to set target status 985 * @hif_ctx: HIF Context 986 * @status: Target Status 987 * 988 * Return: void 989 */ 990 void hif_set_target_status(struct hif_opaque_softc *hif_ctx, enum 991 hif_target_status status) 992 { 993 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 994 995 scn->target_status = status; 996 } 997 998 /** 999 * hif_init_ini_config() - API to initialize HIF configuration parameters 1000 * @hif_ctx: HIF Context 1001 * @cfg: HIF Configuration 1002 * 1003 * Return: void 1004 */ 1005 void hif_init_ini_config(struct hif_opaque_softc *hif_ctx, 1006 struct hif_config_info *cfg) 1007 { 1008 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1009 1010 qdf_mem_copy(&scn->hif_config, cfg, sizeof(struct hif_config_info)); 1011 } 1012 1013 /** 1014 * hif_get_conparam() - API to get driver mode in HIF 1015 * @scn: HIF Context 1016 * 1017 * Return: driver mode of operation 1018 */ 1019 uint32_t hif_get_conparam(struct hif_softc *scn) 1020 { 1021 if (!scn) 1022 return 0; 1023 1024 return scn->hif_con_param; 1025 } 1026 1027 /** 1028 * hif_get_callbacks_handle() - API to get callbacks Handle 1029 * @scn: HIF Context 1030 * 1031 * Return: pointer to HIF Callbacks 1032 */ 1033 struct hif_driver_state_callbacks *hif_get_callbacks_handle( 1034 struct hif_softc *scn) 1035 { 1036 return &scn->callbacks; 1037 } 1038 1039 /** 1040 * hif_is_driver_unloading() - API to query upper layers if driver is unloading 1041 * @scn: HIF Context 1042 * 1043 * Return: True/False 1044 */ 1045 bool hif_is_driver_unloading(struct hif_softc *scn) 1046 { 1047 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn); 1048 1049 if (cbk && cbk->is_driver_unloading) 1050 return cbk->is_driver_unloading(cbk->context); 1051 1052 return false; 1053 } 1054 1055 /** 1056 * hif_is_load_or_unload_in_progress() - API to query upper layers if 1057 * load/unload in progress 1058 * @scn: HIF Context 1059 * 1060 * Return: True/False 1061 */ 1062 bool hif_is_load_or_unload_in_progress(struct hif_softc *scn) 1063 { 1064 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn); 1065 1066 if (cbk && cbk->is_load_unload_in_progress) 1067 return cbk->is_load_unload_in_progress(cbk->context); 1068 1069 return false; 1070 } 1071 1072 /** 1073 * hif_is_recovery_in_progress() - API to query upper layers if recovery in 1074 * progress 1075 * @scn: HIF Context 1076 * 1077 * Return: True/False 1078 */ 1079 bool hif_is_recovery_in_progress(struct hif_softc *scn) 1080 { 1081 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn); 1082 1083 if (cbk && cbk->is_recovery_in_progress) 1084 return cbk->is_recovery_in_progress(cbk->context); 1085 1086 return false; 1087 } 1088 1089 #if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) 1090 1091 /** 1092 * hif_update_pipe_callback() - API to register pipe specific callbacks 1093 * @osc: Opaque softc 1094 * @pipeid: pipe id 1095 * @callbacks: callbacks to register 1096 * 1097 * Return: void 1098 */ 1099 1100 void hif_update_pipe_callback(struct hif_opaque_softc *osc, 1101 u_int8_t pipeid, 1102 struct hif_msg_callbacks *callbacks) 1103 { 1104 struct hif_softc *scn = HIF_GET_SOFTC(osc); 1105 struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); 1106 struct HIF_CE_pipe_info *pipe_info; 1107 1108 QDF_BUG(pipeid < CE_COUNT_MAX); 1109 1110 HIF_INFO_LO("+%s pipeid %d\n", __func__, pipeid); 1111 1112 pipe_info = &hif_state->pipe_info[pipeid]; 1113 1114 qdf_mem_copy(&pipe_info->pipe_callbacks, 1115 callbacks, sizeof(pipe_info->pipe_callbacks)); 1116 1117 HIF_INFO_LO("-%s\n", __func__); 1118 } 1119 qdf_export_symbol(hif_update_pipe_callback); 1120 1121 /** 1122 * hif_is_target_ready() - API to query if target is in ready state 1123 * progress 1124 * @scn: HIF Context 1125 * 1126 * Return: True/False 1127 */ 1128 bool hif_is_target_ready(struct hif_softc *scn) 1129 { 1130 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn); 1131 1132 if (cbk && cbk->is_target_ready) 1133 return cbk->is_target_ready(cbk->context); 1134 /* 1135 * if callback is not registered then there is no way to determine 1136 * if target is ready. In-such case return true to indicate that 1137 * target is ready. 1138 */ 1139 return true; 1140 } 1141 qdf_export_symbol(hif_is_target_ready); 1142 1143 /** 1144 * hif_batch_send() - API to access hif specific function 1145 * ce_batch_send. 1146 * @osc: HIF Context 1147 * @msdu : list of msdus to be sent 1148 * @transfer_id : transfer id 1149 * @len : donwloaded length 1150 * 1151 * Return: list of msds not sent 1152 */ 1153 qdf_nbuf_t hif_batch_send(struct hif_opaque_softc *osc, qdf_nbuf_t msdu, 1154 uint32_t transfer_id, u_int32_t len, uint32_t sendhead) 1155 { 1156 void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE); 1157 1158 return ce_batch_send((struct CE_handle *)ce_tx_hdl, msdu, transfer_id, 1159 len, sendhead); 1160 } 1161 qdf_export_symbol(hif_batch_send); 1162 1163 /** 1164 * hif_update_tx_ring() - API to access hif specific function 1165 * ce_update_tx_ring. 1166 * @osc: HIF Context 1167 * @num_htt_cmpls : number of htt compl received. 1168 * 1169 * Return: void 1170 */ 1171 void hif_update_tx_ring(struct hif_opaque_softc *osc, u_int32_t num_htt_cmpls) 1172 { 1173 void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE); 1174 1175 ce_update_tx_ring(ce_tx_hdl, num_htt_cmpls); 1176 } 1177 qdf_export_symbol(hif_update_tx_ring); 1178 1179 1180 /** 1181 * hif_send_single() - API to access hif specific function 1182 * ce_send_single. 1183 * @osc: HIF Context 1184 * @msdu : msdu to be sent 1185 * @transfer_id: transfer id 1186 * @len : downloaded length 1187 * 1188 * Return: msdu sent status 1189 */ 1190 int hif_send_single(struct hif_opaque_softc *osc, qdf_nbuf_t msdu, uint32_t 1191 transfer_id, u_int32_t len) 1192 { 1193 void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE); 1194 1195 return ce_send_single((struct CE_handle *)ce_tx_hdl, msdu, transfer_id, 1196 len); 1197 } 1198 qdf_export_symbol(hif_send_single); 1199 #endif 1200 1201 /** 1202 * hif_reg_write() - API to access hif specific function 1203 * hif_write32_mb. 1204 * @hif_ctx : HIF Context 1205 * @offset : offset on which value has to be written 1206 * @value : value to be written 1207 * 1208 * Return: None 1209 */ 1210 void hif_reg_write(struct hif_opaque_softc *hif_ctx, uint32_t offset, 1211 uint32_t value) 1212 { 1213 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1214 1215 hif_write32_mb(scn, scn->mem + offset, value); 1216 1217 } 1218 qdf_export_symbol(hif_reg_write); 1219 1220 /** 1221 * hif_reg_read() - API to access hif specific function 1222 * hif_read32_mb. 1223 * @hif_ctx : HIF Context 1224 * @offset : offset from which value has to be read 1225 * 1226 * Return: Read value 1227 */ 1228 uint32_t hif_reg_read(struct hif_opaque_softc *hif_ctx, uint32_t offset) 1229 { 1230 1231 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1232 1233 return hif_read32_mb(scn, scn->mem + offset); 1234 } 1235 qdf_export_symbol(hif_reg_read); 1236 1237 /** 1238 * hif_ramdump_handler(): generic ramdump handler 1239 * @scn: struct hif_opaque_softc 1240 * 1241 * Return: None 1242 */ 1243 void hif_ramdump_handler(struct hif_opaque_softc *scn) 1244 { 1245 if (hif_get_bus_type(scn) == QDF_BUS_TYPE_USB) 1246 hif_usb_ramdump_handler(scn); 1247 } 1248 1249 #ifdef WLAN_SUSPEND_RESUME_TEST 1250 irqreturn_t hif_wake_interrupt_handler(int irq, void *context) 1251 { 1252 struct hif_softc *scn = context; 1253 1254 HIF_INFO("wake interrupt received on irq %d", irq); 1255 1256 if (scn->initial_wakeup_cb) 1257 scn->initial_wakeup_cb(scn->initial_wakeup_priv); 1258 1259 if (hif_is_ut_suspended(scn)) 1260 hif_ut_fw_resume(scn); 1261 1262 return IRQ_HANDLED; 1263 } 1264 #else /* WLAN_SUSPEND_RESUME_TEST */ 1265 irqreturn_t hif_wake_interrupt_handler(int irq, void *context) 1266 { 1267 struct hif_softc *scn = context; 1268 1269 HIF_INFO("wake interrupt received on irq %d", irq); 1270 1271 if (scn->initial_wakeup_cb) 1272 scn->initial_wakeup_cb(scn->initial_wakeup_priv); 1273 1274 return IRQ_HANDLED; 1275 } 1276 #endif /* WLAN_SUSPEND_RESUME_TEST */ 1277 1278 void hif_set_initial_wakeup_cb(struct hif_opaque_softc *hif_ctx, 1279 void (*callback)(void *), 1280 void *priv) 1281 { 1282 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1283 1284 scn->initial_wakeup_cb = callback; 1285 scn->initial_wakeup_priv = priv; 1286 } 1287 1288 void hif_set_ce_service_max_yield_time(struct hif_opaque_softc *hif, 1289 uint32_t ce_service_max_yield_time) 1290 { 1291 struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif); 1292 1293 hif_ctx->ce_service_max_yield_time = 1294 ce_service_max_yield_time * 1000; 1295 } 1296 1297 unsigned long long 1298 hif_get_ce_service_max_yield_time(struct hif_opaque_softc *hif) 1299 { 1300 struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif); 1301 1302 return hif_ctx->ce_service_max_yield_time; 1303 } 1304 1305 void hif_set_ce_service_max_rx_ind_flush(struct hif_opaque_softc *hif, 1306 uint8_t ce_service_max_rx_ind_flush) 1307 { 1308 struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif); 1309 1310 if (ce_service_max_rx_ind_flush == 0 || 1311 ce_service_max_rx_ind_flush > MSG_FLUSH_NUM) 1312 hif_ctx->ce_service_max_rx_ind_flush = MSG_FLUSH_NUM; 1313 else 1314 hif_ctx->ce_service_max_rx_ind_flush = 1315 ce_service_max_rx_ind_flush; 1316 } 1317