1 /* 2 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. 3 * Copyright (c) 2018, The Linux Foundation. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <linux/module.h> 19 #include <linux/pci.h> 20 #include <linux/moduleparam.h> 21 #include <linux/interrupt.h> 22 #include <linux/suspend.h> 23 #include "wil6210.h" 24 #include <linux/rtnetlink.h> 25 #include <linux/pm_runtime.h> 26 27 static int n_msi = 3; 28 module_param(n_msi, int, 0444); 29 MODULE_PARM_DESC(n_msi, " Use MSI interrupt: 0 - use INTx, 1 - single, or 3 - (default) "); 30 31 bool ftm_mode; 32 module_param(ftm_mode, bool, 0444); 33 MODULE_PARM_DESC(ftm_mode, " Set factory test mode, default - false"); 34 35 static int wil6210_pm_notify(struct notifier_block *notify_block, 36 unsigned long mode, void *unused); 37 38 static 39 int wil_set_capabilities(struct wil6210_priv *wil) 40 { 41 const char *wil_fw_name; 42 u32 jtag_id = wil_r(wil, RGF_USER_JTAG_DEV_ID); 43 u8 chip_revision = (wil_r(wil, RGF_USER_REVISION_ID) & 44 RGF_USER_REVISION_ID_MASK); 45 int platform_capa; 46 struct fw_map *iccm_section, *sct; 47 48 bitmap_zero(wil->hw_capa, hw_capa_last); 49 bitmap_zero(wil->fw_capabilities, WMI_FW_CAPABILITY_MAX); 50 bitmap_zero(wil->platform_capa, WIL_PLATFORM_CAPA_MAX); 51 wil->wil_fw_name = ftm_mode ? WIL_FW_NAME_FTM_DEFAULT : 52 WIL_FW_NAME_DEFAULT; 53 wil->chip_revision = chip_revision; 54 55 switch (jtag_id) { 56 case JTAG_DEV_ID_SPARROW: 57 memcpy(fw_mapping, sparrow_fw_mapping, 58 sizeof(sparrow_fw_mapping)); 59 switch (chip_revision) { 60 case REVISION_ID_SPARROW_D0: 61 wil->hw_name = "Sparrow D0"; 62 wil->hw_version = HW_VER_SPARROW_D0; 63 wil_fw_name = ftm_mode ? WIL_FW_NAME_FTM_SPARROW_PLUS : 64 WIL_FW_NAME_SPARROW_PLUS; 65 66 if (wil_fw_verify_file_exists(wil, wil_fw_name)) 67 wil->wil_fw_name = wil_fw_name; 68 sct = wil_find_fw_mapping("mac_rgf_ext"); 69 if (!sct) { 70 wil_err(wil, "mac_rgf_ext section not found in fw_mapping\n"); 71 return -EINVAL; 72 } 73 memcpy(sct, &sparrow_d0_mac_rgf_ext, sizeof(*sct)); 74 break; 75 case REVISION_ID_SPARROW_B0: 76 wil->hw_name = "Sparrow B0"; 77 wil->hw_version = HW_VER_SPARROW_B0; 78 break; 79 default: 80 wil->hw_name = "Unknown"; 81 wil->hw_version = HW_VER_UNKNOWN; 82 break; 83 } 84 wil->rgf_fw_assert_code_addr = SPARROW_RGF_FW_ASSERT_CODE; 85 wil->rgf_ucode_assert_code_addr = SPARROW_RGF_UCODE_ASSERT_CODE; 86 break; 87 case JTAG_DEV_ID_TALYN: 88 wil->hw_name = "Talyn-MA"; 89 wil->hw_version = HW_VER_TALYN; 90 memcpy(fw_mapping, talyn_fw_mapping, sizeof(talyn_fw_mapping)); 91 wil->rgf_fw_assert_code_addr = TALYN_RGF_FW_ASSERT_CODE; 92 wil->rgf_ucode_assert_code_addr = TALYN_RGF_UCODE_ASSERT_CODE; 93 if (wil_r(wil, RGF_USER_OTP_HW_RD_MACHINE_1) & 94 BIT_NO_FLASH_INDICATION) 95 set_bit(hw_capa_no_flash, wil->hw_capa); 96 wil_fw_name = ftm_mode ? WIL_FW_NAME_FTM_TALYN : 97 WIL_FW_NAME_TALYN; 98 if (wil_fw_verify_file_exists(wil, wil_fw_name)) 99 wil->wil_fw_name = wil_fw_name; 100 break; 101 case JTAG_DEV_ID_TALYN_MB: 102 wil->hw_name = "Talyn-MB"; 103 wil->hw_version = HW_VER_TALYN_MB; 104 memcpy(fw_mapping, talyn_mb_fw_mapping, 105 sizeof(talyn_mb_fw_mapping)); 106 wil->rgf_fw_assert_code_addr = TALYN_RGF_FW_ASSERT_CODE; 107 wil->rgf_ucode_assert_code_addr = TALYN_RGF_UCODE_ASSERT_CODE; 108 set_bit(hw_capa_no_flash, wil->hw_capa); 109 wil->use_enhanced_dma_hw = true; 110 wil->use_rx_hw_reordering = true; 111 wil_fw_name = ftm_mode ? WIL_FW_NAME_FTM_TALYN : 112 WIL_FW_NAME_TALYN; 113 if (wil_fw_verify_file_exists(wil, wil_fw_name)) 114 wil->wil_fw_name = wil_fw_name; 115 break; 116 default: 117 wil_err(wil, "Unknown board hardware, chip_id 0x%08x, chip_revision 0x%08x\n", 118 jtag_id, chip_revision); 119 wil->hw_name = "Unknown"; 120 wil->hw_version = HW_VER_UNKNOWN; 121 return -EINVAL; 122 } 123 124 wil_init_txrx_ops(wil); 125 126 iccm_section = wil_find_fw_mapping("fw_code"); 127 if (!iccm_section) { 128 wil_err(wil, "fw_code section not found in fw_mapping\n"); 129 return -EINVAL; 130 } 131 wil->iccm_base = iccm_section->host; 132 133 wil_info(wil, "Board hardware is %s, flash %sexist\n", wil->hw_name, 134 test_bit(hw_capa_no_flash, wil->hw_capa) ? "doesn't " : ""); 135 136 /* Get platform capabilities */ 137 if (wil->platform_ops.get_capa) { 138 platform_capa = 139 wil->platform_ops.get_capa(wil->platform_handle); 140 memcpy(wil->platform_capa, &platform_capa, 141 min(sizeof(wil->platform_capa), sizeof(platform_capa))); 142 } 143 144 /* extract FW capabilities from file without loading the FW */ 145 wil_request_firmware(wil, wil->wil_fw_name, false); 146 wil_refresh_fw_capabilities(wil); 147 148 return 0; 149 } 150 151 void wil_disable_irq(struct wil6210_priv *wil) 152 { 153 int irq = wil->pdev->irq; 154 155 disable_irq(irq); 156 if (wil->n_msi == 3) { 157 disable_irq(irq + 1); 158 disable_irq(irq + 2); 159 } 160 } 161 162 void wil_enable_irq(struct wil6210_priv *wil) 163 { 164 int irq = wil->pdev->irq; 165 166 enable_irq(irq); 167 if (wil->n_msi == 3) { 168 enable_irq(irq + 1); 169 enable_irq(irq + 2); 170 } 171 } 172 173 static void wil_remove_all_additional_vifs(struct wil6210_priv *wil) 174 { 175 struct wil6210_vif *vif; 176 int i; 177 178 for (i = 1; i < wil->max_vifs; i++) { 179 vif = wil->vifs[i]; 180 if (vif) { 181 wil_vif_prepare_stop(vif); 182 wil_vif_remove(wil, vif->mid); 183 } 184 } 185 } 186 187 /* Bus ops */ 188 static int wil_if_pcie_enable(struct wil6210_priv *wil) 189 { 190 struct pci_dev *pdev = wil->pdev; 191 int rc; 192 /* on platforms with buggy ACPI, pdev->msi_enabled may be set to 193 * allow pci_enable_device to work. This indicates INTx was not routed 194 * and only MSI should be used 195 */ 196 int msi_only = pdev->msi_enabled; 197 198 wil_dbg_misc(wil, "if_pcie_enable\n"); 199 200 pci_set_master(pdev); 201 202 /* how many MSI interrupts to request? */ 203 switch (n_msi) { 204 case 3: 205 case 1: 206 wil_dbg_misc(wil, "Setup %d MSI interrupts\n", n_msi); 207 break; 208 case 0: 209 wil_dbg_misc(wil, "MSI interrupts disabled, use INTx\n"); 210 break; 211 default: 212 wil_err(wil, "Invalid n_msi=%d, default to 1\n", n_msi); 213 n_msi = 1; 214 } 215 216 if (n_msi == 3 && 217 pci_alloc_irq_vectors(pdev, n_msi, n_msi, PCI_IRQ_MSI) < n_msi) { 218 wil_err(wil, "3 MSI mode failed, try 1 MSI\n"); 219 n_msi = 1; 220 } 221 222 if (n_msi == 1 && pci_enable_msi(pdev)) { 223 wil_err(wil, "pci_enable_msi failed, use INTx\n"); 224 n_msi = 0; 225 } 226 227 wil->n_msi = n_msi; 228 229 if (wil->n_msi == 0 && msi_only) { 230 wil_err(wil, "Interrupt pin not routed, unable to use INTx\n"); 231 rc = -ENODEV; 232 goto stop_master; 233 } 234 235 rc = wil6210_init_irq(wil, pdev->irq); 236 if (rc) 237 goto release_vectors; 238 239 /* need reset here to obtain MAC */ 240 mutex_lock(&wil->mutex); 241 rc = wil_reset(wil, false); 242 mutex_unlock(&wil->mutex); 243 if (rc) 244 goto release_irq; 245 246 return 0; 247 248 release_irq: 249 wil6210_fini_irq(wil, pdev->irq); 250 release_vectors: 251 /* safe to call if no allocation */ 252 pci_free_irq_vectors(pdev); 253 stop_master: 254 pci_clear_master(pdev); 255 return rc; 256 } 257 258 static int wil_if_pcie_disable(struct wil6210_priv *wil) 259 { 260 struct pci_dev *pdev = wil->pdev; 261 262 wil_dbg_misc(wil, "if_pcie_disable\n"); 263 264 pci_clear_master(pdev); 265 /* disable and release IRQ */ 266 wil6210_fini_irq(wil, pdev->irq); 267 /* safe to call if no MSI */ 268 pci_disable_msi(pdev); 269 /* TODO: disable HW */ 270 271 return 0; 272 } 273 274 static int wil_platform_rop_ramdump(void *wil_handle, void *buf, uint32_t size) 275 { 276 struct wil6210_priv *wil = wil_handle; 277 278 if (!wil) 279 return -EINVAL; 280 281 return wil_fw_copy_crash_dump(wil, buf, size); 282 } 283 284 static int wil_platform_rop_fw_recovery(void *wil_handle) 285 { 286 struct wil6210_priv *wil = wil_handle; 287 288 if (!wil) 289 return -EINVAL; 290 291 wil_fw_error_recovery(wil); 292 293 return 0; 294 } 295 296 static void wil_platform_ops_uninit(struct wil6210_priv *wil) 297 { 298 if (wil->platform_ops.uninit) 299 wil->platform_ops.uninit(wil->platform_handle); 300 memset(&wil->platform_ops, 0, sizeof(wil->platform_ops)); 301 } 302 303 static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) 304 { 305 struct wil6210_priv *wil; 306 struct device *dev = &pdev->dev; 307 int rc; 308 const struct wil_platform_rops rops = { 309 .ramdump = wil_platform_rop_ramdump, 310 .fw_recovery = wil_platform_rop_fw_recovery, 311 }; 312 u32 bar_size = pci_resource_len(pdev, 0); 313 int dma_addr_size[] = {64, 48, 40, 32}; /* keep descending order */ 314 int i, start_idx; 315 316 /* check HW */ 317 dev_info(&pdev->dev, WIL_NAME 318 " device found [%04x:%04x] (rev %x) bar size 0x%x\n", 319 (int)pdev->vendor, (int)pdev->device, (int)pdev->revision, 320 bar_size); 321 322 if ((bar_size < WIL6210_MIN_MEM_SIZE) || 323 (bar_size > WIL6210_MAX_MEM_SIZE)) { 324 dev_err(&pdev->dev, "Unexpected BAR0 size 0x%x\n", 325 bar_size); 326 return -ENODEV; 327 } 328 329 wil = wil_if_alloc(dev); 330 if (IS_ERR(wil)) { 331 rc = (int)PTR_ERR(wil); 332 dev_err(dev, "wil_if_alloc failed: %d\n", rc); 333 return rc; 334 } 335 336 wil->pdev = pdev; 337 pci_set_drvdata(pdev, wil); 338 wil->bar_size = bar_size; 339 /* rollback to if_free */ 340 341 wil->platform_handle = 342 wil_platform_init(&pdev->dev, &wil->platform_ops, &rops, wil); 343 if (!wil->platform_handle) { 344 rc = -ENODEV; 345 wil_err(wil, "wil_platform_init failed\n"); 346 goto if_free; 347 } 348 /* rollback to err_plat */ 349 rc = pci_enable_device(pdev); 350 if (rc && pdev->msi_enabled == 0) { 351 wil_err(wil, 352 "pci_enable_device failed, retry with MSI only\n"); 353 /* Work around for platforms that can't allocate IRQ: 354 * retry with MSI only 355 */ 356 pdev->msi_enabled = 1; 357 rc = pci_enable_device(pdev); 358 } 359 if (rc) { 360 wil_err(wil, 361 "pci_enable_device failed, even with MSI only\n"); 362 goto err_plat; 363 } 364 /* rollback to err_disable_pdev */ 365 pci_set_power_state(pdev, PCI_D0); 366 367 rc = pci_request_region(pdev, 0, WIL_NAME); 368 if (rc) { 369 wil_err(wil, "pci_request_region failed\n"); 370 goto err_disable_pdev; 371 } 372 /* rollback to err_release_reg */ 373 374 wil->csr = pci_ioremap_bar(pdev, 0); 375 if (!wil->csr) { 376 wil_err(wil, "pci_ioremap_bar failed\n"); 377 rc = -ENODEV; 378 goto err_release_reg; 379 } 380 /* rollback to err_iounmap */ 381 wil_info(wil, "CSR at %pR -> 0x%p\n", &pdev->resource[0], wil->csr); 382 383 rc = wil_set_capabilities(wil); 384 if (rc) { 385 wil_err(wil, "wil_set_capabilities failed, rc %d\n", rc); 386 goto err_iounmap; 387 } 388 389 /* device supports >32bit addresses. 390 * for legacy DMA start from 48 bit. 391 */ 392 start_idx = wil->use_enhanced_dma_hw ? 0 : 1; 393 394 for (i = start_idx; i < ARRAY_SIZE(dma_addr_size); i++) { 395 rc = dma_set_mask_and_coherent(dev, 396 DMA_BIT_MASK(dma_addr_size[i])); 397 if (rc) { 398 dev_err(dev, "dma_set_mask_and_coherent(%d) failed: %d\n", 399 dma_addr_size[i], rc); 400 continue; 401 } 402 dev_info(dev, "using dma mask %d", dma_addr_size[i]); 403 wil->dma_addr_size = dma_addr_size[i]; 404 break; 405 } 406 407 if (wil->dma_addr_size == 0) 408 goto err_iounmap; 409 410 wil6210_clear_irq(wil); 411 412 /* FW should raise IRQ when ready */ 413 rc = wil_if_pcie_enable(wil); 414 if (rc) { 415 wil_err(wil, "Enable device failed\n"); 416 goto err_iounmap; 417 } 418 /* rollback to bus_disable */ 419 420 rc = wil_if_add(wil); 421 if (rc) { 422 wil_err(wil, "wil_if_add failed: %d\n", rc); 423 goto bus_disable; 424 } 425 426 /* in case of WMI-only FW, perform full reset and FW loading */ 427 if (test_bit(WMI_FW_CAPABILITY_WMI_ONLY, wil->fw_capabilities)) { 428 wil_dbg_misc(wil, "Loading WMI only FW\n"); 429 mutex_lock(&wil->mutex); 430 rc = wil_reset(wil, true); 431 mutex_unlock(&wil->mutex); 432 if (rc) { 433 wil_err(wil, "failed to load WMI only FW\n"); 434 goto if_remove; 435 } 436 } 437 438 if (IS_ENABLED(CONFIG_PM)) 439 wil->pm_notify.notifier_call = wil6210_pm_notify; 440 441 rc = register_pm_notifier(&wil->pm_notify); 442 if (rc) 443 /* Do not fail the driver initialization, as suspend can 444 * be prevented in a later phase if needed 445 */ 446 wil_err(wil, "register_pm_notifier failed: %d\n", rc); 447 448 wil6210_debugfs_init(wil); 449 450 wil_pm_runtime_allow(wil); 451 452 return 0; 453 454 if_remove: 455 wil_if_remove(wil); 456 bus_disable: 457 wil_if_pcie_disable(wil); 458 err_iounmap: 459 pci_iounmap(pdev, wil->csr); 460 err_release_reg: 461 pci_release_region(pdev, 0); 462 err_disable_pdev: 463 pci_disable_device(pdev); 464 err_plat: 465 wil_platform_ops_uninit(wil); 466 if_free: 467 wil_if_free(wil); 468 469 return rc; 470 } 471 472 static void wil_pcie_remove(struct pci_dev *pdev) 473 { 474 struct wil6210_priv *wil = pci_get_drvdata(pdev); 475 void __iomem *csr = wil->csr; 476 477 wil_dbg_misc(wil, "pcie_remove\n"); 478 479 unregister_pm_notifier(&wil->pm_notify); 480 481 wil_pm_runtime_forbid(wil); 482 483 wil6210_debugfs_remove(wil); 484 rtnl_lock(); 485 wil_p2p_wdev_free(wil); 486 wil_remove_all_additional_vifs(wil); 487 rtnl_unlock(); 488 wil_if_remove(wil); 489 wil_if_pcie_disable(wil); 490 pci_iounmap(pdev, csr); 491 pci_release_region(pdev, 0); 492 pci_disable_device(pdev); 493 wil_platform_ops_uninit(wil); 494 wil_if_free(wil); 495 } 496 497 static const struct pci_device_id wil6210_pcie_ids[] = { 498 { PCI_DEVICE(0x1ae9, 0x0310) }, 499 { PCI_DEVICE(0x1ae9, 0x0302) }, /* same as above, firmware broken */ 500 { PCI_DEVICE(0x17cb, 0x1201) }, /* Talyn */ 501 { /* end: all zeroes */ }, 502 }; 503 MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); 504 505 static int wil6210_suspend(struct device *dev, bool is_runtime) 506 { 507 int rc = 0; 508 struct pci_dev *pdev = to_pci_dev(dev); 509 struct wil6210_priv *wil = pci_get_drvdata(pdev); 510 bool keep_radio_on, active_ifaces; 511 512 wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system"); 513 514 mutex_lock(&wil->vif_mutex); 515 active_ifaces = wil_has_active_ifaces(wil, true, false); 516 mutex_unlock(&wil->vif_mutex); 517 keep_radio_on = active_ifaces && wil->keep_radio_on_during_sleep; 518 519 rc = wil_can_suspend(wil, is_runtime); 520 if (rc) 521 goto out; 522 523 rc = wil_suspend(wil, is_runtime, keep_radio_on); 524 if (!rc) { 525 /* In case radio stays on, platform device will control 526 * PCIe master 527 */ 528 if (!keep_radio_on) { 529 /* disable bus mastering */ 530 pci_clear_master(pdev); 531 wil->suspend_stats.r_off.successful_suspends++; 532 } else { 533 wil->suspend_stats.r_on.successful_suspends++; 534 } 535 } 536 out: 537 return rc; 538 } 539 540 static int wil6210_resume(struct device *dev, bool is_runtime) 541 { 542 int rc = 0; 543 struct pci_dev *pdev = to_pci_dev(dev); 544 struct wil6210_priv *wil = pci_get_drvdata(pdev); 545 bool keep_radio_on, active_ifaces; 546 547 wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system"); 548 549 mutex_lock(&wil->vif_mutex); 550 active_ifaces = wil_has_active_ifaces(wil, true, false); 551 mutex_unlock(&wil->vif_mutex); 552 keep_radio_on = active_ifaces && wil->keep_radio_on_during_sleep; 553 554 /* In case radio stays on, platform device will control 555 * PCIe master 556 */ 557 if (!keep_radio_on) 558 /* allow master */ 559 pci_set_master(pdev); 560 rc = wil_resume(wil, is_runtime, keep_radio_on); 561 if (rc) { 562 wil_err(wil, "device failed to resume (%d)\n", rc); 563 if (!keep_radio_on) { 564 pci_clear_master(pdev); 565 wil->suspend_stats.r_off.failed_resumes++; 566 } else { 567 wil->suspend_stats.r_on.failed_resumes++; 568 } 569 } else { 570 if (keep_radio_on) 571 wil->suspend_stats.r_on.successful_resumes++; 572 else 573 wil->suspend_stats.r_off.successful_resumes++; 574 } 575 576 return rc; 577 } 578 579 static int wil6210_pm_notify(struct notifier_block *notify_block, 580 unsigned long mode, void *unused) 581 { 582 struct wil6210_priv *wil = container_of( 583 notify_block, struct wil6210_priv, pm_notify); 584 int rc = 0; 585 enum wil_platform_event evt; 586 587 wil_dbg_pm(wil, "pm_notify: mode (%ld)\n", mode); 588 589 switch (mode) { 590 case PM_HIBERNATION_PREPARE: 591 case PM_SUSPEND_PREPARE: 592 case PM_RESTORE_PREPARE: 593 rc = wil_can_suspend(wil, false); 594 if (rc) 595 break; 596 evt = WIL_PLATFORM_EVT_PRE_SUSPEND; 597 if (wil->platform_ops.notify) 598 rc = wil->platform_ops.notify(wil->platform_handle, 599 evt); 600 break; 601 case PM_POST_SUSPEND: 602 case PM_POST_HIBERNATION: 603 case PM_POST_RESTORE: 604 evt = WIL_PLATFORM_EVT_POST_SUSPEND; 605 if (wil->platform_ops.notify) 606 rc = wil->platform_ops.notify(wil->platform_handle, 607 evt); 608 break; 609 default: 610 wil_dbg_pm(wil, "unhandled notify mode %ld\n", mode); 611 break; 612 } 613 614 wil_dbg_pm(wil, "notification mode %ld: rc (%d)\n", mode, rc); 615 return rc; 616 } 617 618 static int __maybe_unused wil6210_pm_suspend(struct device *dev) 619 { 620 return wil6210_suspend(dev, false); 621 } 622 623 static int __maybe_unused wil6210_pm_resume(struct device *dev) 624 { 625 return wil6210_resume(dev, false); 626 } 627 628 static int __maybe_unused wil6210_pm_runtime_idle(struct device *dev) 629 { 630 struct pci_dev *pdev = to_pci_dev(dev); 631 struct wil6210_priv *wil = pci_get_drvdata(pdev); 632 633 wil_dbg_pm(wil, "Runtime idle\n"); 634 635 return wil_can_suspend(wil, true); 636 } 637 638 static int __maybe_unused wil6210_pm_runtime_resume(struct device *dev) 639 { 640 return wil6210_resume(dev, true); 641 } 642 643 static int __maybe_unused wil6210_pm_runtime_suspend(struct device *dev) 644 { 645 struct pci_dev *pdev = to_pci_dev(dev); 646 struct wil6210_priv *wil = pci_get_drvdata(pdev); 647 648 if (test_bit(wil_status_suspended, wil->status)) { 649 wil_dbg_pm(wil, "trying to suspend while suspended\n"); 650 return 1; 651 } 652 653 return wil6210_suspend(dev, true); 654 } 655 656 static const struct dev_pm_ops wil6210_pm_ops = { 657 SET_SYSTEM_SLEEP_PM_OPS(wil6210_pm_suspend, wil6210_pm_resume) 658 SET_RUNTIME_PM_OPS(wil6210_pm_runtime_suspend, 659 wil6210_pm_runtime_resume, 660 wil6210_pm_runtime_idle) 661 }; 662 663 static struct pci_driver wil6210_driver = { 664 .probe = wil_pcie_probe, 665 .remove = wil_pcie_remove, 666 .id_table = wil6210_pcie_ids, 667 .name = WIL_NAME, 668 .driver = { 669 .pm = &wil6210_pm_ops, 670 }, 671 }; 672 673 static int __init wil6210_driver_init(void) 674 { 675 int rc; 676 677 rc = wil_platform_modinit(); 678 if (rc) 679 return rc; 680 681 rc = pci_register_driver(&wil6210_driver); 682 if (rc) 683 wil_platform_modexit(); 684 return rc; 685 } 686 module_init(wil6210_driver_init); 687 688 static void __exit wil6210_driver_exit(void) 689 { 690 pci_unregister_driver(&wil6210_driver); 691 wil_platform_modexit(); 692 } 693 module_exit(wil6210_driver_exit); 694 695 MODULE_LICENSE("Dual BSD/GPL"); 696 MODULE_AUTHOR("Qualcomm Atheros <wil6210@qca.qualcomm.com>"); 697 MODULE_DESCRIPTION("Driver for 60g WiFi WIL6210 card"); 698