ath6kl: Avoid taking struct as argument in ath6kl_wmi_set_ip_cmd
[deliverable/linux.git] / drivers / net / wireless / ath / ath6kl / cfg80211.c
CommitLineData
bdcd8170
KV
1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc.
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
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
6eb07caf
PG
17#include <linux/moduleparam.h>
18
bdcd8170
KV
19#include "core.h"
20#include "cfg80211.h"
21#include "debug.h"
abcb344b 22#include "hif-ops.h"
003353b0 23#include "testmode.h"
bdcd8170 24
6bbc7c35
JM
25static unsigned int ath6kl_p2p;
26
27module_param(ath6kl_p2p, uint, 0644);
28
bdcd8170
KV
29#define RATETAB_ENT(_rate, _rateid, _flags) { \
30 .bitrate = (_rate), \
31 .flags = (_flags), \
32 .hw_value = (_rateid), \
33}
34
35#define CHAN2G(_channel, _freq, _flags) { \
36 .band = IEEE80211_BAND_2GHZ, \
37 .hw_value = (_channel), \
38 .center_freq = (_freq), \
39 .flags = (_flags), \
40 .max_antenna_gain = 0, \
41 .max_power = 30, \
42}
43
44#define CHAN5G(_channel, _flags) { \
45 .band = IEEE80211_BAND_5GHZ, \
46 .hw_value = (_channel), \
47 .center_freq = 5000 + (5 * (_channel)), \
48 .flags = (_flags), \
49 .max_antenna_gain = 0, \
50 .max_power = 30, \
51}
52
53static struct ieee80211_rate ath6kl_rates[] = {
54 RATETAB_ENT(10, 0x1, 0),
55 RATETAB_ENT(20, 0x2, 0),
56 RATETAB_ENT(55, 0x4, 0),
57 RATETAB_ENT(110, 0x8, 0),
58 RATETAB_ENT(60, 0x10, 0),
59 RATETAB_ENT(90, 0x20, 0),
60 RATETAB_ENT(120, 0x40, 0),
61 RATETAB_ENT(180, 0x80, 0),
62 RATETAB_ENT(240, 0x100, 0),
63 RATETAB_ENT(360, 0x200, 0),
64 RATETAB_ENT(480, 0x400, 0),
65 RATETAB_ENT(540, 0x800, 0),
66};
67
68#define ath6kl_a_rates (ath6kl_rates + 4)
69#define ath6kl_a_rates_size 8
70#define ath6kl_g_rates (ath6kl_rates + 0)
71#define ath6kl_g_rates_size 12
72
73static struct ieee80211_channel ath6kl_2ghz_channels[] = {
74 CHAN2G(1, 2412, 0),
75 CHAN2G(2, 2417, 0),
76 CHAN2G(3, 2422, 0),
77 CHAN2G(4, 2427, 0),
78 CHAN2G(5, 2432, 0),
79 CHAN2G(6, 2437, 0),
80 CHAN2G(7, 2442, 0),
81 CHAN2G(8, 2447, 0),
82 CHAN2G(9, 2452, 0),
83 CHAN2G(10, 2457, 0),
84 CHAN2G(11, 2462, 0),
85 CHAN2G(12, 2467, 0),
86 CHAN2G(13, 2472, 0),
87 CHAN2G(14, 2484, 0),
88};
89
90static struct ieee80211_channel ath6kl_5ghz_a_channels[] = {
91 CHAN5G(34, 0), CHAN5G(36, 0),
92 CHAN5G(38, 0), CHAN5G(40, 0),
93 CHAN5G(42, 0), CHAN5G(44, 0),
94 CHAN5G(46, 0), CHAN5G(48, 0),
95 CHAN5G(52, 0), CHAN5G(56, 0),
96 CHAN5G(60, 0), CHAN5G(64, 0),
97 CHAN5G(100, 0), CHAN5G(104, 0),
98 CHAN5G(108, 0), CHAN5G(112, 0),
99 CHAN5G(116, 0), CHAN5G(120, 0),
100 CHAN5G(124, 0), CHAN5G(128, 0),
101 CHAN5G(132, 0), CHAN5G(136, 0),
102 CHAN5G(140, 0), CHAN5G(149, 0),
103 CHAN5G(153, 0), CHAN5G(157, 0),
104 CHAN5G(161, 0), CHAN5G(165, 0),
105 CHAN5G(184, 0), CHAN5G(188, 0),
106 CHAN5G(192, 0), CHAN5G(196, 0),
107 CHAN5G(200, 0), CHAN5G(204, 0),
108 CHAN5G(208, 0), CHAN5G(212, 0),
109 CHAN5G(216, 0),
110};
111
112static struct ieee80211_supported_band ath6kl_band_2ghz = {
113 .n_channels = ARRAY_SIZE(ath6kl_2ghz_channels),
114 .channels = ath6kl_2ghz_channels,
115 .n_bitrates = ath6kl_g_rates_size,
116 .bitrates = ath6kl_g_rates,
117};
118
119static struct ieee80211_supported_band ath6kl_band_5ghz = {
120 .n_channels = ARRAY_SIZE(ath6kl_5ghz_a_channels),
121 .channels = ath6kl_5ghz_a_channels,
122 .n_bitrates = ath6kl_a_rates_size,
123 .bitrates = ath6kl_a_rates,
124};
125
837cb97e
JM
126#define CCKM_KRK_CIPHER_SUITE 0x004096ff /* use for KRK */
127
10509f90
KV
128/* returns true if scheduled scan was stopped */
129static bool __ath6kl_cfg80211_sscan_stop(struct ath6kl_vif *vif)
130{
131 struct ath6kl *ar = vif->ar;
132
133 if (ar->state != ATH6KL_STATE_SCHED_SCAN)
134 return false;
135
136 del_timer_sync(&vif->sched_scan_timer);
137
138 ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
139 ATH6KL_HOST_MODE_AWAKE);
140
141 ar->state = ATH6KL_STATE_ON;
142
143 return true;
144}
145
146static void ath6kl_cfg80211_sscan_disable(struct ath6kl_vif *vif)
147{
148 struct ath6kl *ar = vif->ar;
149 bool stopped;
150
151 stopped = __ath6kl_cfg80211_sscan_stop(vif);
152
153 if (!stopped)
154 return;
155
156 cfg80211_sched_scan_stopped(ar->wiphy);
157}
158
240d2799 159static int ath6kl_set_wpa_version(struct ath6kl_vif *vif,
bdcd8170
KV
160 enum nl80211_wpa_versions wpa_version)
161{
162 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: %u\n", __func__, wpa_version);
163
164 if (!wpa_version) {
3450334f 165 vif->auth_mode = NONE_AUTH;
bdcd8170 166 } else if (wpa_version & NL80211_WPA_VERSION_2) {
3450334f 167 vif->auth_mode = WPA2_AUTH;
bdcd8170 168 } else if (wpa_version & NL80211_WPA_VERSION_1) {
3450334f 169 vif->auth_mode = WPA_AUTH;
bdcd8170
KV
170 } else {
171 ath6kl_err("%s: %u not supported\n", __func__, wpa_version);
172 return -ENOTSUPP;
173 }
174
175 return 0;
176}
177
240d2799 178static int ath6kl_set_auth_type(struct ath6kl_vif *vif,
bdcd8170
KV
179 enum nl80211_auth_type auth_type)
180{
bdcd8170
KV
181 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: 0x%x\n", __func__, auth_type);
182
183 switch (auth_type) {
184 case NL80211_AUTHTYPE_OPEN_SYSTEM:
3450334f 185 vif->dot11_auth_mode = OPEN_AUTH;
bdcd8170
KV
186 break;
187 case NL80211_AUTHTYPE_SHARED_KEY:
3450334f 188 vif->dot11_auth_mode = SHARED_AUTH;
bdcd8170
KV
189 break;
190 case NL80211_AUTHTYPE_NETWORK_EAP:
3450334f 191 vif->dot11_auth_mode = LEAP_AUTH;
bdcd8170
KV
192 break;
193
194 case NL80211_AUTHTYPE_AUTOMATIC:
3450334f 195 vif->dot11_auth_mode = OPEN_AUTH | SHARED_AUTH;
bdcd8170
KV
196 break;
197
198 default:
199 ath6kl_err("%s: 0x%x not spported\n", __func__, auth_type);
200 return -ENOTSUPP;
201 }
202
203 return 0;
204}
205
240d2799 206static int ath6kl_set_cipher(struct ath6kl_vif *vif, u32 cipher, bool ucast)
bdcd8170 207{
3450334f
VT
208 u8 *ar_cipher = ucast ? &vif->prwise_crypto : &vif->grp_crypto;
209 u8 *ar_cipher_len = ucast ? &vif->prwise_crypto_len :
210 &vif->grp_crypto_len;
bdcd8170
KV
211
212 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: cipher 0x%x, ucast %u\n",
213 __func__, cipher, ucast);
214
215 switch (cipher) {
216 case 0:
217 /* our own hack to use value 0 as no crypto used */
218 *ar_cipher = NONE_CRYPT;
219 *ar_cipher_len = 0;
220 break;
221 case WLAN_CIPHER_SUITE_WEP40:
222 *ar_cipher = WEP_CRYPT;
223 *ar_cipher_len = 5;
224 break;
225 case WLAN_CIPHER_SUITE_WEP104:
226 *ar_cipher = WEP_CRYPT;
227 *ar_cipher_len = 13;
228 break;
229 case WLAN_CIPHER_SUITE_TKIP:
230 *ar_cipher = TKIP_CRYPT;
231 *ar_cipher_len = 0;
232 break;
233 case WLAN_CIPHER_SUITE_CCMP:
234 *ar_cipher = AES_CRYPT;
235 *ar_cipher_len = 0;
236 break;
5e07021e
DS
237 case WLAN_CIPHER_SUITE_SMS4:
238 *ar_cipher = WAPI_CRYPT;
239 *ar_cipher_len = 0;
240 break;
bdcd8170
KV
241 default:
242 ath6kl_err("cipher 0x%x not supported\n", cipher);
243 return -ENOTSUPP;
244 }
245
246 return 0;
247}
248
240d2799 249static void ath6kl_set_key_mgmt(struct ath6kl_vif *vif, u32 key_mgmt)
bdcd8170
KV
250{
251 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: 0x%x\n", __func__, key_mgmt);
252
253 if (key_mgmt == WLAN_AKM_SUITE_PSK) {
3450334f
VT
254 if (vif->auth_mode == WPA_AUTH)
255 vif->auth_mode = WPA_PSK_AUTH;
256 else if (vif->auth_mode == WPA2_AUTH)
257 vif->auth_mode = WPA2_PSK_AUTH;
837cb97e 258 } else if (key_mgmt == 0x00409600) {
3450334f
VT
259 if (vif->auth_mode == WPA_AUTH)
260 vif->auth_mode = WPA_AUTH_CCKM;
261 else if (vif->auth_mode == WPA2_AUTH)
262 vif->auth_mode = WPA2_AUTH_CCKM;
bdcd8170 263 } else if (key_mgmt != WLAN_AKM_SUITE_8021X) {
3450334f 264 vif->auth_mode = NONE_AUTH;
bdcd8170
KV
265 }
266}
267
990bd915 268static bool ath6kl_cfg80211_ready(struct ath6kl_vif *vif)
bdcd8170 269{
990bd915 270 struct ath6kl *ar = vif->ar;
59c98449 271
bdcd8170
KV
272 if (!test_bit(WMI_READY, &ar->flag)) {
273 ath6kl_err("wmi is not ready\n");
274 return false;
275 }
276
59c98449 277 if (!test_bit(WLAN_ENABLED, &vif->flags)) {
bdcd8170
KV
278 ath6kl_err("wlan disabled\n");
279 return false;
280 }
281
282 return true;
283}
284
6981ffdc
KF
285static bool ath6kl_is_wpa_ie(const u8 *pos)
286{
287 return pos[0] == WLAN_EID_WPA && pos[1] >= 4 &&
288 pos[2] == 0x00 && pos[3] == 0x50 &&
289 pos[4] == 0xf2 && pos[5] == 0x01;
290}
291
292static bool ath6kl_is_rsn_ie(const u8 *pos)
293{
294 return pos[0] == WLAN_EID_RSN;
295}
296
63541212
AT
297static bool ath6kl_is_wps_ie(const u8 *pos)
298{
299 return (pos[0] == WLAN_EID_VENDOR_SPECIFIC &&
300 pos[1] >= 4 &&
301 pos[2] == 0x00 && pos[3] == 0x50 && pos[4] == 0xf2 &&
302 pos[5] == 0x04);
303}
304
334234b5
VT
305static int ath6kl_set_assoc_req_ies(struct ath6kl_vif *vif, const u8 *ies,
306 size_t ies_len)
6981ffdc 307{
334234b5 308 struct ath6kl *ar = vif->ar;
6981ffdc
KF
309 const u8 *pos;
310 u8 *buf = NULL;
311 size_t len = 0;
312 int ret;
313
63541212
AT
314 /*
315 * Clear previously set flag
316 */
317
318 ar->connect_ctrl_flags &= ~CONNECT_WPS_FLAG;
319
6981ffdc
KF
320 /*
321 * Filter out RSN/WPA IE(s)
322 */
323
324 if (ies && ies_len) {
325 buf = kmalloc(ies_len, GFP_KERNEL);
326 if (buf == NULL)
327 return -ENOMEM;
328 pos = ies;
329
330 while (pos + 1 < ies + ies_len) {
331 if (pos + 2 + pos[1] > ies + ies_len)
332 break;
333 if (!(ath6kl_is_wpa_ie(pos) || ath6kl_is_rsn_ie(pos))) {
334 memcpy(buf + len, pos, 2 + pos[1]);
335 len += 2 + pos[1];
336 }
63541212
AT
337
338 if (ath6kl_is_wps_ie(pos))
339 ar->connect_ctrl_flags |= CONNECT_WPS_FLAG;
340
6981ffdc
KF
341 pos += 2 + pos[1];
342 }
343 }
344
334234b5
VT
345 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
346 WMI_FRAME_ASSOC_REQ, buf, len);
6981ffdc
KF
347 kfree(buf);
348 return ret;
349}
350
55055976
VT
351static int ath6kl_nliftype_to_drv_iftype(enum nl80211_iftype type, u8 *nw_type)
352{
353 switch (type) {
354 case NL80211_IFTYPE_STATION:
355 *nw_type = INFRA_NETWORK;
356 break;
357 case NL80211_IFTYPE_ADHOC:
358 *nw_type = ADHOC_NETWORK;
359 break;
360 case NL80211_IFTYPE_AP:
361 *nw_type = AP_NETWORK;
362 break;
363 case NL80211_IFTYPE_P2P_CLIENT:
364 *nw_type = INFRA_NETWORK;
365 break;
366 case NL80211_IFTYPE_P2P_GO:
367 *nw_type = AP_NETWORK;
368 break;
369 default:
370 ath6kl_err("invalid interface type %u\n", type);
371 return -ENOTSUPP;
372 }
373
374 return 0;
375}
376
377static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type,
378 u8 *if_idx, u8 *nw_type)
379{
380 int i;
381
382 if (ath6kl_nliftype_to_drv_iftype(type, nw_type))
383 return false;
384
385 if (ar->ibss_if_active || ((type == NL80211_IFTYPE_ADHOC) &&
386 ar->num_vif))
387 return false;
388
389 if (type == NL80211_IFTYPE_STATION ||
390 type == NL80211_IFTYPE_AP || type == NL80211_IFTYPE_ADHOC) {
71f96ee6 391 for (i = 0; i < ar->vif_max; i++) {
55055976
VT
392 if ((ar->avail_idx_map >> i) & BIT(0)) {
393 *if_idx = i;
394 return true;
395 }
396 }
397 }
398
3226f68a
VT
399 if (type == NL80211_IFTYPE_P2P_CLIENT ||
400 type == NL80211_IFTYPE_P2P_GO) {
71f96ee6 401 for (i = ar->max_norm_iface; i < ar->vif_max; i++) {
3226f68a
VT
402 if ((ar->avail_idx_map >> i) & BIT(0)) {
403 *if_idx = i;
404 return true;
405 }
406 }
407 }
408
55055976
VT
409 return false;
410}
411
bdcd8170
KV
412static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
413 struct cfg80211_connect_params *sme)
414{
415 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 416 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170 417 int status;
3ca9d1fc 418 u8 nw_subtype = (ar->p2p) ? SUBTYPE_P2PDEV : SUBTYPE_NONE;
bdcd8170 419
10509f90
KV
420 ath6kl_cfg80211_sscan_disable(vif);
421
14ee6f6b 422 vif->sme_state = SME_CONNECTING;
bdcd8170 423
990bd915 424 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
425 return -EIO;
426
427 if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
428 ath6kl_err("destroy in progress\n");
429 return -EBUSY;
430 }
431
432 if (test_bit(SKIP_SCAN, &ar->flag) &&
433 ((sme->channel && sme->channel->center_freq == 0) ||
434 (sme->bssid && is_zero_ether_addr(sme->bssid)))) {
435 ath6kl_err("SkipScan: channel or bssid invalid\n");
436 return -EINVAL;
437 }
438
439 if (down_interruptible(&ar->sem)) {
440 ath6kl_err("busy, couldn't get access\n");
441 return -ERESTARTSYS;
442 }
443
444 if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
445 ath6kl_err("busy, destroy in progress\n");
446 up(&ar->sem);
447 return -EBUSY;
448 }
449
450 if (ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)]) {
451 /*
452 * sleep until the command queue drains
453 */
454 wait_event_interruptible_timeout(ar->event_wq,
455 ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)] == 0,
456 WMI_TIMEOUT);
457 if (signal_pending(current)) {
458 ath6kl_err("cmd queue drain timeout\n");
459 up(&ar->sem);
460 return -EINTR;
461 }
462 }
463
6e786cb1
JM
464 status = ath6kl_set_assoc_req_ies(vif, sme->ie, sme->ie_len);
465 if (status) {
466 up(&ar->sem);
467 return status;
468 }
469
470 if (sme->ie == NULL || sme->ie_len == 0)
542c519a 471 ar->connect_ctrl_flags &= ~CONNECT_WPS_FLAG;
6981ffdc 472
59c98449 473 if (test_bit(CONNECTED, &vif->flags) &&
3450334f
VT
474 vif->ssid_len == sme->ssid_len &&
475 !memcmp(vif->ssid, sme->ssid, vif->ssid_len)) {
cf5333d7 476 vif->reconnect_flag = true;
334234b5
VT
477 status = ath6kl_wmi_reconnect_cmd(ar->wmi, vif->fw_vif_idx,
478 vif->req_bssid,
f74bac54 479 vif->ch_hint);
bdcd8170
KV
480
481 up(&ar->sem);
482 if (status) {
483 ath6kl_err("wmi_reconnect_cmd failed\n");
484 return -EIO;
485 }
486 return 0;
3450334f
VT
487 } else if (vif->ssid_len == sme->ssid_len &&
488 !memcmp(vif->ssid, sme->ssid, vif->ssid_len)) {
240d2799 489 ath6kl_disconnect(vif);
bdcd8170
KV
490 }
491
3450334f
VT
492 memset(vif->ssid, 0, sizeof(vif->ssid));
493 vif->ssid_len = sme->ssid_len;
494 memcpy(vif->ssid, sme->ssid, sme->ssid_len);
bdcd8170
KV
495
496 if (sme->channel)
f74bac54 497 vif->ch_hint = sme->channel->center_freq;
bdcd8170 498
8c8b65e3 499 memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
bdcd8170 500 if (sme->bssid && !is_broadcast_ether_addr(sme->bssid))
8c8b65e3 501 memcpy(vif->req_bssid, sme->bssid, sizeof(vif->req_bssid));
bdcd8170 502
240d2799 503 ath6kl_set_wpa_version(vif, sme->crypto.wpa_versions);
bdcd8170 504
240d2799 505 status = ath6kl_set_auth_type(vif, sme->auth_type);
bdcd8170
KV
506 if (status) {
507 up(&ar->sem);
508 return status;
509 }
510
511 if (sme->crypto.n_ciphers_pairwise)
240d2799 512 ath6kl_set_cipher(vif, sme->crypto.ciphers_pairwise[0], true);
bdcd8170 513 else
240d2799 514 ath6kl_set_cipher(vif, 0, true);
bdcd8170 515
240d2799 516 ath6kl_set_cipher(vif, sme->crypto.cipher_group, false);
bdcd8170
KV
517
518 if (sme->crypto.n_akm_suites)
240d2799 519 ath6kl_set_key_mgmt(vif, sme->crypto.akm_suites[0]);
bdcd8170
KV
520
521 if ((sme->key_len) &&
3450334f
VT
522 (vif->auth_mode == NONE_AUTH) &&
523 (vif->prwise_crypto == WEP_CRYPT)) {
bdcd8170
KV
524 struct ath6kl_key *key = NULL;
525
526 if (sme->key_idx < WMI_MIN_KEY_INDEX ||
527 sme->key_idx > WMI_MAX_KEY_INDEX) {
528 ath6kl_err("key index %d out of bounds\n",
529 sme->key_idx);
530 up(&ar->sem);
531 return -ENOENT;
532 }
533
6f2a73f9 534 key = &vif->keys[sme->key_idx];
bdcd8170
KV
535 key->key_len = sme->key_len;
536 memcpy(key->key, sme->key, key->key_len);
3450334f
VT
537 key->cipher = vif->prwise_crypto;
538 vif->def_txkey_index = sme->key_idx;
bdcd8170 539
334234b5 540 ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx, sme->key_idx,
3450334f 541 vif->prwise_crypto,
bdcd8170
KV
542 GROUP_USAGE | TX_USAGE,
543 key->key_len,
f4bb9a6f 544 NULL, 0,
bdcd8170
KV
545 key->key, KEY_OP_INIT_VAL, NULL,
546 NO_SYNC_WMIFLAG);
547 }
548
549 if (!ar->usr_bss_filter) {
59c98449 550 clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
240d2799
VT
551 if (ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
552 ALL_BSS_FILTER, 0) != 0) {
bdcd8170
KV
553 ath6kl_err("couldn't set bss filtering\n");
554 up(&ar->sem);
555 return -EIO;
556 }
557 }
558
f5938f24 559 vif->nw_type = vif->next_mode;
bdcd8170 560
3ca9d1fc
AT
561 if (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)
562 nw_subtype = SUBTYPE_P2PCLIENT;
563
bdcd8170
KV
564 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
565 "%s: connect called with authmode %d dot11 auth %d"
566 " PW crypto %d PW crypto len %d GRP crypto %d"
567 " GRP crypto len %d channel hint %u\n",
568 __func__,
3450334f
VT
569 vif->auth_mode, vif->dot11_auth_mode, vif->prwise_crypto,
570 vif->prwise_crypto_len, vif->grp_crypto,
f74bac54 571 vif->grp_crypto_len, vif->ch_hint);
bdcd8170 572
cf5333d7 573 vif->reconnect_flag = 0;
334234b5 574 status = ath6kl_wmi_connect_cmd(ar->wmi, vif->fw_vif_idx, vif->nw_type,
3450334f
VT
575 vif->dot11_auth_mode, vif->auth_mode,
576 vif->prwise_crypto,
577 vif->prwise_crypto_len,
578 vif->grp_crypto, vif->grp_crypto_len,
579 vif->ssid_len, vif->ssid,
f74bac54 580 vif->req_bssid, vif->ch_hint,
3ca9d1fc 581 ar->connect_ctrl_flags, nw_subtype);
bdcd8170
KV
582
583 up(&ar->sem);
584
585 if (status == -EINVAL) {
3450334f
VT
586 memset(vif->ssid, 0, sizeof(vif->ssid));
587 vif->ssid_len = 0;
bdcd8170
KV
588 ath6kl_err("invalid request\n");
589 return -ENOENT;
590 } else if (status) {
591 ath6kl_err("ath6kl_wmi_connect_cmd failed\n");
592 return -EIO;
593 }
594
595 if ((!(ar->connect_ctrl_flags & CONNECT_DO_WPA_OFFLOAD)) &&
3450334f
VT
596 ((vif->auth_mode == WPA_PSK_AUTH)
597 || (vif->auth_mode == WPA2_PSK_AUTH))) {
de3ad713 598 mod_timer(&vif->disconnect_timer,
bdcd8170
KV
599 jiffies + msecs_to_jiffies(DISCON_TIMER_INTVAL));
600 }
601
602 ar->connect_ctrl_flags &= ~CONNECT_DO_WPA_OFFLOAD;
59c98449 603 set_bit(CONNECT_PEND, &vif->flags);
bdcd8170
KV
604
605 return 0;
606}
607
5e13fd35
VT
608static struct cfg80211_bss *
609ath6kl_add_bss_if_needed(struct ath6kl_vif *vif,
610 enum network_type nw_type,
611 const u8 *bssid,
612 struct ieee80211_channel *chan,
613 const u8 *beacon_ie,
614 size_t beacon_ie_len)
01cac476 615{
240d2799 616 struct ath6kl *ar = vif->ar;
01cac476 617 struct cfg80211_bss *bss;
4eab6f4f 618 u16 cap_mask, cap_val;
01cac476
JM
619 u8 *ie;
620
4eab6f4f
RM
621 if (nw_type & ADHOC_NETWORK) {
622 cap_mask = WLAN_CAPABILITY_IBSS;
623 cap_val = WLAN_CAPABILITY_IBSS;
624 } else {
625 cap_mask = WLAN_CAPABILITY_ESS;
626 cap_val = WLAN_CAPABILITY_ESS;
627 }
628
be98e3a4 629 bss = cfg80211_get_bss(ar->wiphy, chan, bssid,
4eab6f4f
RM
630 vif->ssid, vif->ssid_len,
631 cap_mask, cap_val);
01cac476
JM
632 if (bss == NULL) {
633 /*
634 * Since cfg80211 may not yet know about the BSS,
635 * generate a partial entry until the first BSS info
636 * event becomes available.
637 *
638 * Prepend SSID element since it is not included in the Beacon
639 * IEs from the target.
640 */
3450334f 641 ie = kmalloc(2 + vif->ssid_len + beacon_ie_len, GFP_KERNEL);
01cac476 642 if (ie == NULL)
5e13fd35 643 return NULL;
01cac476 644 ie[0] = WLAN_EID_SSID;
3450334f
VT
645 ie[1] = vif->ssid_len;
646 memcpy(ie + 2, vif->ssid, vif->ssid_len);
647 memcpy(ie + 2 + vif->ssid_len, beacon_ie, beacon_ie_len);
be98e3a4 648 bss = cfg80211_inform_bss(ar->wiphy, chan,
4eab6f4f 649 bssid, 0, cap_val, 100,
3450334f 650 ie, 2 + vif->ssid_len + beacon_ie_len,
01cac476
JM
651 0, GFP_KERNEL);
652 if (bss)
4eab6f4f
RM
653 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added bss %pM to "
654 "cfg80211\n", bssid);
01cac476
JM
655 kfree(ie);
656 } else
5e13fd35 657 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss\n");
01cac476 658
5e13fd35 659 return bss;
01cac476
JM
660}
661
240d2799 662void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
bdcd8170
KV
663 u8 *bssid, u16 listen_intvl,
664 u16 beacon_intvl,
665 enum network_type nw_type,
666 u8 beacon_ie_len, u8 assoc_req_len,
667 u8 assoc_resp_len, u8 *assoc_info)
668{
01cac476 669 struct ieee80211_channel *chan;
240d2799 670 struct ath6kl *ar = vif->ar;
5e13fd35 671 struct cfg80211_bss *bss;
bdcd8170
KV
672
673 /* capinfo + listen interval */
674 u8 assoc_req_ie_offset = sizeof(u16) + sizeof(u16);
675
676 /* capinfo + status code + associd */
677 u8 assoc_resp_ie_offset = sizeof(u16) + sizeof(u16) + sizeof(u16);
678
679 u8 *assoc_req_ie = assoc_info + beacon_ie_len + assoc_req_ie_offset;
680 u8 *assoc_resp_ie = assoc_info + beacon_ie_len + assoc_req_len +
681 assoc_resp_ie_offset;
682
683 assoc_req_len -= assoc_req_ie_offset;
684 assoc_resp_len -= assoc_resp_ie_offset;
685
32c10874
JM
686 /*
687 * Store Beacon interval here; DTIM period will be available only once
688 * a Beacon frame from the AP is seen.
689 */
cf5333d7 690 vif->assoc_bss_beacon_int = beacon_intvl;
59c98449 691 clear_bit(DTIM_PERIOD_AVAIL, &vif->flags);
32c10874 692
bdcd8170 693 if (nw_type & ADHOC_NETWORK) {
551959d8 694 if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) {
bdcd8170
KV
695 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
696 "%s: ath6k not in ibss mode\n", __func__);
697 return;
698 }
699 }
700
701 if (nw_type & INFRA_NETWORK) {
551959d8
VT
702 if (vif->wdev.iftype != NL80211_IFTYPE_STATION &&
703 vif->wdev.iftype != NL80211_IFTYPE_P2P_CLIENT) {
bdcd8170
KV
704 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
705 "%s: ath6k not in station mode\n", __func__);
706 return;
707 }
708 }
709
be98e3a4 710 chan = ieee80211_get_channel(ar->wiphy, (int) channel);
bdcd8170 711
5e13fd35
VT
712 bss = ath6kl_add_bss_if_needed(vif, nw_type, bssid, chan,
713 assoc_info, beacon_ie_len);
714 if (!bss) {
4eab6f4f 715 ath6kl_err("could not add cfg80211 bss entry\n");
bdcd8170
KV
716 return;
717 }
718
4eab6f4f
RM
719 if (nw_type & ADHOC_NETWORK) {
720 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n",
721 nw_type & ADHOC_CREATOR ? "creator" : "joiner");
722 cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
5e13fd35 723 cfg80211_put_bss(bss);
bdcd8170
KV
724 return;
725 }
726
14ee6f6b 727 if (vif->sme_state == SME_CONNECTING) {
bdcd8170 728 /* inform connect result to cfg80211 */
14ee6f6b 729 vif->sme_state = SME_CONNECTED;
240d2799 730 cfg80211_connect_result(vif->ndev, bssid,
bdcd8170
KV
731 assoc_req_ie, assoc_req_len,
732 assoc_resp_ie, assoc_resp_len,
733 WLAN_STATUS_SUCCESS, GFP_KERNEL);
5e13fd35 734 cfg80211_put_bss(bss);
14ee6f6b 735 } else if (vif->sme_state == SME_CONNECTED) {
bdcd8170 736 /* inform roam event to cfg80211 */
5e13fd35
VT
737 cfg80211_roamed_bss(vif->ndev, bss, assoc_req_ie, assoc_req_len,
738 assoc_resp_ie, assoc_resp_len, GFP_KERNEL);
bdcd8170
KV
739 }
740}
741
742static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy,
743 struct net_device *dev, u16 reason_code)
744{
d6d5c06c 745 struct ath6kl *ar = ath6kl_priv(dev);
3450334f 746 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170
KV
747
748 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: reason=%u\n", __func__,
749 reason_code);
750
10509f90
KV
751 ath6kl_cfg80211_sscan_disable(vif);
752
990bd915 753 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
754 return -EIO;
755
756 if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
757 ath6kl_err("busy, destroy in progress\n");
758 return -EBUSY;
759 }
760
761 if (down_interruptible(&ar->sem)) {
762 ath6kl_err("busy, couldn't get access\n");
763 return -ERESTARTSYS;
764 }
765
cf5333d7 766 vif->reconnect_flag = 0;
240d2799 767 ath6kl_disconnect(vif);
3450334f
VT
768 memset(vif->ssid, 0, sizeof(vif->ssid));
769 vif->ssid_len = 0;
bdcd8170
KV
770
771 if (!test_bit(SKIP_SCAN, &ar->flag))
8c8b65e3 772 memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
bdcd8170
KV
773
774 up(&ar->sem);
775
14ee6f6b 776 vif->sme_state = SME_DISCONNECTED;
170826dd 777
bdcd8170
KV
778 return 0;
779}
780
240d2799 781void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
bdcd8170
KV
782 u8 *bssid, u8 assoc_resp_len,
783 u8 *assoc_info, u16 proto_reason)
784{
240d2799 785 struct ath6kl *ar = vif->ar;
59c98449 786
14ee6f6b
VT
787 if (vif->scan_req) {
788 cfg80211_scan_done(vif->scan_req, true);
789 vif->scan_req = NULL;
bdcd8170
KV
790 }
791
f5938f24 792 if (vif->nw_type & ADHOC_NETWORK) {
551959d8 793 if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) {
bdcd8170
KV
794 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
795 "%s: ath6k not in ibss mode\n", __func__);
796 return;
797 }
798 memset(bssid, 0, ETH_ALEN);
240d2799 799 cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
bdcd8170
KV
800 return;
801 }
802
f5938f24 803 if (vif->nw_type & INFRA_NETWORK) {
551959d8
VT
804 if (vif->wdev.iftype != NL80211_IFTYPE_STATION &&
805 vif->wdev.iftype != NL80211_IFTYPE_P2P_CLIENT) {
bdcd8170
KV
806 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
807 "%s: ath6k not in station mode\n", __func__);
808 return;
809 }
810 }
811
1de547d6
VT
812 /*
813 * Send a disconnect command to target when a disconnect event is
814 * received with reason code other than 3 (DISCONNECT_CMD - disconnect
815 * request from host) to make the firmware stop trying to connect even
816 * after giving disconnect event. There will be one more disconnect
817 * event for this disconnect command with reason code DISCONNECT_CMD
818 * which will be notified to cfg80211.
819 */
bdcd8170 820
1de547d6 821 if (reason != DISCONNECT_CMD) {
334234b5 822 ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
bdcd8170
KV
823 return;
824 }
825
59c98449 826 clear_bit(CONNECT_PEND, &vif->flags);
bdcd8170 827
14ee6f6b 828 if (vif->sme_state == SME_CONNECTING) {
240d2799 829 cfg80211_connect_result(vif->ndev,
ac59a2b2
VT
830 bssid, NULL, 0,
831 NULL, 0,
832 WLAN_STATUS_UNSPECIFIED_FAILURE,
833 GFP_KERNEL);
14ee6f6b 834 } else if (vif->sme_state == SME_CONNECTED) {
240d2799 835 cfg80211_disconnected(vif->ndev, reason,
ac59a2b2 836 NULL, 0, GFP_KERNEL);
bdcd8170
KV
837 }
838
14ee6f6b 839 vif->sme_state = SME_DISCONNECTED;
bdcd8170
KV
840}
841
bdcd8170
KV
842static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
843 struct cfg80211_scan_request *request)
844{
d6d5c06c 845 struct ath6kl *ar = ath6kl_priv(ndev);
59c98449 846 struct ath6kl_vif *vif = netdev_priv(ndev);
1276c9ef
EL
847 s8 n_channels = 0;
848 u16 *channels = NULL;
bdcd8170 849 int ret = 0;
f1f92179 850 u32 force_fg_scan = 0;
bdcd8170 851
990bd915 852 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
853 return -EIO;
854
10509f90
KV
855 ath6kl_cfg80211_sscan_disable(vif);
856
bdcd8170 857 if (!ar->usr_bss_filter) {
59c98449 858 clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
1b1e6ee3 859 ret = ath6kl_wmi_bssfilter_cmd(
240d2799 860 ar->wmi, vif->fw_vif_idx,
59c98449 861 (test_bit(CONNECTED, &vif->flags) ?
1b1e6ee3
JM
862 ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), 0);
863 if (ret) {
bdcd8170 864 ath6kl_err("couldn't set bss filtering\n");
1b1e6ee3 865 return ret;
bdcd8170
KV
866 }
867 }
868
869 if (request->n_ssids && request->ssids[0].ssid_len) {
870 u8 i;
871
872 if (request->n_ssids > (MAX_PROBED_SSID_INDEX - 1))
873 request->n_ssids = MAX_PROBED_SSID_INDEX - 1;
874
875 for (i = 0; i < request->n_ssids; i++)
334234b5
VT
876 ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
877 i + 1, SPECIFIC_SSID_FLAG,
bdcd8170
KV
878 request->ssids[i].ssid_len,
879 request->ssids[i].ssid);
880 }
881
10509f90
KV
882 /*
883 * FIXME: we should clear the IE in fw if it's not set so just
884 * remove the check altogether
885 */
b84da8c7 886 if (request->ie) {
334234b5
VT
887 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
888 WMI_FRAME_PROBE_REQ,
b84da8c7
JM
889 request->ie, request->ie_len);
890 if (ret) {
891 ath6kl_err("failed to set Probe Request appie for "
892 "scan");
893 return ret;
894 }
895 }
896
11869bef
JM
897 /*
898 * Scan only the requested channels if the request specifies a set of
899 * channels. If the list is longer than the target supports, do not
900 * configure the list and instead, scan all available channels.
901 */
902 if (request->n_channels > 0 &&
903 request->n_channels <= WMI_MAX_CHANNELS) {
1276c9ef
EL
904 u8 i;
905
11869bef 906 n_channels = request->n_channels;
1276c9ef
EL
907
908 channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL);
909 if (channels == NULL) {
910 ath6kl_warn("failed to set scan channels, "
911 "scan all channels");
912 n_channels = 0;
913 }
914
915 for (i = 0; i < n_channels; i++)
916 channels[i] = request->channels[i]->center_freq;
917 }
918
59c98449 919 if (test_bit(CONNECTED, &vif->flags))
f1f92179
VT
920 force_fg_scan = 1;
921
3ca9d1fc
AT
922 if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
923 ar->fw_capabilities)) {
924 /*
925 * If capable of doing P2P mgmt operations using
926 * station interface, send additional information like
927 * supported rates to advertise and xmit rates for
928 * probe requests
929 */
930 ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx,
931 WMI_LONG_SCAN, force_fg_scan,
932 false, 0, 0, n_channels,
933 channels, request->no_cck,
934 request->rates);
935 } else {
936 ret = ath6kl_wmi_startscan_cmd(ar->wmi, vif->fw_vif_idx,
937 WMI_LONG_SCAN, force_fg_scan,
938 false, 0, 0, n_channels,
939 channels);
940 }
1b1e6ee3 941 if (ret)
bdcd8170 942 ath6kl_err("wmi_startscan_cmd failed\n");
11869bef 943 else
14ee6f6b 944 vif->scan_req = request;
bdcd8170 945
1276c9ef
EL
946 kfree(channels);
947
bdcd8170
KV
948 return ret;
949}
950
1c17d313 951void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted)
bdcd8170 952{
240d2799 953 struct ath6kl *ar = vif->ar;
6fd1eace 954 int i;
bdcd8170 955
1c17d313
KV
956 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status%s\n", __func__,
957 aborted ? " aborted" : "");
bdcd8170 958
14ee6f6b 959 if (!vif->scan_req)
6fd1eace
KV
960 return;
961
1c17d313 962 if (aborted)
6fd1eace 963 goto out;
6fd1eace 964
14ee6f6b
VT
965 if (vif->scan_req->n_ssids && vif->scan_req->ssids[0].ssid_len) {
966 for (i = 0; i < vif->scan_req->n_ssids; i++) {
334234b5
VT
967 ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
968 i + 1, DISABLE_SSID_FLAG,
6fd1eace 969 0, NULL);
bdcd8170 970 }
bdcd8170 971 }
6fd1eace
KV
972
973out:
cb93821a 974 cfg80211_scan_done(vif->scan_req, aborted);
14ee6f6b 975 vif->scan_req = NULL;
bdcd8170
KV
976}
977
978static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
979 u8 key_index, bool pairwise,
980 const u8 *mac_addr,
981 struct key_params *params)
982{
d6d5c06c 983 struct ath6kl *ar = ath6kl_priv(ndev);
59c98449 984 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170
KV
985 struct ath6kl_key *key = NULL;
986 u8 key_usage;
987 u8 key_type;
bdcd8170 988
990bd915 989 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
990 return -EIO;
991
837cb97e
JM
992 if (params->cipher == CCKM_KRK_CIPHER_SUITE) {
993 if (params->key_len != WMI_KRK_LEN)
994 return -EINVAL;
240d2799
VT
995 return ath6kl_wmi_add_krk_cmd(ar->wmi, vif->fw_vif_idx,
996 params->key);
837cb97e
JM
997 }
998
bdcd8170
KV
999 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
1000 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1001 "%s: key index %d out of bounds\n", __func__,
1002 key_index);
1003 return -ENOENT;
1004 }
1005
6f2a73f9 1006 key = &vif->keys[key_index];
bdcd8170
KV
1007 memset(key, 0, sizeof(struct ath6kl_key));
1008
1009 if (pairwise)
1010 key_usage = PAIRWISE_USAGE;
1011 else
1012 key_usage = GROUP_USAGE;
1013
1014 if (params) {
5e07021e
DS
1015 int seq_len = params->seq_len;
1016 if (params->cipher == WLAN_CIPHER_SUITE_SMS4 &&
1017 seq_len > ATH6KL_KEY_SEQ_LEN) {
1018 /* Only first half of the WPI PN is configured */
1019 seq_len = ATH6KL_KEY_SEQ_LEN;
1020 }
bdcd8170 1021 if (params->key_len > WLAN_MAX_KEY_LEN ||
5e07021e 1022 seq_len > sizeof(key->seq))
bdcd8170
KV
1023 return -EINVAL;
1024
1025 key->key_len = params->key_len;
1026 memcpy(key->key, params->key, key->key_len);
5e07021e 1027 key->seq_len = seq_len;
bdcd8170
KV
1028 memcpy(key->seq, params->seq, key->seq_len);
1029 key->cipher = params->cipher;
1030 }
1031
1032 switch (key->cipher) {
1033 case WLAN_CIPHER_SUITE_WEP40:
1034 case WLAN_CIPHER_SUITE_WEP104:
1035 key_type = WEP_CRYPT;
1036 break;
1037
1038 case WLAN_CIPHER_SUITE_TKIP:
1039 key_type = TKIP_CRYPT;
1040 break;
1041
1042 case WLAN_CIPHER_SUITE_CCMP:
1043 key_type = AES_CRYPT;
1044 break;
5e07021e
DS
1045 case WLAN_CIPHER_SUITE_SMS4:
1046 key_type = WAPI_CRYPT;
1047 break;
bdcd8170
KV
1048
1049 default:
1050 return -ENOTSUPP;
1051 }
1052
3450334f
VT
1053 if (((vif->auth_mode == WPA_PSK_AUTH)
1054 || (vif->auth_mode == WPA2_PSK_AUTH))
bdcd8170 1055 && (key_usage & GROUP_USAGE))
de3ad713 1056 del_timer(&vif->disconnect_timer);
bdcd8170
KV
1057
1058 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1059 "%s: index %d, key_len %d, key_type 0x%x, key_usage 0x%x, seq_len %d\n",
1060 __func__, key_index, key->key_len, key_type,
1061 key_usage, key->seq_len);
1062
f5938f24 1063 if (vif->nw_type == AP_NETWORK && !pairwise &&
4703290a
JM
1064 (key_type == TKIP_CRYPT || key_type == AES_CRYPT ||
1065 key_type == WAPI_CRYPT) && params) {
9a5b1318
JM
1066 ar->ap_mode_bkey.valid = true;
1067 ar->ap_mode_bkey.key_index = key_index;
1068 ar->ap_mode_bkey.key_type = key_type;
1069 ar->ap_mode_bkey.key_len = key->key_len;
1070 memcpy(ar->ap_mode_bkey.key, key->key, key->key_len);
59c98449 1071 if (!test_bit(CONNECTED, &vif->flags)) {
9a5b1318
JM
1072 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group "
1073 "key configuration until AP mode has been "
1074 "started\n");
1075 /*
1076 * The key will be set in ath6kl_connect_ap_mode() once
1077 * the connected event is received from the target.
1078 */
1079 return 0;
1080 }
1081 }
1082
f5938f24 1083 if (vif->next_mode == AP_NETWORK && key_type == WEP_CRYPT &&
59c98449 1084 !test_bit(CONNECTED, &vif->flags)) {
151411e8
JM
1085 /*
1086 * Store the key locally so that it can be re-configured after
1087 * the AP mode has properly started
1088 * (ath6kl_install_statioc_wep_keys).
1089 */
1090 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay WEP key configuration "
1091 "until AP mode has been started\n");
6f2a73f9
VT
1092 vif->wep_key_list[key_index].key_len = key->key_len;
1093 memcpy(vif->wep_key_list[key_index].key, key->key,
1094 key->key_len);
151411e8
JM
1095 return 0;
1096 }
1097
7cefa44f 1098 return ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx, key_index,
f3e61ece
JM
1099 key_type, key_usage, key->key_len,
1100 key->seq, key->seq_len, key->key,
1101 KEY_OP_INIT_VAL,
1102 (u8 *) mac_addr, SYNC_BOTH_WMIFLAG);
bdcd8170
KV
1103}
1104
1105static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
1106 u8 key_index, bool pairwise,
1107 const u8 *mac_addr)
1108{
d6d5c06c 1109 struct ath6kl *ar = ath6kl_priv(ndev);
6f2a73f9 1110 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170
KV
1111
1112 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1113
990bd915 1114 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1115 return -EIO;
1116
1117 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
1118 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1119 "%s: key index %d out of bounds\n", __func__,
1120 key_index);
1121 return -ENOENT;
1122 }
1123
6f2a73f9 1124 if (!vif->keys[key_index].key_len) {
bdcd8170
KV
1125 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1126 "%s: index %d is empty\n", __func__, key_index);
1127 return 0;
1128 }
1129
6f2a73f9 1130 vif->keys[key_index].key_len = 0;
bdcd8170 1131
334234b5 1132 return ath6kl_wmi_deletekey_cmd(ar->wmi, vif->fw_vif_idx, key_index);
bdcd8170
KV
1133}
1134
1135static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
1136 u8 key_index, bool pairwise,
1137 const u8 *mac_addr, void *cookie,
1138 void (*callback) (void *cookie,
1139 struct key_params *))
1140{
6f2a73f9 1141 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170
KV
1142 struct ath6kl_key *key = NULL;
1143 struct key_params params;
1144
1145 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1146
990bd915 1147 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1148 return -EIO;
1149
1150 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
1151 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1152 "%s: key index %d out of bounds\n", __func__,
1153 key_index);
1154 return -ENOENT;
1155 }
1156
6f2a73f9 1157 key = &vif->keys[key_index];
bdcd8170
KV
1158 memset(&params, 0, sizeof(params));
1159 params.cipher = key->cipher;
1160 params.key_len = key->key_len;
1161 params.seq_len = key->seq_len;
1162 params.seq = key->seq;
1163 params.key = key->key;
1164
1165 callback(cookie, &params);
1166
1167 return key->key_len ? 0 : -ENOENT;
1168}
1169
1170static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
1171 struct net_device *ndev,
1172 u8 key_index, bool unicast,
1173 bool multicast)
1174{
d6d5c06c 1175 struct ath6kl *ar = ath6kl_priv(ndev);
59c98449 1176 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170 1177 struct ath6kl_key *key = NULL;
bdcd8170 1178 u8 key_usage;
229ed6b5 1179 enum crypto_type key_type = NONE_CRYPT;
bdcd8170
KV
1180
1181 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1182
990bd915 1183 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1184 return -EIO;
1185
1186 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
1187 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1188 "%s: key index %d out of bounds\n",
1189 __func__, key_index);
1190 return -ENOENT;
1191 }
1192
6f2a73f9 1193 if (!vif->keys[key_index].key_len) {
bdcd8170
KV
1194 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: invalid key index %d\n",
1195 __func__, key_index);
1196 return -EINVAL;
1197 }
1198
3450334f 1199 vif->def_txkey_index = key_index;
6f2a73f9 1200 key = &vif->keys[vif->def_txkey_index];
bdcd8170 1201 key_usage = GROUP_USAGE;
3450334f 1202 if (vif->prwise_crypto == WEP_CRYPT)
bdcd8170 1203 key_usage |= TX_USAGE;
229ed6b5 1204 if (unicast)
3450334f 1205 key_type = vif->prwise_crypto;
229ed6b5 1206 if (multicast)
3450334f 1207 key_type = vif->grp_crypto;
bdcd8170 1208
f5938f24 1209 if (vif->next_mode == AP_NETWORK && !test_bit(CONNECTED, &vif->flags))
9a5b1318
JM
1210 return 0; /* Delay until AP mode has been started */
1211
f3e61ece
JM
1212 return ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx,
1213 vif->def_txkey_index,
1214 key_type, key_usage,
1215 key->key_len, key->seq, key->seq_len,
1216 key->key,
1217 KEY_OP_INIT_VAL, NULL,
1218 SYNC_BOTH_WMIFLAG);
bdcd8170
KV
1219}
1220
240d2799 1221void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl_vif *vif, u8 keyid,
bdcd8170
KV
1222 bool ismcast)
1223{
1224 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1225 "%s: keyid %d, ismcast %d\n", __func__, keyid, ismcast);
1226
240d2799 1227 cfg80211_michael_mic_failure(vif->ndev, vif->bssid,
bdcd8170
KV
1228 (ismcast ? NL80211_KEYTYPE_GROUP :
1229 NL80211_KEYTYPE_PAIRWISE), keyid, NULL,
1230 GFP_KERNEL);
1231}
1232
1233static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1234{
1235 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
990bd915 1236 struct ath6kl_vif *vif;
bdcd8170
KV
1237 int ret;
1238
1239 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: changed 0x%x\n", __func__,
1240 changed);
1241
990bd915
VT
1242 vif = ath6kl_vif_first(ar);
1243 if (!vif)
1244 return -EIO;
1245
1246 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1247 return -EIO;
1248
1249 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
1250 ret = ath6kl_wmi_set_rts_cmd(ar->wmi, wiphy->rts_threshold);
1251 if (ret != 0) {
1252 ath6kl_err("ath6kl_wmi_set_rts_cmd failed\n");
1253 return -EIO;
1254 }
1255 }
1256
1257 return 0;
1258}
1259
1260/*
1261 * The type nl80211_tx_power_setting replaces the following
1262 * data type from 2.6.36 onwards
1263*/
1264static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
1265 enum nl80211_tx_power_setting type,
b992a285 1266 int mbm)
bdcd8170
KV
1267{
1268 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
990bd915 1269 struct ath6kl_vif *vif;
bdcd8170 1270 u8 ath6kl_dbm;
b992a285 1271 int dbm = MBM_TO_DBM(mbm);
bdcd8170
KV
1272
1273 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__,
1274 type, dbm);
1275
990bd915
VT
1276 vif = ath6kl_vif_first(ar);
1277 if (!vif)
1278 return -EIO;
1279
1280 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1281 return -EIO;
1282
1283 switch (type) {
1284 case NL80211_TX_POWER_AUTOMATIC:
1285 return 0;
1286 case NL80211_TX_POWER_LIMITED:
1287 ar->tx_pwr = ath6kl_dbm = dbm;
1288 break;
1289 default:
1290 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x not supported\n",
1291 __func__, type);
1292 return -EOPNOTSUPP;
1293 }
1294
990bd915 1295 ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx, ath6kl_dbm);
bdcd8170
KV
1296
1297 return 0;
1298}
1299
1300static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
1301{
1302 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
990bd915
VT
1303 struct ath6kl_vif *vif;
1304
1305 vif = ath6kl_vif_first(ar);
1306 if (!vif)
1307 return -EIO;
bdcd8170 1308
990bd915 1309 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1310 return -EIO;
1311
59c98449 1312 if (test_bit(CONNECTED, &vif->flags)) {
bdcd8170
KV
1313 ar->tx_pwr = 0;
1314
990bd915 1315 if (ath6kl_wmi_get_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx) != 0) {
bdcd8170
KV
1316 ath6kl_err("ath6kl_wmi_get_tx_pwr_cmd failed\n");
1317 return -EIO;
1318 }
1319
1320 wait_event_interruptible_timeout(ar->event_wq, ar->tx_pwr != 0,
1321 5 * HZ);
1322
1323 if (signal_pending(current)) {
1324 ath6kl_err("target did not respond\n");
1325 return -EINTR;
1326 }
1327 }
1328
1329 *dbm = ar->tx_pwr;
1330 return 0;
1331}
1332
1333static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
1334 struct net_device *dev,
1335 bool pmgmt, int timeout)
1336{
1337 struct ath6kl *ar = ath6kl_priv(dev);
1338 struct wmi_power_mode_cmd mode;
334234b5 1339 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170
KV
1340
1341 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: pmgmt %d, timeout %d\n",
1342 __func__, pmgmt, timeout);
1343
990bd915 1344 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1345 return -EIO;
1346
1347 if (pmgmt) {
1348 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: max perf\n", __func__);
1349 mode.pwr_mode = REC_POWER;
1350 } else {
1351 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: rec power\n", __func__);
1352 mode.pwr_mode = MAX_PERF_POWER;
1353 }
1354
334234b5
VT
1355 if (ath6kl_wmi_powermode_cmd(ar->wmi, vif->fw_vif_idx,
1356 mode.pwr_mode) != 0) {
bdcd8170
KV
1357 ath6kl_err("wmi_powermode_cmd failed\n");
1358 return -EIO;
1359 }
1360
1361 return 0;
1362}
1363
55055976
VT
1364static struct net_device *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
1365 char *name,
1366 enum nl80211_iftype type,
1367 u32 *flags,
1368 struct vif_params *params)
1369{
1370 struct ath6kl *ar = wiphy_priv(wiphy);
1371 struct net_device *ndev;
1372 u8 if_idx, nw_type;
1373
71f96ee6 1374 if (ar->num_vif == ar->vif_max) {
55055976
VT
1375 ath6kl_err("Reached maximum number of supported vif\n");
1376 return ERR_PTR(-EINVAL);
1377 }
1378
1379 if (!ath6kl_is_valid_iftype(ar, type, &if_idx, &nw_type)) {
1380 ath6kl_err("Not a supported interface type\n");
1381 return ERR_PTR(-EINVAL);
1382 }
1383
1384 ndev = ath6kl_interface_add(ar, name, type, if_idx, nw_type);
1385 if (!ndev)
1386 return ERR_PTR(-ENOMEM);
1387
1388 ar->num_vif++;
1389
1390 return ndev;
1391}
1392
1393static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy,
1394 struct net_device *ndev)
1395{
1396 struct ath6kl *ar = wiphy_priv(wiphy);
1397 struct ath6kl_vif *vif = netdev_priv(ndev);
1398
11f6e40d 1399 spin_lock_bh(&ar->list_lock);
55055976 1400 list_del(&vif->list);
11f6e40d 1401 spin_unlock_bh(&ar->list_lock);
55055976
VT
1402
1403 ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag));
1404
1405 ath6kl_deinit_if_data(vif);
1406
1407 return 0;
1408}
1409
bdcd8170
KV
1410static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
1411 struct net_device *ndev,
1412 enum nl80211_iftype type, u32 *flags,
1413 struct vif_params *params)
1414{
f5938f24 1415 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170
KV
1416
1417 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type);
1418
bdcd8170
KV
1419 switch (type) {
1420 case NL80211_IFTYPE_STATION:
f5938f24 1421 vif->next_mode = INFRA_NETWORK;
bdcd8170
KV
1422 break;
1423 case NL80211_IFTYPE_ADHOC:
f5938f24 1424 vif->next_mode = ADHOC_NETWORK;
bdcd8170 1425 break;
6e4604c8 1426 case NL80211_IFTYPE_AP:
f5938f24 1427 vif->next_mode = AP_NETWORK;
6e4604c8 1428 break;
6b5e5d25 1429 case NL80211_IFTYPE_P2P_CLIENT:
f5938f24 1430 vif->next_mode = INFRA_NETWORK;
6b5e5d25
JM
1431 break;
1432 case NL80211_IFTYPE_P2P_GO:
f5938f24 1433 vif->next_mode = AP_NETWORK;
6b5e5d25 1434 break;
bdcd8170
KV
1435 default:
1436 ath6kl_err("invalid interface type %u\n", type);
1437 return -EOPNOTSUPP;
1438 }
1439
551959d8 1440 vif->wdev.iftype = type;
bdcd8170
KV
1441
1442 return 0;
1443}
1444
1445static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
1446 struct net_device *dev,
1447 struct cfg80211_ibss_params *ibss_param)
1448{
1449 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 1450 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170
KV
1451 int status;
1452
990bd915 1453 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1454 return -EIO;
1455
3450334f
VT
1456 vif->ssid_len = ibss_param->ssid_len;
1457 memcpy(vif->ssid, ibss_param->ssid, vif->ssid_len);
bdcd8170
KV
1458
1459 if (ibss_param->channel)
f74bac54 1460 vif->ch_hint = ibss_param->channel->center_freq;
bdcd8170
KV
1461
1462 if (ibss_param->channel_fixed) {
1463 /*
1464 * TODO: channel_fixed: The channel should be fixed, do not
1465 * search for IBSSs to join on other channels. Target
1466 * firmware does not support this feature, needs to be
1467 * updated.
1468 */
1469 return -EOPNOTSUPP;
1470 }
1471
8c8b65e3 1472 memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
bdcd8170 1473 if (ibss_param->bssid && !is_broadcast_ether_addr(ibss_param->bssid))
8c8b65e3
VT
1474 memcpy(vif->req_bssid, ibss_param->bssid,
1475 sizeof(vif->req_bssid));
bdcd8170 1476
240d2799 1477 ath6kl_set_wpa_version(vif, 0);
bdcd8170 1478
240d2799 1479 status = ath6kl_set_auth_type(vif, NL80211_AUTHTYPE_OPEN_SYSTEM);
bdcd8170
KV
1480 if (status)
1481 return status;
1482
1483 if (ibss_param->privacy) {
240d2799
VT
1484 ath6kl_set_cipher(vif, WLAN_CIPHER_SUITE_WEP40, true);
1485 ath6kl_set_cipher(vif, WLAN_CIPHER_SUITE_WEP40, false);
bdcd8170 1486 } else {
240d2799
VT
1487 ath6kl_set_cipher(vif, 0, true);
1488 ath6kl_set_cipher(vif, 0, false);
bdcd8170
KV
1489 }
1490
f5938f24 1491 vif->nw_type = vif->next_mode;
bdcd8170
KV
1492
1493 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1494 "%s: connect called with authmode %d dot11 auth %d"
1495 " PW crypto %d PW crypto len %d GRP crypto %d"
1496 " GRP crypto len %d channel hint %u\n",
1497 __func__,
3450334f
VT
1498 vif->auth_mode, vif->dot11_auth_mode, vif->prwise_crypto,
1499 vif->prwise_crypto_len, vif->grp_crypto,
f74bac54 1500 vif->grp_crypto_len, vif->ch_hint);
bdcd8170 1501
334234b5 1502 status = ath6kl_wmi_connect_cmd(ar->wmi, vif->fw_vif_idx, vif->nw_type,
3450334f
VT
1503 vif->dot11_auth_mode, vif->auth_mode,
1504 vif->prwise_crypto,
1505 vif->prwise_crypto_len,
1506 vif->grp_crypto, vif->grp_crypto_len,
1507 vif->ssid_len, vif->ssid,
f74bac54 1508 vif->req_bssid, vif->ch_hint,
3ca9d1fc 1509 ar->connect_ctrl_flags, SUBTYPE_NONE);
59c98449 1510 set_bit(CONNECT_PEND, &vif->flags);
bdcd8170
KV
1511
1512 return 0;
1513}
1514
1515static int ath6kl_cfg80211_leave_ibss(struct wiphy *wiphy,
1516 struct net_device *dev)
1517{
3450334f 1518 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170 1519
990bd915 1520 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1521 return -EIO;
1522
240d2799 1523 ath6kl_disconnect(vif);
3450334f
VT
1524 memset(vif->ssid, 0, sizeof(vif->ssid));
1525 vif->ssid_len = 0;
bdcd8170
KV
1526
1527 return 0;
1528}
1529
1530static const u32 cipher_suites[] = {
1531 WLAN_CIPHER_SUITE_WEP40,
1532 WLAN_CIPHER_SUITE_WEP104,
1533 WLAN_CIPHER_SUITE_TKIP,
1534 WLAN_CIPHER_SUITE_CCMP,
837cb97e 1535 CCKM_KRK_CIPHER_SUITE,
5e07021e 1536 WLAN_CIPHER_SUITE_SMS4,
bdcd8170
KV
1537};
1538
1539static bool is_rate_legacy(s32 rate)
1540{
1541 static const s32 legacy[] = { 1000, 2000, 5500, 11000,
1542 6000, 9000, 12000, 18000, 24000,
1543 36000, 48000, 54000
1544 };
1545 u8 i;
1546
1547 for (i = 0; i < ARRAY_SIZE(legacy); i++)
1548 if (rate == legacy[i])
1549 return true;
1550
1551 return false;
1552}
1553
1554static bool is_rate_ht20(s32 rate, u8 *mcs, bool *sgi)
1555{
1556 static const s32 ht20[] = { 6500, 13000, 19500, 26000, 39000,
1557 52000, 58500, 65000, 72200
1558 };
1559 u8 i;
1560
1561 for (i = 0; i < ARRAY_SIZE(ht20); i++) {
1562 if (rate == ht20[i]) {
1563 if (i == ARRAY_SIZE(ht20) - 1)
1564 /* last rate uses sgi */
1565 *sgi = true;
1566 else
1567 *sgi = false;
1568
1569 *mcs = i;
1570 return true;
1571 }
1572 }
1573 return false;
1574}
1575
1576static bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi)
1577{
1578 static const s32 ht40[] = { 13500, 27000, 40500, 54000,
1579 81000, 108000, 121500, 135000,
1580 150000
1581 };
1582 u8 i;
1583
1584 for (i = 0; i < ARRAY_SIZE(ht40); i++) {
1585 if (rate == ht40[i]) {
1586 if (i == ARRAY_SIZE(ht40) - 1)
1587 /* last rate uses sgi */
1588 *sgi = true;
1589 else
1590 *sgi = false;
1591
1592 *mcs = i;
1593 return true;
1594 }
1595 }
1596
1597 return false;
1598}
1599
1600static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
1601 u8 *mac, struct station_info *sinfo)
1602{
1603 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 1604 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170
KV
1605 long left;
1606 bool sgi;
1607 s32 rate;
1608 int ret;
1609 u8 mcs;
1610
8c8b65e3 1611 if (memcmp(mac, vif->bssid, ETH_ALEN) != 0)
bdcd8170
KV
1612 return -ENOENT;
1613
1614 if (down_interruptible(&ar->sem))
1615 return -EBUSY;
1616
b95907a7 1617 set_bit(STATS_UPDATE_PEND, &vif->flags);
bdcd8170 1618
334234b5 1619 ret = ath6kl_wmi_get_stats_cmd(ar->wmi, vif->fw_vif_idx);
bdcd8170
KV
1620
1621 if (ret != 0) {
1622 up(&ar->sem);
1623 return -EIO;
1624 }
1625
1626 left = wait_event_interruptible_timeout(ar->event_wq,
1627 !test_bit(STATS_UPDATE_PEND,
b95907a7 1628 &vif->flags),
bdcd8170
KV
1629 WMI_TIMEOUT);
1630
1631 up(&ar->sem);
1632
1633 if (left == 0)
1634 return -ETIMEDOUT;
1635 else if (left < 0)
1636 return left;
1637
b95907a7
VT
1638 if (vif->target_stats.rx_byte) {
1639 sinfo->rx_bytes = vif->target_stats.rx_byte;
bdcd8170 1640 sinfo->filled |= STATION_INFO_RX_BYTES;
b95907a7 1641 sinfo->rx_packets = vif->target_stats.rx_pkt;
bdcd8170
KV
1642 sinfo->filled |= STATION_INFO_RX_PACKETS;
1643 }
1644
b95907a7
VT
1645 if (vif->target_stats.tx_byte) {
1646 sinfo->tx_bytes = vif->target_stats.tx_byte;
bdcd8170 1647 sinfo->filled |= STATION_INFO_TX_BYTES;
b95907a7 1648 sinfo->tx_packets = vif->target_stats.tx_pkt;
bdcd8170
KV
1649 sinfo->filled |= STATION_INFO_TX_PACKETS;
1650 }
1651
b95907a7 1652 sinfo->signal = vif->target_stats.cs_rssi;
bdcd8170
KV
1653 sinfo->filled |= STATION_INFO_SIGNAL;
1654
b95907a7 1655 rate = vif->target_stats.tx_ucast_rate;
bdcd8170
KV
1656
1657 if (is_rate_legacy(rate)) {
1658 sinfo->txrate.legacy = rate / 100;
1659 } else if (is_rate_ht20(rate, &mcs, &sgi)) {
1660 if (sgi) {
1661 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
1662 sinfo->txrate.mcs = mcs - 1;
1663 } else {
1664 sinfo->txrate.mcs = mcs;
1665 }
1666
1667 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
1668 } else if (is_rate_ht40(rate, &mcs, &sgi)) {
1669 if (sgi) {
1670 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
1671 sinfo->txrate.mcs = mcs - 1;
1672 } else {
1673 sinfo->txrate.mcs = mcs;
1674 }
1675
1676 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
1677 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
1678 } else {
9a730834
KV
1679 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1680 "invalid rate from stats: %d\n", rate);
1681 ath6kl_debug_war(ar, ATH6KL_WAR_INVALID_RATE);
bdcd8170
KV
1682 return 0;
1683 }
1684
1685 sinfo->filled |= STATION_INFO_TX_BITRATE;
1686
59c98449
VT
1687 if (test_bit(CONNECTED, &vif->flags) &&
1688 test_bit(DTIM_PERIOD_AVAIL, &vif->flags) &&
f5938f24 1689 vif->nw_type == INFRA_NETWORK) {
32c10874
JM
1690 sinfo->filled |= STATION_INFO_BSS_PARAM;
1691 sinfo->bss_param.flags = 0;
cf5333d7
VT
1692 sinfo->bss_param.dtim_period = vif->assoc_bss_dtim_period;
1693 sinfo->bss_param.beacon_interval = vif->assoc_bss_beacon_int;
32c10874
JM
1694 }
1695
bdcd8170
KV
1696 return 0;
1697}
1698
1699static int ath6kl_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1700 struct cfg80211_pmksa *pmksa)
1701{
1702 struct ath6kl *ar = ath6kl_priv(netdev);
334234b5
VT
1703 struct ath6kl_vif *vif = netdev_priv(netdev);
1704
1705 return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx, pmksa->bssid,
bdcd8170
KV
1706 pmksa->pmkid, true);
1707}
1708
1709static int ath6kl_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1710 struct cfg80211_pmksa *pmksa)
1711{
1712 struct ath6kl *ar = ath6kl_priv(netdev);
334234b5
VT
1713 struct ath6kl_vif *vif = netdev_priv(netdev);
1714
1715 return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx, pmksa->bssid,
bdcd8170
KV
1716 pmksa->pmkid, false);
1717}
1718
1719static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
1720{
1721 struct ath6kl *ar = ath6kl_priv(netdev);
59c98449
VT
1722 struct ath6kl_vif *vif = netdev_priv(netdev);
1723
1724 if (test_bit(CONNECTED, &vif->flags))
334234b5
VT
1725 return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx,
1726 vif->bssid, NULL, false);
bdcd8170
KV
1727 return 0;
1728}
1729
6cb3c714
RM
1730static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
1731{
1732 struct ath6kl_vif *vif;
1733 int ret, pos, left;
1734 u32 filter = 0;
1735 u16 i;
1736 u8 mask[WOW_MASK_SIZE];
1737
1738 vif = ath6kl_vif_first(ar);
1739 if (!vif)
1740 return -EIO;
1741
1742 if (!ath6kl_cfg80211_ready(vif))
1743 return -EIO;
1744
1745 if (!test_bit(CONNECTED, &vif->flags))
1746 return -EINVAL;
1747
1748 /* Clear existing WOW patterns */
1749 for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++)
1750 ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx,
1751 WOW_LIST_ID, i);
1752 /* Configure new WOW patterns */
1753 for (i = 0; i < wow->n_patterns; i++) {
1754
1755 /*
1756 * Convert given nl80211 specific mask value to equivalent
1757 * driver specific mask value and send it to the chip along
1758 * with patterns. For example, If the mask value defined in
1759 * struct cfg80211_wowlan is 0xA (equivalent binary is 1010),
1760 * then equivalent driver specific mask value is
1761 * "0xFF 0x00 0xFF 0x00".
1762 */
1763 memset(&mask, 0, sizeof(mask));
1764 for (pos = 0; pos < wow->patterns[i].pattern_len; pos++) {
1765 if (wow->patterns[i].mask[pos / 8] & (0x1 << (pos % 8)))
1766 mask[pos] = 0xFF;
1767 }
1768 /*
1769 * Note: Pattern's offset is not passed as part of wowlan
1770 * parameter from CFG layer. So it's always passed as ZERO
1771 * to the firmware. It means, given WOW patterns are always
1772 * matched from the first byte of received pkt in the firmware.
1773 */
1774 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1775 vif->fw_vif_idx, WOW_LIST_ID,
1776 wow->patterns[i].pattern_len,
1777 0 /* pattern offset */,
1778 wow->patterns[i].pattern, mask);
1779 if (ret)
1780 return ret;
1781 }
1782
1783 if (wow->disconnect)
1784 filter |= WOW_FILTER_OPTION_NWK_DISASSOC;
1785
1786 if (wow->magic_pkt)
1787 filter |= WOW_FILTER_OPTION_MAGIC_PACKET;
1788
1789 if (wow->gtk_rekey_failure)
1790 filter |= WOW_FILTER_OPTION_GTK_ERROR;
1791
1792 if (wow->eap_identity_req)
1793 filter |= WOW_FILTER_OPTION_EAP_REQ;
1794
1795 if (wow->four_way_handshake)
1796 filter |= WOW_FILTER_OPTION_8021X_4WAYHS;
1797
1798 ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
1799 ATH6KL_WOW_MODE_ENABLE,
1800 filter,
1801 WOW_HOST_REQ_DELAY);
1802 if (ret)
1803 return ret;
1804
1805 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
1806 ATH6KL_HOST_MODE_ASLEEP);
1807 if (ret)
1808 return ret;
1809
1810 if (ar->tx_pending[ar->ctrl_ep]) {
1811 left = wait_event_interruptible_timeout(ar->event_wq,
1812 ar->tx_pending[ar->ctrl_ep] == 0, WMI_TIMEOUT);
1813 if (left == 0) {
1814 ath6kl_warn("clear wmi ctrl data timeout\n");
1815 ret = -ETIMEDOUT;
1816 } else if (left < 0) {
1817 ath6kl_warn("clear wmi ctrl data failed: %d\n", left);
1818 ret = left;
1819 }
1820 }
1821
1822 return ret;
1823}
1824
1825static int ath6kl_wow_resume(struct ath6kl *ar)
1826{
1827 struct ath6kl_vif *vif;
1828 int ret;
1829
1830 vif = ath6kl_vif_first(ar);
1831 if (!vif)
1832 return -EIO;
1833
1834 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
1835 ATH6KL_HOST_MODE_AWAKE);
1836 return ret;
1837}
1838
52d81a68 1839int ath6kl_cfg80211_suspend(struct ath6kl *ar,
0f60e9f4
RM
1840 enum ath6kl_cfg_suspend_mode mode,
1841 struct cfg80211_wowlan *wow)
52d81a68
KV
1842{
1843 int ret;
1844
52d81a68 1845 switch (mode) {
d7c44e0b
RM
1846 case ATH6KL_CFG_SUSPEND_WOW:
1847
1848 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "wow mode suspend\n");
1849
1850 /* Flush all non control pkts in TX path */
1851 ath6kl_tx_data_cleanup(ar);
1852
1853 ret = ath6kl_wow_suspend(ar, wow);
1854 if (ret) {
1855 ath6kl_err("wow suspend failed: %d\n", ret);
1856 return ret;
1857 }
1858 ar->state = ATH6KL_STATE_WOW;
1859 break;
1860
52d81a68 1861 case ATH6KL_CFG_SUSPEND_DEEPSLEEP:
524441e3 1862
7125f01d 1863 ath6kl_cfg80211_stop_all(ar);
524441e3 1864
52d81a68
KV
1865 /* save the current power mode before enabling power save */
1866 ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
1867
1868 ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER);
1869 if (ret) {
1870 ath6kl_warn("wmi powermode command failed during suspend: %d\n",
1871 ret);
1872 }
1873
76a9fbe2
KV
1874 ar->state = ATH6KL_STATE_DEEPSLEEP;
1875
52d81a68 1876 break;
b4b2a0b1
KV
1877
1878 case ATH6KL_CFG_SUSPEND_CUTPOWER:
524441e3 1879
7125f01d 1880 ath6kl_cfg80211_stop_all(ar);
524441e3 1881
b4b2a0b1
KV
1882 if (ar->state == ATH6KL_STATE_OFF) {
1883 ath6kl_dbg(ATH6KL_DBG_SUSPEND,
1884 "suspend hw off, no action for cutpower\n");
1885 break;
1886 }
1887
1888 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "suspend cutting power\n");
1889
1890 ret = ath6kl_init_hw_stop(ar);
1891 if (ret) {
1892 ath6kl_warn("failed to stop hw during suspend: %d\n",
1893 ret);
1894 }
1895
1896 ar->state = ATH6KL_STATE_CUTPOWER;
1897
1898 break;
1899
10509f90
KV
1900 case ATH6KL_CFG_SUSPEND_SCHED_SCAN:
1901 /*
1902 * Nothing needed for schedule scan, firmware is already in
1903 * wow mode and sleeping most of the time.
1904 */
1905 break;
1906
b4b2a0b1
KV
1907 default:
1908 break;
52d81a68
KV
1909 }
1910
1911 return 0;
1912}
1913
1914int ath6kl_cfg80211_resume(struct ath6kl *ar)
1915{
76a9fbe2
KV
1916 int ret;
1917
1918 switch (ar->state) {
d7c44e0b
RM
1919 case ATH6KL_STATE_WOW:
1920 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "wow mode resume\n");
1921
1922 ret = ath6kl_wow_resume(ar);
1923 if (ret) {
1924 ath6kl_warn("wow mode resume failed: %d\n", ret);
1925 return ret;
1926 }
1927
1928 ar->state = ATH6KL_STATE_ON;
1929 break;
1930
76a9fbe2
KV
1931 case ATH6KL_STATE_DEEPSLEEP:
1932 if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) {
1933 ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0,
1934 ar->wmi->saved_pwr_mode);
1935 if (ret) {
1936 ath6kl_warn("wmi powermode command failed during resume: %d\n",
1937 ret);
1938 }
1939 }
1940
1941 ar->state = ATH6KL_STATE_ON;
1942
1943 break;
1944
b4b2a0b1
KV
1945 case ATH6KL_STATE_CUTPOWER:
1946 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "resume restoring power\n");
1947
1948 ret = ath6kl_init_hw_start(ar);
1949 if (ret) {
1950 ath6kl_warn("Failed to boot hw in resume: %d\n", ret);
1951 return ret;
1952 }
d7c44e0b 1953 break;
b4b2a0b1 1954
10509f90
KV
1955 case ATH6KL_STATE_SCHED_SCAN:
1956 break;
1957
76a9fbe2
KV
1958 default:
1959 break;
52d81a68
KV
1960 }
1961
1962 return 0;
1963}
1964
abcb344b 1965#ifdef CONFIG_PM
52d81a68
KV
1966
1967/* hif layer decides what suspend mode to use */
1968static int __ath6kl_cfg80211_suspend(struct wiphy *wiphy,
abcb344b
KV
1969 struct cfg80211_wowlan *wow)
1970{
1971 struct ath6kl *ar = wiphy_priv(wiphy);
1972
0f60e9f4 1973 return ath6kl_hif_suspend(ar, wow);
abcb344b 1974}
aa6cffc1 1975
52d81a68 1976static int __ath6kl_cfg80211_resume(struct wiphy *wiphy)
aa6cffc1
CN
1977{
1978 struct ath6kl *ar = wiphy_priv(wiphy);
1979
1980 return ath6kl_hif_resume(ar);
1981}
a918fb3c
RM
1982
1983/*
1984 * FIXME: WOW suspend mode is selected if the host sdio controller supports
1985 * both sdio irq wake up and keep power. The target pulls sdio data line to
1986 * wake up the host when WOW pattern matches. This causes sdio irq handler
1987 * is being called in the host side which internally hits ath6kl's RX path.
1988 *
1989 * Since sdio interrupt is not disabled, RX path executes even before
1990 * the host executes the actual resume operation from PM module.
1991 *
1992 * In the current scenario, WOW resume should happen before start processing
1993 * any data from the target. So It's required to perform WOW resume in RX path.
1994 * Ideally we should perform WOW resume only in the actual platform
1995 * resume path. This area needs bit rework to avoid WOW resume in RX path.
1996 *
1997 * ath6kl_check_wow_status() is called from ath6kl_rx().
1998 */
1999void ath6kl_check_wow_status(struct ath6kl *ar)
2000{
2001 if (ar->state == ATH6KL_STATE_WOW)
2002 ath6kl_cfg80211_resume(ar);
2003}
2004
2005#else
2006
2007void ath6kl_check_wow_status(struct ath6kl *ar)
2008{
2009}
abcb344b
KV
2010#endif
2011
6a7c9bad
JM
2012static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev,
2013 struct ieee80211_channel *chan,
2014 enum nl80211_channel_type channel_type)
2015{
cf5333d7 2016 struct ath6kl_vif *vif = netdev_priv(dev);
6a7c9bad 2017
990bd915 2018 if (!ath6kl_cfg80211_ready(vif))
6a7c9bad
JM
2019 return -EIO;
2020
2021 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n",
2022 __func__, chan->center_freq, chan->hw_value);
cf5333d7 2023 vif->next_chan = chan->center_freq;
6a7c9bad
JM
2024
2025 return 0;
2026}
2027
8bdfbf40
JM
2028static bool ath6kl_is_p2p_ie(const u8 *pos)
2029{
2030 return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
2031 pos[2] == 0x50 && pos[3] == 0x6f &&
2032 pos[4] == 0x9a && pos[5] == 0x09;
2033}
2034
334234b5
VT
2035static int ath6kl_set_ap_probe_resp_ies(struct ath6kl_vif *vif,
2036 const u8 *ies, size_t ies_len)
8bdfbf40 2037{
334234b5 2038 struct ath6kl *ar = vif->ar;
8bdfbf40
JM
2039 const u8 *pos;
2040 u8 *buf = NULL;
2041 size_t len = 0;
2042 int ret;
2043
2044 /*
2045 * Filter out P2P IE(s) since they will be included depending on
2046 * the Probe Request frame in ath6kl_send_go_probe_resp().
2047 */
2048
2049 if (ies && ies_len) {
2050 buf = kmalloc(ies_len, GFP_KERNEL);
2051 if (buf == NULL)
2052 return -ENOMEM;
2053 pos = ies;
2054 while (pos + 1 < ies + ies_len) {
2055 if (pos + 2 + pos[1] > ies + ies_len)
2056 break;
2057 if (!ath6kl_is_p2p_ie(pos)) {
2058 memcpy(buf + len, pos, 2 + pos[1]);
2059 len += 2 + pos[1];
2060 }
2061 pos += 2 + pos[1];
2062 }
2063 }
2064
334234b5
VT
2065 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2066 WMI_FRAME_PROBE_RESP, buf, len);
8bdfbf40
JM
2067 kfree(buf);
2068 return ret;
2069}
2070
6a7c9bad
JM
2071static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
2072 struct beacon_parameters *info, bool add)
2073{
2074 struct ath6kl *ar = ath6kl_priv(dev);
3450334f 2075 struct ath6kl_vif *vif = netdev_priv(dev);
6a7c9bad
JM
2076 struct ieee80211_mgmt *mgmt;
2077 u8 *ies;
2078 int ies_len;
2079 struct wmi_connect_cmd p;
2080 int res;
be5abaaf 2081 int i, ret;
6a7c9bad
JM
2082
2083 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: add=%d\n", __func__, add);
2084
990bd915 2085 if (!ath6kl_cfg80211_ready(vif))
6a7c9bad
JM
2086 return -EIO;
2087
f5938f24 2088 if (vif->next_mode != AP_NETWORK)
6a7c9bad
JM
2089 return -EOPNOTSUPP;
2090
2091 if (info->beacon_ies) {
334234b5
VT
2092 res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2093 WMI_FRAME_BEACON,
6a7c9bad
JM
2094 info->beacon_ies,
2095 info->beacon_ies_len);
2096 if (res)
2097 return res;
2098 }
2099 if (info->proberesp_ies) {
334234b5 2100 res = ath6kl_set_ap_probe_resp_ies(vif, info->proberesp_ies,
8bdfbf40 2101 info->proberesp_ies_len);
6a7c9bad
JM
2102 if (res)
2103 return res;
2104 }
2105 if (info->assocresp_ies) {
334234b5
VT
2106 res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2107 WMI_FRAME_ASSOC_RESP,
6a7c9bad
JM
2108 info->assocresp_ies,
2109 info->assocresp_ies_len);
2110 if (res)
2111 return res;
2112 }
2113
2114 if (!add)
2115 return 0;
2116
9a5b1318
JM
2117 ar->ap_mode_bkey.valid = false;
2118
6a7c9bad
JM
2119 /* TODO:
2120 * info->interval
2121 * info->dtim_period
2122 */
2123
2124 if (info->head == NULL)
2125 return -EINVAL;
2126 mgmt = (struct ieee80211_mgmt *) info->head;
2127 ies = mgmt->u.beacon.variable;
2128 if (ies > info->head + info->head_len)
2129 return -EINVAL;
2130 ies_len = info->head + info->head_len - ies;
2131
2132 if (info->ssid == NULL)
2133 return -EINVAL;
3450334f
VT
2134 memcpy(vif->ssid, info->ssid, info->ssid_len);
2135 vif->ssid_len = info->ssid_len;
6a7c9bad
JM
2136 if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
2137 return -EOPNOTSUPP; /* TODO */
2138
be5abaaf
VT
2139 ret = ath6kl_set_auth_type(vif, info->auth_type);
2140 if (ret)
2141 return ret;
6a7c9bad
JM
2142
2143 memset(&p, 0, sizeof(p));
2144
2145 for (i = 0; i < info->crypto.n_akm_suites; i++) {
2146 switch (info->crypto.akm_suites[i]) {
2147 case WLAN_AKM_SUITE_8021X:
2148 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1)
2149 p.auth_mode |= WPA_AUTH;
2150 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2)
2151 p.auth_mode |= WPA2_AUTH;
2152 break;
2153 case WLAN_AKM_SUITE_PSK:
2154 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1)
2155 p.auth_mode |= WPA_PSK_AUTH;
2156 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2)
2157 p.auth_mode |= WPA2_PSK_AUTH;
2158 break;
2159 }
2160 }
2161 if (p.auth_mode == 0)
2162 p.auth_mode = NONE_AUTH;
3450334f 2163 vif->auth_mode = p.auth_mode;
6a7c9bad
JM
2164
2165 for (i = 0; i < info->crypto.n_ciphers_pairwise; i++) {
2166 switch (info->crypto.ciphers_pairwise[i]) {
2167 case WLAN_CIPHER_SUITE_WEP40:
2168 case WLAN_CIPHER_SUITE_WEP104:
2169 p.prwise_crypto_type |= WEP_CRYPT;
2170 break;
2171 case WLAN_CIPHER_SUITE_TKIP:
2172 p.prwise_crypto_type |= TKIP_CRYPT;
2173 break;
2174 case WLAN_CIPHER_SUITE_CCMP:
2175 p.prwise_crypto_type |= AES_CRYPT;
2176 break;
b8214df1
DS
2177 case WLAN_CIPHER_SUITE_SMS4:
2178 p.prwise_crypto_type |= WAPI_CRYPT;
2179 break;
6a7c9bad
JM
2180 }
2181 }
229ed6b5 2182 if (p.prwise_crypto_type == 0) {
6a7c9bad 2183 p.prwise_crypto_type = NONE_CRYPT;
240d2799 2184 ath6kl_set_cipher(vif, 0, true);
229ed6b5 2185 } else if (info->crypto.n_ciphers_pairwise == 1)
240d2799 2186 ath6kl_set_cipher(vif, info->crypto.ciphers_pairwise[0], true);
6a7c9bad
JM
2187
2188 switch (info->crypto.cipher_group) {
2189 case WLAN_CIPHER_SUITE_WEP40:
2190 case WLAN_CIPHER_SUITE_WEP104:
2191 p.grp_crypto_type = WEP_CRYPT;
2192 break;
2193 case WLAN_CIPHER_SUITE_TKIP:
2194 p.grp_crypto_type = TKIP_CRYPT;
2195 break;
2196 case WLAN_CIPHER_SUITE_CCMP:
2197 p.grp_crypto_type = AES_CRYPT;
2198 break;
b8214df1
DS
2199 case WLAN_CIPHER_SUITE_SMS4:
2200 p.grp_crypto_type = WAPI_CRYPT;
2201 break;
6a7c9bad
JM
2202 default:
2203 p.grp_crypto_type = NONE_CRYPT;
2204 break;
2205 }
240d2799 2206 ath6kl_set_cipher(vif, info->crypto.cipher_group, false);
6a7c9bad
JM
2207
2208 p.nw_type = AP_NETWORK;
f5938f24 2209 vif->nw_type = vif->next_mode;
6a7c9bad 2210
3450334f
VT
2211 p.ssid_len = vif->ssid_len;
2212 memcpy(p.ssid, vif->ssid, vif->ssid_len);
2213 p.dot11_auth_mode = vif->dot11_auth_mode;
cf5333d7 2214 p.ch = cpu_to_le16(vif->next_chan);
6a7c9bad 2215
3ca9d1fc
AT
2216 if (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) {
2217 p.nw_subtype = SUBTYPE_P2PGO;
2218 } else {
2219 /*
2220 * Due to firmware limitation, it is not possible to
2221 * do P2P mgmt operations in AP mode
2222 */
2223 p.nw_subtype = SUBTYPE_NONE;
2224 }
2225
334234b5 2226 res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p);
9a5b1318
JM
2227 if (res < 0)
2228 return res;
2229
2230 return 0;
6a7c9bad
JM
2231}
2232
2233static int ath6kl_add_beacon(struct wiphy *wiphy, struct net_device *dev,
2234 struct beacon_parameters *info)
2235{
2236 return ath6kl_ap_beacon(wiphy, dev, info, true);
2237}
2238
2239static int ath6kl_set_beacon(struct wiphy *wiphy, struct net_device *dev,
2240 struct beacon_parameters *info)
2241{
2242 return ath6kl_ap_beacon(wiphy, dev, info, false);
2243}
2244
2245static int ath6kl_del_beacon(struct wiphy *wiphy, struct net_device *dev)
2246{
2247 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 2248 struct ath6kl_vif *vif = netdev_priv(dev);
6a7c9bad 2249
f5938f24 2250 if (vif->nw_type != AP_NETWORK)
6a7c9bad 2251 return -EOPNOTSUPP;
59c98449 2252 if (!test_bit(CONNECTED, &vif->flags))
6a7c9bad
JM
2253 return -ENOTCONN;
2254
334234b5 2255 ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
59c98449 2256 clear_bit(CONNECTED, &vif->flags);
6a7c9bad
JM
2257
2258 return 0;
2259}
2260
23875136
JM
2261static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
2262 u8 *mac, struct station_parameters *params)
2263{
2264 struct ath6kl *ar = ath6kl_priv(dev);
f5938f24 2265 struct ath6kl_vif *vif = netdev_priv(dev);
23875136 2266
f5938f24 2267 if (vif->nw_type != AP_NETWORK)
23875136
JM
2268 return -EOPNOTSUPP;
2269
2270 /* Use this only for authorizing/unauthorizing a station */
2271 if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
2272 return -EOPNOTSUPP;
2273
2274 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
334234b5
VT
2275 return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx,
2276 WMI_AP_MLME_AUTHORIZE, mac, 0);
2277 return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx,
2278 WMI_AP_MLME_UNAUTHORIZE, mac, 0);
23875136
JM
2279}
2280
63fa1e0c
JM
2281static int ath6kl_remain_on_channel(struct wiphy *wiphy,
2282 struct net_device *dev,
2283 struct ieee80211_channel *chan,
2284 enum nl80211_channel_type channel_type,
2285 unsigned int duration,
2286 u64 *cookie)
2287{
2288 struct ath6kl *ar = ath6kl_priv(dev);
334234b5 2289 struct ath6kl_vif *vif = netdev_priv(dev);
1052261e 2290 u32 id;
63fa1e0c
JM
2291
2292 /* TODO: if already pending or ongoing remain-on-channel,
2293 * return -EBUSY */
1052261e
JM
2294 id = ++vif->last_roc_id;
2295 if (id == 0) {
2296 /* Do not use 0 as the cookie value */
2297 id = ++vif->last_roc_id;
2298 }
2299 *cookie = id;
63fa1e0c 2300
334234b5
VT
2301 return ath6kl_wmi_remain_on_chnl_cmd(ar->wmi, vif->fw_vif_idx,
2302 chan->center_freq, duration);
63fa1e0c
JM
2303}
2304
2305static int ath6kl_cancel_remain_on_channel(struct wiphy *wiphy,
2306 struct net_device *dev,
2307 u64 cookie)
2308{
2309 struct ath6kl *ar = ath6kl_priv(dev);
334234b5 2310 struct ath6kl_vif *vif = netdev_priv(dev);
63fa1e0c 2311
1052261e 2312 if (cookie != vif->last_roc_id)
63fa1e0c 2313 return -ENOENT;
1052261e 2314 vif->last_cancel_roc_id = cookie;
63fa1e0c 2315
334234b5 2316 return ath6kl_wmi_cancel_remain_on_chnl_cmd(ar->wmi, vif->fw_vif_idx);
63fa1e0c
JM
2317}
2318
334234b5
VT
2319static int ath6kl_send_go_probe_resp(struct ath6kl_vif *vif,
2320 const u8 *buf, size_t len,
2321 unsigned int freq)
8bdfbf40 2322{
334234b5 2323 struct ath6kl *ar = vif->ar;
8bdfbf40
JM
2324 const u8 *pos;
2325 u8 *p2p;
2326 int p2p_len;
2327 int ret;
2328 const struct ieee80211_mgmt *mgmt;
2329
2330 mgmt = (const struct ieee80211_mgmt *) buf;
2331
2332 /* Include P2P IE(s) from the frame generated in user space. */
2333
2334 p2p = kmalloc(len, GFP_KERNEL);
2335 if (p2p == NULL)
2336 return -ENOMEM;
2337 p2p_len = 0;
2338
2339 pos = mgmt->u.probe_resp.variable;
2340 while (pos + 1 < buf + len) {
2341 if (pos + 2 + pos[1] > buf + len)
2342 break;
2343 if (ath6kl_is_p2p_ie(pos)) {
2344 memcpy(p2p + p2p_len, pos, 2 + pos[1]);
2345 p2p_len += 2 + pos[1];
2346 }
2347 pos += 2 + pos[1];
2348 }
2349
334234b5
VT
2350 ret = ath6kl_wmi_send_probe_response_cmd(ar->wmi, vif->fw_vif_idx, freq,
2351 mgmt->da, p2p, p2p_len);
8bdfbf40
JM
2352 kfree(p2p);
2353 return ret;
2354}
2355
8a6c8060
JM
2356static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
2357 struct ieee80211_channel *chan, bool offchan,
2358 enum nl80211_channel_type channel_type,
2359 bool channel_type_valid, unsigned int wait,
e247bd90
JB
2360 const u8 *buf, size_t len, bool no_cck,
2361 bool dont_wait_for_ack, u64 *cookie)
8a6c8060
JM
2362{
2363 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 2364 struct ath6kl_vif *vif = netdev_priv(dev);
8a6c8060 2365 u32 id;
8bdfbf40
JM
2366 const struct ieee80211_mgmt *mgmt;
2367
2368 mgmt = (const struct ieee80211_mgmt *) buf;
2369 if (buf + len >= mgmt->u.probe_resp.variable &&
f5938f24 2370 vif->nw_type == AP_NETWORK && test_bit(CONNECTED, &vif->flags) &&
8bdfbf40
JM
2371 ieee80211_is_probe_resp(mgmt->frame_control)) {
2372 /*
2373 * Send Probe Response frame in AP mode using a separate WMI
2374 * command to allow the target to fill in the generic IEs.
2375 */
2376 *cookie = 0; /* TX status not supported */
334234b5 2377 return ath6kl_send_go_probe_resp(vif, buf, len,
8bdfbf40
JM
2378 chan->center_freq);
2379 }
8a6c8060 2380
cf5333d7 2381 id = vif->send_action_id++;
8a6c8060
JM
2382 if (id == 0) {
2383 /*
2384 * 0 is a reserved value in the WMI command and shall not be
2385 * used for the command.
2386 */
cf5333d7 2387 id = vif->send_action_id++;
8a6c8060
JM
2388 }
2389
2390 *cookie = id;
3ca9d1fc
AT
2391
2392 if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
2393 ar->fw_capabilities)) {
2394 /*
2395 * If capable of doing P2P mgmt operations using
2396 * station interface, send additional information like
2397 * supported rates to advertise and xmit rates for
2398 * probe requests
2399 */
2400 return ath6kl_wmi_send_mgmt_cmd(ar->wmi, vif->fw_vif_idx, id,
2401 chan->center_freq, wait,
2402 buf, len, no_cck);
2403 } else {
2404 return ath6kl_wmi_send_action_cmd(ar->wmi, vif->fw_vif_idx, id,
2405 chan->center_freq, wait,
2406 buf, len);
2407 }
8a6c8060
JM
2408}
2409
ae32c30a
JM
2410static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
2411 struct net_device *dev,
2412 u16 frame_type, bool reg)
2413{
cf5333d7 2414 struct ath6kl_vif *vif = netdev_priv(dev);
ae32c30a
JM
2415
2416 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: frame_type=0x%x reg=%d\n",
2417 __func__, frame_type, reg);
2418 if (frame_type == IEEE80211_STYPE_PROBE_REQ) {
2419 /*
2420 * Note: This notification callback is not allowed to sleep, so
2421 * we cannot send WMI_PROBE_REQ_REPORT_CMD here. Instead, we
2422 * hardcode target to report Probe Request frames all the time.
2423 */
cf5333d7 2424 vif->probe_req_report = reg;
ae32c30a
JM
2425 }
2426}
2427
10509f90
KV
2428static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
2429 struct net_device *dev,
2430 struct cfg80211_sched_scan_request *request)
2431{
2432 struct ath6kl *ar = ath6kl_priv(dev);
2433 struct ath6kl_vif *vif = netdev_priv(dev);
2434 u16 interval;
2435 int ret;
2436 u8 i;
2437
2438 if (ar->state != ATH6KL_STATE_ON)
2439 return -EIO;
2440
2441 if (vif->sme_state != SME_DISCONNECTED)
2442 return -EBUSY;
2443
2444 for (i = 0; i < ar->wiphy->max_sched_scan_ssids; i++) {
2445 ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
2446 i, DISABLE_SSID_FLAG,
2447 0, NULL);
2448 }
2449
2450 /* fw uses seconds, also make sure that it's >0 */
2451 interval = max_t(u16, 1, request->interval / 1000);
2452
2453 ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
2454 interval, interval,
2455 10, 0, 0, 0, 3, 0, 0, 0);
2456
2457 if (request->n_ssids && request->ssids[0].ssid_len) {
2458 for (i = 0; i < request->n_ssids; i++) {
2459 ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
2460 i, SPECIFIC_SSID_FLAG,
2461 request->ssids[i].ssid_len,
2462 request->ssids[i].ssid);
2463 }
2464 }
2465
2466 ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
2467 ATH6KL_WOW_MODE_ENABLE,
2468 WOW_FILTER_SSID,
2469 WOW_HOST_REQ_DELAY);
2470 if (ret) {
2471 ath6kl_warn("Failed to enable wow with ssid filter: %d\n", ret);
2472 return ret;
2473 }
2474
2475 /* this also clears IE in fw if it's not set */
2476 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2477 WMI_FRAME_PROBE_REQ,
2478 request->ie, request->ie_len);
2479 if (ret) {
2480 ath6kl_warn("Failed to set probe request IE for scheduled scan: %d",
2481 ret);
2482 return ret;
2483 }
2484
2485 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
2486 ATH6KL_HOST_MODE_ASLEEP);
2487 if (ret) {
2488 ath6kl_warn("Failed to enable host sleep mode for sched scan: %d\n",
2489 ret);
2490 return ret;
2491 }
2492
2493 ar->state = ATH6KL_STATE_SCHED_SCAN;
2494
2495 return ret;
2496}
2497
2498static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy,
2499 struct net_device *dev)
2500{
2501 struct ath6kl_vif *vif = netdev_priv(dev);
2502 bool stopped;
2503
2504 stopped = __ath6kl_cfg80211_sscan_stop(vif);
2505
2506 if (!stopped)
2507 return -EIO;
2508
2509 return 0;
2510}
2511
f80574ae
JM
2512static const struct ieee80211_txrx_stypes
2513ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
2514 [NL80211_IFTYPE_STATION] = {
2515 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2516 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
2517 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2518 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
2519 },
2520 [NL80211_IFTYPE_P2P_CLIENT] = {
2521 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2522 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
2523 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2524 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
2525 },
2526 [NL80211_IFTYPE_P2P_GO] = {
2527 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2528 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
2529 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2530 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
2531 },
2532};
2533
bdcd8170 2534static struct cfg80211_ops ath6kl_cfg80211_ops = {
55055976
VT
2535 .add_virtual_intf = ath6kl_cfg80211_add_iface,
2536 .del_virtual_intf = ath6kl_cfg80211_del_iface,
bdcd8170
KV
2537 .change_virtual_intf = ath6kl_cfg80211_change_iface,
2538 .scan = ath6kl_cfg80211_scan,
2539 .connect = ath6kl_cfg80211_connect,
2540 .disconnect = ath6kl_cfg80211_disconnect,
2541 .add_key = ath6kl_cfg80211_add_key,
2542 .get_key = ath6kl_cfg80211_get_key,
2543 .del_key = ath6kl_cfg80211_del_key,
2544 .set_default_key = ath6kl_cfg80211_set_default_key,
2545 .set_wiphy_params = ath6kl_cfg80211_set_wiphy_params,
2546 .set_tx_power = ath6kl_cfg80211_set_txpower,
2547 .get_tx_power = ath6kl_cfg80211_get_txpower,
2548 .set_power_mgmt = ath6kl_cfg80211_set_power_mgmt,
2549 .join_ibss = ath6kl_cfg80211_join_ibss,
2550 .leave_ibss = ath6kl_cfg80211_leave_ibss,
2551 .get_station = ath6kl_get_station,
2552 .set_pmksa = ath6kl_set_pmksa,
2553 .del_pmksa = ath6kl_del_pmksa,
2554 .flush_pmksa = ath6kl_flush_pmksa,
003353b0 2555 CFG80211_TESTMODE_CMD(ath6kl_tm_cmd)
abcb344b 2556#ifdef CONFIG_PM
52d81a68
KV
2557 .suspend = __ath6kl_cfg80211_suspend,
2558 .resume = __ath6kl_cfg80211_resume,
abcb344b 2559#endif
6a7c9bad
JM
2560 .set_channel = ath6kl_set_channel,
2561 .add_beacon = ath6kl_add_beacon,
2562 .set_beacon = ath6kl_set_beacon,
2563 .del_beacon = ath6kl_del_beacon,
23875136 2564 .change_station = ath6kl_change_station,
63fa1e0c
JM
2565 .remain_on_channel = ath6kl_remain_on_channel,
2566 .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel,
8a6c8060 2567 .mgmt_tx = ath6kl_mgmt_tx,
ae32c30a 2568 .mgmt_frame_register = ath6kl_mgmt_frame_register,
10509f90
KV
2569 .sched_scan_start = ath6kl_cfg80211_sscan_start,
2570 .sched_scan_stop = ath6kl_cfg80211_sscan_stop,
bdcd8170
KV
2571};
2572
7125f01d 2573void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
ec4b7f60 2574{
10509f90
KV
2575 ath6kl_cfg80211_sscan_disable(vif);
2576
ec4b7f60 2577 switch (vif->sme_state) {
c97a31b0
KV
2578 case SME_DISCONNECTED:
2579 break;
ec4b7f60
KV
2580 case SME_CONNECTING:
2581 cfg80211_connect_result(vif->ndev, vif->bssid, NULL, 0,
2582 NULL, 0,
2583 WLAN_STATUS_UNSPECIFIED_FAILURE,
2584 GFP_KERNEL);
2585 break;
2586 case SME_CONNECTED:
ec4b7f60
KV
2587 cfg80211_disconnected(vif->ndev, 0, NULL, 0, GFP_KERNEL);
2588 break;
2589 }
2590
2591 if (test_bit(CONNECTED, &vif->flags) ||
2592 test_bit(CONNECT_PEND, &vif->flags))
7125f01d 2593 ath6kl_wmi_disconnect_cmd(vif->ar->wmi, vif->fw_vif_idx);
ec4b7f60
KV
2594
2595 vif->sme_state = SME_DISCONNECTED;
1f405255
KV
2596 clear_bit(CONNECTED, &vif->flags);
2597 clear_bit(CONNECT_PEND, &vif->flags);
ec4b7f60
KV
2598
2599 /* disable scanning */
7125f01d
KV
2600 if (ath6kl_wmi_scanparams_cmd(vif->ar->wmi, vif->fw_vif_idx, 0xFFFF,
2601 0, 0, 0, 0, 0, 0, 0, 0, 0) != 0)
2602 ath6kl_warn("failed to disable scan during stop\n");
ec4b7f60
KV
2603
2604 ath6kl_cfg80211_scan_complete_event(vif, true);
2605}
2606
7125f01d
KV
2607void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
2608{
2609 struct ath6kl_vif *vif;
2610
2611 vif = ath6kl_vif_first(ar);
2612 if (!vif) {
2613 /* save the current power mode before enabling power save */
2614 ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
2615
2616 if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0)
2617 ath6kl_warn("ath6kl_deep_sleep_enable: "
2618 "wmi_powermode_cmd failed\n");
2619 return;
2620 }
2621
2622 /*
2623 * FIXME: we should take ar->list_lock to protect changes in the
2624 * vif_list, but that's not trivial to do as ath6kl_cfg80211_stop()
2625 * sleeps.
2626 */
2627 list_for_each_entry(vif, &ar->vif_list, list)
2628 ath6kl_cfg80211_stop(vif);
2629}
2630
8dafb70e 2631struct ath6kl *ath6kl_core_alloc(struct device *dev)
bdcd8170 2632{
6bbc7c35 2633 struct ath6kl *ar;
be98e3a4 2634 struct wiphy *wiphy;
8dafb70e 2635 u8 ctr;
bdcd8170
KV
2636
2637 /* create a new wiphy for use with cfg80211 */
be98e3a4 2638 wiphy = wiphy_new(&ath6kl_cfg80211_ops, sizeof(struct ath6kl));
8dafb70e 2639
be98e3a4 2640 if (!wiphy) {
bdcd8170 2641 ath6kl_err("couldn't allocate wiphy device\n");
bdcd8170
KV
2642 return NULL;
2643 }
2644
be98e3a4 2645 ar = wiphy_priv(wiphy);
774439ad 2646 ar->p2p = !!ath6kl_p2p;
be98e3a4 2647 ar->wiphy = wiphy;
8dafb70e
VT
2648 ar->dev = dev;
2649
71f96ee6
KV
2650 ar->vif_max = 1;
2651
3226f68a
VT
2652 ar->max_norm_iface = 1;
2653
8dafb70e
VT
2654 spin_lock_init(&ar->lock);
2655 spin_lock_init(&ar->mcastpsq_lock);
990bd915 2656 spin_lock_init(&ar->list_lock);
8dafb70e
VT
2657
2658 init_waitqueue_head(&ar->event_wq);
2659 sema_init(&ar->sem, 1);
2660
2661 INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue);
990bd915 2662 INIT_LIST_HEAD(&ar->vif_list);
8dafb70e
VT
2663
2664 clear_bit(WMI_ENABLED, &ar->flag);
2665 clear_bit(SKIP_SCAN, &ar->flag);
2666 clear_bit(DESTROY_IN_PROGRESS, &ar->flag);
2667
2668 ar->listen_intvl_t = A_DEFAULT_LISTEN_INTERVAL;
2669 ar->listen_intvl_b = 0;
2670 ar->tx_pwr = 0;
2671
2672 ar->intra_bss = 1;
8dafb70e
VT
2673 ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD;
2674
76a9fbe2
KV
2675 ar->state = ATH6KL_STATE_OFF;
2676
8dafb70e
VT
2677 memset((u8 *)ar->sta_list, 0,
2678 AP_MAX_NUM_STA * sizeof(struct ath6kl_sta));
2679
2680 /* Init the PS queues */
2681 for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) {
2682 spin_lock_init(&ar->sta_list[ctr].psq_lock);
2683 skb_queue_head_init(&ar->sta_list[ctr].psq);
2684 }
2685
2686 skb_queue_head_init(&ar->mcastpsq);
2687
2688 memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3);
2689
2690 return ar;
2691}
2692
2693int ath6kl_register_ieee80211_hw(struct ath6kl *ar)
2694{
2695 struct wiphy *wiphy = ar->wiphy;
2696 int ret;
6bbc7c35 2697
be98e3a4 2698 wiphy->mgmt_stypes = ath6kl_mgmt_stypes;
f80574ae 2699
be98e3a4 2700 wiphy->max_remain_on_channel_duration = 5000;
63fa1e0c 2701
bdcd8170 2702 /* set device pointer for wiphy */
8dafb70e 2703 set_wiphy_dev(wiphy, ar->dev);
bdcd8170 2704
be98e3a4 2705 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
8dafb70e
VT
2706 BIT(NL80211_IFTYPE_ADHOC) |
2707 BIT(NL80211_IFTYPE_AP);
6bbc7c35 2708 if (ar->p2p) {
be98e3a4 2709 wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_GO) |
8dafb70e 2710 BIT(NL80211_IFTYPE_P2P_CLIENT);
6bbc7c35 2711 }
8dafb70e 2712
bdcd8170 2713 /* max num of ssids that can be probed during scanning */
be98e3a4
VT
2714 wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
2715 wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
2716 wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
2717 wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz;
2718 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
bdcd8170 2719
be98e3a4
VT
2720 wiphy->cipher_suites = cipher_suites;
2721 wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
bdcd8170 2722
eae9e066
RM
2723 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
2724 WIPHY_WOWLAN_DISCONNECT |
2725 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
2726 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
2727 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
2728 WIPHY_WOWLAN_4WAY_HANDSHAKE;
2729 wiphy->wowlan.n_patterns = WOW_MAX_FILTERS_PER_LIST;
2730 wiphy->wowlan.pattern_min_len = 1;
2731 wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE;
2732
10509f90
KV
2733 wiphy->max_sched_scan_ssids = 10;
2734
be98e3a4 2735 ret = wiphy_register(wiphy);
bdcd8170
KV
2736 if (ret < 0) {
2737 ath6kl_err("couldn't register wiphy device\n");
8dafb70e 2738 return ret;
bdcd8170
KV
2739 }
2740
8dafb70e 2741 return 0;
bdcd8170
KV
2742}
2743
108438bc 2744static int ath6kl_init_if_data(struct ath6kl_vif *vif)
bdcd8170 2745{
2132c69c
VT
2746 vif->aggr_cntxt = aggr_init(vif->ndev);
2747 if (!vif->aggr_cntxt) {
8dafb70e
VT
2748 ath6kl_err("failed to initialize aggr\n");
2749 return -ENOMEM;
2750 }
2751
de3ad713 2752 setup_timer(&vif->disconnect_timer, disconnect_timer_handler,
108438bc 2753 (unsigned long) vif->ndev);
10509f90
KV
2754 setup_timer(&vif->sched_scan_timer, ath6kl_wmi_sscan_timer,
2755 (unsigned long) vif);
2756
de3ad713 2757 set_bit(WMM_ENABLED, &vif->flags);
478ac027 2758 spin_lock_init(&vif->if_lock);
bdcd8170 2759
8dafb70e
VT
2760 return 0;
2761}
2762
108438bc 2763void ath6kl_deinit_if_data(struct ath6kl_vif *vif)
8dafb70e 2764{
55055976
VT
2765 struct ath6kl *ar = vif->ar;
2766
2132c69c 2767 aggr_module_destroy(vif->aggr_cntxt);
8dafb70e 2768
55055976
VT
2769 ar->avail_idx_map |= BIT(vif->fw_vif_idx);
2770
2771 if (vif->nw_type == ADHOC_NETWORK)
2772 ar->ibss_if_active = false;
2773
27929723 2774 unregister_netdevice(vif->ndev);
55055976
VT
2775
2776 ar->num_vif--;
8dafb70e
VT
2777}
2778
2779struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
55055976
VT
2780 enum nl80211_iftype type, u8 fw_vif_idx,
2781 u8 nw_type)
8dafb70e
VT
2782{
2783 struct net_device *ndev;
108438bc 2784 struct ath6kl_vif *vif;
8dafb70e 2785
55055976 2786 ndev = alloc_netdev(sizeof(*vif), name, ether_setup);
8dafb70e
VT
2787 if (!ndev)
2788 return NULL;
2789
108438bc
VT
2790 vif = netdev_priv(ndev);
2791 ndev->ieee80211_ptr = &vif->wdev;
2792 vif->wdev.wiphy = ar->wiphy;
2793 vif->ar = ar;
108438bc
VT
2794 vif->ndev = ndev;
2795 SET_NETDEV_DEV(ndev, wiphy_dev(vif->wdev.wiphy));
2796 vif->wdev.netdev = ndev;
2797 vif->wdev.iftype = type;
334234b5 2798 vif->fw_vif_idx = fw_vif_idx;
55055976 2799 vif->nw_type = vif->next_mode = nw_type;
8dafb70e 2800
55055976
VT
2801 memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
2802 if (fw_vif_idx != 0)
2803 ndev->dev_addr[0] = (ndev->dev_addr[0] ^ (1 << fw_vif_idx)) |
2804 0x2;
2805
8dafb70e
VT
2806 init_netdev(ndev);
2807
e29f25f5 2808 ath6kl_init_control_info(vif);
8dafb70e
VT
2809
2810 /* TODO: Pass interface specific pointer instead of ar */
108438bc 2811 if (ath6kl_init_if_data(vif))
8dafb70e
VT
2812 goto err;
2813
27929723 2814 if (register_netdevice(ndev))
8dafb70e
VT
2815 goto err;
2816
55055976 2817 ar->avail_idx_map &= ~BIT(fw_vif_idx);
14ee6f6b 2818 vif->sme_state = SME_DISCONNECTED;
59c98449 2819 set_bit(WLAN_ENABLED, &vif->flags);
8dafb70e 2820 ar->wlan_pwr_state = WLAN_POWER_STATE_ON;
59c98449 2821 set_bit(NETDEV_REGISTERED, &vif->flags);
8dafb70e 2822
55055976
VT
2823 if (type == NL80211_IFTYPE_ADHOC)
2824 ar->ibss_if_active = true;
2825
11f6e40d 2826 spin_lock_bh(&ar->list_lock);
990bd915 2827 list_add_tail(&vif->list, &ar->vif_list);
11f6e40d 2828 spin_unlock_bh(&ar->list_lock);
990bd915 2829
8dafb70e
VT
2830 return ndev;
2831
2832err:
27929723
VT
2833 aggr_module_destroy(vif->aggr_cntxt);
2834 free_netdev(ndev);
8dafb70e
VT
2835 return NULL;
2836}
2837
2838void ath6kl_deinit_ieee80211_hw(struct ath6kl *ar)
2839{
be98e3a4
VT
2840 wiphy_unregister(ar->wiphy);
2841 wiphy_free(ar->wiphy);
bdcd8170 2842}
This page took 0.219637 seconds and 5 git commands to generate.