1
2
3
4
5
6
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
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
55 if (cancel_delayed_work(&wdev->cooling_timeout_work))
56 wfx_tx_unlock(wdev);
57 } else {
58
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 static 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
94void wfx_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
95 unsigned int *total_flags, u64 unused)
96{
97 struct wfx_vif *wvif = NULL;
98 struct wfx_dev *wdev = hw->priv;
99 bool filter_bssid, filter_prbreq, filter_beacon;
100
101
102
103
104
105
106
107
108 *total_flags &= FIF_BCN_PRBRESP_PROMISC | FIF_ALLMULTI | FIF_OTHER_BSS |
109 FIF_PROBE_REQ | FIF_PSPOLL;
110
111 mutex_lock(&wdev->conf_mutex);
112 while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
113 mutex_lock(&wvif->scan_lock);
114
115
116
117 if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
118 filter_beacon = false;
119 else
120 filter_beacon = true;
121 wfx_filter_beacon(wvif, filter_beacon);
122
123 if (*total_flags & FIF_OTHER_BSS)
124 filter_bssid = false;
125 else
126 filter_bssid = true;
127
128
129 if (*total_flags & FIF_PROBE_REQ &&
130 wvif->vif->type == NL80211_IFTYPE_AP) {
131 dev_dbg(wdev->dev, "do not forward probe request in AP mode\n");
132 *total_flags &= ~FIF_PROBE_REQ;
133 }
134
135 if (*total_flags & FIF_PROBE_REQ)
136 filter_prbreq = false;
137 else
138 filter_prbreq = true;
139 hif_set_rx_filter(wvif, filter_bssid, filter_prbreq);
140
141 mutex_unlock(&wvif->scan_lock);
142 }
143 mutex_unlock(&wdev->conf_mutex);
144}
145
146static int wfx_get_ps_timeout(struct wfx_vif *wvif, bool *enable_ps)
147{
148 struct ieee80211_channel *chan0 = NULL, *chan1 = NULL;
149 struct ieee80211_conf *conf = &wvif->wdev->hw->conf;
150
151 WARN(!wvif->vif->bss_conf.assoc && enable_ps,
152 "enable_ps is reliable only if associated");
153 if (wdev_to_wvif(wvif->wdev, 0))
154 chan0 = wdev_to_wvif(wvif->wdev, 0)->vif->bss_conf.chandef.chan;
155 if (wdev_to_wvif(wvif->wdev, 1))
156 chan1 = wdev_to_wvif(wvif->wdev, 1)->vif->bss_conf.chandef.chan;
157 if (chan0 && chan1 && chan0->hw_value != chan1->hw_value &&
158 wvif->vif->type != NL80211_IFTYPE_AP) {
159
160
161 if (enable_ps)
162 *enable_ps = true;
163 if (wvif->wdev->force_ps_timeout > -1)
164 return wvif->wdev->force_ps_timeout;
165 else if (wfx_api_older_than(wvif->wdev, 3, 2))
166 return 0;
167 else
168 return 30;
169 }
170 if (enable_ps)
171 *enable_ps = wvif->vif->bss_conf.ps;
172 if (wvif->wdev->force_ps_timeout > -1)
173 return wvif->wdev->force_ps_timeout;
174 else if (wvif->vif->bss_conf.assoc && wvif->vif->bss_conf.ps)
175 return conf->dynamic_ps_timeout;
176 else
177 return -1;
178}
179
180int wfx_update_pm(struct wfx_vif *wvif)
181{
182 int ps_timeout;
183 bool ps;
184
185 if (!wvif->vif->bss_conf.assoc)
186 return 0;
187 ps_timeout = wfx_get_ps_timeout(wvif, &ps);
188 if (!ps)
189 ps_timeout = 0;
190 WARN_ON(ps_timeout < 0);
191 if (wvif->uapsd_mask)
192 ps_timeout = 0;
193
194 if (!wait_for_completion_timeout(&wvif->set_pm_mode_complete,
195 TU_TO_JIFFIES(512)))
196 dev_warn(wvif->wdev->dev,
197 "timeout while waiting of set_pm_mode_complete\n");
198 return hif_set_pm(wvif, ps, ps_timeout);
199}
200
201int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
202 u16 queue, const struct ieee80211_tx_queue_params *params)
203{
204 struct wfx_dev *wdev = hw->priv;
205 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
206 int old_uapsd = wvif->uapsd_mask;
207
208 WARN_ON(queue >= hw->queues);
209
210 mutex_lock(&wdev->conf_mutex);
211 assign_bit(queue, &wvif->uapsd_mask, params->uapsd);
212 hif_set_edca_queue_params(wvif, queue, params);
213 if (wvif->vif->type == NL80211_IFTYPE_STATION &&
214 old_uapsd != wvif->uapsd_mask) {
215 hif_set_uapsd_info(wvif, wvif->uapsd_mask);
216 wfx_update_pm(wvif);
217 }
218 mutex_unlock(&wdev->conf_mutex);
219 return 0;
220}
221
222int wfx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
223{
224 struct wfx_dev *wdev = hw->priv;
225 struct wfx_vif *wvif = NULL;
226
227 while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
228 hif_rts_threshold(wvif, value);
229 return 0;
230}
231
232
233
234void wfx_event_report_rssi(struct wfx_vif *wvif, u8 raw_rcpi_rssi)
235{
236
237
238
239 int rcpi_rssi;
240 int cqm_evt;
241
242 rcpi_rssi = raw_rcpi_rssi / 2 - 110;
243 if (rcpi_rssi <= wvif->vif->bss_conf.cqm_rssi_thold)
244 cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
245 else
246 cqm_evt = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
247 ieee80211_cqm_rssi_notify(wvif->vif, cqm_evt, rcpi_rssi, GFP_KERNEL);
248}
249
250static void wfx_beacon_loss_work(struct work_struct *work)
251{
252 struct wfx_vif *wvif = container_of(to_delayed_work(work),
253 struct wfx_vif, beacon_loss_work);
254 struct ieee80211_bss_conf *bss_conf = &wvif->vif->bss_conf;
255
256 ieee80211_beacon_loss(wvif->vif);
257 schedule_delayed_work(to_delayed_work(work),
258 msecs_to_jiffies(bss_conf->beacon_int));
259}
260
261void wfx_set_default_unicast_key(struct ieee80211_hw *hw,
262 struct ieee80211_vif *vif, int idx)
263{
264 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
265
266 hif_wep_default_key_id(wvif, idx);
267}
268
269void wfx_reset(struct wfx_vif *wvif)
270{
271 struct wfx_dev *wdev = wvif->wdev;
272
273 wfx_tx_lock_flush(wdev);
274 hif_reset(wvif, false);
275 wfx_tx_policy_init(wvif);
276 if (wvif_count(wdev) <= 1)
277 hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
278 wfx_tx_unlock(wdev);
279 wvif->join_in_progress = false;
280 cancel_delayed_work_sync(&wvif->beacon_loss_work);
281 wvif = NULL;
282 while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
283 wfx_update_pm(wvif);
284}
285
286int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
287 struct ieee80211_sta *sta)
288{
289 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
290 struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *)&sta->drv_priv;
291
292 sta_priv->vif_id = wvif->id;
293
294 if (vif->type == NL80211_IFTYPE_STATION)
295 hif_set_mfp(wvif, sta->mfp, sta->mfp);
296
297
298 if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
299 return 0;
300 sta_priv->link_id = ffz(wvif->link_id_map);
301 wvif->link_id_map |= BIT(sta_priv->link_id);
302 WARN_ON(!sta_priv->link_id);
303 WARN_ON(sta_priv->link_id >= HIF_LINK_ID_MAX);
304 hif_map_link(wvif, false, sta->addr, sta_priv->link_id, sta->mfp);
305
306 return 0;
307}
308
309int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
310 struct ieee80211_sta *sta)
311{
312 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
313 struct wfx_sta_priv *sta_priv = (struct wfx_sta_priv *)&sta->drv_priv;
314
315
316 if (!sta_priv->link_id)
317 return 0;
318
319 hif_map_link(wvif, true, sta->addr, sta_priv->link_id, false);
320 wvif->link_id_map &= ~BIT(sta_priv->link_id);
321 return 0;
322}
323
324static int wfx_upload_ap_templates(struct wfx_vif *wvif)
325{
326 struct sk_buff *skb;
327
328 skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif);
329 if (!skb)
330 return -ENOMEM;
331 hif_set_template_frame(wvif, skb, HIF_TMPLT_BCN,
332 API_RATE_INDEX_B_1MBPS);
333 dev_kfree_skb(skb);
334
335 skb = ieee80211_proberesp_get(wvif->wdev->hw, wvif->vif);
336 if (!skb)
337 return -ENOMEM;
338 hif_set_template_frame(wvif, skb, HIF_TMPLT_PRBRES,
339 API_RATE_INDEX_B_1MBPS);
340 dev_kfree_skb(skb);
341 return 0;
342}
343
344static void wfx_set_mfp_ap(struct wfx_vif *wvif)
345{
346 struct sk_buff *skb = ieee80211_beacon_get(wvif->wdev->hw, wvif->vif);
347 const int ieoffset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
348 const u16 *ptr = (u16 *)cfg80211_find_ie(WLAN_EID_RSN,
349 skb->data + ieoffset,
350 skb->len - ieoffset);
351 const int pairwise_cipher_suite_count_offset = 8 / sizeof(u16);
352 const int pairwise_cipher_suite_size = 4 / sizeof(u16);
353 const int akm_suite_size = 4 / sizeof(u16);
354
355 if (ptr) {
356 ptr += pairwise_cipher_suite_count_offset;
357 if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
358 return;
359 ptr += 1 + pairwise_cipher_suite_size * *ptr;
360 if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
361 return;
362 ptr += 1 + akm_suite_size * *ptr;
363 if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
364 return;
365 hif_set_mfp(wvif, *ptr & BIT(7), *ptr & BIT(6));
366 }
367}
368
369int wfx_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
370{
371 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
372 struct wfx_dev *wdev = wvif->wdev;
373 int ret;
374
375 wvif = NULL;
376 while ((wvif = wvif_iterate(wdev, wvif)) != NULL)
377 wfx_update_pm(wvif);
378 wvif = (struct wfx_vif *)vif->drv_priv;
379 wfx_upload_ap_templates(wvif);
380 ret = hif_start(wvif, &vif->bss_conf, wvif->channel);
381 if (ret > 0)
382 return -EIO;
383 wfx_set_mfp_ap(wvif);
384 return ret;
385}
386
387void wfx_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
388{
389 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
390
391 wfx_reset(wvif);
392}
393
394static void wfx_join(struct wfx_vif *wvif)
395{
396 int ret;
397 struct ieee80211_bss_conf *conf = &wvif->vif->bss_conf;
398 struct cfg80211_bss *bss = NULL;
399 u8 ssid[IEEE80211_MAX_SSID_LEN];
400 const u8 *ssidie = NULL;
401 int ssidlen = 0;
402
403 wfx_tx_lock_flush(wvif->wdev);
404
405 bss = cfg80211_get_bss(wvif->wdev->hw->wiphy, wvif->channel,
406 conf->bssid, NULL, 0,
407 IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY);
408 if (!bss && !conf->ibss_joined) {
409 wfx_tx_unlock(wvif->wdev);
410 return;
411 }
412
413 rcu_read_lock();
414 if (bss)
415 ssidie = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
416 if (ssidie) {
417 ssidlen = ssidie[1];
418 if (ssidlen > IEEE80211_MAX_SSID_LEN)
419 ssidlen = IEEE80211_MAX_SSID_LEN;
420 memcpy(ssid, &ssidie[2], ssidlen);
421 }
422 rcu_read_unlock();
423
424 cfg80211_put_bss(wvif->wdev->hw->wiphy, bss);
425
426 wvif->join_in_progress = true;
427 ret = hif_join(wvif, conf, wvif->channel, ssid, ssidlen);
428 if (ret) {
429 ieee80211_connection_loss(wvif->vif);
430 wfx_reset(wvif);
431 } else {
432
433
434
435
436
437 wfx_filter_beacon(wvif, false);
438 }
439 wfx_tx_unlock(wvif->wdev);
440}
441
442static void wfx_join_finalize(struct wfx_vif *wvif,
443 struct ieee80211_bss_conf *info)
444{
445 struct ieee80211_sta *sta = NULL;
446 int ampdu_density = 0;
447 bool greenfield = false;
448
449 rcu_read_lock();
450 if (info->bssid && !info->ibss_joined)
451 sta = ieee80211_find_sta(wvif->vif, info->bssid);
452 if (sta && sta->ht_cap.ht_supported)
453 ampdu_density = sta->ht_cap.ampdu_density;
454 if (sta && sta->ht_cap.ht_supported &&
455 !(info->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT))
456 greenfield = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD);
457 rcu_read_unlock();
458
459 wvif->join_in_progress = false;
460 hif_set_association_mode(wvif, ampdu_density, greenfield,
461 info->use_short_preamble);
462 hif_keep_alive_period(wvif, 0);
463
464
465 hif_set_bss_params(wvif, info->aid, 7);
466 hif_set_beacon_wakeup_period(wvif, 1, 1);
467 wfx_update_pm(wvif);
468}
469
470int wfx_join_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
471{
472 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
473
474 wfx_upload_ap_templates(wvif);
475 wfx_join(wvif);
476 return 0;
477}
478
479void wfx_leave_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
480{
481 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
482
483 wfx_reset(wvif);
484}
485
486static void wfx_enable_beacon(struct wfx_vif *wvif, bool enable)
487{
488
489
490
491
492 if (!enable && wfx_tx_queues_has_cab(wvif)) {
493 wvif->after_dtim_tx_allowed = true;
494 wfx_bh_request_tx(wvif->wdev);
495 }
496 hif_beacon_transmit(wvif, enable);
497}
498
499void wfx_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
500 struct ieee80211_bss_conf *info, u32 changed)
501{
502 struct wfx_dev *wdev = hw->priv;
503 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
504 int i;
505
506 mutex_lock(&wdev->conf_mutex);
507
508 if (changed & BSS_CHANGED_BASIC_RATES ||
509 changed & BSS_CHANGED_BEACON_INT ||
510 changed & BSS_CHANGED_BSSID) {
511 if (vif->type == NL80211_IFTYPE_STATION)
512 wfx_join(wvif);
513 }
514
515 if (changed & BSS_CHANGED_ASSOC) {
516 if (info->assoc || info->ibss_joined)
517 wfx_join_finalize(wvif, info);
518 else if (!info->assoc && vif->type == NL80211_IFTYPE_STATION)
519 wfx_reset(wvif);
520 else
521 dev_warn(wdev->dev, "%s: misunderstood change: ASSOC\n",
522 __func__);
523 }
524
525 if (changed & BSS_CHANGED_BEACON_INFO) {
526 if (vif->type != NL80211_IFTYPE_STATION)
527 dev_warn(wdev->dev, "%s: misunderstood change: BEACON_INFO\n",
528 __func__);
529 hif_set_beacon_wakeup_period(wvif, info->dtim_period,
530 info->dtim_period);
531
532
533 wfx_filter_beacon(wvif, true);
534 }
535
536 if (changed & BSS_CHANGED_ARP_FILTER) {
537 for (i = 0; i < HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES; i++) {
538 __be32 *arp_addr = &info->arp_addr_list[i];
539
540 if (info->arp_addr_cnt > HIF_MAX_ARP_IP_ADDRTABLE_ENTRIES)
541 arp_addr = NULL;
542 if (i >= info->arp_addr_cnt)
543 arp_addr = NULL;
544 hif_set_arp_ipv4_filter(wvif, i, arp_addr);
545 }
546 }
547
548 if (changed & BSS_CHANGED_AP_PROBE_RESP ||
549 changed & BSS_CHANGED_BEACON)
550 wfx_upload_ap_templates(wvif);
551
552 if (changed & BSS_CHANGED_BEACON_ENABLED)
553 wfx_enable_beacon(wvif, info->enable_beacon);
554
555 if (changed & BSS_CHANGED_KEEP_ALIVE)
556 hif_keep_alive_period(wvif, info->max_idle_period *
557 USEC_PER_TU / USEC_PER_MSEC);
558
559 if (changed & BSS_CHANGED_ERP_CTS_PROT)
560 hif_erp_use_protection(wvif, info->use_cts_prot);
561
562 if (changed & BSS_CHANGED_ERP_SLOT)
563 hif_slot_time(wvif, info->use_short_slot ? 9 : 20);
564
565 if (changed & BSS_CHANGED_CQM)
566 hif_set_rcpi_rssi_threshold(wvif, info->cqm_rssi_thold,
567 info->cqm_rssi_hyst);
568
569 if (changed & BSS_CHANGED_TXPOWER)
570 hif_set_output_power(wvif, info->txpower);
571
572 if (changed & BSS_CHANGED_PS)
573 wfx_update_pm(wvif);
574
575 mutex_unlock(&wdev->conf_mutex);
576}
577
578static int wfx_update_tim(struct wfx_vif *wvif)
579{
580 struct sk_buff *skb;
581 u16 tim_offset, tim_length;
582 u8 *tim_ptr;
583
584 skb = ieee80211_beacon_get_tim(wvif->wdev->hw, wvif->vif,
585 &tim_offset, &tim_length);
586 if (!skb)
587 return -ENOENT;
588 tim_ptr = skb->data + tim_offset;
589
590 if (tim_offset && tim_length >= 6) {
591
592
593
594 tim_ptr[2] = 0;
595
596
597 if (wfx_tx_queues_has_cab(wvif))
598 tim_ptr[4] |= 1;
599 else
600 tim_ptr[4] &= ~1;
601 }
602
603 hif_update_ie_beacon(wvif, tim_ptr, tim_length);
604 dev_kfree_skb(skb);
605
606 return 0;
607}
608
609static void wfx_update_tim_work(struct work_struct *work)
610{
611 struct wfx_vif *wvif = container_of(work, struct wfx_vif, update_tim_work);
612
613 wfx_update_tim(wvif);
614}
615
616int wfx_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
617{
618 struct wfx_dev *wdev = hw->priv;
619 struct wfx_sta_priv *sta_dev = (struct wfx_sta_priv *)&sta->drv_priv;
620 struct wfx_vif *wvif = wdev_to_wvif(wdev, sta_dev->vif_id);
621
622 if (!wvif) {
623 dev_warn(wdev->dev, "%s: received event for non-existent vif\n", __func__);
624 return -EIO;
625 }
626 schedule_work(&wvif->update_tim_work);
627 return 0;
628}
629
630void wfx_suspend_resume_mc(struct wfx_vif *wvif, enum sta_notify_cmd notify_cmd)
631{
632 if (notify_cmd != STA_NOTIFY_AWAKE)
633 return;
634 WARN(!wfx_tx_queues_has_cab(wvif), "incorrect sequence");
635 WARN(wvif->after_dtim_tx_allowed, "incorrect sequence");
636 wvif->after_dtim_tx_allowed = true;
637 wfx_bh_request_tx(wvif->wdev);
638}
639
640int wfx_ampdu_action(struct ieee80211_hw *hw,
641 struct ieee80211_vif *vif,
642 struct ieee80211_ampdu_params *params)
643{
644
645 switch (params->action) {
646 case IEEE80211_AMPDU_RX_START:
647 case IEEE80211_AMPDU_RX_STOP:
648
649 return 0;
650 default:
651
652 return -ENOTSUPP;
653 }
654}
655
656int wfx_add_chanctx(struct ieee80211_hw *hw,
657 struct ieee80211_chanctx_conf *conf)
658{
659 return 0;
660}
661
662void wfx_remove_chanctx(struct ieee80211_hw *hw,
663 struct ieee80211_chanctx_conf *conf)
664{
665}
666
667void wfx_change_chanctx(struct ieee80211_hw *hw,
668 struct ieee80211_chanctx_conf *conf,
669 u32 changed)
670{
671}
672
673int wfx_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
674 struct ieee80211_chanctx_conf *conf)
675{
676 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
677 struct ieee80211_channel *ch = conf->def.chan;
678
679 WARN(wvif->channel, "channel overwrite");
680 wvif->channel = ch;
681
682 return 0;
683}
684
685void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw,
686 struct ieee80211_vif *vif,
687 struct ieee80211_chanctx_conf *conf)
688{
689 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
690 struct ieee80211_channel *ch = conf->def.chan;
691
692 WARN(wvif->channel != ch, "channel mismatch");
693 wvif->channel = NULL;
694}
695
696int wfx_config(struct ieee80211_hw *hw, u32 changed)
697{
698 return 0;
699}
700
701int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
702{
703 int i, ret = 0;
704 struct wfx_dev *wdev = hw->priv;
705 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
706
707 vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
708 IEEE80211_VIF_SUPPORTS_UAPSD |
709 IEEE80211_VIF_SUPPORTS_CQM_RSSI;
710
711 mutex_lock(&wdev->conf_mutex);
712
713 switch (vif->type) {
714 case NL80211_IFTYPE_STATION:
715 case NL80211_IFTYPE_ADHOC:
716 case NL80211_IFTYPE_AP:
717 break;
718 default:
719 mutex_unlock(&wdev->conf_mutex);
720 return -EOPNOTSUPP;
721 }
722
723
724 wvif->vif = vif;
725 wvif->wdev = wdev;
726
727 wvif->link_id_map = 1;
728 INIT_WORK(&wvif->update_tim_work, wfx_update_tim_work);
729 INIT_DELAYED_WORK(&wvif->beacon_loss_work, wfx_beacon_loss_work);
730
731 init_completion(&wvif->set_pm_mode_complete);
732 complete(&wvif->set_pm_mode_complete);
733 INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
734
735 mutex_init(&wvif->scan_lock);
736 init_completion(&wvif->scan_complete);
737 INIT_WORK(&wvif->scan_work, wfx_hw_scan_work);
738
739 wfx_tx_queues_init(wvif);
740 wfx_tx_policy_init(wvif);
741
742 for (i = 0; i < ARRAY_SIZE(wdev->vif); i++) {
743 if (!wdev->vif[i]) {
744 wdev->vif[i] = vif;
745 wvif->id = i;
746 break;
747 }
748 }
749 WARN(i == ARRAY_SIZE(wdev->vif), "try to instantiate more vif than supported");
750
751 hif_set_macaddr(wvif, vif->addr);
752
753 mutex_unlock(&wdev->conf_mutex);
754
755 wvif = NULL;
756 while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
757
758 if (wvif_count(wdev) == 1)
759 hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
760 else
761 hif_set_block_ack_policy(wvif, 0x00, 0x00);
762 }
763 return ret;
764}
765
766void wfx_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
767{
768 struct wfx_dev *wdev = hw->priv;
769 struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
770
771 wait_for_completion_timeout(&wvif->set_pm_mode_complete, msecs_to_jiffies(300));
772 wfx_tx_queues_check_empty(wvif);
773
774 mutex_lock(&wdev->conf_mutex);
775 WARN(wvif->link_id_map != 1, "corrupted state");
776
777 hif_reset(wvif, false);
778 hif_set_macaddr(wvif, NULL);
779 wfx_tx_policy_init(wvif);
780
781 cancel_delayed_work_sync(&wvif->beacon_loss_work);
782 wdev->vif[wvif->id] = NULL;
783 wvif->vif = NULL;
784
785 mutex_unlock(&wdev->conf_mutex);
786
787 wvif = NULL;
788 while ((wvif = wvif_iterate(wdev, wvif)) != NULL) {
789
790 if (wvif_count(wdev) == 1)
791 hif_set_block_ack_policy(wvif, 0xFF, 0xFF);
792 else
793 hif_set_block_ack_policy(wvif, 0x00, 0x00);
794 }
795}
796
797int wfx_start(struct ieee80211_hw *hw)
798{
799 return 0;
800}
801
802void wfx_stop(struct ieee80211_hw *hw)
803{
804 struct wfx_dev *wdev = hw->priv;
805
806 WARN_ON(!skb_queue_empty_lockless(&wdev->tx_pending));
807}
808