wcn36xx: Print FW capabilities
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / ath / wcn36xx / main.c
1 /*
2  * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
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 "wcn36xx.h"
23
24 unsigned int wcn36xx_dbg_mask;
25 module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644);
26 MODULE_PARM_DESC(debug_mask, "Debugging mask");
27
28 #define CHAN2G(_freq, _idx) { \
29         .band = IEEE80211_BAND_2GHZ, \
30         .center_freq = (_freq), \
31         .hw_value = (_idx), \
32         .max_power = 25, \
33 }
34
35 #define CHAN5G(_freq, _idx) { \
36         .band = IEEE80211_BAND_5GHZ, \
37         .center_freq = (_freq), \
38         .hw_value = (_idx), \
39         .max_power = 25, \
40 }
41
42 /* The wcn firmware expects channel values to matching
43  * their mnemonic values. So use these for .hw_value. */
44 static struct ieee80211_channel wcn_2ghz_channels[] = {
45         CHAN2G(2412, 1), /* Channel 1 */
46         CHAN2G(2417, 2), /* Channel 2 */
47         CHAN2G(2422, 3), /* Channel 3 */
48         CHAN2G(2427, 4), /* Channel 4 */
49         CHAN2G(2432, 5), /* Channel 5 */
50         CHAN2G(2437, 6), /* Channel 6 */
51         CHAN2G(2442, 7), /* Channel 7 */
52         CHAN2G(2447, 8), /* Channel 8 */
53         CHAN2G(2452, 9), /* Channel 9 */
54         CHAN2G(2457, 10), /* Channel 10 */
55         CHAN2G(2462, 11), /* Channel 11 */
56         CHAN2G(2467, 12), /* Channel 12 */
57         CHAN2G(2472, 13), /* Channel 13 */
58         CHAN2G(2484, 14)  /* Channel 14 */
59
60 };
61
62 static struct ieee80211_channel wcn_5ghz_channels[] = {
63         CHAN5G(5180, 36),
64         CHAN5G(5200, 40),
65         CHAN5G(5220, 44),
66         CHAN5G(5240, 48),
67         CHAN5G(5260, 52),
68         CHAN5G(5280, 56),
69         CHAN5G(5300, 60),
70         CHAN5G(5320, 64),
71         CHAN5G(5500, 100),
72         CHAN5G(5520, 104),
73         CHAN5G(5540, 108),
74         CHAN5G(5560, 112),
75         CHAN5G(5580, 116),
76         CHAN5G(5600, 120),
77         CHAN5G(5620, 124),
78         CHAN5G(5640, 128),
79         CHAN5G(5660, 132),
80         CHAN5G(5700, 140),
81         CHAN5G(5745, 149),
82         CHAN5G(5765, 153),
83         CHAN5G(5785, 157),
84         CHAN5G(5805, 161),
85         CHAN5G(5825, 165)
86 };
87
88 #define RATE(_bitrate, _hw_rate, _flags) { \
89         .bitrate        = (_bitrate),                   \
90         .flags          = (_flags),                     \
91         .hw_value       = (_hw_rate),                   \
92         .hw_value_short = (_hw_rate)  \
93 }
94
95 static struct ieee80211_rate wcn_2ghz_rates[] = {
96         RATE(10, HW_RATE_INDEX_1MBPS, 0),
97         RATE(20, HW_RATE_INDEX_2MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
98         RATE(55, HW_RATE_INDEX_5_5MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
99         RATE(110, HW_RATE_INDEX_11MBPS, IEEE80211_RATE_SHORT_PREAMBLE),
100         RATE(60, HW_RATE_INDEX_6MBPS, 0),
101         RATE(90, HW_RATE_INDEX_9MBPS, 0),
102         RATE(120, HW_RATE_INDEX_12MBPS, 0),
103         RATE(180, HW_RATE_INDEX_18MBPS, 0),
104         RATE(240, HW_RATE_INDEX_24MBPS, 0),
105         RATE(360, HW_RATE_INDEX_36MBPS, 0),
106         RATE(480, HW_RATE_INDEX_48MBPS, 0),
107         RATE(540, HW_RATE_INDEX_54MBPS, 0)
108 };
109
110 static struct ieee80211_rate wcn_5ghz_rates[] = {
111         RATE(60, HW_RATE_INDEX_6MBPS, 0),
112         RATE(90, HW_RATE_INDEX_9MBPS, 0),
113         RATE(120, HW_RATE_INDEX_12MBPS, 0),
114         RATE(180, HW_RATE_INDEX_18MBPS, 0),
115         RATE(240, HW_RATE_INDEX_24MBPS, 0),
116         RATE(360, HW_RATE_INDEX_36MBPS, 0),
117         RATE(480, HW_RATE_INDEX_48MBPS, 0),
118         RATE(540, HW_RATE_INDEX_54MBPS, 0)
119 };
120
121 static struct ieee80211_supported_band wcn_band_2ghz = {
122         .channels       = wcn_2ghz_channels,
123         .n_channels     = ARRAY_SIZE(wcn_2ghz_channels),
124         .bitrates       = wcn_2ghz_rates,
125         .n_bitrates     = ARRAY_SIZE(wcn_2ghz_rates),
126         .ht_cap         = {
127                 .cap =  IEEE80211_HT_CAP_GRN_FLD |
128                         IEEE80211_HT_CAP_SGI_20 |
129                         IEEE80211_HT_CAP_DSSSCCK40 |
130                         IEEE80211_HT_CAP_LSIG_TXOP_PROT,
131                 .ht_supported = true,
132                 .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
133                 .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
134                 .mcs = {
135                         .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
136                         .rx_highest = cpu_to_le16(72),
137                         .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
138                 }
139         }
140 };
141
142 static struct ieee80211_supported_band wcn_band_5ghz = {
143         .channels       = wcn_5ghz_channels,
144         .n_channels     = ARRAY_SIZE(wcn_5ghz_channels),
145         .bitrates       = wcn_5ghz_rates,
146         .n_bitrates     = ARRAY_SIZE(wcn_5ghz_rates),
147         .ht_cap         = {
148                 .cap =  IEEE80211_HT_CAP_GRN_FLD |
149                         IEEE80211_HT_CAP_SGI_20 |
150                         IEEE80211_HT_CAP_DSSSCCK40 |
151                         IEEE80211_HT_CAP_LSIG_TXOP_PROT |
152                         IEEE80211_HT_CAP_SGI_40 |
153                         IEEE80211_HT_CAP_SUP_WIDTH_20_40,
154                 .ht_supported = true,
155                 .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
156                 .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
157                 .mcs = {
158                         .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
159                         .rx_highest = cpu_to_le16(72),
160                         .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
161                 }
162         }
163 };
164
165 #ifdef CONFIG_PM
166
167 static const struct wiphy_wowlan_support wowlan_support = {
168         .flags = WIPHY_WOWLAN_ANY
169 };
170
171 #endif
172
173 static inline u8 get_sta_index(struct ieee80211_vif *vif,
174                                struct wcn36xx_sta *sta_priv)
175 {
176         return NL80211_IFTYPE_STATION == vif->type ?
177                sta_priv->bss_sta_index :
178                sta_priv->sta_index;
179 }
180
181 static const char * const wcn36xx_caps_names[] = {
182         "MCC",                          /* 0 */
183         "P2P",                          /* 1 */
184         "DOT11AC",                      /* 2 */
185         "SLM_SESSIONIZATION",           /* 3 */
186         "DOT11AC_OPMODE",               /* 4 */
187         "SAP32STA",                     /* 5 */
188         "TDLS",                         /* 6 */
189         "P2P_GO_NOA_DECOUPLE_INIT_SCAN",/* 7 */
190         "WLANACTIVE_OFFLOAD",           /* 8 */
191         "BEACON_OFFLOAD",               /* 9 */
192         "SCAN_OFFLOAD",                 /* 10 */
193         "ROAM_OFFLOAD",                 /* 11 */
194         "BCN_MISS_OFFLOAD",             /* 12 */
195         "STA_POWERSAVE",                /* 13 */
196         "STA_ADVANCED_PWRSAVE",         /* 14 */
197         "AP_UAPSD",                     /* 15 */
198         "AP_DFS",                       /* 16 */
199         "BLOCKACK",                     /* 17 */
200         "PHY_ERR",                      /* 18 */
201         "BCN_FILTER",                   /* 19 */
202         "RTT",                          /* 20 */
203         "RATECTRL",                     /* 21 */
204         "WOW"                           /* 22 */
205 };
206
207 static const char *wcn36xx_get_cap_name(enum place_holder_in_cap_bitmap x)
208 {
209         if (x >= ARRAY_SIZE(wcn36xx_caps_names))
210                 return "UNKNOWN";
211         return wcn36xx_caps_names[x];
212 }
213
214 static void wcn36xx_feat_caps_info(struct wcn36xx *wcn)
215 {
216         int i;
217
218         for (i = 0; i < MAX_FEATURE_SUPPORTED; i++) {
219                 if (get_feat_caps(wcn->fw_feat_caps, i))
220                         wcn36xx_info("FW Cap %s\n", wcn36xx_get_cap_name(i));
221         }
222 }
223
224 static int wcn36xx_start(struct ieee80211_hw *hw)
225 {
226         struct wcn36xx *wcn = hw->priv;
227         int ret;
228
229         wcn36xx_dbg(WCN36XX_DBG_MAC, "mac start\n");
230
231         /* SMD initialization */
232         ret = wcn36xx_smd_open(wcn);
233         if (ret) {
234                 wcn36xx_err("Failed to open smd channel: %d\n", ret);
235                 goto out_err;
236         }
237
238         /* Allocate memory pools for Mgmt BD headers and Data BD headers */
239         ret = wcn36xx_dxe_allocate_mem_pools(wcn);
240         if (ret) {
241                 wcn36xx_err("Failed to alloc DXE mempool: %d\n", ret);
242                 goto out_smd_close;
243         }
244
245         ret = wcn36xx_dxe_alloc_ctl_blks(wcn);
246         if (ret) {
247                 wcn36xx_err("Failed to alloc DXE ctl blocks: %d\n", ret);
248                 goto out_free_dxe_pool;
249         }
250
251         wcn->hal_buf = kmalloc(WCN36XX_HAL_BUF_SIZE, GFP_KERNEL);
252         if (!wcn->hal_buf) {
253                 wcn36xx_err("Failed to allocate smd buf\n");
254                 ret = -ENOMEM;
255                 goto out_free_dxe_ctl;
256         }
257
258         ret = wcn36xx_smd_load_nv(wcn);
259         if (ret) {
260                 wcn36xx_err("Failed to push NV to chip\n");
261                 goto out_free_smd_buf;
262         }
263
264         ret = wcn36xx_smd_start(wcn);
265         if (ret) {
266                 wcn36xx_err("Failed to start chip\n");
267                 goto out_free_smd_buf;
268         }
269
270         /* DMA channel initialization */
271         ret = wcn36xx_dxe_init(wcn);
272         if (ret) {
273                 wcn36xx_err("DXE init failed\n");
274                 goto out_smd_stop;
275         }
276
277         wcn36xx_debugfs_init(wcn);
278
279         if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
280                 ret = wcn36xx_smd_feature_caps_exchange(wcn);
281                 if (ret)
282                         wcn36xx_warn("Exchange feature caps failed\n");
283                 else
284                         wcn36xx_feat_caps_info(wcn);
285         }
286         INIT_LIST_HEAD(&wcn->vif_list);
287         return 0;
288
289 out_smd_stop:
290         wcn36xx_smd_stop(wcn);
291 out_free_smd_buf:
292         kfree(wcn->hal_buf);
293 out_free_dxe_pool:
294         wcn36xx_dxe_free_mem_pools(wcn);
295 out_free_dxe_ctl:
296         wcn36xx_dxe_free_ctl_blks(wcn);
297 out_smd_close:
298         wcn36xx_smd_close(wcn);
299 out_err:
300         return ret;
301 }
302
303 static void wcn36xx_stop(struct ieee80211_hw *hw)
304 {
305         struct wcn36xx *wcn = hw->priv;
306
307         wcn36xx_dbg(WCN36XX_DBG_MAC, "mac stop\n");
308
309         wcn36xx_debugfs_exit(wcn);
310         wcn36xx_smd_stop(wcn);
311         wcn36xx_dxe_deinit(wcn);
312         wcn36xx_smd_close(wcn);
313
314         wcn36xx_dxe_free_mem_pools(wcn);
315         wcn36xx_dxe_free_ctl_blks(wcn);
316
317         kfree(wcn->hal_buf);
318 }
319
320 static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
321 {
322         struct wcn36xx *wcn = hw->priv;
323         struct ieee80211_vif *vif = NULL;
324         struct wcn36xx_vif *tmp;
325
326         wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed);
327
328         if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
329                 int ch = WCN36XX_HW_CHANNEL(wcn);
330                 wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n",
331                             ch);
332                 list_for_each_entry(tmp, &wcn->vif_list, list) {
333                         vif = container_of((void *)tmp,
334                                            struct ieee80211_vif,
335                                            drv_priv);
336                         wcn36xx_smd_switch_channel(wcn, vif, ch);
337                 }
338         }
339
340         return 0;
341 }
342
343 #define WCN36XX_SUPPORTED_FILTERS (0)
344
345 static void wcn36xx_configure_filter(struct ieee80211_hw *hw,
346                                      unsigned int changed,
347                                      unsigned int *total, u64 multicast)
348 {
349         wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n");
350
351         *total &= WCN36XX_SUPPORTED_FILTERS;
352 }
353
354 static void wcn36xx_tx(struct ieee80211_hw *hw,
355                        struct ieee80211_tx_control *control,
356                        struct sk_buff *skb)
357 {
358         struct wcn36xx *wcn = hw->priv;
359         struct wcn36xx_sta *sta_priv = NULL;
360
361         if (control->sta)
362                 sta_priv = (struct wcn36xx_sta *)control->sta->drv_priv;
363
364         if (wcn36xx_start_tx(wcn, sta_priv, skb))
365                 ieee80211_free_txskb(wcn->hw, skb);
366 }
367
368 static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
369                            struct ieee80211_vif *vif,
370                            struct ieee80211_sta *sta,
371                            struct ieee80211_key_conf *key_conf)
372 {
373         struct wcn36xx *wcn = hw->priv;
374         struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
375         struct wcn36xx_sta *sta_priv = vif_priv->sta;
376         int ret = 0;
377         u8 key[WLAN_MAX_KEY_LEN];
378
379         wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 set key\n");
380         wcn36xx_dbg(WCN36XX_DBG_MAC, "Key: cmd=0x%x algo:0x%x, id:%d, len:%d flags 0x%x\n",
381                     cmd, key_conf->cipher, key_conf->keyidx,
382                     key_conf->keylen, key_conf->flags);
383         wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "KEY: ",
384                          key_conf->key,
385                          key_conf->keylen);
386
387         switch (key_conf->cipher) {
388         case WLAN_CIPHER_SUITE_WEP40:
389                 vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40;
390                 break;
391         case WLAN_CIPHER_SUITE_WEP104:
392                 vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40;
393                 break;
394         case WLAN_CIPHER_SUITE_CCMP:
395                 vif_priv->encrypt_type = WCN36XX_HAL_ED_CCMP;
396                 break;
397         case WLAN_CIPHER_SUITE_TKIP:
398                 vif_priv->encrypt_type = WCN36XX_HAL_ED_TKIP;
399                 break;
400         default:
401                 wcn36xx_err("Unsupported key type 0x%x\n",
402                               key_conf->cipher);
403                 ret = -EOPNOTSUPP;
404                 goto out;
405         }
406
407         switch (cmd) {
408         case SET_KEY:
409                 if (WCN36XX_HAL_ED_TKIP == vif_priv->encrypt_type) {
410                         /*
411                          * Supplicant is sending key in the wrong order:
412                          * Temporal Key (16 b) - TX MIC (8 b) - RX MIC (8 b)
413                          * but HW expects it to be in the order as described in
414                          * IEEE 802.11 spec (see chapter 11.7) like this:
415                          * Temporal Key (16 b) - RX MIC (8 b) - TX MIC (8 b)
416                          */
417                         memcpy(key, key_conf->key, 16);
418                         memcpy(key + 16, key_conf->key + 24, 8);
419                         memcpy(key + 24, key_conf->key + 16, 8);
420                 } else {
421                         memcpy(key, key_conf->key, key_conf->keylen);
422                 }
423
424                 if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) {
425                         sta_priv->is_data_encrypted = true;
426                         /* Reconfigure bss with encrypt_type */
427                         if (NL80211_IFTYPE_STATION == vif->type)
428                                 wcn36xx_smd_config_bss(wcn,
429                                                        vif,
430                                                        sta,
431                                                        sta->addr,
432                                                        true);
433
434                         wcn36xx_smd_set_stakey(wcn,
435                                 vif_priv->encrypt_type,
436                                 key_conf->keyidx,
437                                 key_conf->keylen,
438                                 key,
439                                 get_sta_index(vif, sta_priv));
440                 } else {
441                         wcn36xx_smd_set_bsskey(wcn,
442                                 vif_priv->encrypt_type,
443                                 key_conf->keyidx,
444                                 key_conf->keylen,
445                                 key);
446                         if ((WLAN_CIPHER_SUITE_WEP40 == key_conf->cipher) ||
447                             (WLAN_CIPHER_SUITE_WEP104 == key_conf->cipher)) {
448                                 sta_priv->is_data_encrypted = true;
449                                 wcn36xx_smd_set_stakey(wcn,
450                                         vif_priv->encrypt_type,
451                                         key_conf->keyidx,
452                                         key_conf->keylen,
453                                         key,
454                                         get_sta_index(vif, sta_priv));
455                         }
456                 }
457                 break;
458         case DISABLE_KEY:
459                 if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) {
460                         wcn36xx_smd_remove_bsskey(wcn,
461                                 vif_priv->encrypt_type,
462                                 key_conf->keyidx);
463                 } else {
464                         sta_priv->is_data_encrypted = false;
465                         /* do not remove key if disassociated */
466                         if (sta_priv->aid)
467                                 wcn36xx_smd_remove_stakey(wcn,
468                                         vif_priv->encrypt_type,
469                                         key_conf->keyidx,
470                                         get_sta_index(vif, sta_priv));
471                 }
472                 break;
473         default:
474                 wcn36xx_err("Unsupported key cmd 0x%x\n", cmd);
475                 ret = -EOPNOTSUPP;
476                 goto out;
477                 break;
478         }
479
480 out:
481         return ret;
482 }
483
484 static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw)
485 {
486         struct wcn36xx *wcn = hw->priv;
487
488         wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN);
489         wcn36xx_smd_start_scan(wcn);
490 }
491
492 static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw)
493 {
494         struct wcn36xx *wcn = hw->priv;
495
496         wcn36xx_smd_end_scan(wcn);
497         wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN);
498 }
499
500 static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
501                                          enum ieee80211_band band)
502 {
503         int i, size;
504         u16 *rates_table;
505         struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
506         u32 rates = sta->supp_rates[band];
507
508         memset(&sta_priv->supported_rates, 0,
509                 sizeof(sta_priv->supported_rates));
510         sta_priv->supported_rates.op_rate_mode = STA_11n;
511
512         size = ARRAY_SIZE(sta_priv->supported_rates.dsss_rates);
513         rates_table = sta_priv->supported_rates.dsss_rates;
514         if (band == IEEE80211_BAND_2GHZ) {
515                 for (i = 0; i < size; i++) {
516                         if (rates & 0x01) {
517                                 rates_table[i] = wcn_2ghz_rates[i].hw_value;
518                                 rates = rates >> 1;
519                         }
520                 }
521         }
522
523         size = ARRAY_SIZE(sta_priv->supported_rates.ofdm_rates);
524         rates_table = sta_priv->supported_rates.ofdm_rates;
525         for (i = 0; i < size; i++) {
526                 if (rates & 0x01) {
527                         rates_table[i] = wcn_5ghz_rates[i].hw_value;
528                         rates = rates >> 1;
529                 }
530         }
531
532         if (sta->ht_cap.ht_supported) {
533                 BUILD_BUG_ON(sizeof(sta->ht_cap.mcs.rx_mask) >
534                         sizeof(sta_priv->supported_rates.supported_mcs_set));
535                 memcpy(sta_priv->supported_rates.supported_mcs_set,
536                        sta->ht_cap.mcs.rx_mask,
537                        sizeof(sta->ht_cap.mcs.rx_mask));
538         }
539 }
540 void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates)
541 {
542         u16 ofdm_rates[WCN36XX_HAL_NUM_OFDM_RATES] = {
543                 HW_RATE_INDEX_6MBPS,
544                 HW_RATE_INDEX_9MBPS,
545                 HW_RATE_INDEX_12MBPS,
546                 HW_RATE_INDEX_18MBPS,
547                 HW_RATE_INDEX_24MBPS,
548                 HW_RATE_INDEX_36MBPS,
549                 HW_RATE_INDEX_48MBPS,
550                 HW_RATE_INDEX_54MBPS
551         };
552         u16 dsss_rates[WCN36XX_HAL_NUM_DSSS_RATES] = {
553                 HW_RATE_INDEX_1MBPS,
554                 HW_RATE_INDEX_2MBPS,
555                 HW_RATE_INDEX_5_5MBPS,
556                 HW_RATE_INDEX_11MBPS
557         };
558
559         rates->op_rate_mode = STA_11n;
560         memcpy(rates->dsss_rates, dsss_rates,
561                 sizeof(*dsss_rates) * WCN36XX_HAL_NUM_DSSS_RATES);
562         memcpy(rates->ofdm_rates, ofdm_rates,
563                 sizeof(*ofdm_rates) * WCN36XX_HAL_NUM_OFDM_RATES);
564         rates->supported_mcs_set[0] = 0xFF;
565 }
566 static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
567                                      struct ieee80211_vif *vif,
568                                      struct ieee80211_bss_conf *bss_conf,
569                                      u32 changed)
570 {
571         struct wcn36xx *wcn = hw->priv;
572         struct sk_buff *skb = NULL;
573         u16 tim_off, tim_len;
574         enum wcn36xx_hal_link_state link_state;
575         struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
576
577         wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n",
578                     vif, changed);
579
580         if (changed & BSS_CHANGED_BEACON_INFO) {
581                 wcn36xx_dbg(WCN36XX_DBG_MAC,
582                             "mac bss changed dtim period %d\n",
583                             bss_conf->dtim_period);
584
585                 vif_priv->dtim_period = bss_conf->dtim_period;
586         }
587
588         if (changed & BSS_CHANGED_PS) {
589                 wcn36xx_dbg(WCN36XX_DBG_MAC,
590                             "mac bss PS set %d\n",
591                             bss_conf->ps);
592                 if (bss_conf->ps) {
593                         wcn36xx_pmc_enter_bmps_state(wcn, vif);
594                 } else {
595                         wcn36xx_pmc_exit_bmps_state(wcn, vif);
596                 }
597         }
598
599         if (changed & BSS_CHANGED_BSSID) {
600                 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed_bssid %pM\n",
601                             bss_conf->bssid);
602
603                 if (!is_zero_ether_addr(bss_conf->bssid)) {
604                         vif_priv->is_joining = true;
605                         vif_priv->bss_index = 0xff;
606                         wcn36xx_smd_join(wcn, bss_conf->bssid,
607                                          vif->addr, WCN36XX_HW_CHANNEL(wcn));
608                         wcn36xx_smd_config_bss(wcn, vif, NULL,
609                                                bss_conf->bssid, false);
610                 } else {
611                         vif_priv->is_joining = false;
612                         wcn36xx_smd_delete_bss(wcn, vif);
613                 }
614         }
615
616         if (changed & BSS_CHANGED_SSID) {
617                 wcn36xx_dbg(WCN36XX_DBG_MAC,
618                             "mac bss changed ssid\n");
619                 wcn36xx_dbg_dump(WCN36XX_DBG_MAC, "ssid ",
620                                  bss_conf->ssid, bss_conf->ssid_len);
621
622                 vif_priv->ssid.length = bss_conf->ssid_len;
623                 memcpy(&vif_priv->ssid.ssid,
624                        bss_conf->ssid,
625                        bss_conf->ssid_len);
626         }
627
628         if (changed & BSS_CHANGED_ASSOC) {
629                 vif_priv->is_joining = false;
630                 if (bss_conf->assoc) {
631                         struct ieee80211_sta *sta;
632                         struct wcn36xx_sta *sta_priv;
633
634                         wcn36xx_dbg(WCN36XX_DBG_MAC,
635                                     "mac assoc bss %pM vif %pM AID=%d\n",
636                                      bss_conf->bssid,
637                                      vif->addr,
638                                      bss_conf->aid);
639
640                         rcu_read_lock();
641                         sta = ieee80211_find_sta(vif, bss_conf->bssid);
642                         if (!sta) {
643                                 wcn36xx_err("sta %pM is not found\n",
644                                               bss_conf->bssid);
645                                 rcu_read_unlock();
646                                 goto out;
647                         }
648                         sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
649
650                         wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn));
651
652                         wcn36xx_smd_set_link_st(wcn, bss_conf->bssid,
653                                 vif->addr,
654                                 WCN36XX_HAL_LINK_POSTASSOC_STATE);
655                         wcn36xx_smd_config_bss(wcn, vif, sta,
656                                                bss_conf->bssid,
657                                                true);
658                         sta_priv->aid = bss_conf->aid;
659                         /*
660                          * config_sta must be called from  because this is the
661                          * place where AID is available.
662                          */
663                         wcn36xx_smd_config_sta(wcn, vif, sta);
664                         rcu_read_unlock();
665                 } else {
666                         wcn36xx_dbg(WCN36XX_DBG_MAC,
667                                     "disassociated bss %pM vif %pM AID=%d\n",
668                                     bss_conf->bssid,
669                                     vif->addr,
670                                     bss_conf->aid);
671                         wcn36xx_smd_set_link_st(wcn,
672                                                 bss_conf->bssid,
673                                                 vif->addr,
674                                                 WCN36XX_HAL_LINK_IDLE_STATE);
675                 }
676         }
677
678         if (changed & BSS_CHANGED_AP_PROBE_RESP) {
679                 wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss changed ap probe resp\n");
680                 skb = ieee80211_proberesp_get(hw, vif);
681                 if (!skb) {
682                         wcn36xx_err("failed to alloc probereq skb\n");
683                         goto out;
684                 }
685
686                 wcn36xx_smd_update_proberesp_tmpl(wcn, vif, skb);
687                 dev_kfree_skb(skb);
688         }
689
690         if (changed & BSS_CHANGED_BEACON_ENABLED ||
691             changed & BSS_CHANGED_BEACON) {
692                 wcn36xx_dbg(WCN36XX_DBG_MAC,
693                             "mac bss changed beacon enabled %d\n",
694                             bss_conf->enable_beacon);
695
696                 if (bss_conf->enable_beacon) {
697                         vif_priv->bss_index = 0xff;
698                         wcn36xx_smd_config_bss(wcn, vif, NULL,
699                                                vif->addr, false);
700                         skb = ieee80211_beacon_get_tim(hw, vif, &tim_off,
701                                                        &tim_len);
702                         if (!skb) {
703                                 wcn36xx_err("failed to alloc beacon skb\n");
704                                 goto out;
705                         }
706                         wcn36xx_smd_send_beacon(wcn, vif, skb, tim_off, 0);
707                         dev_kfree_skb(skb);
708
709                         if (vif->type == NL80211_IFTYPE_ADHOC ||
710                             vif->type == NL80211_IFTYPE_MESH_POINT)
711                                 link_state = WCN36XX_HAL_LINK_IBSS_STATE;
712                         else
713                                 link_state = WCN36XX_HAL_LINK_AP_STATE;
714
715                         wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
716                                                 link_state);
717                 } else {
718                         wcn36xx_smd_set_link_st(wcn, vif->addr, vif->addr,
719                                                 WCN36XX_HAL_LINK_IDLE_STATE);
720                         wcn36xx_smd_delete_bss(wcn, vif);
721                 }
722         }
723 out:
724         return;
725 }
726
727 /* this is required when using IEEE80211_HW_HAS_RATE_CONTROL */
728 static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
729 {
730         struct wcn36xx *wcn = hw->priv;
731         wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value);
732
733         wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_RTS_THRESHOLD, value);
734         return 0;
735 }
736
737 static void wcn36xx_remove_interface(struct ieee80211_hw *hw,
738                                      struct ieee80211_vif *vif)
739 {
740         struct wcn36xx *wcn = hw->priv;
741         struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
742         wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif);
743
744         list_del(&vif_priv->list);
745         wcn36xx_smd_delete_sta_self(wcn, vif->addr);
746 }
747
748 static int wcn36xx_add_interface(struct ieee80211_hw *hw,
749                                  struct ieee80211_vif *vif)
750 {
751         struct wcn36xx *wcn = hw->priv;
752         struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
753
754         wcn36xx_dbg(WCN36XX_DBG_MAC, "mac add interface vif %p type %d\n",
755                     vif, vif->type);
756
757         if (!(NL80211_IFTYPE_STATION == vif->type ||
758               NL80211_IFTYPE_AP == vif->type ||
759               NL80211_IFTYPE_ADHOC == vif->type ||
760               NL80211_IFTYPE_MESH_POINT == vif->type)) {
761                 wcn36xx_warn("Unsupported interface type requested: %d\n",
762                              vif->type);
763                 return -EOPNOTSUPP;
764         }
765
766         list_add(&vif_priv->list, &wcn->vif_list);
767         wcn36xx_smd_add_sta_self(wcn, vif);
768
769         return 0;
770 }
771
772 static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
773                            struct ieee80211_sta *sta)
774 {
775         struct wcn36xx *wcn = hw->priv;
776         struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
777         struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
778         wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n",
779                     vif, sta->addr);
780
781         vif_priv->sta = sta_priv;
782         sta_priv->vif = vif_priv;
783         /*
784          * For STA mode HW will be configured on BSS_CHANGED_ASSOC because
785          * at this stage AID is not available yet.
786          */
787         if (NL80211_IFTYPE_STATION != vif->type) {
788                 wcn36xx_update_allowed_rates(sta, WCN36XX_BAND(wcn));
789                 sta_priv->aid = sta->aid;
790                 wcn36xx_smd_config_sta(wcn, vif, sta);
791         }
792         return 0;
793 }
794
795 static int wcn36xx_sta_remove(struct ieee80211_hw *hw,
796                               struct ieee80211_vif *vif,
797                               struct ieee80211_sta *sta)
798 {
799         struct wcn36xx *wcn = hw->priv;
800         struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
801         struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
802
803         wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n",
804                     vif, sta->addr, sta_priv->sta_index);
805
806         wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index);
807         vif_priv->sta = NULL;
808         sta_priv->vif = NULL;
809         return 0;
810 }
811
812 #ifdef CONFIG_PM
813
814 static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow)
815 {
816         struct wcn36xx *wcn = hw->priv;
817
818         wcn36xx_dbg(WCN36XX_DBG_MAC, "mac suspend\n");
819
820         flush_workqueue(wcn->hal_ind_wq);
821         wcn36xx_smd_set_power_params(wcn, true);
822         return 0;
823 }
824
825 static int wcn36xx_resume(struct ieee80211_hw *hw)
826 {
827         struct wcn36xx *wcn = hw->priv;
828
829         wcn36xx_dbg(WCN36XX_DBG_MAC, "mac resume\n");
830
831         flush_workqueue(wcn->hal_ind_wq);
832         wcn36xx_smd_set_power_params(wcn, false);
833         return 0;
834 }
835
836 #endif
837
838 static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
839                     struct ieee80211_vif *vif,
840                     enum ieee80211_ampdu_mlme_action action,
841                     struct ieee80211_sta *sta, u16 tid, u16 *ssn,
842                     u8 buf_size)
843 {
844         struct wcn36xx *wcn = hw->priv;
845         struct wcn36xx_sta *sta_priv = NULL;
846
847         wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
848                     action, tid);
849
850         sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
851
852         switch (action) {
853         case IEEE80211_AMPDU_RX_START:
854                 sta_priv->tid = tid;
855                 wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 0,
856                         get_sta_index(vif, sta_priv));
857                 wcn36xx_smd_add_ba(wcn);
858                 wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv));
859                 ieee80211_start_tx_ba_session(sta, tid, 0);
860                 break;
861         case IEEE80211_AMPDU_RX_STOP:
862                 wcn36xx_smd_del_ba(wcn, tid, get_sta_index(vif, sta_priv));
863                 break;
864         case IEEE80211_AMPDU_TX_START:
865                 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
866                 break;
867         case IEEE80211_AMPDU_TX_OPERATIONAL:
868                 wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1,
869                         get_sta_index(vif, sta_priv));
870                 break;
871         case IEEE80211_AMPDU_TX_STOP_FLUSH:
872         case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
873         case IEEE80211_AMPDU_TX_STOP_CONT:
874                 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
875                 break;
876         default:
877                 wcn36xx_err("Unknown AMPDU action\n");
878         }
879
880         return 0;
881 }
882
883 static const struct ieee80211_ops wcn36xx_ops = {
884         .start                  = wcn36xx_start,
885         .stop                   = wcn36xx_stop,
886         .add_interface          = wcn36xx_add_interface,
887         .remove_interface       = wcn36xx_remove_interface,
888 #ifdef CONFIG_PM
889         .suspend                = wcn36xx_suspend,
890         .resume                 = wcn36xx_resume,
891 #endif
892         .config                 = wcn36xx_config,
893         .configure_filter       = wcn36xx_configure_filter,
894         .tx                     = wcn36xx_tx,
895         .set_key                = wcn36xx_set_key,
896         .sw_scan_start          = wcn36xx_sw_scan_start,
897         .sw_scan_complete       = wcn36xx_sw_scan_complete,
898         .bss_info_changed       = wcn36xx_bss_info_changed,
899         .set_rts_threshold      = wcn36xx_set_rts_threshold,
900         .sta_add                = wcn36xx_sta_add,
901         .sta_remove             = wcn36xx_sta_remove,
902         .ampdu_action           = wcn36xx_ampdu_action,
903 };
904
905 static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
906 {
907         int ret = 0;
908
909         static const u32 cipher_suites[] = {
910                 WLAN_CIPHER_SUITE_WEP40,
911                 WLAN_CIPHER_SUITE_WEP104,
912                 WLAN_CIPHER_SUITE_TKIP,
913                 WLAN_CIPHER_SUITE_CCMP,
914         };
915
916         wcn->hw->flags = IEEE80211_HW_SIGNAL_DBM |
917                 IEEE80211_HW_HAS_RATE_CONTROL |
918                 IEEE80211_HW_SUPPORTS_PS |
919                 IEEE80211_HW_CONNECTION_MONITOR |
920                 IEEE80211_HW_AMPDU_AGGREGATION |
921                 IEEE80211_HW_TIMING_BEACON_ONLY;
922
923         wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
924                 BIT(NL80211_IFTYPE_AP) |
925                 BIT(NL80211_IFTYPE_ADHOC) |
926                 BIT(NL80211_IFTYPE_MESH_POINT);
927
928         wcn->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wcn_band_2ghz;
929         wcn->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wcn_band_5ghz;
930
931         wcn->hw->wiphy->cipher_suites = cipher_suites;
932         wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
933
934         wcn->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
935
936 #ifdef CONFIG_PM
937         wcn->hw->wiphy->wowlan = &wowlan_support;
938 #endif
939
940         wcn->hw->max_listen_interval = 200;
941
942         wcn->hw->queues = 4;
943
944         SET_IEEE80211_DEV(wcn->hw, wcn->dev);
945
946         wcn->hw->sta_data_size = sizeof(struct wcn36xx_sta);
947         wcn->hw->vif_data_size = sizeof(struct wcn36xx_vif);
948
949         return ret;
950 }
951
952 static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
953                                           struct platform_device *pdev)
954 {
955         struct resource *res;
956         /* Set TX IRQ */
957         res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
958                                            "wcnss_wlantx_irq");
959         if (!res) {
960                 wcn36xx_err("failed to get tx_irq\n");
961                 return -ENOENT;
962         }
963         wcn->tx_irq = res->start;
964
965         /* Set RX IRQ */
966         res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
967                                            "wcnss_wlanrx_irq");
968         if (!res) {
969                 wcn36xx_err("failed to get rx_irq\n");
970                 return -ENOENT;
971         }
972         wcn->rx_irq = res->start;
973
974         /* Map the memory */
975         res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
976                                                  "wcnss_mmio");
977         if (!res) {
978                 wcn36xx_err("failed to get mmio\n");
979                 return -ENOENT;
980         }
981         wcn->mmio = ioremap(res->start, resource_size(res));
982         if (!wcn->mmio) {
983                 wcn36xx_err("failed to map io memory\n");
984                 return -ENOMEM;
985         }
986         return 0;
987 }
988
989 static int wcn36xx_probe(struct platform_device *pdev)
990 {
991         struct ieee80211_hw *hw;
992         struct wcn36xx *wcn;
993         int ret;
994         u8 addr[ETH_ALEN];
995
996         wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
997
998         hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops);
999         if (!hw) {
1000                 wcn36xx_err("failed to alloc hw\n");
1001                 ret = -ENOMEM;
1002                 goto out_err;
1003         }
1004         platform_set_drvdata(pdev, hw);
1005         wcn = hw->priv;
1006         wcn->hw = hw;
1007         wcn->dev = &pdev->dev;
1008         wcn->ctrl_ops = pdev->dev.platform_data;
1009
1010         mutex_init(&wcn->hal_mutex);
1011
1012         if (!wcn->ctrl_ops->get_hw_mac(addr)) {
1013                 wcn36xx_info("mac address: %pM\n", addr);
1014                 SET_IEEE80211_PERM_ADDR(wcn->hw, addr);
1015         }
1016
1017         ret = wcn36xx_platform_get_resources(wcn, pdev);
1018         if (ret)
1019                 goto out_wq;
1020
1021         wcn36xx_init_ieee80211(wcn);
1022         ret = ieee80211_register_hw(wcn->hw);
1023         if (ret)
1024                 goto out_unmap;
1025
1026         return 0;
1027
1028 out_unmap:
1029         iounmap(wcn->mmio);
1030 out_wq:
1031         ieee80211_free_hw(hw);
1032 out_err:
1033         return ret;
1034 }
1035 static int wcn36xx_remove(struct platform_device *pdev)
1036 {
1037         struct ieee80211_hw *hw = platform_get_drvdata(pdev);
1038         struct wcn36xx *wcn = hw->priv;
1039         wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n");
1040
1041         release_firmware(wcn->nv);
1042         mutex_destroy(&wcn->hal_mutex);
1043
1044         ieee80211_unregister_hw(hw);
1045         iounmap(wcn->mmio);
1046         ieee80211_free_hw(hw);
1047
1048         return 0;
1049 }
1050 static const struct platform_device_id wcn36xx_platform_id_table[] = {
1051         {
1052                 .name = "wcn36xx",
1053                 .driver_data = 0
1054         },
1055         {}
1056 };
1057 MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table);
1058
1059 static struct platform_driver wcn36xx_driver = {
1060         .probe      = wcn36xx_probe,
1061         .remove     = wcn36xx_remove,
1062         .driver         = {
1063                 .name   = "wcn36xx",
1064                 .owner  = THIS_MODULE,
1065         },
1066         .id_table    = wcn36xx_platform_id_table,
1067 };
1068
1069 static int __init wcn36xx_init(void)
1070 {
1071         platform_driver_register(&wcn36xx_driver);
1072         return 0;
1073 }
1074 module_init(wcn36xx_init);
1075
1076 static void __exit wcn36xx_exit(void)
1077 {
1078         platform_driver_unregister(&wcn36xx_driver);
1079 }
1080 module_exit(wcn36xx_exit);
1081
1082 MODULE_LICENSE("Dual BSD/GPL");
1083 MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com");
1084 MODULE_FIRMWARE(WLAN_NV_FILE);