1 /* 2 * Copyright (c) 2012-2014 Qualcomm Atheros, Inc. 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/moduleparam.h> 18 #include <linux/if_arp.h> 19 #include <linux/etherdevice.h> 20 21 #include "wil6210.h" 22 #include "txrx.h" 23 #include "wmi.h" 24 25 #define WAIT_FOR_DISCONNECT_TIMEOUT_MS 2000 26 #define WAIT_FOR_DISCONNECT_INTERVAL_MS 10 27 28 static bool no_fw_recovery; 29 module_param(no_fw_recovery, bool, S_IRUGO | S_IWUSR); 30 MODULE_PARM_DESC(no_fw_recovery, " disable FW error recovery"); 31 32 static bool no_fw_load = true; 33 module_param(no_fw_load, bool, S_IRUGO | S_IWUSR); 34 MODULE_PARM_DESC(no_fw_load, " do not download FW, use one in on-card flash."); 35 36 #define RST_DELAY (20) /* msec, for loop in @wil_target_reset */ 37 #define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */ 38 39 /* 40 * Due to a hardware issue, 41 * one has to read/write to/from NIC in 32-bit chunks; 42 * regular memcpy_fromio and siblings will 43 * not work on 64-bit platform - it uses 64-bit transactions 44 * 45 * Force 32-bit transactions to enable NIC on 64-bit platforms 46 * 47 * To avoid byte swap on big endian host, __raw_{read|write}l 48 * should be used - {read|write}l would swap bytes to provide 49 * little endian on PCI value in host endianness. 50 */ 51 void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, 52 size_t count) 53 { 54 u32 *d = dst; 55 const volatile u32 __iomem *s = src; 56 57 /* size_t is unsigned, if (count%4 != 0) it will wrap */ 58 for (count += 4; count > 4; count -= 4) 59 *d++ = __raw_readl(s++); 60 } 61 62 void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, 63 size_t count) 64 { 65 volatile u32 __iomem *d = dst; 66 const u32 *s = src; 67 68 for (count += 4; count > 4; count -= 4) 69 __raw_writel(*s++, d++); 70 } 71 72 static void wil_disconnect_cid(struct wil6210_priv *wil, int cid) 73 { 74 uint i; 75 struct net_device *ndev = wil_to_ndev(wil); 76 struct wireless_dev *wdev = wil->wdev; 77 struct wil_sta_info *sta = &wil->sta[cid]; 78 79 wil_dbg_misc(wil, "%s(CID %d, status %d)\n", __func__, cid, 80 sta->status); 81 82 sta->data_port_open = false; 83 if (sta->status != wil_sta_unused) { 84 wmi_disconnect_sta(wil, sta->addr, WLAN_REASON_DEAUTH_LEAVING); 85 switch (wdev->iftype) { 86 case NL80211_IFTYPE_AP: 87 case NL80211_IFTYPE_P2P_GO: 88 /* AP-like interface */ 89 cfg80211_del_sta(ndev, sta->addr, GFP_KERNEL); 90 break; 91 default: 92 break; 93 } 94 sta->status = wil_sta_unused; 95 } 96 97 for (i = 0; i < WIL_STA_TID_NUM; i++) { 98 struct wil_tid_ampdu_rx *r; 99 unsigned long flags; 100 101 spin_lock_irqsave(&sta->tid_rx_lock, flags); 102 103 r = sta->tid_rx[i]; 104 sta->tid_rx[i] = NULL; 105 wil_tid_ampdu_rx_free(wil, r); 106 107 spin_unlock_irqrestore(&sta->tid_rx_lock, flags); 108 } 109 for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { 110 if (wil->vring2cid_tid[i][0] == cid) 111 wil_vring_fini_tx(wil, i); 112 } 113 memset(&sta->stats, 0, sizeof(sta->stats)); 114 } 115 116 static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) 117 { 118 int cid = -ENOENT; 119 struct net_device *ndev = wil_to_ndev(wil); 120 struct wireless_dev *wdev = wil->wdev; 121 122 might_sleep(); 123 if (bssid) { 124 cid = wil_find_cid(wil, bssid); 125 wil_dbg_misc(wil, "%s(%pM, CID %d)\n", __func__, bssid, cid); 126 } else { 127 wil_dbg_misc(wil, "%s(all)\n", __func__); 128 } 129 130 if (cid >= 0) /* disconnect 1 peer */ 131 wil_disconnect_cid(wil, cid); 132 else /* disconnect all */ 133 for (cid = 0; cid < WIL6210_MAX_CID; cid++) 134 wil_disconnect_cid(wil, cid); 135 136 /* link state */ 137 switch (wdev->iftype) { 138 case NL80211_IFTYPE_STATION: 139 case NL80211_IFTYPE_P2P_CLIENT: 140 wil_link_off(wil); 141 if (test_bit(wil_status_fwconnected, &wil->status)) { 142 clear_bit(wil_status_fwconnected, &wil->status); 143 cfg80211_disconnected(ndev, 144 WLAN_STATUS_UNSPECIFIED_FAILURE, 145 NULL, 0, GFP_KERNEL); 146 } else if (test_bit(wil_status_fwconnecting, &wil->status)) { 147 cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0, 148 WLAN_STATUS_UNSPECIFIED_FAILURE, 149 GFP_KERNEL); 150 } 151 clear_bit(wil_status_fwconnecting, &wil->status); 152 break; 153 default: 154 break; 155 } 156 } 157 158 static void wil_disconnect_worker(struct work_struct *work) 159 { 160 struct wil6210_priv *wil = container_of(work, 161 struct wil6210_priv, disconnect_worker); 162 163 mutex_lock(&wil->mutex); 164 _wil6210_disconnect(wil, NULL); 165 mutex_unlock(&wil->mutex); 166 } 167 168 static void wil_connect_timer_fn(ulong x) 169 { 170 struct wil6210_priv *wil = (void *)x; 171 172 wil_dbg_misc(wil, "Connect timeout\n"); 173 174 /* reschedule to thread context - disconnect won't 175 * run from atomic context 176 */ 177 schedule_work(&wil->disconnect_worker); 178 } 179 180 static void wil_scan_timer_fn(ulong x) 181 { 182 struct wil6210_priv *wil = (void *)x; 183 184 clear_bit(wil_status_fwready, &wil->status); 185 wil_err(wil, "Scan timeout detected, start fw error recovery\n"); 186 schedule_work(&wil->fw_error_worker); 187 } 188 189 static void wil_fw_error_worker(struct work_struct *work) 190 { 191 struct wil6210_priv *wil = container_of(work, 192 struct wil6210_priv, fw_error_worker); 193 struct wireless_dev *wdev = wil->wdev; 194 195 wil_dbg_misc(wil, "fw error worker\n"); 196 197 if (no_fw_recovery) 198 return; 199 200 /* increment @recovery_count if less then WIL6210_FW_RECOVERY_TO 201 * passed since last recovery attempt 202 */ 203 if (time_is_after_jiffies(wil->last_fw_recovery + 204 WIL6210_FW_RECOVERY_TO)) 205 wil->recovery_count++; 206 else 207 wil->recovery_count = 1; /* fw was alive for a long time */ 208 209 if (wil->recovery_count > WIL6210_FW_RECOVERY_RETRIES) { 210 wil_err(wil, "too many recovery attempts (%d), giving up\n", 211 wil->recovery_count); 212 return; 213 } 214 215 wil->last_fw_recovery = jiffies; 216 217 mutex_lock(&wil->mutex); 218 switch (wdev->iftype) { 219 case NL80211_IFTYPE_STATION: 220 case NL80211_IFTYPE_P2P_CLIENT: 221 case NL80211_IFTYPE_MONITOR: 222 wil_info(wil, "fw error recovery started (try %d)...\n", 223 wil->recovery_count); 224 wil_reset(wil); 225 226 /* need to re-allocate Rx ring after reset */ 227 wil_rx_init(wil); 228 break; 229 case NL80211_IFTYPE_AP: 230 case NL80211_IFTYPE_P2P_GO: 231 /* recovery in these modes is done by upper layers */ 232 break; 233 default: 234 break; 235 } 236 mutex_unlock(&wil->mutex); 237 } 238 239 static int wil_find_free_vring(struct wil6210_priv *wil) 240 { 241 int i; 242 243 for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { 244 if (!wil->vring_tx[i].va) 245 return i; 246 } 247 return -EINVAL; 248 } 249 250 static void wil_connect_worker(struct work_struct *work) 251 { 252 int rc; 253 struct wil6210_priv *wil = container_of(work, struct wil6210_priv, 254 connect_worker); 255 int cid = wil->pending_connect_cid; 256 int ringid = wil_find_free_vring(wil); 257 258 if (cid < 0) { 259 wil_err(wil, "No connection pending\n"); 260 return; 261 } 262 263 wil_dbg_wmi(wil, "Configure for connection CID %d\n", cid); 264 265 rc = wil_vring_init_tx(wil, ringid, WIL6210_TX_RING_SIZE, cid, 0); 266 wil->pending_connect_cid = -1; 267 if (rc == 0) { 268 wil->sta[cid].status = wil_sta_connected; 269 wil_link_on(wil); 270 } else { 271 wil->sta[cid].status = wil_sta_unused; 272 } 273 } 274 275 int wil_priv_init(struct wil6210_priv *wil) 276 { 277 uint i; 278 279 wil_dbg_misc(wil, "%s()\n", __func__); 280 281 memset(wil->sta, 0, sizeof(wil->sta)); 282 for (i = 0; i < WIL6210_MAX_CID; i++) 283 spin_lock_init(&wil->sta[i].tid_rx_lock); 284 285 mutex_init(&wil->mutex); 286 mutex_init(&wil->wmi_mutex); 287 288 init_completion(&wil->wmi_ready); 289 290 wil->pending_connect_cid = -1; 291 setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); 292 setup_timer(&wil->scan_timer, wil_scan_timer_fn, (ulong)wil); 293 294 INIT_WORK(&wil->connect_worker, wil_connect_worker); 295 INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); 296 INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); 297 INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker); 298 299 INIT_LIST_HEAD(&wil->pending_wmi_ev); 300 spin_lock_init(&wil->wmi_ev_lock); 301 302 wil->wmi_wq = create_singlethread_workqueue(WIL_NAME"_wmi"); 303 if (!wil->wmi_wq) 304 return -EAGAIN; 305 306 wil->wmi_wq_conn = create_singlethread_workqueue(WIL_NAME"_connect"); 307 if (!wil->wmi_wq_conn) { 308 destroy_workqueue(wil->wmi_wq); 309 return -EAGAIN; 310 } 311 312 wil->last_fw_recovery = jiffies; 313 314 return 0; 315 } 316 317 void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) 318 { 319 wil_dbg_misc(wil, "%s()\n", __func__); 320 321 del_timer_sync(&wil->connect_timer); 322 _wil6210_disconnect(wil, bssid); 323 } 324 325 void wil_priv_deinit(struct wil6210_priv *wil) 326 { 327 wil_dbg_misc(wil, "%s()\n", __func__); 328 329 del_timer_sync(&wil->scan_timer); 330 cancel_work_sync(&wil->disconnect_worker); 331 cancel_work_sync(&wil->fw_error_worker); 332 mutex_lock(&wil->mutex); 333 wil6210_disconnect(wil, NULL); 334 mutex_unlock(&wil->mutex); 335 wmi_event_flush(wil); 336 destroy_workqueue(wil->wmi_wq_conn); 337 destroy_workqueue(wil->wmi_wq); 338 } 339 340 /* target operations */ 341 /* register read */ 342 #define R(a) ioread32(wil->csr + HOSTADDR(a)) 343 /* register write. wmb() to make sure it is completed */ 344 #define W(a, v) do { iowrite32(v, wil->csr + HOSTADDR(a)); wmb(); } while (0) 345 /* register set = read, OR, write */ 346 #define S(a, v) W(a, R(a) | v) 347 /* register clear = read, AND with inverted, write */ 348 #define C(a, v) W(a, R(a) & ~v) 349 350 static inline void wil_halt_cpu(struct wil6210_priv *wil) 351 { 352 W(RGF_USER_USER_CPU_0, BIT_USER_USER_CPU_MAN_RST); 353 W(RGF_USER_MAC_CPU_0, BIT_USER_MAC_CPU_MAN_RST); 354 } 355 356 static inline void wil_release_cpu(struct wil6210_priv *wil) 357 { 358 /* Start CPU */ 359 W(RGF_USER_USER_CPU_0, 1); 360 } 361 362 static int wil_target_reset(struct wil6210_priv *wil) 363 { 364 int delay = 0; 365 u32 hw_state; 366 u32 rev_id; 367 bool is_sparrow = (wil->board->board == WIL_BOARD_SPARROW); 368 369 wil_dbg_misc(wil, "Resetting \"%s\"...\n", wil->board->name); 370 371 wil->hw_version = R(RGF_USER_FW_REV_ID); 372 rev_id = wil->hw_version & 0xff; 373 374 /* Clear MAC link up */ 375 S(RGF_HP_CTRL, BIT(15)); 376 S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT_HPAL_PERST_FROM_PAD); 377 S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT_CAR_PERST_RST); 378 379 wil_halt_cpu(wil); 380 C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_CAR_AHB_SW_SEL); /* 40 MHz */ 381 382 if (is_sparrow) { 383 W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f); 384 W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0xf); 385 } 386 387 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); 388 W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); 389 W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, is_sparrow ? 0x000000f0 : 0x00000170); 390 W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FE00); 391 392 if (is_sparrow) { 393 W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x0); 394 W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0x0); 395 } 396 397 W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0); 398 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0); 399 W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0); 400 W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); 401 402 if (is_sparrow) { 403 W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000003); 404 /* reset A2 PCIE AHB */ 405 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000); 406 } else { 407 W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001); 408 if (rev_id == 1) { 409 /* reset A1 BOTH PCIE AHB & PCIE RGF */ 410 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080); 411 } else { 412 W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8)); 413 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000); 414 } 415 } 416 417 /* TODO: check order here!!! Erez code is different */ 418 W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); 419 420 /* wait until device ready. typical time is 200..250 msec */ 421 do { 422 msleep(RST_DELAY); 423 hw_state = R(RGF_USER_HW_MACHINE_STATE); 424 if (delay++ > RST_COUNT) { 425 wil_err(wil, "Reset not completed, hw_state 0x%08x\n", 426 hw_state); 427 return -ETIME; 428 } 429 } while (hw_state != HW_MACHINE_BOOT_DONE); 430 431 /* TODO: Erez check rev_id != 1 */ 432 if (!is_sparrow && (rev_id != 1)) 433 W(RGF_PCIE_LOS_COUNTER_CTL, BIT(8)); 434 435 C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD); 436 437 wil_dbg_misc(wil, "Reset completed in %d ms\n", delay * RST_DELAY); 438 return 0; 439 } 440 441 #undef R 442 #undef W 443 #undef S 444 #undef C 445 446 void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r) 447 { 448 le32_to_cpus(&r->base); 449 le16_to_cpus(&r->entry_size); 450 le16_to_cpus(&r->size); 451 le32_to_cpus(&r->tail); 452 le32_to_cpus(&r->head); 453 } 454 455 static int wil_wait_for_fw_ready(struct wil6210_priv *wil) 456 { 457 ulong to = msecs_to_jiffies(1000); 458 ulong left = wait_for_completion_timeout(&wil->wmi_ready, to); 459 460 if (0 == left) { 461 wil_err(wil, "Firmware not ready\n"); 462 return -ETIME; 463 } else { 464 wil_info(wil, "FW ready after %d ms. HW version 0x%08x\n", 465 jiffies_to_msecs(to-left), wil->hw_version); 466 } 467 return 0; 468 } 469 470 /* 471 * We reset all the structures, and we reset the UMAC. 472 * After calling this routine, you're expected to reload 473 * the firmware. 474 */ 475 int wil_reset(struct wil6210_priv *wil) 476 { 477 int rc; 478 479 wil_dbg_misc(wil, "%s()\n", __func__); 480 481 WARN_ON(!mutex_is_locked(&wil->mutex)); 482 483 cancel_work_sync(&wil->disconnect_worker); 484 wil6210_disconnect(wil, NULL); 485 486 wil->status = 0; /* prevent NAPI from being scheduled */ 487 if (test_bit(wil_status_napi_en, &wil->status)) 488 napi_synchronize(&wil->napi_rx); 489 490 if (wil->scan_request) { 491 wil_dbg_misc(wil, "Abort scan_request 0x%p\n", 492 wil->scan_request); 493 del_timer_sync(&wil->scan_timer); 494 cfg80211_scan_done(wil->scan_request, true); 495 wil->scan_request = NULL; 496 } 497 498 wil6210_disable_irq(wil); 499 500 wmi_event_flush(wil); 501 502 flush_workqueue(wil->wmi_wq_conn); 503 flush_workqueue(wil->wmi_wq); 504 505 rc = wil_target_reset(wil); 506 wil_rx_fini(wil); 507 if (rc) 508 return rc; 509 510 if (!no_fw_load) { 511 wil_info(wil, "Use firmware <%s>\n", WIL_FW_NAME); 512 wil_halt_cpu(wil); 513 /* Loading f/w from the file */ 514 rc = wil_request_firmware(wil, WIL_FW_NAME); 515 if (rc) 516 return rc; 517 518 /* clear any interrupts which on-card-firmware may have set */ 519 wil6210_clear_irq(wil); 520 { /* CAF_ICR - clear and mask */ 521 u32 a = HOSTADDR(RGF_CAF_ICR) + 522 offsetof(struct RGF_ICR, ICR); 523 u32 m = HOSTADDR(RGF_CAF_ICR) + 524 offsetof(struct RGF_ICR, IMV); 525 u32 icr = ioread32(wil->csr + a); 526 527 iowrite32(icr, wil->csr + a); /* W1C */ 528 iowrite32(~0, wil->csr + m); 529 wmb(); /* wait for completion */ 530 } 531 wil_release_cpu(wil); 532 } else { 533 wil_info(wil, "Use firmware from on-card flash\n"); 534 } 535 536 /* init after reset */ 537 wil->pending_connect_cid = -1; 538 reinit_completion(&wil->wmi_ready); 539 540 wil6210_enable_irq(wil); 541 542 /* we just started MAC, wait for FW ready */ 543 rc = wil_wait_for_fw_ready(wil); 544 545 return rc; 546 } 547 548 void wil_fw_error_recovery(struct wil6210_priv *wil) 549 { 550 wil_dbg_misc(wil, "starting fw error recovery\n"); 551 schedule_work(&wil->fw_error_worker); 552 } 553 554 void wil_link_on(struct wil6210_priv *wil) 555 { 556 struct net_device *ndev = wil_to_ndev(wil); 557 558 wil_dbg_misc(wil, "%s()\n", __func__); 559 560 netif_carrier_on(ndev); 561 wil_dbg_misc(wil, "netif_tx_wake : link on\n"); 562 netif_tx_wake_all_queues(ndev); 563 } 564 565 void wil_link_off(struct wil6210_priv *wil) 566 { 567 struct net_device *ndev = wil_to_ndev(wil); 568 569 wil_dbg_misc(wil, "%s()\n", __func__); 570 571 netif_tx_stop_all_queues(ndev); 572 wil_dbg_misc(wil, "netif_tx_stop : link off\n"); 573 netif_carrier_off(ndev); 574 } 575 576 static int __wil_up(struct wil6210_priv *wil) 577 { 578 struct net_device *ndev = wil_to_ndev(wil); 579 struct wireless_dev *wdev = wil->wdev; 580 int rc; 581 582 WARN_ON(!mutex_is_locked(&wil->mutex)); 583 584 rc = wil_reset(wil); 585 if (rc) 586 return rc; 587 588 /* Rx VRING. After MAC and beacon */ 589 rc = wil_rx_init(wil); 590 if (rc) 591 return rc; 592 593 switch (wdev->iftype) { 594 case NL80211_IFTYPE_STATION: 595 wil_dbg_misc(wil, "type: STATION\n"); 596 ndev->type = ARPHRD_ETHER; 597 break; 598 case NL80211_IFTYPE_AP: 599 wil_dbg_misc(wil, "type: AP\n"); 600 ndev->type = ARPHRD_ETHER; 601 break; 602 case NL80211_IFTYPE_P2P_CLIENT: 603 wil_dbg_misc(wil, "type: P2P_CLIENT\n"); 604 ndev->type = ARPHRD_ETHER; 605 break; 606 case NL80211_IFTYPE_P2P_GO: 607 wil_dbg_misc(wil, "type: P2P_GO\n"); 608 ndev->type = ARPHRD_ETHER; 609 break; 610 case NL80211_IFTYPE_MONITOR: 611 wil_dbg_misc(wil, "type: Monitor\n"); 612 ndev->type = ARPHRD_IEEE80211_RADIOTAP; 613 /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_RADIOTAP ? */ 614 break; 615 default: 616 return -EOPNOTSUPP; 617 } 618 619 /* MAC address - pre-requisite for other commands */ 620 wmi_set_mac_address(wil, ndev->dev_addr); 621 622 623 napi_enable(&wil->napi_rx); 624 napi_enable(&wil->napi_tx); 625 set_bit(wil_status_napi_en, &wil->status); 626 627 if (wil->platform_ops.bus_request) 628 wil->platform_ops.bus_request(wil->platform_handle, 629 WIL_MAX_BUS_REQUEST_KBPS); 630 631 return 0; 632 } 633 634 int wil_up(struct wil6210_priv *wil) 635 { 636 int rc; 637 638 wil_dbg_misc(wil, "%s()\n", __func__); 639 640 mutex_lock(&wil->mutex); 641 rc = __wil_up(wil); 642 mutex_unlock(&wil->mutex); 643 644 return rc; 645 } 646 647 static int __wil_down(struct wil6210_priv *wil) 648 { 649 int iter = WAIT_FOR_DISCONNECT_TIMEOUT_MS / 650 WAIT_FOR_DISCONNECT_INTERVAL_MS; 651 652 WARN_ON(!mutex_is_locked(&wil->mutex)); 653 654 if (wil->platform_ops.bus_request) 655 wil->platform_ops.bus_request(wil->platform_handle, 0); 656 657 clear_bit(wil_status_napi_en, &wil->status); 658 napi_disable(&wil->napi_rx); 659 napi_disable(&wil->napi_tx); 660 661 if (wil->scan_request) { 662 wil_dbg_misc(wil, "Abort scan_request 0x%p\n", 663 wil->scan_request); 664 del_timer_sync(&wil->scan_timer); 665 cfg80211_scan_done(wil->scan_request, true); 666 wil->scan_request = NULL; 667 } 668 669 if (test_bit(wil_status_fwconnected, &wil->status) || 670 test_bit(wil_status_fwconnecting, &wil->status)) 671 wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0); 672 673 /* make sure wil is idle (not connected) */ 674 mutex_unlock(&wil->mutex); 675 while (iter--) { 676 int idle = !test_bit(wil_status_fwconnected, &wil->status) && 677 !test_bit(wil_status_fwconnecting, &wil->status); 678 if (idle) 679 break; 680 msleep(WAIT_FOR_DISCONNECT_INTERVAL_MS); 681 } 682 mutex_lock(&wil->mutex); 683 684 if (!iter) 685 wil_err(wil, "timeout waiting for idle FW/HW\n"); 686 687 wil_rx_fini(wil); 688 689 return 0; 690 } 691 692 int wil_down(struct wil6210_priv *wil) 693 { 694 int rc; 695 696 wil_dbg_misc(wil, "%s()\n", __func__); 697 698 mutex_lock(&wil->mutex); 699 rc = __wil_down(wil); 700 mutex_unlock(&wil->mutex); 701 702 return rc; 703 } 704 705 int wil_find_cid(struct wil6210_priv *wil, const u8 *mac) 706 { 707 int i; 708 int rc = -ENOENT; 709 710 for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { 711 if ((wil->sta[i].status != wil_sta_unused) && 712 ether_addr_equal(wil->sta[i].addr, mac)) { 713 rc = i; 714 break; 715 } 716 } 717 718 return rc; 719 } 720