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