1 // SPDX-License-Identifier: GPL-2.0-only
3 * Implementation of mac80211 API.
5 * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
6 * Copyright (c) 2010, ST-Ericsson
8 #include <linux/etherdevice.h>
9 #include <net/mac80211.h>
19 #include "hif_tx_mib.h"
21 #define HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES 2
23 u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates)
27 // WFx only support 2GHz
28 struct ieee80211_supported_band *sband = wdev->hw->wiphy->bands[NL80211_BAND_2GHZ];
30 for (i = 0; i < sband->n_bitrates; i++) {
32 if (i >= sband->n_bitrates)
33 dev_warn(wdev->dev, "unsupported basic rate\n");
35 ret |= BIT(sband->bitrates[i].hw_value);
41 void wfx_cooling_timeout_work(struct work_struct *work)
43 struct wfx_dev *wdev = container_of(to_delayed_work(work),
45 cooling_timeout_work);
47 wdev->chip_frozen = true;
51 void wfx_suspend_hot_dev(struct wfx_dev *wdev, enum sta_notify_cmd cmd)
53 if (cmd == STA_NOTIFY_AWAKE) {
54 // Device recover normal temperature
55 if (cancel_delayed_work(&wdev->cooling_timeout_work))
59 schedule_delayed_work(&wdev->cooling_timeout_work, 10 * HZ);
64 static void wfx_filter_beacon(struct wfx_vif *wvif, bool filter_beacon)
66 const struct hif_ie_table_entry filter_ies[] = {
68 .ie_id = WLAN_EID_VENDOR_SPECIFIC,
72 .oui = { 0x50, 0x6F, 0x9A },
74 .ie_id = WLAN_EID_HT_OPERATION,
79 .ie_id = WLAN_EID_ERP_INFO,
87 hif_beacon_filter_control(wvif, 0, 1);
89 hif_set_beacon_filter_table(wvif, 3, filter_ies);
90 hif_beacon_filter_control(wvif, HIF_BEACON_FILTER_ENABLE, 0);
94 void wfx_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
95 unsigned int *total_flags, u64 unused)
97 struct wfx_vif *wvif = NULL;
98 struct wfx_dev *wdev = hw->priv;
99 bool filter_bssid, filter_prbreq, filter_beacon;
102 // - Probe responses (FIF_BCN_PRBRESP_PROMISC) are never filtered
103 // - PS-Poll (FIF_PSPOLL) are never filtered
104 // - RTS, CTS and Ack (FIF_CONTROL) are always filtered
105 // - Broken frames (FIF_FCSFAIL and FIF_PLCPFAIL) are always filtered
106 // - Firmware does (yet) allow to forward unicast traffic sent to
107 // other stations (aka. promiscuous mode)
108 *total_flags &= FIF_BCN_PRBRESP_PROMISC | FIF_ALLMULTI | FIF_OTHER_BSS |
109 FIF_PROBE_REQ | FIF_PSPOLL;
111 mutex_lock(&wdev->conf_mutex);
112 while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
113 mutex_lock(&wvif->scan_lock);
115 // Note: FIF_BCN_PRBRESP_PROMISC covers probe response and
116 // beacons from other BSS
117 if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
118 filter_beacon = false;
120 filter_beacon = true;
121 wfx_filter_beacon(wvif, filter_beacon);
123 if (*total_flags & FIF_OTHER_BSS)
124 filter_bssid = false;
128 // In AP mode, chip can reply to probe request itself
129 if (*total_flags & FIF_PROBE_REQ &&
130 wvif->vif->type == NL80211_IFTYPE_AP) {
131 dev_dbg(wdev->dev, "do not forward probe request in AP mode\n");
132 *total_flags &= ~FIF_PROBE_REQ;
135 if (*total_flags & FIF_PROBE_REQ)
136 filter_prbreq = false;
138 filter_prbreq = true;
139 hif_set_rx_filter(wvif, filter_bssid, filter_prbreq);
141 mutex_unlock(&wvif->scan_lock);
143 mutex_unlock(&wdev->conf_mutex);
146 static int wfx_get_ps_timeout(struct wfx_vif *wvif, bool *enable_ps)
148 struct ieee80211_channel *chan0 = NULL, *chan1 = NULL;
149 struct ieee80211_conf *conf = &wvif->wdev->hw->conf;
151 WARN(!wvif->vif->bss_conf.assoc && enable_ps,
152 "enable_ps is reliable only if associated");
153 if (wdev_to_wvif(wvif->wdev, 0))
154 chan0 = wdev_to_wvif(wvif->wdev, 0)->vif->bss_conf.chandef.chan;
155 if (wdev_to_wvif(wvif->wdev, 1))
156 chan1 = wdev_to_wvif(wvif->wdev, 1)->vif->bss_conf.chandef.chan;
157 if (chan0 && chan1 && chan0->hw_value != chan1->hw_value &&
158 wvif->vif->type != NL80211_IFTYPE_AP) {
159 // It is necessary to enable powersave if channels
163 if (wvif->wdev->force_ps_timeout > -1)
164 return wvif->wdev->force_ps_timeout;
165 else if (wfx_api_older_than(wvif->wdev, 3, 2))
171 *enable_ps = wvif->vif->bss_conf.ps;
172 if (wvif->wdev->force_ps_timeout > -1)
173 return wvif->wdev->force_ps_timeout;
174 else if (wvif->vif->bss_conf.assoc && wvif->vif->bss_conf.ps)
175 return conf->dynamic_ps_timeout;
180 int wfx_update_pm(struct wfx_vif *wvif)
185 if (!wvif->vif->bss_conf.assoc)
187 ps_timeout = wfx_get_ps_timeout(wvif, &ps);
190 WARN_ON(ps_timeout < 0);
191 if (wvif->uapsd_mask)
194 if (!wait_for_completion_timeout(&wvif->set_pm_mode_complete,
196 dev_warn(wvif->wdev->dev,
197 "timeout while waiting of set_pm_mode_complete\n");
198 return hif_set_pm(wvif, ps, ps_timeout);
201 int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
202 u16 queue, const struct ieee80211_tx_queue_params *params)
204 struct wfx_dev *wdev = hw->priv;
205 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
206 int old_uapsd = wvif->uapsd_mask;
208 WARN_ON(queue >= hw->queues);
210 mutex_lock(&wdev->conf_mutex);
211 assign_bit(queue, &wvif->uapsd_mask, params->uapsd);
212 hif_set_edca_queue_params(wvif, queue, params);
213 if (wvif->vif->type == NL80211_IFTYPE_STATION &&
214 old_uapsd != wvif->uapsd_mask) {
215 hif_set_uapsd_info(wvif, wvif->uapsd_mask);
218 mutex_unlock(&wdev->conf_mutex);
222 int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
224 struct wfx_dev *wdev = hw->priv;
225 struct wfx_vif *wvif = NULL;
227 while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
228 hif_rts_threshold(wvif, value);
234 void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi)
236 /* RSSI: signed Q8.0, RCPI: unsigned Q7.1
237 * RSSI = RCPI / 2 - 110
242 rcpi_rssi = raw_rcpi_rssi / 2 - 110;
243 if (rcpi_rssi <= wvif->vif->bss_conf.cqm_rssi_thold)
244 cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
246 cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
247 ieee80211_cqm_rssi_notify(wvif->vif, cqm_evt, rcpi_rssi, GFP_KERNEL);
250 static void wfx_beacon_loss_work(struct work_struct *work)
252 struct wfx_vif *wvif = container_of(to_delayed_work(work),
253 struct wfx_vif, beacon_loss_work);
254 struct ieee80211_bss_conf *bss_conf = &wvif->vif->bss_conf;
256 ieee80211_beacon_loss(wvif->vif);
257 schedule_delayed_work(to_delayed_work(work),
258 msecs_to_jiffies(bss_conf->beacon_int));
261 void wfx_set_default_unicast_key(struct ieee80211_hw *hw,
262 struct ieee80211_vif *vif, int idx)
264 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
266 hif_wep_default_key_id(wvif, idx);
269 void wfx_reset(struct wfx_vif *wvif)
271 struct wfx_dev *wdev = wvif->wdev;
273 wfx_tx_lock_flush(wdev);
274 hif_reset(wvif, false);
275 wfx_tx_policy_init(wvif);
276 if (wvif_count(wdev) <= 1)
277 hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
279 wvif->join_in_progress = false;
280 cancel_delayed_work_sync(&wvif->beacon_loss_work);
282 while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
286 int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
287 struct ieee80211_sta *sta)
289 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
290 struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *)&sta->drv_priv;
292 sta_priv->vif_id = wvif->id;
294 if (vif->type == NL80211_IFTYPE_STATION)
295 hif_set_mfp(wvif, sta->mfp, sta->mfp);
297 // In station mode, the firmware interprets new link-id as a TDLS peer.
298 if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
300 sta_priv->link_id = ffz(wvif->link_id_map);
301 wvif->link_id_map |= BIT(sta_priv->link_id);
302 WARN_ON(!sta_priv->link_id);
303 WARN_ON(sta_priv->link_id >= HIF_LINK_ID_MAX);
304 hif_map_link(wvif, false, sta->addr, sta_priv->link_id, sta->mfp);
309 int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
310 struct ieee80211_sta *sta)
312 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
313 struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *)&sta->drv_priv;
315 // See note in wfx_sta_add()
316 if (!sta_priv->link_id)
318 // FIXME add a mutex?
319 hif_map_link(wvif, true, sta->addr, sta_priv->link_id, false);
320 wvif->link_id_map &= ~BIT(sta_priv->link_id);
324 static int wfx_upload_ap_templates(struct wfx_vif *wvif)
328 skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif);
331 hif_set_template_frame(wvif, skb, HIF_TMPLT_BCN,
332 API_RATE_INDEX_B_1MBPS);
335 skb = ieee80211_proberesp_get(wvif->wdev->hw, wvif->vif);
338 hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBRES,
339 API_RATE_INDEX_B_1MBPS);
344 static void wfx_set_mfp_ap(struct wfx_vif *wvif)
346 struct sk_buff *skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif);
347 const int ieoffset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
348 const u16 *ptr = (u16 *)cfg80211_find_ie(WLAN_EID_RSN,
349 skb->data + ieoffset,
350 skb->len - ieoffset);
351 const int pairwise_cipher_suite_count_offset = 8 / sizeof(u16);
352 const int pairwise_cipher_suite_size = 4 / sizeof(u16);
353 const int akm_suite_size = 4 / sizeof(u16);
356 ptr += pairwise_cipher_suite_count_offset;
357 if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
359 ptr += 1 + pairwise_cipher_suite_size * *ptr;
360 if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
362 ptr += 1 + akm_suite_size * *ptr;
363 if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
365 hif_set_mfp(wvif, *ptr & BIT(7), *ptr & BIT(6));
369 int wfx_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
371 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
372 struct wfx_dev *wdev = wvif->wdev;
376 while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
378 wvif = (struct wfx_vif *)vif->drv_priv;
379 wfx_upload_ap_templates(wvif);
380 ret = hif_start(wvif, &vif->bss_conf, wvif->channel);
383 wfx_set_mfp_ap(wvif);
387 void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
389 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
394 static void wfx_join(struct wfx_vif *wvif)
397 struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf;
398 struct cfg80211_bss *bss = NULL;
399 u8 ssid[IEEE80211_MAX_SSID_LEN];
400 const u8 *ssidie = NULL;
403 wfx_tx_lock_flush(wvif->wdev);
405 bss = cfg80211_get_bss(wvif->wdev->hw->wiphy, wvif->channel,
406 conf->bssid, NULL, 0,
407 IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY);
408 if (!bss && !conf->ibss_joined) {
409 wfx_tx_unlock(wvif->wdev);
413 rcu_read_lock(); // protect ssidie
415 ssidie = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
418 if (ssidlen > IEEE80211_MAX_SSID_LEN)
419 ssidlen = IEEE80211_MAX_SSID_LEN;
420 memcpy(ssid, &ssidie[2], ssidlen);
424 cfg80211_put_bss(wvif->wdev->hw->wiphy, bss);
426 wvif->join_in_progress = true;
427 ret = hif_join(wvif, conf, wvif->channel, ssid, ssidlen);
429 ieee80211_connection_loss(wvif->vif);
432 /* Due to beacon filtering it is possible that the
433 * AP's beacon is not known for the mac80211 stack.
434 * Disable filtering temporary to make sure the stack
435 * receives at least one
437 wfx_filter_beacon(wvif, false);
439 wfx_tx_unlock(wvif->wdev);
442 static void wfx_join_finalize(struct wfx_vif *wvif,
443 struct ieee80211_bss_conf *info)
445 struct ieee80211_sta *sta = NULL;
446 int ampdu_density = 0;
447 bool greenfield = false;
449 rcu_read_lock(); // protect sta
450 if (info->bssid && !info->ibss_joined)
451 sta = ieee80211_find_sta(wvif->vif, info->bssid);
452 if (sta && sta->ht_cap.ht_supported)
453 ampdu_density = sta->ht_cap.ampdu_density;
454 if (sta && sta->ht_cap.ht_supported &&
455 !(info->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT))
456 greenfield = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD);
459 wvif->join_in_progress = false;
460 hif_set_association_mode(wvif, ampdu_density, greenfield,
461 info->use_short_preamble);
462 hif_keep_alive_period(wvif, 0);
463 // beacon_loss_count is defined to 7 in net/mac80211/mlme.c. Let's use
465 hif_set_bss_params(wvif, info->aid, 7);
466 hif_set_beacon_wakeup_period(wvif, 1, 1);
470 int wfx_join_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
472 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
474 wfx_upload_ap_templates(wvif);
479 void wfx_leave_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
481 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
486 static void wfx_enable_beacon(struct wfx_vif *wvif, bool enable)
488 // Driver has Content After DTIM Beacon in queue. Driver is waiting for
489 // a signal from the firmware. Since we are going to stop to send
490 // beacons, this signal will never happens. See also
491 // wfx_suspend_resume_mc()
492 if (!enable && wfx_tx_queues_has_cab(wvif)) {
493 wvif->after_dtim_tx_allowed = true;
494 wfx_bh_request_tx(wvif->wdev);
496 hif_beacon_transmit(wvif, enable);
499 void wfx_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
500 struct ieee80211_bss_conf *info, u32 changed)
502 struct wfx_dev *wdev = hw->priv;
503 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
506 mutex_lock(&wdev->conf_mutex);
508 if (changed & BSS_CHANGED_BASIC_RATES ||
509 changed & BSS_CHANGED_BEACON_INT ||
510 changed & BSS_CHANGED_BSSID) {
511 if (vif->type == NL80211_IFTYPE_STATION)
515 if (changed & BSS_CHANGED_ASSOC) {
516 if (info->assoc || info->ibss_joined)
517 wfx_join_finalize(wvif, info);
518 else if (!info->assoc && vif->type == NL80211_IFTYPE_STATION)
521 dev_warn(wdev->dev, "%s: misunderstood change: ASSOC\n",
525 if (changed & BSS_CHANGED_BEACON_INFO) {
526 if (vif->type != NL80211_IFTYPE_STATION)
527 dev_warn(wdev->dev, "%s: misunderstood change: BEACON_INFO\n",
529 hif_set_beacon_wakeup_period(wvif, info->dtim_period,
531 // We temporary forwarded beacon for join process. It is now no
533 wfx_filter_beacon(wvif, true);
536 if (changed & BSS_CHANGED_ARP_FILTER) {
537 for (i = 0; i < HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES; i++) {
538 __be32 *arp_addr = &info->arp_addr_list[i];
540 if (info->arp_addr_cnt > HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES)
542 if (i >= info->arp_addr_cnt)
544 hif_set_arp_ipv4_filter(wvif, i, arp_addr);
548 if (changed & BSS_CHANGED_AP_PROBE_RESP ||
549 changed & BSS_CHANGED_BEACON)
550 wfx_upload_ap_templates(wvif);
552 if (changed & BSS_CHANGED_BEACON_ENABLED)
553 wfx_enable_beacon(wvif, info->enable_beacon);
555 if (changed & BSS_CHANGED_KEEP_ALIVE)
556 hif_keep_alive_period(wvif, info->max_idle_period *
557 USEC_PER_TU / USEC_PER_MSEC);
559 if (changed & BSS_CHANGED_ERP_CTS_PROT)
560 hif_erp_use_protection(wvif, info->use_cts_prot);
562 if (changed & BSS_CHANGED_ERP_SLOT)
563 hif_slot_time(wvif, info->use_short_slot ? 9 : 20);
565 if (changed & BSS_CHANGED_CQM)
566 hif_set_rcpi_rssi_threshold(wvif, info->cqm_rssi_thold,
567 info->cqm_rssi_hyst);
569 if (changed & BSS_CHANGED_TXPOWER)
570 hif_set_output_power(wvif, info->txpower);
572 if (changed & BSS_CHANGED_PS)
575 mutex_unlock(&wdev->conf_mutex);
578 static int wfx_update_tim(struct wfx_vif *wvif)
581 u16 tim_offset, tim_length;
584 skb = ieee80211_beacon_get_tim(wvif->wdev->hw, wvif->vif,
585 &tim_offset, &tim_length);
588 tim_ptr = skb->data + tim_offset;
590 if (tim_offset && tim_length >= 6) {
591 /* Ignore DTIM count from mac80211:
592 * firmware handles DTIM internally.
596 /* Set/reset aid0 bit */
597 if (wfx_tx_queues_has_cab(wvif))
603 hif_update_ie_beacon(wvif, tim_ptr, tim_length);
609 static void wfx_update_tim_work(struct work_struct *work)
611 struct wfx_vif *wvif = container_of(work, struct wfx_vif, update_tim_work);
613 wfx_update_tim(wvif);
616 int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
618 struct wfx_dev *wdev = hw->priv;
619 struct wfx_sta_priv *sta_dev = (struct wfx_sta_priv *)&sta->drv_priv;
620 struct wfx_vif *wvif = wdev_to_wvif(wdev, sta_dev->vif_id);
622 schedule_work(&wvif->update_tim_work);
626 void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd)
628 if (notify_cmd != STA_NOTIFY_AWAKE)
630 WARN(!wfx_tx_queues_has_cab(wvif), "incorrect sequence");
631 WARN(wvif->after_dtim_tx_allowed, "incorrect sequence");
632 wvif->after_dtim_tx_allowed = true;
633 wfx_bh_request_tx(wvif->wdev);
636 int wfx_ampdu_action(struct ieee80211_hw *hw,
637 struct ieee80211_vif *vif,
638 struct ieee80211_ampdu_params *params)
640 // Aggregation is implemented fully in firmware
641 switch (params->action) {
642 case IEEE80211_AMPDU_RX_START:
643 case IEEE80211_AMPDU_RX_STOP:
644 // Just acknowledge it to enable frame re-ordering
647 // Leave the firmware doing its business for tx aggregation
652 int wfx_add_chanctx(struct ieee80211_hw *hw,
653 struct ieee80211_chanctx_conf *conf)
658 void wfx_remove_chanctx(struct ieee80211_hw *hw,
659 struct ieee80211_chanctx_conf *conf)
663 void wfx_change_chanctx(struct ieee80211_hw *hw,
664 struct ieee80211_chanctx_conf *conf,
669 int wfx_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
670 struct ieee80211_chanctx_conf *conf)
672 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
673 struct ieee80211_channel *ch = conf->def.chan;
675 WARN(wvif->channel, "channel overwrite");
681 void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw,
682 struct ieee80211_vif *vif,
683 struct ieee80211_chanctx_conf *conf)
685 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
686 struct ieee80211_channel *ch = conf->def.chan;
688 WARN(wvif->channel != ch, "channel mismatch");
689 wvif->channel = NULL;
692 int wfx_config(struct ieee80211_hw *hw, u32 changed)
697 int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
700 struct wfx_dev *wdev = hw->priv;
701 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
703 vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
704 IEEE80211_VIF_SUPPORTS_UAPSD |
705 IEEE80211_VIF_SUPPORTS_CQM_RSSI;
707 mutex_lock(&wdev->conf_mutex);
710 case NL80211_IFTYPE_STATION:
711 case NL80211_IFTYPE_ADHOC:
712 case NL80211_IFTYPE_AP:
715 mutex_unlock(&wdev->conf_mutex);
719 // FIXME: prefer use of container_of() to get vif
723 wvif->link_id_map = 1; // link-id 0 is reserved for multicast
724 INIT_WORK(&wvif->update_tim_work, wfx_update_tim_work);
725 INIT_DELAYED_WORK(&wvif->beacon_loss_work, wfx_beacon_loss_work);
727 init_completion(&wvif->set_pm_mode_complete);
728 complete(&wvif->set_pm_mode_complete);
729 INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
731 mutex_init(&wvif->scan_lock);
732 init_completion(&wvif->scan_complete);
733 INIT_WORK(&wvif->scan_work, wfx_hw_scan_work);
735 wfx_tx_queues_init(wvif);
736 wfx_tx_policy_init(wvif);
738 for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) {
745 WARN(i == ARRAY_SIZE(wdev->vif), "try to instantiate more vif than supported");
747 hif_set_macaddr(wvif, vif->addr);
749 mutex_unlock(&wdev->conf_mutex);
752 while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
753 // Combo mode does not support Block Acks. We can re-enable them
754 if (wvif_count(wdev) == 1)
755 hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
757 hif_set_block_ack_policy(wvif, 0x00, 0x00);
762 void wfx_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
764 struct wfx_dev *wdev = hw->priv;
765 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
767 wait_for_completion_timeout(&wvif->set_pm_mode_complete, msecs_to_jiffies(300));
768 wfx_tx_queues_check_empty(wvif);
770 mutex_lock(&wdev->conf_mutex);
771 WARN(wvif->link_id_map != 1, "corrupted state");
773 hif_reset(wvif, false);
774 hif_set_macaddr(wvif, NULL);
775 wfx_tx_policy_init(wvif);
777 cancel_delayed_work_sync(&wvif->beacon_loss_work);
778 wdev->vif[wvif->id] = NULL;
781 mutex_unlock(&wdev->conf_mutex);
784 while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
785 // Combo mode does not support Block Acks. We can re-enable them
786 if (wvif_count(wdev) == 1)
787 hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
789 hif_set_block_ack_policy(wvif, 0x00, 0x00);
793 int wfx_start(struct ieee80211_hw *hw)
798 void wfx_stop(struct ieee80211_hw *hw)
800 struct wfx_dev *wdev = hw->priv;
802 WARN_ON(!skb_queue_empty_lockless(&wdev->tx_pending));