Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
23u32 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
41void wfx_cooling_timeout_work(struct work_struct *work)
42{
43 struct wfx_dev *wdev = container_of(to_delayed_work(work),
44 struct wfx_dev,
45 cooling_timeout_work);
46
47 wdev->chip_frozen = true;
48 wfx_tx_unlock(wdev);
49}
50
51void wfx_suspend_hot_dev(struct wfx_dev *wdev, enum sta_notify_cmd cmd)
52{
53 if (cmd == STA_NOTIFY_AWAKE) {
54 // Device recover normal temperature
55 if (cancel_delayed_work(&wdev->cooling_timeout_work))
56 wfx_tx_unlock(wdev);
57 } else {
58 // Device is too hot
59 schedule_delayed_work(&wdev->cooling_timeout_work, 10 * HZ);
60 wfx_tx_lock(wdev);
61 }
62}
63
64static void wfx_filter_beacon(struct wfx_vif *wvif, bool filter_beacon)
65{
66 const struct hif_ie_table_entry filter_ies[] = {
67 {
68 .ie_id = WLAN_EID_VENDOR_SPECIFIC,
69 .has_changed = 1,
70 .no_longer = 1,
71 .has_appeared = 1,
72 .oui = { 0x50, 0x6F, 0x9A },
73 }, {
74 .ie_id = WLAN_EID_HT_OPERATION,
75 .has_changed = 1,
76 .no_longer = 1,
77 .has_appeared = 1,
78 }, {
79 .ie_id = WLAN_EID_ERP_INFO,
80 .has_changed = 1,
81 .no_longer = 1,
82 .has_appeared = 1,
83 }
84 };
85
86 if (!filter_beacon) {
87 hif_beacon_filter_control(wvif, 0, 1);
88 } else {
89 hif_set_beacon_filter_table(wvif, 3, filter_ies);
90 hif_beacon_filter_control(wvif, HIF_BEACON_FILTER_ENABLE, 0);
91 }
92}
93
94static void wfx_filter_mcast(struct wfx_vif *wvif, bool filter_mcast)
95{
96 int i;
97
98 // Temporary workaround for filters
99 hif_set_data_filtering(wvif, false, true);
100 return;
101
102 if (!filter_mcast) {
103 hif_set_data_filtering(wvif, false, true);
104 return;
105 }
106 for (i = 0; i < wvif->filter_mcast_count; i++)
107 hif_set_mac_addr_condition(wvif, i, wvif->filter_mcast_addr[i]);
108 hif_set_uc_mc_bc_condition(wvif, 0,
109 HIF_FILTER_UNICAST | HIF_FILTER_BROADCAST);
110 hif_set_config_data_filter(wvif, true, 0, BIT(1),
111 BIT(wvif->filter_mcast_count) - 1);
112 hif_set_data_filtering(wvif, true, true);
113}
114
115u64 wfx_prepare_multicast(struct ieee80211_hw *hw,
116 struct netdev_hw_addr_list *mc_list)
117{
118 int i;
119 struct netdev_hw_addr *ha;
120 struct wfx_vif *wvif = NULL;
121 struct wfx_dev *wdev = hw->priv;
122 int count = netdev_hw_addr_list_count(mc_list);
123
124 while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
125 if (count > ARRAY_SIZE(wvif->filter_mcast_addr)) {
126 wvif->filter_mcast_count = 0;
127 continue;
128 }
129 wvif->filter_mcast_count = count;
130
131 i = 0;
132 netdev_hw_addr_list_for_each(ha, mc_list) {
133 ether_addr_copy(wvif->filter_mcast_addr[i], ha->addr);
134 i++;
135 }
136 }
137
138 return 0;
139}
140
141void wfx_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
142 unsigned int *total_flags, u64 unused)
143{
144 struct wfx_vif *wvif = NULL;
145 struct wfx_dev *wdev = hw->priv;
146 bool filter_bssid, filter_prbreq, filter_beacon, filter_mcast;
147
148 // Notes:
149 // - Probe responses (FIF_BCN_PRBRESP_PROMISC) are never filtered
150 // - PS-Poll (FIF_PSPOLL) are never filtered
151 // - RTS, CTS and Ack (FIF_CONTROL) are always filtered
152 // - Broken frames (FIF_FCSFAIL and FIF_PLCPFAIL) are always filtered
153 // - Firmware does (yet) allow to forward unicast traffic sent to
154 // other stations (aka. promiscuous mode)
155 *total_flags &= FIF_BCN_PRBRESP_PROMISC | FIF_ALLMULTI | FIF_OTHER_BSS |
156 FIF_PROBE_REQ | FIF_PSPOLL;
157
158 mutex_lock(&wdev->conf_mutex);
159 while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
160 mutex_lock(&wvif->scan_lock);
161
162 // Note: FIF_BCN_PRBRESP_PROMISC covers probe response and
163 // beacons from other BSS
164 if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
165 filter_beacon = false;
166 else
167 filter_beacon = true;
168 wfx_filter_beacon(wvif, filter_beacon);
169
170 if (*total_flags & FIF_ALLMULTI) {
171 filter_mcast = false;
172 } else if (!wvif->filter_mcast_count) {
173 dev_dbg(wdev->dev, "disabling unconfigured multicast filter");
174 filter_mcast = false;
175 } else {
176 filter_mcast = true;
177 }
178 wfx_filter_mcast(wvif, filter_mcast);
179
180 if (*total_flags & FIF_OTHER_BSS)
181 filter_bssid = false;
182 else
183 filter_bssid = true;
184
185 // In AP mode, chip can reply to probe request itself
186 if (*total_flags & FIF_PROBE_REQ &&
187 wvif->vif->type == NL80211_IFTYPE_AP) {
188 dev_dbg(wdev->dev, "do not forward probe request in AP mode\n");
189 *total_flags &= ~FIF_PROBE_REQ;
190 }
191
192 if (*total_flags & FIF_PROBE_REQ)
193 filter_prbreq = false;
194 else
195 filter_prbreq = true;
196 hif_set_rx_filter(wvif, filter_bssid, filter_prbreq);
197
198 mutex_unlock(&wvif->scan_lock);
199 }
200 mutex_unlock(&wdev->conf_mutex);
201}
202
203static int wfx_get_ps_timeout(struct wfx_vif *wvif, bool *enable_ps)
204{
205 struct ieee80211_channel *chan0 = NULL, *chan1 = NULL;
206 struct ieee80211_conf *conf = &wvif->wdev->hw->conf;
207
208 WARN(!wvif->vif->bss_conf.assoc && enable_ps,
209 "enable_ps is reliable only if associated");
210 if (wdev_to_wvif(wvif->wdev, 0))
211 chan0 = wdev_to_wvif(wvif->wdev, 0)->vif->bss_conf.chandef.chan;
212 if (wdev_to_wvif(wvif->wdev, 1))
213 chan1 = wdev_to_wvif(wvif->wdev, 1)->vif->bss_conf.chandef.chan;
214 if (chan0 && chan1 && chan0->hw_value != chan1->hw_value &&
215 wvif->vif->type != NL80211_IFTYPE_AP) {
216 // It is necessary to enable powersave if channels
217 // are differents.
218 if (enable_ps)
219 *enable_ps = true;
220 if (wvif->wdev->force_ps_timeout > -1)
221 return wvif->wdev->force_ps_timeout;
222 else if (wfx_api_older_than(wvif->wdev, 3, 2))
223 return 0;
224 else
225 return 30;
226 }
227 if (enable_ps)
228 *enable_ps = wvif->vif->bss_conf.ps;
229 if (wvif->wdev->force_ps_timeout > -1)
230 return wvif->wdev->force_ps_timeout;
231 else if (wvif->vif->bss_conf.assoc && wvif->vif->bss_conf.ps)
232 return conf->dynamic_ps_timeout;
233 else
234 return -1;
235}
236
237int wfx_update_pm(struct wfx_vif *wvif)
238{
239 int ps_timeout;
240 bool ps;
241
242 if (!wvif->vif->bss_conf.assoc)
243 return 0;
244 ps_timeout = wfx_get_ps_timeout(wvif, &ps);
245 if (!ps)
246 ps_timeout = 0;
247 WARN_ON(ps_timeout < 0);
248 if (wvif->uapsd_mask)
249 ps_timeout = 0;
250
251 if (!wait_for_completion_timeout(&wvif->set_pm_mode_complete,
252 TU_TO_JIFFIES(512)))
253 dev_warn(wvif->wdev->dev,
254 "timeout while waiting of set_pm_mode_complete\n");
255 return hif_set_pm(wvif, ps, ps_timeout);
256}
257
258int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
259 u16 queue, const struct ieee80211_tx_queue_params *params)
260{
261 struct wfx_dev *wdev = hw->priv;
262 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
263 int old_uapsd = wvif->uapsd_mask;
264
265 WARN_ON(queue >= hw->queues);
266
267 mutex_lock(&wdev->conf_mutex);
268 assign_bit(queue, &wvif->uapsd_mask, params->uapsd);
269 hif_set_edca_queue_params(wvif, queue, params);
270 if (wvif->vif->type == NL80211_IFTYPE_STATION &&
271 old_uapsd != wvif->uapsd_mask) {
272 hif_set_uapsd_info(wvif, wvif->uapsd_mask);
273 wfx_update_pm(wvif);
274 }
275 mutex_unlock(&wdev->conf_mutex);
276 return 0;
277}
278
279int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
280{
281 struct wfx_dev *wdev = hw->priv;
282 struct wfx_vif *wvif = NULL;
283
284 while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
285 hif_rts_threshold(wvif, value);
286 return 0;
287}
288
289/* WSM callbacks */
290
291void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi)
292{
293 /* RSSI: signed Q8.0, RCPI: unsigned Q7.1
294 * RSSI = RCPI / 2 - 110
295 */
296 int rcpi_rssi;
297 int cqm_evt;
298
299 rcpi_rssi = raw_rcpi_rssi / 2 - 110;
300 if (rcpi_rssi <= wvif->vif->bss_conf.cqm_rssi_thold)
301 cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
302 else
303 cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
304 ieee80211_cqm_rssi_notify(wvif->vif, cqm_evt, rcpi_rssi, GFP_KERNEL);
305}
306
307static void wfx_beacon_loss_work(struct work_struct *work)
308{
309 struct wfx_vif *wvif = container_of(to_delayed_work(work),
310 struct wfx_vif, beacon_loss_work);
311 struct ieee80211_bss_conf *bss_conf = &wvif->vif->bss_conf;
312
313 ieee80211_beacon_loss(wvif->vif);
314 schedule_delayed_work(to_delayed_work(work),
315 msecs_to_jiffies(bss_conf->beacon_int));
316}
317
318void wfx_set_default_unicast_key(struct ieee80211_hw *hw,
319 struct ieee80211_vif *vif, int idx)
320{
321 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
322
323 hif_wep_default_key_id(wvif, idx);
324}
325
326static void wfx_set_mfp(struct wfx_vif *wvif,
327 struct cfg80211_bss *bss)
328{
329 const int pairwise_cipher_suite_count_offset = 8 / sizeof(u16);
330 const int pairwise_cipher_suite_size = 4 / sizeof(u16);
331 const int akm_suite_size = 4 / sizeof(u16);
332 const u16 *ptr = NULL;
333 bool mfpc = false;
334 bool mfpr = false;
335
336 /* 802.11w protected mgmt frames */
337
338 /* retrieve MFPC and MFPR flags from beacon or PBRSP */
339
340 rcu_read_lock();
341 if (bss)
342 ptr = (const u16 *)ieee80211_bss_get_ie(bss, WLAN_EID_RSN);
343
344 if (ptr) {
345 ptr += pairwise_cipher_suite_count_offset;
346 ptr += 1 + pairwise_cipher_suite_size * *ptr;
347 ptr += 1 + akm_suite_size * *ptr;
348 mfpr = *ptr & BIT(6);
349 mfpc = *ptr & BIT(7);
350 }
351 rcu_read_unlock();
352
353 hif_set_mfp(wvif, mfpc, mfpr);
354}
355
356void wfx_reset(struct wfx_vif *wvif)
357{
358 struct wfx_dev *wdev = wvif->wdev;
359
360 wfx_tx_lock_flush(wdev);
361 hif_reset(wvif, false);
362 wfx_tx_policy_init(wvif);
363 if (wvif_count(wdev) <= 1)
364 hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
365 wfx_tx_unlock(wdev);
366 wvif->join_in_progress = false;
367 cancel_delayed_work_sync(&wvif->beacon_loss_work);
368 wvif = NULL;
369 while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
370 wfx_update_pm(wvif);
371}
372
373static void wfx_do_join(struct wfx_vif *wvif)
374{
375 int ret;
376 struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf;
377 struct cfg80211_bss *bss = NULL;
378 u8 ssid[IEEE80211_MAX_SSID_LEN];
379 const u8 *ssidie = NULL;
380 int ssidlen = 0;
381
382 wfx_tx_lock_flush(wvif->wdev);
383
384 bss = cfg80211_get_bss(wvif->wdev->hw->wiphy, wvif->channel,
385 conf->bssid, NULL, 0,
386 IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY);
387 if (!bss && !conf->ibss_joined) {
388 wfx_tx_unlock(wvif->wdev);
389 return;
390 }
391
392 rcu_read_lock(); // protect ssidie
393 if (bss)
394 ssidie = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
395 if (ssidie) {
396 ssidlen = ssidie[1];
397 if (ssidlen > IEEE80211_MAX_SSID_LEN)
398 ssidlen = IEEE80211_MAX_SSID_LEN;
399 memcpy(ssid, &ssidie[2], ssidlen);
400 }
401 rcu_read_unlock();
402
403 wfx_set_mfp(wvif, bss);
404 cfg80211_put_bss(wvif->wdev->hw->wiphy, bss);
405
406 wvif->join_in_progress = true;
407 ret = hif_join(wvif, conf, wvif->channel, ssid, ssidlen);
408 if (ret) {
409 ieee80211_connection_loss(wvif->vif);
410 wfx_reset(wvif);
411 } else {
412 /* Due to beacon filtering it is possible that the
413 * AP's beacon is not known for the mac80211 stack.
414 * Disable filtering temporary to make sure the stack
415 * receives at least one
416 */
417 wfx_filter_beacon(wvif, false);
418 }
419 wfx_tx_unlock(wvif->wdev);
420}
421
422int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
423 struct ieee80211_sta *sta)
424{
425 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
426 struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *)&sta->drv_priv;
427
428 sta_priv->vif_id = wvif->id;
429
430 // In station mode, the firmware interprets new link-id as a TDLS peer.
431 if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
432 return 0;
433 sta_priv->link_id = ffz(wvif->link_id_map);
434 wvif->link_id_map |= BIT(sta_priv->link_id);
435 WARN_ON(!sta_priv->link_id);
436 WARN_ON(sta_priv->link_id >= HIF_LINK_ID_MAX);
437 hif_map_link(wvif, sta->addr, 0, sta_priv->link_id);
438
439 return 0;
440}
441
442int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
443 struct ieee80211_sta *sta)
444{
445 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
446 struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *)&sta->drv_priv;
447
448 // See note in wfx_sta_add()
449 if (!sta_priv->link_id)
450 return 0;
451 // FIXME add a mutex?
452 hif_map_link(wvif, sta->addr, 1, sta_priv->link_id);
453 wvif->link_id_map &= ~BIT(sta_priv->link_id);
454 return 0;
455}
456
457static int wfx_upload_ap_templates(struct wfx_vif *wvif)
458{
459 struct sk_buff *skb;
460
461 skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif);
462 if (!skb)
463 return -ENOMEM;
464 hif_set_template_frame(wvif, skb, HIF_TMPLT_BCN,
465 API_RATE_INDEX_B_1MBPS);
466 dev_kfree_skb(skb);
467
468 skb = ieee80211_proberesp_get(wvif->wdev->hw, wvif->vif);
469 if (!skb)
470 return -ENOMEM;
471 hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBRES,
472 API_RATE_INDEX_B_1MBPS);
473 dev_kfree_skb(skb);
474 return 0;
475}
476
477int wfx_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
478{
479 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
480 struct wfx_dev *wdev = wvif->wdev;
481 int ret;
482
483 wvif = NULL;
484 while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
485 wfx_update_pm(wvif);
486 wvif = (struct wfx_vif *)vif->drv_priv;
487 wfx_upload_ap_templates(wvif);
488 ret = hif_start(wvif, &vif->bss_conf, wvif->channel);
489 if (ret > 0)
490 return -EIO;
491 return ret;
492}
493
494void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
495{
496 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
497
498 wfx_reset(wvif);
499}
500
501static void wfx_join_finalize(struct wfx_vif *wvif,
502 struct ieee80211_bss_conf *info)
503{
504 wvif->join_in_progress = false;
505 hif_set_association_mode(wvif, info);
506 hif_keep_alive_period(wvif, 0);
507 // beacon_loss_count is defined to 7 in net/mac80211/mlme.c. Let's use
508 // the same value.
509 hif_set_bss_params(wvif, info->aid, 7);
510 hif_set_beacon_wakeup_period(wvif, 1, 1);
511 wfx_update_pm(wvif);
512}
513
514int wfx_join_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
515{
516 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
517
518 wfx_upload_ap_templates(wvif);
519 wfx_do_join(wvif);
520 return 0;
521}
522
523void wfx_leave_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
524{
525 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
526
527 wfx_reset(wvif);
528}
529
530static void wfx_enable_beacon(struct wfx_vif *wvif, bool enable)
531{
532 // Driver has Content After DTIM Beacon in queue. Driver is waiting for
533 // a signal from the firmware. Since we are going to stop to send
534 // beacons, this signal will never happens. See also
535 // wfx_suspend_resume_mc()
536 if (!enable && wfx_tx_queues_has_cab(wvif)) {
537 wvif->after_dtim_tx_allowed = true;
538 wfx_bh_request_tx(wvif->wdev);
539 }
540 hif_beacon_transmit(wvif, enable);
541}
542
543void wfx_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
544 struct ieee80211_bss_conf *info, u32 changed)
545{
546 struct wfx_dev *wdev = hw->priv;
547 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
548 int i;
549
550 mutex_lock(&wdev->conf_mutex);
551
552 /* TODO: BSS_CHANGED_QOS */
553 if (changed & BSS_CHANGED_ARP_FILTER) {
554 for (i = 0; i < HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES; i++) {
555 __be32 *arp_addr = &info->arp_addr_list[i];
556
557 if (info->arp_addr_cnt > HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES)
558 arp_addr = NULL;
559 if (i >= info->arp_addr_cnt)
560 arp_addr = NULL;
561 hif_set_arp_ipv4_filter(wvif, i, arp_addr);
562 }
563 }
564
565 if (changed & BSS_CHANGED_BASIC_RATES ||
566 changed & BSS_CHANGED_BEACON_INT ||
567 changed & BSS_CHANGED_BSSID) {
568 if (vif->type == NL80211_IFTYPE_STATION)
569 wfx_do_join(wvif);
570 }
571
572 if (changed & BSS_CHANGED_AP_PROBE_RESP ||
573 changed & BSS_CHANGED_BEACON)
574 wfx_upload_ap_templates(wvif);
575
576 if (changed & BSS_CHANGED_BEACON_ENABLED)
577 wfx_enable_beacon(wvif, info->enable_beacon);
578
579 if (changed & BSS_CHANGED_BEACON_INFO) {
580 if (vif->type != NL80211_IFTYPE_STATION)
581 dev_warn(wdev->dev, "%s: misunderstood change: BEACON_INFO\n",
582 __func__);
583 hif_set_beacon_wakeup_period(wvif, info->dtim_period,
584 info->dtim_period);
585 // We temporary forwarded beacon for join process. It is now no
586 // more necessary.
587 wfx_filter_beacon(wvif, true);
588 }
589
590 if (changed & BSS_CHANGED_ASSOC) {
591 if (info->assoc || info->ibss_joined)
592 wfx_join_finalize(wvif, info);
593 else if (!info->assoc && vif->type == NL80211_IFTYPE_STATION)
594 wfx_reset(wvif);
595 else
596 dev_warn(wdev->dev, "%s: misunderstood change: ASSOC\n",
597 __func__);
598 }
599
600 if (changed & BSS_CHANGED_KEEP_ALIVE)
601 hif_keep_alive_period(wvif, info->max_idle_period *
602 USEC_PER_TU / USEC_PER_MSEC);
603
604 if (changed & BSS_CHANGED_ERP_CTS_PROT)
605 hif_erp_use_protection(wvif, info->use_cts_prot);
606
607 if (changed & BSS_CHANGED_ERP_SLOT)
608 hif_slot_time(wvif, info->use_short_slot ? 9 : 20);
609
610 if (changed & BSS_CHANGED_CQM)
611 hif_set_rcpi_rssi_threshold(wvif, info->cqm_rssi_thold,
612 info->cqm_rssi_hyst);
613
614 if (changed & BSS_CHANGED_TXPOWER)
615 hif_set_output_power(wvif, info->txpower);
616
617 if (changed & BSS_CHANGED_PS)
618 wfx_update_pm(wvif);
619
620 mutex_unlock(&wdev->conf_mutex);
621}
622
623static int wfx_update_tim(struct wfx_vif *wvif)
624{
625 struct sk_buff *skb;
626 u16 tim_offset, tim_length;
627 u8 *tim_ptr;
628
629 skb = ieee80211_beacon_get_tim(wvif->wdev->hw, wvif->vif,
630 &tim_offset, &tim_length);
631 if (!skb)
632 return -ENOENT;
633 tim_ptr = skb->data + tim_offset;
634
635 if (tim_offset && tim_length >= 6) {
636 /* Ignore DTIM count from mac80211:
637 * firmware handles DTIM internally.
638 */
639 tim_ptr[2] = 0;
640
641 /* Set/reset aid0 bit */
642 if (wfx_tx_queues_has_cab(wvif))
643 tim_ptr[4] |= 1;
644 else
645 tim_ptr[4] &= ~1;
646 }
647
648 hif_update_ie_beacon(wvif, tim_ptr, tim_length);
649 dev_kfree_skb(skb);
650
651 return 0;
652}
653
654static void wfx_update_tim_work(struct work_struct *work)
655{
656 struct wfx_vif *wvif = container_of(work, struct wfx_vif, update_tim_work);
657
658 wfx_update_tim(wvif);
659}
660
661int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
662{
663 struct wfx_dev *wdev = hw->priv;
664 struct wfx_sta_priv *sta_dev = (struct wfx_sta_priv *)&sta->drv_priv;
665 struct wfx_vif *wvif = wdev_to_wvif(wdev, sta_dev->vif_id);
666
667 schedule_work(&wvif->update_tim_work);
668 return 0;
669}
670
671void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd)
672{
673 if (notify_cmd != STA_NOTIFY_AWAKE)
674 return;
675 WARN(!wfx_tx_queues_has_cab(wvif), "incorrect sequence");
676 WARN(wvif->after_dtim_tx_allowed, "incorrect sequence");
677 wvif->after_dtim_tx_allowed = true;
678 wfx_bh_request_tx(wvif->wdev);
679}
680
681int wfx_ampdu_action(struct ieee80211_hw *hw,
682 struct ieee80211_vif *vif,
683 struct ieee80211_ampdu_params *params)
684{
685 /* Aggregation is implemented fully in firmware,
686 * including block ack negotiation. Do not allow
687 * mac80211 stack to do anything: it interferes with
688 * the firmware.
689 */
690
691 /* Note that we still need this function stubbed. */
692
693 return -ENOTSUPP;
694}
695
696int wfx_add_chanctx(struct ieee80211_hw *hw,
697 struct ieee80211_chanctx_conf *conf)
698{
699 return 0;
700}
701
702void wfx_remove_chanctx(struct ieee80211_hw *hw,
703 struct ieee80211_chanctx_conf *conf)
704{
705}
706
707void wfx_change_chanctx(struct ieee80211_hw *hw,
708 struct ieee80211_chanctx_conf *conf,
709 u32 changed)
710{
711}
712
713int wfx_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
714 struct ieee80211_chanctx_conf *conf)
715{
716 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
717 struct ieee80211_channel *ch = conf->def.chan;
718
719 WARN(wvif->channel, "channel overwrite");
720 wvif->channel = ch;
721
722 return 0;
723}
724
725void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw,
726 struct ieee80211_vif *vif,
727 struct ieee80211_chanctx_conf *conf)
728{
729 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
730 struct ieee80211_channel *ch = conf->def.chan;
731
732 WARN(wvif->channel != ch, "channel mismatch");
733 wvif->channel = NULL;
734}
735
736int wfx_config(struct ieee80211_hw *hw, u32 changed)
737{
738 return 0;
739}
740
741int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
742{
743 int i, ret = 0;
744 struct wfx_dev *wdev = hw->priv;
745 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
746
747 vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
748 IEEE80211_VIF_SUPPORTS_UAPSD |
749 IEEE80211_VIF_SUPPORTS_CQM_RSSI;
750
751 mutex_lock(&wdev->conf_mutex);
752
753 switch (vif->type) {
754 case NL80211_IFTYPE_STATION:
755 case NL80211_IFTYPE_ADHOC:
756 case NL80211_IFTYPE_AP:
757 break;
758 default:
759 mutex_unlock(&wdev->conf_mutex);
760 return -EOPNOTSUPP;
761 }
762
763 for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) {
764 if (!wdev->vif[i]) {
765 wdev->vif[i] = vif;
766 wvif->id = i;
767 break;
768 }
769 }
770 if (i == ARRAY_SIZE(wdev->vif)) {
771 mutex_unlock(&wdev->conf_mutex);
772 return -EOPNOTSUPP;
773 }
774 // FIXME: prefer use of container_of() to get vif
775 wvif->vif = vif;
776 wvif->wdev = wdev;
777
778 wvif->link_id_map = 1; // link-id 0 is reserved for multicast
779 INIT_WORK(&wvif->update_tim_work, wfx_update_tim_work);
780 INIT_DELAYED_WORK(&wvif->beacon_loss_work, wfx_beacon_loss_work);
781
782 init_completion(&wvif->set_pm_mode_complete);
783 complete(&wvif->set_pm_mode_complete);
784 INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
785
786 mutex_init(&wvif->scan_lock);
787 init_completion(&wvif->scan_complete);
788 INIT_WORK(&wvif->scan_work, wfx_hw_scan_work);
789
790 mutex_unlock(&wdev->conf_mutex);
791
792 hif_set_macaddr(wvif, vif->addr);
793
794 wfx_tx_queues_init(wvif);
795 wfx_tx_policy_init(wvif);
796 wvif = NULL;
797 while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
798 // Combo mode does not support Block Acks. We can re-enable them
799 if (wvif_count(wdev) == 1)
800 hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
801 else
802 hif_set_block_ack_policy(wvif, 0x00, 0x00);
803 }
804 return ret;
805}
806
807void wfx_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
808{
809 struct wfx_dev *wdev = hw->priv;
810 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
811
812 wait_for_completion_timeout(&wvif->set_pm_mode_complete, msecs_to_jiffies(300));
813 wfx_tx_queues_check_empty(wvif);
814
815 mutex_lock(&wdev->conf_mutex);
816 WARN(wvif->link_id_map != 1, "corrupted state");
817
818 hif_reset(wvif, false);
819 hif_set_macaddr(wvif, NULL);
820 wfx_tx_policy_init(wvif);
821
822 cancel_delayed_work_sync(&wvif->beacon_loss_work);
823 wdev->vif[wvif->id] = NULL;
824 wvif->vif = NULL;
825
826 mutex_unlock(&wdev->conf_mutex);
827 wvif = NULL;
828 while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
829 // Combo mode does not support Block Acks. We can re-enable them
830 if (wvif_count(wdev) == 1)
831 hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
832 else
833 hif_set_block_ack_policy(wvif, 0x00, 0x00);
834 }
835}
836
837int wfx_start(struct ieee80211_hw *hw)
838{
839 return 0;
840}
841
842void wfx_stop(struct ieee80211_hw *hw)
843{
844 struct wfx_dev *wdev = hw->priv;
845
846 WARN_ON(!skb_queue_empty_lockless(&wdev->tx_pending));
847}