ath6kl: Fix compilation error from of.h
[deliverable/linux.git] / drivers / net / wireless / ath / ath6kl / cfg80211.c
CommitLineData
bdcd8170
KV
1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "core.h"
18#include "cfg80211.h"
19#include "debug.h"
abcb344b 20#include "hif-ops.h"
003353b0 21#include "testmode.h"
bdcd8170 22
6bbc7c35 23static unsigned int ath6kl_p2p;
3226f68a 24static unsigned int multi_norm_if_support;
6bbc7c35
JM
25
26module_param(ath6kl_p2p, uint, 0644);
3226f68a 27module_param(multi_norm_if_support, uint, 0644);
6bbc7c35 28
bdcd8170
KV
29#define RATETAB_ENT(_rate, _rateid, _flags) { \
30 .bitrate = (_rate), \
31 .flags = (_flags), \
32 .hw_value = (_rateid), \
33}
34
35#define CHAN2G(_channel, _freq, _flags) { \
36 .band = IEEE80211_BAND_2GHZ, \
37 .hw_value = (_channel), \
38 .center_freq = (_freq), \
39 .flags = (_flags), \
40 .max_antenna_gain = 0, \
41 .max_power = 30, \
42}
43
44#define CHAN5G(_channel, _flags) { \
45 .band = IEEE80211_BAND_5GHZ, \
46 .hw_value = (_channel), \
47 .center_freq = 5000 + (5 * (_channel)), \
48 .flags = (_flags), \
49 .max_antenna_gain = 0, \
50 .max_power = 30, \
51}
52
53static struct ieee80211_rate ath6kl_rates[] = {
54 RATETAB_ENT(10, 0x1, 0),
55 RATETAB_ENT(20, 0x2, 0),
56 RATETAB_ENT(55, 0x4, 0),
57 RATETAB_ENT(110, 0x8, 0),
58 RATETAB_ENT(60, 0x10, 0),
59 RATETAB_ENT(90, 0x20, 0),
60 RATETAB_ENT(120, 0x40, 0),
61 RATETAB_ENT(180, 0x80, 0),
62 RATETAB_ENT(240, 0x100, 0),
63 RATETAB_ENT(360, 0x200, 0),
64 RATETAB_ENT(480, 0x400, 0),
65 RATETAB_ENT(540, 0x800, 0),
66};
67
68#define ath6kl_a_rates (ath6kl_rates + 4)
69#define ath6kl_a_rates_size 8
70#define ath6kl_g_rates (ath6kl_rates + 0)
71#define ath6kl_g_rates_size 12
72
73static struct ieee80211_channel ath6kl_2ghz_channels[] = {
74 CHAN2G(1, 2412, 0),
75 CHAN2G(2, 2417, 0),
76 CHAN2G(3, 2422, 0),
77 CHAN2G(4, 2427, 0),
78 CHAN2G(5, 2432, 0),
79 CHAN2G(6, 2437, 0),
80 CHAN2G(7, 2442, 0),
81 CHAN2G(8, 2447, 0),
82 CHAN2G(9, 2452, 0),
83 CHAN2G(10, 2457, 0),
84 CHAN2G(11, 2462, 0),
85 CHAN2G(12, 2467, 0),
86 CHAN2G(13, 2472, 0),
87 CHAN2G(14, 2484, 0),
88};
89
90static struct ieee80211_channel ath6kl_5ghz_a_channels[] = {
91 CHAN5G(34, 0), CHAN5G(36, 0),
92 CHAN5G(38, 0), CHAN5G(40, 0),
93 CHAN5G(42, 0), CHAN5G(44, 0),
94 CHAN5G(46, 0), CHAN5G(48, 0),
95 CHAN5G(52, 0), CHAN5G(56, 0),
96 CHAN5G(60, 0), CHAN5G(64, 0),
97 CHAN5G(100, 0), CHAN5G(104, 0),
98 CHAN5G(108, 0), CHAN5G(112, 0),
99 CHAN5G(116, 0), CHAN5G(120, 0),
100 CHAN5G(124, 0), CHAN5G(128, 0),
101 CHAN5G(132, 0), CHAN5G(136, 0),
102 CHAN5G(140, 0), CHAN5G(149, 0),
103 CHAN5G(153, 0), CHAN5G(157, 0),
104 CHAN5G(161, 0), CHAN5G(165, 0),
105 CHAN5G(184, 0), CHAN5G(188, 0),
106 CHAN5G(192, 0), CHAN5G(196, 0),
107 CHAN5G(200, 0), CHAN5G(204, 0),
108 CHAN5G(208, 0), CHAN5G(212, 0),
109 CHAN5G(216, 0),
110};
111
112static struct ieee80211_supported_band ath6kl_band_2ghz = {
113 .n_channels = ARRAY_SIZE(ath6kl_2ghz_channels),
114 .channels = ath6kl_2ghz_channels,
115 .n_bitrates = ath6kl_g_rates_size,
116 .bitrates = ath6kl_g_rates,
117};
118
119static struct ieee80211_supported_band ath6kl_band_5ghz = {
120 .n_channels = ARRAY_SIZE(ath6kl_5ghz_a_channels),
121 .channels = ath6kl_5ghz_a_channels,
122 .n_bitrates = ath6kl_a_rates_size,
123 .bitrates = ath6kl_a_rates,
124};
125
837cb97e
JM
126#define CCKM_KRK_CIPHER_SUITE 0x004096ff /* use for KRK */
127
240d2799 128static int ath6kl_set_wpa_version(struct ath6kl_vif *vif,
bdcd8170
KV
129 enum nl80211_wpa_versions wpa_version)
130{
131 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: %u\n", __func__, wpa_version);
132
133 if (!wpa_version) {
3450334f 134 vif->auth_mode = NONE_AUTH;
bdcd8170 135 } else if (wpa_version & NL80211_WPA_VERSION_2) {
3450334f 136 vif->auth_mode = WPA2_AUTH;
bdcd8170 137 } else if (wpa_version & NL80211_WPA_VERSION_1) {
3450334f 138 vif->auth_mode = WPA_AUTH;
bdcd8170
KV
139 } else {
140 ath6kl_err("%s: %u not supported\n", __func__, wpa_version);
141 return -ENOTSUPP;
142 }
143
144 return 0;
145}
146
240d2799 147static int ath6kl_set_auth_type(struct ath6kl_vif *vif,
bdcd8170
KV
148 enum nl80211_auth_type auth_type)
149{
bdcd8170
KV
150 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: 0x%x\n", __func__, auth_type);
151
152 switch (auth_type) {
153 case NL80211_AUTHTYPE_OPEN_SYSTEM:
3450334f 154 vif->dot11_auth_mode = OPEN_AUTH;
bdcd8170
KV
155 break;
156 case NL80211_AUTHTYPE_SHARED_KEY:
3450334f 157 vif->dot11_auth_mode = SHARED_AUTH;
bdcd8170
KV
158 break;
159 case NL80211_AUTHTYPE_NETWORK_EAP:
3450334f 160 vif->dot11_auth_mode = LEAP_AUTH;
bdcd8170
KV
161 break;
162
163 case NL80211_AUTHTYPE_AUTOMATIC:
3450334f 164 vif->dot11_auth_mode = OPEN_AUTH | SHARED_AUTH;
bdcd8170
KV
165 break;
166
167 default:
168 ath6kl_err("%s: 0x%x not spported\n", __func__, auth_type);
169 return -ENOTSUPP;
170 }
171
172 return 0;
173}
174
240d2799 175static int ath6kl_set_cipher(struct ath6kl_vif *vif, u32 cipher, bool ucast)
bdcd8170 176{
3450334f
VT
177 u8 *ar_cipher = ucast ? &vif->prwise_crypto : &vif->grp_crypto;
178 u8 *ar_cipher_len = ucast ? &vif->prwise_crypto_len :
179 &vif->grp_crypto_len;
bdcd8170
KV
180
181 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: cipher 0x%x, ucast %u\n",
182 __func__, cipher, ucast);
183
184 switch (cipher) {
185 case 0:
186 /* our own hack to use value 0 as no crypto used */
187 *ar_cipher = NONE_CRYPT;
188 *ar_cipher_len = 0;
189 break;
190 case WLAN_CIPHER_SUITE_WEP40:
191 *ar_cipher = WEP_CRYPT;
192 *ar_cipher_len = 5;
193 break;
194 case WLAN_CIPHER_SUITE_WEP104:
195 *ar_cipher = WEP_CRYPT;
196 *ar_cipher_len = 13;
197 break;
198 case WLAN_CIPHER_SUITE_TKIP:
199 *ar_cipher = TKIP_CRYPT;
200 *ar_cipher_len = 0;
201 break;
202 case WLAN_CIPHER_SUITE_CCMP:
203 *ar_cipher = AES_CRYPT;
204 *ar_cipher_len = 0;
205 break;
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
240d2799 874void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, int status)
bdcd8170 875{
240d2799 876 struct ath6kl *ar = vif->ar;
6fd1eace 877 int i;
bdcd8170
KV
878
879 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status %d\n", __func__, status);
880
14ee6f6b 881 if (!vif->scan_req)
6fd1eace
KV
882 return;
883
884 if ((status == -ECANCELED) || (status == -EBUSY)) {
14ee6f6b 885 cfg80211_scan_done(vif->scan_req, true);
6fd1eace
KV
886 goto out;
887 }
6fd1eace 888
14ee6f6b 889 cfg80211_scan_done(vif->scan_req, false);
6fd1eace 890
14ee6f6b
VT
891 if (vif->scan_req->n_ssids && vif->scan_req->ssids[0].ssid_len) {
892 for (i = 0; i < vif->scan_req->n_ssids; i++) {
334234b5
VT
893 ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
894 i + 1, DISABLE_SSID_FLAG,
6fd1eace 895 0, NULL);
bdcd8170 896 }
bdcd8170 897 }
6fd1eace
KV
898
899out:
14ee6f6b 900 vif->scan_req = NULL;
bdcd8170
KV
901}
902
903static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
904 u8 key_index, bool pairwise,
905 const u8 *mac_addr,
906 struct key_params *params)
907{
908 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
59c98449 909 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170
KV
910 struct ath6kl_key *key = NULL;
911 u8 key_usage;
912 u8 key_type;
913 int status = 0;
914
990bd915 915 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
916 return -EIO;
917
837cb97e
JM
918 if (params->cipher == CCKM_KRK_CIPHER_SUITE) {
919 if (params->key_len != WMI_KRK_LEN)
920 return -EINVAL;
240d2799
VT
921 return ath6kl_wmi_add_krk_cmd(ar->wmi, vif->fw_vif_idx,
922 params->key);
837cb97e
JM
923 }
924
bdcd8170
KV
925 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
926 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
927 "%s: key index %d out of bounds\n", __func__,
928 key_index);
929 return -ENOENT;
930 }
931
6f2a73f9 932 key = &vif->keys[key_index];
bdcd8170
KV
933 memset(key, 0, sizeof(struct ath6kl_key));
934
935 if (pairwise)
936 key_usage = PAIRWISE_USAGE;
937 else
938 key_usage = GROUP_USAGE;
939
940 if (params) {
941 if (params->key_len > WLAN_MAX_KEY_LEN ||
942 params->seq_len > sizeof(key->seq))
943 return -EINVAL;
944
945 key->key_len = params->key_len;
946 memcpy(key->key, params->key, key->key_len);
947 key->seq_len = params->seq_len;
948 memcpy(key->seq, params->seq, key->seq_len);
949 key->cipher = params->cipher;
950 }
951
952 switch (key->cipher) {
953 case WLAN_CIPHER_SUITE_WEP40:
954 case WLAN_CIPHER_SUITE_WEP104:
955 key_type = WEP_CRYPT;
956 break;
957
958 case WLAN_CIPHER_SUITE_TKIP:
959 key_type = TKIP_CRYPT;
960 break;
961
962 case WLAN_CIPHER_SUITE_CCMP:
963 key_type = AES_CRYPT;
964 break;
965
966 default:
967 return -ENOTSUPP;
968 }
969
3450334f
VT
970 if (((vif->auth_mode == WPA_PSK_AUTH)
971 || (vif->auth_mode == WPA2_PSK_AUTH))
bdcd8170 972 && (key_usage & GROUP_USAGE))
de3ad713 973 del_timer(&vif->disconnect_timer);
bdcd8170
KV
974
975 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
976 "%s: index %d, key_len %d, key_type 0x%x, key_usage 0x%x, seq_len %d\n",
977 __func__, key_index, key->key_len, key_type,
978 key_usage, key->seq_len);
979
3450334f 980 vif->def_txkey_index = key_index;
9a5b1318 981
f5938f24 982 if (vif->nw_type == AP_NETWORK && !pairwise &&
9a5b1318
JM
983 (key_type == TKIP_CRYPT || key_type == AES_CRYPT) && params) {
984 ar->ap_mode_bkey.valid = true;
985 ar->ap_mode_bkey.key_index = key_index;
986 ar->ap_mode_bkey.key_type = key_type;
987 ar->ap_mode_bkey.key_len = key->key_len;
988 memcpy(ar->ap_mode_bkey.key, key->key, key->key_len);
59c98449 989 if (!test_bit(CONNECTED, &vif->flags)) {
9a5b1318
JM
990 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group "
991 "key configuration until AP mode has been "
992 "started\n");
993 /*
994 * The key will be set in ath6kl_connect_ap_mode() once
995 * the connected event is received from the target.
996 */
997 return 0;
998 }
999 }
1000
f5938f24 1001 if (vif->next_mode == AP_NETWORK && key_type == WEP_CRYPT &&
59c98449 1002 !test_bit(CONNECTED, &vif->flags)) {
151411e8
JM
1003 /*
1004 * Store the key locally so that it can be re-configured after
1005 * the AP mode has properly started
1006 * (ath6kl_install_statioc_wep_keys).
1007 */
1008 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay WEP key configuration "
1009 "until AP mode has been started\n");
6f2a73f9
VT
1010 vif->wep_key_list[key_index].key_len = key->key_len;
1011 memcpy(vif->wep_key_list[key_index].key, key->key,
1012 key->key_len);
151411e8
JM
1013 return 0;
1014 }
1015
334234b5
VT
1016 status = ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx,
1017 vif->def_txkey_index,
bdcd8170
KV
1018 key_type, key_usage, key->key_len,
1019 key->seq, key->key, KEY_OP_INIT_VAL,
1020 (u8 *) mac_addr, SYNC_BOTH_WMIFLAG);
1021
1022 if (status)
1023 return -EIO;
1024
1025 return 0;
1026}
1027
1028static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
1029 u8 key_index, bool pairwise,
1030 const u8 *mac_addr)
1031{
1032 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
6f2a73f9 1033 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170
KV
1034
1035 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1036
990bd915 1037 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1038 return -EIO;
1039
1040 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
1041 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1042 "%s: key index %d out of bounds\n", __func__,
1043 key_index);
1044 return -ENOENT;
1045 }
1046
6f2a73f9 1047 if (!vif->keys[key_index].key_len) {
bdcd8170
KV
1048 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1049 "%s: index %d is empty\n", __func__, key_index);
1050 return 0;
1051 }
1052
6f2a73f9 1053 vif->keys[key_index].key_len = 0;
bdcd8170 1054
334234b5 1055 return ath6kl_wmi_deletekey_cmd(ar->wmi, vif->fw_vif_idx, key_index);
bdcd8170
KV
1056}
1057
1058static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
1059 u8 key_index, bool pairwise,
1060 const u8 *mac_addr, void *cookie,
1061 void (*callback) (void *cookie,
1062 struct key_params *))
1063{
6f2a73f9 1064 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170
KV
1065 struct ath6kl_key *key = NULL;
1066 struct key_params params;
1067
1068 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1069
990bd915 1070 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1071 return -EIO;
1072
1073 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
1074 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1075 "%s: key index %d out of bounds\n", __func__,
1076 key_index);
1077 return -ENOENT;
1078 }
1079
6f2a73f9 1080 key = &vif->keys[key_index];
bdcd8170
KV
1081 memset(&params, 0, sizeof(params));
1082 params.cipher = key->cipher;
1083 params.key_len = key->key_len;
1084 params.seq_len = key->seq_len;
1085 params.seq = key->seq;
1086 params.key = key->key;
1087
1088 callback(cookie, &params);
1089
1090 return key->key_len ? 0 : -ENOENT;
1091}
1092
1093static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
1094 struct net_device *ndev,
1095 u8 key_index, bool unicast,
1096 bool multicast)
1097{
1098 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
59c98449 1099 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170
KV
1100 struct ath6kl_key *key = NULL;
1101 int status = 0;
1102 u8 key_usage;
229ed6b5 1103 enum crypto_type key_type = NONE_CRYPT;
bdcd8170
KV
1104
1105 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1106
990bd915 1107 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1108 return -EIO;
1109
1110 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
1111 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1112 "%s: key index %d out of bounds\n",
1113 __func__, key_index);
1114 return -ENOENT;
1115 }
1116
6f2a73f9 1117 if (!vif->keys[key_index].key_len) {
bdcd8170
KV
1118 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: invalid key index %d\n",
1119 __func__, key_index);
1120 return -EINVAL;
1121 }
1122
3450334f 1123 vif->def_txkey_index = key_index;
6f2a73f9 1124 key = &vif->keys[vif->def_txkey_index];
bdcd8170 1125 key_usage = GROUP_USAGE;
3450334f 1126 if (vif->prwise_crypto == WEP_CRYPT)
bdcd8170 1127 key_usage |= TX_USAGE;
229ed6b5 1128 if (unicast)
3450334f 1129 key_type = vif->prwise_crypto;
229ed6b5 1130 if (multicast)
3450334f 1131 key_type = vif->grp_crypto;
bdcd8170 1132
f5938f24 1133 if (vif->next_mode == AP_NETWORK && !test_bit(CONNECTED, &vif->flags))
9a5b1318
JM
1134 return 0; /* Delay until AP mode has been started */
1135
334234b5
VT
1136 status = ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx,
1137 vif->def_txkey_index,
229ed6b5 1138 key_type, key_usage,
bdcd8170
KV
1139 key->key_len, key->seq, key->key,
1140 KEY_OP_INIT_VAL, NULL,
1141 SYNC_BOTH_WMIFLAG);
1142 if (status)
1143 return -EIO;
1144
1145 return 0;
1146}
1147
240d2799 1148void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl_vif *vif, u8 keyid,
bdcd8170
KV
1149 bool ismcast)
1150{
1151 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1152 "%s: keyid %d, ismcast %d\n", __func__, keyid, ismcast);
1153
240d2799 1154 cfg80211_michael_mic_failure(vif->ndev, vif->bssid,
bdcd8170
KV
1155 (ismcast ? NL80211_KEYTYPE_GROUP :
1156 NL80211_KEYTYPE_PAIRWISE), keyid, NULL,
1157 GFP_KERNEL);
1158}
1159
1160static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1161{
1162 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
990bd915 1163 struct ath6kl_vif *vif;
bdcd8170
KV
1164 int ret;
1165
1166 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: changed 0x%x\n", __func__,
1167 changed);
1168
990bd915
VT
1169 vif = ath6kl_vif_first(ar);
1170 if (!vif)
1171 return -EIO;
1172
1173 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1174 return -EIO;
1175
1176 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
1177 ret = ath6kl_wmi_set_rts_cmd(ar->wmi, wiphy->rts_threshold);
1178 if (ret != 0) {
1179 ath6kl_err("ath6kl_wmi_set_rts_cmd failed\n");
1180 return -EIO;
1181 }
1182 }
1183
1184 return 0;
1185}
1186
1187/*
1188 * The type nl80211_tx_power_setting replaces the following
1189 * data type from 2.6.36 onwards
1190*/
1191static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
1192 enum nl80211_tx_power_setting type,
1193 int dbm)
1194{
1195 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
990bd915 1196 struct ath6kl_vif *vif;
bdcd8170
KV
1197 u8 ath6kl_dbm;
1198
1199 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__,
1200 type, dbm);
1201
990bd915
VT
1202 vif = ath6kl_vif_first(ar);
1203 if (!vif)
1204 return -EIO;
1205
1206 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1207 return -EIO;
1208
1209 switch (type) {
1210 case NL80211_TX_POWER_AUTOMATIC:
1211 return 0;
1212 case NL80211_TX_POWER_LIMITED:
1213 ar->tx_pwr = ath6kl_dbm = dbm;
1214 break;
1215 default:
1216 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x not supported\n",
1217 __func__, type);
1218 return -EOPNOTSUPP;
1219 }
1220
990bd915 1221 ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx, ath6kl_dbm);
bdcd8170
KV
1222
1223 return 0;
1224}
1225
1226static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
1227{
1228 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
990bd915
VT
1229 struct ath6kl_vif *vif;
1230
1231 vif = ath6kl_vif_first(ar);
1232 if (!vif)
1233 return -EIO;
bdcd8170 1234
990bd915 1235 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1236 return -EIO;
1237
59c98449 1238 if (test_bit(CONNECTED, &vif->flags)) {
bdcd8170
KV
1239 ar->tx_pwr = 0;
1240
990bd915 1241 if (ath6kl_wmi_get_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx) != 0) {
bdcd8170
KV
1242 ath6kl_err("ath6kl_wmi_get_tx_pwr_cmd failed\n");
1243 return -EIO;
1244 }
1245
1246 wait_event_interruptible_timeout(ar->event_wq, ar->tx_pwr != 0,
1247 5 * HZ);
1248
1249 if (signal_pending(current)) {
1250 ath6kl_err("target did not respond\n");
1251 return -EINTR;
1252 }
1253 }
1254
1255 *dbm = ar->tx_pwr;
1256 return 0;
1257}
1258
1259static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
1260 struct net_device *dev,
1261 bool pmgmt, int timeout)
1262{
1263 struct ath6kl *ar = ath6kl_priv(dev);
1264 struct wmi_power_mode_cmd mode;
334234b5 1265 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170
KV
1266
1267 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: pmgmt %d, timeout %d\n",
1268 __func__, pmgmt, timeout);
1269
990bd915 1270 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1271 return -EIO;
1272
1273 if (pmgmt) {
1274 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: max perf\n", __func__);
1275 mode.pwr_mode = REC_POWER;
1276 } else {
1277 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: rec power\n", __func__);
1278 mode.pwr_mode = MAX_PERF_POWER;
1279 }
1280
334234b5
VT
1281 if (ath6kl_wmi_powermode_cmd(ar->wmi, vif->fw_vif_idx,
1282 mode.pwr_mode) != 0) {
bdcd8170
KV
1283 ath6kl_err("wmi_powermode_cmd failed\n");
1284 return -EIO;
1285 }
1286
1287 return 0;
1288}
1289
55055976
VT
1290static struct net_device *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
1291 char *name,
1292 enum nl80211_iftype type,
1293 u32 *flags,
1294 struct vif_params *params)
1295{
1296 struct ath6kl *ar = wiphy_priv(wiphy);
1297 struct net_device *ndev;
1298 u8 if_idx, nw_type;
1299
1300 if (ar->num_vif == MAX_NUM_VIF) {
1301 ath6kl_err("Reached maximum number of supported vif\n");
1302 return ERR_PTR(-EINVAL);
1303 }
1304
1305 if (!ath6kl_is_valid_iftype(ar, type, &if_idx, &nw_type)) {
1306 ath6kl_err("Not a supported interface type\n");
1307 return ERR_PTR(-EINVAL);
1308 }
1309
1310 ndev = ath6kl_interface_add(ar, name, type, if_idx, nw_type);
1311 if (!ndev)
1312 return ERR_PTR(-ENOMEM);
1313
1314 ar->num_vif++;
1315
1316 return ndev;
1317}
1318
1319static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy,
1320 struct net_device *ndev)
1321{
1322 struct ath6kl *ar = wiphy_priv(wiphy);
1323 struct ath6kl_vif *vif = netdev_priv(ndev);
1324
1325 spin_lock(&ar->list_lock);
1326 list_del(&vif->list);
1327 spin_unlock(&ar->list_lock);
1328
1329 ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag));
1330
1331 ath6kl_deinit_if_data(vif);
1332
1333 return 0;
1334}
1335
bdcd8170
KV
1336static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
1337 struct net_device *ndev,
1338 enum nl80211_iftype type, u32 *flags,
1339 struct vif_params *params)
1340{
f5938f24 1341 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170
KV
1342
1343 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type);
1344
990bd915 1345 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1346 return -EIO;
1347
1348 switch (type) {
1349 case NL80211_IFTYPE_STATION:
f5938f24 1350 vif->next_mode = INFRA_NETWORK;
bdcd8170
KV
1351 break;
1352 case NL80211_IFTYPE_ADHOC:
f5938f24 1353 vif->next_mode = ADHOC_NETWORK;
bdcd8170 1354 break;
6e4604c8 1355 case NL80211_IFTYPE_AP:
f5938f24 1356 vif->next_mode = AP_NETWORK;
6e4604c8 1357 break;
6b5e5d25 1358 case NL80211_IFTYPE_P2P_CLIENT:
f5938f24 1359 vif->next_mode = INFRA_NETWORK;
6b5e5d25
JM
1360 break;
1361 case NL80211_IFTYPE_P2P_GO:
f5938f24 1362 vif->next_mode = AP_NETWORK;
6b5e5d25 1363 break;
bdcd8170
KV
1364 default:
1365 ath6kl_err("invalid interface type %u\n", type);
1366 return -EOPNOTSUPP;
1367 }
1368
551959d8 1369 vif->wdev.iftype = type;
bdcd8170
KV
1370
1371 return 0;
1372}
1373
1374static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
1375 struct net_device *dev,
1376 struct cfg80211_ibss_params *ibss_param)
1377{
1378 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 1379 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170
KV
1380 int status;
1381
990bd915 1382 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1383 return -EIO;
1384
3450334f
VT
1385 vif->ssid_len = ibss_param->ssid_len;
1386 memcpy(vif->ssid, ibss_param->ssid, vif->ssid_len);
bdcd8170
KV
1387
1388 if (ibss_param->channel)
f74bac54 1389 vif->ch_hint = ibss_param->channel->center_freq;
bdcd8170
KV
1390
1391 if (ibss_param->channel_fixed) {
1392 /*
1393 * TODO: channel_fixed: The channel should be fixed, do not
1394 * search for IBSSs to join on other channels. Target
1395 * firmware does not support this feature, needs to be
1396 * updated.
1397 */
1398 return -EOPNOTSUPP;
1399 }
1400
8c8b65e3 1401 memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
bdcd8170 1402 if (ibss_param->bssid && !is_broadcast_ether_addr(ibss_param->bssid))
8c8b65e3
VT
1403 memcpy(vif->req_bssid, ibss_param->bssid,
1404 sizeof(vif->req_bssid));
bdcd8170 1405
240d2799 1406 ath6kl_set_wpa_version(vif, 0);
bdcd8170 1407
240d2799 1408 status = ath6kl_set_auth_type(vif, NL80211_AUTHTYPE_OPEN_SYSTEM);
bdcd8170
KV
1409 if (status)
1410 return status;
1411
1412 if (ibss_param->privacy) {
240d2799
VT
1413 ath6kl_set_cipher(vif, WLAN_CIPHER_SUITE_WEP40, true);
1414 ath6kl_set_cipher(vif, WLAN_CIPHER_SUITE_WEP40, false);
bdcd8170 1415 } else {
240d2799
VT
1416 ath6kl_set_cipher(vif, 0, true);
1417 ath6kl_set_cipher(vif, 0, false);
bdcd8170
KV
1418 }
1419
f5938f24 1420 vif->nw_type = vif->next_mode;
bdcd8170
KV
1421
1422 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1423 "%s: connect called with authmode %d dot11 auth %d"
1424 " PW crypto %d PW crypto len %d GRP crypto %d"
1425 " GRP crypto len %d channel hint %u\n",
1426 __func__,
3450334f
VT
1427 vif->auth_mode, vif->dot11_auth_mode, vif->prwise_crypto,
1428 vif->prwise_crypto_len, vif->grp_crypto,
f74bac54 1429 vif->grp_crypto_len, vif->ch_hint);
bdcd8170 1430
334234b5 1431 status = ath6kl_wmi_connect_cmd(ar->wmi, vif->fw_vif_idx, vif->nw_type,
3450334f
VT
1432 vif->dot11_auth_mode, vif->auth_mode,
1433 vif->prwise_crypto,
1434 vif->prwise_crypto_len,
1435 vif->grp_crypto, vif->grp_crypto_len,
1436 vif->ssid_len, vif->ssid,
f74bac54 1437 vif->req_bssid, vif->ch_hint,
bdcd8170 1438 ar->connect_ctrl_flags);
59c98449 1439 set_bit(CONNECT_PEND, &vif->flags);
bdcd8170
KV
1440
1441 return 0;
1442}
1443
1444static int ath6kl_cfg80211_leave_ibss(struct wiphy *wiphy,
1445 struct net_device *dev)
1446{
3450334f 1447 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170 1448
990bd915 1449 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1450 return -EIO;
1451
240d2799 1452 ath6kl_disconnect(vif);
3450334f
VT
1453 memset(vif->ssid, 0, sizeof(vif->ssid));
1454 vif->ssid_len = 0;
bdcd8170
KV
1455
1456 return 0;
1457}
1458
1459static const u32 cipher_suites[] = {
1460 WLAN_CIPHER_SUITE_WEP40,
1461 WLAN_CIPHER_SUITE_WEP104,
1462 WLAN_CIPHER_SUITE_TKIP,
1463 WLAN_CIPHER_SUITE_CCMP,
837cb97e 1464 CCKM_KRK_CIPHER_SUITE,
bdcd8170
KV
1465};
1466
1467static bool is_rate_legacy(s32 rate)
1468{
1469 static const s32 legacy[] = { 1000, 2000, 5500, 11000,
1470 6000, 9000, 12000, 18000, 24000,
1471 36000, 48000, 54000
1472 };
1473 u8 i;
1474
1475 for (i = 0; i < ARRAY_SIZE(legacy); i++)
1476 if (rate == legacy[i])
1477 return true;
1478
1479 return false;
1480}
1481
1482static bool is_rate_ht20(s32 rate, u8 *mcs, bool *sgi)
1483{
1484 static const s32 ht20[] = { 6500, 13000, 19500, 26000, 39000,
1485 52000, 58500, 65000, 72200
1486 };
1487 u8 i;
1488
1489 for (i = 0; i < ARRAY_SIZE(ht20); i++) {
1490 if (rate == ht20[i]) {
1491 if (i == ARRAY_SIZE(ht20) - 1)
1492 /* last rate uses sgi */
1493 *sgi = true;
1494 else
1495 *sgi = false;
1496
1497 *mcs = i;
1498 return true;
1499 }
1500 }
1501 return false;
1502}
1503
1504static bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi)
1505{
1506 static const s32 ht40[] = { 13500, 27000, 40500, 54000,
1507 81000, 108000, 121500, 135000,
1508 150000
1509 };
1510 u8 i;
1511
1512 for (i = 0; i < ARRAY_SIZE(ht40); i++) {
1513 if (rate == ht40[i]) {
1514 if (i == ARRAY_SIZE(ht40) - 1)
1515 /* last rate uses sgi */
1516 *sgi = true;
1517 else
1518 *sgi = false;
1519
1520 *mcs = i;
1521 return true;
1522 }
1523 }
1524
1525 return false;
1526}
1527
1528static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
1529 u8 *mac, struct station_info *sinfo)
1530{
1531 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 1532 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170
KV
1533 long left;
1534 bool sgi;
1535 s32 rate;
1536 int ret;
1537 u8 mcs;
1538
8c8b65e3 1539 if (memcmp(mac, vif->bssid, ETH_ALEN) != 0)
bdcd8170
KV
1540 return -ENOENT;
1541
1542 if (down_interruptible(&ar->sem))
1543 return -EBUSY;
1544
b95907a7 1545 set_bit(STATS_UPDATE_PEND, &vif->flags);
bdcd8170 1546
334234b5 1547 ret = ath6kl_wmi_get_stats_cmd(ar->wmi, vif->fw_vif_idx);
bdcd8170
KV
1548
1549 if (ret != 0) {
1550 up(&ar->sem);
1551 return -EIO;
1552 }
1553
1554 left = wait_event_interruptible_timeout(ar->event_wq,
1555 !test_bit(STATS_UPDATE_PEND,
b95907a7 1556 &vif->flags),
bdcd8170
KV
1557 WMI_TIMEOUT);
1558
1559 up(&ar->sem);
1560
1561 if (left == 0)
1562 return -ETIMEDOUT;
1563 else if (left < 0)
1564 return left;
1565
b95907a7
VT
1566 if (vif->target_stats.rx_byte) {
1567 sinfo->rx_bytes = vif->target_stats.rx_byte;
bdcd8170 1568 sinfo->filled |= STATION_INFO_RX_BYTES;
b95907a7 1569 sinfo->rx_packets = vif->target_stats.rx_pkt;
bdcd8170
KV
1570 sinfo->filled |= STATION_INFO_RX_PACKETS;
1571 }
1572
b95907a7
VT
1573 if (vif->target_stats.tx_byte) {
1574 sinfo->tx_bytes = vif->target_stats.tx_byte;
bdcd8170 1575 sinfo->filled |= STATION_INFO_TX_BYTES;
b95907a7 1576 sinfo->tx_packets = vif->target_stats.tx_pkt;
bdcd8170
KV
1577 sinfo->filled |= STATION_INFO_TX_PACKETS;
1578 }
1579
b95907a7 1580 sinfo->signal = vif->target_stats.cs_rssi;
bdcd8170
KV
1581 sinfo->filled |= STATION_INFO_SIGNAL;
1582
b95907a7 1583 rate = vif->target_stats.tx_ucast_rate;
bdcd8170
KV
1584
1585 if (is_rate_legacy(rate)) {
1586 sinfo->txrate.legacy = rate / 100;
1587 } else if (is_rate_ht20(rate, &mcs, &sgi)) {
1588 if (sgi) {
1589 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
1590 sinfo->txrate.mcs = mcs - 1;
1591 } else {
1592 sinfo->txrate.mcs = mcs;
1593 }
1594
1595 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
1596 } else if (is_rate_ht40(rate, &mcs, &sgi)) {
1597 if (sgi) {
1598 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
1599 sinfo->txrate.mcs = mcs - 1;
1600 } else {
1601 sinfo->txrate.mcs = mcs;
1602 }
1603
1604 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
1605 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
1606 } else {
9a730834
KV
1607 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1608 "invalid rate from stats: %d\n", rate);
1609 ath6kl_debug_war(ar, ATH6KL_WAR_INVALID_RATE);
bdcd8170
KV
1610 return 0;
1611 }
1612
1613 sinfo->filled |= STATION_INFO_TX_BITRATE;
1614
59c98449
VT
1615 if (test_bit(CONNECTED, &vif->flags) &&
1616 test_bit(DTIM_PERIOD_AVAIL, &vif->flags) &&
f5938f24 1617 vif->nw_type == INFRA_NETWORK) {
32c10874
JM
1618 sinfo->filled |= STATION_INFO_BSS_PARAM;
1619 sinfo->bss_param.flags = 0;
cf5333d7
VT
1620 sinfo->bss_param.dtim_period = vif->assoc_bss_dtim_period;
1621 sinfo->bss_param.beacon_interval = vif->assoc_bss_beacon_int;
32c10874
JM
1622 }
1623
bdcd8170
KV
1624 return 0;
1625}
1626
1627static int ath6kl_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1628 struct cfg80211_pmksa *pmksa)
1629{
1630 struct ath6kl *ar = ath6kl_priv(netdev);
334234b5
VT
1631 struct ath6kl_vif *vif = netdev_priv(netdev);
1632
1633 return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx, pmksa->bssid,
bdcd8170
KV
1634 pmksa->pmkid, true);
1635}
1636
1637static int ath6kl_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1638 struct cfg80211_pmksa *pmksa)
1639{
1640 struct ath6kl *ar = ath6kl_priv(netdev);
334234b5
VT
1641 struct ath6kl_vif *vif = netdev_priv(netdev);
1642
1643 return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx, pmksa->bssid,
bdcd8170
KV
1644 pmksa->pmkid, false);
1645}
1646
1647static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
1648{
1649 struct ath6kl *ar = ath6kl_priv(netdev);
59c98449
VT
1650 struct ath6kl_vif *vif = netdev_priv(netdev);
1651
1652 if (test_bit(CONNECTED, &vif->flags))
334234b5
VT
1653 return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx,
1654 vif->bssid, NULL, false);
bdcd8170
KV
1655 return 0;
1656}
1657
abcb344b
KV
1658#ifdef CONFIG_PM
1659static int ar6k_cfg80211_suspend(struct wiphy *wiphy,
1660 struct cfg80211_wowlan *wow)
1661{
1662 struct ath6kl *ar = wiphy_priv(wiphy);
1663
1664 return ath6kl_hif_suspend(ar);
1665}
aa6cffc1
CN
1666
1667static int ar6k_cfg80211_resume(struct wiphy *wiphy)
1668{
1669 struct ath6kl *ar = wiphy_priv(wiphy);
1670
1671 return ath6kl_hif_resume(ar);
1672}
abcb344b
KV
1673#endif
1674
6a7c9bad
JM
1675static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev,
1676 struct ieee80211_channel *chan,
1677 enum nl80211_channel_type channel_type)
1678{
cf5333d7 1679 struct ath6kl_vif *vif = netdev_priv(dev);
6a7c9bad 1680
990bd915 1681 if (!ath6kl_cfg80211_ready(vif))
6a7c9bad
JM
1682 return -EIO;
1683
1684 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n",
1685 __func__, chan->center_freq, chan->hw_value);
cf5333d7 1686 vif->next_chan = chan->center_freq;
6a7c9bad
JM
1687
1688 return 0;
1689}
1690
8bdfbf40
JM
1691static bool ath6kl_is_p2p_ie(const u8 *pos)
1692{
1693 return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
1694 pos[2] == 0x50 && pos[3] == 0x6f &&
1695 pos[4] == 0x9a && pos[5] == 0x09;
1696}
1697
334234b5
VT
1698static int ath6kl_set_ap_probe_resp_ies(struct ath6kl_vif *vif,
1699 const u8 *ies, size_t ies_len)
8bdfbf40 1700{
334234b5 1701 struct ath6kl *ar = vif->ar;
8bdfbf40
JM
1702 const u8 *pos;
1703 u8 *buf = NULL;
1704 size_t len = 0;
1705 int ret;
1706
1707 /*
1708 * Filter out P2P IE(s) since they will be included depending on
1709 * the Probe Request frame in ath6kl_send_go_probe_resp().
1710 */
1711
1712 if (ies && ies_len) {
1713 buf = kmalloc(ies_len, GFP_KERNEL);
1714 if (buf == NULL)
1715 return -ENOMEM;
1716 pos = ies;
1717 while (pos + 1 < ies + ies_len) {
1718 if (pos + 2 + pos[1] > ies + ies_len)
1719 break;
1720 if (!ath6kl_is_p2p_ie(pos)) {
1721 memcpy(buf + len, pos, 2 + pos[1]);
1722 len += 2 + pos[1];
1723 }
1724 pos += 2 + pos[1];
1725 }
1726 }
1727
334234b5
VT
1728 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
1729 WMI_FRAME_PROBE_RESP, buf, len);
8bdfbf40
JM
1730 kfree(buf);
1731 return ret;
1732}
1733
6a7c9bad
JM
1734static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
1735 struct beacon_parameters *info, bool add)
1736{
1737 struct ath6kl *ar = ath6kl_priv(dev);
3450334f 1738 struct ath6kl_vif *vif = netdev_priv(dev);
6a7c9bad
JM
1739 struct ieee80211_mgmt *mgmt;
1740 u8 *ies;
1741 int ies_len;
1742 struct wmi_connect_cmd p;
1743 int res;
1744 int i;
1745
1746 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: add=%d\n", __func__, add);
1747
990bd915 1748 if (!ath6kl_cfg80211_ready(vif))
6a7c9bad
JM
1749 return -EIO;
1750
f5938f24 1751 if (vif->next_mode != AP_NETWORK)
6a7c9bad
JM
1752 return -EOPNOTSUPP;
1753
1754 if (info->beacon_ies) {
334234b5
VT
1755 res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
1756 WMI_FRAME_BEACON,
6a7c9bad
JM
1757 info->beacon_ies,
1758 info->beacon_ies_len);
1759 if (res)
1760 return res;
1761 }
1762 if (info->proberesp_ies) {
334234b5 1763 res = ath6kl_set_ap_probe_resp_ies(vif, info->proberesp_ies,
8bdfbf40 1764 info->proberesp_ies_len);
6a7c9bad
JM
1765 if (res)
1766 return res;
1767 }
1768 if (info->assocresp_ies) {
334234b5
VT
1769 res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
1770 WMI_FRAME_ASSOC_RESP,
6a7c9bad
JM
1771 info->assocresp_ies,
1772 info->assocresp_ies_len);
1773 if (res)
1774 return res;
1775 }
1776
1777 if (!add)
1778 return 0;
1779
9a5b1318
JM
1780 ar->ap_mode_bkey.valid = false;
1781
6a7c9bad
JM
1782 /* TODO:
1783 * info->interval
1784 * info->dtim_period
1785 */
1786
1787 if (info->head == NULL)
1788 return -EINVAL;
1789 mgmt = (struct ieee80211_mgmt *) info->head;
1790 ies = mgmt->u.beacon.variable;
1791 if (ies > info->head + info->head_len)
1792 return -EINVAL;
1793 ies_len = info->head + info->head_len - ies;
1794
1795 if (info->ssid == NULL)
1796 return -EINVAL;
3450334f
VT
1797 memcpy(vif->ssid, info->ssid, info->ssid_len);
1798 vif->ssid_len = info->ssid_len;
6a7c9bad
JM
1799 if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1800 return -EOPNOTSUPP; /* TODO */
1801
3450334f 1802 vif->dot11_auth_mode = OPEN_AUTH;
6a7c9bad
JM
1803
1804 memset(&p, 0, sizeof(p));
1805
1806 for (i = 0; i < info->crypto.n_akm_suites; i++) {
1807 switch (info->crypto.akm_suites[i]) {
1808 case WLAN_AKM_SUITE_8021X:
1809 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1810 p.auth_mode |= WPA_AUTH;
1811 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1812 p.auth_mode |= WPA2_AUTH;
1813 break;
1814 case WLAN_AKM_SUITE_PSK:
1815 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1816 p.auth_mode |= WPA_PSK_AUTH;
1817 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1818 p.auth_mode |= WPA2_PSK_AUTH;
1819 break;
1820 }
1821 }
1822 if (p.auth_mode == 0)
1823 p.auth_mode = NONE_AUTH;
3450334f 1824 vif->auth_mode = p.auth_mode;
6a7c9bad
JM
1825
1826 for (i = 0; i < info->crypto.n_ciphers_pairwise; i++) {
1827 switch (info->crypto.ciphers_pairwise[i]) {
1828 case WLAN_CIPHER_SUITE_WEP40:
1829 case WLAN_CIPHER_SUITE_WEP104:
1830 p.prwise_crypto_type |= WEP_CRYPT;
1831 break;
1832 case WLAN_CIPHER_SUITE_TKIP:
1833 p.prwise_crypto_type |= TKIP_CRYPT;
1834 break;
1835 case WLAN_CIPHER_SUITE_CCMP:
1836 p.prwise_crypto_type |= AES_CRYPT;
1837 break;
1838 }
1839 }
229ed6b5 1840 if (p.prwise_crypto_type == 0) {
6a7c9bad 1841 p.prwise_crypto_type = NONE_CRYPT;
240d2799 1842 ath6kl_set_cipher(vif, 0, true);
229ed6b5 1843 } else if (info->crypto.n_ciphers_pairwise == 1)
240d2799 1844 ath6kl_set_cipher(vif, info->crypto.ciphers_pairwise[0], true);
6a7c9bad
JM
1845
1846 switch (info->crypto.cipher_group) {
1847 case WLAN_CIPHER_SUITE_WEP40:
1848 case WLAN_CIPHER_SUITE_WEP104:
1849 p.grp_crypto_type = WEP_CRYPT;
1850 break;
1851 case WLAN_CIPHER_SUITE_TKIP:
1852 p.grp_crypto_type = TKIP_CRYPT;
1853 break;
1854 case WLAN_CIPHER_SUITE_CCMP:
1855 p.grp_crypto_type = AES_CRYPT;
1856 break;
1857 default:
1858 p.grp_crypto_type = NONE_CRYPT;
1859 break;
1860 }
240d2799 1861 ath6kl_set_cipher(vif, info->crypto.cipher_group, false);
6a7c9bad
JM
1862
1863 p.nw_type = AP_NETWORK;
f5938f24 1864 vif->nw_type = vif->next_mode;
6a7c9bad 1865
3450334f
VT
1866 p.ssid_len = vif->ssid_len;
1867 memcpy(p.ssid, vif->ssid, vif->ssid_len);
1868 p.dot11_auth_mode = vif->dot11_auth_mode;
cf5333d7 1869 p.ch = cpu_to_le16(vif->next_chan);
6a7c9bad 1870
334234b5 1871 res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p);
9a5b1318
JM
1872 if (res < 0)
1873 return res;
1874
1875 return 0;
6a7c9bad
JM
1876}
1877
1878static int ath6kl_add_beacon(struct wiphy *wiphy, struct net_device *dev,
1879 struct beacon_parameters *info)
1880{
1881 return ath6kl_ap_beacon(wiphy, dev, info, true);
1882}
1883
1884static int ath6kl_set_beacon(struct wiphy *wiphy, struct net_device *dev,
1885 struct beacon_parameters *info)
1886{
1887 return ath6kl_ap_beacon(wiphy, dev, info, false);
1888}
1889
1890static int ath6kl_del_beacon(struct wiphy *wiphy, struct net_device *dev)
1891{
1892 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 1893 struct ath6kl_vif *vif = netdev_priv(dev);
6a7c9bad 1894
f5938f24 1895 if (vif->nw_type != AP_NETWORK)
6a7c9bad 1896 return -EOPNOTSUPP;
59c98449 1897 if (!test_bit(CONNECTED, &vif->flags))
6a7c9bad
JM
1898 return -ENOTCONN;
1899
334234b5 1900 ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
59c98449 1901 clear_bit(CONNECTED, &vif->flags);
6a7c9bad
JM
1902
1903 return 0;
1904}
1905
23875136
JM
1906static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
1907 u8 *mac, struct station_parameters *params)
1908{
1909 struct ath6kl *ar = ath6kl_priv(dev);
f5938f24 1910 struct ath6kl_vif *vif = netdev_priv(dev);
23875136 1911
f5938f24 1912 if (vif->nw_type != AP_NETWORK)
23875136
JM
1913 return -EOPNOTSUPP;
1914
1915 /* Use this only for authorizing/unauthorizing a station */
1916 if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
1917 return -EOPNOTSUPP;
1918
1919 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
334234b5
VT
1920 return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx,
1921 WMI_AP_MLME_AUTHORIZE, mac, 0);
1922 return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx,
1923 WMI_AP_MLME_UNAUTHORIZE, mac, 0);
23875136
JM
1924}
1925
63fa1e0c
JM
1926static int ath6kl_remain_on_channel(struct wiphy *wiphy,
1927 struct net_device *dev,
1928 struct ieee80211_channel *chan,
1929 enum nl80211_channel_type channel_type,
1930 unsigned int duration,
1931 u64 *cookie)
1932{
1933 struct ath6kl *ar = ath6kl_priv(dev);
334234b5 1934 struct ath6kl_vif *vif = netdev_priv(dev);
63fa1e0c
JM
1935
1936 /* TODO: if already pending or ongoing remain-on-channel,
1937 * return -EBUSY */
1938 *cookie = 1; /* only a single pending request is supported */
1939
334234b5
VT
1940 return ath6kl_wmi_remain_on_chnl_cmd(ar->wmi, vif->fw_vif_idx,
1941 chan->center_freq, duration);
63fa1e0c
JM
1942}
1943
1944static int ath6kl_cancel_remain_on_channel(struct wiphy *wiphy,
1945 struct net_device *dev,
1946 u64 cookie)
1947{
1948 struct ath6kl *ar = ath6kl_priv(dev);
334234b5 1949 struct ath6kl_vif *vif = netdev_priv(dev);
63fa1e0c
JM
1950
1951 if (cookie != 1)
1952 return -ENOENT;
1953
334234b5 1954 return ath6kl_wmi_cancel_remain_on_chnl_cmd(ar->wmi, vif->fw_vif_idx);
63fa1e0c
JM
1955}
1956
334234b5
VT
1957static int ath6kl_send_go_probe_resp(struct ath6kl_vif *vif,
1958 const u8 *buf, size_t len,
1959 unsigned int freq)
8bdfbf40 1960{
334234b5 1961 struct ath6kl *ar = vif->ar;
8bdfbf40
JM
1962 const u8 *pos;
1963 u8 *p2p;
1964 int p2p_len;
1965 int ret;
1966 const struct ieee80211_mgmt *mgmt;
1967
1968 mgmt = (const struct ieee80211_mgmt *) buf;
1969
1970 /* Include P2P IE(s) from the frame generated in user space. */
1971
1972 p2p = kmalloc(len, GFP_KERNEL);
1973 if (p2p == NULL)
1974 return -ENOMEM;
1975 p2p_len = 0;
1976
1977 pos = mgmt->u.probe_resp.variable;
1978 while (pos + 1 < buf + len) {
1979 if (pos + 2 + pos[1] > buf + len)
1980 break;
1981 if (ath6kl_is_p2p_ie(pos)) {
1982 memcpy(p2p + p2p_len, pos, 2 + pos[1]);
1983 p2p_len += 2 + pos[1];
1984 }
1985 pos += 2 + pos[1];
1986 }
1987
334234b5
VT
1988 ret = ath6kl_wmi_send_probe_response_cmd(ar->wmi, vif->fw_vif_idx, freq,
1989 mgmt->da, p2p, p2p_len);
8bdfbf40
JM
1990 kfree(p2p);
1991 return ret;
1992}
1993
8a6c8060
JM
1994static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
1995 struct ieee80211_channel *chan, bool offchan,
1996 enum nl80211_channel_type channel_type,
1997 bool channel_type_valid, unsigned int wait,
e247bd90
JB
1998 const u8 *buf, size_t len, bool no_cck,
1999 bool dont_wait_for_ack, u64 *cookie)
8a6c8060
JM
2000{
2001 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 2002 struct ath6kl_vif *vif = netdev_priv(dev);
8a6c8060 2003 u32 id;
8bdfbf40
JM
2004 const struct ieee80211_mgmt *mgmt;
2005
2006 mgmt = (const struct ieee80211_mgmt *) buf;
2007 if (buf + len >= mgmt->u.probe_resp.variable &&
f5938f24 2008 vif->nw_type == AP_NETWORK && test_bit(CONNECTED, &vif->flags) &&
8bdfbf40
JM
2009 ieee80211_is_probe_resp(mgmt->frame_control)) {
2010 /*
2011 * Send Probe Response frame in AP mode using a separate WMI
2012 * command to allow the target to fill in the generic IEs.
2013 */
2014 *cookie = 0; /* TX status not supported */
334234b5 2015 return ath6kl_send_go_probe_resp(vif, buf, len,
8bdfbf40
JM
2016 chan->center_freq);
2017 }
8a6c8060 2018
cf5333d7 2019 id = vif->send_action_id++;
8a6c8060
JM
2020 if (id == 0) {
2021 /*
2022 * 0 is a reserved value in the WMI command and shall not be
2023 * used for the command.
2024 */
cf5333d7 2025 id = vif->send_action_id++;
8a6c8060
JM
2026 }
2027
2028 *cookie = id;
334234b5
VT
2029 return ath6kl_wmi_send_action_cmd(ar->wmi, vif->fw_vif_idx, id,
2030 chan->center_freq, wait,
8a6c8060
JM
2031 buf, len);
2032}
2033
ae32c30a
JM
2034static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
2035 struct net_device *dev,
2036 u16 frame_type, bool reg)
2037{
cf5333d7 2038 struct ath6kl_vif *vif = netdev_priv(dev);
ae32c30a
JM
2039
2040 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: frame_type=0x%x reg=%d\n",
2041 __func__, frame_type, reg);
2042 if (frame_type == IEEE80211_STYPE_PROBE_REQ) {
2043 /*
2044 * Note: This notification callback is not allowed to sleep, so
2045 * we cannot send WMI_PROBE_REQ_REPORT_CMD here. Instead, we
2046 * hardcode target to report Probe Request frames all the time.
2047 */
cf5333d7 2048 vif->probe_req_report = reg;
ae32c30a
JM
2049 }
2050}
2051
f80574ae
JM
2052static const struct ieee80211_txrx_stypes
2053ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
2054 [NL80211_IFTYPE_STATION] = {
2055 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2056 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
2057 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2058 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
2059 },
2060 [NL80211_IFTYPE_P2P_CLIENT] = {
2061 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2062 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
2063 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2064 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
2065 },
2066 [NL80211_IFTYPE_P2P_GO] = {
2067 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2068 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
2069 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2070 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
2071 },
2072};
2073
bdcd8170 2074static struct cfg80211_ops ath6kl_cfg80211_ops = {
55055976
VT
2075 .add_virtual_intf = ath6kl_cfg80211_add_iface,
2076 .del_virtual_intf = ath6kl_cfg80211_del_iface,
bdcd8170
KV
2077 .change_virtual_intf = ath6kl_cfg80211_change_iface,
2078 .scan = ath6kl_cfg80211_scan,
2079 .connect = ath6kl_cfg80211_connect,
2080 .disconnect = ath6kl_cfg80211_disconnect,
2081 .add_key = ath6kl_cfg80211_add_key,
2082 .get_key = ath6kl_cfg80211_get_key,
2083 .del_key = ath6kl_cfg80211_del_key,
2084 .set_default_key = ath6kl_cfg80211_set_default_key,
2085 .set_wiphy_params = ath6kl_cfg80211_set_wiphy_params,
2086 .set_tx_power = ath6kl_cfg80211_set_txpower,
2087 .get_tx_power = ath6kl_cfg80211_get_txpower,
2088 .set_power_mgmt = ath6kl_cfg80211_set_power_mgmt,
2089 .join_ibss = ath6kl_cfg80211_join_ibss,
2090 .leave_ibss = ath6kl_cfg80211_leave_ibss,
2091 .get_station = ath6kl_get_station,
2092 .set_pmksa = ath6kl_set_pmksa,
2093 .del_pmksa = ath6kl_del_pmksa,
2094 .flush_pmksa = ath6kl_flush_pmksa,
003353b0 2095 CFG80211_TESTMODE_CMD(ath6kl_tm_cmd)
abcb344b
KV
2096#ifdef CONFIG_PM
2097 .suspend = ar6k_cfg80211_suspend,
aa6cffc1 2098 .resume = ar6k_cfg80211_resume,
abcb344b 2099#endif
6a7c9bad
JM
2100 .set_channel = ath6kl_set_channel,
2101 .add_beacon = ath6kl_add_beacon,
2102 .set_beacon = ath6kl_set_beacon,
2103 .del_beacon = ath6kl_del_beacon,
23875136 2104 .change_station = ath6kl_change_station,
63fa1e0c
JM
2105 .remain_on_channel = ath6kl_remain_on_channel,
2106 .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel,
8a6c8060 2107 .mgmt_tx = ath6kl_mgmt_tx,
ae32c30a 2108 .mgmt_frame_register = ath6kl_mgmt_frame_register,
bdcd8170
KV
2109};
2110
8dafb70e 2111struct ath6kl *ath6kl_core_alloc(struct device *dev)
bdcd8170 2112{
6bbc7c35 2113 struct ath6kl *ar;
be98e3a4 2114 struct wiphy *wiphy;
8dafb70e 2115 u8 ctr;
bdcd8170
KV
2116
2117 /* create a new wiphy for use with cfg80211 */
be98e3a4 2118 wiphy = wiphy_new(&ath6kl_cfg80211_ops, sizeof(struct ath6kl));
8dafb70e 2119
be98e3a4 2120 if (!wiphy) {
bdcd8170 2121 ath6kl_err("couldn't allocate wiphy device\n");
bdcd8170
KV
2122 return NULL;
2123 }
2124
be98e3a4 2125 ar = wiphy_priv(wiphy);
3226f68a
VT
2126 if (!multi_norm_if_support)
2127 ar->p2p = !!ath6kl_p2p;
be98e3a4 2128 ar->wiphy = wiphy;
8dafb70e
VT
2129 ar->dev = dev;
2130
3226f68a
VT
2131 if (multi_norm_if_support)
2132 ar->max_norm_iface = 2;
2133 else
2134 ar->max_norm_iface = 1;
2135
2136 /* FIXME: Remove this once the multivif support is enabled */
2137 ar->max_norm_iface = 1;
2138
8dafb70e
VT
2139 spin_lock_init(&ar->lock);
2140 spin_lock_init(&ar->mcastpsq_lock);
990bd915 2141 spin_lock_init(&ar->list_lock);
8dafb70e
VT
2142
2143 init_waitqueue_head(&ar->event_wq);
2144 sema_init(&ar->sem, 1);
2145
2146 INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue);
990bd915 2147 INIT_LIST_HEAD(&ar->vif_list);
8dafb70e
VT
2148
2149 clear_bit(WMI_ENABLED, &ar->flag);
2150 clear_bit(SKIP_SCAN, &ar->flag);
2151 clear_bit(DESTROY_IN_PROGRESS, &ar->flag);
2152
2153 ar->listen_intvl_t = A_DEFAULT_LISTEN_INTERVAL;
2154 ar->listen_intvl_b = 0;
2155 ar->tx_pwr = 0;
2156
2157 ar->intra_bss = 1;
2158 memset(&ar->sc_params, 0, sizeof(ar->sc_params));
2159 ar->sc_params.short_scan_ratio = WMI_SHORTSCANRATIO_DEFAULT;
2160 ar->sc_params.scan_ctrl_flags = DEFAULT_SCAN_CTRL_FLAGS;
2161 ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD;
2162
2163 memset((u8 *)ar->sta_list, 0,
2164 AP_MAX_NUM_STA * sizeof(struct ath6kl_sta));
2165
2166 /* Init the PS queues */
2167 for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) {
2168 spin_lock_init(&ar->sta_list[ctr].psq_lock);
2169 skb_queue_head_init(&ar->sta_list[ctr].psq);
2170 }
2171
2172 skb_queue_head_init(&ar->mcastpsq);
2173
2174 memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3);
2175
2176 return ar;
2177}
2178
2179int ath6kl_register_ieee80211_hw(struct ath6kl *ar)
2180{
2181 struct wiphy *wiphy = ar->wiphy;
2182 int ret;
6bbc7c35 2183
be98e3a4 2184 wiphy->mgmt_stypes = ath6kl_mgmt_stypes;
f80574ae 2185
be98e3a4 2186 wiphy->max_remain_on_channel_duration = 5000;
63fa1e0c 2187
bdcd8170 2188 /* set device pointer for wiphy */
8dafb70e 2189 set_wiphy_dev(wiphy, ar->dev);
bdcd8170 2190
be98e3a4 2191 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
8dafb70e
VT
2192 BIT(NL80211_IFTYPE_ADHOC) |
2193 BIT(NL80211_IFTYPE_AP);
6bbc7c35 2194 if (ar->p2p) {
be98e3a4 2195 wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_GO) |
8dafb70e 2196 BIT(NL80211_IFTYPE_P2P_CLIENT);
6bbc7c35 2197 }
8dafb70e 2198
bdcd8170 2199 /* max num of ssids that can be probed during scanning */
be98e3a4
VT
2200 wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
2201 wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
2202 wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
2203 wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz;
2204 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
bdcd8170 2205
be98e3a4
VT
2206 wiphy->cipher_suites = cipher_suites;
2207 wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
bdcd8170 2208
be98e3a4 2209 ret = wiphy_register(wiphy);
bdcd8170
KV
2210 if (ret < 0) {
2211 ath6kl_err("couldn't register wiphy device\n");
8dafb70e 2212 return ret;
bdcd8170
KV
2213 }
2214
8dafb70e 2215 return 0;
bdcd8170
KV
2216}
2217
108438bc 2218static int ath6kl_init_if_data(struct ath6kl_vif *vif)
bdcd8170 2219{
2132c69c
VT
2220 vif->aggr_cntxt = aggr_init(vif->ndev);
2221 if (!vif->aggr_cntxt) {
8dafb70e
VT
2222 ath6kl_err("failed to initialize aggr\n");
2223 return -ENOMEM;
2224 }
2225
de3ad713 2226 setup_timer(&vif->disconnect_timer, disconnect_timer_handler,
108438bc 2227 (unsigned long) vif->ndev);
de3ad713 2228 set_bit(WMM_ENABLED, &vif->flags);
478ac027 2229 spin_lock_init(&vif->if_lock);
bdcd8170 2230
8dafb70e
VT
2231 return 0;
2232}
2233
108438bc 2234void ath6kl_deinit_if_data(struct ath6kl_vif *vif)
8dafb70e 2235{
55055976
VT
2236 struct ath6kl *ar = vif->ar;
2237
2132c69c 2238 aggr_module_destroy(vif->aggr_cntxt);
8dafb70e 2239
55055976
VT
2240 ar->avail_idx_map |= BIT(vif->fw_vif_idx);
2241
2242 if (vif->nw_type == ADHOC_NETWORK)
2243 ar->ibss_if_active = false;
2244
27929723 2245 unregister_netdevice(vif->ndev);
55055976
VT
2246
2247 ar->num_vif--;
8dafb70e
VT
2248}
2249
2250struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
55055976
VT
2251 enum nl80211_iftype type, u8 fw_vif_idx,
2252 u8 nw_type)
8dafb70e
VT
2253{
2254 struct net_device *ndev;
108438bc 2255 struct ath6kl_vif *vif;
8dafb70e 2256
55055976 2257 ndev = alloc_netdev(sizeof(*vif), name, ether_setup);
8dafb70e
VT
2258 if (!ndev)
2259 return NULL;
2260
108438bc
VT
2261 vif = netdev_priv(ndev);
2262 ndev->ieee80211_ptr = &vif->wdev;
2263 vif->wdev.wiphy = ar->wiphy;
2264 vif->ar = ar;
108438bc
VT
2265 vif->ndev = ndev;
2266 SET_NETDEV_DEV(ndev, wiphy_dev(vif->wdev.wiphy));
2267 vif->wdev.netdev = ndev;
2268 vif->wdev.iftype = type;
334234b5 2269 vif->fw_vif_idx = fw_vif_idx;
55055976 2270 vif->nw_type = vif->next_mode = nw_type;
8dafb70e 2271
55055976
VT
2272 memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
2273 if (fw_vif_idx != 0)
2274 ndev->dev_addr[0] = (ndev->dev_addr[0] ^ (1 << fw_vif_idx)) |
2275 0x2;
2276
8dafb70e
VT
2277 init_netdev(ndev);
2278
e29f25f5 2279 ath6kl_init_control_info(vif);
8dafb70e
VT
2280
2281 /* TODO: Pass interface specific pointer instead of ar */
108438bc 2282 if (ath6kl_init_if_data(vif))
8dafb70e
VT
2283 goto err;
2284
27929723 2285 if (register_netdevice(ndev))
8dafb70e
VT
2286 goto err;
2287
55055976 2288 ar->avail_idx_map &= ~BIT(fw_vif_idx);
14ee6f6b 2289 vif->sme_state = SME_DISCONNECTED;
59c98449 2290 set_bit(WLAN_ENABLED, &vif->flags);
8dafb70e 2291 ar->wlan_pwr_state = WLAN_POWER_STATE_ON;
59c98449 2292 set_bit(NETDEV_REGISTERED, &vif->flags);
8dafb70e 2293
55055976
VT
2294 if (type == NL80211_IFTYPE_ADHOC)
2295 ar->ibss_if_active = true;
2296
990bd915
VT
2297 spin_lock(&ar->list_lock);
2298 list_add_tail(&vif->list, &ar->vif_list);
2299 spin_unlock(&ar->list_lock);
2300
8dafb70e
VT
2301 return ndev;
2302
2303err:
27929723
VT
2304 aggr_module_destroy(vif->aggr_cntxt);
2305 free_netdev(ndev);
8dafb70e
VT
2306 return NULL;
2307}
2308
2309void ath6kl_deinit_ieee80211_hw(struct ath6kl *ar)
2310{
be98e3a4
VT
2311 wiphy_unregister(ar->wiphy);
2312 wiphy_free(ar->wiphy);
bdcd8170 2313}
This page took 0.209102 seconds and 5 git commands to generate.