1 /* 2 * Copyright (c) 2015-2018 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 #ifdef QCA_WIFI_QCA8074 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 == NULL) { 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) || \ 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 == NULL) 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 == NULL) { 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_COMPOSITE: 816 case QCN7605_STANDALONE: 817 *hif_type = HIF_TYPE_QCN7605; 818 *target_type = TARGET_TYPE_QCN7605; 819 HIF_INFO(" *********** QCN7605 *************\n"); 820 break; 821 822 case QCA6390_DEVICE_ID: 823 case QCA6390_EMULATION_DEVICE_ID: 824 *hif_type = HIF_TYPE_QCA6390; 825 *target_type = TARGET_TYPE_QCA6390; 826 HIF_INFO(" *********** QCA6390 *************\n"); 827 break; 828 829 case QCA8074V2_DEVICE_ID: 830 case RUMIM2M_DEVICE_ID_NODE0: 831 case RUMIM2M_DEVICE_ID_NODE1: 832 case RUMIM2M_DEVICE_ID_NODE2: 833 case RUMIM2M_DEVICE_ID_NODE3: 834 *hif_type = HIF_TYPE_QCA8074V2; 835 *target_type = TARGET_TYPE_QCA8074V2; 836 HIF_INFO(" *********** QCA8074V2 *************\n"); 837 break; 838 839 default: 840 HIF_ERROR("%s: Unsupported device ID = 0x%x!", 841 __func__, device_id); 842 ret = -ENODEV; 843 break; 844 } 845 846 if (*target_type == TARGET_TYPE_UNKNOWN) { 847 HIF_ERROR("%s: Unsupported target_type!", __func__); 848 ret = -ENODEV; 849 } 850 end: 851 return ret; 852 } 853 854 /** 855 * hif_get_bus_type() - return the bus type 856 * 857 * Return: enum qdf_bus_type 858 */ 859 enum qdf_bus_type hif_get_bus_type(struct hif_opaque_softc *hif_hdl) 860 { 861 struct hif_softc *scn = HIF_GET_SOFTC(hif_hdl); 862 863 return scn->bus_type; 864 } 865 866 /** 867 * Target info and ini parameters are global to the driver 868 * Hence these structures are exposed to all the modules in 869 * the driver and they don't need to maintains multiple copies 870 * of the same info, instead get the handle from hif and 871 * modify them in hif 872 */ 873 874 /** 875 * hif_get_ini_handle() - API to get hif_config_param handle 876 * @hif_ctx: HIF Context 877 * 878 * Return: pointer to hif_config_info 879 */ 880 struct hif_config_info *hif_get_ini_handle(struct hif_opaque_softc *hif_ctx) 881 { 882 struct hif_softc *sc = HIF_GET_SOFTC(hif_ctx); 883 884 return &sc->hif_config; 885 } 886 887 /** 888 * hif_get_target_info_handle() - API to get hif_target_info handle 889 * @hif_ctx: HIF context 890 * 891 * Return: Pointer to hif_target_info 892 */ 893 struct hif_target_info *hif_get_target_info_handle( 894 struct hif_opaque_softc *hif_ctx) 895 { 896 struct hif_softc *sc = HIF_GET_SOFTC(hif_ctx); 897 898 return &sc->target_info; 899 900 } 901 qdf_export_symbol(hif_get_target_info_handle); 902 903 #ifdef RECEIVE_OFFLOAD 904 void hif_offld_flush_cb_register(struct hif_opaque_softc *scn, 905 void (offld_flush_handler)(void *)) 906 { 907 if (hif_napi_enabled(scn, -1)) 908 hif_napi_rx_offld_flush_cb_register(scn, offld_flush_handler); 909 else 910 HIF_ERROR("NAPI not enabled\n"); 911 } 912 qdf_export_symbol(hif_offld_flush_cb_register); 913 914 void hif_offld_flush_cb_deregister(struct hif_opaque_softc *scn) 915 { 916 if (hif_napi_enabled(scn, -1)) 917 hif_napi_rx_offld_flush_cb_deregister(scn); 918 else 919 HIF_ERROR("NAPI not enabled\n"); 920 } 921 qdf_export_symbol(hif_offld_flush_cb_deregister); 922 923 int hif_get_rx_ctx_id(int ctx_id, struct hif_opaque_softc *hif_hdl) 924 { 925 if (hif_napi_enabled(hif_hdl, -1)) 926 return NAPI_PIPE2ID(ctx_id); 927 else 928 return ctx_id; 929 } 930 #else /* RECEIVE_OFFLOAD */ 931 int hif_get_rx_ctx_id(int ctx_id, struct hif_opaque_softc *hif_hdl) 932 { 933 return 0; 934 } 935 #endif /* RECEIVE_OFFLOAD */ 936 937 #if defined(FEATURE_LRO) 938 939 /** 940 * hif_get_lro_info - Returns LRO instance for instance ID 941 * @ctx_id: LRO instance ID 942 * @hif_hdl: HIF Context 943 * 944 * Return: Pointer to LRO instance. 945 */ 946 void *hif_get_lro_info(int ctx_id, struct hif_opaque_softc *hif_hdl) 947 { 948 void *data; 949 950 if (hif_napi_enabled(hif_hdl, -1)) 951 data = hif_napi_get_lro_info(hif_hdl, ctx_id); 952 else 953 data = hif_ce_get_lro_ctx(hif_hdl, ctx_id); 954 955 return data; 956 } 957 #endif 958 959 /** 960 * hif_get_target_status - API to get target status 961 * @hif_ctx: HIF Context 962 * 963 * Return: enum hif_target_status 964 */ 965 enum hif_target_status hif_get_target_status(struct hif_opaque_softc *hif_ctx) 966 { 967 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 968 969 return scn->target_status; 970 } 971 qdf_export_symbol(hif_get_target_status); 972 973 /** 974 * hif_set_target_status() - API to set target status 975 * @hif_ctx: HIF Context 976 * @status: Target Status 977 * 978 * Return: void 979 */ 980 void hif_set_target_status(struct hif_opaque_softc *hif_ctx, enum 981 hif_target_status status) 982 { 983 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 984 985 scn->target_status = status; 986 } 987 988 /** 989 * hif_init_ini_config() - API to initialize HIF configuration parameters 990 * @hif_ctx: HIF Context 991 * @cfg: HIF Configuration 992 * 993 * Return: void 994 */ 995 void hif_init_ini_config(struct hif_opaque_softc *hif_ctx, 996 struct hif_config_info *cfg) 997 { 998 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 999 1000 qdf_mem_copy(&scn->hif_config, cfg, sizeof(struct hif_config_info)); 1001 } 1002 1003 /** 1004 * hif_get_conparam() - API to get driver mode in HIF 1005 * @scn: HIF Context 1006 * 1007 * Return: driver mode of operation 1008 */ 1009 uint32_t hif_get_conparam(struct hif_softc *scn) 1010 { 1011 if (!scn) 1012 return 0; 1013 1014 return scn->hif_con_param; 1015 } 1016 1017 /** 1018 * hif_get_callbacks_handle() - API to get callbacks Handle 1019 * @scn: HIF Context 1020 * 1021 * Return: pointer to HIF Callbacks 1022 */ 1023 struct hif_driver_state_callbacks *hif_get_callbacks_handle( 1024 struct hif_softc *scn) 1025 { 1026 return &scn->callbacks; 1027 } 1028 1029 /** 1030 * hif_is_driver_unloading() - API to query upper layers if driver is unloading 1031 * @scn: HIF Context 1032 * 1033 * Return: True/False 1034 */ 1035 bool hif_is_driver_unloading(struct hif_softc *scn) 1036 { 1037 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn); 1038 1039 if (cbk && cbk->is_driver_unloading) 1040 return cbk->is_driver_unloading(cbk->context); 1041 1042 return false; 1043 } 1044 1045 /** 1046 * hif_is_load_or_unload_in_progress() - API to query upper layers if 1047 * load/unload in progress 1048 * @scn: HIF Context 1049 * 1050 * Return: True/False 1051 */ 1052 bool hif_is_load_or_unload_in_progress(struct hif_softc *scn) 1053 { 1054 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn); 1055 1056 if (cbk && cbk->is_load_unload_in_progress) 1057 return cbk->is_load_unload_in_progress(cbk->context); 1058 1059 return false; 1060 } 1061 1062 /** 1063 * hif_is_recovery_in_progress() - API to query upper layers if recovery in 1064 * progress 1065 * @scn: HIF Context 1066 * 1067 * Return: True/False 1068 */ 1069 bool hif_is_recovery_in_progress(struct hif_softc *scn) 1070 { 1071 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn); 1072 1073 if (cbk && cbk->is_recovery_in_progress) 1074 return cbk->is_recovery_in_progress(cbk->context); 1075 1076 return false; 1077 } 1078 1079 #if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) 1080 1081 /** 1082 * hif_update_pipe_callback() - API to register pipe specific callbacks 1083 * @osc: Opaque softc 1084 * @pipeid: pipe id 1085 * @callbacks: callbacks to register 1086 * 1087 * Return: void 1088 */ 1089 1090 void hif_update_pipe_callback(struct hif_opaque_softc *osc, 1091 u_int8_t pipeid, 1092 struct hif_msg_callbacks *callbacks) 1093 { 1094 struct hif_softc *scn = HIF_GET_SOFTC(osc); 1095 struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); 1096 struct HIF_CE_pipe_info *pipe_info; 1097 1098 QDF_BUG(pipeid < CE_COUNT_MAX); 1099 1100 HIF_INFO_LO("+%s pipeid %d\n", __func__, pipeid); 1101 1102 pipe_info = &hif_state->pipe_info[pipeid]; 1103 1104 qdf_mem_copy(&pipe_info->pipe_callbacks, 1105 callbacks, sizeof(pipe_info->pipe_callbacks)); 1106 1107 HIF_INFO_LO("-%s\n", __func__); 1108 } 1109 qdf_export_symbol(hif_update_pipe_callback); 1110 1111 /** 1112 * hif_is_target_ready() - API to query if target is in ready state 1113 * progress 1114 * @scn: HIF Context 1115 * 1116 * Return: True/False 1117 */ 1118 bool hif_is_target_ready(struct hif_softc *scn) 1119 { 1120 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn); 1121 1122 if (cbk && cbk->is_target_ready) 1123 return cbk->is_target_ready(cbk->context); 1124 1125 return false; 1126 } 1127 1128 /** 1129 * hif_batch_send() - API to access hif specific function 1130 * ce_batch_send. 1131 * @osc: HIF Context 1132 * @msdu : list of msdus to be sent 1133 * @transfer_id : transfer id 1134 * @len : donwloaded length 1135 * 1136 * Return: list of msds not sent 1137 */ 1138 qdf_nbuf_t hif_batch_send(struct hif_opaque_softc *osc, qdf_nbuf_t msdu, 1139 uint32_t transfer_id, u_int32_t len, uint32_t sendhead) 1140 { 1141 void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE); 1142 1143 return ce_batch_send((struct CE_handle *)ce_tx_hdl, msdu, transfer_id, 1144 len, sendhead); 1145 } 1146 qdf_export_symbol(hif_batch_send); 1147 1148 /** 1149 * hif_update_tx_ring() - API to access hif specific function 1150 * ce_update_tx_ring. 1151 * @osc: HIF Context 1152 * @num_htt_cmpls : number of htt compl received. 1153 * 1154 * Return: void 1155 */ 1156 void hif_update_tx_ring(struct hif_opaque_softc *osc, u_int32_t num_htt_cmpls) 1157 { 1158 void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE); 1159 1160 ce_update_tx_ring(ce_tx_hdl, num_htt_cmpls); 1161 } 1162 qdf_export_symbol(hif_update_tx_ring); 1163 1164 1165 /** 1166 * hif_send_single() - API to access hif specific function 1167 * ce_send_single. 1168 * @osc: HIF Context 1169 * @msdu : msdu to be sent 1170 * @transfer_id: transfer id 1171 * @len : downloaded length 1172 * 1173 * Return: msdu sent status 1174 */ 1175 int hif_send_single(struct hif_opaque_softc *osc, qdf_nbuf_t msdu, uint32_t 1176 transfer_id, u_int32_t len) 1177 { 1178 void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE); 1179 1180 return ce_send_single((struct CE_handle *)ce_tx_hdl, msdu, transfer_id, 1181 len); 1182 } 1183 qdf_export_symbol(hif_send_single); 1184 1185 #ifdef WLAN_FEATURE_FASTPATH 1186 /** 1187 * hif_send_fast() - API to access hif specific function 1188 * ce_send_fast. 1189 * @osc: HIF Context 1190 * @msdu : array of msdus to be sent 1191 * @num_msdus : number of msdus in an array 1192 * @transfer_id: transfer id 1193 * @download_len: download length 1194 * 1195 * Return: No. of packets that could be sent 1196 */ 1197 int hif_send_fast(struct hif_opaque_softc *osc, qdf_nbuf_t nbuf, 1198 uint32_t transfer_id, uint32_t download_len) 1199 { 1200 void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE); 1201 1202 return ce_send_fast((struct CE_handle *)ce_tx_hdl, nbuf, 1203 transfer_id, download_len); 1204 } 1205 qdf_export_symbol(hif_send_fast); 1206 #endif 1207 #endif 1208 1209 /** 1210 * hif_reg_write() - API to access hif specific function 1211 * hif_write32_mb. 1212 * @hif_ctx : HIF Context 1213 * @offset : offset on which value has to be written 1214 * @value : value to be written 1215 * 1216 * Return: None 1217 */ 1218 void hif_reg_write(struct hif_opaque_softc *hif_ctx, uint32_t offset, 1219 uint32_t value) 1220 { 1221 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1222 1223 hif_write32_mb(scn, scn->mem + offset, value); 1224 1225 } 1226 qdf_export_symbol(hif_reg_write); 1227 1228 /** 1229 * hif_reg_read() - API to access hif specific function 1230 * hif_read32_mb. 1231 * @hif_ctx : HIF Context 1232 * @offset : offset from which value has to be read 1233 * 1234 * Return: Read value 1235 */ 1236 uint32_t hif_reg_read(struct hif_opaque_softc *hif_ctx, uint32_t offset) 1237 { 1238 1239 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1240 1241 return hif_read32_mb(scn, scn->mem + offset); 1242 } 1243 qdf_export_symbol(hif_reg_read); 1244 1245 /** 1246 * hif_ramdump_handler(): generic ramdump handler 1247 * @scn: struct hif_opaque_softc 1248 * 1249 * Return: None 1250 */ 1251 void hif_ramdump_handler(struct hif_opaque_softc *scn) 1252 { 1253 if (hif_get_bus_type(scn) == QDF_BUS_TYPE_USB) 1254 hif_usb_ramdump_handler(scn); 1255 } 1256 1257 #ifdef WLAN_SUSPEND_RESUME_TEST 1258 irqreturn_t hif_wake_interrupt_handler(int irq, void *context) 1259 { 1260 struct hif_softc *scn = context; 1261 1262 HIF_INFO("wake interrupt received on irq %d", irq); 1263 1264 if (scn->initial_wakeup_cb) 1265 scn->initial_wakeup_cb(scn->initial_wakeup_priv); 1266 1267 if (hif_is_ut_suspended(scn)) 1268 hif_ut_fw_resume(scn); 1269 1270 return IRQ_HANDLED; 1271 } 1272 #else /* WLAN_SUSPEND_RESUME_TEST */ 1273 irqreturn_t hif_wake_interrupt_handler(int irq, void *context) 1274 { 1275 struct hif_softc *scn = context; 1276 1277 HIF_INFO("wake interrupt received on irq %d", irq); 1278 1279 if (scn->initial_wakeup_cb) 1280 scn->initial_wakeup_cb(scn->initial_wakeup_priv); 1281 1282 return IRQ_HANDLED; 1283 } 1284 #endif /* WLAN_SUSPEND_RESUME_TEST */ 1285 1286 void hif_set_initial_wakeup_cb(struct hif_opaque_softc *hif_ctx, 1287 void (*callback)(void *), 1288 void *priv) 1289 { 1290 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1291 1292 scn->initial_wakeup_cb = callback; 1293 scn->initial_wakeup_priv = priv; 1294 } 1295 1296 void hif_set_ce_service_max_yield_time(struct hif_opaque_softc *hif, 1297 uint32_t ce_service_max_yield_time) 1298 { 1299 struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif); 1300 1301 hif_ctx->ce_service_max_yield_time = 1302 ce_service_max_yield_time * 1000; 1303 } 1304 1305 unsigned long long 1306 hif_get_ce_service_max_yield_time(struct hif_opaque_softc *hif) 1307 { 1308 struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif); 1309 1310 return hif_ctx->ce_service_max_yield_time; 1311 } 1312 1313 void hif_set_ce_service_max_rx_ind_flush(struct hif_opaque_softc *hif, 1314 uint8_t ce_service_max_rx_ind_flush) 1315 { 1316 struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif); 1317 1318 if (ce_service_max_rx_ind_flush == 0 || 1319 ce_service_max_rx_ind_flush > MSG_FLUSH_NUM) 1320 hif_ctx->ce_service_max_rx_ind_flush = MSG_FLUSH_NUM; 1321 else 1322 hif_ctx->ce_service_max_rx_ind_flush = 1323 ce_service_max_rx_ind_flush; 1324 } 1325