2 * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
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.
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.
17 #include <linux/moduleparam.h>
18 #include <linux/if_arp.h>
19 #include <linux/etherdevice.h>
25 #define WAIT_FOR_DISCONNECT_TIMEOUT_MS 2000
26 #define WAIT_FOR_DISCONNECT_INTERVAL_MS 10
29 module_param(no_fw_recovery
, bool, S_IRUGO
| S_IWUSR
);
30 MODULE_PARM_DESC(no_fw_recovery
, " disable automatic FW error recovery");
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.");
36 static unsigned int itr_trsh
= WIL6210_ITR_TRSH_DEFAULT
;
38 module_param(itr_trsh
, uint
, S_IRUGO
);
39 MODULE_PARM_DESC(itr_trsh
, " Interrupt moderation threshold, usecs.");
41 #define RST_DELAY (20) /* msec, for loop in @wil_target_reset */
42 #define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */
45 * Due to a hardware issue,
46 * one has to read/write to/from NIC in 32-bit chunks;
47 * regular memcpy_fromio and siblings will
48 * not work on 64-bit platform - it uses 64-bit transactions
50 * Force 32-bit transactions to enable NIC on 64-bit platforms
52 * To avoid byte swap on big endian host, __raw_{read|write}l
53 * should be used - {read|write}l would swap bytes to provide
54 * little endian on PCI value in host endianness.
56 void wil_memcpy_fromio_32(void *dst
, const volatile void __iomem
*src
,
60 const volatile u32 __iomem
*s
= src
;
62 /* size_t is unsigned, if (count%4 != 0) it will wrap */
63 for (count
+= 4; count
> 4; count
-= 4)
64 *d
++ = __raw_readl(s
++);
67 void wil_memcpy_toio_32(volatile void __iomem
*dst
, const void *src
,
70 volatile u32 __iomem
*d
= dst
;
73 for (count
+= 4; count
> 4; count
-= 4)
74 __raw_writel(*s
++, d
++);
77 static void wil_disconnect_cid(struct wil6210_priv
*wil
, int cid
)
80 struct net_device
*ndev
= wil_to_ndev(wil
);
81 struct wireless_dev
*wdev
= wil
->wdev
;
82 struct wil_sta_info
*sta
= &wil
->sta
[cid
];
84 wil_dbg_misc(wil
, "%s(CID %d, status %d)\n", __func__
, cid
,
87 sta
->data_port_open
= false;
88 if (sta
->status
!= wil_sta_unused
) {
89 wmi_disconnect_sta(wil
, sta
->addr
, WLAN_REASON_DEAUTH_LEAVING
);
90 switch (wdev
->iftype
) {
91 case NL80211_IFTYPE_AP
:
92 case NL80211_IFTYPE_P2P_GO
:
93 /* AP-like interface */
94 cfg80211_del_sta(ndev
, sta
->addr
, GFP_KERNEL
);
99 sta
->status
= wil_sta_unused
;
102 for (i
= 0; i
< WIL_STA_TID_NUM
; i
++) {
103 struct wil_tid_ampdu_rx
*r
;
106 spin_lock_irqsave(&sta
->tid_rx_lock
, flags
);
109 sta
->tid_rx
[i
] = NULL
;
110 wil_tid_ampdu_rx_free(wil
, r
);
112 spin_unlock_irqrestore(&sta
->tid_rx_lock
, flags
);
114 for (i
= 0; i
< ARRAY_SIZE(wil
->vring_tx
); i
++) {
115 if (wil
->vring2cid_tid
[i
][0] == cid
)
116 wil_vring_fini_tx(wil
, i
);
118 memset(&sta
->stats
, 0, sizeof(sta
->stats
));
121 static void _wil6210_disconnect(struct wil6210_priv
*wil
, const u8
*bssid
)
124 struct net_device
*ndev
= wil_to_ndev(wil
);
125 struct wireless_dev
*wdev
= wil
->wdev
;
129 cid
= wil_find_cid(wil
, bssid
);
130 wil_dbg_misc(wil
, "%s(%pM, CID %d)\n", __func__
, bssid
, cid
);
132 wil_dbg_misc(wil
, "%s(all)\n", __func__
);
135 if (cid
>= 0) /* disconnect 1 peer */
136 wil_disconnect_cid(wil
, cid
);
137 else /* disconnect all */
138 for (cid
= 0; cid
< WIL6210_MAX_CID
; cid
++)
139 wil_disconnect_cid(wil
, cid
);
142 switch (wdev
->iftype
) {
143 case NL80211_IFTYPE_STATION
:
144 case NL80211_IFTYPE_P2P_CLIENT
:
146 if (test_bit(wil_status_fwconnected
, &wil
->status
)) {
147 clear_bit(wil_status_fwconnected
, &wil
->status
);
148 cfg80211_disconnected(ndev
,
149 WLAN_STATUS_UNSPECIFIED_FAILURE
,
150 NULL
, 0, GFP_KERNEL
);
151 } else if (test_bit(wil_status_fwconnecting
, &wil
->status
)) {
152 cfg80211_connect_result(ndev
, bssid
, NULL
, 0, NULL
, 0,
153 WLAN_STATUS_UNSPECIFIED_FAILURE
,
156 clear_bit(wil_status_fwconnecting
, &wil
->status
);
163 static void wil_disconnect_worker(struct work_struct
*work
)
165 struct wil6210_priv
*wil
= container_of(work
,
166 struct wil6210_priv
, disconnect_worker
);
168 mutex_lock(&wil
->mutex
);
169 _wil6210_disconnect(wil
, NULL
);
170 mutex_unlock(&wil
->mutex
);
173 static void wil_connect_timer_fn(ulong x
)
175 struct wil6210_priv
*wil
= (void *)x
;
177 wil_dbg_misc(wil
, "Connect timeout\n");
179 /* reschedule to thread context - disconnect won't
180 * run from atomic context
182 schedule_work(&wil
->disconnect_worker
);
185 static void wil_scan_timer_fn(ulong x
)
187 struct wil6210_priv
*wil
= (void *)x
;
189 clear_bit(wil_status_fwready
, &wil
->status
);
190 wil_err(wil
, "Scan timeout detected, start fw error recovery\n");
191 schedule_work(&wil
->fw_error_worker
);
194 static int wil_wait_for_recovery(struct wil6210_priv
*wil
)
196 if (wait_event_interruptible(wil
->wq
, wil
->recovery_state
!=
197 fw_recovery_pending
)) {
198 wil_err(wil
, "Interrupt, canceling recovery\n");
201 if (wil
->recovery_state
!= fw_recovery_running
) {
202 wil_info(wil
, "Recovery cancelled\n");
205 wil_info(wil
, "Proceed with recovery\n");
209 void wil_set_recovery_state(struct wil6210_priv
*wil
, int state
)
211 wil_dbg_misc(wil
, "%s(%d -> %d)\n", __func__
,
212 wil
->recovery_state
, state
);
214 wil
->recovery_state
= state
;
215 wake_up_interruptible(&wil
->wq
);
218 static void wil_fw_error_worker(struct work_struct
*work
)
220 struct wil6210_priv
*wil
= container_of(work
, struct wil6210_priv
,
222 struct wireless_dev
*wdev
= wil
->wdev
;
224 wil_dbg_misc(wil
, "fw error worker\n");
226 /* increment @recovery_count if less then WIL6210_FW_RECOVERY_TO
227 * passed since last recovery attempt
229 if (time_is_after_jiffies(wil
->last_fw_recovery
+
230 WIL6210_FW_RECOVERY_TO
))
231 wil
->recovery_count
++;
233 wil
->recovery_count
= 1; /* fw was alive for a long time */
235 if (wil
->recovery_count
> WIL6210_FW_RECOVERY_RETRIES
) {
236 wil_err(wil
, "too many recovery attempts (%d), giving up\n",
237 wil
->recovery_count
);
241 wil
->last_fw_recovery
= jiffies
;
243 wil_info(wil
, "fw error recovery requested (try %d)...\n",
244 wil
->recovery_count
);
246 wil
->recovery_state
= fw_recovery_running
;
247 if (wil_wait_for_recovery(wil
) != 0)
250 mutex_lock(&wil
->mutex
);
251 switch (wdev
->iftype
) {
252 case NL80211_IFTYPE_STATION
:
253 case NL80211_IFTYPE_P2P_CLIENT
:
254 case NL80211_IFTYPE_MONITOR
:
255 /* silent recovery, upper layers will see disconnect */
259 case NL80211_IFTYPE_AP
:
260 case NL80211_IFTYPE_P2P_GO
:
261 /* recovery in these modes is done by upper layers */
266 mutex_unlock(&wil
->mutex
);
269 static int wil_find_free_vring(struct wil6210_priv
*wil
)
273 for (i
= 0; i
< WIL6210_MAX_TX_RINGS
; i
++) {
274 if (!wil
->vring_tx
[i
].va
)
280 static void wil_connect_worker(struct work_struct
*work
)
283 struct wil6210_priv
*wil
= container_of(work
, struct wil6210_priv
,
285 int cid
= wil
->pending_connect_cid
;
286 int ringid
= wil_find_free_vring(wil
);
289 wil_err(wil
, "No connection pending\n");
293 wil_dbg_wmi(wil
, "Configure for connection CID %d\n", cid
);
295 rc
= wil_vring_init_tx(wil
, ringid
, WIL6210_TX_RING_SIZE
, cid
, 0);
296 wil
->pending_connect_cid
= -1;
298 wil
->sta
[cid
].status
= wil_sta_connected
;
301 wil
->sta
[cid
].status
= wil_sta_unused
;
305 int wil_priv_init(struct wil6210_priv
*wil
)
309 wil_dbg_misc(wil
, "%s()\n", __func__
);
311 memset(wil
->sta
, 0, sizeof(wil
->sta
));
312 for (i
= 0; i
< WIL6210_MAX_CID
; i
++)
313 spin_lock_init(&wil
->sta
[i
].tid_rx_lock
);
315 mutex_init(&wil
->mutex
);
316 mutex_init(&wil
->wmi_mutex
);
318 init_completion(&wil
->wmi_ready
);
319 init_completion(&wil
->wmi_call
);
321 wil
->pending_connect_cid
= -1;
322 setup_timer(&wil
->connect_timer
, wil_connect_timer_fn
, (ulong
)wil
);
323 setup_timer(&wil
->scan_timer
, wil_scan_timer_fn
, (ulong
)wil
);
325 INIT_WORK(&wil
->connect_worker
, wil_connect_worker
);
326 INIT_WORK(&wil
->disconnect_worker
, wil_disconnect_worker
);
327 INIT_WORK(&wil
->wmi_event_worker
, wmi_event_worker
);
328 INIT_WORK(&wil
->fw_error_worker
, wil_fw_error_worker
);
330 INIT_LIST_HEAD(&wil
->pending_wmi_ev
);
331 spin_lock_init(&wil
->wmi_ev_lock
);
332 init_waitqueue_head(&wil
->wq
);
334 wil
->wmi_wq
= create_singlethread_workqueue(WIL_NAME
"_wmi");
338 wil
->wmi_wq_conn
= create_singlethread_workqueue(WIL_NAME
"_connect");
339 if (!wil
->wmi_wq_conn
) {
340 destroy_workqueue(wil
->wmi_wq
);
344 wil
->last_fw_recovery
= jiffies
;
345 wil
->itr_trsh
= itr_trsh
;
350 void wil6210_disconnect(struct wil6210_priv
*wil
, const u8
*bssid
)
352 wil_dbg_misc(wil
, "%s()\n", __func__
);
354 del_timer_sync(&wil
->connect_timer
);
355 _wil6210_disconnect(wil
, bssid
);
358 void wil_priv_deinit(struct wil6210_priv
*wil
)
360 wil_dbg_misc(wil
, "%s()\n", __func__
);
362 wil_set_recovery_state(wil
, fw_recovery_idle
);
363 del_timer_sync(&wil
->scan_timer
);
364 cancel_work_sync(&wil
->disconnect_worker
);
365 cancel_work_sync(&wil
->fw_error_worker
);
366 mutex_lock(&wil
->mutex
);
367 wil6210_disconnect(wil
, NULL
);
368 mutex_unlock(&wil
->mutex
);
369 wmi_event_flush(wil
);
370 destroy_workqueue(wil
->wmi_wq_conn
);
371 destroy_workqueue(wil
->wmi_wq
);
374 /* target operations */
376 #define R(a) ioread32(wil->csr + HOSTADDR(a))
377 /* register write. wmb() to make sure it is completed */
378 #define W(a, v) do { iowrite32(v, wil->csr + HOSTADDR(a)); wmb(); } while (0)
379 /* register set = read, OR, write */
380 #define S(a, v) W(a, R(a) | v)
381 /* register clear = read, AND with inverted, write */
382 #define C(a, v) W(a, R(a) & ~v)
384 static inline void wil_halt_cpu(struct wil6210_priv
*wil
)
386 W(RGF_USER_USER_CPU_0
, BIT_USER_USER_CPU_MAN_RST
);
387 W(RGF_USER_MAC_CPU_0
, BIT_USER_MAC_CPU_MAN_RST
);
390 static inline void wil_release_cpu(struct wil6210_priv
*wil
)
393 W(RGF_USER_USER_CPU_0
, 1);
396 static int wil_target_reset(struct wil6210_priv
*wil
)
401 bool is_sparrow
= (wil
->board
->board
== WIL_BOARD_SPARROW
);
403 wil_dbg_misc(wil
, "Resetting \"%s\"...\n", wil
->board
->name
);
405 wil
->hw_version
= R(RGF_USER_FW_REV_ID
);
406 rev_id
= wil
->hw_version
& 0xff;
408 /* Clear MAC link up */
409 S(RGF_HP_CTRL
, BIT(15));
410 S(RGF_USER_CLKS_CTL_SW_RST_MASK_0
, BIT_HPAL_PERST_FROM_PAD
);
411 S(RGF_USER_CLKS_CTL_SW_RST_MASK_0
, BIT_CAR_PERST_RST
);
414 C(RGF_USER_CLKS_CTL_0
, BIT_USER_CLKS_CAR_AHB_SW_SEL
); /* 40 MHz */
417 W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0
, 0x3ff81f);
418 W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1
, 0xf);
421 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2
, 0xFE000000);
422 W(RGF_USER_CLKS_CTL_SW_RST_VEC_1
, 0x0000003F);
423 W(RGF_USER_CLKS_CTL_SW_RST_VEC_3
, is_sparrow
? 0x000000f0 : 0x00000170);
424 W(RGF_USER_CLKS_CTL_SW_RST_VEC_0
, 0xFFE7FE00);
427 W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0
, 0x0);
428 W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1
, 0x0);
431 W(RGF_USER_CLKS_CTL_SW_RST_VEC_3
, 0);
432 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2
, 0);
433 W(RGF_USER_CLKS_CTL_SW_RST_VEC_1
, 0);
434 W(RGF_USER_CLKS_CTL_SW_RST_VEC_0
, 0);
437 W(RGF_USER_CLKS_CTL_SW_RST_VEC_3
, 0x00000003);
438 /* reset A2 PCIE AHB */
439 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2
, 0x00008000);
441 W(RGF_USER_CLKS_CTL_SW_RST_VEC_3
, 0x00000001);
443 /* reset A1 BOTH PCIE AHB & PCIE RGF */
444 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2
, 0x00000080);
446 W(RGF_PCIE_LOS_COUNTER_CTL
, BIT(6) | BIT(8));
447 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2
, 0x00008000);
451 /* TODO: check order here!!! Erez code is different */
452 W(RGF_USER_CLKS_CTL_SW_RST_VEC_0
, 0);
454 /* wait until device ready. typical time is 200..250 msec */
457 hw_state
= R(RGF_USER_HW_MACHINE_STATE
);
458 if (delay
++ > RST_COUNT
) {
459 wil_err(wil
, "Reset not completed, hw_state 0x%08x\n",
463 } while (hw_state
!= HW_MACHINE_BOOT_DONE
);
465 /* TODO: Erez check rev_id != 1 */
466 if (!is_sparrow
&& (rev_id
!= 1))
467 W(RGF_PCIE_LOS_COUNTER_CTL
, BIT(8));
469 C(RGF_USER_CLKS_CTL_0
, BIT_USER_CLKS_RST_PWGD
);
471 wil_dbg_misc(wil
, "Reset completed in %d ms\n", delay
* RST_DELAY
);
476 * wil_set_itr_trsh: - apply interrupt coalescing params
478 void wil_set_itr_trsh(struct wil6210_priv
*wil
)
480 /* disable, use usec resolution */
481 W(RGF_DMA_ITR_CNT_CRL
, BIT_DMA_ITR_CNT_CRL_EXT_TICK
);
483 /* disable interrupt moderation for monitor
484 * to get better timestamp precision
486 if (wil
->wdev
->iftype
== NL80211_IFTYPE_MONITOR
)
489 wil_info(wil
, "set ITR_TRSH = %d usec\n", wil
->itr_trsh
);
490 W(RGF_DMA_ITR_CNT_TRSH
, wil
->itr_trsh
);
491 W(RGF_DMA_ITR_CNT_CRL
, BIT_DMA_ITR_CNT_CRL_EN
|
492 BIT_DMA_ITR_CNT_CRL_EXT_TICK
); /* start it */
500 void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring
*r
)
502 le32_to_cpus(&r
->base
);
503 le16_to_cpus(&r
->entry_size
);
504 le16_to_cpus(&r
->size
);
505 le32_to_cpus(&r
->tail
);
506 le32_to_cpus(&r
->head
);
509 static int wil_wait_for_fw_ready(struct wil6210_priv
*wil
)
511 ulong to
= msecs_to_jiffies(1000);
512 ulong left
= wait_for_completion_timeout(&wil
->wmi_ready
, to
);
515 wil_err(wil
, "Firmware not ready\n");
518 wil_info(wil
, "FW ready after %d ms. HW version 0x%08x\n",
519 jiffies_to_msecs(to
-left
), wil
->hw_version
);
525 * We reset all the structures, and we reset the UMAC.
526 * After calling this routine, you're expected to reload
529 int wil_reset(struct wil6210_priv
*wil
)
533 wil_dbg_misc(wil
, "%s()\n", __func__
);
535 WARN_ON(!mutex_is_locked(&wil
->mutex
));
536 WARN_ON(test_bit(wil_status_napi_en
, &wil
->status
));
538 cancel_work_sync(&wil
->disconnect_worker
);
539 wil6210_disconnect(wil
, NULL
);
541 wil
->status
= 0; /* prevent NAPI from being scheduled */
543 if (wil
->scan_request
) {
544 wil_dbg_misc(wil
, "Abort scan_request 0x%p\n",
546 del_timer_sync(&wil
->scan_timer
);
547 cfg80211_scan_done(wil
->scan_request
, true);
548 wil
->scan_request
= NULL
;
553 wmi_event_flush(wil
);
555 flush_workqueue(wil
->wmi_wq_conn
);
556 flush_workqueue(wil
->wmi_wq
);
558 rc
= wil_target_reset(wil
);
564 wil_info(wil
, "Use firmware <%s>\n", WIL_FW_NAME
);
566 /* Loading f/w from the file */
567 rc
= wil_request_firmware(wil
, WIL_FW_NAME
);
571 /* clear any interrupts which on-card-firmware may have set */
572 wil6210_clear_irq(wil
);
573 { /* CAF_ICR - clear and mask */
574 u32 a
= HOSTADDR(RGF_CAF_ICR
) +
575 offsetof(struct RGF_ICR
, ICR
);
576 u32 m
= HOSTADDR(RGF_CAF_ICR
) +
577 offsetof(struct RGF_ICR
, IMV
);
578 u32 icr
= ioread32(wil
->csr
+ a
);
580 iowrite32(icr
, wil
->csr
+ a
); /* W1C */
581 iowrite32(~0, wil
->csr
+ m
);
582 wmb(); /* wait for completion */
584 wil_release_cpu(wil
);
586 wil_info(wil
, "Use firmware from on-card flash\n");
589 /* init after reset */
590 wil
->pending_connect_cid
= -1;
591 reinit_completion(&wil
->wmi_ready
);
592 reinit_completion(&wil
->wmi_call
);
596 /* we just started MAC, wait for FW ready */
597 rc
= wil_wait_for_fw_ready(wil
);
602 void wil_fw_error_recovery(struct wil6210_priv
*wil
)
604 wil_dbg_misc(wil
, "starting fw error recovery\n");
605 wil
->recovery_state
= fw_recovery_pending
;
606 schedule_work(&wil
->fw_error_worker
);
609 void wil_link_on(struct wil6210_priv
*wil
)
611 struct net_device
*ndev
= wil_to_ndev(wil
);
613 wil_dbg_misc(wil
, "%s()\n", __func__
);
615 netif_carrier_on(ndev
);
616 wil_dbg_misc(wil
, "netif_tx_wake : link on\n");
617 netif_tx_wake_all_queues(ndev
);
620 void wil_link_off(struct wil6210_priv
*wil
)
622 struct net_device
*ndev
= wil_to_ndev(wil
);
624 wil_dbg_misc(wil
, "%s()\n", __func__
);
626 netif_tx_stop_all_queues(ndev
);
627 wil_dbg_misc(wil
, "netif_tx_stop : link off\n");
628 netif_carrier_off(ndev
);
631 int __wil_up(struct wil6210_priv
*wil
)
633 struct net_device
*ndev
= wil_to_ndev(wil
);
634 struct wireless_dev
*wdev
= wil
->wdev
;
637 WARN_ON(!mutex_is_locked(&wil
->mutex
));
643 /* Rx VRING. After MAC and beacon */
644 rc
= wil_rx_init(wil
);
648 switch (wdev
->iftype
) {
649 case NL80211_IFTYPE_STATION
:
650 wil_dbg_misc(wil
, "type: STATION\n");
651 ndev
->type
= ARPHRD_ETHER
;
653 case NL80211_IFTYPE_AP
:
654 wil_dbg_misc(wil
, "type: AP\n");
655 ndev
->type
= ARPHRD_ETHER
;
657 case NL80211_IFTYPE_P2P_CLIENT
:
658 wil_dbg_misc(wil
, "type: P2P_CLIENT\n");
659 ndev
->type
= ARPHRD_ETHER
;
661 case NL80211_IFTYPE_P2P_GO
:
662 wil_dbg_misc(wil
, "type: P2P_GO\n");
663 ndev
->type
= ARPHRD_ETHER
;
665 case NL80211_IFTYPE_MONITOR
:
666 wil_dbg_misc(wil
, "type: Monitor\n");
667 ndev
->type
= ARPHRD_IEEE80211_RADIOTAP
;
668 /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_RADIOTAP ? */
674 /* MAC address - pre-requisite for other commands */
675 wmi_set_mac_address(wil
, ndev
->dev_addr
);
677 wil_dbg_misc(wil
, "NAPI enable\n");
678 napi_enable(&wil
->napi_rx
);
679 napi_enable(&wil
->napi_tx
);
680 set_bit(wil_status_napi_en
, &wil
->status
);
682 if (wil
->platform_ops
.bus_request
)
683 wil
->platform_ops
.bus_request(wil
->platform_handle
,
684 WIL_MAX_BUS_REQUEST_KBPS
);
689 int wil_up(struct wil6210_priv
*wil
)
693 wil_dbg_misc(wil
, "%s()\n", __func__
);
695 mutex_lock(&wil
->mutex
);
697 mutex_unlock(&wil
->mutex
);
702 int __wil_down(struct wil6210_priv
*wil
)
704 int iter
= WAIT_FOR_DISCONNECT_TIMEOUT_MS
/
705 WAIT_FOR_DISCONNECT_INTERVAL_MS
;
707 WARN_ON(!mutex_is_locked(&wil
->mutex
));
709 if (wil
->platform_ops
.bus_request
)
710 wil
->platform_ops
.bus_request(wil
->platform_handle
, 0);
712 wil_disable_irq(wil
);
713 if (test_and_clear_bit(wil_status_napi_en
, &wil
->status
)) {
714 napi_disable(&wil
->napi_rx
);
715 napi_disable(&wil
->napi_tx
);
716 wil_dbg_misc(wil
, "NAPI disable\n");
720 if (wil
->scan_request
) {
721 wil_dbg_misc(wil
, "Abort scan_request 0x%p\n",
723 del_timer_sync(&wil
->scan_timer
);
724 cfg80211_scan_done(wil
->scan_request
, true);
725 wil
->scan_request
= NULL
;
728 if (test_bit(wil_status_fwconnected
, &wil
->status
) ||
729 test_bit(wil_status_fwconnecting
, &wil
->status
))
730 wmi_send(wil
, WMI_DISCONNECT_CMDID
, NULL
, 0);
732 /* make sure wil is idle (not connected) */
733 mutex_unlock(&wil
->mutex
);
735 int idle
= !test_bit(wil_status_fwconnected
, &wil
->status
) &&
736 !test_bit(wil_status_fwconnecting
, &wil
->status
);
739 msleep(WAIT_FOR_DISCONNECT_INTERVAL_MS
);
741 mutex_lock(&wil
->mutex
);
744 wil_err(wil
, "timeout waiting for idle FW/HW\n");
751 int wil_down(struct wil6210_priv
*wil
)
755 wil_dbg_misc(wil
, "%s()\n", __func__
);
757 wil_set_recovery_state(wil
, fw_recovery_idle
);
758 mutex_lock(&wil
->mutex
);
759 rc
= __wil_down(wil
);
760 mutex_unlock(&wil
->mutex
);
765 int wil_find_cid(struct wil6210_priv
*wil
, const u8
*mac
)
770 for (i
= 0; i
< ARRAY_SIZE(wil
->sta
); i
++) {
771 if ((wil
->sta
[i
].status
!= wil_sta_unused
) &&
772 ether_addr_equal(wil
->sta
[i
].addr
, mac
)) {