1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18
19#include <linux/module.h>
20#include <linux/firmware.h>
21#include <linux/platform_device.h>
22#include <linux/of_address.h>
23#include <linux/of_device.h>
24#include <linux/of_irq.h>
25#include <linux/rpmsg.h>
26#include <linux/soc/qcom/smem_state.h>
27#include <linux/soc/qcom/wcnss_ctrl.h>
28#include <net/ipv6.h>
29#include "wcn36xx.h"
30#include "testmode.h"
31
32unsigned int wcn36xx_dbg_mask;
33module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644);
34MODULE_PARM_DESC(debug_mask, "Debugging mask");
35
36#define CHAN2G(_freq, _idx) { \
37 .band = NL80211_BAND_2GHZ, \
38 .center_freq = (_freq), \
39 .hw_value = (_idx), \
40 .max_power = 25, \
41}
42
43#define CHAN5G(_freq, _idx, _phy_val) { \
44 .band = NL80211_BAND_5GHZ, \
45 .center_freq = (_freq), \
46 .hw_value = (_phy_val) << HW_VALUE_PHY_SHIFT | HW_VALUE_CHANNEL(_idx), \
47 .max_power = 25, \
48}
49
50
51
52static struct ieee80211_channel wcn_2ghz_channels[] = {
53 CHAN2G(2412, 1),
54 CHAN2G(2417, 2),
55 CHAN2G(2422, 3),
56 CHAN2G(2427, 4),
57 CHAN2G(2432, 5),
58 CHAN2G(2437, 6),
59 CHAN2G(2442, 7),
60 CHAN2G(2447, 8),
61 CHAN2G(2452, 9),
62 CHAN2G(2457, 10),
63 CHAN2G(2462, 11),
64 CHAN2G(2467, 12),
65 CHAN2G(2472, 13),
66 CHAN2G(2484, 14)
67
68};
69
70static struct ieee80211_channel wcn_5ghz_channels[] = {
71 CHAN5G(5180, 36, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
72 CHAN5G(5200, 40, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
73 CHAN5G(5220, 44, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
74 CHAN5G(5240, 48, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
75 CHAN5G(5260, 52, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
76 CHAN5G(5280, 56, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
77 CHAN5G(5300, 60, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
78 CHAN5G(5320, 64, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
79 CHAN5G(5500, 100, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
80 CHAN5G(5520, 104, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
81 CHAN5G(5540, 108, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
82 CHAN5G(5560, 112, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
83 CHAN5G(5580, 116, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
84 CHAN5G(5600, 120, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
85 CHAN5G(5620, 124, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
86 CHAN5G(5640, 128, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
87 CHAN5G(5660, 132, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
88 CHAN5G(5700, 140, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
89 CHAN5G(5745, 149, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
90 CHAN5G(5765, 153, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
91 CHAN5G(5785, 157, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
92 CHAN5G(5805, 161, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
93 CHAN5G(5825, 165, 0)
94};
95
96#define RATE(_bitrate, _hw_rate, _flags) { \
97 .bitrate = (_bitrate), \
98 .flags = (_flags), \
99 .hw_value = (_hw_rate), \
100 .hw_value_short = (_hw_rate) \
101}
102
103static struct ieee80211_rate wcn_2ghz_rates[] = {
104 RATE(10, HW_RATE_INDEX_1MBPS, 0),
105 RATE(20, HW_RATE_INDEX_2MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
106 RATE(55, HW_RATE_INDEX_5_5MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
107 RATE(110, HW_RATE_INDEX_11MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
108 RATE(60, HW_RATE_INDEX_6MBPS, 0),
109 RATE(90, HW_RATE_INDEX_9MBPS, 0),
110 RATE(120, HW_RATE_INDEX_12MBPS, 0),
111 RATE(180, HW_RATE_INDEX_18MBPS, 0),
112 RATE(240, HW_RATE_INDEX_24MBPS, 0),
113 RATE(360, HW_RATE_INDEX_36MBPS, 0),
114 RATE(480, HW_RATE_INDEX_48MBPS, 0),
115 RATE(540, HW_RATE_INDEX_54MBPS, 0)
116};
117
118static struct ieee80211_rate wcn_5ghz_rates[] = {
119 RATE(60, HW_RATE_INDEX_6MBPS, 0),
120 RATE(90, HW_RATE_INDEX_9MBPS, 0),
121 RATE(120, HW_RATE_INDEX_12MBPS, 0),
122 RATE(180, HW_RATE_INDEX_18MBPS, 0),
123 RATE(240, HW_RATE_INDEX_24MBPS, 0),
124 RATE(360, HW_RATE_INDEX_36MBPS, 0),
125 RATE(480, HW_RATE_INDEX_48MBPS, 0),
126 RATE(540, HW_RATE_INDEX_54MBPS, 0)
127};
128
129static struct ieee80211_supported_band wcn_band_2ghz = {
130 .channels = wcn_2ghz_channels,
131 .n_channels = ARRAY_SIZE(wcn_2ghz_channels),
132 .bitrates = wcn_2ghz_rates,
133 .n_bitrates = ARRAY_SIZE(wcn_2ghz_rates),
134 .ht_cap = {
135 .cap = IEEE80211_HT_CAP_GRN_FLD |
136 IEEE80211_HT_CAP_SGI_20 |
137 IEEE80211_HT_CAP_DSSSCCK40 |
138 IEEE80211_HT_CAP_LSIG_TXOP_PROT,
139 .ht_supported = true,
140 .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
141 .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
142 .mcs = {
143 .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
144 .rx_highest = cpu_to_le16(72),
145 .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
146 }
147 }
148};
149
150static struct ieee80211_supported_band wcn_band_5ghz = {
151 .channels = wcn_5ghz_channels,
152 .n_channels = ARRAY_SIZE(wcn_5ghz_channels),
153 .bitrates = wcn_5ghz_rates,
154 .n_bitrates = ARRAY_SIZE(wcn_5ghz_rates),
155 .ht_cap = {
156 .cap = IEEE80211_HT_CAP_GRN_FLD |
157 IEEE80211_HT_CAP_SGI_20 |
158 IEEE80211_HT_CAP_DSSSCCK40 |
159 IEEE80211_HT_CAP_LSIG_TXOP_PROT |
160 IEEE80211_HT_CAP_SGI_40 |
161 IEEE80211_HT_CAP_SUP_WIDTH_20_40,
162 .ht_supported = true,
163 .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
164 .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
165 .mcs = {
166 .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
167 .rx_highest = cpu_to_le16(150),
168 .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
169 }
170 }
171};
172
173#ifdef CONFIG_PM
174
175static const struct wiphy_wowlan_support wowlan_support = {
176 .flags = WIPHY_WOWLAN_ANY |
177 WIPHY_WOWLAN_MAGIC_PKT |
178 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY
179};
180
181#endif
182
183static inline u8 get_sta_index(struct ieee80211_vif *vif,
184 struct wcn36xx_sta *sta_priv)
185{
186 return NL80211_IFTYPE_STATION == vif->type ?
187 sta_priv->bss_sta_index :
188 sta_priv->sta_index;
189}
190
191static const char * const wcn36xx_caps_names[] = {
192 "MCC",
193 "P2P",
194 "DOT11AC",
195 "SLM_SESSIONIZATION",
196 "DOT11AC_OPMODE",
197 "SAP32STA",
198 "TDLS",
199 "P2P_GO_NOA_DECOUPLE_INIT_SCAN",
200 "WLANACTIVE_OFFLOAD",
201 "BEACON_OFFLOAD",
202 "SCAN_OFFLOAD",
203 "ROAM_OFFLOAD",
204 "BCN_MISS_OFFLOAD",
205 "STA_POWERSAVE",
206 "STA_ADVANCED_PWRSAVE",
207 "AP_UAPSD",
208 "AP_DFS",
209 "BLOCKACK",
210 "PHY_ERR",
211 "BCN_FILTER",
212 "RTT",
213 "RATECTRL",
214 "WOW",
215 "WLAN_ROAM_SCAN_OFFLOAD",
216 "SPECULATIVE_PS_POLL",
217 "SCAN_SCH",
218 "IBSS_HEARTBEAT_OFFLOAD",
219 "WLAN_SCAN_OFFLOAD",
220 "WLAN_PERIODIC_TX_PTRN",
221 "ADVANCE_TDLS",
222 "BATCH_SCAN",
223 "FW_IN_TX_PATH",
224 "EXTENDED_NSOFFLOAD_SLOT",
225 "CH_SWITCH_V1",
226 "HT40_OBSS_SCAN",
227 "UPDATE_CHANNEL_LIST",
228 "WLAN_MCADDR_FLT",
229 "WLAN_CH144",
230 "NAN",
231 "TDLS_SCAN_COEXISTENCE",
232 "LINK_LAYER_STATS_MEAS",
233 "MU_MIMO",
234 "EXTENDED_SCAN",
235 "DYNAMIC_WMM_PS",
236 "MAC_SPOOFED_SCAN",
237 "BMU_ERROR_GENERIC_RECOVERY",
238 "DISA",
239 "FW_STATS",
240 "WPS_PRBRSP_TMPL",
241 "BCN_IE_FLT_DELTA",
242 "TDLS_OFF_CHANNEL",
243 "RTT3",
244 "MGMT_FRAME_LOGGING",
245 "ENHANCED_TXBD_COMPLETION",
246 "LOGGING_ENHANCEMENT",
247 "EXT_SCAN_ENHANCED",
248 "MEMORY_DUMP_SUPPORTED",
249 "PER_PKT_STATS_SUPPORTED",
250 "EXT_LL_STAT",
251 "WIFI_CONFIG",
252 "ANTENNA_DIVERSITY_SELECTION",
253};
254
255static const char *wcn36xx_get_cap_name(enum place_holder_in_cap_bitmap x)
256{
257 if (x >= ARRAY_SIZE(wcn36xx_caps_names))
258 return "UNKNOWN";
259 return wcn36xx_caps_names[x];
260}
261
262static void wcn36xx_feat_caps_info(struct wcn36xx *wcn)
263{
264 int i;
265
266 for (i = 0; i < MAX_FEATURE_SUPPORTED; i++) {
267 if (get_feat_caps(wcn->fw_feat_caps, i))
268 wcn36xx_dbg(WCN36XX_DBG_MAC, "FW Cap %s\n", wcn36xx_get_cap_name(i));
269 }
270}
271
272static int wcn36xx_start(struct ieee80211_hw *hw)
273{
274 struct wcn36xx *wcn = hw->priv;
275 int ret;
276
277 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac start\n");
278
279
280 ret = wcn36xx_smd_open(wcn);
281 if (ret) {
282 wcn36xx_err("Failed to open smd channel: %d\n", ret);
283 goto out_err;
284 }
285
286
287 ret = wcn36xx_dxe_allocate_mem_pools(wcn);
288 if (ret) {
289 wcn36xx_err("Failed to alloc DXE mempool: %d\n", ret);
290 goto out_smd_close;
291 }
292
293 ret = wcn36xx_dxe_alloc_ctl_blks(wcn);
294 if (ret) {
295 wcn36xx_err("Failed to alloc DXE ctl blocks: %d\n", ret);
296 goto out_free_dxe_pool;
297 }
298
299 ret = wcn36xx_smd_load_nv(wcn);
300 if (ret) {
301 wcn36xx_err("Failed to push NV to chip\n");
302 goto out_free_dxe_ctl;
303 }
304
305 ret = wcn36xx_smd_start(wcn);
306 if (ret) {
307 wcn36xx_err("Failed to start chip\n");
308 goto out_free_dxe_ctl;
309 }
310
311 if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
312 ret = wcn36xx_smd_feature_caps_exchange(wcn);
313 if (ret)
314 wcn36xx_warn("Exchange feature caps failed\n");
315 else
316 wcn36xx_feat_caps_info(wcn);
317 }
318
319
320 ret = wcn36xx_dxe_init(wcn);
321 if (ret) {
322 wcn36xx_err("DXE init failed\n");
323 goto out_smd_stop;
324 }
325
326 wcn36xx_debugfs_init(wcn);
327
328 INIT_LIST_HEAD(&wcn->vif_list);
329 spin_lock_init(&wcn->dxe_lock);
330
331 return 0;
332
333out_smd_stop:
334 wcn36xx_smd_stop(wcn);
335out_free_dxe_ctl:
336 wcn36xx_dxe_free_ctl_blks(wcn);
337out_free_dxe_pool:
338 wcn36xx_dxe_free_mem_pools(wcn);
339out_smd_close:
340 wcn36xx_smd_close(wcn);
341out_err:
342 return ret;
343}
344
345static void wcn36xx_stop(struct ieee80211_hw *hw)
346{
347 struct wcn36xx *wcn = hw->priv;
348
349 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop\n");
350
351 mutex_lock(&wcn->scan_lock);
352 if (wcn->scan_req) {
353 struct cfg80211_scan_info scan_info = {
354 .aborted = true,
355 };
356
357 ieee80211_scan_completed(wcn->hw, &scan_info);
358 }
359 wcn->scan_req = NULL;
360 mutex_unlock(&wcn->scan_lock);
361
362 wcn36xx_debugfs_exit(wcn);
363 wcn36xx_smd_stop(wcn);
364 wcn36xx_dxe_deinit(wcn);
365 wcn36xx_smd_close(wcn);
366
367 wcn36xx_dxe_free_mem_pools(wcn);
368 wcn36xx_dxe_free_ctl_blks(wcn);
369}
370
371static void wcn36xx_change_ps(struct wcn36xx *wcn, bool enable)
372{
373 struct ieee80211_vif *vif = NULL;
374 struct wcn36xx_vif *tmp;
375
376 list_for_each_entry(tmp, &wcn->vif_list, list) {
377 vif = wcn36xx_priv_to_vif(tmp);
378 if (enable && !wcn->sw_scan) {
379 if (vif->bss_conf.ps)
380 wcn36xx_pmc_enter_bmps_state(wcn, vif);
381 } else {
382 wcn36xx_pmc_exit_bmps_state(wcn, vif);
383 }
384 }
385}
386
387static void wcn36xx_change_opchannel(struct wcn36xx *wcn, int ch)
388{
389 struct ieee80211_vif *vif = NULL;
390 struct wcn36xx_vif *tmp;
391
392 list_for_each_entry(tmp, &wcn->vif_list, list) {
393 vif = wcn36xx_priv_to_vif(tmp);
394 wcn36xx_smd_switch_channel(wcn, vif, ch);
395 }
396}
397
398static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
399{
400 struct wcn36xx *wcn = hw->priv;
401
402 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed);
403
404 mutex_lock(&wcn->conf_mutex);
405
406 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
407 int ch = WCN36XX_HW_CHANNEL(wcn);
408 wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n",
409 ch);
410
411 if (wcn->sw_scan_opchannel == ch) {
412
413
414
415
416 wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN,
417 wcn->sw_scan_vif);
418 } else if (wcn->sw_scan) {
419
420
421
422 wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN,
423 wcn->sw_scan_vif);
424 wcn36xx_smd_start_scan(wcn, ch);
425 } else {
426 wcn36xx_change_opchannel(wcn, ch);
427 }
428 }
429
430 if (changed & IEEE80211_CONF_CHANGE_PS)
431 wcn36xx_change_ps(wcn, hw->conf.flags & IEEE80211_CONF_PS);
432
433 mutex_unlock(&wcn->conf_mutex);
434
435 return 0;
436}
437
438static void wcn36xx_configure_filter(struct ieee80211_hw *hw,
439 unsigned int changed,
440 unsigned int *total, u64 multicast)
441{
442 struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp;
443 struct wcn36xx *wcn = hw->priv;
444 struct wcn36xx_vif *tmp;
445 struct ieee80211_vif *vif = NULL;
446
447 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n");
448
449 mutex_lock(&wcn->conf_mutex);
450
451 *total &= FIF_ALLMULTI;
452
453 fp = (void *)(unsigned long)multicast;
454 list_for_each_entry(tmp, &wcn->vif_list, list) {
455 vif = wcn36xx_priv_to_vif(tmp);
456
457
458 if (*total & FIF_ALLMULTI)
459 wcn36xx_smd_set_mc_list(wcn, vif, NULL);
460 else if (NL80211_IFTYPE_STATION == vif->type && tmp->sta_assoc)
461 wcn36xx_smd_set_mc_list(wcn, vif, fp);
462 }
463
464 mutex_unlock(&wcn->conf_mutex);
465 kfree(fp);
466}
467
468static u64 wcn36xx_prepare_multicast(struct ieee80211_hw *hw,
469 struct netdev_hw_addr_list *mc_list)
470{
471 struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp;
472 struct netdev_hw_addr *ha;
473
474 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac prepare multicast list\n");
475 fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
476 if (!fp) {
477 wcn36xx_err("Out of memory setting filters.\n");
478 return 0;
479 }
480
481 fp->mc_addr_count = 0;
482
483 if (netdev_hw_addr_list_count(mc_list) <=
484 WCN36XX_HAL_MAX_NUM_MULTICAST_ADDRESS) {
485 netdev_hw_addr_list_for_each(ha, mc_list) {
486 memcpy(fp->mc_addr[fp->mc_addr_count],
487 ha->addr, ETH_ALEN);
488 fp->mc_addr_count++;
489 }
490 }
491
492 return (u64)(unsigned long)fp;
493}
494
495static void wcn36xx_tx(struct ieee80211_hw *hw,
496 struct ieee80211_tx_control *control,
497 struct sk_buff *skb)
498{
499 struct wcn36xx *wcn = hw->priv;
500 struct wcn36xx_sta *sta_priv = NULL;
501
502 if (control->sta)
503 sta_priv = wcn36xx_sta_to_priv(control->sta);
504
505 if (wcn36xx_start_tx(wcn, sta_priv, skb))
506 ieee80211_free_txskb(wcn->hw, skb);
507}
508
509static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
510 struct ieee80211_vif *vif,
511 struct ieee80211_sta *sta,
512 struct ieee80211_key_conf *key_conf)
513{
514 struct wcn36xx *wcn = hw->priv;
515 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
516 struct wcn36xx_sta *sta_priv = sta ? wcn36xx_sta_to_priv(sta) : NULL;
517 int ret = 0;
518 u8 key[WLAN_MAX_KEY_LEN];
519
520 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 set key\n");
521 wcn36xx_dbg(WCN36XX_DBG_MAC, "Key: cmd=0x%x algo:0x%x, id:%d, len:%d flags 0x%x\n",
522 cmd, key_conf->cipher, key_conf->keyidx,
523 key_conf->keylen, key_conf->flags);
524 wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "KEY: ",
525 key_conf->key,
526 key_conf->keylen);
527
528 mutex_lock(&wcn->conf_mutex);
529
530 switch (key_conf->cipher) {
531 case WLAN_CIPHER_SUITE_WEP40:
532 vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40;
533 break;
534 case WLAN_CIPHER_SUITE_WEP104:
535 vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP104;
536 break;
537 case WLAN_CIPHER_SUITE_CCMP:
538 vif_priv->encrypt_type = WCN36XX_HAL_ED_CCMP;
539 break;
540 case WLAN_CIPHER_SUITE_TKIP:
541 vif_priv->encrypt_type = WCN36XX_HAL_ED_TKIP;
542 break;
543 default:
544 wcn36xx_err("Unsupported key type 0x%x\n",
545 key_conf->cipher);
546 ret = -EOPNOTSUPP;
547 goto out;
548 }
549
550 switch (cmd) {
551 case SET_KEY:
552 if (WCN36XX_HAL_ED_TKIP == vif_priv->encrypt_type) {
553
554
555
556
557
558
559
560 memcpy(key, key_conf->key, 16);
561 memcpy(key + 16, key_conf->key + 24, 8);
562 memcpy(key + 24, key_conf->key + 16, 8);
563 } else {
564 memcpy(key, key_conf->key, key_conf->keylen);
565 }
566
567 if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) {
568 sta_priv->is_data_encrypted = true;
569
570 if (NL80211_IFTYPE_STATION == vif->type)
571 wcn36xx_smd_config_bss(wcn,
572 vif,
573 sta,
574 sta->addr,
575 true);
576
577 wcn36xx_smd_set_stakey(wcn,
578 vif_priv->encrypt_type,
579 key_conf->keyidx,
580 key_conf->keylen,
581 key,
582 get_sta_index(vif, sta_priv));
583 } else {
584 wcn36xx_smd_set_bsskey(wcn,
585 vif_priv->encrypt_type,
586 vif_priv->bss_index,
587 key_conf->keyidx,
588 key_conf->keylen,
589 key);
590
591 if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) ||
592 (WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) {
593 list_for_each_entry(sta_priv,
594 &vif_priv->sta_list, list) {
595 sta_priv->is_data_encrypted = true;
596 wcn36xx_smd_set_stakey(wcn,
597 vif_priv->encrypt_type,
598 key_conf->keyidx,
599 key_conf->keylen,
600 key,
601 get_sta_index(vif, sta_priv));
602 }
603 }
604 }
605
606
607
608
609
610
611
612 if (vif->type == NL80211_IFTYPE_STATION)
613 vif_priv->allow_bmps = true;
614 break;
615 case DISABLE_KEY:
616 if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) {
617 if (vif_priv->bss_index != WCN36XX_HAL_BSS_INVALID_IDX)
618 wcn36xx_smd_remove_bsskey(wcn,
619 vif_priv->encrypt_type,
620 vif_priv->bss_index,
621 key_conf->keyidx);
622
623 vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE;
624 } else {
625 sta_priv->is_data_encrypted = false;
626
627 if (sta_priv->aid)
628 wcn36xx_smd_remove_stakey(wcn,
629 vif_priv->encrypt_type,
630 key_conf->keyidx,
631 get_sta_index(vif, sta_priv));
632 }
633 break;
634 default:
635 wcn36xx_err("Unsupported key cmd 0x%x\n", cmd);
636 ret = -EOPNOTSUPP;
637 goto out;
638 }
639
640out:
641 mutex_unlock(&wcn->conf_mutex);
642
643 return ret;
644}
645
646static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
647 struct ieee80211_vif *vif,
648 struct ieee80211_scan_request *hw_req)
649{
650 struct wcn36xx *wcn = hw->priv;
651 int i;
652
653 if (!get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) {
654
655 return 1;
656 }
657
658
659
660
661 for (i = 0; i < hw_req->req.n_channels; i++) {
662 if (hw_req->req.channels[i]->band != NL80211_BAND_2GHZ)
663 return 1;
664 }
665
666 mutex_lock(&wcn->scan_lock);
667 if (wcn->scan_req) {
668 mutex_unlock(&wcn->scan_lock);
669 return -EBUSY;
670 }
671
672 wcn->scan_aborted = false;
673 wcn->scan_req = &hw_req->req;
674
675 mutex_unlock(&wcn->scan_lock);
676
677 return wcn36xx_smd_start_hw_scan(wcn, vif, &hw_req->req);
678}
679
680static void wcn36xx_cancel_hw_scan(struct ieee80211_hw *hw,
681 struct ieee80211_vif *vif)
682{
683 struct wcn36xx *wcn = hw->priv;
684
685 mutex_lock(&wcn->scan_lock);
686 wcn->scan_aborted = true;
687 mutex_unlock(&wcn->scan_lock);
688
689 if (get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) {
690
691
692 wcn36xx_smd_stop_hw_scan(wcn);
693 }
694}
695
696static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw,
697 struct ieee80211_vif *vif,
698 const u8 *mac_addr)
699{
700 struct wcn36xx *wcn = hw->priv;
701 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
702
703 wcn->sw_scan = true;
704 wcn->sw_scan_vif = vif;
705 if (vif_priv->sta_assoc)
706 wcn->sw_scan_opchannel = WCN36XX_HW_CHANNEL(wcn);
707 else
708 wcn->sw_scan_opchannel = 0;
709}
710
711static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw,
712 struct ieee80211_vif *vif)
713{
714 struct wcn36xx *wcn = hw->priv;
715
716
717 wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN, wcn->sw_scan_vif);
718 wcn->sw_scan = false;
719 wcn->sw_scan_opchannel = 0;
720}
721
722static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
723 enum nl80211_band band)
724{
725 int i, size;
726 u16 *rates_table;
727 struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
728 u32 rates = sta->supp_rates[band];
729
730 memset(&sta_priv->supported_rates, 0,
731 sizeof(sta_priv->supported_rates));
732 sta_priv->supported_rates.op_rate_mode = STA_11n;
733
734 size = ARRAY_SIZE(sta_priv->supported_rates.dsss_rates);
735 rates_table = sta_priv->supported_rates.dsss_rates;
736 if (band == NL80211_BAND_2GHZ) {
737 for (i = 0; i < size; i++) {
738 if (rates & 0x01) {
739 rates_table[i] = wcn_2ghz_rates[i].hw_value;
740 rates = rates >> 1;
741 }
742 }
743 }
744
745 size = ARRAY_SIZE(sta_priv->supported_rates.ofdm_rates);
746 rates_table = sta_priv->supported_rates.ofdm_rates;
747 for (i = 0; i < size; i++) {
748 if (rates & 0x01) {
749 rates_table[i] = wcn_5ghz_rates[i].hw_value;
750 rates = rates >> 1;
751 }
752 }
753
754 if (sta->ht_cap.ht_supported) {
755 BUILD_BUG_ON(sizeof(sta->ht_cap.mcs.rx_mask) >
756 sizeof(sta_priv->supported_rates.supported_mcs_set));
757 memcpy(sta_priv->supported_rates.supported_mcs_set,
758 sta->ht_cap.mcs.rx_mask,
759 sizeof(sta->ht_cap.mcs.rx_mask));
760 }
761
762 if (sta->vht_cap.vht_supported) {
763 sta_priv->supported_rates.op_rate_mode = STA_11ac;
764 sta_priv->supported_rates.vht_rx_mcs_map =
765 sta->vht_cap.vht_mcs.rx_mcs_map;
766 sta_priv->supported_rates.vht_tx_mcs_map =
767 sta->vht_cap.vht_mcs.tx_mcs_map;
768 }
769}
770
771void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates)
772{
773 u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES] = {
774 HW_RATE_INDEX_6MBPS,
775 HW_RATE_INDEX_9MBPS,
776 HW_RATE_INDEX_12MBPS,
777 HW_RATE_INDEX_18MBPS,
778 HW_RATE_INDEX_24MBPS,
779 HW_RATE_INDEX_36MBPS,
780 HW_RATE_INDEX_48MBPS,
781 HW_RATE_INDEX_54MBPS
782 };
783 u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES] = {
784 HW_RATE_INDEX_1MBPS,
785 HW_RATE_INDEX_2MBPS,
786 HW_RATE_INDEX_5_5MBPS,
787 HW_RATE_INDEX_11MBPS
788 };
789
790 rates->op_rate_mode = STA_11n;
791 memcpy(rates->dsss_rates, dsss_rates,
792 sizeof(*dsss_rates) * WCN36XX_HAL_NUM_DSSS_RATES);
793 memcpy(rates->ofdm_rates, ofdm_rates,
794 sizeof(*ofdm_rates) * WCN36XX_HAL_NUM_OFDM_RATES);
795 rates->supported_mcs_set[0] = 0xFF;
796}
797
798void wcn36xx_set_default_rates_v1(struct wcn36xx_hal_supported_rates_v1 *rates)
799{
800 rates->op_rate_mode = STA_11ac;
801 rates->vht_rx_mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9;
802 rates->vht_tx_mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9;
803}
804
805static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
806 struct ieee80211_vif *vif,
807 struct ieee80211_bss_conf *bss_conf,
808 u32 changed)
809{
810 struct wcn36xx *wcn = hw->priv;
811 struct sk_buff *skb = NULL;
812 u16 tim_off, tim_len;
813 enum wcn36xx_hal_link_state link_state;
814 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
815
816 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n",
817 vif, changed);
818
819 mutex_lock(&wcn->conf_mutex);
820
821 if (changed & BSS_CHANGED_BEACON_INFO) {
822 wcn36xx_dbg(WCN36XX_DBG_MAC,
823 "mac bss changed dtim period %d\n",
824 bss_conf->dtim_period);
825
826 vif_priv->dtim_period = bss_conf->dtim_period;
827 }
828
829 if (changed & BSS_CHANGED_BSSID) {
830 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n",
831 bss_conf->bssid);
832
833 if (!is_zero_ether_addr(bss_conf->bssid)) {
834 vif_priv->is_joining = true;
835 vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
836 wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, vif->addr,
837 WCN36XX_HAL_LINK_PREASSOC_STATE);
838 wcn36xx_smd_join(wcn, bss_conf->bssid,
839 vif->addr, WCN36XX_HW_CHANNEL(wcn));
840 wcn36xx_smd_config_bss(wcn, vif, NULL,
841 bss_conf->bssid, false);
842 } else {
843 vif_priv->is_joining = false;
844 wcn36xx_smd_delete_bss(wcn, vif);
845 wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, vif->addr,
846 WCN36XX_HAL_LINK_IDLE_STATE);
847 vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE;
848 }
849 }
850
851 if (changed & BSS_CHANGED_SSID) {
852 wcn36xx_dbg(WCN36XX_DBG_MAC,
853 "mac bss changed ssid\n");
854 wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "ssid ",
855 bss_conf->ssid, bss_conf->ssid_len);
856
857 vif_priv->ssid.length = bss_conf->ssid_len;
858 memcpy(&vif_priv->ssid.ssid,
859 bss_conf->ssid,
860 bss_conf->ssid_len);
861 }
862
863 if (changed & BSS_CHANGED_ASSOC) {
864 vif_priv->is_joining = false;
865 if (bss_conf->assoc) {
866 struct ieee80211_sta *sta;
867 struct wcn36xx_sta *sta_priv;
868
869 wcn36xx_dbg(WCN36XX_DBG_MAC,
870 "mac assoc bss %pM vif %pM AID=%d\n",
871 bss_conf->bssid,
872 vif->addr,
873 bss_conf->aid);
874
875 vif_priv->sta_assoc = true;
876
877
878
879
880
881
882
883 sta = ieee80211_find_sta(vif, bss_conf->bssid);
884 if (!sta) {
885 wcn36xx_err("sta %pM is not found\n",
886 bss_conf->bssid);
887 goto out;
888 }
889 sta_priv = wcn36xx_sta_to_priv(sta);
890
891 wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn));
892
893 wcn36xx_smd_set_link_st(wcn, bss_conf->bssid,
894 vif->addr,
895 WCN36XX_HAL_LINK_POSTASSOC_STATE);
896 wcn36xx_smd_config_bss(wcn, vif, sta,
897 bss_conf->bssid,
898 true);
899 sta_priv->aid = bss_conf->aid;
900
901
902
903
904 wcn36xx_smd_config_sta(wcn, vif, sta);
905 wcn36xx_enable_keep_alive_null_packet(wcn, vif);
906 } else {
907 wcn36xx_dbg(WCN36XX_DBG_MAC,
908 "disassociated bss %pM vif %pM AID=%d\n",
909 bss_conf->bssid,
910 vif->addr,
911 bss_conf->aid);
912 vif_priv->sta_assoc = false;
913 vif_priv->allow_bmps = false;
914 wcn36xx_smd_set_link_st(wcn,
915 bss_conf->bssid,
916 vif->addr,
917 WCN36XX_HAL_LINK_IDLE_STATE);
918 }
919 }
920
921 if (changed & BSS_CHANGED_AP_PROBE_RESP) {
922 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed ap probe resp\n");
923 skb = ieee80211_proberesp_get(hw, vif);
924 if (!skb) {
925 wcn36xx_err("failed to alloc probereq skb\n");
926 goto out;
927 }
928
929 wcn36xx_smd_update_proberesp_tmpl(wcn, vif, skb);
930 dev_kfree_skb(skb);
931 }
932
933 if (changed & BSS_CHANGED_BEACON_ENABLED ||
934 changed & BSS_CHANGED_BEACON) {
935 wcn36xx_dbg(WCN36XX_DBG_MAC,
936 "mac bss changed beacon enabled %d\n",
937 bss_conf->enable_beacon);
938
939 if (bss_conf->enable_beacon) {
940 vif_priv->dtim_period = bss_conf->dtim_period;
941 vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
942 wcn36xx_smd_config_bss(wcn, vif, NULL,
943 vif->addr, false);
944 skb = ieee80211_beacon_get_tim(hw, vif, &tim_off,
945 &tim_len);
946 if (!skb) {
947 wcn36xx_err("failed to alloc beacon skb\n");
948 goto out;
949 }
950 wcn36xx_smd_send_beacon(wcn, vif, skb, tim_off, 0);
951 dev_kfree_skb(skb);
952
953 if (vif->type == NL80211_IFTYPE_ADHOC ||
954 vif->type == NL80211_IFTYPE_MESH_POINT)
955 link_state = WCN36XX_HAL_LINK_IBSS_STATE;
956 else
957 link_state = WCN36XX_HAL_LINK_AP_STATE;
958
959 wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
960 link_state);
961 } else {
962 wcn36xx_smd_delete_bss(wcn, vif);
963 wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
964 WCN36XX_HAL_LINK_IDLE_STATE);
965 }
966 }
967out:
968
969 mutex_unlock(&wcn->conf_mutex);
970}
971
972
973static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
974{
975 struct wcn36xx *wcn = hw->priv;
976 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value);
977
978 mutex_lock(&wcn->conf_mutex);
979 wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_RTS_THRESHOLD, value);
980 mutex_unlock(&wcn->conf_mutex);
981
982 return 0;
983}
984
985static void wcn36xx_remove_interface(struct ieee80211_hw *hw,
986 struct ieee80211_vif *vif)
987{
988 struct wcn36xx *wcn = hw->priv;
989 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
990 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif);
991
992 mutex_lock(&wcn->conf_mutex);
993
994 list_del(&vif_priv->list);
995 wcn36xx_smd_delete_sta_self(wcn, vif->addr);
996
997 mutex_unlock(&wcn->conf_mutex);
998}
999
1000static int wcn36xx_add_interface(struct ieee80211_hw *hw,
1001 struct ieee80211_vif *vif)
1002{
1003 struct wcn36xx *wcn = hw->priv;
1004 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1005
1006 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n",
1007 vif, vif->type);
1008
1009 if (!(NL80211_IFTYPE_STATION == vif->type ||
1010 NL80211_IFTYPE_AP == vif->type ||
1011 NL80211_IFTYPE_ADHOC == vif->type ||
1012 NL80211_IFTYPE_MESH_POINT == vif->type)) {
1013 wcn36xx_warn("Unsupported interface type requested: %d\n",
1014 vif->type);
1015 return -EOPNOTSUPP;
1016 }
1017
1018 mutex_lock(&wcn->conf_mutex);
1019
1020 vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX;
1021 INIT_LIST_HEAD(&vif_priv->sta_list);
1022 list_add(&vif_priv->list, &wcn->vif_list);
1023 wcn36xx_smd_add_sta_self(wcn, vif);
1024
1025 mutex_unlock(&wcn->conf_mutex);
1026
1027 return 0;
1028}
1029
1030static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1031 struct ieee80211_sta *sta)
1032{
1033 struct wcn36xx *wcn = hw->priv;
1034 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1035 struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
1036 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n",
1037 vif, sta->addr);
1038
1039 mutex_lock(&wcn->conf_mutex);
1040
1041 spin_lock_init(&sta_priv->ampdu_lock);
1042 sta_priv->vif = vif_priv;
1043 list_add(&sta_priv->list, &vif_priv->sta_list);
1044
1045
1046
1047
1048
1049 if (NL80211_IFTYPE_STATION != vif->type) {
1050 wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn));
1051 sta_priv->aid = sta->aid;
1052 wcn36xx_smd_config_sta(wcn, vif, sta);
1053 }
1054
1055 mutex_unlock(&wcn->conf_mutex);
1056
1057 return 0;
1058}
1059
1060static int wcn36xx_sta_remove(struct ieee80211_hw *hw,
1061 struct ieee80211_vif *vif,
1062 struct ieee80211_sta *sta)
1063{
1064 struct wcn36xx *wcn = hw->priv;
1065 struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
1066
1067 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n",
1068 vif, sta->addr, sta_priv->sta_index);
1069
1070 mutex_lock(&wcn->conf_mutex);
1071
1072 list_del(&sta_priv->list);
1073 wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index);
1074 sta_priv->vif = NULL;
1075
1076 mutex_unlock(&wcn->conf_mutex);
1077
1078 return 0;
1079}
1080
1081#ifdef CONFIG_PM
1082
1083static struct ieee80211_vif *wcn36xx_get_first_assoc_vif(struct wcn36xx *wcn)
1084{
1085 struct wcn36xx_vif *vif_priv = NULL;
1086 struct ieee80211_vif *vif = NULL;
1087
1088 list_for_each_entry(vif_priv, &wcn->vif_list, list) {
1089 if (vif_priv->sta_assoc) {
1090 vif = wcn36xx_priv_to_vif(vif_priv);
1091 break;
1092 }
1093 }
1094 return vif;
1095}
1096
1097static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow)
1098{
1099 struct wcn36xx *wcn = hw->priv;
1100 struct ieee80211_vif *vif = NULL;
1101 int ret = 0;
1102
1103 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac suspend\n");
1104
1105 mutex_lock(&wcn->conf_mutex);
1106
1107 vif = wcn36xx_get_first_assoc_vif(wcn);
1108 if (vif) {
1109 ret = wcn36xx_smd_arp_offload(wcn, vif, true);
1110 if (ret)
1111 goto out;
1112 ret = wcn36xx_smd_ipv6_ns_offload(wcn, vif, true);
1113 if (ret)
1114 goto out;
1115 ret = wcn36xx_smd_gtk_offload(wcn, vif, true);
1116 if (ret)
1117 goto out;
1118 ret = wcn36xx_smd_set_power_params(wcn, true);
1119 if (ret)
1120 goto out;
1121 ret = wcn36xx_smd_wlan_host_suspend_ind(wcn);
1122 }
1123out:
1124 mutex_unlock(&wcn->conf_mutex);
1125 return ret;
1126}
1127
1128static int wcn36xx_resume(struct ieee80211_hw *hw)
1129{
1130 struct wcn36xx *wcn = hw->priv;
1131 struct ieee80211_vif *vif = NULL;
1132
1133 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac resume\n");
1134
1135 mutex_lock(&wcn->conf_mutex);
1136 vif = wcn36xx_get_first_assoc_vif(wcn);
1137 if (vif) {
1138 wcn36xx_smd_host_resume(wcn);
1139 wcn36xx_smd_set_power_params(wcn, false);
1140 wcn36xx_smd_gtk_offload_get_info(wcn, vif);
1141 wcn36xx_smd_gtk_offload(wcn, vif, false);
1142 wcn36xx_smd_ipv6_ns_offload(wcn, vif, false);
1143 wcn36xx_smd_arp_offload(wcn, vif, false);
1144 }
1145 mutex_unlock(&wcn->conf_mutex);
1146
1147 return 0;
1148}
1149
1150static void wcn36xx_set_rekey_data(struct ieee80211_hw *hw,
1151 struct ieee80211_vif *vif,
1152 struct cfg80211_gtk_rekey_data *data)
1153{
1154 struct wcn36xx *wcn = hw->priv;
1155 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1156
1157 mutex_lock(&wcn->conf_mutex);
1158
1159 memcpy(vif_priv->rekey_data.kek, data->kek, NL80211_KEK_LEN);
1160 memcpy(vif_priv->rekey_data.kck, data->kck, NL80211_KCK_LEN);
1161 vif_priv->rekey_data.replay_ctr =
1162 cpu_to_le64(be64_to_cpup((__be64 *)data->replay_ctr));
1163 vif_priv->rekey_data.valid = true;
1164
1165 mutex_unlock(&wcn->conf_mutex);
1166}
1167
1168#endif
1169
1170static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
1171 struct ieee80211_vif *vif,
1172 struct ieee80211_ampdu_params *params)
1173{
1174 struct wcn36xx *wcn = hw->priv;
1175 struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(params->sta);
1176 struct ieee80211_sta *sta = params->sta;
1177 enum ieee80211_ampdu_mlme_action action = params->action;
1178 u16 tid = params->tid;
1179 u16 *ssn = ¶ms->ssn;
1180 int ret = 0;
1181 u8 session;
1182
1183 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
1184 action, tid);
1185
1186 mutex_lock(&wcn->conf_mutex);
1187
1188 switch (action) {
1189 case IEEE80211_AMPDU_RX_START:
1190 sta_priv->tid = tid;
1191 session = wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0,
1192 get_sta_index(vif, sta_priv));
1193 wcn36xx_smd_add_ba(wcn, session);
1194 wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv), tid,
1195 session);
1196 break;
1197 case IEEE80211_AMPDU_RX_STOP:
1198 wcn36xx_smd_del_ba(wcn, tid, 0, get_sta_index(vif, sta_priv));
1199 break;
1200 case IEEE80211_AMPDU_TX_START:
1201 spin_lock_bh(&sta_priv->ampdu_lock);
1202 sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START;
1203 spin_unlock_bh(&sta_priv->ampdu_lock);
1204
1205 ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
1206 break;
1207 case IEEE80211_AMPDU_TX_OPERATIONAL:
1208 spin_lock_bh(&sta_priv->ampdu_lock);
1209 sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_OPERATIONAL;
1210 spin_unlock_bh(&sta_priv->ampdu_lock);
1211
1212 wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1,
1213 get_sta_index(vif, sta_priv));
1214 break;
1215 case IEEE80211_AMPDU_TX_STOP_FLUSH:
1216 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
1217 case IEEE80211_AMPDU_TX_STOP_CONT:
1218 spin_lock_bh(&sta_priv->ampdu_lock);
1219 sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_NONE;
1220 spin_unlock_bh(&sta_priv->ampdu_lock);
1221
1222 wcn36xx_smd_del_ba(wcn, tid, 1, get_sta_index(vif, sta_priv));
1223 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1224 break;
1225 default:
1226 wcn36xx_err("Unknown AMPDU action\n");
1227 }
1228
1229 mutex_unlock(&wcn->conf_mutex);
1230
1231 return ret;
1232}
1233
1234#if IS_ENABLED(CONFIG_IPV6)
1235static void wcn36xx_ipv6_addr_change(struct ieee80211_hw *hw,
1236 struct ieee80211_vif *vif,
1237 struct inet6_dev *idev)
1238{
1239 struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
1240 struct inet6_ifaddr *ifa;
1241 int idx = 0;
1242
1243 memset(vif_priv->tentative_addrs, 0, sizeof(vif_priv->tentative_addrs));
1244
1245 read_lock_bh(&idev->lock);
1246 list_for_each_entry(ifa, &idev->addr_list, if_list) {
1247 vif_priv->target_ipv6_addrs[idx] = ifa->addr;
1248 if (ifa->flags & IFA_F_TENTATIVE)
1249 __set_bit(idx, vif_priv->tentative_addrs);
1250 idx++;
1251 if (idx >= WCN36XX_HAL_IPV6_OFFLOAD_ADDR_MAX)
1252 break;
1253 wcn36xx_dbg(WCN36XX_DBG_MAC, "%pI6 %s\n", &ifa->addr,
1254 (ifa->flags & IFA_F_TENTATIVE) ? "tentative" : NULL);
1255 }
1256 read_unlock_bh(&idev->lock);
1257
1258 vif_priv->num_target_ipv6_addrs = idx;
1259}
1260#endif
1261
1262static const struct ieee80211_ops wcn36xx_ops = {
1263 .start = wcn36xx_start,
1264 .stop = wcn36xx_stop,
1265 .add_interface = wcn36xx_add_interface,
1266 .remove_interface = wcn36xx_remove_interface,
1267#ifdef CONFIG_PM
1268 .suspend = wcn36xx_suspend,
1269 .resume = wcn36xx_resume,
1270 .set_rekey_data = wcn36xx_set_rekey_data,
1271#endif
1272 .config = wcn36xx_config,
1273 .prepare_multicast = wcn36xx_prepare_multicast,
1274 .configure_filter = wcn36xx_configure_filter,
1275 .tx = wcn36xx_tx,
1276 .set_key = wcn36xx_set_key,
1277 .hw_scan = wcn36xx_hw_scan,
1278 .cancel_hw_scan = wcn36xx_cancel_hw_scan,
1279 .sw_scan_start = wcn36xx_sw_scan_start,
1280 .sw_scan_complete = wcn36xx_sw_scan_complete,
1281 .bss_info_changed = wcn36xx_bss_info_changed,
1282 .set_rts_threshold = wcn36xx_set_rts_threshold,
1283 .sta_add = wcn36xx_sta_add,
1284 .sta_remove = wcn36xx_sta_remove,
1285 .ampdu_action = wcn36xx_ampdu_action,
1286#if IS_ENABLED(CONFIG_IPV6)
1287 .ipv6_addr_change = wcn36xx_ipv6_addr_change,
1288#endif
1289
1290 CFG80211_TESTMODE_CMD(wcn36xx_tm_cmd)
1291};
1292
1293static void
1294wcn36xx_set_ieee80211_vht_caps(struct ieee80211_sta_vht_cap *vht_cap)
1295{
1296 vht_cap->vht_supported = true;
1297
1298 vht_cap->cap = (IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 |
1299 IEEE80211_VHT_CAP_SHORT_GI_80 |
1300 IEEE80211_VHT_CAP_RXSTBC_1 |
1301 IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
1302 IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
1303 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT |
1304 7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
1305
1306 vht_cap->vht_mcs.rx_mcs_map =
1307 cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 |
1308 IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 |
1309 IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 |
1310 IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 |
1311 IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 |
1312 IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 |
1313 IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 |
1314 IEEE80211_VHT_MCS_NOT_SUPPORTED << 14);
1315
1316 vht_cap->vht_mcs.rx_highest = cpu_to_le16(433);
1317 vht_cap->vht_mcs.tx_highest = vht_cap->vht_mcs.rx_highest;
1318
1319 vht_cap->vht_mcs.tx_mcs_map = vht_cap->vht_mcs.rx_mcs_map;
1320}
1321
1322static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
1323{
1324 static const u32 cipher_suites[] = {
1325 WLAN_CIPHER_SUITE_WEP40,
1326 WLAN_CIPHER_SUITE_WEP104,
1327 WLAN_CIPHER_SUITE_TKIP,
1328 WLAN_CIPHER_SUITE_CCMP,
1329 };
1330
1331 ieee80211_hw_set(wcn->hw, TIMING_BEACON_ONLY);
1332 ieee80211_hw_set(wcn->hw, AMPDU_AGGREGATION);
1333 ieee80211_hw_set(wcn->hw, SUPPORTS_PS);
1334 ieee80211_hw_set(wcn->hw, SIGNAL_DBM);
1335 ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL);
1336 ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS);
1337 ieee80211_hw_set(wcn->hw, REPORTS_TX_ACK_STATUS);
1338 ieee80211_hw_set(wcn->hw, CONNECTION_MONITOR);
1339
1340 wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
1341 BIT(NL80211_IFTYPE_AP) |
1342 BIT(NL80211_IFTYPE_ADHOC) |
1343 BIT(NL80211_IFTYPE_MESH_POINT);
1344
1345 wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = &wcn_band_2ghz;
1346 if (wcn->rf_id != RF_IRIS_WCN3620)
1347 wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = &wcn_band_5ghz;
1348
1349 if (wcn->rf_id == RF_IRIS_WCN3680)
1350 wcn36xx_set_ieee80211_vht_caps(&wcn_band_5ghz.vht_cap);
1351
1352 wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS;
1353 wcn->hw->wiphy->max_scan_ie_len = WCN36XX_MAX_SCAN_IE_LEN;
1354
1355 wcn->hw->wiphy->cipher_suites = cipher_suites;
1356 wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
1357
1358#ifdef CONFIG_PM
1359 wcn->hw->wiphy->wowlan = &wowlan_support;
1360#endif
1361
1362 wcn->hw->max_listen_interval = 200;
1363
1364 wcn->hw->queues = 4;
1365
1366 SET_IEEE80211_DEV(wcn->hw, wcn->dev);
1367
1368 wcn->hw->sta_data_size = sizeof(struct wcn36xx_sta);
1369 wcn->hw->vif_data_size = sizeof(struct wcn36xx_vif);
1370
1371 wiphy_ext_feature_set(wcn->hw->wiphy,
1372 NL80211_EXT_FEATURE_CQM_RSSI_LIST);
1373
1374 return 0;
1375}
1376
1377static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
1378 struct platform_device *pdev)
1379{
1380 struct device_node *mmio_node;
1381 struct device_node *iris_node;
1382 struct resource *res;
1383 int index;
1384 int ret;
1385
1386
1387 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "tx");
1388 if (!res) {
1389 wcn36xx_err("failed to get tx_irq\n");
1390 return -ENOENT;
1391 }
1392 wcn->tx_irq = res->start;
1393
1394
1395 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "rx");
1396 if (!res) {
1397 wcn36xx_err("failed to get rx_irq\n");
1398 return -ENOENT;
1399 }
1400 wcn->rx_irq = res->start;
1401
1402
1403 wcn->tx_enable_state = qcom_smem_state_get(&pdev->dev,
1404 "tx-enable", &wcn->tx_enable_state_bit);
1405 if (IS_ERR(wcn->tx_enable_state)) {
1406 wcn36xx_err("failed to get tx-enable state\n");
1407 return PTR_ERR(wcn->tx_enable_state);
1408 }
1409
1410
1411 wcn->tx_rings_empty_state = qcom_smem_state_get(&pdev->dev,
1412 "tx-rings-empty", &wcn->tx_rings_empty_state_bit);
1413 if (IS_ERR(wcn->tx_rings_empty_state)) {
1414 wcn36xx_err("failed to get tx-rings-empty state\n");
1415 return PTR_ERR(wcn->tx_rings_empty_state);
1416 }
1417
1418 mmio_node = of_parse_phandle(pdev->dev.parent->of_node, "qcom,mmio", 0);
1419 if (!mmio_node) {
1420 wcn36xx_err("failed to acquire qcom,mmio reference\n");
1421 return -EINVAL;
1422 }
1423
1424 wcn->is_pronto = !!of_device_is_compatible(mmio_node, "qcom,pronto");
1425
1426
1427 index = of_property_match_string(mmio_node, "reg-names", "ccu");
1428 wcn->ccu_base = of_iomap(mmio_node, index);
1429 if (!wcn->ccu_base) {
1430 wcn36xx_err("failed to map ccu memory\n");
1431 ret = -ENOMEM;
1432 goto put_mmio_node;
1433 }
1434
1435
1436 index = of_property_match_string(mmio_node, "reg-names", "dxe");
1437 wcn->dxe_base = of_iomap(mmio_node, index);
1438 if (!wcn->dxe_base) {
1439 wcn36xx_err("failed to map dxe memory\n");
1440 ret = -ENOMEM;
1441 goto unmap_ccu;
1442 }
1443
1444
1445 iris_node = of_get_child_by_name(mmio_node, "iris");
1446 if (iris_node) {
1447 if (of_device_is_compatible(iris_node, "qcom,wcn3620"))
1448 wcn->rf_id = RF_IRIS_WCN3620;
1449 if (of_device_is_compatible(iris_node, "qcom,wcn3680"))
1450 wcn->rf_id = RF_IRIS_WCN3680;
1451 of_node_put(iris_node);
1452 }
1453
1454 of_node_put(mmio_node);
1455 return 0;
1456
1457unmap_ccu:
1458 iounmap(wcn->ccu_base);
1459put_mmio_node:
1460 of_node_put(mmio_node);
1461 return ret;
1462}
1463
1464static int wcn36xx_probe(struct platform_device *pdev)
1465{
1466 struct ieee80211_hw *hw;
1467 struct wcn36xx *wcn;
1468 void *wcnss;
1469 int ret;
1470 const u8 *addr;
1471
1472 wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
1473
1474 wcnss = dev_get_drvdata(pdev->dev.parent);
1475
1476 hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops);
1477 if (!hw) {
1478 wcn36xx_err("failed to alloc hw\n");
1479 ret = -ENOMEM;
1480 goto out_err;
1481 }
1482 platform_set_drvdata(pdev, hw);
1483 wcn = hw->priv;
1484 wcn->hw = hw;
1485 wcn->dev = &pdev->dev;
1486 wcn->first_boot = true;
1487 mutex_init(&wcn->conf_mutex);
1488 mutex_init(&wcn->hal_mutex);
1489 mutex_init(&wcn->scan_lock);
1490
1491 wcn->hal_buf = devm_kmalloc(wcn->dev, WCN36XX_HAL_BUF_SIZE, GFP_KERNEL);
1492 if (!wcn->hal_buf) {
1493 ret = -ENOMEM;
1494 goto out_wq;
1495 }
1496
1497 ret = dma_set_mask_and_coherent(wcn->dev, DMA_BIT_MASK(32));
1498 if (ret < 0) {
1499 wcn36xx_err("failed to set DMA mask: %d\n", ret);
1500 goto out_wq;
1501 }
1502
1503 wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process, hw);
1504 if (IS_ERR(wcn->smd_channel)) {
1505 wcn36xx_err("failed to open WLAN_CTRL channel\n");
1506 ret = PTR_ERR(wcn->smd_channel);
1507 goto out_wq;
1508 }
1509
1510 addr = of_get_property(pdev->dev.of_node, "local-mac-address", &ret);
1511 if (addr && ret != ETH_ALEN) {
1512 wcn36xx_err("invalid local-mac-address\n");
1513 ret = -EINVAL;
1514 goto out_destroy_ept;
1515 } else if (addr) {
1516 wcn36xx_info("mac address: %pM\n", addr);
1517 SET_IEEE80211_PERM_ADDR(wcn->hw, addr);
1518 }
1519
1520 ret = wcn36xx_platform_get_resources(wcn, pdev);
1521 if (ret)
1522 goto out_destroy_ept;
1523
1524 wcn36xx_init_ieee80211(wcn);
1525 ret = ieee80211_register_hw(wcn->hw);
1526 if (ret)
1527 goto out_unmap;
1528
1529 return 0;
1530
1531out_unmap:
1532 iounmap(wcn->ccu_base);
1533 iounmap(wcn->dxe_base);
1534out_destroy_ept:
1535 rpmsg_destroy_ept(wcn->smd_channel);
1536out_wq:
1537 ieee80211_free_hw(hw);
1538out_err:
1539 return ret;
1540}
1541
1542static int wcn36xx_remove(struct platform_device *pdev)
1543{
1544 struct ieee80211_hw *hw = platform_get_drvdata(pdev);
1545 struct wcn36xx *wcn = hw->priv;
1546 wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n");
1547
1548 release_firmware(wcn->nv);
1549
1550 ieee80211_unregister_hw(hw);
1551
1552 qcom_smem_state_put(wcn->tx_enable_state);
1553 qcom_smem_state_put(wcn->tx_rings_empty_state);
1554
1555 rpmsg_destroy_ept(wcn->smd_channel);
1556
1557 iounmap(wcn->dxe_base);
1558 iounmap(wcn->ccu_base);
1559
1560 mutex_destroy(&wcn->hal_mutex);
1561 ieee80211_free_hw(hw);
1562
1563 return 0;
1564}
1565
1566static const struct of_device_id wcn36xx_of_match[] = {
1567 { .compatible = "qcom,wcnss-wlan" },
1568 {}
1569};
1570MODULE_DEVICE_TABLE(of, wcn36xx_of_match);
1571
1572static struct platform_driver wcn36xx_driver = {
1573 .probe = wcn36xx_probe,
1574 .remove = wcn36xx_remove,
1575 .driver = {
1576 .name = "wcn36xx",
1577 .of_match_table = wcn36xx_of_match,
1578 },
1579};
1580
1581module_platform_driver(wcn36xx_driver);
1582
1583MODULE_LICENSE("Dual BSD/GPL");
1584MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com");
1585MODULE_FIRMWARE(WLAN_NV_FILE);
1586