1 // SPDX-License-Identifier: GPL-2.0-only
3 * Implementation of mac80211 API.
5 * Copyright (c) 2017-2019, 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 static void wfx_filter_beacon(struct wfx_vif *wvif, bool filter_beacon)
43 const struct hif_ie_table_entry filter_ies[] = {
45 .ie_id = WLAN_EID_VENDOR_SPECIFIC,
49 .oui = { 0x50, 0x6F, 0x9A },
51 .ie_id = WLAN_EID_HT_OPERATION,
56 .ie_id = WLAN_EID_ERP_INFO,
64 hif_set_beacon_filter_table(wvif, 0, NULL);
65 hif_beacon_filter_control(wvif, 0, 1);
67 hif_set_beacon_filter_table(wvif, 3, filter_ies);
68 hif_beacon_filter_control(wvif, HIF_BEACON_FILTER_ENABLE, 0);
72 static void wfx_filter_mcast(struct wfx_vif *wvif, bool filter_mcast)
76 // Temporary workaround for filters
77 hif_set_data_filtering(wvif, false, true);
81 hif_set_data_filtering(wvif, false, true);
84 for (i = 0; i < wvif->filter_mcast_count; i++)
85 hif_set_mac_addr_condition(wvif, i, wvif->filter_mcast_addr[i]);
86 hif_set_uc_mc_bc_condition(wvif, 0,
87 HIF_FILTER_UNICAST | HIF_FILTER_BROADCAST);
88 hif_set_config_data_filter(wvif, true, 0, BIT(1),
89 BIT(wvif->filter_mcast_count) - 1);
90 hif_set_data_filtering(wvif, true, true);
93 u64 wfx_prepare_multicast(struct ieee80211_hw *hw,
94 struct netdev_hw_addr_list *mc_list)
97 struct netdev_hw_addr *ha;
98 struct wfx_vif *wvif = NULL;
99 struct wfx_dev *wdev = hw->priv;
100 int count = netdev_hw_addr_list_count(mc_list);
102 while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
103 if (count > ARRAY_SIZE(wvif->filter_mcast_addr)) {
104 wvif->filter_mcast_count = 0;
107 wvif->filter_mcast_count = count;
110 netdev_hw_addr_list_for_each(ha, mc_list) {
111 ether_addr_copy(wvif->filter_mcast_addr[i], ha->addr);
119 void wfx_configure_filter(struct ieee80211_hw *hw,
120 unsigned int changed_flags,
121 unsigned int *total_flags,
124 struct wfx_vif *wvif = NULL;
125 struct wfx_dev *wdev = hw->priv;
126 bool filter_bssid, filter_prbreq, filter_beacon, filter_mcast;
129 // - Probe responses (FIF_BCN_PRBRESP_PROMISC) are never filtered
130 // - PS-Poll (FIF_PSPOLL) are never filtered
131 // - RTS, CTS and Ack (FIF_CONTROL) are always filtered
132 // - Broken frames (FIF_FCSFAIL and FIF_PLCPFAIL) are always filtered
133 // - Firmware does (yet) allow to forward unicast traffic sent to
134 // other stations (aka. promiscuous mode)
135 *total_flags &= FIF_BCN_PRBRESP_PROMISC | FIF_ALLMULTI | FIF_OTHER_BSS |
136 FIF_PROBE_REQ | FIF_PSPOLL;
138 mutex_lock(&wdev->conf_mutex);
139 while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
140 mutex_lock(&wvif->scan_lock);
142 // Note: FIF_BCN_PRBRESP_PROMISC covers probe response and
143 // beacons from other BSS
144 if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
145 filter_beacon = false;
147 filter_beacon = true;
148 wfx_filter_beacon(wvif, filter_beacon);
150 if (*total_flags & FIF_ALLMULTI) {
151 filter_mcast = false;
152 } else if (!wvif->filter_mcast_count) {
153 dev_dbg(wdev->dev, "disabling unconfigured multicast filter");
154 filter_mcast = false;
158 wfx_filter_mcast(wvif, filter_mcast);
160 if (*total_flags & FIF_OTHER_BSS)
161 filter_bssid = false;
165 // In AP mode, chip can reply to probe request itself
166 if (*total_flags & FIF_PROBE_REQ &&
167 wvif->vif->type == NL80211_IFTYPE_AP) {
168 dev_dbg(wdev->dev, "do not forward probe request in AP mode\n");
169 *total_flags &= ~FIF_PROBE_REQ;
172 if (*total_flags & FIF_PROBE_REQ)
173 filter_prbreq = false;
175 filter_prbreq = true;
176 hif_set_rx_filter(wvif, filter_bssid, filter_prbreq);
178 mutex_unlock(&wvif->scan_lock);
180 mutex_unlock(&wdev->conf_mutex);
183 static int wfx_update_pm(struct wfx_vif *wvif)
185 struct ieee80211_conf *conf = &wvif->wdev->hw->conf;
186 bool ps = conf->flags & IEEE80211_CONF_PS;
187 int ps_timeout = conf->dynamic_ps_timeout;
188 struct ieee80211_channel *chan0 = NULL, *chan1 = NULL;
190 WARN_ON(conf->dynamic_ps_timeout < 0);
191 if (!wvif->vif->bss_conf.assoc)
195 if (wvif->uapsd_mask)
198 // Kernel disable powersave when an AP is in use. In contrary, it is
199 // absolutely necessary to enable legacy powersave for WF200 if channels
201 if (wdev_to_wvif(wvif->wdev, 0))
202 chan0 = wdev_to_wvif(wvif->wdev, 0)->vif->bss_conf.chandef.chan;
203 if (wdev_to_wvif(wvif->wdev, 1))
204 chan1 = wdev_to_wvif(wvif->wdev, 1)->vif->bss_conf.chandef.chan;
205 if (chan0 && chan1 && chan0->hw_value != chan1->hw_value &&
206 wvif->vif->type != NL80211_IFTYPE_AP) {
211 if (!wait_for_completion_timeout(&wvif->set_pm_mode_complete,
213 dev_warn(wvif->wdev->dev,
214 "timeout while waiting of set_pm_mode_complete\n");
215 return hif_set_pm(wvif, ps, ps_timeout);
218 int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
219 u16 queue, const struct ieee80211_tx_queue_params *params)
221 struct wfx_dev *wdev = hw->priv;
222 struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
223 int old_uapsd = wvif->uapsd_mask;
225 WARN_ON(queue >= hw->queues);
227 mutex_lock(&wdev->conf_mutex);
228 assign_bit(queue, &wvif->uapsd_mask, params->uapsd);
229 hif_set_edca_queue_params(wvif, queue, params);
230 if (wvif->vif->type == NL80211_IFTYPE_STATION &&
231 old_uapsd != wvif->uapsd_mask) {
232 hif_set_uapsd_info(wvif, wvif->uapsd_mask);
235 mutex_unlock(&wdev->conf_mutex);
239 int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
241 struct wfx_dev *wdev = hw->priv;
242 struct wfx_vif *wvif = NULL;
244 while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
245 hif_rts_threshold(wvif, value);
251 void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi)
253 /* RSSI: signed Q8.0, RCPI: unsigned Q7.1
254 * RSSI = RCPI / 2 - 110
259 rcpi_rssi = raw_rcpi_rssi / 2 - 110;
260 if (rcpi_rssi <= wvif->vif->bss_conf.cqm_rssi_thold)
261 cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
263 cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
264 ieee80211_cqm_rssi_notify(wvif->vif, cqm_evt, rcpi_rssi, GFP_KERNEL);
267 static void wfx_beacon_loss_work(struct work_struct *work)
269 struct wfx_vif *wvif = container_of(to_delayed_work(work),
270 struct wfx_vif, beacon_loss_work);
271 struct ieee80211_bss_conf *bss_conf = &wvif->vif->bss_conf;
273 ieee80211_beacon_loss(wvif->vif);
274 schedule_delayed_work(to_delayed_work(work),
275 msecs_to_jiffies(bss_conf->beacon_int));
278 void wfx_set_default_unicast_key(struct ieee80211_hw *hw,
279 struct ieee80211_vif *vif, int idx)
281 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
283 hif_wep_default_key_id(wvif, idx);
286 // Call it with wdev->conf_mutex locked
287 static void wfx_do_unjoin(struct wfx_vif *wvif)
289 /* Unjoin is a reset. */
290 wfx_tx_lock_flush(wvif->wdev);
291 hif_reset(wvif, false);
292 wfx_tx_policy_init(wvif);
293 if (wvif_count(wvif->wdev) <= 1)
294 hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
295 wfx_tx_unlock(wvif->wdev);
296 cancel_delayed_work_sync(&wvif->beacon_loss_work);
299 static void wfx_set_mfp(struct wfx_vif *wvif,
300 struct cfg80211_bss *bss)
302 const int pairwise_cipher_suite_count_offset = 8 / sizeof(u16);
303 const int pairwise_cipher_suite_size = 4 / sizeof(u16);
304 const int akm_suite_size = 4 / sizeof(u16);
305 const u16 *ptr = NULL;
309 /* 802.11w protected mgmt frames */
311 /* retrieve MFPC and MFPR flags from beacon or PBRSP */
315 ptr = (const u16 *) ieee80211_bss_get_ie(bss,
319 ptr += pairwise_cipher_suite_count_offset;
320 ptr += 1 + pairwise_cipher_suite_size * *ptr;
321 ptr += 1 + akm_suite_size * *ptr;
322 mfpr = *ptr & BIT(6);
323 mfpc = *ptr & BIT(7);
327 hif_set_mfp(wvif, mfpc, mfpr);
330 static void wfx_do_join(struct wfx_vif *wvif)
333 struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf;
334 struct cfg80211_bss *bss = NULL;
335 u8 ssid[IEEE80211_MAX_SSID_LEN];
336 const u8 *ssidie = NULL;
339 wfx_tx_lock_flush(wvif->wdev);
341 bss = cfg80211_get_bss(wvif->wdev->hw->wiphy, wvif->channel,
342 conf->bssid, NULL, 0,
343 IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY);
344 if (!bss && !conf->ibss_joined) {
345 wfx_tx_unlock(wvif->wdev);
349 rcu_read_lock(); // protect ssidie
351 ssidie = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
354 memcpy(ssid, &ssidie[2], ssidie[1]);
358 wfx_set_mfp(wvif, bss);
359 cfg80211_put_bss(wvif->wdev->hw->wiphy, bss);
361 ret = hif_join(wvif, conf, wvif->channel, ssid, ssidlen);
363 ieee80211_connection_loss(wvif->vif);
366 /* Due to beacon filtering it is possible that the
367 * AP's beacon is not known for the mac80211 stack.
368 * Disable filtering temporary to make sure the stack
369 * receives at least one
371 wfx_filter_beacon(wvif, false);
373 wfx_tx_unlock(wvif->wdev);
376 int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
377 struct ieee80211_sta *sta)
379 struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
380 struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *) &sta->drv_priv;
382 spin_lock_init(&sta_priv->lock);
383 sta_priv->vif_id = wvif->id;
385 // FIXME: in station mode, the current API interprets new link-id as a
387 if (vif->type == NL80211_IFTYPE_STATION)
389 sta_priv->link_id = ffz(wvif->link_id_map);
390 wvif->link_id_map |= BIT(sta_priv->link_id);
391 WARN_ON(!sta_priv->link_id);
392 WARN_ON(sta_priv->link_id >= HIF_LINK_ID_MAX);
393 hif_map_link(wvif, sta->addr, 0, sta_priv->link_id);
398 int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
399 struct ieee80211_sta *sta)
401 struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
402 struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *) &sta->drv_priv;
405 for (i = 0; i < ARRAY_SIZE(sta_priv->buffered); i++)
406 if (sta_priv->buffered[i])
407 dev_warn(wvif->wdev->dev, "release station while %d pending frame on queue %d",
408 sta_priv->buffered[i], i);
409 // FIXME: see note in wfx_sta_add()
410 if (vif->type == NL80211_IFTYPE_STATION)
412 // FIXME add a mutex?
413 hif_map_link(wvif, sta->addr, 1, sta_priv->link_id);
414 wvif->link_id_map &= ~BIT(sta_priv->link_id);
418 static int wfx_upload_ap_templates(struct wfx_vif *wvif)
422 skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif);
425 hif_set_template_frame(wvif, skb, HIF_TMPLT_BCN,
426 API_RATE_INDEX_B_1MBPS);
429 skb = ieee80211_proberesp_get(wvif->wdev->hw, wvif->vif);
432 hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBRES,
433 API_RATE_INDEX_B_1MBPS);
438 int wfx_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
440 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
442 wfx_upload_ap_templates(wvif);
443 hif_start(wvif, &vif->bss_conf, wvif->channel);
447 void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
449 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
451 hif_reset(wvif, false);
452 wfx_tx_policy_init(wvif);
453 if (wvif_count(wvif->wdev) <= 1)
454 hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
457 static void wfx_join_finalize(struct wfx_vif *wvif,
458 struct ieee80211_bss_conf *info)
460 hif_set_association_mode(wvif, info);
461 hif_keep_alive_period(wvif, 0);
462 // beacon_loss_count is defined to 7 in net/mac80211/mlme.c. Let's use
464 hif_set_bss_params(wvif, info->aid, 7);
465 hif_set_beacon_wakeup_period(wvif, 1, 1);
469 int wfx_join_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
471 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
473 wfx_upload_ap_templates(wvif);
478 void wfx_leave_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
480 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
485 void wfx_enable_beacon(struct wfx_vif *wvif, bool enable)
487 // Driver has Content After DTIM Beacon in queue. Driver is waiting for
488 // a signal from the firmware. Since we are going to stop to send
489 // beacons, this signal will never happens. See also
490 // wfx_suspend_resume_mc()
491 if (!enable && wfx_tx_queues_has_cab(wvif)) {
492 wvif->after_dtim_tx_allowed = true;
493 wfx_bh_request_tx(wvif->wdev);
495 hif_beacon_transmit(wvif, enable);
498 void wfx_bss_info_changed(struct ieee80211_hw *hw,
499 struct ieee80211_vif *vif,
500 struct ieee80211_bss_conf *info,
503 struct wfx_dev *wdev = hw->priv;
504 struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
507 mutex_lock(&wdev->conf_mutex);
509 /* TODO: BSS_CHANGED_QOS */
510 if (changed & BSS_CHANGED_ARP_FILTER) {
511 for (i = 0; i < HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES; i++) {
512 __be32 *arp_addr = &info->arp_addr_list[i];
514 if (info->arp_addr_cnt > HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES)
516 if (i >= info->arp_addr_cnt)
518 hif_set_arp_ipv4_filter(wvif, i, arp_addr);
522 if (changed & BSS_CHANGED_BASIC_RATES ||
523 changed & BSS_CHANGED_BEACON_INT ||
524 changed & BSS_CHANGED_BSSID) {
525 if (vif->type == NL80211_IFTYPE_STATION)
529 if (changed & BSS_CHANGED_AP_PROBE_RESP ||
530 changed & BSS_CHANGED_BEACON)
531 wfx_upload_ap_templates(wvif);
533 if (changed & BSS_CHANGED_BEACON_ENABLED)
534 wfx_enable_beacon(wvif, info->enable_beacon);
536 if (changed & BSS_CHANGED_BEACON_INFO) {
537 if (vif->type != NL80211_IFTYPE_STATION)
538 dev_warn(wdev->dev, "%s: misunderstood change: BEACON_INFO\n",
540 hif_set_beacon_wakeup_period(wvif, info->dtim_period,
542 // We temporary forwarded beacon for join process. It is now no
544 wfx_filter_beacon(wvif, true);
547 if (changed & BSS_CHANGED_ASSOC) {
548 if (info->assoc || info->ibss_joined)
549 wfx_join_finalize(wvif, info);
550 else if (!info->assoc && vif->type == NL80211_IFTYPE_STATION)
553 dev_warn(wdev->dev, "%s: misunderstood change: ASSOC\n",
557 if (changed & BSS_CHANGED_KEEP_ALIVE)
558 hif_keep_alive_period(wvif, info->max_idle_period *
559 USEC_PER_TU / USEC_PER_MSEC);
561 if (changed & BSS_CHANGED_ERP_CTS_PROT)
562 hif_erp_use_protection(wvif, info->use_cts_prot);
564 if (changed & BSS_CHANGED_ERP_SLOT)
565 hif_slot_time(wvif, info->use_short_slot ? 9 : 20);
567 if (changed & BSS_CHANGED_CQM)
568 hif_set_rcpi_rssi_threshold(wvif, info->cqm_rssi_thold,
569 info->cqm_rssi_hyst);
571 if (changed & BSS_CHANGED_TXPOWER)
572 hif_set_output_power(wvif, info->txpower);
574 if (changed & BSS_CHANGED_PS)
577 mutex_unlock(&wdev->conf_mutex);
580 static int wfx_update_tim(struct wfx_vif *wvif)
583 u16 tim_offset, tim_length;
586 skb = ieee80211_beacon_get_tim(wvif->wdev->hw, wvif->vif,
587 &tim_offset, &tim_length);
590 tim_ptr = skb->data + tim_offset;
592 if (tim_offset && tim_length >= 6) {
593 /* Ignore DTIM count from mac80211:
594 * firmware handles DTIM internally.
598 /* Set/reset aid0 bit */
599 if (wfx_tx_queues_has_cab(wvif))
605 hif_update_ie_beacon(wvif, tim_ptr, tim_length);
611 static void wfx_update_tim_work(struct work_struct *work)
613 struct wfx_vif *wvif = container_of(work, struct wfx_vif, update_tim_work);
615 wfx_update_tim(wvif);
618 int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
620 struct wfx_dev *wdev = hw->priv;
621 struct wfx_sta_priv *sta_dev = (struct wfx_sta_priv *)&sta->drv_priv;
622 struct wfx_vif *wvif = wdev_to_wvif(wdev, sta_dev->vif_id);
624 schedule_work(&wvif->update_tim_work);
628 void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd)
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 * including block ack negotiation. Do not allow
642 * mac80211 stack to do anything: it interferes with
646 /* Note that we still need this function stubbed. */
651 int wfx_add_chanctx(struct ieee80211_hw *hw,
652 struct ieee80211_chanctx_conf *conf)
657 void wfx_remove_chanctx(struct ieee80211_hw *hw,
658 struct ieee80211_chanctx_conf *conf)
662 void wfx_change_chanctx(struct ieee80211_hw *hw,
663 struct ieee80211_chanctx_conf *conf,
668 int wfx_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
669 struct ieee80211_chanctx_conf *conf)
671 struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
672 struct ieee80211_channel *ch = conf->def.chan;
674 WARN(wvif->channel, "channel overwrite");
680 void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw,
681 struct ieee80211_vif *vif,
682 struct ieee80211_chanctx_conf *conf)
684 struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
685 struct ieee80211_channel *ch = conf->def.chan;
687 WARN(wvif->channel != ch, "channel mismatch");
688 wvif->channel = NULL;
691 int wfx_config(struct ieee80211_hw *hw, u32 changed)
696 int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
699 struct wfx_dev *wdev = hw->priv;
700 struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
702 vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
703 IEEE80211_VIF_SUPPORTS_UAPSD |
704 IEEE80211_VIF_SUPPORTS_CQM_RSSI;
706 mutex_lock(&wdev->conf_mutex);
709 case NL80211_IFTYPE_STATION:
710 case NL80211_IFTYPE_ADHOC:
711 case NL80211_IFTYPE_AP:
714 mutex_unlock(&wdev->conf_mutex);
718 for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) {
725 if (i == ARRAY_SIZE(wdev->vif)) {
726 mutex_unlock(&wdev->conf_mutex);
729 // FIXME: prefer use of container_of() to get vif
733 wvif->link_id_map = 1; // link-id 0 is reserved for multicast
734 INIT_WORK(&wvif->update_tim_work, wfx_update_tim_work);
735 INIT_DELAYED_WORK(&wvif->beacon_loss_work, wfx_beacon_loss_work);
737 init_completion(&wvif->set_pm_mode_complete);
738 complete(&wvif->set_pm_mode_complete);
739 INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
741 mutex_init(&wvif->scan_lock);
742 init_completion(&wvif->scan_complete);
743 INIT_WORK(&wvif->scan_work, wfx_hw_scan_work);
745 INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
746 mutex_unlock(&wdev->conf_mutex);
748 hif_set_macaddr(wvif, vif->addr);
750 wfx_tx_policy_init(wvif);
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);
758 // Combo force powersave mode. We can re-enable it now
759 ret = wfx_update_pm(wvif);
764 void wfx_remove_interface(struct ieee80211_hw *hw,
765 struct ieee80211_vif *vif)
767 struct wfx_dev *wdev = hw->priv;
768 struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
770 wait_for_completion_timeout(&wvif->set_pm_mode_complete, msecs_to_jiffies(300));
772 mutex_lock(&wdev->conf_mutex);
773 WARN(wvif->link_id_map != 1, "corrupted state");
775 hif_reset(wvif, false);
776 hif_set_macaddr(wvif, NULL);
777 wfx_tx_policy_init(wvif);
779 cancel_delayed_work_sync(&wvif->beacon_loss_work);
780 wdev->vif[wvif->id] = NULL;
783 mutex_unlock(&wdev->conf_mutex);
785 while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
786 // Combo mode does not support Block Acks. We can re-enable them
787 if (wvif_count(wdev) == 1)
788 hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
790 hif_set_block_ack_policy(wvif, 0x00, 0x00);
791 // Combo force powersave mode. We can re-enable it now
796 int wfx_start(struct ieee80211_hw *hw)
801 void wfx_stop(struct ieee80211_hw *hw)
803 struct wfx_dev *wdev = hw->priv;
805 wfx_tx_queues_check_empty(wdev);