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) {
208 if (wvif->bss_not_support_ps_poll)
214 if (!wait_for_completion_timeout(&wvif->set_pm_mode_complete,
216 dev_warn(wvif->wdev->dev,
217 "timeout while waiting of set_pm_mode_complete\n");
218 return hif_set_pm(wvif, ps, ps_timeout);
221 static void wfx_update_pm_work(struct work_struct *work)
223 struct wfx_vif *wvif = container_of(work, struct wfx_vif,
229 int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
230 u16 queue, const struct ieee80211_tx_queue_params *params)
232 struct wfx_dev *wdev = hw->priv;
233 struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
234 int old_uapsd = wvif->uapsd_mask;
236 WARN_ON(queue >= hw->queues);
238 mutex_lock(&wdev->conf_mutex);
239 assign_bit(queue, &wvif->uapsd_mask, params->uapsd);
240 hif_set_edca_queue_params(wvif, queue, params);
241 if (wvif->vif->type == NL80211_IFTYPE_STATION &&
242 old_uapsd != wvif->uapsd_mask) {
243 hif_set_uapsd_info(wvif, wvif->uapsd_mask);
246 mutex_unlock(&wdev->conf_mutex);
250 int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
252 struct wfx_dev *wdev = hw->priv;
253 struct wfx_vif *wvif = NULL;
255 while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
256 hif_rts_threshold(wvif, value);
262 void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi)
264 /* RSSI: signed Q8.0, RCPI: unsigned Q7.1
265 * RSSI = RCPI / 2 - 110
270 rcpi_rssi = raw_rcpi_rssi / 2 - 110;
271 if (rcpi_rssi <= wvif->vif->bss_conf.cqm_rssi_thold)
272 cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
274 cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
275 ieee80211_cqm_rssi_notify(wvif->vif, cqm_evt, rcpi_rssi, GFP_KERNEL);
278 static void wfx_beacon_loss_work(struct work_struct *work)
280 struct wfx_vif *wvif = container_of(to_delayed_work(work),
281 struct wfx_vif, beacon_loss_work);
282 struct ieee80211_bss_conf *bss_conf = &wvif->vif->bss_conf;
284 ieee80211_beacon_loss(wvif->vif);
285 schedule_delayed_work(to_delayed_work(work),
286 msecs_to_jiffies(bss_conf->beacon_int));
289 void wfx_set_default_unicast_key(struct ieee80211_hw *hw,
290 struct ieee80211_vif *vif, int idx)
292 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
294 hif_wep_default_key_id(wvif, idx);
297 // Call it with wdev->conf_mutex locked
298 static void wfx_do_unjoin(struct wfx_vif *wvif)
300 /* Unjoin is a reset. */
301 wfx_tx_lock_flush(wvif->wdev);
302 hif_reset(wvif, false);
303 wfx_tx_policy_init(wvif);
304 if (wvif_count(wvif->wdev) <= 1)
305 hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
306 wfx_tx_unlock(wvif->wdev);
307 wvif->bss_not_support_ps_poll = false;
308 cancel_delayed_work_sync(&wvif->beacon_loss_work);
311 static void wfx_set_mfp(struct wfx_vif *wvif,
312 struct cfg80211_bss *bss)
314 const int pairwise_cipher_suite_count_offset = 8 / sizeof(u16);
315 const int pairwise_cipher_suite_size = 4 / sizeof(u16);
316 const int akm_suite_size = 4 / sizeof(u16);
317 const u16 *ptr = NULL;
321 /* 802.11w protected mgmt frames */
323 /* retrieve MFPC and MFPR flags from beacon or PBRSP */
327 ptr = (const u16 *) ieee80211_bss_get_ie(bss,
331 ptr += pairwise_cipher_suite_count_offset;
332 ptr += 1 + pairwise_cipher_suite_size * *ptr;
333 ptr += 1 + akm_suite_size * *ptr;
334 mfpr = *ptr & BIT(6);
335 mfpc = *ptr & BIT(7);
339 hif_set_mfp(wvif, mfpc, mfpr);
342 static void wfx_do_join(struct wfx_vif *wvif)
345 struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf;
346 struct cfg80211_bss *bss = NULL;
347 u8 ssid[IEEE80211_MAX_SSID_LEN];
348 const u8 *ssidie = NULL;
351 wfx_tx_lock_flush(wvif->wdev);
353 bss = cfg80211_get_bss(wvif->wdev->hw->wiphy, wvif->channel,
354 conf->bssid, NULL, 0,
355 IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY);
356 if (!bss && !conf->ibss_joined) {
357 wfx_tx_unlock(wvif->wdev);
361 rcu_read_lock(); // protect ssidie
363 ssidie = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
366 if (ssidlen > IEEE80211_MAX_SSID_LEN)
367 ssidlen = IEEE80211_MAX_SSID_LEN;
368 memcpy(ssid, &ssidie[2], ssidlen);
372 wfx_set_mfp(wvif, bss);
373 cfg80211_put_bss(wvif->wdev->hw->wiphy, bss);
375 ret = hif_join(wvif, conf, wvif->channel, ssid, ssidlen);
377 ieee80211_connection_loss(wvif->vif);
380 /* Due to beacon filtering it is possible that the
381 * AP's beacon is not known for the mac80211 stack.
382 * Disable filtering temporary to make sure the stack
383 * receives at least one
385 wfx_filter_beacon(wvif, false);
387 wfx_tx_unlock(wvif->wdev);
390 int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
391 struct ieee80211_sta *sta)
393 struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
394 struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *) &sta->drv_priv;
396 spin_lock_init(&sta_priv->lock);
397 sta_priv->vif_id = wvif->id;
399 // In station mode, the firmware interprets new link-id as a TDLS peer.
400 if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
402 sta_priv->link_id = ffz(wvif->link_id_map);
403 wvif->link_id_map |= BIT(sta_priv->link_id);
404 WARN_ON(!sta_priv->link_id);
405 WARN_ON(sta_priv->link_id >= HIF_LINK_ID_MAX);
406 hif_map_link(wvif, sta->addr, 0, sta_priv->link_id);
411 int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
412 struct ieee80211_sta *sta)
414 struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
415 struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *) &sta->drv_priv;
418 for (i = 0; i < ARRAY_SIZE(sta_priv->buffered); i++)
419 if (sta_priv->buffered[i])
420 dev_warn(wvif->wdev->dev, "release station while %d pending frame on queue %d",
421 sta_priv->buffered[i], i);
422 // See note in wfx_sta_add()
423 if (!sta_priv->link_id)
425 // FIXME add a mutex?
426 hif_map_link(wvif, sta->addr, 1, sta_priv->link_id);
427 wvif->link_id_map &= ~BIT(sta_priv->link_id);
431 static int wfx_upload_ap_templates(struct wfx_vif *wvif)
435 skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif);
438 hif_set_template_frame(wvif, skb, HIF_TMPLT_BCN,
439 API_RATE_INDEX_B_1MBPS);
442 skb = ieee80211_proberesp_get(wvif->wdev->hw, wvif->vif);
445 hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBRES,
446 API_RATE_INDEX_B_1MBPS);
451 int wfx_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
453 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
455 wfx_upload_ap_templates(wvif);
456 hif_start(wvif, &vif->bss_conf, wvif->channel);
460 void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
462 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
464 hif_reset(wvif, false);
465 wfx_tx_policy_init(wvif);
466 if (wvif_count(wvif->wdev) <= 1)
467 hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
468 wvif->bss_not_support_ps_poll = false;
471 static void wfx_join_finalize(struct wfx_vif *wvif,
472 struct ieee80211_bss_conf *info)
474 hif_set_association_mode(wvif, info);
475 hif_keep_alive_period(wvif, 0);
476 // beacon_loss_count is defined to 7 in net/mac80211/mlme.c. Let's use
478 hif_set_bss_params(wvif, info->aid, 7);
479 hif_set_beacon_wakeup_period(wvif, 1, 1);
483 int wfx_join_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
485 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
487 wfx_upload_ap_templates(wvif);
492 void wfx_leave_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
494 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
499 void wfx_enable_beacon(struct wfx_vif *wvif, bool enable)
501 // Driver has Content After DTIM Beacon in queue. Driver is waiting for
502 // a signal from the firmware. Since we are going to stop to send
503 // beacons, this signal will never happens. See also
504 // wfx_suspend_resume_mc()
505 if (!enable && wfx_tx_queues_has_cab(wvif)) {
506 wvif->after_dtim_tx_allowed = true;
507 wfx_bh_request_tx(wvif->wdev);
509 hif_beacon_transmit(wvif, enable);
512 void wfx_bss_info_changed(struct ieee80211_hw *hw,
513 struct ieee80211_vif *vif,
514 struct ieee80211_bss_conf *info,
517 struct wfx_dev *wdev = hw->priv;
518 struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
521 mutex_lock(&wdev->conf_mutex);
523 /* TODO: BSS_CHANGED_QOS */
524 if (changed & BSS_CHANGED_ARP_FILTER) {
525 for (i = 0; i < HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES; i++) {
526 __be32 *arp_addr = &info->arp_addr_list[i];
528 if (info->arp_addr_cnt > HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES)
530 if (i >= info->arp_addr_cnt)
532 hif_set_arp_ipv4_filter(wvif, i, arp_addr);
536 if (changed & BSS_CHANGED_BASIC_RATES ||
537 changed & BSS_CHANGED_BEACON_INT ||
538 changed & BSS_CHANGED_BSSID) {
539 if (vif->type == NL80211_IFTYPE_STATION)
543 if (changed & BSS_CHANGED_AP_PROBE_RESP ||
544 changed & BSS_CHANGED_BEACON)
545 wfx_upload_ap_templates(wvif);
547 if (changed & BSS_CHANGED_BEACON_ENABLED)
548 wfx_enable_beacon(wvif, info->enable_beacon);
550 if (changed & BSS_CHANGED_BEACON_INFO) {
551 if (vif->type != NL80211_IFTYPE_STATION)
552 dev_warn(wdev->dev, "%s: misunderstood change: BEACON_INFO\n",
554 hif_set_beacon_wakeup_period(wvif, info->dtim_period,
556 // We temporary forwarded beacon for join process. It is now no
558 wfx_filter_beacon(wvif, true);
561 if (changed & BSS_CHANGED_ASSOC) {
562 if (info->assoc || info->ibss_joined)
563 wfx_join_finalize(wvif, info);
564 else if (!info->assoc && vif->type == NL80211_IFTYPE_STATION)
567 dev_warn(wdev->dev, "%s: misunderstood change: ASSOC\n",
571 if (changed & BSS_CHANGED_KEEP_ALIVE)
572 hif_keep_alive_period(wvif, info->max_idle_period *
573 USEC_PER_TU / USEC_PER_MSEC);
575 if (changed & BSS_CHANGED_ERP_CTS_PROT)
576 hif_erp_use_protection(wvif, info->use_cts_prot);
578 if (changed & BSS_CHANGED_ERP_SLOT)
579 hif_slot_time(wvif, info->use_short_slot ? 9 : 20);
581 if (changed & BSS_CHANGED_CQM)
582 hif_set_rcpi_rssi_threshold(wvif, info->cqm_rssi_thold,
583 info->cqm_rssi_hyst);
585 if (changed & BSS_CHANGED_TXPOWER)
586 hif_set_output_power(wvif, info->txpower);
588 if (changed & BSS_CHANGED_PS)
591 mutex_unlock(&wdev->conf_mutex);
594 static int wfx_update_tim(struct wfx_vif *wvif)
597 u16 tim_offset, tim_length;
600 skb = ieee80211_beacon_get_tim(wvif->wdev->hw, wvif->vif,
601 &tim_offset, &tim_length);
604 tim_ptr = skb->data + tim_offset;
606 if (tim_offset && tim_length >= 6) {
607 /* Ignore DTIM count from mac80211:
608 * firmware handles DTIM internally.
612 /* Set/reset aid0 bit */
613 if (wfx_tx_queues_has_cab(wvif))
619 hif_update_ie_beacon(wvif, tim_ptr, tim_length);
625 static void wfx_update_tim_work(struct work_struct *work)
627 struct wfx_vif *wvif = container_of(work, struct wfx_vif, update_tim_work);
629 wfx_update_tim(wvif);
632 int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
634 struct wfx_dev *wdev = hw->priv;
635 struct wfx_sta_priv *sta_dev = (struct wfx_sta_priv *)&sta->drv_priv;
636 struct wfx_vif *wvif = wdev_to_wvif(wdev, sta_dev->vif_id);
638 schedule_work(&wvif->update_tim_work);
642 void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd)
644 WARN(!wfx_tx_queues_has_cab(wvif), "incorrect sequence");
645 WARN(wvif->after_dtim_tx_allowed, "incorrect sequence");
646 wvif->after_dtim_tx_allowed = true;
647 wfx_bh_request_tx(wvif->wdev);
650 int wfx_ampdu_action(struct ieee80211_hw *hw,
651 struct ieee80211_vif *vif,
652 struct ieee80211_ampdu_params *params)
654 /* Aggregation is implemented fully in firmware,
655 * including block ack negotiation. Do not allow
656 * mac80211 stack to do anything: it interferes with
660 /* Note that we still need this function stubbed. */
665 int wfx_add_chanctx(struct ieee80211_hw *hw,
666 struct ieee80211_chanctx_conf *conf)
671 void wfx_remove_chanctx(struct ieee80211_hw *hw,
672 struct ieee80211_chanctx_conf *conf)
676 void wfx_change_chanctx(struct ieee80211_hw *hw,
677 struct ieee80211_chanctx_conf *conf,
682 int wfx_assign_vif_chanctx(struct ieee80211_hw *hw, 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, "channel overwrite");
694 void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw,
695 struct ieee80211_vif *vif,
696 struct ieee80211_chanctx_conf *conf)
698 struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
699 struct ieee80211_channel *ch = conf->def.chan;
701 WARN(wvif->channel != ch, "channel mismatch");
702 wvif->channel = NULL;
705 int wfx_config(struct ieee80211_hw *hw, u32 changed)
710 int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
713 struct wfx_dev *wdev = hw->priv;
714 struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
716 vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
717 IEEE80211_VIF_SUPPORTS_UAPSD |
718 IEEE80211_VIF_SUPPORTS_CQM_RSSI;
720 mutex_lock(&wdev->conf_mutex);
723 case NL80211_IFTYPE_STATION:
724 case NL80211_IFTYPE_ADHOC:
725 case NL80211_IFTYPE_AP:
728 mutex_unlock(&wdev->conf_mutex);
732 for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) {
739 if (i == ARRAY_SIZE(wdev->vif)) {
740 mutex_unlock(&wdev->conf_mutex);
743 // FIXME: prefer use of container_of() to get vif
747 wvif->link_id_map = 1; // link-id 0 is reserved for multicast
748 INIT_WORK(&wvif->update_tim_work, wfx_update_tim_work);
749 INIT_DELAYED_WORK(&wvif->beacon_loss_work, wfx_beacon_loss_work);
751 init_completion(&wvif->set_pm_mode_complete);
752 complete(&wvif->set_pm_mode_complete);
753 INIT_WORK(&wvif->update_pm_work, wfx_update_pm_work);
754 INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
756 mutex_init(&wvif->scan_lock);
757 init_completion(&wvif->scan_complete);
758 INIT_WORK(&wvif->scan_work, wfx_hw_scan_work);
760 INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
761 mutex_unlock(&wdev->conf_mutex);
763 hif_set_macaddr(wvif, vif->addr);
765 wfx_tx_policy_init(wvif);
767 while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
768 // Combo mode does not support Block Acks. We can re-enable them
769 if (wvif_count(wdev) == 1)
770 hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
772 hif_set_block_ack_policy(wvif, 0x00, 0x00);
773 // Combo force powersave mode. We can re-enable it now
774 ret = wfx_update_pm(wvif);
779 void wfx_remove_interface(struct ieee80211_hw *hw,
780 struct ieee80211_vif *vif)
782 struct wfx_dev *wdev = hw->priv;
783 struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
785 wait_for_completion_timeout(&wvif->set_pm_mode_complete, msecs_to_jiffies(300));
787 mutex_lock(&wdev->conf_mutex);
788 WARN(wvif->link_id_map != 1, "corrupted state");
790 hif_reset(wvif, false);
791 hif_set_macaddr(wvif, NULL);
792 wfx_tx_policy_init(wvif);
794 cancel_delayed_work_sync(&wvif->beacon_loss_work);
795 wdev->vif[wvif->id] = NULL;
798 mutex_unlock(&wdev->conf_mutex);
800 while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
801 // Combo mode does not support Block Acks. We can re-enable them
802 if (wvif_count(wdev) == 1)
803 hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
805 hif_set_block_ack_policy(wvif, 0x00, 0x00);
806 // Combo force powersave mode. We can re-enable it now
811 int wfx_start(struct ieee80211_hw *hw)
816 void wfx_stop(struct ieee80211_hw *hw)
818 struct wfx_dev *wdev = hw->priv;
820 wfx_tx_queues_check_empty(wdev);