Lines Matching refs:wil

136 static void wil_disconnect_cid(struct wil6210_priv *wil, int cid,  in wil_disconnect_cid()  argument
141 struct net_device *ndev = wil_to_ndev(wil); in wil_disconnect_cid()
142 struct wireless_dev *wdev = wil->wdev; in wil_disconnect_cid()
143 struct wil_sta_info *sta = &wil->sta[cid]; in wil_disconnect_cid()
146 wil_dbg_misc(wil, "%s(CID %d, status %d)\n", __func__, cid, in wil_disconnect_cid()
152 wmi_disconnect_sta(wil, sta->addr, reason_code); in wil_disconnect_cid()
173 wil_tid_ampdu_rx_free(wil, r); in wil_disconnect_cid()
177 for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { in wil_disconnect_cid()
178 if (wil->vring2cid_tid[i][0] == cid) in wil_disconnect_cid()
179 wil_vring_fini_tx(wil, i); in wil_disconnect_cid()
184 static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, in _wil6210_disconnect() argument
188 struct net_device *ndev = wil_to_ndev(wil); in _wil6210_disconnect()
189 struct wireless_dev *wdev = wil->wdev; in _wil6210_disconnect()
192 wil_dbg_misc(wil, "%s(bssid=%pM, reason=%d, ev%s)\n", __func__, bssid, in _wil6210_disconnect()
205 cid = wil_find_cid(wil, bssid); in _wil6210_disconnect()
206 wil_dbg_misc(wil, "Disconnect %pM, CID=%d, reason=%d\n", in _wil6210_disconnect()
209 wil_disconnect_cid(wil, cid, reason_code, from_event); in _wil6210_disconnect()
211 wil_dbg_misc(wil, "Disconnect all\n"); in _wil6210_disconnect()
213 wil_disconnect_cid(wil, cid, reason_code, from_event); in _wil6210_disconnect()
220 wil_bcast_fini(wil); in _wil6210_disconnect()
224 if (test_bit(wil_status_fwconnected, wil->status)) { in _wil6210_disconnect()
225 clear_bit(wil_status_fwconnected, wil->status); in _wil6210_disconnect()
228 } else if (test_bit(wil_status_fwconnecting, wil->status)) { in _wil6210_disconnect()
233 clear_bit(wil_status_fwconnecting, wil->status); in _wil6210_disconnect()
242 struct wil6210_priv *wil = container_of(work, in wil_disconnect_worker() local
245 mutex_lock(&wil->mutex); in wil_disconnect_worker()
246 _wil6210_disconnect(wil, NULL, WLAN_REASON_UNSPECIFIED, false); in wil_disconnect_worker()
247 mutex_unlock(&wil->mutex); in wil_disconnect_worker()
252 struct wil6210_priv *wil = (void *)x; in wil_connect_timer_fn() local
254 wil_dbg_misc(wil, "Connect timeout\n"); in wil_connect_timer_fn()
259 schedule_work(&wil->disconnect_worker); in wil_connect_timer_fn()
264 struct wil6210_priv *wil = (void *)x; in wil_scan_timer_fn() local
266 clear_bit(wil_status_fwready, wil->status); in wil_scan_timer_fn()
267 wil_err(wil, "Scan timeout detected, start fw error recovery\n"); in wil_scan_timer_fn()
268 wil->recovery_state = fw_recovery_pending; in wil_scan_timer_fn()
269 schedule_work(&wil->fw_error_worker); in wil_scan_timer_fn()
272 static int wil_wait_for_recovery(struct wil6210_priv *wil) in wil_wait_for_recovery() argument
274 if (wait_event_interruptible(wil->wq, wil->recovery_state != in wil_wait_for_recovery()
276 wil_err(wil, "Interrupt, canceling recovery\n"); in wil_wait_for_recovery()
279 if (wil->recovery_state != fw_recovery_running) { in wil_wait_for_recovery()
280 wil_info(wil, "Recovery cancelled\n"); in wil_wait_for_recovery()
283 wil_info(wil, "Proceed with recovery\n"); in wil_wait_for_recovery()
287 void wil_set_recovery_state(struct wil6210_priv *wil, int state) in wil_set_recovery_state() argument
289 wil_dbg_misc(wil, "%s(%d -> %d)\n", __func__, in wil_set_recovery_state()
290 wil->recovery_state, state); in wil_set_recovery_state()
292 wil->recovery_state = state; in wil_set_recovery_state()
293 wake_up_interruptible(&wil->wq); in wil_set_recovery_state()
298 struct wil6210_priv *wil = container_of(work, struct wil6210_priv, in wil_fw_error_worker() local
300 struct wireless_dev *wdev = wil->wdev; in wil_fw_error_worker()
302 wil_dbg_misc(wil, "fw error worker\n"); in wil_fw_error_worker()
304 if (!netif_running(wil_to_ndev(wil))) { in wil_fw_error_worker()
305 wil_info(wil, "No recovery - interface is down\n"); in wil_fw_error_worker()
312 if (time_is_after_jiffies(wil->last_fw_recovery + in wil_fw_error_worker()
314 wil->recovery_count++; in wil_fw_error_worker()
316 wil->recovery_count = 1; /* fw was alive for a long time */ in wil_fw_error_worker()
318 if (wil->recovery_count > WIL6210_FW_RECOVERY_RETRIES) { in wil_fw_error_worker()
319 wil_err(wil, "too many recovery attempts (%d), giving up\n", in wil_fw_error_worker()
320 wil->recovery_count); in wil_fw_error_worker()
324 wil->last_fw_recovery = jiffies; in wil_fw_error_worker()
326 mutex_lock(&wil->mutex); in wil_fw_error_worker()
331 wil_info(wil, "fw error recovery requested (try %d)...\n", in wil_fw_error_worker()
332 wil->recovery_count); in wil_fw_error_worker()
334 wil->recovery_state = fw_recovery_running; in wil_fw_error_worker()
335 if (0 != wil_wait_for_recovery(wil)) in wil_fw_error_worker()
338 __wil_down(wil); in wil_fw_error_worker()
339 __wil_up(wil); in wil_fw_error_worker()
343 wil_info(wil, "No recovery for AP-like interface\n"); in wil_fw_error_worker()
347 wil_err(wil, "No recovery - unknown interface type %d\n", in wil_fw_error_worker()
351 mutex_unlock(&wil->mutex); in wil_fw_error_worker()
354 static int wil_find_free_vring(struct wil6210_priv *wil) in wil_find_free_vring() argument
359 if (!wil->vring_tx[i].va) in wil_find_free_vring()
365 int wil_bcast_init(struct wil6210_priv *wil) in wil_bcast_init() argument
367 int ri = wil->bcast_vring, rc; in wil_bcast_init()
369 if ((ri >= 0) && wil->vring_tx[ri].va) in wil_bcast_init()
372 ri = wil_find_free_vring(wil); in wil_bcast_init()
376 rc = wil_vring_init_bcast(wil, ri, 1 << bcast_ring_order); in wil_bcast_init()
378 wil->bcast_vring = ri; in wil_bcast_init()
383 void wil_bcast_fini(struct wil6210_priv *wil) in wil_bcast_fini() argument
385 int ri = wil->bcast_vring; in wil_bcast_fini()
390 wil->bcast_vring = -1; in wil_bcast_fini()
391 wil_vring_fini_tx(wil, ri); in wil_bcast_fini()
397 struct wil6210_priv *wil = container_of(work, struct wil6210_priv, in wil_connect_worker() local
399 struct net_device *ndev = wil_to_ndev(wil); in wil_connect_worker()
401 int cid = wil->pending_connect_cid; in wil_connect_worker()
402 int ringid = wil_find_free_vring(wil); in wil_connect_worker()
405 wil_err(wil, "No connection pending\n"); in wil_connect_worker()
409 wil_dbg_wmi(wil, "Configure for connection CID %d\n", cid); in wil_connect_worker()
411 rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0); in wil_connect_worker()
412 wil->pending_connect_cid = -1; in wil_connect_worker()
414 wil->sta[cid].status = wil_sta_connected; in wil_connect_worker()
417 wil->sta[cid].status = wil_sta_unused; in wil_connect_worker()
421 int wil_priv_init(struct wil6210_priv *wil) in wil_priv_init() argument
425 wil_dbg_misc(wil, "%s()\n", __func__); in wil_priv_init()
427 memset(wil->sta, 0, sizeof(wil->sta)); in wil_priv_init()
429 spin_lock_init(&wil->sta[i].tid_rx_lock); in wil_priv_init()
431 mutex_init(&wil->mutex); in wil_priv_init()
432 mutex_init(&wil->wmi_mutex); in wil_priv_init()
433 mutex_init(&wil->back_rx_mutex); in wil_priv_init()
434 mutex_init(&wil->back_tx_mutex); in wil_priv_init()
435 mutex_init(&wil->probe_client_mutex); in wil_priv_init()
437 init_completion(&wil->wmi_ready); in wil_priv_init()
438 init_completion(&wil->wmi_call); in wil_priv_init()
440 wil->pending_connect_cid = -1; in wil_priv_init()
441 wil->bcast_vring = -1; in wil_priv_init()
442 setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); in wil_priv_init()
443 setup_timer(&wil->scan_timer, wil_scan_timer_fn, (ulong)wil); in wil_priv_init()
445 INIT_WORK(&wil->connect_worker, wil_connect_worker); in wil_priv_init()
446 INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); in wil_priv_init()
447 INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); in wil_priv_init()
448 INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker); in wil_priv_init()
449 INIT_WORK(&wil->back_rx_worker, wil_back_rx_worker); in wil_priv_init()
450 INIT_WORK(&wil->back_tx_worker, wil_back_tx_worker); in wil_priv_init()
451 INIT_WORK(&wil->probe_client_worker, wil_probe_client_worker); in wil_priv_init()
453 INIT_LIST_HEAD(&wil->pending_wmi_ev); in wil_priv_init()
454 INIT_LIST_HEAD(&wil->back_rx_pending); in wil_priv_init()
455 INIT_LIST_HEAD(&wil->back_tx_pending); in wil_priv_init()
456 INIT_LIST_HEAD(&wil->probe_client_pending); in wil_priv_init()
457 spin_lock_init(&wil->wmi_ev_lock); in wil_priv_init()
458 init_waitqueue_head(&wil->wq); in wil_priv_init()
460 wil->wmi_wq = create_singlethread_workqueue(WIL_NAME "_wmi"); in wil_priv_init()
461 if (!wil->wmi_wq) in wil_priv_init()
464 wil->wq_service = create_singlethread_workqueue(WIL_NAME "_service"); in wil_priv_init()
465 if (!wil->wq_service) in wil_priv_init()
468 wil->last_fw_recovery = jiffies; in wil_priv_init()
469 wil->tx_interframe_timeout = WIL6210_ITR_TX_INTERFRAME_TIMEOUT_DEFAULT; in wil_priv_init()
470 wil->rx_interframe_timeout = WIL6210_ITR_RX_INTERFRAME_TIMEOUT_DEFAULT; in wil_priv_init()
471 wil->tx_max_burst_duration = WIL6210_ITR_TX_MAX_BURST_DURATION_DEFAULT; in wil_priv_init()
472 wil->rx_max_burst_duration = WIL6210_ITR_RX_MAX_BURST_DURATION_DEFAULT; in wil_priv_init()
479 destroy_workqueue(wil->wmi_wq); in wil_priv_init()
494 void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, in wil6210_disconnect() argument
497 wil_dbg_misc(wil, "%s()\n", __func__); in wil6210_disconnect()
499 del_timer_sync(&wil->connect_timer); in wil6210_disconnect()
500 _wil6210_disconnect(wil, bssid, reason_code, from_event); in wil6210_disconnect()
503 void wil_priv_deinit(struct wil6210_priv *wil) in wil_priv_deinit() argument
505 wil_dbg_misc(wil, "%s()\n", __func__); in wil_priv_deinit()
507 wil_set_recovery_state(wil, fw_recovery_idle); in wil_priv_deinit()
508 del_timer_sync(&wil->scan_timer); in wil_priv_deinit()
509 cancel_work_sync(&wil->disconnect_worker); in wil_priv_deinit()
510 cancel_work_sync(&wil->fw_error_worker); in wil_priv_deinit()
511 mutex_lock(&wil->mutex); in wil_priv_deinit()
512 wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); in wil_priv_deinit()
513 mutex_unlock(&wil->mutex); in wil_priv_deinit()
514 wmi_event_flush(wil); in wil_priv_deinit()
515 wil_back_rx_flush(wil); in wil_priv_deinit()
516 cancel_work_sync(&wil->back_rx_worker); in wil_priv_deinit()
517 wil_back_tx_flush(wil); in wil_priv_deinit()
518 cancel_work_sync(&wil->back_tx_worker); in wil_priv_deinit()
519 wil_probe_client_flush(wil); in wil_priv_deinit()
520 cancel_work_sync(&wil->probe_client_worker); in wil_priv_deinit()
521 destroy_workqueue(wil->wq_service); in wil_priv_deinit()
522 destroy_workqueue(wil->wmi_wq); in wil_priv_deinit()
527 #define R(a) ioread32(wil->csr + HOSTADDR(a))
529 #define W(a, v) do { iowrite32(v, wil->csr + HOSTADDR(a)); wmb(); } while (0)
535 static inline void wil_halt_cpu(struct wil6210_priv *wil) in wil_halt_cpu() argument
541 static inline void wil_release_cpu(struct wil6210_priv *wil) in wil_release_cpu() argument
547 static int wil_target_reset(struct wil6210_priv *wil) in wil_target_reset() argument
552 wil_dbg_misc(wil, "Resetting \"%s\"...\n", wil->hw_name); in wil_target_reset()
559 wil_halt_cpu(wil); in wil_target_reset()
571 wil_err(wil, "Xtal stabilization timeout\n" in wil_target_reset()
606 wil_err(wil, "Reset not completed, bl.ready 0x%08x\n", in wil_target_reset()
618 wil_dbg_misc(wil, "Reset completed in %d ms\n", delay * RST_DELAY); in wil_target_reset()
631 static int wil_get_bl_info(struct wil6210_priv *wil) in wil_get_bl_info() argument
633 struct net_device *ndev = wil_to_ndev(wil); in wil_get_bl_info()
636 wil_memcpy_fromio_32(&bl, wil->csr + HOSTADDR(RGF_USER_BL), sizeof(bl)); in wil_get_bl_info()
643 wil_err(wil, "BL: Invalid MAC %pM\n", bl.mac_address); in wil_get_bl_info()
650 wil_info(wil, in wil_get_bl_info()
657 static int wil_wait_for_fw_ready(struct wil6210_priv *wil) in wil_wait_for_fw_ready() argument
660 ulong left = wait_for_completion_timeout(&wil->wmi_ready, to); in wil_wait_for_fw_ready()
663 wil_err(wil, "Firmware not ready\n"); in wil_wait_for_fw_ready()
666 wil_info(wil, "FW ready after %d ms. HW version 0x%08x\n", in wil_wait_for_fw_ready()
667 jiffies_to_msecs(to-left), wil->hw_version); in wil_wait_for_fw_ready()
677 int wil_reset(struct wil6210_priv *wil, bool load_fw) in wil_reset() argument
681 wil_dbg_misc(wil, "%s()\n", __func__); in wil_reset()
683 if (wil->hw_version == HW_VER_UNKNOWN) in wil_reset()
686 WARN_ON(!mutex_is_locked(&wil->mutex)); in wil_reset()
687 WARN_ON(test_bit(wil_status_napi_en, wil->status)); in wil_reset()
689 cancel_work_sync(&wil->disconnect_worker); in wil_reset()
690 wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); in wil_reset()
691 wil_bcast_fini(wil); in wil_reset()
694 bitmap_zero(wil->status, wil_status_last); in wil_reset()
696 if (wil->scan_request) { in wil_reset()
697 wil_dbg_misc(wil, "Abort scan_request 0x%p\n", in wil_reset()
698 wil->scan_request); in wil_reset()
699 del_timer_sync(&wil->scan_timer); in wil_reset()
700 cfg80211_scan_done(wil->scan_request, true); in wil_reset()
701 wil->scan_request = NULL; in wil_reset()
704 wil_mask_irq(wil); in wil_reset()
706 wmi_event_flush(wil); in wil_reset()
708 flush_workqueue(wil->wq_service); in wil_reset()
709 flush_workqueue(wil->wmi_wq); in wil_reset()
711 rc = wil_target_reset(wil); in wil_reset()
712 wil_rx_fini(wil); in wil_reset()
716 rc = wil_get_bl_info(wil); in wil_reset()
721 wil_info(wil, "Use firmware <%s> + board <%s>\n", WIL_FW_NAME, in wil_reset()
724 wil_halt_cpu(wil); in wil_reset()
726 rc = wil_request_firmware(wil, WIL_FW_NAME); in wil_reset()
729 rc = wil_request_firmware(wil, WIL_FW2_NAME); in wil_reset()
739 wil6210_clear_irq(wil); in wil_reset()
745 wil_release_cpu(wil); in wil_reset()
749 wil->pending_connect_cid = -1; in wil_reset()
750 wil->ap_isolate = 0; in wil_reset()
751 reinit_completion(&wil->wmi_ready); in wil_reset()
752 reinit_completion(&wil->wmi_call); in wil_reset()
755 wil_configure_interrupt_moderation(wil); in wil_reset()
756 wil_unmask_irq(wil); in wil_reset()
759 rc = wil_wait_for_fw_ready(wil); in wil_reset()
761 rc = wmi_echo(wil); in wil_reset()
772 void wil_fw_error_recovery(struct wil6210_priv *wil) in wil_fw_error_recovery() argument
774 wil_dbg_misc(wil, "starting fw error recovery\n"); in wil_fw_error_recovery()
775 wil->recovery_state = fw_recovery_pending; in wil_fw_error_recovery()
776 schedule_work(&wil->fw_error_worker); in wil_fw_error_recovery()
779 int __wil_up(struct wil6210_priv *wil) in __wil_up() argument
781 struct net_device *ndev = wil_to_ndev(wil); in __wil_up()
782 struct wireless_dev *wdev = wil->wdev; in __wil_up()
785 WARN_ON(!mutex_is_locked(&wil->mutex)); in __wil_up()
787 rc = wil_reset(wil, true); in __wil_up()
792 rc = wil_rx_init(wil, 1 << rx_ring_order); in __wil_up()
798 wil_dbg_misc(wil, "type: STATION\n"); in __wil_up()
802 wil_dbg_misc(wil, "type: AP\n"); in __wil_up()
806 wil_dbg_misc(wil, "type: P2P_CLIENT\n"); in __wil_up()
810 wil_dbg_misc(wil, "type: P2P_GO\n"); in __wil_up()
814 wil_dbg_misc(wil, "type: Monitor\n"); in __wil_up()
823 wmi_set_mac_address(wil, ndev->dev_addr); in __wil_up()
825 wil_dbg_misc(wil, "NAPI enable\n"); in __wil_up()
826 napi_enable(&wil->napi_rx); in __wil_up()
827 napi_enable(&wil->napi_tx); in __wil_up()
828 set_bit(wil_status_napi_en, wil->status); in __wil_up()
830 if (wil->platform_ops.bus_request) in __wil_up()
831 wil->platform_ops.bus_request(wil->platform_handle, in __wil_up()
837 int wil_up(struct wil6210_priv *wil) in wil_up() argument
841 wil_dbg_misc(wil, "%s()\n", __func__); in wil_up()
843 mutex_lock(&wil->mutex); in wil_up()
844 rc = __wil_up(wil); in wil_up()
845 mutex_unlock(&wil->mutex); in wil_up()
850 int __wil_down(struct wil6210_priv *wil) in __wil_down() argument
855 WARN_ON(!mutex_is_locked(&wil->mutex)); in __wil_down()
857 if (wil->platform_ops.bus_request) in __wil_down()
858 wil->platform_ops.bus_request(wil->platform_handle, 0); in __wil_down()
860 wil_disable_irq(wil); in __wil_down()
861 if (test_and_clear_bit(wil_status_napi_en, wil->status)) { in __wil_down()
862 napi_disable(&wil->napi_rx); in __wil_down()
863 napi_disable(&wil->napi_tx); in __wil_down()
864 wil_dbg_misc(wil, "NAPI disable\n"); in __wil_down()
866 wil_enable_irq(wil); in __wil_down()
868 if (wil->scan_request) { in __wil_down()
869 wil_dbg_misc(wil, "Abort scan_request 0x%p\n", in __wil_down()
870 wil->scan_request); in __wil_down()
871 del_timer_sync(&wil->scan_timer); in __wil_down()
872 cfg80211_scan_done(wil->scan_request, true); in __wil_down()
873 wil->scan_request = NULL; in __wil_down()
876 if (test_bit(wil_status_fwconnected, wil->status) || in __wil_down()
877 test_bit(wil_status_fwconnecting, wil->status)) in __wil_down()
878 wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0); in __wil_down()
881 mutex_unlock(&wil->mutex); in __wil_down()
883 int idle = !test_bit(wil_status_fwconnected, wil->status) && in __wil_down()
884 !test_bit(wil_status_fwconnecting, wil->status); in __wil_down()
889 mutex_lock(&wil->mutex); in __wil_down()
892 wil_err(wil, "timeout waiting for idle FW/HW\n"); in __wil_down()
894 wil_reset(wil, false); in __wil_down()
899 int wil_down(struct wil6210_priv *wil) in wil_down() argument
903 wil_dbg_misc(wil, "%s()\n", __func__); in wil_down()
905 wil_set_recovery_state(wil, fw_recovery_idle); in wil_down()
906 mutex_lock(&wil->mutex); in wil_down()
907 rc = __wil_down(wil); in wil_down()
908 mutex_unlock(&wil->mutex); in wil_down()
913 int wil_find_cid(struct wil6210_priv *wil, const u8 *mac) in wil_find_cid() argument
918 for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { in wil_find_cid()
919 if ((wil->sta[i].status != wil_sta_unused) && in wil_find_cid()
920 ether_addr_equal(wil->sta[i].addr, mac)) { in wil_find_cid()