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