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