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