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