ath6kl: Use delayed key configuration for WAPI in AP mode
[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
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 &&
4703290a
JM
1002 (key_type == TKIP_CRYPT || key_type == AES_CRYPT ||
1003 key_type == WAPI_CRYPT) && params) {
9a5b1318
JM
1004 ar->ap_mode_bkey.valid = true;
1005 ar->ap_mode_bkey.key_index = key_index;
1006 ar->ap_mode_bkey.key_type = key_type;
1007 ar->ap_mode_bkey.key_len = key->key_len;
1008 memcpy(ar->ap_mode_bkey.key, key->key, key->key_len);
59c98449 1009 if (!test_bit(CONNECTED, &vif->flags)) {
9a5b1318
JM
1010 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group "
1011 "key configuration until AP mode has been "
1012 "started\n");
1013 /*
1014 * The key will be set in ath6kl_connect_ap_mode() once
1015 * the connected event is received from the target.
1016 */
1017 return 0;
1018 }
1019 }
1020
f5938f24 1021 if (vif->next_mode == AP_NETWORK && key_type == WEP_CRYPT &&
59c98449 1022 !test_bit(CONNECTED, &vif->flags)) {
151411e8
JM
1023 /*
1024 * Store the key locally so that it can be re-configured after
1025 * the AP mode has properly started
1026 * (ath6kl_install_statioc_wep_keys).
1027 */
1028 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay WEP key configuration "
1029 "until AP mode has been started\n");
6f2a73f9
VT
1030 vif->wep_key_list[key_index].key_len = key->key_len;
1031 memcpy(vif->wep_key_list[key_index].key, key->key,
1032 key->key_len);
151411e8
JM
1033 return 0;
1034 }
1035
7cefa44f 1036 return ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx, key_index,
f3e61ece
JM
1037 key_type, key_usage, key->key_len,
1038 key->seq, key->seq_len, key->key,
1039 KEY_OP_INIT_VAL,
1040 (u8 *) mac_addr, SYNC_BOTH_WMIFLAG);
bdcd8170
KV
1041}
1042
1043static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
1044 u8 key_index, bool pairwise,
1045 const u8 *mac_addr)
1046{
1047 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
6f2a73f9 1048 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170
KV
1049
1050 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1051
990bd915 1052 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1053 return -EIO;
1054
1055 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
1056 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1057 "%s: key index %d out of bounds\n", __func__,
1058 key_index);
1059 return -ENOENT;
1060 }
1061
6f2a73f9 1062 if (!vif->keys[key_index].key_len) {
bdcd8170
KV
1063 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1064 "%s: index %d is empty\n", __func__, key_index);
1065 return 0;
1066 }
1067
6f2a73f9 1068 vif->keys[key_index].key_len = 0;
bdcd8170 1069
334234b5 1070 return ath6kl_wmi_deletekey_cmd(ar->wmi, vif->fw_vif_idx, key_index);
bdcd8170
KV
1071}
1072
1073static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
1074 u8 key_index, bool pairwise,
1075 const u8 *mac_addr, void *cookie,
1076 void (*callback) (void *cookie,
1077 struct key_params *))
1078{
6f2a73f9 1079 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170
KV
1080 struct ath6kl_key *key = NULL;
1081 struct key_params params;
1082
1083 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1084
990bd915 1085 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1086 return -EIO;
1087
1088 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
1089 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1090 "%s: key index %d out of bounds\n", __func__,
1091 key_index);
1092 return -ENOENT;
1093 }
1094
6f2a73f9 1095 key = &vif->keys[key_index];
bdcd8170
KV
1096 memset(&params, 0, sizeof(params));
1097 params.cipher = key->cipher;
1098 params.key_len = key->key_len;
1099 params.seq_len = key->seq_len;
1100 params.seq = key->seq;
1101 params.key = key->key;
1102
1103 callback(cookie, &params);
1104
1105 return key->key_len ? 0 : -ENOENT;
1106}
1107
1108static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
1109 struct net_device *ndev,
1110 u8 key_index, bool unicast,
1111 bool multicast)
1112{
1113 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
59c98449 1114 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170 1115 struct ath6kl_key *key = NULL;
bdcd8170 1116 u8 key_usage;
229ed6b5 1117 enum crypto_type key_type = NONE_CRYPT;
bdcd8170
KV
1118
1119 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1120
990bd915 1121 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1122 return -EIO;
1123
1124 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
1125 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1126 "%s: key index %d out of bounds\n",
1127 __func__, key_index);
1128 return -ENOENT;
1129 }
1130
6f2a73f9 1131 if (!vif->keys[key_index].key_len) {
bdcd8170
KV
1132 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: invalid key index %d\n",
1133 __func__, key_index);
1134 return -EINVAL;
1135 }
1136
3450334f 1137 vif->def_txkey_index = key_index;
6f2a73f9 1138 key = &vif->keys[vif->def_txkey_index];
bdcd8170 1139 key_usage = GROUP_USAGE;
3450334f 1140 if (vif->prwise_crypto == WEP_CRYPT)
bdcd8170 1141 key_usage |= TX_USAGE;
229ed6b5 1142 if (unicast)
3450334f 1143 key_type = vif->prwise_crypto;
229ed6b5 1144 if (multicast)
3450334f 1145 key_type = vif->grp_crypto;
bdcd8170 1146
f5938f24 1147 if (vif->next_mode == AP_NETWORK && !test_bit(CONNECTED, &vif->flags))
9a5b1318
JM
1148 return 0; /* Delay until AP mode has been started */
1149
f3e61ece
JM
1150 return ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx,
1151 vif->def_txkey_index,
1152 key_type, key_usage,
1153 key->key_len, key->seq, key->seq_len,
1154 key->key,
1155 KEY_OP_INIT_VAL, NULL,
1156 SYNC_BOTH_WMIFLAG);
bdcd8170
KV
1157}
1158
240d2799 1159void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl_vif *vif, u8 keyid,
bdcd8170
KV
1160 bool ismcast)
1161{
1162 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1163 "%s: keyid %d, ismcast %d\n", __func__, keyid, ismcast);
1164
240d2799 1165 cfg80211_michael_mic_failure(vif->ndev, vif->bssid,
bdcd8170
KV
1166 (ismcast ? NL80211_KEYTYPE_GROUP :
1167 NL80211_KEYTYPE_PAIRWISE), keyid, NULL,
1168 GFP_KERNEL);
1169}
1170
1171static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1172{
1173 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
990bd915 1174 struct ath6kl_vif *vif;
bdcd8170
KV
1175 int ret;
1176
1177 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: changed 0x%x\n", __func__,
1178 changed);
1179
990bd915
VT
1180 vif = ath6kl_vif_first(ar);
1181 if (!vif)
1182 return -EIO;
1183
1184 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1185 return -EIO;
1186
1187 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
1188 ret = ath6kl_wmi_set_rts_cmd(ar->wmi, wiphy->rts_threshold);
1189 if (ret != 0) {
1190 ath6kl_err("ath6kl_wmi_set_rts_cmd failed\n");
1191 return -EIO;
1192 }
1193 }
1194
1195 return 0;
1196}
1197
1198/*
1199 * The type nl80211_tx_power_setting replaces the following
1200 * data type from 2.6.36 onwards
1201*/
1202static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
1203 enum nl80211_tx_power_setting type,
b992a285 1204 int mbm)
bdcd8170
KV
1205{
1206 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
990bd915 1207 struct ath6kl_vif *vif;
bdcd8170 1208 u8 ath6kl_dbm;
b992a285 1209 int dbm = MBM_TO_DBM(mbm);
bdcd8170
KV
1210
1211 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__,
1212 type, dbm);
1213
990bd915
VT
1214 vif = ath6kl_vif_first(ar);
1215 if (!vif)
1216 return -EIO;
1217
1218 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1219 return -EIO;
1220
1221 switch (type) {
1222 case NL80211_TX_POWER_AUTOMATIC:
1223 return 0;
1224 case NL80211_TX_POWER_LIMITED:
1225 ar->tx_pwr = ath6kl_dbm = dbm;
1226 break;
1227 default:
1228 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x not supported\n",
1229 __func__, type);
1230 return -EOPNOTSUPP;
1231 }
1232
990bd915 1233 ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx, ath6kl_dbm);
bdcd8170
KV
1234
1235 return 0;
1236}
1237
1238static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
1239{
1240 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
990bd915
VT
1241 struct ath6kl_vif *vif;
1242
1243 vif = ath6kl_vif_first(ar);
1244 if (!vif)
1245 return -EIO;
bdcd8170 1246
990bd915 1247 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1248 return -EIO;
1249
59c98449 1250 if (test_bit(CONNECTED, &vif->flags)) {
bdcd8170
KV
1251 ar->tx_pwr = 0;
1252
990bd915 1253 if (ath6kl_wmi_get_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx) != 0) {
bdcd8170
KV
1254 ath6kl_err("ath6kl_wmi_get_tx_pwr_cmd failed\n");
1255 return -EIO;
1256 }
1257
1258 wait_event_interruptible_timeout(ar->event_wq, ar->tx_pwr != 0,
1259 5 * HZ);
1260
1261 if (signal_pending(current)) {
1262 ath6kl_err("target did not respond\n");
1263 return -EINTR;
1264 }
1265 }
1266
1267 *dbm = ar->tx_pwr;
1268 return 0;
1269}
1270
1271static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
1272 struct net_device *dev,
1273 bool pmgmt, int timeout)
1274{
1275 struct ath6kl *ar = ath6kl_priv(dev);
1276 struct wmi_power_mode_cmd mode;
334234b5 1277 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170
KV
1278
1279 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: pmgmt %d, timeout %d\n",
1280 __func__, pmgmt, timeout);
1281
990bd915 1282 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1283 return -EIO;
1284
1285 if (pmgmt) {
1286 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: max perf\n", __func__);
1287 mode.pwr_mode = REC_POWER;
1288 } else {
1289 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: rec power\n", __func__);
1290 mode.pwr_mode = MAX_PERF_POWER;
1291 }
1292
334234b5
VT
1293 if (ath6kl_wmi_powermode_cmd(ar->wmi, vif->fw_vif_idx,
1294 mode.pwr_mode) != 0) {
bdcd8170
KV
1295 ath6kl_err("wmi_powermode_cmd failed\n");
1296 return -EIO;
1297 }
1298
1299 return 0;
1300}
1301
55055976
VT
1302static struct net_device *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
1303 char *name,
1304 enum nl80211_iftype type,
1305 u32 *flags,
1306 struct vif_params *params)
1307{
1308 struct ath6kl *ar = wiphy_priv(wiphy);
1309 struct net_device *ndev;
1310 u8 if_idx, nw_type;
1311
71f96ee6 1312 if (ar->num_vif == ar->vif_max) {
55055976
VT
1313 ath6kl_err("Reached maximum number of supported vif\n");
1314 return ERR_PTR(-EINVAL);
1315 }
1316
1317 if (!ath6kl_is_valid_iftype(ar, type, &if_idx, &nw_type)) {
1318 ath6kl_err("Not a supported interface type\n");
1319 return ERR_PTR(-EINVAL);
1320 }
1321
1322 ndev = ath6kl_interface_add(ar, name, type, if_idx, nw_type);
1323 if (!ndev)
1324 return ERR_PTR(-ENOMEM);
1325
1326 ar->num_vif++;
1327
1328 return ndev;
1329}
1330
1331static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy,
1332 struct net_device *ndev)
1333{
1334 struct ath6kl *ar = wiphy_priv(wiphy);
1335 struct ath6kl_vif *vif = netdev_priv(ndev);
1336
11f6e40d 1337 spin_lock_bh(&ar->list_lock);
55055976 1338 list_del(&vif->list);
11f6e40d 1339 spin_unlock_bh(&ar->list_lock);
55055976
VT
1340
1341 ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag));
1342
1343 ath6kl_deinit_if_data(vif);
1344
1345 return 0;
1346}
1347
bdcd8170
KV
1348static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
1349 struct net_device *ndev,
1350 enum nl80211_iftype type, u32 *flags,
1351 struct vif_params *params)
1352{
f5938f24 1353 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170
KV
1354
1355 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type);
1356
bdcd8170
KV
1357 switch (type) {
1358 case NL80211_IFTYPE_STATION:
f5938f24 1359 vif->next_mode = INFRA_NETWORK;
bdcd8170
KV
1360 break;
1361 case NL80211_IFTYPE_ADHOC:
f5938f24 1362 vif->next_mode = ADHOC_NETWORK;
bdcd8170 1363 break;
6e4604c8 1364 case NL80211_IFTYPE_AP:
f5938f24 1365 vif->next_mode = AP_NETWORK;
6e4604c8 1366 break;
6b5e5d25 1367 case NL80211_IFTYPE_P2P_CLIENT:
f5938f24 1368 vif->next_mode = INFRA_NETWORK;
6b5e5d25
JM
1369 break;
1370 case NL80211_IFTYPE_P2P_GO:
f5938f24 1371 vif->next_mode = AP_NETWORK;
6b5e5d25 1372 break;
bdcd8170
KV
1373 default:
1374 ath6kl_err("invalid interface type %u\n", type);
1375 return -EOPNOTSUPP;
1376 }
1377
551959d8 1378 vif->wdev.iftype = type;
bdcd8170
KV
1379
1380 return 0;
1381}
1382
1383static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
1384 struct net_device *dev,
1385 struct cfg80211_ibss_params *ibss_param)
1386{
1387 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 1388 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170
KV
1389 int status;
1390
990bd915 1391 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1392 return -EIO;
1393
3450334f
VT
1394 vif->ssid_len = ibss_param->ssid_len;
1395 memcpy(vif->ssid, ibss_param->ssid, vif->ssid_len);
bdcd8170
KV
1396
1397 if (ibss_param->channel)
f74bac54 1398 vif->ch_hint = ibss_param->channel->center_freq;
bdcd8170
KV
1399
1400 if (ibss_param->channel_fixed) {
1401 /*
1402 * TODO: channel_fixed: The channel should be fixed, do not
1403 * search for IBSSs to join on other channels. Target
1404 * firmware does not support this feature, needs to be
1405 * updated.
1406 */
1407 return -EOPNOTSUPP;
1408 }
1409
8c8b65e3 1410 memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
bdcd8170 1411 if (ibss_param->bssid && !is_broadcast_ether_addr(ibss_param->bssid))
8c8b65e3
VT
1412 memcpy(vif->req_bssid, ibss_param->bssid,
1413 sizeof(vif->req_bssid));
bdcd8170 1414
240d2799 1415 ath6kl_set_wpa_version(vif, 0);
bdcd8170 1416
240d2799 1417 status = ath6kl_set_auth_type(vif, NL80211_AUTHTYPE_OPEN_SYSTEM);
bdcd8170
KV
1418 if (status)
1419 return status;
1420
1421 if (ibss_param->privacy) {
240d2799
VT
1422 ath6kl_set_cipher(vif, WLAN_CIPHER_SUITE_WEP40, true);
1423 ath6kl_set_cipher(vif, WLAN_CIPHER_SUITE_WEP40, false);
bdcd8170 1424 } else {
240d2799
VT
1425 ath6kl_set_cipher(vif, 0, true);
1426 ath6kl_set_cipher(vif, 0, false);
bdcd8170
KV
1427 }
1428
f5938f24 1429 vif->nw_type = vif->next_mode;
bdcd8170
KV
1430
1431 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1432 "%s: connect called with authmode %d dot11 auth %d"
1433 " PW crypto %d PW crypto len %d GRP crypto %d"
1434 " GRP crypto len %d channel hint %u\n",
1435 __func__,
3450334f
VT
1436 vif->auth_mode, vif->dot11_auth_mode, vif->prwise_crypto,
1437 vif->prwise_crypto_len, vif->grp_crypto,
f74bac54 1438 vif->grp_crypto_len, vif->ch_hint);
bdcd8170 1439
334234b5 1440 status = ath6kl_wmi_connect_cmd(ar->wmi, vif->fw_vif_idx, vif->nw_type,
3450334f
VT
1441 vif->dot11_auth_mode, vif->auth_mode,
1442 vif->prwise_crypto,
1443 vif->prwise_crypto_len,
1444 vif->grp_crypto, vif->grp_crypto_len,
1445 vif->ssid_len, vif->ssid,
f74bac54 1446 vif->req_bssid, vif->ch_hint,
bdcd8170 1447 ar->connect_ctrl_flags);
59c98449 1448 set_bit(CONNECT_PEND, &vif->flags);
bdcd8170
KV
1449
1450 return 0;
1451}
1452
1453static int ath6kl_cfg80211_leave_ibss(struct wiphy *wiphy,
1454 struct net_device *dev)
1455{
3450334f 1456 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170 1457
990bd915 1458 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1459 return -EIO;
1460
240d2799 1461 ath6kl_disconnect(vif);
3450334f
VT
1462 memset(vif->ssid, 0, sizeof(vif->ssid));
1463 vif->ssid_len = 0;
bdcd8170
KV
1464
1465 return 0;
1466}
1467
1468static const u32 cipher_suites[] = {
1469 WLAN_CIPHER_SUITE_WEP40,
1470 WLAN_CIPHER_SUITE_WEP104,
1471 WLAN_CIPHER_SUITE_TKIP,
1472 WLAN_CIPHER_SUITE_CCMP,
837cb97e 1473 CCKM_KRK_CIPHER_SUITE,
5e07021e 1474 WLAN_CIPHER_SUITE_SMS4,
bdcd8170
KV
1475};
1476
1477static bool is_rate_legacy(s32 rate)
1478{
1479 static const s32 legacy[] = { 1000, 2000, 5500, 11000,
1480 6000, 9000, 12000, 18000, 24000,
1481 36000, 48000, 54000
1482 };
1483 u8 i;
1484
1485 for (i = 0; i < ARRAY_SIZE(legacy); i++)
1486 if (rate == legacy[i])
1487 return true;
1488
1489 return false;
1490}
1491
1492static bool is_rate_ht20(s32 rate, u8 *mcs, bool *sgi)
1493{
1494 static const s32 ht20[] = { 6500, 13000, 19500, 26000, 39000,
1495 52000, 58500, 65000, 72200
1496 };
1497 u8 i;
1498
1499 for (i = 0; i < ARRAY_SIZE(ht20); i++) {
1500 if (rate == ht20[i]) {
1501 if (i == ARRAY_SIZE(ht20) - 1)
1502 /* last rate uses sgi */
1503 *sgi = true;
1504 else
1505 *sgi = false;
1506
1507 *mcs = i;
1508 return true;
1509 }
1510 }
1511 return false;
1512}
1513
1514static bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi)
1515{
1516 static const s32 ht40[] = { 13500, 27000, 40500, 54000,
1517 81000, 108000, 121500, 135000,
1518 150000
1519 };
1520 u8 i;
1521
1522 for (i = 0; i < ARRAY_SIZE(ht40); i++) {
1523 if (rate == ht40[i]) {
1524 if (i == ARRAY_SIZE(ht40) - 1)
1525 /* last rate uses sgi */
1526 *sgi = true;
1527 else
1528 *sgi = false;
1529
1530 *mcs = i;
1531 return true;
1532 }
1533 }
1534
1535 return false;
1536}
1537
1538static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
1539 u8 *mac, struct station_info *sinfo)
1540{
1541 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 1542 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170
KV
1543 long left;
1544 bool sgi;
1545 s32 rate;
1546 int ret;
1547 u8 mcs;
1548
8c8b65e3 1549 if (memcmp(mac, vif->bssid, ETH_ALEN) != 0)
bdcd8170
KV
1550 return -ENOENT;
1551
1552 if (down_interruptible(&ar->sem))
1553 return -EBUSY;
1554
b95907a7 1555 set_bit(STATS_UPDATE_PEND, &vif->flags);
bdcd8170 1556
334234b5 1557 ret = ath6kl_wmi_get_stats_cmd(ar->wmi, vif->fw_vif_idx);
bdcd8170
KV
1558
1559 if (ret != 0) {
1560 up(&ar->sem);
1561 return -EIO;
1562 }
1563
1564 left = wait_event_interruptible_timeout(ar->event_wq,
1565 !test_bit(STATS_UPDATE_PEND,
b95907a7 1566 &vif->flags),
bdcd8170
KV
1567 WMI_TIMEOUT);
1568
1569 up(&ar->sem);
1570
1571 if (left == 0)
1572 return -ETIMEDOUT;
1573 else if (left < 0)
1574 return left;
1575
b95907a7
VT
1576 if (vif->target_stats.rx_byte) {
1577 sinfo->rx_bytes = vif->target_stats.rx_byte;
bdcd8170 1578 sinfo->filled |= STATION_INFO_RX_BYTES;
b95907a7 1579 sinfo->rx_packets = vif->target_stats.rx_pkt;
bdcd8170
KV
1580 sinfo->filled |= STATION_INFO_RX_PACKETS;
1581 }
1582
b95907a7
VT
1583 if (vif->target_stats.tx_byte) {
1584 sinfo->tx_bytes = vif->target_stats.tx_byte;
bdcd8170 1585 sinfo->filled |= STATION_INFO_TX_BYTES;
b95907a7 1586 sinfo->tx_packets = vif->target_stats.tx_pkt;
bdcd8170
KV
1587 sinfo->filled |= STATION_INFO_TX_PACKETS;
1588 }
1589
b95907a7 1590 sinfo->signal = vif->target_stats.cs_rssi;
bdcd8170
KV
1591 sinfo->filled |= STATION_INFO_SIGNAL;
1592
b95907a7 1593 rate = vif->target_stats.tx_ucast_rate;
bdcd8170
KV
1594
1595 if (is_rate_legacy(rate)) {
1596 sinfo->txrate.legacy = rate / 100;
1597 } else if (is_rate_ht20(rate, &mcs, &sgi)) {
1598 if (sgi) {
1599 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
1600 sinfo->txrate.mcs = mcs - 1;
1601 } else {
1602 sinfo->txrate.mcs = mcs;
1603 }
1604
1605 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
1606 } else if (is_rate_ht40(rate, &mcs, &sgi)) {
1607 if (sgi) {
1608 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
1609 sinfo->txrate.mcs = mcs - 1;
1610 } else {
1611 sinfo->txrate.mcs = mcs;
1612 }
1613
1614 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
1615 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
1616 } else {
9a730834
KV
1617 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1618 "invalid rate from stats: %d\n", rate);
1619 ath6kl_debug_war(ar, ATH6KL_WAR_INVALID_RATE);
bdcd8170
KV
1620 return 0;
1621 }
1622
1623 sinfo->filled |= STATION_INFO_TX_BITRATE;
1624
59c98449
VT
1625 if (test_bit(CONNECTED, &vif->flags) &&
1626 test_bit(DTIM_PERIOD_AVAIL, &vif->flags) &&
f5938f24 1627 vif->nw_type == INFRA_NETWORK) {
32c10874
JM
1628 sinfo->filled |= STATION_INFO_BSS_PARAM;
1629 sinfo->bss_param.flags = 0;
cf5333d7
VT
1630 sinfo->bss_param.dtim_period = vif->assoc_bss_dtim_period;
1631 sinfo->bss_param.beacon_interval = vif->assoc_bss_beacon_int;
32c10874
JM
1632 }
1633
bdcd8170
KV
1634 return 0;
1635}
1636
1637static int ath6kl_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1638 struct cfg80211_pmksa *pmksa)
1639{
1640 struct ath6kl *ar = ath6kl_priv(netdev);
334234b5
VT
1641 struct ath6kl_vif *vif = netdev_priv(netdev);
1642
1643 return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx, pmksa->bssid,
bdcd8170
KV
1644 pmksa->pmkid, true);
1645}
1646
1647static int ath6kl_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1648 struct cfg80211_pmksa *pmksa)
1649{
1650 struct ath6kl *ar = ath6kl_priv(netdev);
334234b5
VT
1651 struct ath6kl_vif *vif = netdev_priv(netdev);
1652
1653 return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx, pmksa->bssid,
bdcd8170
KV
1654 pmksa->pmkid, false);
1655}
1656
1657static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
1658{
1659 struct ath6kl *ar = ath6kl_priv(netdev);
59c98449
VT
1660 struct ath6kl_vif *vif = netdev_priv(netdev);
1661
1662 if (test_bit(CONNECTED, &vif->flags))
334234b5
VT
1663 return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx,
1664 vif->bssid, NULL, false);
bdcd8170
KV
1665 return 0;
1666}
1667
6cb3c714
RM
1668static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
1669{
1670 struct ath6kl_vif *vif;
1671 int ret, pos, left;
1672 u32 filter = 0;
1673 u16 i;
1674 u8 mask[WOW_MASK_SIZE];
1675
1676 vif = ath6kl_vif_first(ar);
1677 if (!vif)
1678 return -EIO;
1679
1680 if (!ath6kl_cfg80211_ready(vif))
1681 return -EIO;
1682
1683 if (!test_bit(CONNECTED, &vif->flags))
1684 return -EINVAL;
1685
1686 /* Clear existing WOW patterns */
1687 for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++)
1688 ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx,
1689 WOW_LIST_ID, i);
1690 /* Configure new WOW patterns */
1691 for (i = 0; i < wow->n_patterns; i++) {
1692
1693 /*
1694 * Convert given nl80211 specific mask value to equivalent
1695 * driver specific mask value and send it to the chip along
1696 * with patterns. For example, If the mask value defined in
1697 * struct cfg80211_wowlan is 0xA (equivalent binary is 1010),
1698 * then equivalent driver specific mask value is
1699 * "0xFF 0x00 0xFF 0x00".
1700 */
1701 memset(&mask, 0, sizeof(mask));
1702 for (pos = 0; pos < wow->patterns[i].pattern_len; pos++) {
1703 if (wow->patterns[i].mask[pos / 8] & (0x1 << (pos % 8)))
1704 mask[pos] = 0xFF;
1705 }
1706 /*
1707 * Note: Pattern's offset is not passed as part of wowlan
1708 * parameter from CFG layer. So it's always passed as ZERO
1709 * to the firmware. It means, given WOW patterns are always
1710 * matched from the first byte of received pkt in the firmware.
1711 */
1712 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1713 vif->fw_vif_idx, WOW_LIST_ID,
1714 wow->patterns[i].pattern_len,
1715 0 /* pattern offset */,
1716 wow->patterns[i].pattern, mask);
1717 if (ret)
1718 return ret;
1719 }
1720
1721 if (wow->disconnect)
1722 filter |= WOW_FILTER_OPTION_NWK_DISASSOC;
1723
1724 if (wow->magic_pkt)
1725 filter |= WOW_FILTER_OPTION_MAGIC_PACKET;
1726
1727 if (wow->gtk_rekey_failure)
1728 filter |= WOW_FILTER_OPTION_GTK_ERROR;
1729
1730 if (wow->eap_identity_req)
1731 filter |= WOW_FILTER_OPTION_EAP_REQ;
1732
1733 if (wow->four_way_handshake)
1734 filter |= WOW_FILTER_OPTION_8021X_4WAYHS;
1735
1736 ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
1737 ATH6KL_WOW_MODE_ENABLE,
1738 filter,
1739 WOW_HOST_REQ_DELAY);
1740 if (ret)
1741 return ret;
1742
1743 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
1744 ATH6KL_HOST_MODE_ASLEEP);
1745 if (ret)
1746 return ret;
1747
1748 if (ar->tx_pending[ar->ctrl_ep]) {
1749 left = wait_event_interruptible_timeout(ar->event_wq,
1750 ar->tx_pending[ar->ctrl_ep] == 0, WMI_TIMEOUT);
1751 if (left == 0) {
1752 ath6kl_warn("clear wmi ctrl data timeout\n");
1753 ret = -ETIMEDOUT;
1754 } else if (left < 0) {
1755 ath6kl_warn("clear wmi ctrl data failed: %d\n", left);
1756 ret = left;
1757 }
1758 }
1759
1760 return ret;
1761}
1762
1763static int ath6kl_wow_resume(struct ath6kl *ar)
1764{
1765 struct ath6kl_vif *vif;
1766 int ret;
1767
1768 vif = ath6kl_vif_first(ar);
1769 if (!vif)
1770 return -EIO;
1771
1772 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
1773 ATH6KL_HOST_MODE_AWAKE);
1774 return ret;
1775}
1776
52d81a68 1777int ath6kl_cfg80211_suspend(struct ath6kl *ar,
0f60e9f4
RM
1778 enum ath6kl_cfg_suspend_mode mode,
1779 struct cfg80211_wowlan *wow)
52d81a68
KV
1780{
1781 int ret;
1782
52d81a68 1783 switch (mode) {
d7c44e0b
RM
1784 case ATH6KL_CFG_SUSPEND_WOW:
1785
1786 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "wow mode suspend\n");
1787
1788 /* Flush all non control pkts in TX path */
1789 ath6kl_tx_data_cleanup(ar);
1790
1791 ret = ath6kl_wow_suspend(ar, wow);
1792 if (ret) {
1793 ath6kl_err("wow suspend failed: %d\n", ret);
1794 return ret;
1795 }
1796 ar->state = ATH6KL_STATE_WOW;
1797 break;
1798
52d81a68 1799 case ATH6KL_CFG_SUSPEND_DEEPSLEEP:
524441e3
RM
1800
1801 ath6kl_cfg80211_stop(ar);
1802
52d81a68
KV
1803 /* save the current power mode before enabling power save */
1804 ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
1805
1806 ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER);
1807 if (ret) {
1808 ath6kl_warn("wmi powermode command failed during suspend: %d\n",
1809 ret);
1810 }
1811
76a9fbe2
KV
1812 ar->state = ATH6KL_STATE_DEEPSLEEP;
1813
52d81a68 1814 break;
b4b2a0b1
KV
1815
1816 case ATH6KL_CFG_SUSPEND_CUTPOWER:
524441e3
RM
1817
1818 ath6kl_cfg80211_stop(ar);
1819
b4b2a0b1
KV
1820 if (ar->state == ATH6KL_STATE_OFF) {
1821 ath6kl_dbg(ATH6KL_DBG_SUSPEND,
1822 "suspend hw off, no action for cutpower\n");
1823 break;
1824 }
1825
1826 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "suspend cutting power\n");
1827
1828 ret = ath6kl_init_hw_stop(ar);
1829 if (ret) {
1830 ath6kl_warn("failed to stop hw during suspend: %d\n",
1831 ret);
1832 }
1833
1834 ar->state = ATH6KL_STATE_CUTPOWER;
1835
1836 break;
1837
1838 default:
1839 break;
52d81a68
KV
1840 }
1841
1842 return 0;
1843}
1844
1845int ath6kl_cfg80211_resume(struct ath6kl *ar)
1846{
76a9fbe2
KV
1847 int ret;
1848
1849 switch (ar->state) {
d7c44e0b
RM
1850 case ATH6KL_STATE_WOW:
1851 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "wow mode resume\n");
1852
1853 ret = ath6kl_wow_resume(ar);
1854 if (ret) {
1855 ath6kl_warn("wow mode resume failed: %d\n", ret);
1856 return ret;
1857 }
1858
1859 ar->state = ATH6KL_STATE_ON;
1860 break;
1861
76a9fbe2
KV
1862 case ATH6KL_STATE_DEEPSLEEP:
1863 if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) {
1864 ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0,
1865 ar->wmi->saved_pwr_mode);
1866 if (ret) {
1867 ath6kl_warn("wmi powermode command failed during resume: %d\n",
1868 ret);
1869 }
1870 }
1871
1872 ar->state = ATH6KL_STATE_ON;
1873
1874 break;
1875
b4b2a0b1
KV
1876 case ATH6KL_STATE_CUTPOWER:
1877 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "resume restoring power\n");
1878
1879 ret = ath6kl_init_hw_start(ar);
1880 if (ret) {
1881 ath6kl_warn("Failed to boot hw in resume: %d\n", ret);
1882 return ret;
1883 }
d7c44e0b 1884 break;
b4b2a0b1 1885
76a9fbe2
KV
1886 default:
1887 break;
52d81a68
KV
1888 }
1889
1890 return 0;
1891}
1892
abcb344b 1893#ifdef CONFIG_PM
52d81a68
KV
1894
1895/* hif layer decides what suspend mode to use */
1896static int __ath6kl_cfg80211_suspend(struct wiphy *wiphy,
abcb344b
KV
1897 struct cfg80211_wowlan *wow)
1898{
1899 struct ath6kl *ar = wiphy_priv(wiphy);
1900
0f60e9f4 1901 return ath6kl_hif_suspend(ar, wow);
abcb344b 1902}
aa6cffc1 1903
52d81a68 1904static int __ath6kl_cfg80211_resume(struct wiphy *wiphy)
aa6cffc1
CN
1905{
1906 struct ath6kl *ar = wiphy_priv(wiphy);
1907
1908 return ath6kl_hif_resume(ar);
1909}
a918fb3c
RM
1910
1911/*
1912 * FIXME: WOW suspend mode is selected if the host sdio controller supports
1913 * both sdio irq wake up and keep power. The target pulls sdio data line to
1914 * wake up the host when WOW pattern matches. This causes sdio irq handler
1915 * is being called in the host side which internally hits ath6kl's RX path.
1916 *
1917 * Since sdio interrupt is not disabled, RX path executes even before
1918 * the host executes the actual resume operation from PM module.
1919 *
1920 * In the current scenario, WOW resume should happen before start processing
1921 * any data from the target. So It's required to perform WOW resume in RX path.
1922 * Ideally we should perform WOW resume only in the actual platform
1923 * resume path. This area needs bit rework to avoid WOW resume in RX path.
1924 *
1925 * ath6kl_check_wow_status() is called from ath6kl_rx().
1926 */
1927void ath6kl_check_wow_status(struct ath6kl *ar)
1928{
1929 if (ar->state == ATH6KL_STATE_WOW)
1930 ath6kl_cfg80211_resume(ar);
1931}
1932
1933#else
1934
1935void ath6kl_check_wow_status(struct ath6kl *ar)
1936{
1937}
abcb344b
KV
1938#endif
1939
6a7c9bad
JM
1940static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev,
1941 struct ieee80211_channel *chan,
1942 enum nl80211_channel_type channel_type)
1943{
cf5333d7 1944 struct ath6kl_vif *vif = netdev_priv(dev);
6a7c9bad 1945
990bd915 1946 if (!ath6kl_cfg80211_ready(vif))
6a7c9bad
JM
1947 return -EIO;
1948
1949 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n",
1950 __func__, chan->center_freq, chan->hw_value);
cf5333d7 1951 vif->next_chan = chan->center_freq;
6a7c9bad
JM
1952
1953 return 0;
1954}
1955
8bdfbf40
JM
1956static bool ath6kl_is_p2p_ie(const u8 *pos)
1957{
1958 return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
1959 pos[2] == 0x50 && pos[3] == 0x6f &&
1960 pos[4] == 0x9a && pos[5] == 0x09;
1961}
1962
334234b5
VT
1963static int ath6kl_set_ap_probe_resp_ies(struct ath6kl_vif *vif,
1964 const u8 *ies, size_t ies_len)
8bdfbf40 1965{
334234b5 1966 struct ath6kl *ar = vif->ar;
8bdfbf40
JM
1967 const u8 *pos;
1968 u8 *buf = NULL;
1969 size_t len = 0;
1970 int ret;
1971
1972 /*
1973 * Filter out P2P IE(s) since they will be included depending on
1974 * the Probe Request frame in ath6kl_send_go_probe_resp().
1975 */
1976
1977 if (ies && ies_len) {
1978 buf = kmalloc(ies_len, GFP_KERNEL);
1979 if (buf == NULL)
1980 return -ENOMEM;
1981 pos = ies;
1982 while (pos + 1 < ies + ies_len) {
1983 if (pos + 2 + pos[1] > ies + ies_len)
1984 break;
1985 if (!ath6kl_is_p2p_ie(pos)) {
1986 memcpy(buf + len, pos, 2 + pos[1]);
1987 len += 2 + pos[1];
1988 }
1989 pos += 2 + pos[1];
1990 }
1991 }
1992
334234b5
VT
1993 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
1994 WMI_FRAME_PROBE_RESP, buf, len);
8bdfbf40
JM
1995 kfree(buf);
1996 return ret;
1997}
1998
6a7c9bad
JM
1999static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
2000 struct beacon_parameters *info, bool add)
2001{
2002 struct ath6kl *ar = ath6kl_priv(dev);
3450334f 2003 struct ath6kl_vif *vif = netdev_priv(dev);
6a7c9bad
JM
2004 struct ieee80211_mgmt *mgmt;
2005 u8 *ies;
2006 int ies_len;
2007 struct wmi_connect_cmd p;
2008 int res;
be5abaaf 2009 int i, ret;
6a7c9bad
JM
2010
2011 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: add=%d\n", __func__, add);
2012
990bd915 2013 if (!ath6kl_cfg80211_ready(vif))
6a7c9bad
JM
2014 return -EIO;
2015
f5938f24 2016 if (vif->next_mode != AP_NETWORK)
6a7c9bad
JM
2017 return -EOPNOTSUPP;
2018
2019 if (info->beacon_ies) {
334234b5
VT
2020 res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2021 WMI_FRAME_BEACON,
6a7c9bad
JM
2022 info->beacon_ies,
2023 info->beacon_ies_len);
2024 if (res)
2025 return res;
2026 }
2027 if (info->proberesp_ies) {
334234b5 2028 res = ath6kl_set_ap_probe_resp_ies(vif, info->proberesp_ies,
8bdfbf40 2029 info->proberesp_ies_len);
6a7c9bad
JM
2030 if (res)
2031 return res;
2032 }
2033 if (info->assocresp_ies) {
334234b5
VT
2034 res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2035 WMI_FRAME_ASSOC_RESP,
6a7c9bad
JM
2036 info->assocresp_ies,
2037 info->assocresp_ies_len);
2038 if (res)
2039 return res;
2040 }
2041
2042 if (!add)
2043 return 0;
2044
9a5b1318
JM
2045 ar->ap_mode_bkey.valid = false;
2046
6a7c9bad
JM
2047 /* TODO:
2048 * info->interval
2049 * info->dtim_period
2050 */
2051
2052 if (info->head == NULL)
2053 return -EINVAL;
2054 mgmt = (struct ieee80211_mgmt *) info->head;
2055 ies = mgmt->u.beacon.variable;
2056 if (ies > info->head + info->head_len)
2057 return -EINVAL;
2058 ies_len = info->head + info->head_len - ies;
2059
2060 if (info->ssid == NULL)
2061 return -EINVAL;
3450334f
VT
2062 memcpy(vif->ssid, info->ssid, info->ssid_len);
2063 vif->ssid_len = info->ssid_len;
6a7c9bad
JM
2064 if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
2065 return -EOPNOTSUPP; /* TODO */
2066
be5abaaf
VT
2067 ret = ath6kl_set_auth_type(vif, info->auth_type);
2068 if (ret)
2069 return ret;
6a7c9bad
JM
2070
2071 memset(&p, 0, sizeof(p));
2072
2073 for (i = 0; i < info->crypto.n_akm_suites; i++) {
2074 switch (info->crypto.akm_suites[i]) {
2075 case WLAN_AKM_SUITE_8021X:
2076 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1)
2077 p.auth_mode |= WPA_AUTH;
2078 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2)
2079 p.auth_mode |= WPA2_AUTH;
2080 break;
2081 case WLAN_AKM_SUITE_PSK:
2082 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1)
2083 p.auth_mode |= WPA_PSK_AUTH;
2084 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2)
2085 p.auth_mode |= WPA2_PSK_AUTH;
2086 break;
2087 }
2088 }
2089 if (p.auth_mode == 0)
2090 p.auth_mode = NONE_AUTH;
3450334f 2091 vif->auth_mode = p.auth_mode;
6a7c9bad
JM
2092
2093 for (i = 0; i < info->crypto.n_ciphers_pairwise; i++) {
2094 switch (info->crypto.ciphers_pairwise[i]) {
2095 case WLAN_CIPHER_SUITE_WEP40:
2096 case WLAN_CIPHER_SUITE_WEP104:
2097 p.prwise_crypto_type |= WEP_CRYPT;
2098 break;
2099 case WLAN_CIPHER_SUITE_TKIP:
2100 p.prwise_crypto_type |= TKIP_CRYPT;
2101 break;
2102 case WLAN_CIPHER_SUITE_CCMP:
2103 p.prwise_crypto_type |= AES_CRYPT;
2104 break;
b8214df1
DS
2105 case WLAN_CIPHER_SUITE_SMS4:
2106 p.prwise_crypto_type |= WAPI_CRYPT;
2107 break;
6a7c9bad
JM
2108 }
2109 }
229ed6b5 2110 if (p.prwise_crypto_type == 0) {
6a7c9bad 2111 p.prwise_crypto_type = NONE_CRYPT;
240d2799 2112 ath6kl_set_cipher(vif, 0, true);
229ed6b5 2113 } else if (info->crypto.n_ciphers_pairwise == 1)
240d2799 2114 ath6kl_set_cipher(vif, info->crypto.ciphers_pairwise[0], true);
6a7c9bad
JM
2115
2116 switch (info->crypto.cipher_group) {
2117 case WLAN_CIPHER_SUITE_WEP40:
2118 case WLAN_CIPHER_SUITE_WEP104:
2119 p.grp_crypto_type = WEP_CRYPT;
2120 break;
2121 case WLAN_CIPHER_SUITE_TKIP:
2122 p.grp_crypto_type = TKIP_CRYPT;
2123 break;
2124 case WLAN_CIPHER_SUITE_CCMP:
2125 p.grp_crypto_type = AES_CRYPT;
2126 break;
b8214df1
DS
2127 case WLAN_CIPHER_SUITE_SMS4:
2128 p.grp_crypto_type = WAPI_CRYPT;
2129 break;
6a7c9bad
JM
2130 default:
2131 p.grp_crypto_type = NONE_CRYPT;
2132 break;
2133 }
240d2799 2134 ath6kl_set_cipher(vif, info->crypto.cipher_group, false);
6a7c9bad
JM
2135
2136 p.nw_type = AP_NETWORK;
f5938f24 2137 vif->nw_type = vif->next_mode;
6a7c9bad 2138
3450334f
VT
2139 p.ssid_len = vif->ssid_len;
2140 memcpy(p.ssid, vif->ssid, vif->ssid_len);
2141 p.dot11_auth_mode = vif->dot11_auth_mode;
cf5333d7 2142 p.ch = cpu_to_le16(vif->next_chan);
6a7c9bad 2143
334234b5 2144 res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p);
9a5b1318
JM
2145 if (res < 0)
2146 return res;
2147
2148 return 0;
6a7c9bad
JM
2149}
2150
2151static int ath6kl_add_beacon(struct wiphy *wiphy, struct net_device *dev,
2152 struct beacon_parameters *info)
2153{
2154 return ath6kl_ap_beacon(wiphy, dev, info, true);
2155}
2156
2157static int ath6kl_set_beacon(struct wiphy *wiphy, struct net_device *dev,
2158 struct beacon_parameters *info)
2159{
2160 return ath6kl_ap_beacon(wiphy, dev, info, false);
2161}
2162
2163static int ath6kl_del_beacon(struct wiphy *wiphy, struct net_device *dev)
2164{
2165 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 2166 struct ath6kl_vif *vif = netdev_priv(dev);
6a7c9bad 2167
f5938f24 2168 if (vif->nw_type != AP_NETWORK)
6a7c9bad 2169 return -EOPNOTSUPP;
59c98449 2170 if (!test_bit(CONNECTED, &vif->flags))
6a7c9bad
JM
2171 return -ENOTCONN;
2172
334234b5 2173 ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
59c98449 2174 clear_bit(CONNECTED, &vif->flags);
6a7c9bad
JM
2175
2176 return 0;
2177}
2178
23875136
JM
2179static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
2180 u8 *mac, struct station_parameters *params)
2181{
2182 struct ath6kl *ar = ath6kl_priv(dev);
f5938f24 2183 struct ath6kl_vif *vif = netdev_priv(dev);
23875136 2184
f5938f24 2185 if (vif->nw_type != AP_NETWORK)
23875136
JM
2186 return -EOPNOTSUPP;
2187
2188 /* Use this only for authorizing/unauthorizing a station */
2189 if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
2190 return -EOPNOTSUPP;
2191
2192 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
334234b5
VT
2193 return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx,
2194 WMI_AP_MLME_AUTHORIZE, mac, 0);
2195 return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx,
2196 WMI_AP_MLME_UNAUTHORIZE, mac, 0);
23875136
JM
2197}
2198
63fa1e0c
JM
2199static int ath6kl_remain_on_channel(struct wiphy *wiphy,
2200 struct net_device *dev,
2201 struct ieee80211_channel *chan,
2202 enum nl80211_channel_type channel_type,
2203 unsigned int duration,
2204 u64 *cookie)
2205{
2206 struct ath6kl *ar = ath6kl_priv(dev);
334234b5 2207 struct ath6kl_vif *vif = netdev_priv(dev);
1052261e 2208 u32 id;
63fa1e0c
JM
2209
2210 /* TODO: if already pending or ongoing remain-on-channel,
2211 * return -EBUSY */
1052261e
JM
2212 id = ++vif->last_roc_id;
2213 if (id == 0) {
2214 /* Do not use 0 as the cookie value */
2215 id = ++vif->last_roc_id;
2216 }
2217 *cookie = id;
63fa1e0c 2218
334234b5
VT
2219 return ath6kl_wmi_remain_on_chnl_cmd(ar->wmi, vif->fw_vif_idx,
2220 chan->center_freq, duration);
63fa1e0c
JM
2221}
2222
2223static int ath6kl_cancel_remain_on_channel(struct wiphy *wiphy,
2224 struct net_device *dev,
2225 u64 cookie)
2226{
2227 struct ath6kl *ar = ath6kl_priv(dev);
334234b5 2228 struct ath6kl_vif *vif = netdev_priv(dev);
63fa1e0c 2229
1052261e 2230 if (cookie != vif->last_roc_id)
63fa1e0c 2231 return -ENOENT;
1052261e 2232 vif->last_cancel_roc_id = cookie;
63fa1e0c 2233
334234b5 2234 return ath6kl_wmi_cancel_remain_on_chnl_cmd(ar->wmi, vif->fw_vif_idx);
63fa1e0c
JM
2235}
2236
334234b5
VT
2237static int ath6kl_send_go_probe_resp(struct ath6kl_vif *vif,
2238 const u8 *buf, size_t len,
2239 unsigned int freq)
8bdfbf40 2240{
334234b5 2241 struct ath6kl *ar = vif->ar;
8bdfbf40
JM
2242 const u8 *pos;
2243 u8 *p2p;
2244 int p2p_len;
2245 int ret;
2246 const struct ieee80211_mgmt *mgmt;
2247
2248 mgmt = (const struct ieee80211_mgmt *) buf;
2249
2250 /* Include P2P IE(s) from the frame generated in user space. */
2251
2252 p2p = kmalloc(len, GFP_KERNEL);
2253 if (p2p == NULL)
2254 return -ENOMEM;
2255 p2p_len = 0;
2256
2257 pos = mgmt->u.probe_resp.variable;
2258 while (pos + 1 < buf + len) {
2259 if (pos + 2 + pos[1] > buf + len)
2260 break;
2261 if (ath6kl_is_p2p_ie(pos)) {
2262 memcpy(p2p + p2p_len, pos, 2 + pos[1]);
2263 p2p_len += 2 + pos[1];
2264 }
2265 pos += 2 + pos[1];
2266 }
2267
334234b5
VT
2268 ret = ath6kl_wmi_send_probe_response_cmd(ar->wmi, vif->fw_vif_idx, freq,
2269 mgmt->da, p2p, p2p_len);
8bdfbf40
JM
2270 kfree(p2p);
2271 return ret;
2272}
2273
8a6c8060
JM
2274static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
2275 struct ieee80211_channel *chan, bool offchan,
2276 enum nl80211_channel_type channel_type,
2277 bool channel_type_valid, unsigned int wait,
e247bd90
JB
2278 const u8 *buf, size_t len, bool no_cck,
2279 bool dont_wait_for_ack, u64 *cookie)
8a6c8060
JM
2280{
2281 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 2282 struct ath6kl_vif *vif = netdev_priv(dev);
8a6c8060 2283 u32 id;
8bdfbf40
JM
2284 const struct ieee80211_mgmt *mgmt;
2285
2286 mgmt = (const struct ieee80211_mgmt *) buf;
2287 if (buf + len >= mgmt->u.probe_resp.variable &&
f5938f24 2288 vif->nw_type == AP_NETWORK && test_bit(CONNECTED, &vif->flags) &&
8bdfbf40
JM
2289 ieee80211_is_probe_resp(mgmt->frame_control)) {
2290 /*
2291 * Send Probe Response frame in AP mode using a separate WMI
2292 * command to allow the target to fill in the generic IEs.
2293 */
2294 *cookie = 0; /* TX status not supported */
334234b5 2295 return ath6kl_send_go_probe_resp(vif, buf, len,
8bdfbf40
JM
2296 chan->center_freq);
2297 }
8a6c8060 2298
cf5333d7 2299 id = vif->send_action_id++;
8a6c8060
JM
2300 if (id == 0) {
2301 /*
2302 * 0 is a reserved value in the WMI command and shall not be
2303 * used for the command.
2304 */
cf5333d7 2305 id = vif->send_action_id++;
8a6c8060
JM
2306 }
2307
2308 *cookie = id;
334234b5
VT
2309 return ath6kl_wmi_send_action_cmd(ar->wmi, vif->fw_vif_idx, id,
2310 chan->center_freq, wait,
8a6c8060
JM
2311 buf, len);
2312}
2313
ae32c30a
JM
2314static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
2315 struct net_device *dev,
2316 u16 frame_type, bool reg)
2317{
cf5333d7 2318 struct ath6kl_vif *vif = netdev_priv(dev);
ae32c30a
JM
2319
2320 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: frame_type=0x%x reg=%d\n",
2321 __func__, frame_type, reg);
2322 if (frame_type == IEEE80211_STYPE_PROBE_REQ) {
2323 /*
2324 * Note: This notification callback is not allowed to sleep, so
2325 * we cannot send WMI_PROBE_REQ_REPORT_CMD here. Instead, we
2326 * hardcode target to report Probe Request frames all the time.
2327 */
cf5333d7 2328 vif->probe_req_report = reg;
ae32c30a
JM
2329 }
2330}
2331
f80574ae
JM
2332static const struct ieee80211_txrx_stypes
2333ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
2334 [NL80211_IFTYPE_STATION] = {
2335 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2336 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
2337 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2338 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
2339 },
2340 [NL80211_IFTYPE_P2P_CLIENT] = {
2341 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2342 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
2343 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2344 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
2345 },
2346 [NL80211_IFTYPE_P2P_GO] = {
2347 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2348 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
2349 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2350 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
2351 },
2352};
2353
bdcd8170 2354static struct cfg80211_ops ath6kl_cfg80211_ops = {
55055976
VT
2355 .add_virtual_intf = ath6kl_cfg80211_add_iface,
2356 .del_virtual_intf = ath6kl_cfg80211_del_iface,
bdcd8170
KV
2357 .change_virtual_intf = ath6kl_cfg80211_change_iface,
2358 .scan = ath6kl_cfg80211_scan,
2359 .connect = ath6kl_cfg80211_connect,
2360 .disconnect = ath6kl_cfg80211_disconnect,
2361 .add_key = ath6kl_cfg80211_add_key,
2362 .get_key = ath6kl_cfg80211_get_key,
2363 .del_key = ath6kl_cfg80211_del_key,
2364 .set_default_key = ath6kl_cfg80211_set_default_key,
2365 .set_wiphy_params = ath6kl_cfg80211_set_wiphy_params,
2366 .set_tx_power = ath6kl_cfg80211_set_txpower,
2367 .get_tx_power = ath6kl_cfg80211_get_txpower,
2368 .set_power_mgmt = ath6kl_cfg80211_set_power_mgmt,
2369 .join_ibss = ath6kl_cfg80211_join_ibss,
2370 .leave_ibss = ath6kl_cfg80211_leave_ibss,
2371 .get_station = ath6kl_get_station,
2372 .set_pmksa = ath6kl_set_pmksa,
2373 .del_pmksa = ath6kl_del_pmksa,
2374 .flush_pmksa = ath6kl_flush_pmksa,
003353b0 2375 CFG80211_TESTMODE_CMD(ath6kl_tm_cmd)
abcb344b 2376#ifdef CONFIG_PM
52d81a68
KV
2377 .suspend = __ath6kl_cfg80211_suspend,
2378 .resume = __ath6kl_cfg80211_resume,
abcb344b 2379#endif
6a7c9bad
JM
2380 .set_channel = ath6kl_set_channel,
2381 .add_beacon = ath6kl_add_beacon,
2382 .set_beacon = ath6kl_set_beacon,
2383 .del_beacon = ath6kl_del_beacon,
23875136 2384 .change_station = ath6kl_change_station,
63fa1e0c
JM
2385 .remain_on_channel = ath6kl_remain_on_channel,
2386 .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel,
8a6c8060 2387 .mgmt_tx = ath6kl_mgmt_tx,
ae32c30a 2388 .mgmt_frame_register = ath6kl_mgmt_frame_register,
bdcd8170
KV
2389};
2390
ec4b7f60
KV
2391void ath6kl_cfg80211_stop(struct ath6kl *ar)
2392{
2393 struct ath6kl_vif *vif;
2394
2395 /* FIXME: for multi vif */
2396 vif = ath6kl_vif_first(ar);
2397 if (!vif) {
2398 /* save the current power mode before enabling power save */
2399 ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
2400
2401 if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0)
2402 ath6kl_warn("ath6kl_deep_sleep_enable: "
2403 "wmi_powermode_cmd failed\n");
2404 return;
2405 }
2406
2407 switch (vif->sme_state) {
2408 case SME_CONNECTING:
2409 cfg80211_connect_result(vif->ndev, vif->bssid, NULL, 0,
2410 NULL, 0,
2411 WLAN_STATUS_UNSPECIFIED_FAILURE,
2412 GFP_KERNEL);
2413 break;
2414 case SME_CONNECTED:
2415 default:
2416 /*
2417 * FIXME: oddly enough smeState is in DISCONNECTED during
2418 * suspend, why? Need to send disconnected event in that
2419 * state.
2420 */
2421 cfg80211_disconnected(vif->ndev, 0, NULL, 0, GFP_KERNEL);
2422 break;
2423 }
2424
2425 if (test_bit(CONNECTED, &vif->flags) ||
2426 test_bit(CONNECT_PEND, &vif->flags))
2427 ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
2428
2429 vif->sme_state = SME_DISCONNECTED;
1f405255
KV
2430 clear_bit(CONNECTED, &vif->flags);
2431 clear_bit(CONNECT_PEND, &vif->flags);
ec4b7f60
KV
2432
2433 /* disable scanning */
2434 if (ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, 0xFFFF, 0, 0,
2435 0, 0, 0, 0, 0, 0, 0) != 0)
2436 printk(KERN_WARNING "ath6kl: failed to disable scan "
2437 "during suspend\n");
2438
2439 ath6kl_cfg80211_scan_complete_event(vif, true);
2440}
2441
8dafb70e 2442struct ath6kl *ath6kl_core_alloc(struct device *dev)
bdcd8170 2443{
6bbc7c35 2444 struct ath6kl *ar;
be98e3a4 2445 struct wiphy *wiphy;
8dafb70e 2446 u8 ctr;
bdcd8170
KV
2447
2448 /* create a new wiphy for use with cfg80211 */
be98e3a4 2449 wiphy = wiphy_new(&ath6kl_cfg80211_ops, sizeof(struct ath6kl));
8dafb70e 2450
be98e3a4 2451 if (!wiphy) {
bdcd8170 2452 ath6kl_err("couldn't allocate wiphy device\n");
bdcd8170
KV
2453 return NULL;
2454 }
2455
be98e3a4 2456 ar = wiphy_priv(wiphy);
774439ad 2457 ar->p2p = !!ath6kl_p2p;
be98e3a4 2458 ar->wiphy = wiphy;
8dafb70e
VT
2459 ar->dev = dev;
2460
71f96ee6
KV
2461 ar->vif_max = 1;
2462
3226f68a
VT
2463 ar->max_norm_iface = 1;
2464
8dafb70e
VT
2465 spin_lock_init(&ar->lock);
2466 spin_lock_init(&ar->mcastpsq_lock);
990bd915 2467 spin_lock_init(&ar->list_lock);
8dafb70e
VT
2468
2469 init_waitqueue_head(&ar->event_wq);
2470 sema_init(&ar->sem, 1);
2471
2472 INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue);
990bd915 2473 INIT_LIST_HEAD(&ar->vif_list);
8dafb70e
VT
2474
2475 clear_bit(WMI_ENABLED, &ar->flag);
2476 clear_bit(SKIP_SCAN, &ar->flag);
2477 clear_bit(DESTROY_IN_PROGRESS, &ar->flag);
2478
2479 ar->listen_intvl_t = A_DEFAULT_LISTEN_INTERVAL;
2480 ar->listen_intvl_b = 0;
2481 ar->tx_pwr = 0;
2482
2483 ar->intra_bss = 1;
8dafb70e
VT
2484 ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD;
2485
76a9fbe2
KV
2486 ar->state = ATH6KL_STATE_OFF;
2487
8dafb70e
VT
2488 memset((u8 *)ar->sta_list, 0,
2489 AP_MAX_NUM_STA * sizeof(struct ath6kl_sta));
2490
2491 /* Init the PS queues */
2492 for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) {
2493 spin_lock_init(&ar->sta_list[ctr].psq_lock);
2494 skb_queue_head_init(&ar->sta_list[ctr].psq);
2495 }
2496
2497 skb_queue_head_init(&ar->mcastpsq);
2498
2499 memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3);
2500
2501 return ar;
2502}
2503
2504int ath6kl_register_ieee80211_hw(struct ath6kl *ar)
2505{
2506 struct wiphy *wiphy = ar->wiphy;
2507 int ret;
6bbc7c35 2508
be98e3a4 2509 wiphy->mgmt_stypes = ath6kl_mgmt_stypes;
f80574ae 2510
be98e3a4 2511 wiphy->max_remain_on_channel_duration = 5000;
63fa1e0c 2512
bdcd8170 2513 /* set device pointer for wiphy */
8dafb70e 2514 set_wiphy_dev(wiphy, ar->dev);
bdcd8170 2515
be98e3a4 2516 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
8dafb70e
VT
2517 BIT(NL80211_IFTYPE_ADHOC) |
2518 BIT(NL80211_IFTYPE_AP);
6bbc7c35 2519 if (ar->p2p) {
be98e3a4 2520 wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_GO) |
8dafb70e 2521 BIT(NL80211_IFTYPE_P2P_CLIENT);
6bbc7c35 2522 }
8dafb70e 2523
bdcd8170 2524 /* max num of ssids that can be probed during scanning */
be98e3a4
VT
2525 wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
2526 wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
2527 wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
2528 wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz;
2529 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
bdcd8170 2530
be98e3a4
VT
2531 wiphy->cipher_suites = cipher_suites;
2532 wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
bdcd8170 2533
eae9e066
RM
2534 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
2535 WIPHY_WOWLAN_DISCONNECT |
2536 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
2537 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
2538 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
2539 WIPHY_WOWLAN_4WAY_HANDSHAKE;
2540 wiphy->wowlan.n_patterns = WOW_MAX_FILTERS_PER_LIST;
2541 wiphy->wowlan.pattern_min_len = 1;
2542 wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE;
2543
be98e3a4 2544 ret = wiphy_register(wiphy);
bdcd8170
KV
2545 if (ret < 0) {
2546 ath6kl_err("couldn't register wiphy device\n");
8dafb70e 2547 return ret;
bdcd8170
KV
2548 }
2549
8dafb70e 2550 return 0;
bdcd8170
KV
2551}
2552
108438bc 2553static int ath6kl_init_if_data(struct ath6kl_vif *vif)
bdcd8170 2554{
2132c69c
VT
2555 vif->aggr_cntxt = aggr_init(vif->ndev);
2556 if (!vif->aggr_cntxt) {
8dafb70e
VT
2557 ath6kl_err("failed to initialize aggr\n");
2558 return -ENOMEM;
2559 }
2560
de3ad713 2561 setup_timer(&vif->disconnect_timer, disconnect_timer_handler,
108438bc 2562 (unsigned long) vif->ndev);
de3ad713 2563 set_bit(WMM_ENABLED, &vif->flags);
478ac027 2564 spin_lock_init(&vif->if_lock);
bdcd8170 2565
8dafb70e
VT
2566 return 0;
2567}
2568
108438bc 2569void ath6kl_deinit_if_data(struct ath6kl_vif *vif)
8dafb70e 2570{
55055976
VT
2571 struct ath6kl *ar = vif->ar;
2572
2132c69c 2573 aggr_module_destroy(vif->aggr_cntxt);
8dafb70e 2574
55055976
VT
2575 ar->avail_idx_map |= BIT(vif->fw_vif_idx);
2576
2577 if (vif->nw_type == ADHOC_NETWORK)
2578 ar->ibss_if_active = false;
2579
27929723 2580 unregister_netdevice(vif->ndev);
55055976
VT
2581
2582 ar->num_vif--;
8dafb70e
VT
2583}
2584
2585struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
55055976
VT
2586 enum nl80211_iftype type, u8 fw_vif_idx,
2587 u8 nw_type)
8dafb70e
VT
2588{
2589 struct net_device *ndev;
108438bc 2590 struct ath6kl_vif *vif;
8dafb70e 2591
55055976 2592 ndev = alloc_netdev(sizeof(*vif), name, ether_setup);
8dafb70e
VT
2593 if (!ndev)
2594 return NULL;
2595
108438bc
VT
2596 vif = netdev_priv(ndev);
2597 ndev->ieee80211_ptr = &vif->wdev;
2598 vif->wdev.wiphy = ar->wiphy;
2599 vif->ar = ar;
108438bc
VT
2600 vif->ndev = ndev;
2601 SET_NETDEV_DEV(ndev, wiphy_dev(vif->wdev.wiphy));
2602 vif->wdev.netdev = ndev;
2603 vif->wdev.iftype = type;
334234b5 2604 vif->fw_vif_idx = fw_vif_idx;
55055976 2605 vif->nw_type = vif->next_mode = nw_type;
8dafb70e 2606
55055976
VT
2607 memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
2608 if (fw_vif_idx != 0)
2609 ndev->dev_addr[0] = (ndev->dev_addr[0] ^ (1 << fw_vif_idx)) |
2610 0x2;
2611
8dafb70e
VT
2612 init_netdev(ndev);
2613
e29f25f5 2614 ath6kl_init_control_info(vif);
8dafb70e
VT
2615
2616 /* TODO: Pass interface specific pointer instead of ar */
108438bc 2617 if (ath6kl_init_if_data(vif))
8dafb70e
VT
2618 goto err;
2619
27929723 2620 if (register_netdevice(ndev))
8dafb70e
VT
2621 goto err;
2622
55055976 2623 ar->avail_idx_map &= ~BIT(fw_vif_idx);
14ee6f6b 2624 vif->sme_state = SME_DISCONNECTED;
59c98449 2625 set_bit(WLAN_ENABLED, &vif->flags);
8dafb70e 2626 ar->wlan_pwr_state = WLAN_POWER_STATE_ON;
59c98449 2627 set_bit(NETDEV_REGISTERED, &vif->flags);
8dafb70e 2628
55055976
VT
2629 if (type == NL80211_IFTYPE_ADHOC)
2630 ar->ibss_if_active = true;
2631
11f6e40d 2632 spin_lock_bh(&ar->list_lock);
990bd915 2633 list_add_tail(&vif->list, &ar->vif_list);
11f6e40d 2634 spin_unlock_bh(&ar->list_lock);
990bd915 2635
8dafb70e
VT
2636 return ndev;
2637
2638err:
27929723
VT
2639 aggr_module_destroy(vif->aggr_cntxt);
2640 free_netdev(ndev);
8dafb70e
VT
2641 return NULL;
2642}
2643
2644void ath6kl_deinit_ieee80211_hw(struct ath6kl *ar)
2645{
be98e3a4
VT
2646 wiphy_unregister(ar->wiphy);
2647 wiphy_free(ar->wiphy);
bdcd8170 2648}
This page took 1.561455 seconds and 5 git commands to generate.