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