1 /* 2 * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <linux/slab.h> 18 #include <linux/interrupt.h> 19 #include <linux/if_arp.h> 20 #ifdef CONFIG_PCI_MSM 21 #include <linux/msm_pcie.h> 22 #endif 23 #include "hif_io32.h" 24 #include "if_ipci.h" 25 #include "hif.h" 26 #include "target_type.h" 27 #include "hif_main.h" 28 #include "ce_main.h" 29 #include "ce_api.h" 30 #include "ce_internal.h" 31 #include "ce_reg.h" 32 #include "ce_bmi.h" 33 #include "regtable.h" 34 #include "hif_hw_version.h" 35 #include <linux/debugfs.h> 36 #include <linux/seq_file.h> 37 #include "qdf_status.h" 38 #include "qdf_atomic.h" 39 #include "pld_common.h" 40 #include "mp_dev.h" 41 #include "hif_debug.h" 42 43 #include "ce_tasklet.h" 44 #include "targaddrs.h" 45 #include "hif_exec.h" 46 47 #include "ipci_api.h" 48 49 #ifdef FEATURE_RUNTIME_PM 50 inline struct hif_runtime_pm_ctx *hif_ipci_get_rpm_ctx(struct hif_softc *scn) 51 { 52 struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(scn); 53 54 return &sc->rpm_ctx; 55 } 56 57 inline struct device *hif_ipci_get_dev(struct hif_softc *scn) 58 { 59 struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(scn); 60 61 return sc->dev; 62 } 63 #endif 64 65 void hif_ipci_enable_power_management(struct hif_softc *hif_sc, 66 bool is_packet_log_enabled) 67 { 68 hif_pm_runtime_start(hif_sc); 69 } 70 71 void hif_ipci_disable_power_management(struct hif_softc *hif_ctx) 72 { 73 hif_pm_runtime_stop(hif_ctx); 74 } 75 76 void hif_ipci_display_stats(struct hif_softc *hif_ctx) 77 { 78 hif_display_ce_stats(hif_ctx); 79 } 80 81 void hif_ipci_clear_stats(struct hif_softc *hif_ctx) 82 { 83 struct hif_ipci_softc *ipci_ctx = HIF_GET_IPCI_SOFTC(hif_ctx); 84 85 if (!ipci_ctx) { 86 HIF_ERROR("%s, hif_ctx null", __func__); 87 return; 88 } 89 hif_clear_ce_stats(&ipci_ctx->ce_sc); 90 } 91 92 QDF_STATUS hif_ipci_open(struct hif_softc *hif_ctx, enum qdf_bus_type bus_type) 93 { 94 struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(hif_ctx); 95 96 hif_ctx->bus_type = bus_type; 97 hif_pm_runtime_open(hif_ctx); 98 99 qdf_spinlock_create(&sc->irq_lock); 100 101 return hif_ce_open(hif_ctx); 102 } 103 104 /** 105 * hif_ce_msi_map_ce_to_irq() - map CE to IRQ 106 * @scn: hif context 107 * @ce_id: CE Id 108 * 109 * Return: IRQ number 110 */ 111 static int hif_ce_msi_map_ce_to_irq(struct hif_softc *scn, int ce_id) 112 { 113 struct hif_ipci_softc *ipci_scn = HIF_GET_IPCI_SOFTC(scn); 114 115 return ipci_scn->ce_msi_irq_num[ce_id]; 116 } 117 118 int hif_ipci_bus_configure(struct hif_softc *hif_sc) 119 { 120 int status = 0; 121 struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_sc); 122 uint8_t wake_ce_id; 123 124 hif_ce_prepare_config(hif_sc); 125 126 /* initialize sleep state adjust variables */ 127 hif_state->sleep_timer_init = true; 128 hif_state->keep_awake_count = 0; 129 hif_state->fake_sleep = false; 130 hif_state->sleep_ticks = 0; 131 132 status = hif_wlan_enable(hif_sc); 133 if (status) { 134 HIF_ERROR("%s: hif_wlan_enable error = %d", 135 __func__, status); 136 goto timer_free; 137 } 138 139 A_TARGET_ACCESS_LIKELY(hif_sc); 140 141 status = hif_config_ce(hif_sc); 142 if (status) 143 goto disable_wlan; 144 145 status = hif_get_wake_ce_id(hif_sc, &wake_ce_id); 146 if (status) 147 goto unconfig_ce; 148 149 status = hif_configure_irq(hif_sc); 150 if (status < 0) 151 goto unconfig_ce; 152 153 hif_sc->wake_irq = hif_ce_msi_map_ce_to_irq(hif_sc, wake_ce_id); 154 155 HIF_INFO("expecting wake from ce %d, irq %d", 156 wake_ce_id, hif_sc->wake_irq); 157 158 A_TARGET_ACCESS_UNLIKELY(hif_sc); 159 160 return status; 161 162 unconfig_ce: 163 hif_unconfig_ce(hif_sc); 164 disable_wlan: 165 A_TARGET_ACCESS_UNLIKELY(hif_sc); 166 hif_wlan_disable(hif_sc); 167 168 timer_free: 169 qdf_timer_stop(&hif_state->sleep_timer); 170 qdf_timer_free(&hif_state->sleep_timer); 171 hif_state->sleep_timer_init = false; 172 173 HIF_ERROR("%s: failed, status = %d", __func__, status); 174 return status; 175 } 176 177 void hif_ipci_close(struct hif_softc *hif_sc) 178 { 179 hif_pm_runtime_close(hif_sc); 180 hif_ce_close(hif_sc); 181 } 182 183 /** 184 * hif_ce_srng_msi_free_irq(): free CE msi IRQ 185 * @scn: struct hif_softc 186 * 187 * Return: ErrorNo 188 */ 189 static int hif_ce_srng_msi_free_irq(struct hif_softc *scn) 190 { 191 int ret; 192 int ce_id, irq; 193 uint32_t msi_data_start; 194 uint32_t msi_data_count; 195 uint32_t msi_irq_start; 196 struct HIF_CE_state *ce_sc = HIF_GET_CE_STATE(scn); 197 198 ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE", 199 &msi_data_count, &msi_data_start, 200 &msi_irq_start); 201 if (ret) 202 return ret; 203 204 /* needs to match the ce_id -> irq data mapping 205 * used in the srng parameter configuration 206 */ 207 for (ce_id = 0; ce_id < scn->ce_count; ce_id++) { 208 unsigned int msi_data; 209 210 if (!ce_sc->tasklets[ce_id].inited) 211 continue; 212 213 msi_data = (ce_id % msi_data_count) + msi_irq_start; 214 irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data); 215 216 hif_debug("%s: (ce_id %d, msi_data %d, irq %d)", __func__, 217 ce_id, msi_data, irq); 218 219 pfrm_free_irq(scn->qdf_dev->dev, irq, &ce_sc->tasklets[ce_id]); 220 } 221 222 return ret; 223 } 224 225 /** 226 * hif_ipci_deconfigure_grp_irq(): deconfigure HW block IRQ 227 * @scn: struct hif_softc 228 * 229 * Return: none 230 */ 231 static void hif_ipci_deconfigure_grp_irq(struct hif_softc *scn) 232 { 233 int i, j, irq; 234 struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); 235 struct hif_exec_context *hif_ext_group; 236 237 for (i = 0; i < hif_state->hif_num_extgroup; i++) { 238 hif_ext_group = hif_state->hif_ext_group[i]; 239 if (hif_ext_group->irq_requested) { 240 hif_ext_group->irq_requested = false; 241 for (j = 0; j < hif_ext_group->numirq; j++) { 242 irq = hif_ext_group->os_irq[j]; 243 pfrm_free_irq(scn->qdf_dev->dev, 244 irq, hif_ext_group); 245 } 246 hif_ext_group->numirq = 0; 247 } 248 } 249 } 250 251 void hif_ipci_nointrs(struct hif_softc *scn) 252 { 253 int ret; 254 struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); 255 256 ce_unregister_irq(hif_state, CE_ALL_BITMAP); 257 258 if (scn->request_irq_done == false) 259 return; 260 261 hif_ipci_deconfigure_grp_irq(scn); 262 263 ret = hif_ce_srng_msi_free_irq(scn); 264 265 scn->request_irq_done = false; 266 } 267 268 void hif_ipci_disable_bus(struct hif_softc *scn) 269 { 270 struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(scn); 271 void __iomem *mem; 272 273 /* Attach did not succeed, all resources have been 274 * freed in error handler 275 */ 276 if (!sc) 277 return; 278 279 mem = (void __iomem *)sc->mem; 280 if (mem) { 281 hif_dump_pipe_debug_count(scn); 282 if (scn->athdiag_procfs_inited) { 283 athdiag_procfs_remove(); 284 scn->athdiag_procfs_inited = false; 285 } 286 scn->mem = NULL; 287 } 288 HIF_INFO("%s: X", __func__); 289 } 290 291 #if defined(CONFIG_PCI_MSM) 292 void hif_ipci_prevent_linkdown(struct hif_softc *scn, bool flag) 293 { 294 int errno; 295 296 HIF_INFO("wlan: %s pcie power collapse", flag ? "disable" : "enable"); 297 hif_runtime_prevent_linkdown(scn, flag); 298 299 errno = pld_wlan_pm_control(scn->qdf_dev->dev, flag); 300 if (errno) 301 HIF_ERROR("%s: Failed pld_wlan_pm_control; errno %d", 302 __func__, errno); 303 } 304 #else 305 void hif_ipci_prevent_linkdown(struct hif_softc *scn, bool flag) 306 { 307 HIF_INFO("wlan: %s pcie power collapse", (flag ? "disable" : "enable")); 308 hif_runtime_prevent_linkdown(scn, flag); 309 } 310 #endif 311 312 int hif_ipci_bus_suspend(struct hif_softc *scn) 313 { 314 return hif_apps_enable_irq_wake(GET_HIF_OPAQUE_HDL(scn)); 315 } 316 317 int hif_ipci_bus_resume(struct hif_softc *scn) 318 { 319 return hif_apps_disable_irq_wake(GET_HIF_OPAQUE_HDL(scn)); 320 } 321 322 int hif_ipci_bus_suspend_noirq(struct hif_softc *scn) 323 { 324 QDF_STATUS ret; 325 326 ret = hif_try_complete_tasks(scn); 327 if (QDF_IS_STATUS_ERROR(ret)) 328 return -EBUSY; 329 330 return 0; 331 } 332 333 int hif_ipci_bus_resume_noirq(struct hif_softc *scn) 334 { 335 return 0; 336 } 337 338 void hif_ipci_disable_isr(struct hif_softc *scn) 339 { 340 struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(scn); 341 342 hif_exec_kill(&scn->osc); 343 hif_nointrs(scn); 344 /* Cancel the pending tasklet */ 345 ce_tasklet_kill(scn); 346 tasklet_kill(&sc->intr_tq); 347 qdf_atomic_set(&scn->active_tasklet_cnt, 0); 348 qdf_atomic_set(&scn->active_grp_tasklet_cnt, 0); 349 } 350 351 int hif_ipci_dump_registers(struct hif_softc *hif_ctx) 352 { 353 int status; 354 struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); 355 356 status = hif_dump_ce_registers(scn); 357 358 if (status) 359 HIF_ERROR("%s: Dump CE Registers Failed", __func__); 360 361 return 0; 362 } 363 364 /** 365 * hif_ce_interrupt_handler() - interrupt handler for copy engine 366 * @irq: irq number 367 * @context: tasklet context 368 * 369 * Return: irqreturn_t 370 */ 371 static irqreturn_t hif_ce_interrupt_handler(int irq, void *context) 372 { 373 struct ce_tasklet_entry *tasklet_entry = context; 374 375 hif_pm_runtime_check_and_request_resume( 376 GET_HIF_OPAQUE_HDL(tasklet_entry->hif_ce_state)); 377 return ce_dispatch_interrupt(tasklet_entry->ce_id, tasklet_entry); 378 } 379 380 extern const char *ce_name[]; 381 382 /* hif_ce_srng_msi_irq_disable() - disable the irq for msi 383 * @hif_sc: hif context 384 * @ce_id: which ce to disable copy complete interrupts for 385 * 386 * @Return: none 387 */ 388 static void hif_ce_srng_msi_irq_disable(struct hif_softc *hif_sc, int ce_id) 389 { 390 pfrm_disable_irq_nosync(hif_sc->qdf_dev->dev, 391 hif_ce_msi_map_ce_to_irq(hif_sc, ce_id)); 392 393 } 394 395 /* hif_ce_srng_msi_irq_enable() - enable the irq for msi 396 * @hif_sc: hif context 397 * @ce_id: which ce to enable copy complete interrupts for 398 * 399 * @Return: none 400 */ 401 static void hif_ce_srng_msi_irq_enable(struct hif_softc *hif_sc, int ce_id) 402 { 403 pfrm_enable_irq(hif_sc->qdf_dev->dev, 404 hif_ce_msi_map_ce_to_irq(hif_sc, ce_id)); 405 406 } 407 408 /* hif_ce_msi_configure_irq() - configure the irq 409 * @scn: hif context 410 * 411 * @Return: none 412 */ 413 static int hif_ce_msi_configure_irq(struct hif_softc *scn) 414 { 415 int ret; 416 int ce_id, irq; 417 uint32_t msi_data_start; 418 uint32_t msi_data_count; 419 uint32_t msi_irq_start; 420 struct HIF_CE_state *ce_sc = HIF_GET_CE_STATE(scn); 421 struct hif_ipci_softc *ipci_sc = HIF_GET_IPCI_SOFTC(scn); 422 uint8_t wake_ce_id; 423 424 ret = hif_get_wake_ce_id(scn, &wake_ce_id); 425 if (ret) 426 return ret; 427 428 /* do ce irq assignments */ 429 ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE", 430 &msi_data_count, &msi_data_start, 431 &msi_irq_start); 432 if (ret) 433 return ret; 434 435 scn->bus_ops.hif_irq_disable = &hif_ce_srng_msi_irq_disable; 436 scn->bus_ops.hif_irq_enable = &hif_ce_srng_msi_irq_enable; 437 scn->bus_ops.hif_map_ce_to_irq = &hif_ce_msi_map_ce_to_irq; 438 439 /* needs to match the ce_id -> irq data mapping 440 * used in the srng parameter configuration 441 */ 442 for (ce_id = 0; ce_id < scn->ce_count; ce_id++) { 443 unsigned long irqflags = IRQF_SHARED; 444 unsigned int msi_data = (ce_id % msi_data_count) + 445 msi_irq_start; 446 irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data); 447 HIF_DBG("%s: (ce_id %d, msi_data %d, irq %d tasklet %pK)", 448 __func__, ce_id, msi_data, irq, 449 &ce_sc->tasklets[ce_id]); 450 451 /* implies the ce is also initialized */ 452 if (!ce_sc->tasklets[ce_id].inited) 453 continue; 454 455 ipci_sc->ce_msi_irq_num[ce_id] = irq; 456 ret = pfrm_request_irq(scn->qdf_dev->dev, 457 irq, hif_ce_interrupt_handler, 458 irqflags, 459 ce_name[ce_id], 460 &ce_sc->tasklets[ce_id]); 461 if (ret) 462 goto free_irq; 463 } 464 465 return ret; 466 467 free_irq: 468 /* the request_irq for the last ce_id failed so skip it. */ 469 while (ce_id > 0 && ce_id < scn->ce_count) { 470 unsigned int msi_data; 471 472 ce_id--; 473 msi_data = (ce_id % msi_data_count) + msi_irq_start; 474 irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data); 475 pfrm_free_irq(scn->qdf_dev->dev, irq, &ce_sc->tasklets[ce_id]); 476 } 477 478 return ret; 479 } 480 481 /** 482 * hif_exec_grp_irq_disable() - disable the irq for group 483 * @hif_ext_group: hif exec context 484 * 485 * Return: none 486 */ 487 static void hif_exec_grp_irq_disable(struct hif_exec_context *hif_ext_group) 488 { 489 int i; 490 struct hif_softc *scn = HIF_GET_SOFTC(hif_ext_group->hif); 491 492 for (i = 0; i < hif_ext_group->numirq; i++) 493 pfrm_disable_irq_nosync(scn->qdf_dev->dev, 494 hif_ext_group->os_irq[i]); 495 } 496 497 /** 498 * hif_exec_grp_irq_enable() - enable the irq for group 499 * @hif_ext_group: hif exec context 500 * 501 * Return: none 502 */ 503 static void hif_exec_grp_irq_enable(struct hif_exec_context *hif_ext_group) 504 { 505 int i; 506 struct hif_softc *scn = HIF_GET_SOFTC(hif_ext_group->hif); 507 508 for (i = 0; i < hif_ext_group->numirq; i++) 509 pfrm_enable_irq(scn->qdf_dev->dev, hif_ext_group->os_irq[i]); 510 } 511 512 const char *hif_ipci_get_irq_name(int irq_no) 513 { 514 return "pci-dummy"; 515 } 516 517 int hif_ipci_configure_grp_irq(struct hif_softc *scn, 518 struct hif_exec_context *hif_ext_group) 519 { 520 int ret = 0; 521 int irq = 0; 522 int j; 523 524 hif_ext_group->irq_enable = &hif_exec_grp_irq_enable; 525 hif_ext_group->irq_disable = &hif_exec_grp_irq_disable; 526 hif_ext_group->irq_name = &hif_ipci_get_irq_name; 527 hif_ext_group->work_complete = &hif_dummy_grp_done; 528 529 for (j = 0; j < hif_ext_group->numirq; j++) { 530 irq = hif_ext_group->irq[j]; 531 532 hif_info("request_irq = %d for grp %d", 533 irq, hif_ext_group->grp_id); 534 ret = pfrm_request_irq(scn->qdf_dev->dev, irq, 535 hif_ext_group_interrupt_handler, 536 IRQF_SHARED | IRQF_NO_SUSPEND, 537 "wlan_EXT_GRP", 538 hif_ext_group); 539 if (ret) { 540 HIF_ERROR("%s: request_irq failed ret = %d", 541 __func__, ret); 542 return -EFAULT; 543 } 544 hif_ext_group->os_irq[j] = irq; 545 } 546 hif_ext_group->irq_requested = true; 547 return 0; 548 } 549 550 int hif_configure_irq(struct hif_softc *scn) 551 { 552 int ret = 0; 553 554 HIF_TRACE("%s: E", __func__); 555 556 if (hif_is_polled_mode_enabled(GET_HIF_OPAQUE_HDL(scn))) { 557 scn->request_irq_done = false; 558 return 0; 559 } 560 561 ret = hif_ce_msi_configure_irq(scn); 562 if (ret == 0) 563 goto end; 564 565 if (ret < 0) { 566 HIF_ERROR("%s: hif_ipci_configure_irq error = %d", 567 __func__, ret); 568 return ret; 569 } 570 end: 571 scn->request_irq_done = true; 572 return 0; 573 } 574 575 /** 576 * hif_ipci_get_soc_info_pld() - get soc info for ipcie bus from pld target 577 * @sc: ipci context 578 * @dev: device structure 579 * 580 * Return: none 581 */ 582 static void hif_ipci_get_soc_info_pld(struct hif_ipci_softc *sc, 583 struct device *dev) 584 { 585 struct pld_soc_info info; 586 587 pld_get_soc_info(dev, &info); 588 sc->mem = info.v_addr; 589 sc->ce_sc.ol_sc.mem = info.v_addr; 590 sc->ce_sc.ol_sc.mem_pa = info.p_addr; 591 } 592 593 /** 594 * hif_ipci_get_soc_info_nopld() - get soc info for ipcie bus for non pld target 595 * @sc: ipci context 596 * @dev: device structure 597 * 598 * Return: none 599 */ 600 static void hif_ipci_get_soc_info_nopld(struct hif_ipci_softc *sc, 601 struct device *dev) 602 {} 603 604 /** 605 * hif_is_pld_based_target() - verify if the target is pld based 606 * @sc: ipci context 607 * @device_id: device id 608 * 609 * Return: none 610 */ 611 static bool hif_is_pld_based_target(struct hif_ipci_softc *sc, 612 int device_id) 613 { 614 if (!pld_have_platform_driver_support(sc->dev)) 615 return false; 616 617 switch (device_id) { 618 #ifdef QCA_WIFI_QCA6750 619 case QCA6750_DEVICE_ID: 620 #endif 621 return true; 622 } 623 return false; 624 } 625 626 /** 627 * hif_ipci_init_deinit_ops_attach() - attach ops for ipci 628 * @sc: ipci context 629 * @device_id: device id 630 * 631 * Return: none 632 */ 633 static void hif_ipci_init_deinit_ops_attach(struct hif_ipci_softc *sc, 634 int device_id) 635 { 636 if (hif_is_pld_based_target(sc, device_id)) 637 sc->hif_ipci_get_soc_info = hif_ipci_get_soc_info_pld; 638 else 639 sc->hif_ipci_get_soc_info = hif_ipci_get_soc_info_nopld; 640 } 641 642 QDF_STATUS hif_ipci_enable_bus(struct hif_softc *ol_sc, 643 struct device *dev, void *bdev, 644 const struct hif_bus_id *bid, 645 enum hif_enable_type type) 646 { 647 int ret = 0; 648 uint32_t hif_type, target_type; 649 struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(ol_sc); 650 struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(ol_sc); 651 uint16_t revision_id = 0; 652 struct hif_target_info *tgt_info; 653 int device_id = QCA6750_DEVICE_ID; 654 655 if (!ol_sc) { 656 HIF_ERROR("%s: hif_ctx is NULL", __func__); 657 return QDF_STATUS_E_NOMEM; 658 } 659 660 ret = qdf_set_dma_coherent_mask(dev, 661 DMA_COHERENT_MASK_DEFAULT); 662 if (ret) { 663 HIF_ERROR("%s: failed to set dma mask error = %d", 664 __func__, ret); 665 return qdf_status_from_os_return(ret); 666 } 667 668 sc->dev = dev; 669 tgt_info = hif_get_target_info_handle(hif_hdl); 670 hif_ipci_init_deinit_ops_attach(sc, device_id); 671 sc->hif_ipci_get_soc_info(sc, dev); 672 HIF_TRACE("%s: hif_enable_pci done", __func__); 673 674 ret = hif_get_device_type(device_id, revision_id, 675 &hif_type, &target_type); 676 if (ret < 0) { 677 HIF_ERROR("%s: invalid device id/revision_id", __func__); 678 return QDF_STATUS_E_ABORTED; 679 } 680 HIF_TRACE("%s: hif_type = 0x%x, target_type = 0x%x", 681 __func__, hif_type, target_type); 682 683 hif_register_tbl_attach(ol_sc, hif_type); 684 hif_target_register_tbl_attach(ol_sc, target_type); 685 sc->use_register_windowing = false; 686 tgt_info->target_type = target_type; 687 688 if (!ol_sc->mem_pa) { 689 HIF_ERROR("%s: ERROR - BAR0 uninitialized", __func__); 690 return QDF_STATUS_E_ABORTED; 691 } 692 693 return QDF_STATUS_SUCCESS; 694 } 695 696 bool hif_ipci_needs_bmi(struct hif_softc *scn) 697 { 698 return !ce_srng_based(scn); 699 } 700 701 #ifdef FORCE_WAKE 702 int hif_force_wake_request(struct hif_opaque_softc *hif_handle) 703 { 704 uint32_t timeout = 0; 705 struct hif_softc *scn = (struct hif_softc *)hif_handle; 706 struct hif_ipci_softc *ipci_scn = HIF_GET_IPCI_SOFTC(scn); 707 708 if (pld_force_wake_request(scn->qdf_dev->dev)) { 709 hif_err("force wake request send failed"); 710 return -EINVAL; 711 } 712 713 HIF_STATS_INC(ipci_scn, mhi_force_wake_request_vote, 1); 714 while (!pld_is_device_awake(scn->qdf_dev->dev) && 715 timeout <= FORCE_WAKE_DELAY_TIMEOUT_MS) { 716 qdf_mdelay(FORCE_WAKE_DELAY_MS); 717 timeout += FORCE_WAKE_DELAY_MS; 718 } 719 720 if (pld_is_device_awake(scn->qdf_dev->dev) <= 0) { 721 hif_err("Unable to wake up mhi"); 722 HIF_STATS_INC(ipci_scn, mhi_force_wake_failure, 1); 723 return -EINVAL; 724 } 725 HIF_STATS_INC(ipci_scn, mhi_force_wake_success, 1); 726 727 HIF_STATS_INC(ipci_scn, soc_force_wake_success, 1); 728 729 return 0; 730 } 731 732 int hif_force_wake_release(struct hif_opaque_softc *hif_handle) 733 { 734 int ret; 735 struct hif_softc *scn = (struct hif_softc *)hif_handle; 736 struct hif_ipci_softc *ipci_scn = HIF_GET_IPCI_SOFTC(scn); 737 738 ret = pld_force_wake_release(scn->qdf_dev->dev); 739 if (ret) { 740 hif_err("force wake release failure"); 741 HIF_STATS_INC(ipci_scn, mhi_force_wake_release_failure, 1); 742 return ret; 743 } 744 745 HIF_STATS_INC(ipci_scn, mhi_force_wake_release_success, 1); 746 747 HIF_STATS_INC(ipci_scn, soc_force_wake_release_success, 1); 748 return 0; 749 } 750 751 void hif_print_ipci_stats(struct hif_ipci_softc *ipci_handle) 752 { 753 hif_debug("mhi_force_wake_request_vote: %d", 754 ipci_handle->stats.mhi_force_wake_request_vote); 755 hif_debug("mhi_force_wake_failure: %d", 756 ipci_handle->stats.mhi_force_wake_failure); 757 hif_debug("mhi_force_wake_success: %d", 758 ipci_handle->stats.mhi_force_wake_success); 759 hif_debug("soc_force_wake_register_write_success: %d", 760 ipci_handle->stats.soc_force_wake_register_write_success); 761 hif_debug("soc_force_wake_failure: %d", 762 ipci_handle->stats.soc_force_wake_failure); 763 hif_debug("soc_force_wake_success: %d", 764 ipci_handle->stats.soc_force_wake_success); 765 hif_debug("mhi_force_wake_release_failure: %d", 766 ipci_handle->stats.mhi_force_wake_release_failure); 767 hif_debug("mhi_force_wake_release_success: %d", 768 ipci_handle->stats.mhi_force_wake_release_success); 769 hif_debug("oc_force_wake_release_success: %d", 770 ipci_handle->stats.soc_force_wake_release_success); 771 } 772 #endif /* FORCE_WAKE */ 773