5d5c8951f50b1f98505ee77dd8c1ae7cddbf2c77
[linux-2.6-microblaze.git] / drivers / staging / wfx / sta.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Implementation of mac80211 API.
4  *
5  * Copyright (c) 2017-2019, Silicon Laboratories, Inc.
6  * Copyright (c) 2010, ST-Ericsson
7  */
8 #include <linux/etherdevice.h>
9 #include <net/mac80211.h>
10
11 #include "sta.h"
12 #include "wfx.h"
13 #include "fwio.h"
14 #include "bh.h"
15 #include "key.h"
16 #include "scan.h"
17 #include "debug.h"
18 #include "hif_tx.h"
19 #include "hif_tx_mib.h"
20
21 #define HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES 2
22
23 u32 wfx_rate_mask_to_hw(struct wfx_dev *wdev, u32 rates)
24 {
25         int i;
26         u32 ret = 0;
27         // WFx only support 2GHz
28         struct ieee80211_supported_band *sband = wdev->hw->wiphy->bands[NL80211_BAND_2GHZ];
29
30         for (i = 0; i < sband->n_bitrates; i++) {
31                 if (rates & BIT(i)) {
32                         if (i >= sband->n_bitrates)
33                                 dev_warn(wdev->dev, "unsupported basic rate\n");
34                         else
35                                 ret |= BIT(sband->bitrates[i].hw_value);
36                 }
37         }
38         return ret;
39 }
40
41 static void wfx_filter_beacon(struct wfx_vif *wvif, bool filter_beacon)
42 {
43         const struct hif_ie_table_entry filter_ies[] = {
44                 {
45                         .ie_id        = WLAN_EID_VENDOR_SPECIFIC,
46                         .has_changed  = 1,
47                         .no_longer    = 1,
48                         .has_appeared = 1,
49                         .oui          = { 0x50, 0x6F, 0x9A },
50                 }, {
51                         .ie_id        = WLAN_EID_HT_OPERATION,
52                         .has_changed  = 1,
53                         .no_longer    = 1,
54                         .has_appeared = 1,
55                 }, {
56                         .ie_id        = WLAN_EID_ERP_INFO,
57                         .has_changed  = 1,
58                         .no_longer    = 1,
59                         .has_appeared = 1,
60                 }
61         };
62
63         if (!filter_beacon) {
64                 hif_set_beacon_filter_table(wvif, 0, NULL);
65                 hif_beacon_filter_control(wvif, 0, 1);
66         } else {
67                 hif_set_beacon_filter_table(wvif, 3, filter_ies);
68                 hif_beacon_filter_control(wvif, HIF_BEACON_FILTER_ENABLE, 0);
69         }
70 }
71
72 static void wfx_filter_mcast(struct wfx_vif *wvif, bool filter_mcast)
73 {
74         int i;
75
76         // Temporary workaround for filters
77         hif_set_data_filtering(wvif, false, true);
78         return;
79
80         if (!filter_mcast) {
81                 hif_set_data_filtering(wvif, false, true);
82                 return;
83         }
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);
91 }
92
93 u64 wfx_prepare_multicast(struct ieee80211_hw *hw,
94                           struct netdev_hw_addr_list *mc_list)
95 {
96         int i;
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);
101
102         while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
103                 if (count > ARRAY_SIZE(wvif->filter_mcast_addr)) {
104                         wvif->filter_mcast_count = 0;
105                         continue;
106                 }
107                 wvif->filter_mcast_count = count;
108
109                 i = 0;
110                 netdev_hw_addr_list_for_each(ha, mc_list) {
111                         ether_addr_copy(wvif->filter_mcast_addr[i], ha->addr);
112                         i++;
113                 }
114         }
115
116         return 0;
117 }
118
119 void wfx_configure_filter(struct ieee80211_hw *hw,
120                              unsigned int changed_flags,
121                              unsigned int *total_flags,
122                              u64 unused)
123 {
124         struct wfx_vif *wvif = NULL;
125         struct wfx_dev *wdev = hw->priv;
126         bool filter_bssid, filter_prbreq, filter_beacon, filter_mcast;
127
128         // Notes:
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;
137
138         mutex_lock(&wdev->conf_mutex);
139         while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
140                 mutex_lock(&wvif->scan_lock);
141
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;
146                 else
147                         filter_beacon = true;
148                 wfx_filter_beacon(wvif, filter_beacon);
149
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;
155                 } else {
156                         filter_mcast = true;
157                 }
158                 wfx_filter_mcast(wvif, filter_mcast);
159
160                 if (*total_flags & FIF_OTHER_BSS)
161                         filter_bssid = false;
162                 else
163                         filter_bssid = true;
164
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;
170                 }
171
172                 if (*total_flags & FIF_PROBE_REQ)
173                         filter_prbreq = false;
174                 else
175                         filter_prbreq = true;
176                 hif_set_rx_filter(wvif, filter_bssid, filter_prbreq);
177
178                 mutex_unlock(&wvif->scan_lock);
179         }
180         mutex_unlock(&wdev->conf_mutex);
181 }
182
183 static int wfx_update_pm(struct wfx_vif *wvif)
184 {
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;
189
190         WARN_ON(conf->dynamic_ps_timeout < 0);
191         if (!wvif->vif->bss_conf.assoc)
192                 return 0;
193         if (!ps)
194                 ps_timeout = 0;
195         if (wvif->uapsd_mask)
196                 ps_timeout = 0;
197
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
200         // are differents.
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) {
207                 ps = true;
208                 ps_timeout = 0;
209         }
210
211         if (!wait_for_completion_timeout(&wvif->set_pm_mode_complete,
212                                          TU_TO_JIFFIES(512)))
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);
216 }
217
218 int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
219                    u16 queue, const struct ieee80211_tx_queue_params *params)
220 {
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;
224
225         WARN_ON(queue >= hw->queues);
226
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);
233                 wfx_update_pm(wvif);
234         }
235         mutex_unlock(&wdev->conf_mutex);
236         return 0;
237 }
238
239 int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
240 {
241         struct wfx_dev *wdev = hw->priv;
242         struct wfx_vif *wvif = NULL;
243
244         while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
245                 hif_rts_threshold(wvif, value);
246         return 0;
247 }
248
249 /* WSM callbacks */
250
251 void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi)
252 {
253         /* RSSI: signed Q8.0, RCPI: unsigned Q7.1
254          * RSSI = RCPI / 2 - 110
255          */
256         int rcpi_rssi;
257         int cqm_evt;
258
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;
262         else
263                 cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
264         ieee80211_cqm_rssi_notify(wvif->vif, cqm_evt, rcpi_rssi, GFP_KERNEL);
265 }
266
267 static void wfx_beacon_loss_work(struct work_struct *work)
268 {
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;
272
273         ieee80211_beacon_loss(wvif->vif);
274         schedule_delayed_work(to_delayed_work(work),
275                               msecs_to_jiffies(bss_conf->beacon_int));
276 }
277
278 void wfx_set_default_unicast_key(struct ieee80211_hw *hw,
279                                  struct ieee80211_vif *vif, int idx)
280 {
281         struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
282
283         hif_wep_default_key_id(wvif, idx);
284 }
285
286 // Call it with wdev->conf_mutex locked
287 static void wfx_do_unjoin(struct wfx_vif *wvif)
288 {
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);
297 }
298
299 static void wfx_set_mfp(struct wfx_vif *wvif,
300                         struct cfg80211_bss *bss)
301 {
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;
306         bool mfpc = false;
307         bool mfpr = false;
308
309         /* 802.11w protected mgmt frames */
310
311         /* retrieve MFPC and MFPR flags from beacon or PBRSP */
312
313         rcu_read_lock();
314         if (bss)
315                 ptr = (const u16 *) ieee80211_bss_get_ie(bss,
316                                                               WLAN_EID_RSN);
317
318         if (ptr) {
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);
324         }
325         rcu_read_unlock();
326
327         hif_set_mfp(wvif, mfpc, mfpr);
328 }
329
330 static void wfx_do_join(struct wfx_vif *wvif)
331 {
332         int ret;
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;
337         int ssidlen = 0;
338
339         wfx_tx_lock_flush(wvif->wdev);
340
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);
346                 return;
347         }
348
349         rcu_read_lock(); // protect ssidie
350         if (bss)
351                 ssidie = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
352         if (ssidie) {
353                 ssidlen = ssidie[1];
354                 memcpy(ssid, &ssidie[2], ssidie[1]);
355         }
356         rcu_read_unlock();
357
358         wfx_set_mfp(wvif, bss);
359         cfg80211_put_bss(wvif->wdev->hw->wiphy, bss);
360
361         ret = hif_join(wvif, conf, wvif->channel, ssid, ssidlen);
362         if (ret) {
363                 ieee80211_connection_loss(wvif->vif);
364                 wfx_do_unjoin(wvif);
365         } else {
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
370                  */
371                 wfx_filter_beacon(wvif, false);
372         }
373         wfx_tx_unlock(wvif->wdev);
374 }
375
376 int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
377                 struct ieee80211_sta *sta)
378 {
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;
381
382         spin_lock_init(&sta_priv->lock);
383         sta_priv->vif_id = wvif->id;
384
385         // FIXME: in station mode, the current API interprets new link-id as a
386         // tdls peer.
387         if (vif->type == NL80211_IFTYPE_STATION)
388                 return 0;
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);
394
395         return 0;
396 }
397
398 int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
399                    struct ieee80211_sta *sta)
400 {
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;
403         int i;
404
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)
411                 return 0;
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);
415         return 0;
416 }
417
418 static int wfx_upload_ap_templates(struct wfx_vif *wvif)
419 {
420         struct sk_buff *skb;
421
422         skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif);
423         if (!skb)
424                 return -ENOMEM;
425         hif_set_template_frame(wvif, skb, HIF_TMPLT_BCN,
426                                API_RATE_INDEX_B_1MBPS);
427         dev_kfree_skb(skb);
428
429         skb = ieee80211_proberesp_get(wvif->wdev->hw, wvif->vif);
430         if (!skb)
431                 return -ENOMEM;
432         hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBRES,
433                                API_RATE_INDEX_B_1MBPS);
434         dev_kfree_skb(skb);
435         return 0;
436 }
437
438 int wfx_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
439 {
440         struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
441
442         wfx_upload_ap_templates(wvif);
443         hif_start(wvif, &vif->bss_conf, wvif->channel);
444         return 0;
445 }
446
447 void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
448 {
449         struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
450
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);
455 }
456
457 static void wfx_join_finalize(struct wfx_vif *wvif,
458                               struct ieee80211_bss_conf *info)
459 {
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
463         // the same value.
464         hif_set_bss_params(wvif, info->aid, 7);
465         hif_set_beacon_wakeup_period(wvif, 1, 1);
466         wfx_update_pm(wvif);
467 }
468
469 int wfx_join_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
470 {
471         struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
472
473         wfx_upload_ap_templates(wvif);
474         wfx_do_join(wvif);
475         return 0;
476 }
477
478 void wfx_leave_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
479 {
480         struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
481
482         wfx_do_unjoin(wvif);
483 }
484
485 void wfx_enable_beacon(struct wfx_vif *wvif, bool enable)
486 {
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);
494         }
495         hif_beacon_transmit(wvif, enable);
496 }
497
498 void wfx_bss_info_changed(struct ieee80211_hw *hw,
499                              struct ieee80211_vif *vif,
500                              struct ieee80211_bss_conf *info,
501                              u32 changed)
502 {
503         struct wfx_dev *wdev = hw->priv;
504         struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
505         int i;
506
507         mutex_lock(&wdev->conf_mutex);
508
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];
513
514                         if (info->arp_addr_cnt > HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES)
515                                 arp_addr = NULL;
516                         if (i >= info->arp_addr_cnt)
517                                 arp_addr = NULL;
518                         hif_set_arp_ipv4_filter(wvif, i, arp_addr);
519                 }
520         }
521
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)
526                         wfx_do_join(wvif);
527         }
528
529         if (changed & BSS_CHANGED_AP_PROBE_RESP ||
530             changed & BSS_CHANGED_BEACON)
531                 wfx_upload_ap_templates(wvif);
532
533         if (changed & BSS_CHANGED_BEACON_ENABLED)
534                 wfx_enable_beacon(wvif, info->enable_beacon);
535
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",
539                                  __func__);
540                 hif_set_beacon_wakeup_period(wvif, info->dtim_period,
541                                              info->dtim_period);
542                 // We temporary forwarded beacon for join process. It is now no
543                 // more necessary.
544                 wfx_filter_beacon(wvif, true);
545         }
546
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)
551                         wfx_do_unjoin(wvif);
552                 else
553                         dev_warn(wdev->dev, "%s: misunderstood change: ASSOC\n",
554                                  __func__);
555         }
556
557         if (changed & BSS_CHANGED_KEEP_ALIVE)
558                 hif_keep_alive_period(wvif, info->max_idle_period *
559                                             USEC_PER_TU / USEC_PER_MSEC);
560
561         if (changed & BSS_CHANGED_ERP_CTS_PROT)
562                 hif_erp_use_protection(wvif, info->use_cts_prot);
563
564         if (changed & BSS_CHANGED_ERP_SLOT)
565                 hif_slot_time(wvif, info->use_short_slot ? 9 : 20);
566
567         if (changed & BSS_CHANGED_CQM)
568                 hif_set_rcpi_rssi_threshold(wvif, info->cqm_rssi_thold,
569                                             info->cqm_rssi_hyst);
570
571         if (changed & BSS_CHANGED_TXPOWER)
572                 hif_set_output_power(wvif, info->txpower);
573
574         if (changed & BSS_CHANGED_PS)
575                 wfx_update_pm(wvif);
576
577         mutex_unlock(&wdev->conf_mutex);
578 }
579
580 static int wfx_update_tim(struct wfx_vif *wvif)
581 {
582         struct sk_buff *skb;
583         u16 tim_offset, tim_length;
584         u8 *tim_ptr;
585
586         skb = ieee80211_beacon_get_tim(wvif->wdev->hw, wvif->vif,
587                                        &tim_offset, &tim_length);
588         if (!skb)
589                 return -ENOENT;
590         tim_ptr = skb->data + tim_offset;
591
592         if (tim_offset && tim_length >= 6) {
593                 /* Ignore DTIM count from mac80211:
594                  * firmware handles DTIM internally.
595                  */
596                 tim_ptr[2] = 0;
597
598                 /* Set/reset aid0 bit */
599                 if (wfx_tx_queues_has_cab(wvif))
600                         tim_ptr[4] |= 1;
601                 else
602                         tim_ptr[4] &= ~1;
603         }
604
605         hif_update_ie_beacon(wvif, tim_ptr, tim_length);
606         dev_kfree_skb(skb);
607
608         return 0;
609 }
610
611 static void wfx_update_tim_work(struct work_struct *work)
612 {
613         struct wfx_vif *wvif = container_of(work, struct wfx_vif, update_tim_work);
614
615         wfx_update_tim(wvif);
616 }
617
618 int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
619 {
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);
623
624         schedule_work(&wvif->update_tim_work);
625         return 0;
626 }
627
628 void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd)
629 {
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);
634 }
635
636 int wfx_ampdu_action(struct ieee80211_hw *hw,
637                      struct ieee80211_vif *vif,
638                      struct ieee80211_ampdu_params *params)
639 {
640         /* Aggregation is implemented fully in firmware,
641          * including block ack negotiation. Do not allow
642          * mac80211 stack to do anything: it interferes with
643          * the firmware.
644          */
645
646         /* Note that we still need this function stubbed. */
647
648         return -ENOTSUPP;
649 }
650
651 int wfx_add_chanctx(struct ieee80211_hw *hw,
652                     struct ieee80211_chanctx_conf *conf)
653 {
654         return 0;
655 }
656
657 void wfx_remove_chanctx(struct ieee80211_hw *hw,
658                         struct ieee80211_chanctx_conf *conf)
659 {
660 }
661
662 void wfx_change_chanctx(struct ieee80211_hw *hw,
663                         struct ieee80211_chanctx_conf *conf,
664                         u32 changed)
665 {
666 }
667
668 int wfx_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
669                            struct ieee80211_chanctx_conf *conf)
670 {
671         struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
672         struct ieee80211_channel *ch = conf->def.chan;
673
674         WARN(wvif->channel, "channel overwrite");
675         wvif->channel = ch;
676
677         return 0;
678 }
679
680 void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw,
681                               struct ieee80211_vif *vif,
682                               struct ieee80211_chanctx_conf *conf)
683 {
684         struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
685         struct ieee80211_channel *ch = conf->def.chan;
686
687         WARN(wvif->channel != ch, "channel mismatch");
688         wvif->channel = NULL;
689 }
690
691 int wfx_config(struct ieee80211_hw *hw, u32 changed)
692 {
693         return 0;
694 }
695
696 int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
697 {
698         int i, ret = 0;
699         struct wfx_dev *wdev = hw->priv;
700         struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
701
702         vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
703                              IEEE80211_VIF_SUPPORTS_UAPSD |
704                              IEEE80211_VIF_SUPPORTS_CQM_RSSI;
705
706         mutex_lock(&wdev->conf_mutex);
707
708         switch (vif->type) {
709         case NL80211_IFTYPE_STATION:
710         case NL80211_IFTYPE_ADHOC:
711         case NL80211_IFTYPE_AP:
712                 break;
713         default:
714                 mutex_unlock(&wdev->conf_mutex);
715                 return -EOPNOTSUPP;
716         }
717
718         for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) {
719                 if (!wdev->vif[i]) {
720                         wdev->vif[i] = vif;
721                         wvif->id = i;
722                         break;
723                 }
724         }
725         if (i == ARRAY_SIZE(wdev->vif)) {
726                 mutex_unlock(&wdev->conf_mutex);
727                 return -EOPNOTSUPP;
728         }
729         // FIXME: prefer use of container_of() to get vif
730         wvif->vif = vif;
731         wvif->wdev = wdev;
732
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);
736
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);
740
741         mutex_init(&wvif->scan_lock);
742         init_completion(&wvif->scan_complete);
743         INIT_WORK(&wvif->scan_work, wfx_hw_scan_work);
744
745         INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
746         mutex_unlock(&wdev->conf_mutex);
747
748         hif_set_macaddr(wvif, vif->addr);
749
750         wfx_tx_policy_init(wvif);
751         wvif = NULL;
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);
756                 else
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);
760         }
761         return ret;
762 }
763
764 void wfx_remove_interface(struct ieee80211_hw *hw,
765                           struct ieee80211_vif *vif)
766 {
767         struct wfx_dev *wdev = hw->priv;
768         struct wfx_vif *wvif = (struct wfx_vif *) vif->drv_priv;
769
770         wait_for_completion_timeout(&wvif->set_pm_mode_complete, msecs_to_jiffies(300));
771
772         mutex_lock(&wdev->conf_mutex);
773         WARN(wvif->link_id_map != 1, "corrupted state");
774
775         hif_reset(wvif, false);
776         hif_set_macaddr(wvif, NULL);
777         wfx_tx_policy_init(wvif);
778
779         cancel_delayed_work_sync(&wvif->beacon_loss_work);
780         wdev->vif[wvif->id] = NULL;
781         wvif->vif = NULL;
782
783         mutex_unlock(&wdev->conf_mutex);
784         wvif = NULL;
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);
789                 else
790                         hif_set_block_ack_policy(wvif, 0x00, 0x00);
791                 // Combo force powersave mode. We can re-enable it now
792                 wfx_update_pm(wvif);
793         }
794 }
795
796 int wfx_start(struct ieee80211_hw *hw)
797 {
798         return 0;
799 }
800
801 void wfx_stop(struct ieee80211_hw *hw)
802 {
803         struct wfx_dev *wdev = hw->priv;
804
805         wfx_tx_queues_check_empty(wdev);
806 }