ath6kl: fix error handling ath6kl_target_config_wlan_params()
[linux-block.git] / drivers / net / wireless / ath / ath6kl / cfg80211.c
CommitLineData
bdcd8170
KV
1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc.
1b2df407 3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
bdcd8170
KV
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
6eb07caf 18#include <linux/moduleparam.h>
c08631c6 19#include <linux/inetdevice.h>
d6a434d6 20#include <linux/export.h>
6eb07caf 21
bdcd8170
KV
22#include "core.h"
23#include "cfg80211.h"
24#include "debug.h"
abcb344b 25#include "hif-ops.h"
003353b0 26#include "testmode.h"
bdcd8170
KV
27
28#define RATETAB_ENT(_rate, _rateid, _flags) { \
29 .bitrate = (_rate), \
30 .flags = (_flags), \
31 .hw_value = (_rateid), \
32}
33
34#define CHAN2G(_channel, _freq, _flags) { \
35 .band = IEEE80211_BAND_2GHZ, \
36 .hw_value = (_channel), \
37 .center_freq = (_freq), \
38 .flags = (_flags), \
39 .max_antenna_gain = 0, \
40 .max_power = 30, \
41}
42
43#define CHAN5G(_channel, _flags) { \
44 .band = IEEE80211_BAND_5GHZ, \
45 .hw_value = (_channel), \
46 .center_freq = 5000 + (5 * (_channel)), \
47 .flags = (_flags), \
48 .max_antenna_gain = 0, \
49 .max_power = 30, \
50}
51
52static struct ieee80211_rate ath6kl_rates[] = {
53 RATETAB_ENT(10, 0x1, 0),
54 RATETAB_ENT(20, 0x2, 0),
55 RATETAB_ENT(55, 0x4, 0),
56 RATETAB_ENT(110, 0x8, 0),
57 RATETAB_ENT(60, 0x10, 0),
58 RATETAB_ENT(90, 0x20, 0),
59 RATETAB_ENT(120, 0x40, 0),
60 RATETAB_ENT(180, 0x80, 0),
61 RATETAB_ENT(240, 0x100, 0),
62 RATETAB_ENT(360, 0x200, 0),
63 RATETAB_ENT(480, 0x400, 0),
64 RATETAB_ENT(540, 0x800, 0),
65};
66
67#define ath6kl_a_rates (ath6kl_rates + 4)
68#define ath6kl_a_rates_size 8
69#define ath6kl_g_rates (ath6kl_rates + 0)
70#define ath6kl_g_rates_size 12
71
faaf1929
VT
72#define ath6kl_g_htcap (IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \
73 IEEE80211_HT_CAP_SGI_20 | \
74 IEEE80211_HT_CAP_SGI_40)
75
bdcd8170
KV
76static struct ieee80211_channel ath6kl_2ghz_channels[] = {
77 CHAN2G(1, 2412, 0),
78 CHAN2G(2, 2417, 0),
79 CHAN2G(3, 2422, 0),
80 CHAN2G(4, 2427, 0),
81 CHAN2G(5, 2432, 0),
82 CHAN2G(6, 2437, 0),
83 CHAN2G(7, 2442, 0),
84 CHAN2G(8, 2447, 0),
85 CHAN2G(9, 2452, 0),
86 CHAN2G(10, 2457, 0),
87 CHAN2G(11, 2462, 0),
88 CHAN2G(12, 2467, 0),
89 CHAN2G(13, 2472, 0),
90 CHAN2G(14, 2484, 0),
91};
92
93static struct ieee80211_channel ath6kl_5ghz_a_channels[] = {
94 CHAN5G(34, 0), CHAN5G(36, 0),
95 CHAN5G(38, 0), CHAN5G(40, 0),
96 CHAN5G(42, 0), CHAN5G(44, 0),
97 CHAN5G(46, 0), CHAN5G(48, 0),
98 CHAN5G(52, 0), CHAN5G(56, 0),
99 CHAN5G(60, 0), CHAN5G(64, 0),
100 CHAN5G(100, 0), CHAN5G(104, 0),
101 CHAN5G(108, 0), CHAN5G(112, 0),
102 CHAN5G(116, 0), CHAN5G(120, 0),
103 CHAN5G(124, 0), CHAN5G(128, 0),
104 CHAN5G(132, 0), CHAN5G(136, 0),
105 CHAN5G(140, 0), CHAN5G(149, 0),
106 CHAN5G(153, 0), CHAN5G(157, 0),
107 CHAN5G(161, 0), CHAN5G(165, 0),
108 CHAN5G(184, 0), CHAN5G(188, 0),
109 CHAN5G(192, 0), CHAN5G(196, 0),
110 CHAN5G(200, 0), CHAN5G(204, 0),
111 CHAN5G(208, 0), CHAN5G(212, 0),
112 CHAN5G(216, 0),
113};
114
115static struct ieee80211_supported_band ath6kl_band_2ghz = {
116 .n_channels = ARRAY_SIZE(ath6kl_2ghz_channels),
117 .channels = ath6kl_2ghz_channels,
118 .n_bitrates = ath6kl_g_rates_size,
119 .bitrates = ath6kl_g_rates,
faaf1929
VT
120 .ht_cap.cap = ath6kl_g_htcap,
121 .ht_cap.ht_supported = true,
bdcd8170
KV
122};
123
124static struct ieee80211_supported_band ath6kl_band_5ghz = {
125 .n_channels = ARRAY_SIZE(ath6kl_5ghz_a_channels),
126 .channels = ath6kl_5ghz_a_channels,
127 .n_bitrates = ath6kl_a_rates_size,
128 .bitrates = ath6kl_a_rates,
faaf1929
VT
129 .ht_cap.cap = ath6kl_g_htcap,
130 .ht_cap.ht_supported = true,
bdcd8170
KV
131};
132
837cb97e
JM
133#define CCKM_KRK_CIPHER_SUITE 0x004096ff /* use for KRK */
134
10509f90
KV
135/* returns true if scheduled scan was stopped */
136static bool __ath6kl_cfg80211_sscan_stop(struct ath6kl_vif *vif)
137{
138 struct ath6kl *ar = vif->ar;
139
140 if (ar->state != ATH6KL_STATE_SCHED_SCAN)
141 return false;
142
143 del_timer_sync(&vif->sched_scan_timer);
144
145 ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
146 ATH6KL_HOST_MODE_AWAKE);
147
148 ar->state = ATH6KL_STATE_ON;
149
150 return true;
151}
152
153static void ath6kl_cfg80211_sscan_disable(struct ath6kl_vif *vif)
154{
155 struct ath6kl *ar = vif->ar;
156 bool stopped;
157
158 stopped = __ath6kl_cfg80211_sscan_stop(vif);
159
160 if (!stopped)
161 return;
162
163 cfg80211_sched_scan_stopped(ar->wiphy);
164}
165
240d2799 166static int ath6kl_set_wpa_version(struct ath6kl_vif *vif,
bdcd8170
KV
167 enum nl80211_wpa_versions wpa_version)
168{
169 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: %u\n", __func__, wpa_version);
170
171 if (!wpa_version) {
3450334f 172 vif->auth_mode = NONE_AUTH;
bdcd8170 173 } else if (wpa_version & NL80211_WPA_VERSION_2) {
3450334f 174 vif->auth_mode = WPA2_AUTH;
bdcd8170 175 } else if (wpa_version & NL80211_WPA_VERSION_1) {
3450334f 176 vif->auth_mode = WPA_AUTH;
bdcd8170
KV
177 } else {
178 ath6kl_err("%s: %u not supported\n", __func__, wpa_version);
179 return -ENOTSUPP;
180 }
181
182 return 0;
183}
184
240d2799 185static int ath6kl_set_auth_type(struct ath6kl_vif *vif,
bdcd8170
KV
186 enum nl80211_auth_type auth_type)
187{
bdcd8170
KV
188 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: 0x%x\n", __func__, auth_type);
189
190 switch (auth_type) {
191 case NL80211_AUTHTYPE_OPEN_SYSTEM:
3450334f 192 vif->dot11_auth_mode = OPEN_AUTH;
bdcd8170
KV
193 break;
194 case NL80211_AUTHTYPE_SHARED_KEY:
3450334f 195 vif->dot11_auth_mode = SHARED_AUTH;
bdcd8170
KV
196 break;
197 case NL80211_AUTHTYPE_NETWORK_EAP:
3450334f 198 vif->dot11_auth_mode = LEAP_AUTH;
bdcd8170
KV
199 break;
200
201 case NL80211_AUTHTYPE_AUTOMATIC:
3450334f 202 vif->dot11_auth_mode = OPEN_AUTH | SHARED_AUTH;
bdcd8170
KV
203 break;
204
205 default:
3c325fbd 206 ath6kl_err("%s: 0x%x not supported\n", __func__, auth_type);
bdcd8170
KV
207 return -ENOTSUPP;
208 }
209
210 return 0;
211}
212
240d2799 213static int ath6kl_set_cipher(struct ath6kl_vif *vif, u32 cipher, bool ucast)
bdcd8170 214{
3450334f
VT
215 u8 *ar_cipher = ucast ? &vif->prwise_crypto : &vif->grp_crypto;
216 u8 *ar_cipher_len = ucast ? &vif->prwise_crypto_len :
217 &vif->grp_crypto_len;
bdcd8170
KV
218
219 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: cipher 0x%x, ucast %u\n",
220 __func__, cipher, ucast);
221
222 switch (cipher) {
223 case 0:
224 /* our own hack to use value 0 as no crypto used */
225 *ar_cipher = NONE_CRYPT;
226 *ar_cipher_len = 0;
227 break;
228 case WLAN_CIPHER_SUITE_WEP40:
229 *ar_cipher = WEP_CRYPT;
230 *ar_cipher_len = 5;
231 break;
232 case WLAN_CIPHER_SUITE_WEP104:
233 *ar_cipher = WEP_CRYPT;
234 *ar_cipher_len = 13;
235 break;
236 case WLAN_CIPHER_SUITE_TKIP:
237 *ar_cipher = TKIP_CRYPT;
238 *ar_cipher_len = 0;
239 break;
240 case WLAN_CIPHER_SUITE_CCMP:
241 *ar_cipher = AES_CRYPT;
242 *ar_cipher_len = 0;
243 break;
5e07021e
DS
244 case WLAN_CIPHER_SUITE_SMS4:
245 *ar_cipher = WAPI_CRYPT;
246 *ar_cipher_len = 0;
247 break;
bdcd8170
KV
248 default:
249 ath6kl_err("cipher 0x%x not supported\n", cipher);
250 return -ENOTSUPP;
251 }
252
253 return 0;
254}
255
240d2799 256static void ath6kl_set_key_mgmt(struct ath6kl_vif *vif, u32 key_mgmt)
bdcd8170
KV
257{
258 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: 0x%x\n", __func__, key_mgmt);
259
260 if (key_mgmt == WLAN_AKM_SUITE_PSK) {
3450334f
VT
261 if (vif->auth_mode == WPA_AUTH)
262 vif->auth_mode = WPA_PSK_AUTH;
263 else if (vif->auth_mode == WPA2_AUTH)
264 vif->auth_mode = WPA2_PSK_AUTH;
837cb97e 265 } else if (key_mgmt == 0x00409600) {
3450334f
VT
266 if (vif->auth_mode == WPA_AUTH)
267 vif->auth_mode = WPA_AUTH_CCKM;
268 else if (vif->auth_mode == WPA2_AUTH)
269 vif->auth_mode = WPA2_AUTH_CCKM;
bdcd8170 270 } else if (key_mgmt != WLAN_AKM_SUITE_8021X) {
3450334f 271 vif->auth_mode = NONE_AUTH;
bdcd8170
KV
272 }
273}
274
990bd915 275static bool ath6kl_cfg80211_ready(struct ath6kl_vif *vif)
bdcd8170 276{
990bd915 277 struct ath6kl *ar = vif->ar;
59c98449 278
bdcd8170
KV
279 if (!test_bit(WMI_READY, &ar->flag)) {
280 ath6kl_err("wmi is not ready\n");
281 return false;
282 }
283
59c98449 284 if (!test_bit(WLAN_ENABLED, &vif->flags)) {
bdcd8170
KV
285 ath6kl_err("wlan disabled\n");
286 return false;
287 }
288
289 return true;
290}
291
6981ffdc
KF
292static bool ath6kl_is_wpa_ie(const u8 *pos)
293{
294 return pos[0] == WLAN_EID_WPA && pos[1] >= 4 &&
295 pos[2] == 0x00 && pos[3] == 0x50 &&
296 pos[4] == 0xf2 && pos[5] == 0x01;
297}
298
299static bool ath6kl_is_rsn_ie(const u8 *pos)
300{
301 return pos[0] == WLAN_EID_RSN;
302}
303
63541212
AT
304static bool ath6kl_is_wps_ie(const u8 *pos)
305{
306 return (pos[0] == WLAN_EID_VENDOR_SPECIFIC &&
307 pos[1] >= 4 &&
308 pos[2] == 0x00 && pos[3] == 0x50 && pos[4] == 0xf2 &&
309 pos[5] == 0x04);
310}
311
334234b5
VT
312static int ath6kl_set_assoc_req_ies(struct ath6kl_vif *vif, const u8 *ies,
313 size_t ies_len)
6981ffdc 314{
334234b5 315 struct ath6kl *ar = vif->ar;
6981ffdc
KF
316 const u8 *pos;
317 u8 *buf = NULL;
318 size_t len = 0;
319 int ret;
320
63541212
AT
321 /*
322 * Clear previously set flag
323 */
324
325 ar->connect_ctrl_flags &= ~CONNECT_WPS_FLAG;
326
6981ffdc
KF
327 /*
328 * Filter out RSN/WPA IE(s)
329 */
330
331 if (ies && ies_len) {
332 buf = kmalloc(ies_len, GFP_KERNEL);
333 if (buf == NULL)
334 return -ENOMEM;
335 pos = ies;
336
337 while (pos + 1 < ies + ies_len) {
338 if (pos + 2 + pos[1] > ies + ies_len)
339 break;
340 if (!(ath6kl_is_wpa_ie(pos) || ath6kl_is_rsn_ie(pos))) {
341 memcpy(buf + len, pos, 2 + pos[1]);
342 len += 2 + pos[1];
343 }
63541212
AT
344
345 if (ath6kl_is_wps_ie(pos))
346 ar->connect_ctrl_flags |= CONNECT_WPS_FLAG;
347
6981ffdc
KF
348 pos += 2 + pos[1];
349 }
350 }
351
334234b5
VT
352 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
353 WMI_FRAME_ASSOC_REQ, buf, len);
6981ffdc
KF
354 kfree(buf);
355 return ret;
356}
357
55055976
VT
358static int ath6kl_nliftype_to_drv_iftype(enum nl80211_iftype type, u8 *nw_type)
359{
360 switch (type) {
361 case NL80211_IFTYPE_STATION:
362 *nw_type = INFRA_NETWORK;
363 break;
364 case NL80211_IFTYPE_ADHOC:
365 *nw_type = ADHOC_NETWORK;
366 break;
367 case NL80211_IFTYPE_AP:
368 *nw_type = AP_NETWORK;
369 break;
370 case NL80211_IFTYPE_P2P_CLIENT:
371 *nw_type = INFRA_NETWORK;
372 break;
373 case NL80211_IFTYPE_P2P_GO:
374 *nw_type = AP_NETWORK;
375 break;
376 default:
377 ath6kl_err("invalid interface type %u\n", type);
378 return -ENOTSUPP;
379 }
380
381 return 0;
382}
383
384static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type,
385 u8 *if_idx, u8 *nw_type)
386{
387 int i;
388
389 if (ath6kl_nliftype_to_drv_iftype(type, nw_type))
390 return false;
391
392 if (ar->ibss_if_active || ((type == NL80211_IFTYPE_ADHOC) &&
96f1fadc 393 ar->num_vif))
55055976
VT
394 return false;
395
396 if (type == NL80211_IFTYPE_STATION ||
397 type == NL80211_IFTYPE_AP || type == NL80211_IFTYPE_ADHOC) {
71f96ee6 398 for (i = 0; i < ar->vif_max; i++) {
55055976
VT
399 if ((ar->avail_idx_map >> i) & BIT(0)) {
400 *if_idx = i;
401 return true;
402 }
403 }
404 }
405
3226f68a
VT
406 if (type == NL80211_IFTYPE_P2P_CLIENT ||
407 type == NL80211_IFTYPE_P2P_GO) {
71f96ee6 408 for (i = ar->max_norm_iface; i < ar->vif_max; i++) {
3226f68a
VT
409 if ((ar->avail_idx_map >> i) & BIT(0)) {
410 *if_idx = i;
411 return true;
412 }
413 }
414 }
415
55055976
VT
416 return false;
417}
418
bdcd8170
KV
419static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
420 struct cfg80211_connect_params *sme)
421{
422 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 423 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170 424 int status;
3ca9d1fc 425 u8 nw_subtype = (ar->p2p) ? SUBTYPE_P2PDEV : SUBTYPE_NONE;
ce0dc0cf 426 u16 interval;
bdcd8170 427
10509f90
KV
428 ath6kl_cfg80211_sscan_disable(vif);
429
14ee6f6b 430 vif->sme_state = SME_CONNECTING;
bdcd8170 431
990bd915 432 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
433 return -EIO;
434
435 if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
436 ath6kl_err("destroy in progress\n");
437 return -EBUSY;
438 }
439
440 if (test_bit(SKIP_SCAN, &ar->flag) &&
441 ((sme->channel && sme->channel->center_freq == 0) ||
442 (sme->bssid && is_zero_ether_addr(sme->bssid)))) {
443 ath6kl_err("SkipScan: channel or bssid invalid\n");
444 return -EINVAL;
445 }
446
447 if (down_interruptible(&ar->sem)) {
448 ath6kl_err("busy, couldn't get access\n");
449 return -ERESTARTSYS;
450 }
451
452 if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
453 ath6kl_err("busy, destroy in progress\n");
454 up(&ar->sem);
455 return -EBUSY;
456 }
457
458 if (ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)]) {
459 /*
460 * sleep until the command queue drains
461 */
462 wait_event_interruptible_timeout(ar->event_wq,
463 ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)] == 0,
464 WMI_TIMEOUT);
465 if (signal_pending(current)) {
466 ath6kl_err("cmd queue drain timeout\n");
467 up(&ar->sem);
468 return -EINTR;
469 }
470 }
471
6e786cb1
JM
472 status = ath6kl_set_assoc_req_ies(vif, sme->ie, sme->ie_len);
473 if (status) {
474 up(&ar->sem);
475 return status;
476 }
477
478 if (sme->ie == NULL || sme->ie_len == 0)
542c519a 479 ar->connect_ctrl_flags &= ~CONNECT_WPS_FLAG;
6981ffdc 480
59c98449 481 if (test_bit(CONNECTED, &vif->flags) &&
3450334f
VT
482 vif->ssid_len == sme->ssid_len &&
483 !memcmp(vif->ssid, sme->ssid, vif->ssid_len)) {
cf5333d7 484 vif->reconnect_flag = true;
334234b5
VT
485 status = ath6kl_wmi_reconnect_cmd(ar->wmi, vif->fw_vif_idx,
486 vif->req_bssid,
f74bac54 487 vif->ch_hint);
bdcd8170
KV
488
489 up(&ar->sem);
490 if (status) {
491 ath6kl_err("wmi_reconnect_cmd failed\n");
492 return -EIO;
493 }
494 return 0;
3450334f
VT
495 } else if (vif->ssid_len == sme->ssid_len &&
496 !memcmp(vif->ssid, sme->ssid, vif->ssid_len)) {
240d2799 497 ath6kl_disconnect(vif);
bdcd8170
KV
498 }
499
3450334f
VT
500 memset(vif->ssid, 0, sizeof(vif->ssid));
501 vif->ssid_len = sme->ssid_len;
502 memcpy(vif->ssid, sme->ssid, sme->ssid_len);
bdcd8170
KV
503
504 if (sme->channel)
f74bac54 505 vif->ch_hint = sme->channel->center_freq;
bdcd8170 506
8c8b65e3 507 memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
bdcd8170 508 if (sme->bssid && !is_broadcast_ether_addr(sme->bssid))
8c8b65e3 509 memcpy(vif->req_bssid, sme->bssid, sizeof(vif->req_bssid));
bdcd8170 510
240d2799 511 ath6kl_set_wpa_version(vif, sme->crypto.wpa_versions);
bdcd8170 512
240d2799 513 status = ath6kl_set_auth_type(vif, sme->auth_type);
bdcd8170
KV
514 if (status) {
515 up(&ar->sem);
516 return status;
517 }
518
519 if (sme->crypto.n_ciphers_pairwise)
240d2799 520 ath6kl_set_cipher(vif, sme->crypto.ciphers_pairwise[0], true);
bdcd8170 521 else
240d2799 522 ath6kl_set_cipher(vif, 0, true);
bdcd8170 523
240d2799 524 ath6kl_set_cipher(vif, sme->crypto.cipher_group, false);
bdcd8170
KV
525
526 if (sme->crypto.n_akm_suites)
240d2799 527 ath6kl_set_key_mgmt(vif, sme->crypto.akm_suites[0]);
bdcd8170
KV
528
529 if ((sme->key_len) &&
3450334f
VT
530 (vif->auth_mode == NONE_AUTH) &&
531 (vif->prwise_crypto == WEP_CRYPT)) {
bdcd8170
KV
532 struct ath6kl_key *key = NULL;
533
792ecb33 534 if (sme->key_idx > WMI_MAX_KEY_INDEX) {
bdcd8170
KV
535 ath6kl_err("key index %d out of bounds\n",
536 sme->key_idx);
537 up(&ar->sem);
538 return -ENOENT;
539 }
540
6f2a73f9 541 key = &vif->keys[sme->key_idx];
bdcd8170
KV
542 key->key_len = sme->key_len;
543 memcpy(key->key, sme->key, key->key_len);
3450334f
VT
544 key->cipher = vif->prwise_crypto;
545 vif->def_txkey_index = sme->key_idx;
bdcd8170 546
334234b5 547 ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx, sme->key_idx,
3450334f 548 vif->prwise_crypto,
bdcd8170
KV
549 GROUP_USAGE | TX_USAGE,
550 key->key_len,
f4bb9a6f 551 NULL, 0,
bdcd8170
KV
552 key->key, KEY_OP_INIT_VAL, NULL,
553 NO_SYNC_WMIFLAG);
554 }
555
556 if (!ar->usr_bss_filter) {
59c98449 557 clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
240d2799 558 if (ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
96f1fadc 559 ALL_BSS_FILTER, 0) != 0) {
bdcd8170
KV
560 ath6kl_err("couldn't set bss filtering\n");
561 up(&ar->sem);
562 return -EIO;
563 }
564 }
565
f5938f24 566 vif->nw_type = vif->next_mode;
bdcd8170 567
3ca9d1fc
AT
568 if (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)
569 nw_subtype = SUBTYPE_P2PCLIENT;
570
bdcd8170
KV
571 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
572 "%s: connect called with authmode %d dot11 auth %d"
573 " PW crypto %d PW crypto len %d GRP crypto %d"
574 " GRP crypto len %d channel hint %u\n",
575 __func__,
3450334f
VT
576 vif->auth_mode, vif->dot11_auth_mode, vif->prwise_crypto,
577 vif->prwise_crypto_len, vif->grp_crypto,
f74bac54 578 vif->grp_crypto_len, vif->ch_hint);
bdcd8170 579
cf5333d7 580 vif->reconnect_flag = 0;
ce0dc0cf
RM
581
582 if (vif->nw_type == INFRA_NETWORK) {
583 interval = max(vif->listen_intvl_t,
584 (u16) ATH6KL_MAX_WOW_LISTEN_INTL);
585 status = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
586 interval,
587 0);
588 if (status) {
589 ath6kl_err("couldn't set listen intervel\n");
590 up(&ar->sem);
591 return status;
592 }
593 }
594
334234b5 595 status = ath6kl_wmi_connect_cmd(ar->wmi, vif->fw_vif_idx, vif->nw_type,
3450334f
VT
596 vif->dot11_auth_mode, vif->auth_mode,
597 vif->prwise_crypto,
598 vif->prwise_crypto_len,
599 vif->grp_crypto, vif->grp_crypto_len,
600 vif->ssid_len, vif->ssid,
f74bac54 601 vif->req_bssid, vif->ch_hint,
3ca9d1fc 602 ar->connect_ctrl_flags, nw_subtype);
bdcd8170
KV
603
604 up(&ar->sem);
605
606 if (status == -EINVAL) {
3450334f
VT
607 memset(vif->ssid, 0, sizeof(vif->ssid));
608 vif->ssid_len = 0;
bdcd8170
KV
609 ath6kl_err("invalid request\n");
610 return -ENOENT;
611 } else if (status) {
612 ath6kl_err("ath6kl_wmi_connect_cmd failed\n");
613 return -EIO;
614 }
615
616 if ((!(ar->connect_ctrl_flags & CONNECT_DO_WPA_OFFLOAD)) &&
ddc3d77c
KV
617 ((vif->auth_mode == WPA_PSK_AUTH) ||
618 (vif->auth_mode == WPA2_PSK_AUTH))) {
de3ad713 619 mod_timer(&vif->disconnect_timer,
bdcd8170
KV
620 jiffies + msecs_to_jiffies(DISCON_TIMER_INTVAL));
621 }
622
623 ar->connect_ctrl_flags &= ~CONNECT_DO_WPA_OFFLOAD;
59c98449 624 set_bit(CONNECT_PEND, &vif->flags);
bdcd8170
KV
625
626 return 0;
627}
628
5e13fd35
VT
629static struct cfg80211_bss *
630ath6kl_add_bss_if_needed(struct ath6kl_vif *vif,
631 enum network_type nw_type,
632 const u8 *bssid,
633 struct ieee80211_channel *chan,
634 const u8 *beacon_ie,
635 size_t beacon_ie_len)
01cac476 636{
240d2799 637 struct ath6kl *ar = vif->ar;
01cac476 638 struct cfg80211_bss *bss;
4eab6f4f 639 u16 cap_mask, cap_val;
01cac476
JM
640 u8 *ie;
641
4eab6f4f
RM
642 if (nw_type & ADHOC_NETWORK) {
643 cap_mask = WLAN_CAPABILITY_IBSS;
644 cap_val = WLAN_CAPABILITY_IBSS;
645 } else {
646 cap_mask = WLAN_CAPABILITY_ESS;
647 cap_val = WLAN_CAPABILITY_ESS;
648 }
649
be98e3a4 650 bss = cfg80211_get_bss(ar->wiphy, chan, bssid,
4eab6f4f
RM
651 vif->ssid, vif->ssid_len,
652 cap_mask, cap_val);
01cac476
JM
653 if (bss == NULL) {
654 /*
655 * Since cfg80211 may not yet know about the BSS,
656 * generate a partial entry until the first BSS info
657 * event becomes available.
658 *
659 * Prepend SSID element since it is not included in the Beacon
660 * IEs from the target.
661 */
3450334f 662 ie = kmalloc(2 + vif->ssid_len + beacon_ie_len, GFP_KERNEL);
01cac476 663 if (ie == NULL)
5e13fd35 664 return NULL;
01cac476 665 ie[0] = WLAN_EID_SSID;
3450334f
VT
666 ie[1] = vif->ssid_len;
667 memcpy(ie + 2, vif->ssid, vif->ssid_len);
668 memcpy(ie + 2 + vif->ssid_len, beacon_ie, beacon_ie_len);
be98e3a4 669 bss = cfg80211_inform_bss(ar->wiphy, chan,
4eab6f4f 670 bssid, 0, cap_val, 100,
3450334f 671 ie, 2 + vif->ssid_len + beacon_ie_len,
01cac476
JM
672 0, GFP_KERNEL);
673 if (bss)
4eab6f4f
RM
674 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added bss %pM to "
675 "cfg80211\n", bssid);
01cac476
JM
676 kfree(ie);
677 } else
5e13fd35 678 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss\n");
01cac476 679
5e13fd35 680 return bss;
01cac476
JM
681}
682
240d2799 683void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
bdcd8170
KV
684 u8 *bssid, u16 listen_intvl,
685 u16 beacon_intvl,
686 enum network_type nw_type,
687 u8 beacon_ie_len, u8 assoc_req_len,
688 u8 assoc_resp_len, u8 *assoc_info)
689{
01cac476 690 struct ieee80211_channel *chan;
240d2799 691 struct ath6kl *ar = vif->ar;
5e13fd35 692 struct cfg80211_bss *bss;
bdcd8170
KV
693
694 /* capinfo + listen interval */
695 u8 assoc_req_ie_offset = sizeof(u16) + sizeof(u16);
696
697 /* capinfo + status code + associd */
698 u8 assoc_resp_ie_offset = sizeof(u16) + sizeof(u16) + sizeof(u16);
699
700 u8 *assoc_req_ie = assoc_info + beacon_ie_len + assoc_req_ie_offset;
701 u8 *assoc_resp_ie = assoc_info + beacon_ie_len + assoc_req_len +
702 assoc_resp_ie_offset;
703
704 assoc_req_len -= assoc_req_ie_offset;
705 assoc_resp_len -= assoc_resp_ie_offset;
706
32c10874
JM
707 /*
708 * Store Beacon interval here; DTIM period will be available only once
709 * a Beacon frame from the AP is seen.
710 */
cf5333d7 711 vif->assoc_bss_beacon_int = beacon_intvl;
59c98449 712 clear_bit(DTIM_PERIOD_AVAIL, &vif->flags);
32c10874 713
bdcd8170 714 if (nw_type & ADHOC_NETWORK) {
551959d8 715 if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) {
bdcd8170
KV
716 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
717 "%s: ath6k not in ibss mode\n", __func__);
718 return;
719 }
720 }
721
722 if (nw_type & INFRA_NETWORK) {
551959d8
VT
723 if (vif->wdev.iftype != NL80211_IFTYPE_STATION &&
724 vif->wdev.iftype != NL80211_IFTYPE_P2P_CLIENT) {
bdcd8170
KV
725 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
726 "%s: ath6k not in station mode\n", __func__);
727 return;
728 }
729 }
730
be98e3a4 731 chan = ieee80211_get_channel(ar->wiphy, (int) channel);
bdcd8170 732
5e13fd35
VT
733 bss = ath6kl_add_bss_if_needed(vif, nw_type, bssid, chan,
734 assoc_info, beacon_ie_len);
735 if (!bss) {
4eab6f4f 736 ath6kl_err("could not add cfg80211 bss entry\n");
bdcd8170
KV
737 return;
738 }
739
4eab6f4f
RM
740 if (nw_type & ADHOC_NETWORK) {
741 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n",
742 nw_type & ADHOC_CREATOR ? "creator" : "joiner");
743 cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
5e13fd35 744 cfg80211_put_bss(bss);
bdcd8170
KV
745 return;
746 }
747
14ee6f6b 748 if (vif->sme_state == SME_CONNECTING) {
bdcd8170 749 /* inform connect result to cfg80211 */
14ee6f6b 750 vif->sme_state = SME_CONNECTED;
240d2799 751 cfg80211_connect_result(vif->ndev, bssid,
bdcd8170
KV
752 assoc_req_ie, assoc_req_len,
753 assoc_resp_ie, assoc_resp_len,
754 WLAN_STATUS_SUCCESS, GFP_KERNEL);
5e13fd35 755 cfg80211_put_bss(bss);
14ee6f6b 756 } else if (vif->sme_state == SME_CONNECTED) {
bdcd8170 757 /* inform roam event to cfg80211 */
5e13fd35
VT
758 cfg80211_roamed_bss(vif->ndev, bss, assoc_req_ie, assoc_req_len,
759 assoc_resp_ie, assoc_resp_len, GFP_KERNEL);
bdcd8170
KV
760 }
761}
762
763static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy,
764 struct net_device *dev, u16 reason_code)
765{
d6d5c06c 766 struct ath6kl *ar = ath6kl_priv(dev);
3450334f 767 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170
KV
768
769 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: reason=%u\n", __func__,
770 reason_code);
771
10509f90
KV
772 ath6kl_cfg80211_sscan_disable(vif);
773
990bd915 774 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
775 return -EIO;
776
777 if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
778 ath6kl_err("busy, destroy in progress\n");
779 return -EBUSY;
780 }
781
782 if (down_interruptible(&ar->sem)) {
783 ath6kl_err("busy, couldn't get access\n");
784 return -ERESTARTSYS;
785 }
786
cf5333d7 787 vif->reconnect_flag = 0;
240d2799 788 ath6kl_disconnect(vif);
3450334f
VT
789 memset(vif->ssid, 0, sizeof(vif->ssid));
790 vif->ssid_len = 0;
bdcd8170
KV
791
792 if (!test_bit(SKIP_SCAN, &ar->flag))
8c8b65e3 793 memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
bdcd8170
KV
794
795 up(&ar->sem);
796
14ee6f6b 797 vif->sme_state = SME_DISCONNECTED;
170826dd 798
bdcd8170
KV
799 return 0;
800}
801
240d2799 802void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
bdcd8170
KV
803 u8 *bssid, u8 assoc_resp_len,
804 u8 *assoc_info, u16 proto_reason)
805{
240d2799 806 struct ath6kl *ar = vif->ar;
59c98449 807
14ee6f6b
VT
808 if (vif->scan_req) {
809 cfg80211_scan_done(vif->scan_req, true);
810 vif->scan_req = NULL;
bdcd8170
KV
811 }
812
f5938f24 813 if (vif->nw_type & ADHOC_NETWORK) {
551959d8 814 if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) {
bdcd8170
KV
815 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
816 "%s: ath6k not in ibss mode\n", __func__);
817 return;
818 }
819 memset(bssid, 0, ETH_ALEN);
240d2799 820 cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
bdcd8170
KV
821 return;
822 }
823
f5938f24 824 if (vif->nw_type & INFRA_NETWORK) {
551959d8
VT
825 if (vif->wdev.iftype != NL80211_IFTYPE_STATION &&
826 vif->wdev.iftype != NL80211_IFTYPE_P2P_CLIENT) {
bdcd8170
KV
827 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
828 "%s: ath6k not in station mode\n", __func__);
829 return;
830 }
831 }
832
1de547d6
VT
833 /*
834 * Send a disconnect command to target when a disconnect event is
835 * received with reason code other than 3 (DISCONNECT_CMD - disconnect
836 * request from host) to make the firmware stop trying to connect even
837 * after giving disconnect event. There will be one more disconnect
838 * event for this disconnect command with reason code DISCONNECT_CMD
839 * which will be notified to cfg80211.
840 */
bdcd8170 841
1de547d6 842 if (reason != DISCONNECT_CMD) {
334234b5 843 ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
bdcd8170
KV
844 return;
845 }
846
59c98449 847 clear_bit(CONNECT_PEND, &vif->flags);
bdcd8170 848
14ee6f6b 849 if (vif->sme_state == SME_CONNECTING) {
240d2799 850 cfg80211_connect_result(vif->ndev,
96f1fadc
KV
851 bssid, NULL, 0,
852 NULL, 0,
853 WLAN_STATUS_UNSPECIFIED_FAILURE,
854 GFP_KERNEL);
14ee6f6b 855 } else if (vif->sme_state == SME_CONNECTED) {
240d2799 856 cfg80211_disconnected(vif->ndev, reason,
96f1fadc 857 NULL, 0, GFP_KERNEL);
bdcd8170
KV
858 }
859
14ee6f6b 860 vif->sme_state = SME_DISCONNECTED;
bdcd8170
KV
861}
862
bdcd8170
KV
863static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
864 struct cfg80211_scan_request *request)
865{
d6d5c06c 866 struct ath6kl *ar = ath6kl_priv(ndev);
59c98449 867 struct ath6kl_vif *vif = netdev_priv(ndev);
1276c9ef
EL
868 s8 n_channels = 0;
869 u16 *channels = NULL;
bdcd8170 870 int ret = 0;
f1f92179 871 u32 force_fg_scan = 0;
bdcd8170 872
990bd915 873 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
874 return -EIO;
875
10509f90
KV
876 ath6kl_cfg80211_sscan_disable(vif);
877
bdcd8170 878 if (!ar->usr_bss_filter) {
59c98449 879 clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
1b1e6ee3 880 ret = ath6kl_wmi_bssfilter_cmd(
240d2799 881 ar->wmi, vif->fw_vif_idx,
59c98449 882 (test_bit(CONNECTED, &vif->flags) ?
1b1e6ee3
JM
883 ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), 0);
884 if (ret) {
bdcd8170 885 ath6kl_err("couldn't set bss filtering\n");
1b1e6ee3 886 return ret;
bdcd8170
KV
887 }
888 }
889
890 if (request->n_ssids && request->ssids[0].ssid_len) {
891 u8 i;
892
893 if (request->n_ssids > (MAX_PROBED_SSID_INDEX - 1))
894 request->n_ssids = MAX_PROBED_SSID_INDEX - 1;
895
896 for (i = 0; i < request->n_ssids; i++)
334234b5
VT
897 ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
898 i + 1, SPECIFIC_SSID_FLAG,
bdcd8170
KV
899 request->ssids[i].ssid_len,
900 request->ssids[i].ssid);
901 }
902
080eec4f
AT
903 /* this also clears IE in fw if it's not set */
904 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
905 WMI_FRAME_PROBE_REQ,
906 request->ie, request->ie_len);
907 if (ret) {
908 ath6kl_err("failed to set Probe Request appie for "
909 "scan");
910 return ret;
b84da8c7
JM
911 }
912
11869bef
JM
913 /*
914 * Scan only the requested channels if the request specifies a set of
915 * channels. If the list is longer than the target supports, do not
916 * configure the list and instead, scan all available channels.
917 */
918 if (request->n_channels > 0 &&
919 request->n_channels <= WMI_MAX_CHANNELS) {
1276c9ef
EL
920 u8 i;
921
11869bef 922 n_channels = request->n_channels;
1276c9ef
EL
923
924 channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL);
925 if (channels == NULL) {
926 ath6kl_warn("failed to set scan channels, "
927 "scan all channels");
928 n_channels = 0;
929 }
930
931 for (i = 0; i < n_channels; i++)
932 channels[i] = request->channels[i]->center_freq;
933 }
934
59c98449 935 if (test_bit(CONNECTED, &vif->flags))
f1f92179
VT
936 force_fg_scan = 1;
937
3ca9d1fc 938 if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
96f1fadc 939 ar->fw_capabilities)) {
3ca9d1fc
AT
940 /*
941 * If capable of doing P2P mgmt operations using
942 * station interface, send additional information like
943 * supported rates to advertise and xmit rates for
944 * probe requests
945 */
946 ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx,
947 WMI_LONG_SCAN, force_fg_scan,
13423c31
VT
948 false, 0,
949 ATH6KL_FG_SCAN_INTERVAL,
950 n_channels, channels,
951 request->no_cck,
3ca9d1fc
AT
952 request->rates);
953 } else {
954 ret = ath6kl_wmi_startscan_cmd(ar->wmi, vif->fw_vif_idx,
955 WMI_LONG_SCAN, force_fg_scan,
13423c31
VT
956 false, 0,
957 ATH6KL_FG_SCAN_INTERVAL,
958 n_channels, channels);
3ca9d1fc 959 }
1b1e6ee3 960 if (ret)
bdcd8170 961 ath6kl_err("wmi_startscan_cmd failed\n");
11869bef 962 else
14ee6f6b 963 vif->scan_req = request;
bdcd8170 964
1276c9ef
EL
965 kfree(channels);
966
bdcd8170
KV
967 return ret;
968}
969
1c17d313 970void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted)
bdcd8170 971{
240d2799 972 struct ath6kl *ar = vif->ar;
6fd1eace 973 int i;
bdcd8170 974
1c17d313
KV
975 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status%s\n", __func__,
976 aborted ? " aborted" : "");
bdcd8170 977
14ee6f6b 978 if (!vif->scan_req)
6fd1eace
KV
979 return;
980
1c17d313 981 if (aborted)
6fd1eace 982 goto out;
6fd1eace 983
14ee6f6b
VT
984 if (vif->scan_req->n_ssids && vif->scan_req->ssids[0].ssid_len) {
985 for (i = 0; i < vif->scan_req->n_ssids; i++) {
334234b5
VT
986 ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
987 i + 1, DISABLE_SSID_FLAG,
6fd1eace 988 0, NULL);
bdcd8170 989 }
bdcd8170 990 }
6fd1eace
KV
991
992out:
cb93821a 993 cfg80211_scan_done(vif->scan_req, aborted);
14ee6f6b 994 vif->scan_req = NULL;
bdcd8170
KV
995}
996
997static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
998 u8 key_index, bool pairwise,
999 const u8 *mac_addr,
1000 struct key_params *params)
1001{
d6d5c06c 1002 struct ath6kl *ar = ath6kl_priv(ndev);
59c98449 1003 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170 1004 struct ath6kl_key *key = NULL;
4a8ce2fd 1005 int seq_len;
bdcd8170
KV
1006 u8 key_usage;
1007 u8 key_type;
bdcd8170 1008
990bd915 1009 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1010 return -EIO;
1011
837cb97e
JM
1012 if (params->cipher == CCKM_KRK_CIPHER_SUITE) {
1013 if (params->key_len != WMI_KRK_LEN)
1014 return -EINVAL;
240d2799
VT
1015 return ath6kl_wmi_add_krk_cmd(ar->wmi, vif->fw_vif_idx,
1016 params->key);
837cb97e
JM
1017 }
1018
792ecb33 1019 if (key_index > WMI_MAX_KEY_INDEX) {
bdcd8170
KV
1020 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1021 "%s: key index %d out of bounds\n", __func__,
1022 key_index);
1023 return -ENOENT;
1024 }
1025
6f2a73f9 1026 key = &vif->keys[key_index];
bdcd8170
KV
1027 memset(key, 0, sizeof(struct ath6kl_key));
1028
1029 if (pairwise)
1030 key_usage = PAIRWISE_USAGE;
1031 else
1032 key_usage = GROUP_USAGE;
1033
4a8ce2fd
SM
1034 seq_len = params->seq_len;
1035 if (params->cipher == WLAN_CIPHER_SUITE_SMS4 &&
1036 seq_len > ATH6KL_KEY_SEQ_LEN) {
1037 /* Only first half of the WPI PN is configured */
1038 seq_len = ATH6KL_KEY_SEQ_LEN;
bdcd8170 1039 }
4a8ce2fd
SM
1040 if (params->key_len > WLAN_MAX_KEY_LEN ||
1041 seq_len > sizeof(key->seq))
1042 return -EINVAL;
1043
1044 key->key_len = params->key_len;
1045 memcpy(key->key, params->key, key->key_len);
1046 key->seq_len = seq_len;
1047 memcpy(key->seq, params->seq, key->seq_len);
1048 key->cipher = params->cipher;
bdcd8170
KV
1049
1050 switch (key->cipher) {
1051 case WLAN_CIPHER_SUITE_WEP40:
1052 case WLAN_CIPHER_SUITE_WEP104:
1053 key_type = WEP_CRYPT;
1054 break;
1055
1056 case WLAN_CIPHER_SUITE_TKIP:
1057 key_type = TKIP_CRYPT;
1058 break;
1059
1060 case WLAN_CIPHER_SUITE_CCMP:
1061 key_type = AES_CRYPT;
1062 break;
5e07021e
DS
1063 case WLAN_CIPHER_SUITE_SMS4:
1064 key_type = WAPI_CRYPT;
1065 break;
bdcd8170
KV
1066
1067 default:
1068 return -ENOTSUPP;
1069 }
1070
ddc3d77c
KV
1071 if (((vif->auth_mode == WPA_PSK_AUTH) ||
1072 (vif->auth_mode == WPA2_PSK_AUTH)) &&
1073 (key_usage & GROUP_USAGE))
de3ad713 1074 del_timer(&vif->disconnect_timer);
bdcd8170
KV
1075
1076 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1077 "%s: index %d, key_len %d, key_type 0x%x, key_usage 0x%x, seq_len %d\n",
1078 __func__, key_index, key->key_len, key_type,
1079 key_usage, key->seq_len);
1080
f5938f24 1081 if (vif->nw_type == AP_NETWORK && !pairwise &&
4703290a 1082 (key_type == TKIP_CRYPT || key_type == AES_CRYPT ||
cc4d623d 1083 key_type == WAPI_CRYPT)) {
9a5b1318
JM
1084 ar->ap_mode_bkey.valid = true;
1085 ar->ap_mode_bkey.key_index = key_index;
1086 ar->ap_mode_bkey.key_type = key_type;
1087 ar->ap_mode_bkey.key_len = key->key_len;
1088 memcpy(ar->ap_mode_bkey.key, key->key, key->key_len);
59c98449 1089 if (!test_bit(CONNECTED, &vif->flags)) {
9a5b1318
JM
1090 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group "
1091 "key configuration until AP mode has been "
1092 "started\n");
1093 /*
1094 * The key will be set in ath6kl_connect_ap_mode() once
1095 * the connected event is received from the target.
1096 */
1097 return 0;
1098 }
1099 }
1100
f5938f24 1101 if (vif->next_mode == AP_NETWORK && key_type == WEP_CRYPT &&
59c98449 1102 !test_bit(CONNECTED, &vif->flags)) {
151411e8
JM
1103 /*
1104 * Store the key locally so that it can be re-configured after
1105 * the AP mode has properly started
1106 * (ath6kl_install_statioc_wep_keys).
1107 */
1108 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay WEP key configuration "
1109 "until AP mode has been started\n");
6f2a73f9
VT
1110 vif->wep_key_list[key_index].key_len = key->key_len;
1111 memcpy(vif->wep_key_list[key_index].key, key->key,
1112 key->key_len);
151411e8
JM
1113 return 0;
1114 }
1115
7cefa44f 1116 return ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx, key_index,
f3e61ece
JM
1117 key_type, key_usage, key->key_len,
1118 key->seq, key->seq_len, key->key,
1119 KEY_OP_INIT_VAL,
1120 (u8 *) mac_addr, SYNC_BOTH_WMIFLAG);
bdcd8170
KV
1121}
1122
1123static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
1124 u8 key_index, bool pairwise,
1125 const u8 *mac_addr)
1126{
d6d5c06c 1127 struct ath6kl *ar = ath6kl_priv(ndev);
6f2a73f9 1128 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170
KV
1129
1130 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1131
990bd915 1132 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1133 return -EIO;
1134
792ecb33 1135 if (key_index > WMI_MAX_KEY_INDEX) {
bdcd8170
KV
1136 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1137 "%s: key index %d out of bounds\n", __func__,
1138 key_index);
1139 return -ENOENT;
1140 }
1141
6f2a73f9 1142 if (!vif->keys[key_index].key_len) {
bdcd8170
KV
1143 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1144 "%s: index %d is empty\n", __func__, key_index);
1145 return 0;
1146 }
1147
6f2a73f9 1148 vif->keys[key_index].key_len = 0;
bdcd8170 1149
334234b5 1150 return ath6kl_wmi_deletekey_cmd(ar->wmi, vif->fw_vif_idx, key_index);
bdcd8170
KV
1151}
1152
1153static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
1154 u8 key_index, bool pairwise,
1155 const u8 *mac_addr, void *cookie,
1156 void (*callback) (void *cookie,
1157 struct key_params *))
1158{
6f2a73f9 1159 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170
KV
1160 struct ath6kl_key *key = NULL;
1161 struct key_params params;
1162
1163 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1164
990bd915 1165 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1166 return -EIO;
1167
792ecb33 1168 if (key_index > WMI_MAX_KEY_INDEX) {
bdcd8170
KV
1169 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1170 "%s: key index %d out of bounds\n", __func__,
1171 key_index);
1172 return -ENOENT;
1173 }
1174
6f2a73f9 1175 key = &vif->keys[key_index];
bdcd8170
KV
1176 memset(&params, 0, sizeof(params));
1177 params.cipher = key->cipher;
1178 params.key_len = key->key_len;
1179 params.seq_len = key->seq_len;
1180 params.seq = key->seq;
1181 params.key = key->key;
1182
1183 callback(cookie, &params);
1184
1185 return key->key_len ? 0 : -ENOENT;
1186}
1187
1188static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
1189 struct net_device *ndev,
1190 u8 key_index, bool unicast,
1191 bool multicast)
1192{
d6d5c06c 1193 struct ath6kl *ar = ath6kl_priv(ndev);
59c98449 1194 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170 1195 struct ath6kl_key *key = NULL;
bdcd8170 1196 u8 key_usage;
229ed6b5 1197 enum crypto_type key_type = NONE_CRYPT;
bdcd8170
KV
1198
1199 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1200
990bd915 1201 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1202 return -EIO;
1203
792ecb33 1204 if (key_index > WMI_MAX_KEY_INDEX) {
bdcd8170
KV
1205 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1206 "%s: key index %d out of bounds\n",
1207 __func__, key_index);
1208 return -ENOENT;
1209 }
1210
6f2a73f9 1211 if (!vif->keys[key_index].key_len) {
bdcd8170
KV
1212 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: invalid key index %d\n",
1213 __func__, key_index);
1214 return -EINVAL;
1215 }
1216
3450334f 1217 vif->def_txkey_index = key_index;
6f2a73f9 1218 key = &vif->keys[vif->def_txkey_index];
bdcd8170 1219 key_usage = GROUP_USAGE;
3450334f 1220 if (vif->prwise_crypto == WEP_CRYPT)
bdcd8170 1221 key_usage |= TX_USAGE;
229ed6b5 1222 if (unicast)
3450334f 1223 key_type = vif->prwise_crypto;
229ed6b5 1224 if (multicast)
3450334f 1225 key_type = vif->grp_crypto;
bdcd8170 1226
f5938f24 1227 if (vif->next_mode == AP_NETWORK && !test_bit(CONNECTED, &vif->flags))
9a5b1318
JM
1228 return 0; /* Delay until AP mode has been started */
1229
f3e61ece
JM
1230 return ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx,
1231 vif->def_txkey_index,
1232 key_type, key_usage,
1233 key->key_len, key->seq, key->seq_len,
1234 key->key,
1235 KEY_OP_INIT_VAL, NULL,
1236 SYNC_BOTH_WMIFLAG);
bdcd8170
KV
1237}
1238
240d2799 1239void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl_vif *vif, u8 keyid,
bdcd8170
KV
1240 bool ismcast)
1241{
1242 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1243 "%s: keyid %d, ismcast %d\n", __func__, keyid, ismcast);
1244
240d2799 1245 cfg80211_michael_mic_failure(vif->ndev, vif->bssid,
bdcd8170
KV
1246 (ismcast ? NL80211_KEYTYPE_GROUP :
1247 NL80211_KEYTYPE_PAIRWISE), keyid, NULL,
1248 GFP_KERNEL);
1249}
1250
1251static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1252{
1253 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
990bd915 1254 struct ath6kl_vif *vif;
bdcd8170
KV
1255 int ret;
1256
1257 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: changed 0x%x\n", __func__,
1258 changed);
1259
990bd915
VT
1260 vif = ath6kl_vif_first(ar);
1261 if (!vif)
1262 return -EIO;
1263
1264 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1265 return -EIO;
1266
1267 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
1268 ret = ath6kl_wmi_set_rts_cmd(ar->wmi, wiphy->rts_threshold);
1269 if (ret != 0) {
1270 ath6kl_err("ath6kl_wmi_set_rts_cmd failed\n");
1271 return -EIO;
1272 }
1273 }
1274
1275 return 0;
1276}
1277
1278/*
1279 * The type nl80211_tx_power_setting replaces the following
1280 * data type from 2.6.36 onwards
1281*/
1282static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
1283 enum nl80211_tx_power_setting type,
b992a285 1284 int mbm)
bdcd8170
KV
1285{
1286 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
990bd915 1287 struct ath6kl_vif *vif;
b992a285 1288 int dbm = MBM_TO_DBM(mbm);
bdcd8170
KV
1289
1290 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__,
1291 type, dbm);
1292
990bd915
VT
1293 vif = ath6kl_vif_first(ar);
1294 if (!vif)
1295 return -EIO;
1296
1297 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1298 return -EIO;
1299
1300 switch (type) {
1301 case NL80211_TX_POWER_AUTOMATIC:
1302 return 0;
1303 case NL80211_TX_POWER_LIMITED:
d0d670ab 1304 ar->tx_pwr = dbm;
bdcd8170
KV
1305 break;
1306 default:
1307 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x not supported\n",
1308 __func__, type);
1309 return -EOPNOTSUPP;
1310 }
1311
d0d670ab 1312 ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx, dbm);
bdcd8170
KV
1313
1314 return 0;
1315}
1316
1317static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
1318{
1319 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
990bd915
VT
1320 struct ath6kl_vif *vif;
1321
1322 vif = ath6kl_vif_first(ar);
1323 if (!vif)
1324 return -EIO;
bdcd8170 1325
990bd915 1326 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1327 return -EIO;
1328
59c98449 1329 if (test_bit(CONNECTED, &vif->flags)) {
bdcd8170
KV
1330 ar->tx_pwr = 0;
1331
990bd915 1332 if (ath6kl_wmi_get_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx) != 0) {
bdcd8170
KV
1333 ath6kl_err("ath6kl_wmi_get_tx_pwr_cmd failed\n");
1334 return -EIO;
1335 }
1336
1337 wait_event_interruptible_timeout(ar->event_wq, ar->tx_pwr != 0,
1338 5 * HZ);
1339
1340 if (signal_pending(current)) {
1341 ath6kl_err("target did not respond\n");
1342 return -EINTR;
1343 }
1344 }
1345
1346 *dbm = ar->tx_pwr;
1347 return 0;
1348}
1349
1350static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
1351 struct net_device *dev,
1352 bool pmgmt, int timeout)
1353{
1354 struct ath6kl *ar = ath6kl_priv(dev);
1355 struct wmi_power_mode_cmd mode;
334234b5 1356 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170
KV
1357
1358 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: pmgmt %d, timeout %d\n",
1359 __func__, pmgmt, timeout);
1360
990bd915 1361 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1362 return -EIO;
1363
1364 if (pmgmt) {
1365 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: max perf\n", __func__);
1366 mode.pwr_mode = REC_POWER;
1367 } else {
1368 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: rec power\n", __func__);
1369 mode.pwr_mode = MAX_PERF_POWER;
1370 }
1371
334234b5 1372 if (ath6kl_wmi_powermode_cmd(ar->wmi, vif->fw_vif_idx,
96f1fadc 1373 mode.pwr_mode) != 0) {
bdcd8170
KV
1374 ath6kl_err("wmi_powermode_cmd failed\n");
1375 return -EIO;
1376 }
1377
1378 return 0;
1379}
1380
55055976
VT
1381static struct net_device *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
1382 char *name,
1383 enum nl80211_iftype type,
1384 u32 *flags,
1385 struct vif_params *params)
1386{
1387 struct ath6kl *ar = wiphy_priv(wiphy);
1388 struct net_device *ndev;
1389 u8 if_idx, nw_type;
1390
71f96ee6 1391 if (ar->num_vif == ar->vif_max) {
55055976
VT
1392 ath6kl_err("Reached maximum number of supported vif\n");
1393 return ERR_PTR(-EINVAL);
1394 }
1395
1396 if (!ath6kl_is_valid_iftype(ar, type, &if_idx, &nw_type)) {
1397 ath6kl_err("Not a supported interface type\n");
1398 return ERR_PTR(-EINVAL);
1399 }
1400
1401 ndev = ath6kl_interface_add(ar, name, type, if_idx, nw_type);
1402 if (!ndev)
1403 return ERR_PTR(-ENOMEM);
1404
1405 ar->num_vif++;
1406
1407 return ndev;
1408}
1409
1410static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy,
1411 struct net_device *ndev)
1412{
1413 struct ath6kl *ar = wiphy_priv(wiphy);
1414 struct ath6kl_vif *vif = netdev_priv(ndev);
1415
11f6e40d 1416 spin_lock_bh(&ar->list_lock);
55055976 1417 list_del(&vif->list);
11f6e40d 1418 spin_unlock_bh(&ar->list_lock);
55055976
VT
1419
1420 ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag));
1421
c25889e8 1422 ath6kl_cfg80211_vif_cleanup(vif);
55055976
VT
1423
1424 return 0;
1425}
1426
bdcd8170
KV
1427static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
1428 struct net_device *ndev,
1429 enum nl80211_iftype type, u32 *flags,
1430 struct vif_params *params)
1431{
f5938f24 1432 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170
KV
1433
1434 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type);
1435
bdcd8170
KV
1436 switch (type) {
1437 case NL80211_IFTYPE_STATION:
f5938f24 1438 vif->next_mode = INFRA_NETWORK;
bdcd8170
KV
1439 break;
1440 case NL80211_IFTYPE_ADHOC:
f5938f24 1441 vif->next_mode = ADHOC_NETWORK;
bdcd8170 1442 break;
6e4604c8 1443 case NL80211_IFTYPE_AP:
f5938f24 1444 vif->next_mode = AP_NETWORK;
6e4604c8 1445 break;
6b5e5d25 1446 case NL80211_IFTYPE_P2P_CLIENT:
f5938f24 1447 vif->next_mode = INFRA_NETWORK;
6b5e5d25
JM
1448 break;
1449 case NL80211_IFTYPE_P2P_GO:
f5938f24 1450 vif->next_mode = AP_NETWORK;
6b5e5d25 1451 break;
bdcd8170
KV
1452 default:
1453 ath6kl_err("invalid interface type %u\n", type);
1454 return -EOPNOTSUPP;
1455 }
1456
551959d8 1457 vif->wdev.iftype = type;
bdcd8170
KV
1458
1459 return 0;
1460}
1461
1462static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
1463 struct net_device *dev,
1464 struct cfg80211_ibss_params *ibss_param)
1465{
1466 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 1467 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170
KV
1468 int status;
1469
990bd915 1470 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1471 return -EIO;
1472
3450334f
VT
1473 vif->ssid_len = ibss_param->ssid_len;
1474 memcpy(vif->ssid, ibss_param->ssid, vif->ssid_len);
bdcd8170
KV
1475
1476 if (ibss_param->channel)
f74bac54 1477 vif->ch_hint = ibss_param->channel->center_freq;
bdcd8170
KV
1478
1479 if (ibss_param->channel_fixed) {
1480 /*
1481 * TODO: channel_fixed: The channel should be fixed, do not
1482 * search for IBSSs to join on other channels. Target
1483 * firmware does not support this feature, needs to be
1484 * updated.
1485 */
1486 return -EOPNOTSUPP;
1487 }
1488
8c8b65e3 1489 memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
bdcd8170 1490 if (ibss_param->bssid && !is_broadcast_ether_addr(ibss_param->bssid))
8c8b65e3
VT
1491 memcpy(vif->req_bssid, ibss_param->bssid,
1492 sizeof(vif->req_bssid));
bdcd8170 1493
240d2799 1494 ath6kl_set_wpa_version(vif, 0);
bdcd8170 1495
240d2799 1496 status = ath6kl_set_auth_type(vif, NL80211_AUTHTYPE_OPEN_SYSTEM);
bdcd8170
KV
1497 if (status)
1498 return status;
1499
1500 if (ibss_param->privacy) {
240d2799
VT
1501 ath6kl_set_cipher(vif, WLAN_CIPHER_SUITE_WEP40, true);
1502 ath6kl_set_cipher(vif, WLAN_CIPHER_SUITE_WEP40, false);
bdcd8170 1503 } else {
240d2799
VT
1504 ath6kl_set_cipher(vif, 0, true);
1505 ath6kl_set_cipher(vif, 0, false);
bdcd8170
KV
1506 }
1507
f5938f24 1508 vif->nw_type = vif->next_mode;
bdcd8170
KV
1509
1510 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1511 "%s: connect called with authmode %d dot11 auth %d"
1512 " PW crypto %d PW crypto len %d GRP crypto %d"
1513 " GRP crypto len %d channel hint %u\n",
1514 __func__,
3450334f
VT
1515 vif->auth_mode, vif->dot11_auth_mode, vif->prwise_crypto,
1516 vif->prwise_crypto_len, vif->grp_crypto,
f74bac54 1517 vif->grp_crypto_len, vif->ch_hint);
bdcd8170 1518
334234b5 1519 status = ath6kl_wmi_connect_cmd(ar->wmi, vif->fw_vif_idx, vif->nw_type,
3450334f
VT
1520 vif->dot11_auth_mode, vif->auth_mode,
1521 vif->prwise_crypto,
1522 vif->prwise_crypto_len,
1523 vif->grp_crypto, vif->grp_crypto_len,
1524 vif->ssid_len, vif->ssid,
f74bac54 1525 vif->req_bssid, vif->ch_hint,
3ca9d1fc 1526 ar->connect_ctrl_flags, SUBTYPE_NONE);
59c98449 1527 set_bit(CONNECT_PEND, &vif->flags);
bdcd8170
KV
1528
1529 return 0;
1530}
1531
1532static int ath6kl_cfg80211_leave_ibss(struct wiphy *wiphy,
1533 struct net_device *dev)
1534{
3450334f 1535 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170 1536
990bd915 1537 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1538 return -EIO;
1539
240d2799 1540 ath6kl_disconnect(vif);
3450334f
VT
1541 memset(vif->ssid, 0, sizeof(vif->ssid));
1542 vif->ssid_len = 0;
bdcd8170
KV
1543
1544 return 0;
1545}
1546
1547static const u32 cipher_suites[] = {
1548 WLAN_CIPHER_SUITE_WEP40,
1549 WLAN_CIPHER_SUITE_WEP104,
1550 WLAN_CIPHER_SUITE_TKIP,
1551 WLAN_CIPHER_SUITE_CCMP,
837cb97e 1552 CCKM_KRK_CIPHER_SUITE,
5e07021e 1553 WLAN_CIPHER_SUITE_SMS4,
bdcd8170
KV
1554};
1555
1556static bool is_rate_legacy(s32 rate)
1557{
1558 static const s32 legacy[] = { 1000, 2000, 5500, 11000,
1559 6000, 9000, 12000, 18000, 24000,
1560 36000, 48000, 54000
1561 };
1562 u8 i;
1563
1564 for (i = 0; i < ARRAY_SIZE(legacy); i++)
1565 if (rate == legacy[i])
1566 return true;
1567
1568 return false;
1569}
1570
1571static bool is_rate_ht20(s32 rate, u8 *mcs, bool *sgi)
1572{
1573 static const s32 ht20[] = { 6500, 13000, 19500, 26000, 39000,
1574 52000, 58500, 65000, 72200
1575 };
1576 u8 i;
1577
1578 for (i = 0; i < ARRAY_SIZE(ht20); i++) {
1579 if (rate == ht20[i]) {
1580 if (i == ARRAY_SIZE(ht20) - 1)
1581 /* last rate uses sgi */
1582 *sgi = true;
1583 else
1584 *sgi = false;
1585
1586 *mcs = i;
1587 return true;
1588 }
1589 }
1590 return false;
1591}
1592
1593static bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi)
1594{
1595 static const s32 ht40[] = { 13500, 27000, 40500, 54000,
1596 81000, 108000, 121500, 135000,
1597 150000
1598 };
1599 u8 i;
1600
1601 for (i = 0; i < ARRAY_SIZE(ht40); i++) {
1602 if (rate == ht40[i]) {
1603 if (i == ARRAY_SIZE(ht40) - 1)
1604 /* last rate uses sgi */
1605 *sgi = true;
1606 else
1607 *sgi = false;
1608
1609 *mcs = i;
1610 return true;
1611 }
1612 }
1613
1614 return false;
1615}
1616
1617static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
1618 u8 *mac, struct station_info *sinfo)
1619{
1620 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 1621 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170
KV
1622 long left;
1623 bool sgi;
1624 s32 rate;
1625 int ret;
1626 u8 mcs;
1627
8c8b65e3 1628 if (memcmp(mac, vif->bssid, ETH_ALEN) != 0)
bdcd8170
KV
1629 return -ENOENT;
1630
1631 if (down_interruptible(&ar->sem))
1632 return -EBUSY;
1633
b95907a7 1634 set_bit(STATS_UPDATE_PEND, &vif->flags);
bdcd8170 1635
334234b5 1636 ret = ath6kl_wmi_get_stats_cmd(ar->wmi, vif->fw_vif_idx);
bdcd8170
KV
1637
1638 if (ret != 0) {
1639 up(&ar->sem);
1640 return -EIO;
1641 }
1642
1643 left = wait_event_interruptible_timeout(ar->event_wq,
1644 !test_bit(STATS_UPDATE_PEND,
b95907a7 1645 &vif->flags),
bdcd8170
KV
1646 WMI_TIMEOUT);
1647
1648 up(&ar->sem);
1649
1650 if (left == 0)
1651 return -ETIMEDOUT;
1652 else if (left < 0)
1653 return left;
1654
b95907a7
VT
1655 if (vif->target_stats.rx_byte) {
1656 sinfo->rx_bytes = vif->target_stats.rx_byte;
bdcd8170 1657 sinfo->filled |= STATION_INFO_RX_BYTES;
b95907a7 1658 sinfo->rx_packets = vif->target_stats.rx_pkt;
bdcd8170
KV
1659 sinfo->filled |= STATION_INFO_RX_PACKETS;
1660 }
1661
b95907a7
VT
1662 if (vif->target_stats.tx_byte) {
1663 sinfo->tx_bytes = vif->target_stats.tx_byte;
bdcd8170 1664 sinfo->filled |= STATION_INFO_TX_BYTES;
b95907a7 1665 sinfo->tx_packets = vif->target_stats.tx_pkt;
bdcd8170
KV
1666 sinfo->filled |= STATION_INFO_TX_PACKETS;
1667 }
1668
b95907a7 1669 sinfo->signal = vif->target_stats.cs_rssi;
bdcd8170
KV
1670 sinfo->filled |= STATION_INFO_SIGNAL;
1671
b95907a7 1672 rate = vif->target_stats.tx_ucast_rate;
bdcd8170
KV
1673
1674 if (is_rate_legacy(rate)) {
1675 sinfo->txrate.legacy = rate / 100;
1676 } else if (is_rate_ht20(rate, &mcs, &sgi)) {
1677 if (sgi) {
1678 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
1679 sinfo->txrate.mcs = mcs - 1;
1680 } else {
1681 sinfo->txrate.mcs = mcs;
1682 }
1683
1684 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
1685 } else if (is_rate_ht40(rate, &mcs, &sgi)) {
1686 if (sgi) {
1687 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
1688 sinfo->txrate.mcs = mcs - 1;
1689 } else {
1690 sinfo->txrate.mcs = mcs;
1691 }
1692
1693 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
1694 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
1695 } else {
9a730834
KV
1696 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1697 "invalid rate from stats: %d\n", rate);
1698 ath6kl_debug_war(ar, ATH6KL_WAR_INVALID_RATE);
bdcd8170
KV
1699 return 0;
1700 }
1701
1702 sinfo->filled |= STATION_INFO_TX_BITRATE;
1703
59c98449
VT
1704 if (test_bit(CONNECTED, &vif->flags) &&
1705 test_bit(DTIM_PERIOD_AVAIL, &vif->flags) &&
f5938f24 1706 vif->nw_type == INFRA_NETWORK) {
32c10874
JM
1707 sinfo->filled |= STATION_INFO_BSS_PARAM;
1708 sinfo->bss_param.flags = 0;
cf5333d7
VT
1709 sinfo->bss_param.dtim_period = vif->assoc_bss_dtim_period;
1710 sinfo->bss_param.beacon_interval = vif->assoc_bss_beacon_int;
32c10874
JM
1711 }
1712
bdcd8170
KV
1713 return 0;
1714}
1715
1716static int ath6kl_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1717 struct cfg80211_pmksa *pmksa)
1718{
1719 struct ath6kl *ar = ath6kl_priv(netdev);
334234b5
VT
1720 struct ath6kl_vif *vif = netdev_priv(netdev);
1721
1722 return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx, pmksa->bssid,
bdcd8170
KV
1723 pmksa->pmkid, true);
1724}
1725
1726static int ath6kl_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1727 struct cfg80211_pmksa *pmksa)
1728{
1729 struct ath6kl *ar = ath6kl_priv(netdev);
334234b5
VT
1730 struct ath6kl_vif *vif = netdev_priv(netdev);
1731
1732 return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx, pmksa->bssid,
bdcd8170
KV
1733 pmksa->pmkid, false);
1734}
1735
1736static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
1737{
1738 struct ath6kl *ar = ath6kl_priv(netdev);
59c98449
VT
1739 struct ath6kl_vif *vif = netdev_priv(netdev);
1740
1741 if (test_bit(CONNECTED, &vif->flags))
334234b5
VT
1742 return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx,
1743 vif->bssid, NULL, false);
bdcd8170
KV
1744 return 0;
1745}
1746
d91e8eee
RM
1747static int ath6kl_wow_usr(struct ath6kl *ar, struct ath6kl_vif *vif,
1748 struct cfg80211_wowlan *wow, u32 *filter)
6cb3c714 1749{
d91e8eee
RM
1750 int ret, pos;
1751 u8 mask[WOW_MASK_SIZE];
6cb3c714 1752 u16 i;
6cb3c714 1753
d91e8eee 1754 /* Configure the patterns that we received from the user. */
6cb3c714
RM
1755 for (i = 0; i < wow->n_patterns; i++) {
1756
1757 /*
1758 * Convert given nl80211 specific mask value to equivalent
1759 * driver specific mask value and send it to the chip along
1760 * with patterns. For example, If the mask value defined in
1761 * struct cfg80211_wowlan is 0xA (equivalent binary is 1010),
1762 * then equivalent driver specific mask value is
1763 * "0xFF 0x00 0xFF 0x00".
1764 */
1765 memset(&mask, 0, sizeof(mask));
1766 for (pos = 0; pos < wow->patterns[i].pattern_len; pos++) {
1767 if (wow->patterns[i].mask[pos / 8] & (0x1 << (pos % 8)))
1768 mask[pos] = 0xFF;
1769 }
1770 /*
1771 * Note: Pattern's offset is not passed as part of wowlan
1772 * parameter from CFG layer. So it's always passed as ZERO
1773 * to the firmware. It means, given WOW patterns are always
1774 * matched from the first byte of received pkt in the firmware.
1775 */
1776 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
d91e8eee
RM
1777 vif->fw_vif_idx, WOW_LIST_ID,
1778 wow->patterns[i].pattern_len,
1779 0 /* pattern offset */,
1780 wow->patterns[i].pattern, mask);
6cb3c714
RM
1781 if (ret)
1782 return ret;
1783 }
1784
d91e8eee
RM
1785 if (wow->disconnect)
1786 *filter |= WOW_FILTER_OPTION_NWK_DISASSOC;
1787
1788 if (wow->magic_pkt)
1789 *filter |= WOW_FILTER_OPTION_MAGIC_PACKET;
1790
1791 if (wow->gtk_rekey_failure)
1792 *filter |= WOW_FILTER_OPTION_GTK_ERROR;
1793
1794 if (wow->eap_identity_req)
1795 *filter |= WOW_FILTER_OPTION_EAP_REQ;
1796
1797 if (wow->four_way_handshake)
1798 *filter |= WOW_FILTER_OPTION_8021X_4WAYHS;
1799
1800 return 0;
1801}
1802
1803static int ath6kl_wow_ap(struct ath6kl *ar, struct ath6kl_vif *vif)
1804{
1805 static const u8 unicst_pattern[] = { 0x00, 0x00, 0x00,
1806 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1807 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1808 0x00, 0x08 };
1809 static const u8 unicst_mask[] = { 0x01, 0x00, 0x00,
1810 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1811 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1812 0x00, 0x7f };
1813 u8 unicst_offset = 0;
1814 static const u8 arp_pattern[] = { 0x08, 0x06 };
1815 static const u8 arp_mask[] = { 0xff, 0xff };
1816 u8 arp_offset = 20;
1817 static const u8 discvr_pattern[] = { 0xe0, 0x00, 0x00, 0xf8 };
1818 static const u8 discvr_mask[] = { 0xf0, 0x00, 0x00, 0xf8 };
1819 u8 discvr_offset = 38;
1820 static const u8 dhcp_pattern[] = { 0xff, 0xff, 0xff, 0xff,
1821 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1822 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
1823 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1824 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1825 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 /* port 67 */ };
1826 static const u8 dhcp_mask[] = { 0xff, 0xff, 0xff, 0xff,
1827 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1828 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
1829 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1830 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1831 0x00, 0x00, 0x00, 0x00, 0xff, 0xff /* port 67 */ };
1832 u8 dhcp_offset = 0;
1833 int ret;
1834
1835 /* Setup unicast IP, EAPOL-like and ARP pkt pattern */
1836 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1837 vif->fw_vif_idx, WOW_LIST_ID,
1838 sizeof(unicst_pattern), unicst_offset,
1839 unicst_pattern, unicst_mask);
1840 if (ret) {
1841 ath6kl_err("failed to add WOW unicast IP pattern\n");
1842 return ret;
1843 }
1844
1845 /* Setup all ARP pkt pattern */
1846 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1847 vif->fw_vif_idx, WOW_LIST_ID,
1848 sizeof(arp_pattern), arp_offset,
1849 arp_pattern, arp_mask);
1850 if (ret) {
1851 ath6kl_err("failed to add WOW ARP pattern\n");
1852 return ret;
1853 }
1854
1855 /*
1856 * Setup multicast pattern for mDNS 224.0.0.251,
1857 * SSDP 239.255.255.250 and LLMNR 224.0.0.252
1858 */
1859 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1860 vif->fw_vif_idx, WOW_LIST_ID,
1861 sizeof(discvr_pattern), discvr_offset,
1862 discvr_pattern, discvr_mask);
1863 if (ret) {
1864 ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR pattern\n");
1865 return ret;
1866 }
1867
1868 /* Setup all DHCP broadcast pkt pattern */
1869 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1870 vif->fw_vif_idx, WOW_LIST_ID,
1871 sizeof(dhcp_pattern), dhcp_offset,
1872 dhcp_pattern, dhcp_mask);
1873 if (ret) {
1874 ath6kl_err("failed to add WOW DHCP broadcast pattern\n");
1875 return ret;
1876 }
1877
1878 return 0;
1879}
1880
1881static int ath6kl_wow_sta(struct ath6kl *ar, struct ath6kl_vif *vif)
1882{
1883 struct net_device *ndev = vif->ndev;
1884 static const u8 discvr_pattern[] = { 0xe0, 0x00, 0x00, 0xf8 };
1885 static const u8 discvr_mask[] = { 0xf0, 0x00, 0x00, 0xf8 };
1886 u8 discvr_offset = 38;
1887 u8 mac_mask[ETH_ALEN];
1888 int ret;
1889
1890 /* Setup unicast pkt pattern */
1891 memset(mac_mask, 0xff, ETH_ALEN);
1892 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1893 vif->fw_vif_idx, WOW_LIST_ID,
1894 ETH_ALEN, 0, ndev->dev_addr,
1895 mac_mask);
1896 if (ret) {
1897 ath6kl_err("failed to add WOW unicast pattern\n");
1898 return ret;
1899 }
1900
1901 /*
1902 * Setup multicast pattern for mDNS 224.0.0.251,
1903 * SSDP 239.255.255.250 and LLMNR 224.0.0.252
1904 */
1905 if ((ndev->flags & IFF_ALLMULTI) ||
1906 (ndev->flags & IFF_MULTICAST && netdev_mc_count(ndev) > 0)) {
1907 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1908 vif->fw_vif_idx, WOW_LIST_ID,
1909 sizeof(discvr_pattern), discvr_offset,
1910 discvr_pattern, discvr_mask);
1911 if (ret) {
1912 ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR "
1913 "pattern\n");
1914 return ret;
1915 }
1916 }
1917
1918 return 0;
1919}
1920
1921static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
1922{
1923 struct in_device *in_dev;
1924 struct in_ifaddr *ifa;
1925 struct ath6kl_vif *vif;
1926 int ret, left;
1927 u32 filter = 0;
ce0dc0cf 1928 u16 i, bmiss_time;
d91e8eee
RM
1929 u8 index = 0;
1930 __be32 ips[MAX_IP_ADDRS];
1931
1932 vif = ath6kl_vif_first(ar);
1933 if (!vif)
1934 return -EIO;
1935
1936 if (!ath6kl_cfg80211_ready(vif))
1937 return -EIO;
1938
1939 if (!test_bit(CONNECTED, &vif->flags))
3c411a43 1940 return -ENOTCONN;
d91e8eee
RM
1941
1942 if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
1943 return -EINVAL;
1944
1945 /* Clear existing WOW patterns */
1946 for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++)
1947 ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx,
1948 WOW_LIST_ID, i);
1949
1950 /*
1951 * Skip the default WOW pattern configuration
1952 * if the driver receives any WOW patterns from
1953 * the user.
1954 */
1955 if (wow)
1956 ret = ath6kl_wow_usr(ar, vif, wow, &filter);
1957 else if (vif->nw_type == AP_NETWORK)
1958 ret = ath6kl_wow_ap(ar, vif);
1959 else
1960 ret = ath6kl_wow_sta(ar, vif);
1961
1962 if (ret)
1963 return ret;
1964
390a8c8f
RM
1965 netif_stop_queue(vif->ndev);
1966
ce0dc0cf
RM
1967 if (vif->nw_type != AP_NETWORK) {
1968 ret = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
1969 ATH6KL_MAX_WOW_LISTEN_INTL,
1970 0);
1971 if (ret)
1972 return ret;
1973
1974 /* Set listen interval x 15 times as bmiss time */
1975 bmiss_time = ATH6KL_MAX_WOW_LISTEN_INTL * 15;
1976 if (bmiss_time > ATH6KL_MAX_BMISS_TIME)
1977 bmiss_time = ATH6KL_MAX_BMISS_TIME;
1978
1979 ret = ath6kl_wmi_bmisstime_cmd(ar->wmi, vif->fw_vif_idx,
1980 bmiss_time, 0);
1981 if (ret)
1982 return ret;
1983
1984 ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
1985 0xFFFF, 0, 0xFFFF, 0, 0, 0,
1986 0, 0, 0, 0);
1987 if (ret)
1988 return ret;
1989 }
1990
390a8c8f
RM
1991 ar->state = ATH6KL_STATE_SUSPENDING;
1992
c08631c6
RM
1993 /* Setup own IP addr for ARP agent. */
1994 in_dev = __in_dev_get_rtnl(vif->ndev);
1995 if (!in_dev)
1996 goto skip_arp;
1997
1998 ifa = in_dev->ifa_list;
1999 memset(&ips, 0, sizeof(ips));
2000
2001 /* Configure IP addr only if IP address count < MAX_IP_ADDRS */
2002 while (index < MAX_IP_ADDRS && ifa) {
2003 ips[index] = ifa->ifa_local;
2004 ifa = ifa->ifa_next;
2005 index++;
2006 }
2007
2008 if (ifa) {
2009 ath6kl_err("total IP addr count is exceeding fw limit\n");
2010 return -EINVAL;
2011 }
2012
2013 ret = ath6kl_wmi_set_ip_cmd(ar->wmi, vif->fw_vif_idx, ips[0], ips[1]);
2014 if (ret) {
2015 ath6kl_err("fail to setup ip for arp agent\n");
2016 return ret;
2017 }
2018
2019skip_arp:
6cb3c714
RM
2020 ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
2021 ATH6KL_WOW_MODE_ENABLE,
2022 filter,
2023 WOW_HOST_REQ_DELAY);
2024 if (ret)
2025 return ret;
2026
081c7a84
RM
2027 clear_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags);
2028
6cb3c714
RM
2029 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
2030 ATH6KL_HOST_MODE_ASLEEP);
2031 if (ret)
2032 return ret;
2033
081c7a84
RM
2034 left = wait_event_interruptible_timeout(ar->event_wq,
2035 test_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags),
2036 WMI_TIMEOUT);
2037 if (left == 0) {
2038 ath6kl_warn("timeout, didn't get host sleep cmd "
2039 "processed event\n");
2040 ret = -ETIMEDOUT;
2041 } else if (left < 0) {
2042 ath6kl_warn("error while waiting for host sleep cmd "
2043 "processed event %d\n", left);
2044 ret = left;
2045 }
2046
6cb3c714
RM
2047 if (ar->tx_pending[ar->ctrl_ep]) {
2048 left = wait_event_interruptible_timeout(ar->event_wq,
2049 ar->tx_pending[ar->ctrl_ep] == 0, WMI_TIMEOUT);
2050 if (left == 0) {
2051 ath6kl_warn("clear wmi ctrl data timeout\n");
2052 ret = -ETIMEDOUT;
2053 } else if (left < 0) {
2054 ath6kl_warn("clear wmi ctrl data failed: %d\n", left);
2055 ret = left;
2056 }
2057 }
2058
2059 return ret;
2060}
2061
2062static int ath6kl_wow_resume(struct ath6kl *ar)
2063{
2064 struct ath6kl_vif *vif;
2065 int ret;
2066
2067 vif = ath6kl_vif_first(ar);
2068 if (!vif)
2069 return -EIO;
2070
390a8c8f
RM
2071 ar->state = ATH6KL_STATE_RESUMING;
2072
6cb3c714
RM
2073 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
2074 ATH6KL_HOST_MODE_AWAKE);
390a8c8f
RM
2075 if (ret) {
2076 ath6kl_warn("Failed to configure host sleep mode for "
2077 "wow resume: %d\n", ret);
2078 ar->state = ATH6KL_STATE_WOW;
2079 return ret;
2080 }
2081
ce0dc0cf
RM
2082 if (vif->nw_type != AP_NETWORK) {
2083 ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
2084 0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
2085 if (ret)
2086 return ret;
2087
2088 ret = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
2089 vif->listen_intvl_t, 0);
2090 if (ret)
2091 return ret;
2092
2093 ret = ath6kl_wmi_bmisstime_cmd(ar->wmi, vif->fw_vif_idx,
2094 vif->bmiss_time_t, 0);
2095 if (ret)
2096 return ret;
2097 }
2098
390a8c8f
RM
2099 ar->state = ATH6KL_STATE_ON;
2100
2101 netif_wake_queue(vif->ndev);
2102
2103 return 0;
6cb3c714
RM
2104}
2105
52d81a68 2106int ath6kl_cfg80211_suspend(struct ath6kl *ar,
0f60e9f4
RM
2107 enum ath6kl_cfg_suspend_mode mode,
2108 struct cfg80211_wowlan *wow)
52d81a68 2109{
390a8c8f 2110 enum ath6kl_state prev_state;
52d81a68
KV
2111 int ret;
2112
52d81a68 2113 switch (mode) {
d7c44e0b
RM
2114 case ATH6KL_CFG_SUSPEND_WOW:
2115
2116 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "wow mode suspend\n");
2117
2118 /* Flush all non control pkts in TX path */
2119 ath6kl_tx_data_cleanup(ar);
2120
390a8c8f
RM
2121 prev_state = ar->state;
2122
d7c44e0b 2123 ret = ath6kl_wow_suspend(ar, wow);
390a8c8f
RM
2124 if (ret) {
2125 ar->state = prev_state;
d7c44e0b 2126 return ret;
390a8c8f 2127 }
1e9a905d 2128
d7c44e0b
RM
2129 ar->state = ATH6KL_STATE_WOW;
2130 break;
2131
52d81a68 2132 case ATH6KL_CFG_SUSPEND_DEEPSLEEP:
524441e3 2133
7125f01d 2134 ath6kl_cfg80211_stop_all(ar);
524441e3 2135
52d81a68
KV
2136 /* save the current power mode before enabling power save */
2137 ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
2138
2139 ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER);
2140 if (ret) {
2141 ath6kl_warn("wmi powermode command failed during suspend: %d\n",
2142 ret);
2143 }
2144
76a9fbe2
KV
2145 ar->state = ATH6KL_STATE_DEEPSLEEP;
2146
52d81a68 2147 break;
b4b2a0b1
KV
2148
2149 case ATH6KL_CFG_SUSPEND_CUTPOWER:
524441e3 2150
7125f01d 2151 ath6kl_cfg80211_stop_all(ar);
524441e3 2152
b4b2a0b1
KV
2153 if (ar->state == ATH6KL_STATE_OFF) {
2154 ath6kl_dbg(ATH6KL_DBG_SUSPEND,
2155 "suspend hw off, no action for cutpower\n");
2156 break;
2157 }
2158
2159 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "suspend cutting power\n");
2160
2161 ret = ath6kl_init_hw_stop(ar);
2162 if (ret) {
2163 ath6kl_warn("failed to stop hw during suspend: %d\n",
2164 ret);
2165 }
2166
2167 ar->state = ATH6KL_STATE_CUTPOWER;
2168
2169 break;
2170
10509f90
KV
2171 case ATH6KL_CFG_SUSPEND_SCHED_SCAN:
2172 /*
2173 * Nothing needed for schedule scan, firmware is already in
2174 * wow mode and sleeping most of the time.
2175 */
2176 break;
2177
b4b2a0b1
KV
2178 default:
2179 break;
52d81a68
KV
2180 }
2181
2182 return 0;
2183}
d6a434d6 2184EXPORT_SYMBOL(ath6kl_cfg80211_suspend);
52d81a68
KV
2185
2186int ath6kl_cfg80211_resume(struct ath6kl *ar)
2187{
76a9fbe2
KV
2188 int ret;
2189
2190 switch (ar->state) {
d7c44e0b
RM
2191 case ATH6KL_STATE_WOW:
2192 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "wow mode resume\n");
2193
2194 ret = ath6kl_wow_resume(ar);
2195 if (ret) {
2196 ath6kl_warn("wow mode resume failed: %d\n", ret);
2197 return ret;
2198 }
2199
d7c44e0b
RM
2200 break;
2201
76a9fbe2
KV
2202 case ATH6KL_STATE_DEEPSLEEP:
2203 if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) {
2204 ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0,
2205 ar->wmi->saved_pwr_mode);
2206 if (ret) {
2207 ath6kl_warn("wmi powermode command failed during resume: %d\n",
2208 ret);
2209 }
2210 }
2211
2212 ar->state = ATH6KL_STATE_ON;
2213
2214 break;
2215
b4b2a0b1
KV
2216 case ATH6KL_STATE_CUTPOWER:
2217 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "resume restoring power\n");
2218
2219 ret = ath6kl_init_hw_start(ar);
2220 if (ret) {
2221 ath6kl_warn("Failed to boot hw in resume: %d\n", ret);
2222 return ret;
2223 }
d7c44e0b 2224 break;
b4b2a0b1 2225
10509f90
KV
2226 case ATH6KL_STATE_SCHED_SCAN:
2227 break;
2228
76a9fbe2
KV
2229 default:
2230 break;
52d81a68
KV
2231 }
2232
2233 return 0;
2234}
d6a434d6 2235EXPORT_SYMBOL(ath6kl_cfg80211_resume);
52d81a68 2236
abcb344b 2237#ifdef CONFIG_PM
52d81a68
KV
2238
2239/* hif layer decides what suspend mode to use */
2240static int __ath6kl_cfg80211_suspend(struct wiphy *wiphy,
abcb344b
KV
2241 struct cfg80211_wowlan *wow)
2242{
2243 struct ath6kl *ar = wiphy_priv(wiphy);
2244
0f60e9f4 2245 return ath6kl_hif_suspend(ar, wow);
abcb344b 2246}
aa6cffc1 2247
52d81a68 2248static int __ath6kl_cfg80211_resume(struct wiphy *wiphy)
aa6cffc1
CN
2249{
2250 struct ath6kl *ar = wiphy_priv(wiphy);
2251
2252 return ath6kl_hif_resume(ar);
2253}
a918fb3c
RM
2254
2255/*
2256 * FIXME: WOW suspend mode is selected if the host sdio controller supports
2257 * both sdio irq wake up and keep power. The target pulls sdio data line to
2258 * wake up the host when WOW pattern matches. This causes sdio irq handler
2259 * is being called in the host side which internally hits ath6kl's RX path.
2260 *
2261 * Since sdio interrupt is not disabled, RX path executes even before
2262 * the host executes the actual resume operation from PM module.
2263 *
2264 * In the current scenario, WOW resume should happen before start processing
2265 * any data from the target. So It's required to perform WOW resume in RX path.
2266 * Ideally we should perform WOW resume only in the actual platform
2267 * resume path. This area needs bit rework to avoid WOW resume in RX path.
2268 *
2269 * ath6kl_check_wow_status() is called from ath6kl_rx().
2270 */
2271void ath6kl_check_wow_status(struct ath6kl *ar)
2272{
390a8c8f
RM
2273 if (ar->state == ATH6KL_STATE_SUSPENDING)
2274 return;
2275
a918fb3c
RM
2276 if (ar->state == ATH6KL_STATE_WOW)
2277 ath6kl_cfg80211_resume(ar);
2278}
2279
2280#else
2281
2282void ath6kl_check_wow_status(struct ath6kl *ar)
2283{
2284}
abcb344b
KV
2285#endif
2286
6a7c9bad
JM
2287static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev,
2288 struct ieee80211_channel *chan,
2289 enum nl80211_channel_type channel_type)
2290{
e68f6750
SM
2291 struct ath6kl_vif *vif;
2292
2293 /*
2294 * 'dev' could be NULL if a channel change is required for the hardware
2295 * device itself, instead of a particular VIF.
2296 *
2297 * FIXME: To be handled properly when monitor mode is supported.
2298 */
2299 if (!dev)
2300 return -EBUSY;
2301
2302 vif = netdev_priv(dev);
6a7c9bad 2303
990bd915 2304 if (!ath6kl_cfg80211_ready(vif))
6a7c9bad
JM
2305 return -EIO;
2306
2307 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n",
2308 __func__, chan->center_freq, chan->hw_value);
cf5333d7 2309 vif->next_chan = chan->center_freq;
6a7c9bad
JM
2310
2311 return 0;
2312}
2313
8bdfbf40
JM
2314static bool ath6kl_is_p2p_ie(const u8 *pos)
2315{
2316 return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
2317 pos[2] == 0x50 && pos[3] == 0x6f &&
2318 pos[4] == 0x9a && pos[5] == 0x09;
2319}
2320
334234b5
VT
2321static int ath6kl_set_ap_probe_resp_ies(struct ath6kl_vif *vif,
2322 const u8 *ies, size_t ies_len)
8bdfbf40 2323{
334234b5 2324 struct ath6kl *ar = vif->ar;
8bdfbf40
JM
2325 const u8 *pos;
2326 u8 *buf = NULL;
2327 size_t len = 0;
2328 int ret;
2329
2330 /*
2331 * Filter out P2P IE(s) since they will be included depending on
2332 * the Probe Request frame in ath6kl_send_go_probe_resp().
2333 */
2334
2335 if (ies && ies_len) {
2336 buf = kmalloc(ies_len, GFP_KERNEL);
2337 if (buf == NULL)
2338 return -ENOMEM;
2339 pos = ies;
2340 while (pos + 1 < ies + ies_len) {
2341 if (pos + 2 + pos[1] > ies + ies_len)
2342 break;
2343 if (!ath6kl_is_p2p_ie(pos)) {
2344 memcpy(buf + len, pos, 2 + pos[1]);
2345 len += 2 + pos[1];
2346 }
2347 pos += 2 + pos[1];
2348 }
2349 }
2350
334234b5
VT
2351 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2352 WMI_FRAME_PROBE_RESP, buf, len);
8bdfbf40
JM
2353 kfree(buf);
2354 return ret;
2355}
2356
8860020e
JB
2357static int ath6kl_set_ies(struct ath6kl_vif *vif,
2358 struct cfg80211_beacon_data *info)
6a7c9bad 2359{
8860020e 2360 struct ath6kl *ar = vif->ar;
6a7c9bad 2361 int res;
6a7c9bad
JM
2362
2363 if (info->beacon_ies) {
334234b5
VT
2364 res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2365 WMI_FRAME_BEACON,
6a7c9bad
JM
2366 info->beacon_ies,
2367 info->beacon_ies_len);
2368 if (res)
2369 return res;
2370 }
8860020e 2371
6a7c9bad 2372 if (info->proberesp_ies) {
334234b5 2373 res = ath6kl_set_ap_probe_resp_ies(vif, info->proberesp_ies,
8bdfbf40 2374 info->proberesp_ies_len);
6a7c9bad
JM
2375 if (res)
2376 return res;
2377 }
8860020e 2378
6a7c9bad 2379 if (info->assocresp_ies) {
334234b5
VT
2380 res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2381 WMI_FRAME_ASSOC_RESP,
6a7c9bad
JM
2382 info->assocresp_ies,
2383 info->assocresp_ies_len);
2384 if (res)
2385 return res;
2386 }
2387
8860020e
JB
2388 return 0;
2389}
2390
2391static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
2392 struct cfg80211_ap_settings *info)
6a7c9bad
JM
2393{
2394 struct ath6kl *ar = ath6kl_priv(dev);
3450334f 2395 struct ath6kl_vif *vif = netdev_priv(dev);
6a7c9bad 2396 struct ieee80211_mgmt *mgmt;
67cd22e4 2397 bool hidden = false;
6a7c9bad
JM
2398 u8 *ies;
2399 int ies_len;
2400 struct wmi_connect_cmd p;
2401 int res;
be5abaaf 2402 int i, ret;
6a7c9bad 2403
8860020e 2404 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s:\n", __func__);
6a7c9bad 2405
990bd915 2406 if (!ath6kl_cfg80211_ready(vif))
6a7c9bad
JM
2407 return -EIO;
2408
f5938f24 2409 if (vif->next_mode != AP_NETWORK)
6a7c9bad
JM
2410 return -EOPNOTSUPP;
2411
8860020e 2412 res = ath6kl_set_ies(vif, &info->beacon);
6a7c9bad 2413
9a5b1318
JM
2414 ar->ap_mode_bkey.valid = false;
2415
6a7c9bad
JM
2416 /* TODO:
2417 * info->interval
2418 * info->dtim_period
2419 */
2420
8860020e 2421 if (info->beacon.head == NULL)
6a7c9bad 2422 return -EINVAL;
8860020e 2423 mgmt = (struct ieee80211_mgmt *) info->beacon.head;
6a7c9bad 2424 ies = mgmt->u.beacon.variable;
8860020e 2425 if (ies > info->beacon.head + info->beacon.head_len)
6a7c9bad 2426 return -EINVAL;
8860020e 2427 ies_len = info->beacon.head + info->beacon.head_len - ies;
6a7c9bad
JM
2428
2429 if (info->ssid == NULL)
2430 return -EINVAL;
3450334f
VT
2431 memcpy(vif->ssid, info->ssid, info->ssid_len);
2432 vif->ssid_len = info->ssid_len;
6a7c9bad 2433 if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
67cd22e4
TP
2434 hidden = true;
2435
2436 res = ath6kl_wmi_ap_hidden_ssid(ar->wmi, vif->fw_vif_idx, hidden);
2437 if (res)
2438 return res;
6a7c9bad 2439
be5abaaf
VT
2440 ret = ath6kl_set_auth_type(vif, info->auth_type);
2441 if (ret)
2442 return ret;
6a7c9bad
JM
2443
2444 memset(&p, 0, sizeof(p));
2445
2446 for (i = 0; i < info->crypto.n_akm_suites; i++) {
2447 switch (info->crypto.akm_suites[i]) {
2448 case WLAN_AKM_SUITE_8021X:
2449 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1)
2450 p.auth_mode |= WPA_AUTH;
2451 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2)
2452 p.auth_mode |= WPA2_AUTH;
2453 break;
2454 case WLAN_AKM_SUITE_PSK:
2455 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1)
2456 p.auth_mode |= WPA_PSK_AUTH;
2457 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2)
2458 p.auth_mode |= WPA2_PSK_AUTH;
2459 break;
2460 }
2461 }
2462 if (p.auth_mode == 0)
2463 p.auth_mode = NONE_AUTH;
3450334f 2464 vif->auth_mode = p.auth_mode;
6a7c9bad
JM
2465
2466 for (i = 0; i < info->crypto.n_ciphers_pairwise; i++) {
2467 switch (info->crypto.ciphers_pairwise[i]) {
2468 case WLAN_CIPHER_SUITE_WEP40:
2469 case WLAN_CIPHER_SUITE_WEP104:
2470 p.prwise_crypto_type |= WEP_CRYPT;
2471 break;
2472 case WLAN_CIPHER_SUITE_TKIP:
2473 p.prwise_crypto_type |= TKIP_CRYPT;
2474 break;
2475 case WLAN_CIPHER_SUITE_CCMP:
2476 p.prwise_crypto_type |= AES_CRYPT;
2477 break;
b8214df1
DS
2478 case WLAN_CIPHER_SUITE_SMS4:
2479 p.prwise_crypto_type |= WAPI_CRYPT;
2480 break;
6a7c9bad
JM
2481 }
2482 }
229ed6b5 2483 if (p.prwise_crypto_type == 0) {
6a7c9bad 2484 p.prwise_crypto_type = NONE_CRYPT;
240d2799 2485 ath6kl_set_cipher(vif, 0, true);
229ed6b5 2486 } else if (info->crypto.n_ciphers_pairwise == 1)
240d2799 2487 ath6kl_set_cipher(vif, info->crypto.ciphers_pairwise[0], true);
6a7c9bad
JM
2488
2489 switch (info->crypto.cipher_group) {
2490 case WLAN_CIPHER_SUITE_WEP40:
2491 case WLAN_CIPHER_SUITE_WEP104:
2492 p.grp_crypto_type = WEP_CRYPT;
2493 break;
2494 case WLAN_CIPHER_SUITE_TKIP:
2495 p.grp_crypto_type = TKIP_CRYPT;
2496 break;
2497 case WLAN_CIPHER_SUITE_CCMP:
2498 p.grp_crypto_type = AES_CRYPT;
2499 break;
b8214df1
DS
2500 case WLAN_CIPHER_SUITE_SMS4:
2501 p.grp_crypto_type = WAPI_CRYPT;
2502 break;
6a7c9bad
JM
2503 default:
2504 p.grp_crypto_type = NONE_CRYPT;
2505 break;
2506 }
240d2799 2507 ath6kl_set_cipher(vif, info->crypto.cipher_group, false);
6a7c9bad
JM
2508
2509 p.nw_type = AP_NETWORK;
f5938f24 2510 vif->nw_type = vif->next_mode;
6a7c9bad 2511
3450334f
VT
2512 p.ssid_len = vif->ssid_len;
2513 memcpy(p.ssid, vif->ssid, vif->ssid_len);
2514 p.dot11_auth_mode = vif->dot11_auth_mode;
cf5333d7 2515 p.ch = cpu_to_le16(vif->next_chan);
6a7c9bad 2516
c1762a3f
TP
2517 /* Enable uAPSD support by default */
2518 res = ath6kl_wmi_ap_set_apsd(ar->wmi, vif->fw_vif_idx, true);
2519 if (res < 0)
2520 return res;
2521
3ca9d1fc
AT
2522 if (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) {
2523 p.nw_subtype = SUBTYPE_P2PGO;
2524 } else {
2525 /*
2526 * Due to firmware limitation, it is not possible to
2527 * do P2P mgmt operations in AP mode
2528 */
2529 p.nw_subtype = SUBTYPE_NONE;
2530 }
2531
334234b5 2532 res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p);
9a5b1318
JM
2533 if (res < 0)
2534 return res;
2535
2536 return 0;
6a7c9bad
JM
2537}
2538
8860020e
JB
2539static int ath6kl_change_beacon(struct wiphy *wiphy, struct net_device *dev,
2540 struct cfg80211_beacon_data *beacon)
6a7c9bad 2541{
8860020e 2542 struct ath6kl_vif *vif = netdev_priv(dev);
6a7c9bad 2543
8860020e
JB
2544 if (!ath6kl_cfg80211_ready(vif))
2545 return -EIO;
2546
2547 if (vif->next_mode != AP_NETWORK)
2548 return -EOPNOTSUPP;
2549
2550 return ath6kl_set_ies(vif, beacon);
6a7c9bad
JM
2551}
2552
8860020e 2553static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev)
6a7c9bad
JM
2554{
2555 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 2556 struct ath6kl_vif *vif = netdev_priv(dev);
6a7c9bad 2557
f5938f24 2558 if (vif->nw_type != AP_NETWORK)
6a7c9bad 2559 return -EOPNOTSUPP;
59c98449 2560 if (!test_bit(CONNECTED, &vif->flags))
6a7c9bad
JM
2561 return -ENOTCONN;
2562
334234b5 2563 ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
59c98449 2564 clear_bit(CONNECTED, &vif->flags);
6a7c9bad
JM
2565
2566 return 0;
2567}
2568
33e5308d
JM
2569static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2570
2571static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev,
2572 u8 *mac)
2573{
2574 struct ath6kl *ar = ath6kl_priv(dev);
2575 struct ath6kl_vif *vif = netdev_priv(dev);
2576 const u8 *addr = mac ? mac : bcast_addr;
2577
2578 return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx, WMI_AP_DEAUTH,
2579 addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
2580}
2581
23875136
JM
2582static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
2583 u8 *mac, struct station_parameters *params)
2584{
2585 struct ath6kl *ar = ath6kl_priv(dev);
f5938f24 2586 struct ath6kl_vif *vif = netdev_priv(dev);
23875136 2587
f5938f24 2588 if (vif->nw_type != AP_NETWORK)
23875136
JM
2589 return -EOPNOTSUPP;
2590
2591 /* Use this only for authorizing/unauthorizing a station */
2592 if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
2593 return -EOPNOTSUPP;
2594
2595 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
334234b5
VT
2596 return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx,
2597 WMI_AP_MLME_AUTHORIZE, mac, 0);
2598 return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx,
2599 WMI_AP_MLME_UNAUTHORIZE, mac, 0);
23875136
JM
2600}
2601
63fa1e0c
JM
2602static int ath6kl_remain_on_channel(struct wiphy *wiphy,
2603 struct net_device *dev,
2604 struct ieee80211_channel *chan,
2605 enum nl80211_channel_type channel_type,
2606 unsigned int duration,
2607 u64 *cookie)
2608{
2609 struct ath6kl *ar = ath6kl_priv(dev);
334234b5 2610 struct ath6kl_vif *vif = netdev_priv(dev);
1052261e 2611 u32 id;
63fa1e0c
JM
2612
2613 /* TODO: if already pending or ongoing remain-on-channel,
2614 * return -EBUSY */
1052261e
JM
2615 id = ++vif->last_roc_id;
2616 if (id == 0) {
2617 /* Do not use 0 as the cookie value */
2618 id = ++vif->last_roc_id;
2619 }
2620 *cookie = id;
63fa1e0c 2621
334234b5
VT
2622 return ath6kl_wmi_remain_on_chnl_cmd(ar->wmi, vif->fw_vif_idx,
2623 chan->center_freq, duration);
63fa1e0c
JM
2624}
2625
2626static int ath6kl_cancel_remain_on_channel(struct wiphy *wiphy,
2627 struct net_device *dev,
2628 u64 cookie)
2629{
2630 struct ath6kl *ar = ath6kl_priv(dev);
334234b5 2631 struct ath6kl_vif *vif = netdev_priv(dev);
63fa1e0c 2632
1052261e 2633 if (cookie != vif->last_roc_id)
63fa1e0c 2634 return -ENOENT;
1052261e 2635 vif->last_cancel_roc_id = cookie;
63fa1e0c 2636
334234b5 2637 return ath6kl_wmi_cancel_remain_on_chnl_cmd(ar->wmi, vif->fw_vif_idx);
63fa1e0c
JM
2638}
2639
334234b5
VT
2640static int ath6kl_send_go_probe_resp(struct ath6kl_vif *vif,
2641 const u8 *buf, size_t len,
2642 unsigned int freq)
8bdfbf40 2643{
334234b5 2644 struct ath6kl *ar = vif->ar;
8bdfbf40
JM
2645 const u8 *pos;
2646 u8 *p2p;
2647 int p2p_len;
2648 int ret;
2649 const struct ieee80211_mgmt *mgmt;
2650
2651 mgmt = (const struct ieee80211_mgmt *) buf;
2652
2653 /* Include P2P IE(s) from the frame generated in user space. */
2654
2655 p2p = kmalloc(len, GFP_KERNEL);
2656 if (p2p == NULL)
2657 return -ENOMEM;
2658 p2p_len = 0;
2659
2660 pos = mgmt->u.probe_resp.variable;
2661 while (pos + 1 < buf + len) {
2662 if (pos + 2 + pos[1] > buf + len)
2663 break;
2664 if (ath6kl_is_p2p_ie(pos)) {
2665 memcpy(p2p + p2p_len, pos, 2 + pos[1]);
2666 p2p_len += 2 + pos[1];
2667 }
2668 pos += 2 + pos[1];
2669 }
2670
334234b5
VT
2671 ret = ath6kl_wmi_send_probe_response_cmd(ar->wmi, vif->fw_vif_idx, freq,
2672 mgmt->da, p2p, p2p_len);
8bdfbf40
JM
2673 kfree(p2p);
2674 return ret;
2675}
2676
d0ff7383
NG
2677static bool ath6kl_mgmt_powersave_ap(struct ath6kl_vif *vif,
2678 u32 id,
2679 u32 freq,
2680 u32 wait,
2681 const u8 *buf,
2682 size_t len,
2683 bool *more_data,
2684 bool no_cck)
2685{
2686 struct ieee80211_mgmt *mgmt;
2687 struct ath6kl_sta *conn;
2688 bool is_psq_empty = false;
2689 struct ath6kl_mgmt_buff *mgmt_buf;
2690 size_t mgmt_buf_size;
2691 struct ath6kl *ar = vif->ar;
2692
2693 mgmt = (struct ieee80211_mgmt *) buf;
2694 if (is_multicast_ether_addr(mgmt->da))
2695 return false;
2696
2697 conn = ath6kl_find_sta(vif, mgmt->da);
2698 if (!conn)
2699 return false;
2700
2701 if (conn->sta_flags & STA_PS_SLEEP) {
2702 if (!(conn->sta_flags & STA_PS_POLLED)) {
2703 /* Queue the frames if the STA is sleeping */
2704 mgmt_buf_size = len + sizeof(struct ath6kl_mgmt_buff);
2705 mgmt_buf = kmalloc(mgmt_buf_size, GFP_KERNEL);
2706 if (!mgmt_buf)
2707 return false;
2708
2709 INIT_LIST_HEAD(&mgmt_buf->list);
2710 mgmt_buf->id = id;
2711 mgmt_buf->freq = freq;
2712 mgmt_buf->wait = wait;
2713 mgmt_buf->len = len;
2714 mgmt_buf->no_cck = no_cck;
2715 memcpy(mgmt_buf->buf, buf, len);
2716 spin_lock_bh(&conn->psq_lock);
2717 is_psq_empty = skb_queue_empty(&conn->psq) &&
2718 (conn->mgmt_psq_len == 0);
2719 list_add_tail(&mgmt_buf->list, &conn->mgmt_psq);
2720 conn->mgmt_psq_len++;
2721 spin_unlock_bh(&conn->psq_lock);
2722
2723 /*
2724 * If this is the first pkt getting queued
2725 * for this STA, update the PVB for this
2726 * STA.
2727 */
2728 if (is_psq_empty)
2729 ath6kl_wmi_set_pvb_cmd(ar->wmi, vif->fw_vif_idx,
2730 conn->aid, 1);
2731 return true;
2732 }
2733
2734 /*
2735 * This tx is because of a PsPoll.
2736 * Determine if MoreData bit has to be set.
2737 */
2738 spin_lock_bh(&conn->psq_lock);
2739 if (!skb_queue_empty(&conn->psq) || (conn->mgmt_psq_len != 0))
2740 *more_data = true;
2741 spin_unlock_bh(&conn->psq_lock);
2742 }
2743
2744 return false;
2745}
2746
8a6c8060
JM
2747static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
2748 struct ieee80211_channel *chan, bool offchan,
2749 enum nl80211_channel_type channel_type,
2750 bool channel_type_valid, unsigned int wait,
e247bd90
JB
2751 const u8 *buf, size_t len, bool no_cck,
2752 bool dont_wait_for_ack, u64 *cookie)
8a6c8060
JM
2753{
2754 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 2755 struct ath6kl_vif *vif = netdev_priv(dev);
8a6c8060 2756 u32 id;
8bdfbf40 2757 const struct ieee80211_mgmt *mgmt;
d0ff7383 2758 bool more_data, queued;
8bdfbf40
JM
2759
2760 mgmt = (const struct ieee80211_mgmt *) buf;
2761 if (buf + len >= mgmt->u.probe_resp.variable &&
f5938f24 2762 vif->nw_type == AP_NETWORK && test_bit(CONNECTED, &vif->flags) &&
8bdfbf40
JM
2763 ieee80211_is_probe_resp(mgmt->frame_control)) {
2764 /*
2765 * Send Probe Response frame in AP mode using a separate WMI
2766 * command to allow the target to fill in the generic IEs.
2767 */
2768 *cookie = 0; /* TX status not supported */
334234b5 2769 return ath6kl_send_go_probe_resp(vif, buf, len,
8bdfbf40
JM
2770 chan->center_freq);
2771 }
8a6c8060 2772
cf5333d7 2773 id = vif->send_action_id++;
8a6c8060
JM
2774 if (id == 0) {
2775 /*
2776 * 0 is a reserved value in the WMI command and shall not be
2777 * used for the command.
2778 */
cf5333d7 2779 id = vif->send_action_id++;
8a6c8060
JM
2780 }
2781
2782 *cookie = id;
3ca9d1fc 2783
d0ff7383
NG
2784 /* AP mode Power saving processing */
2785 if (vif->nw_type == AP_NETWORK) {
2786 queued = ath6kl_mgmt_powersave_ap(vif,
2787 id, chan->center_freq,
2788 wait, buf,
2789 len, &more_data, no_cck);
2790 if (queued)
2791 return 0;
3ca9d1fc 2792 }
d0ff7383
NG
2793
2794 return ath6kl_wmi_send_mgmt_cmd(ar->wmi, vif->fw_vif_idx, id,
2795 chan->center_freq, wait,
2796 buf, len, no_cck);
8a6c8060
JM
2797}
2798
ae32c30a
JM
2799static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
2800 struct net_device *dev,
2801 u16 frame_type, bool reg)
2802{
cf5333d7 2803 struct ath6kl_vif *vif = netdev_priv(dev);
ae32c30a
JM
2804
2805 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: frame_type=0x%x reg=%d\n",
2806 __func__, frame_type, reg);
2807 if (frame_type == IEEE80211_STYPE_PROBE_REQ) {
2808 /*
2809 * Note: This notification callback is not allowed to sleep, so
2810 * we cannot send WMI_PROBE_REQ_REPORT_CMD here. Instead, we
2811 * hardcode target to report Probe Request frames all the time.
2812 */
cf5333d7 2813 vif->probe_req_report = reg;
ae32c30a
JM
2814 }
2815}
2816
10509f90
KV
2817static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
2818 struct net_device *dev,
2819 struct cfg80211_sched_scan_request *request)
2820{
2821 struct ath6kl *ar = ath6kl_priv(dev);
2822 struct ath6kl_vif *vif = netdev_priv(dev);
2823 u16 interval;
2824 int ret;
2825 u8 i;
2826
2827 if (ar->state != ATH6KL_STATE_ON)
2828 return -EIO;
2829
2830 if (vif->sme_state != SME_DISCONNECTED)
2831 return -EBUSY;
2832
2833 for (i = 0; i < ar->wiphy->max_sched_scan_ssids; i++) {
2834 ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
2835 i, DISABLE_SSID_FLAG,
2836 0, NULL);
2837 }
2838
2839 /* fw uses seconds, also make sure that it's >0 */
2840 interval = max_t(u16, 1, request->interval / 1000);
2841
2842 ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
2843 interval, interval,
2844 10, 0, 0, 0, 3, 0, 0, 0);
2845
2846 if (request->n_ssids && request->ssids[0].ssid_len) {
2847 for (i = 0; i < request->n_ssids; i++) {
2848 ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
2849 i, SPECIFIC_SSID_FLAG,
2850 request->ssids[i].ssid_len,
2851 request->ssids[i].ssid);
2852 }
2853 }
2854
2855 ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
2856 ATH6KL_WOW_MODE_ENABLE,
2857 WOW_FILTER_SSID,
2858 WOW_HOST_REQ_DELAY);
2859 if (ret) {
2860 ath6kl_warn("Failed to enable wow with ssid filter: %d\n", ret);
2861 return ret;
2862 }
2863
2864 /* this also clears IE in fw if it's not set */
2865 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2866 WMI_FRAME_PROBE_REQ,
2867 request->ie, request->ie_len);
2868 if (ret) {
2869 ath6kl_warn("Failed to set probe request IE for scheduled scan: %d",
2870 ret);
2871 return ret;
2872 }
2873
2874 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
2875 ATH6KL_HOST_MODE_ASLEEP);
2876 if (ret) {
2877 ath6kl_warn("Failed to enable host sleep mode for sched scan: %d\n",
2878 ret);
2879 return ret;
2880 }
2881
2882 ar->state = ATH6KL_STATE_SCHED_SCAN;
2883
2884 return ret;
2885}
2886
2887static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy,
2888 struct net_device *dev)
2889{
2890 struct ath6kl_vif *vif = netdev_priv(dev);
2891 bool stopped;
2892
2893 stopped = __ath6kl_cfg80211_sscan_stop(vif);
2894
2895 if (!stopped)
2896 return -EIO;
2897
2898 return 0;
2899}
2900
f80574ae
JM
2901static const struct ieee80211_txrx_stypes
2902ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
2903 [NL80211_IFTYPE_STATION] = {
2904 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2905 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
2906 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2907 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
2908 },
ba1f6fe3
JM
2909 [NL80211_IFTYPE_AP] = {
2910 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2911 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
2912 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2913 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
2914 },
f80574ae
JM
2915 [NL80211_IFTYPE_P2P_CLIENT] = {
2916 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2917 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
2918 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2919 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
2920 },
2921 [NL80211_IFTYPE_P2P_GO] = {
2922 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2923 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
2924 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
2925 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
2926 },
2927};
2928
bdcd8170 2929static struct cfg80211_ops ath6kl_cfg80211_ops = {
55055976
VT
2930 .add_virtual_intf = ath6kl_cfg80211_add_iface,
2931 .del_virtual_intf = ath6kl_cfg80211_del_iface,
bdcd8170
KV
2932 .change_virtual_intf = ath6kl_cfg80211_change_iface,
2933 .scan = ath6kl_cfg80211_scan,
2934 .connect = ath6kl_cfg80211_connect,
2935 .disconnect = ath6kl_cfg80211_disconnect,
2936 .add_key = ath6kl_cfg80211_add_key,
2937 .get_key = ath6kl_cfg80211_get_key,
2938 .del_key = ath6kl_cfg80211_del_key,
2939 .set_default_key = ath6kl_cfg80211_set_default_key,
2940 .set_wiphy_params = ath6kl_cfg80211_set_wiphy_params,
2941 .set_tx_power = ath6kl_cfg80211_set_txpower,
2942 .get_tx_power = ath6kl_cfg80211_get_txpower,
2943 .set_power_mgmt = ath6kl_cfg80211_set_power_mgmt,
2944 .join_ibss = ath6kl_cfg80211_join_ibss,
2945 .leave_ibss = ath6kl_cfg80211_leave_ibss,
2946 .get_station = ath6kl_get_station,
2947 .set_pmksa = ath6kl_set_pmksa,
2948 .del_pmksa = ath6kl_del_pmksa,
2949 .flush_pmksa = ath6kl_flush_pmksa,
003353b0 2950 CFG80211_TESTMODE_CMD(ath6kl_tm_cmd)
abcb344b 2951#ifdef CONFIG_PM
52d81a68
KV
2952 .suspend = __ath6kl_cfg80211_suspend,
2953 .resume = __ath6kl_cfg80211_resume,
abcb344b 2954#endif
6a7c9bad 2955 .set_channel = ath6kl_set_channel,
8860020e
JB
2956 .start_ap = ath6kl_start_ap,
2957 .change_beacon = ath6kl_change_beacon,
2958 .stop_ap = ath6kl_stop_ap,
33e5308d 2959 .del_station = ath6kl_del_station,
23875136 2960 .change_station = ath6kl_change_station,
63fa1e0c
JM
2961 .remain_on_channel = ath6kl_remain_on_channel,
2962 .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel,
8a6c8060 2963 .mgmt_tx = ath6kl_mgmt_tx,
ae32c30a 2964 .mgmt_frame_register = ath6kl_mgmt_frame_register,
10509f90
KV
2965 .sched_scan_start = ath6kl_cfg80211_sscan_start,
2966 .sched_scan_stop = ath6kl_cfg80211_sscan_stop,
bdcd8170
KV
2967};
2968
7125f01d 2969void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
ec4b7f60 2970{
10509f90
KV
2971 ath6kl_cfg80211_sscan_disable(vif);
2972
ec4b7f60 2973 switch (vif->sme_state) {
c97a31b0
KV
2974 case SME_DISCONNECTED:
2975 break;
ec4b7f60
KV
2976 case SME_CONNECTING:
2977 cfg80211_connect_result(vif->ndev, vif->bssid, NULL, 0,
2978 NULL, 0,
2979 WLAN_STATUS_UNSPECIFIED_FAILURE,
2980 GFP_KERNEL);
2981 break;
2982 case SME_CONNECTED:
ec4b7f60
KV
2983 cfg80211_disconnected(vif->ndev, 0, NULL, 0, GFP_KERNEL);
2984 break;
2985 }
2986
2987 if (test_bit(CONNECTED, &vif->flags) ||
2988 test_bit(CONNECT_PEND, &vif->flags))
7125f01d 2989 ath6kl_wmi_disconnect_cmd(vif->ar->wmi, vif->fw_vif_idx);
ec4b7f60
KV
2990
2991 vif->sme_state = SME_DISCONNECTED;
1f405255
KV
2992 clear_bit(CONNECTED, &vif->flags);
2993 clear_bit(CONNECT_PEND, &vif->flags);
ec4b7f60
KV
2994
2995 /* disable scanning */
7125f01d
KV
2996 if (ath6kl_wmi_scanparams_cmd(vif->ar->wmi, vif->fw_vif_idx, 0xFFFF,
2997 0, 0, 0, 0, 0, 0, 0, 0, 0) != 0)
2998 ath6kl_warn("failed to disable scan during stop\n");
ec4b7f60
KV
2999
3000 ath6kl_cfg80211_scan_complete_event(vif, true);
3001}
3002
7125f01d
KV
3003void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
3004{
3005 struct ath6kl_vif *vif;
3006
3007 vif = ath6kl_vif_first(ar);
3008 if (!vif) {
3009 /* save the current power mode before enabling power save */
3010 ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
3011
3012 if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0)
3013 ath6kl_warn("ath6kl_deep_sleep_enable: "
3014 "wmi_powermode_cmd failed\n");
3015 return;
3016 }
3017
3018 /*
3019 * FIXME: we should take ar->list_lock to protect changes in the
3020 * vif_list, but that's not trivial to do as ath6kl_cfg80211_stop()
3021 * sleeps.
3022 */
3023 list_for_each_entry(vif, &ar->vif_list, list)
3024 ath6kl_cfg80211_stop(vif);
3025}
3026
c25889e8 3027static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif)
bdcd8170 3028{
7baef812 3029 vif->aggr_cntxt = aggr_init(vif);
2132c69c 3030 if (!vif->aggr_cntxt) {
8dafb70e
VT
3031 ath6kl_err("failed to initialize aggr\n");
3032 return -ENOMEM;
3033 }
3034
de3ad713 3035 setup_timer(&vif->disconnect_timer, disconnect_timer_handler,
108438bc 3036 (unsigned long) vif->ndev);
10509f90
KV
3037 setup_timer(&vif->sched_scan_timer, ath6kl_wmi_sscan_timer,
3038 (unsigned long) vif);
3039
de3ad713 3040 set_bit(WMM_ENABLED, &vif->flags);
478ac027 3041 spin_lock_init(&vif->if_lock);
bdcd8170 3042
80abaf9b
VT
3043 INIT_LIST_HEAD(&vif->mc_filter);
3044
8dafb70e
VT
3045 return 0;
3046}
3047
c25889e8 3048void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif)
8dafb70e 3049{
55055976 3050 struct ath6kl *ar = vif->ar;
80abaf9b 3051 struct ath6kl_mc_filter *mc_filter, *tmp;
55055976 3052
2132c69c 3053 aggr_module_destroy(vif->aggr_cntxt);
8dafb70e 3054
55055976
VT
3055 ar->avail_idx_map |= BIT(vif->fw_vif_idx);
3056
3057 if (vif->nw_type == ADHOC_NETWORK)
3058 ar->ibss_if_active = false;
3059
80abaf9b
VT
3060 list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) {
3061 list_del(&mc_filter->list);
3062 kfree(mc_filter);
3063 }
3064
27929723 3065 unregister_netdevice(vif->ndev);
55055976
VT
3066
3067 ar->num_vif--;
8dafb70e
VT
3068}
3069
3070struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
55055976
VT
3071 enum nl80211_iftype type, u8 fw_vif_idx,
3072 u8 nw_type)
8dafb70e
VT
3073{
3074 struct net_device *ndev;
108438bc 3075 struct ath6kl_vif *vif;
8dafb70e 3076
55055976 3077 ndev = alloc_netdev(sizeof(*vif), name, ether_setup);
8dafb70e
VT
3078 if (!ndev)
3079 return NULL;
3080
108438bc
VT
3081 vif = netdev_priv(ndev);
3082 ndev->ieee80211_ptr = &vif->wdev;
3083 vif->wdev.wiphy = ar->wiphy;
3084 vif->ar = ar;
108438bc
VT
3085 vif->ndev = ndev;
3086 SET_NETDEV_DEV(ndev, wiphy_dev(vif->wdev.wiphy));
3087 vif->wdev.netdev = ndev;
3088 vif->wdev.iftype = type;
334234b5 3089 vif->fw_vif_idx = fw_vif_idx;
d0d670ab
KV
3090 vif->nw_type = nw_type;
3091 vif->next_mode = nw_type;
8f46fccd 3092 vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;
ce0dc0cf 3093 vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME;
8dafb70e 3094
55055976
VT
3095 memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
3096 if (fw_vif_idx != 0)
3097 ndev->dev_addr[0] = (ndev->dev_addr[0] ^ (1 << fw_vif_idx)) |
3098 0x2;
3099
8dafb70e
VT
3100 init_netdev(ndev);
3101
e29f25f5 3102 ath6kl_init_control_info(vif);
8dafb70e 3103
c25889e8 3104 if (ath6kl_cfg80211_vif_init(vif))
8dafb70e
VT
3105 goto err;
3106
27929723 3107 if (register_netdevice(ndev))
8dafb70e
VT
3108 goto err;
3109
55055976 3110 ar->avail_idx_map &= ~BIT(fw_vif_idx);
14ee6f6b 3111 vif->sme_state = SME_DISCONNECTED;
59c98449 3112 set_bit(WLAN_ENABLED, &vif->flags);
8dafb70e 3113 ar->wlan_pwr_state = WLAN_POWER_STATE_ON;
59c98449 3114 set_bit(NETDEV_REGISTERED, &vif->flags);
8dafb70e 3115
55055976
VT
3116 if (type == NL80211_IFTYPE_ADHOC)
3117 ar->ibss_if_active = true;
3118
11f6e40d 3119 spin_lock_bh(&ar->list_lock);
990bd915 3120 list_add_tail(&vif->list, &ar->vif_list);
11f6e40d 3121 spin_unlock_bh(&ar->list_lock);
990bd915 3122
8dafb70e
VT
3123 return ndev;
3124
3125err:
27929723
VT
3126 aggr_module_destroy(vif->aggr_cntxt);
3127 free_netdev(ndev);
8dafb70e
VT
3128 return NULL;
3129}
3130
46d33a21
KV
3131int ath6kl_cfg80211_init(struct ath6kl *ar)
3132{
3133 struct wiphy *wiphy = ar->wiphy;
3134 int ret;
3135
3136 wiphy->mgmt_stypes = ath6kl_mgmt_stypes;
3137
3138 wiphy->max_remain_on_channel_duration = 5000;
3139
3140 /* set device pointer for wiphy */
3141 set_wiphy_dev(wiphy, ar->dev);
3142
3143 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
3144 BIT(NL80211_IFTYPE_ADHOC) |
3145 BIT(NL80211_IFTYPE_AP);
3146 if (ar->p2p) {
3147 wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_GO) |
3148 BIT(NL80211_IFTYPE_P2P_CLIENT);
3149 }
3150
3151 /* max num of ssids that can be probed during scanning */
3152 wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
3153 wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
3154 wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
3155 wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz;
3156 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
3157
3158 wiphy->cipher_suites = cipher_suites;
3159 wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
3160
3161 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
3162 WIPHY_WOWLAN_DISCONNECT |
3163 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
3164 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
3165 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
3166 WIPHY_WOWLAN_4WAY_HANDSHAKE;
3167 wiphy->wowlan.n_patterns = WOW_MAX_FILTERS_PER_LIST;
3168 wiphy->wowlan.pattern_min_len = 1;
3169 wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE;
3170
3171 wiphy->max_sched_scan_ssids = 10;
3172
f2afdac7
VT
3173 ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
3174 WIPHY_FLAG_HAVE_AP_SME |
3175 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
3176 WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
3177
3178 if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities))
3179 ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
3180
3181 ar->wiphy->probe_resp_offload =
3182 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
3183 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
3184 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P |
3185 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U;
3186
46d33a21
KV
3187 ret = wiphy_register(wiphy);
3188 if (ret < 0) {
3189 ath6kl_err("couldn't register wiphy device\n");
3190 return ret;
3191 }
3192
e5348a1e
VT
3193 ar->wiphy_registered = true;
3194
46d33a21
KV
3195 return 0;
3196}
3197
3198void ath6kl_cfg80211_cleanup(struct ath6kl *ar)
8dafb70e 3199{
be98e3a4 3200 wiphy_unregister(ar->wiphy);
e5348a1e
VT
3201
3202 ar->wiphy_registered = false;
45eaa78f 3203}
46d33a21 3204
45eaa78f
KV
3205struct ath6kl *ath6kl_cfg80211_create(void)
3206{
3207 struct ath6kl *ar;
3208 struct wiphy *wiphy;
3209
3210 /* create a new wiphy for use with cfg80211 */
3211 wiphy = wiphy_new(&ath6kl_cfg80211_ops, sizeof(struct ath6kl));
3212
3213 if (!wiphy) {
3214 ath6kl_err("couldn't allocate wiphy device\n");
3215 return NULL;
3216 }
3217
3218 ar = wiphy_priv(wiphy);
3219 ar->wiphy = wiphy;
3220
3221 return ar;
3222}
3223
3224/* Note: ar variable must not be accessed after calling this! */
3225void ath6kl_cfg80211_destroy(struct ath6kl *ar)
3226{
1d2a4456
VT
3227 int i;
3228
3229 for (i = 0; i < AP_MAX_NUM_STA; i++)
3230 kfree(ar->sta_list[i].aggr_conn);
3231
be98e3a4 3232 wiphy_free(ar->wiphy);
bdcd8170 3233}
45eaa78f 3234