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 #ifdef QCA_WIFI_QCA8074 490 static QDF_STATUS hif_hal_attach(struct hif_softc *scn) 491 { 492 if (ce_srng_based(scn)) { 493 scn->hal_soc = hal_attach(scn, scn->qdf_dev); 494 if (scn->hal_soc == NULL) 495 return QDF_STATUS_E_FAILURE; 496 } 497 498 return QDF_STATUS_SUCCESS; 499 } 500 501 static QDF_STATUS hif_hal_detach(struct hif_softc *scn) 502 { 503 if (ce_srng_based(scn)) { 504 hal_detach(scn->hal_soc); 505 scn->hal_soc = NULL; 506 } 507 508 return QDF_STATUS_SUCCESS; 509 } 510 #else 511 static QDF_STATUS hif_hal_attach(struct hif_softc *scn) 512 { 513 return QDF_STATUS_SUCCESS; 514 } 515 516 static QDF_STATUS hif_hal_detach(struct hif_softc *scn) 517 { 518 return QDF_STATUS_SUCCESS; 519 } 520 #endif 521 522 /** 523 * hif_enable(): hif_enable 524 * @hif_ctx: hif_ctx 525 * @dev: dev 526 * @bdev: bus dev 527 * @bid: bus ID 528 * @bus_type: bus type 529 * @type: enable type 530 * 531 * Return: QDF_STATUS 532 */ 533 QDF_STATUS hif_enable(struct hif_opaque_softc *hif_ctx, struct device *dev, 534 void *bdev, 535 const struct hif_bus_id *bid, 536 enum qdf_bus_type bus_type, 537 enum hif_enable_type type) 538 { 539 QDF_STATUS status; 540 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 541 542 if (scn == NULL) { 543 HIF_ERROR("%s: hif_ctx = NULL", __func__); 544 return QDF_STATUS_E_NULL_VALUE; 545 } 546 547 status = hif_enable_bus(scn, dev, bdev, bid, type); 548 if (status != QDF_STATUS_SUCCESS) { 549 HIF_ERROR("%s: hif_enable_bus error = %d", 550 __func__, status); 551 return status; 552 } 553 554 status = hif_hal_attach(scn); 555 if (status != QDF_STATUS_SUCCESS) { 556 HIF_ERROR("%s: hal attach failed", __func__); 557 goto disable_bus; 558 } 559 560 if (hif_bus_configure(scn)) { 561 HIF_ERROR("%s: Target probe failed.", __func__); 562 status = QDF_STATUS_E_FAILURE; 563 goto hal_detach; 564 } 565 566 hif_ut_suspend_init(scn); 567 568 /* 569 * Flag to avoid potential unallocated memory access from MSI 570 * interrupt handler which could get scheduled as soon as MSI 571 * is enabled, i.e to take care of the race due to the order 572 * in where MSI is enabled before the memory, that will be 573 * in interrupt handlers, is allocated. 574 */ 575 576 scn->hif_init_done = true; 577 578 HIF_DBG("%s: OK", __func__); 579 580 return QDF_STATUS_SUCCESS; 581 582 hal_detach: 583 hif_hal_detach(scn); 584 disable_bus: 585 hif_disable_bus(scn); 586 return status; 587 } 588 589 void hif_disable(struct hif_opaque_softc *hif_ctx, enum hif_disable_type type) 590 { 591 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 592 593 if (!scn) 594 return; 595 596 hif_nointrs(scn); 597 if (scn->hif_init_done == false) 598 hif_shutdown_device(hif_ctx); 599 else 600 hif_stop(hif_ctx); 601 602 hif_hal_detach(scn); 603 604 hif_disable_bus(scn); 605 606 hif_wlan_disable(scn); 607 608 scn->notice_send = false; 609 610 HIF_DBG("%s: X", __func__); 611 } 612 613 void hif_display_stats(struct hif_opaque_softc *hif_ctx) 614 { 615 hif_display_bus_stats(hif_ctx); 616 } 617 618 void hif_clear_stats(struct hif_opaque_softc *hif_ctx) 619 { 620 hif_clear_bus_stats(hif_ctx); 621 } 622 623 /** 624 * hif_crash_shutdown_dump_bus_register() - dump bus registers 625 * @hif_ctx: hif_ctx 626 * 627 * Return: n/a 628 */ 629 #if defined(TARGET_RAMDUMP_AFTER_KERNEL_PANIC) \ 630 && defined(DEBUG) 631 632 static void hif_crash_shutdown_dump_bus_register(void *hif_ctx) 633 { 634 struct hif_opaque_softc *scn = hif_ctx; 635 636 if (hif_check_soc_status(scn)) 637 return; 638 639 if (hif_dump_registers(scn)) 640 HIF_ERROR("Failed to dump bus registers!"); 641 } 642 643 /** 644 * hif_crash_shutdown(): hif_crash_shutdown 645 * 646 * This function is called by the platform driver to dump CE registers 647 * 648 * @hif_ctx: hif_ctx 649 * 650 * Return: n/a 651 */ 652 void hif_crash_shutdown(struct hif_opaque_softc *hif_ctx) 653 { 654 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 655 656 if (!hif_ctx) 657 return; 658 659 if (scn->bus_type == QDF_BUS_TYPE_SNOC) { 660 HIF_INFO_MED("%s: RAM dump disabled for bustype %d", 661 __func__, scn->bus_type); 662 return; 663 } 664 665 if (TARGET_STATUS_RESET == scn->target_status) { 666 HIF_INFO_MED("%s: Target is already asserted, ignore!", 667 __func__); 668 return; 669 } 670 671 if (hif_is_load_or_unload_in_progress(scn)) { 672 HIF_ERROR("%s: Load/unload is in progress, ignore!", __func__); 673 return; 674 } 675 676 hif_crash_shutdown_dump_bus_register(hif_ctx); 677 678 if (ol_copy_ramdump(hif_ctx)) 679 goto out; 680 681 HIF_INFO_MED("%s: RAM dump collecting completed!", __func__); 682 683 out: 684 return; 685 } 686 #else 687 void hif_crash_shutdown(struct hif_opaque_softc *hif_ctx) 688 { 689 HIF_INFO_MED("%s: Collecting target RAM dump disabled", 690 __func__); 691 } 692 #endif /* TARGET_RAMDUMP_AFTER_KERNEL_PANIC */ 693 694 #ifdef QCA_WIFI_3_0 695 /** 696 * hif_check_fw_reg(): hif_check_fw_reg 697 * @scn: scn 698 * @state: 699 * 700 * Return: int 701 */ 702 int hif_check_fw_reg(struct hif_opaque_softc *scn) 703 { 704 return 0; 705 } 706 #endif 707 708 /** 709 * hif_read_phy_mem_base(): hif_read_phy_mem_base 710 * @scn: scn 711 * @phy_mem_base: physical mem base 712 * 713 * Return: n/a 714 */ 715 void hif_read_phy_mem_base(struct hif_softc *scn, qdf_dma_addr_t *phy_mem_base) 716 { 717 *phy_mem_base = scn->mem_pa; 718 } 719 qdf_export_symbol(hif_read_phy_mem_base); 720 721 /** 722 * hif_get_device_type(): hif_get_device_type 723 * @device_id: device_id 724 * @revision_id: revision_id 725 * @hif_type: returned hif_type 726 * @target_type: returned target_type 727 * 728 * Return: int 729 */ 730 int hif_get_device_type(uint32_t device_id, 731 uint32_t revision_id, 732 uint32_t *hif_type, uint32_t *target_type) 733 { 734 int ret = 0; 735 736 switch (device_id) { 737 case ADRASTEA_DEVICE_ID_P2_E12: 738 739 *hif_type = HIF_TYPE_ADRASTEA; 740 *target_type = TARGET_TYPE_ADRASTEA; 741 break; 742 743 case AR9888_DEVICE_ID: 744 *hif_type = HIF_TYPE_AR9888; 745 *target_type = TARGET_TYPE_AR9888; 746 break; 747 748 case AR6320_DEVICE_ID: 749 switch (revision_id) { 750 case AR6320_FW_1_1: 751 case AR6320_FW_1_3: 752 *hif_type = HIF_TYPE_AR6320; 753 *target_type = TARGET_TYPE_AR6320; 754 break; 755 756 case AR6320_FW_2_0: 757 case AR6320_FW_3_0: 758 case AR6320_FW_3_2: 759 *hif_type = HIF_TYPE_AR6320V2; 760 *target_type = TARGET_TYPE_AR6320V2; 761 break; 762 763 default: 764 HIF_ERROR("%s: error - dev_id = 0x%x, rev_id = 0x%x", 765 __func__, device_id, revision_id); 766 ret = -ENODEV; 767 goto end; 768 } 769 break; 770 771 case AR9887_DEVICE_ID: 772 *hif_type = HIF_TYPE_AR9888; 773 *target_type = TARGET_TYPE_AR9888; 774 HIF_INFO(" *********** AR9887 **************"); 775 break; 776 777 case QCA9984_DEVICE_ID: 778 *hif_type = HIF_TYPE_QCA9984; 779 *target_type = TARGET_TYPE_QCA9984; 780 HIF_INFO(" *********** QCA9984 *************"); 781 break; 782 783 case QCA9888_DEVICE_ID: 784 *hif_type = HIF_TYPE_QCA9888; 785 *target_type = TARGET_TYPE_QCA9888; 786 HIF_INFO(" *********** QCA9888 *************"); 787 break; 788 789 case AR900B_DEVICE_ID: 790 *hif_type = HIF_TYPE_AR900B; 791 *target_type = TARGET_TYPE_AR900B; 792 HIF_INFO(" *********** AR900B *************"); 793 break; 794 795 case IPQ4019_DEVICE_ID: 796 *hif_type = HIF_TYPE_IPQ4019; 797 *target_type = TARGET_TYPE_IPQ4019; 798 HIF_INFO(" *********** IPQ4019 *************"); 799 break; 800 801 case QCA8074_DEVICE_ID: 802 case RUMIM2M_DEVICE_ID_NODE0: 803 case RUMIM2M_DEVICE_ID_NODE1: 804 case RUMIM2M_DEVICE_ID_NODE2: 805 case RUMIM2M_DEVICE_ID_NODE3: 806 *hif_type = HIF_TYPE_QCA8074; 807 *target_type = TARGET_TYPE_QCA8074; 808 HIF_INFO(" *********** QCA8074 *************\n"); 809 break; 810 811 case QCA6290_EMULATION_DEVICE_ID: 812 case QCA6290_DEVICE_ID: 813 *hif_type = HIF_TYPE_QCA6290; 814 *target_type = TARGET_TYPE_QCA6290; 815 HIF_INFO(" *********** QCA6290EMU *************\n"); 816 break; 817 818 case QCN7605_COMPOSITE: 819 case QCN7605_STANDALONE: 820 *hif_type = HIF_TYPE_QCN7605; 821 *target_type = TARGET_TYPE_QCN7605; 822 HIF_INFO(" *********** QCN7605 *************\n"); 823 break; 824 825 default: 826 HIF_ERROR("%s: Unsupported device ID!", __func__); 827 ret = -ENODEV; 828 break; 829 } 830 831 if (*target_type == TARGET_TYPE_UNKNOWN) { 832 HIF_ERROR("%s: Unsupported target_type!", __func__); 833 ret = -ENODEV; 834 } 835 end: 836 return ret; 837 } 838 839 /** 840 * hif_get_bus_type() - return the bus type 841 * 842 * Return: enum qdf_bus_type 843 */ 844 enum qdf_bus_type hif_get_bus_type(struct hif_opaque_softc *hif_hdl) 845 { 846 struct hif_softc *scn = HIF_GET_SOFTC(hif_hdl); 847 848 return scn->bus_type; 849 } 850 851 /** 852 * Target info and ini parameters are global to the driver 853 * Hence these structures are exposed to all the modules in 854 * the driver and they don't need to maintains multiple copies 855 * of the same info, instead get the handle from hif and 856 * modify them in hif 857 */ 858 859 /** 860 * hif_get_ini_handle() - API to get hif_config_param handle 861 * @hif_ctx: HIF Context 862 * 863 * Return: pointer to hif_config_info 864 */ 865 struct hif_config_info *hif_get_ini_handle(struct hif_opaque_softc *hif_ctx) 866 { 867 struct hif_softc *sc = HIF_GET_SOFTC(hif_ctx); 868 869 return &sc->hif_config; 870 } 871 872 /** 873 * hif_get_target_info_handle() - API to get hif_target_info handle 874 * @hif_ctx: HIF context 875 * 876 * Return: Pointer to hif_target_info 877 */ 878 struct hif_target_info *hif_get_target_info_handle( 879 struct hif_opaque_softc *hif_ctx) 880 { 881 struct hif_softc *sc = HIF_GET_SOFTC(hif_ctx); 882 883 return &sc->target_info; 884 885 } 886 qdf_export_symbol(hif_get_target_info_handle); 887 888 #ifdef RECEIVE_OFFLOAD 889 void hif_offld_flush_cb_register(struct hif_opaque_softc *scn, 890 void (offld_flush_handler)(void *)) 891 { 892 if (hif_napi_enabled(scn, -1)) 893 hif_napi_rx_offld_flush_cb_register(scn, offld_flush_handler); 894 else 895 HIF_ERROR("NAPI not enabled\n"); 896 } 897 qdf_export_symbol(hif_offld_flush_cb_register); 898 899 void hif_offld_flush_cb_deregister(struct hif_opaque_softc *scn) 900 { 901 if (hif_napi_enabled(scn, -1)) 902 hif_napi_rx_offld_flush_cb_deregister(scn); 903 else 904 HIF_ERROR("NAPI not enabled\n"); 905 } 906 qdf_export_symbol(hif_offld_flush_cb_deregister); 907 908 int hif_get_rx_ctx_id(int ctx_id, struct hif_opaque_softc *hif_hdl) 909 { 910 if (hif_napi_enabled(hif_hdl, -1)) 911 return NAPI_PIPE2ID(ctx_id); 912 else 913 return ctx_id; 914 } 915 #else /* RECEIVE_OFFLOAD */ 916 int hif_get_rx_ctx_id(int ctx_id, struct hif_opaque_softc *hif_hdl) 917 { 918 return 0; 919 } 920 #endif /* RECEIVE_OFFLOAD */ 921 922 #if defined(FEATURE_LRO) 923 924 /** 925 * hif_get_lro_info - Returns LRO instance for instance ID 926 * @ctx_id: LRO instance ID 927 * @hif_hdl: HIF Context 928 * 929 * Return: Pointer to LRO instance. 930 */ 931 void *hif_get_lro_info(int ctx_id, struct hif_opaque_softc *hif_hdl) 932 { 933 void *data; 934 935 if (hif_napi_enabled(hif_hdl, -1)) 936 data = hif_napi_get_lro_info(hif_hdl, ctx_id); 937 else 938 data = hif_ce_get_lro_ctx(hif_hdl, ctx_id); 939 940 return data; 941 } 942 #endif 943 944 /** 945 * hif_get_target_status - API to get target status 946 * @hif_ctx: HIF Context 947 * 948 * Return: enum hif_target_status 949 */ 950 enum hif_target_status hif_get_target_status(struct hif_opaque_softc *hif_ctx) 951 { 952 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 953 954 return scn->target_status; 955 } 956 qdf_export_symbol(hif_get_target_status); 957 958 /** 959 * hif_set_target_status() - API to set target status 960 * @hif_ctx: HIF Context 961 * @status: Target Status 962 * 963 * Return: void 964 */ 965 void hif_set_target_status(struct hif_opaque_softc *hif_ctx, enum 966 hif_target_status status) 967 { 968 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 969 970 scn->target_status = status; 971 } 972 973 /** 974 * hif_init_ini_config() - API to initialize HIF configuration parameters 975 * @hif_ctx: HIF Context 976 * @cfg: HIF Configuration 977 * 978 * Return: void 979 */ 980 void hif_init_ini_config(struct hif_opaque_softc *hif_ctx, 981 struct hif_config_info *cfg) 982 { 983 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 984 985 qdf_mem_copy(&scn->hif_config, cfg, sizeof(struct hif_config_info)); 986 } 987 988 /** 989 * hif_get_conparam() - API to get driver mode in HIF 990 * @scn: HIF Context 991 * 992 * Return: driver mode of operation 993 */ 994 uint32_t hif_get_conparam(struct hif_softc *scn) 995 { 996 if (!scn) 997 return 0; 998 999 return scn->hif_con_param; 1000 } 1001 1002 /** 1003 * hif_get_callbacks_handle() - API to get callbacks Handle 1004 * @scn: HIF Context 1005 * 1006 * Return: pointer to HIF Callbacks 1007 */ 1008 struct hif_driver_state_callbacks *hif_get_callbacks_handle( 1009 struct hif_softc *scn) 1010 { 1011 return &scn->callbacks; 1012 } 1013 1014 /** 1015 * hif_is_driver_unloading() - API to query upper layers if driver is unloading 1016 * @scn: HIF Context 1017 * 1018 * Return: True/False 1019 */ 1020 bool hif_is_driver_unloading(struct hif_softc *scn) 1021 { 1022 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn); 1023 1024 if (cbk && cbk->is_driver_unloading) 1025 return cbk->is_driver_unloading(cbk->context); 1026 1027 return false; 1028 } 1029 1030 /** 1031 * hif_is_load_or_unload_in_progress() - API to query upper layers if 1032 * load/unload in progress 1033 * @scn: HIF Context 1034 * 1035 * Return: True/False 1036 */ 1037 bool hif_is_load_or_unload_in_progress(struct hif_softc *scn) 1038 { 1039 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn); 1040 1041 if (cbk && cbk->is_load_unload_in_progress) 1042 return cbk->is_load_unload_in_progress(cbk->context); 1043 1044 return false; 1045 } 1046 1047 /** 1048 * hif_is_recovery_in_progress() - API to query upper layers if recovery in 1049 * progress 1050 * @scn: HIF Context 1051 * 1052 * Return: True/False 1053 */ 1054 bool hif_is_recovery_in_progress(struct hif_softc *scn) 1055 { 1056 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn); 1057 1058 if (cbk && cbk->is_recovery_in_progress) 1059 return cbk->is_recovery_in_progress(cbk->context); 1060 1061 return false; 1062 } 1063 1064 #if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) 1065 1066 /** 1067 * hif_update_pipe_callback() - API to register pipe specific callbacks 1068 * @osc: Opaque softc 1069 * @pipeid: pipe id 1070 * @callbacks: callbacks to register 1071 * 1072 * Return: void 1073 */ 1074 1075 void hif_update_pipe_callback(struct hif_opaque_softc *osc, 1076 u_int8_t pipeid, 1077 struct hif_msg_callbacks *callbacks) 1078 { 1079 struct hif_softc *scn = HIF_GET_SOFTC(osc); 1080 struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); 1081 struct HIF_CE_pipe_info *pipe_info; 1082 1083 QDF_BUG(pipeid < CE_COUNT_MAX); 1084 1085 HIF_INFO_LO("+%s pipeid %d\n", __func__, pipeid); 1086 1087 pipe_info = &hif_state->pipe_info[pipeid]; 1088 1089 qdf_mem_copy(&pipe_info->pipe_callbacks, 1090 callbacks, sizeof(pipe_info->pipe_callbacks)); 1091 1092 HIF_INFO_LO("-%s\n", __func__); 1093 } 1094 qdf_export_symbol(hif_update_pipe_callback); 1095 1096 /** 1097 * hif_is_target_ready() - API to query if target is in ready state 1098 * progress 1099 * @scn: HIF Context 1100 * 1101 * Return: True/False 1102 */ 1103 bool hif_is_target_ready(struct hif_softc *scn) 1104 { 1105 struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn); 1106 1107 if (cbk && cbk->is_target_ready) 1108 return cbk->is_target_ready(cbk->context); 1109 1110 return false; 1111 } 1112 1113 /** 1114 * hif_batch_send() - API to access hif specific function 1115 * ce_batch_send. 1116 * @osc: HIF Context 1117 * @msdu : list of msdus to be sent 1118 * @transfer_id : transfer id 1119 * @len : donwloaded length 1120 * 1121 * Return: list of msds not sent 1122 */ 1123 qdf_nbuf_t hif_batch_send(struct hif_opaque_softc *osc, qdf_nbuf_t msdu, 1124 uint32_t transfer_id, u_int32_t len, uint32_t sendhead) 1125 { 1126 void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE); 1127 1128 return ce_batch_send((struct CE_handle *)ce_tx_hdl, msdu, transfer_id, 1129 len, sendhead); 1130 } 1131 qdf_export_symbol(hif_batch_send); 1132 1133 /** 1134 * hif_update_tx_ring() - API to access hif specific function 1135 * ce_update_tx_ring. 1136 * @osc: HIF Context 1137 * @num_htt_cmpls : number of htt compl received. 1138 * 1139 * Return: void 1140 */ 1141 void hif_update_tx_ring(struct hif_opaque_softc *osc, u_int32_t num_htt_cmpls) 1142 { 1143 void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE); 1144 1145 ce_update_tx_ring(ce_tx_hdl, num_htt_cmpls); 1146 } 1147 qdf_export_symbol(hif_update_tx_ring); 1148 1149 1150 /** 1151 * hif_send_single() - API to access hif specific function 1152 * ce_send_single. 1153 * @osc: HIF Context 1154 * @msdu : msdu to be sent 1155 * @transfer_id: transfer id 1156 * @len : downloaded length 1157 * 1158 * Return: msdu sent status 1159 */ 1160 int hif_send_single(struct hif_opaque_softc *osc, qdf_nbuf_t msdu, uint32_t 1161 transfer_id, u_int32_t len) 1162 { 1163 void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE); 1164 1165 return ce_send_single((struct CE_handle *)ce_tx_hdl, msdu, transfer_id, 1166 len); 1167 } 1168 qdf_export_symbol(hif_send_single); 1169 1170 #ifdef WLAN_FEATURE_FASTPATH 1171 /** 1172 * hif_send_fast() - API to access hif specific function 1173 * ce_send_fast. 1174 * @osc: HIF Context 1175 * @msdu : array of msdus to be sent 1176 * @num_msdus : number of msdus in an array 1177 * @transfer_id: transfer id 1178 * @download_len: download length 1179 * 1180 * Return: No. of packets that could be sent 1181 */ 1182 int hif_send_fast(struct hif_opaque_softc *osc, qdf_nbuf_t nbuf, 1183 uint32_t transfer_id, uint32_t download_len) 1184 { 1185 void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE); 1186 1187 return ce_send_fast((struct CE_handle *)ce_tx_hdl, nbuf, 1188 transfer_id, download_len); 1189 } 1190 qdf_export_symbol(hif_send_fast); 1191 #endif 1192 #endif 1193 1194 /** 1195 * hif_reg_write() - API to access hif specific function 1196 * hif_write32_mb. 1197 * @hif_ctx : HIF Context 1198 * @offset : offset on which value has to be written 1199 * @value : value to be written 1200 * 1201 * Return: None 1202 */ 1203 void hif_reg_write(struct hif_opaque_softc *hif_ctx, uint32_t offset, 1204 uint32_t value) 1205 { 1206 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1207 1208 hif_write32_mb(scn, scn->mem + offset, value); 1209 1210 } 1211 qdf_export_symbol(hif_reg_write); 1212 1213 /** 1214 * hif_reg_read() - API to access hif specific function 1215 * hif_read32_mb. 1216 * @hif_ctx : HIF Context 1217 * @offset : offset from which value has to be read 1218 * 1219 * Return: Read value 1220 */ 1221 uint32_t hif_reg_read(struct hif_opaque_softc *hif_ctx, uint32_t offset) 1222 { 1223 1224 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1225 1226 return hif_read32_mb(scn, scn->mem + offset); 1227 } 1228 qdf_export_symbol(hif_reg_read); 1229 1230 /** 1231 * hif_ramdump_handler(): generic ramdump handler 1232 * @scn: struct hif_opaque_softc 1233 * 1234 * Return: None 1235 */ 1236 void hif_ramdump_handler(struct hif_opaque_softc *scn) 1237 { 1238 if (hif_get_bus_type(scn) == QDF_BUS_TYPE_USB) 1239 hif_usb_ramdump_handler(scn); 1240 } 1241 1242 #ifdef WLAN_SUSPEND_RESUME_TEST 1243 irqreturn_t hif_wake_interrupt_handler(int irq, void *context) 1244 { 1245 struct hif_softc *scn = context; 1246 1247 HIF_INFO("wake interrupt received on irq %d", irq); 1248 1249 if (scn->initial_wakeup_cb) 1250 scn->initial_wakeup_cb(scn->initial_wakeup_priv); 1251 1252 if (hif_is_ut_suspended(scn)) 1253 hif_ut_fw_resume(scn); 1254 1255 return IRQ_HANDLED; 1256 } 1257 #else /* 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 return IRQ_HANDLED; 1268 } 1269 #endif /* WLAN_SUSPEND_RESUME_TEST */ 1270 1271 void hif_set_initial_wakeup_cb(struct hif_opaque_softc *hif_ctx, 1272 void (*callback)(void *), 1273 void *priv) 1274 { 1275 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 1276 1277 scn->initial_wakeup_cb = callback; 1278 scn->initial_wakeup_priv = priv; 1279 } 1280 1281 void hif_set_ce_service_max_yield_time(struct hif_opaque_softc *hif, 1282 uint32_t ce_service_max_yield_time) 1283 { 1284 struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif); 1285 1286 hif_ctx->ce_service_max_yield_time = 1287 ce_service_max_yield_time * 1000; 1288 } 1289 1290 unsigned long long 1291 hif_get_ce_service_max_yield_time(struct hif_opaque_softc *hif) 1292 { 1293 struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif); 1294 1295 return hif_ctx->ce_service_max_yield_time; 1296 } 1297 1298 void hif_set_ce_service_max_rx_ind_flush(struct hif_opaque_softc *hif, 1299 uint8_t ce_service_max_rx_ind_flush) 1300 { 1301 struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif); 1302 1303 if (ce_service_max_rx_ind_flush == 0 || 1304 ce_service_max_rx_ind_flush > MSG_FLUSH_NUM) 1305 hif_ctx->ce_service_max_rx_ind_flush = MSG_FLUSH_NUM; 1306 else 1307 hif_ctx->ce_service_max_rx_ind_flush = 1308 ce_service_max_rx_ind_flush; 1309 } 1310