cfg80211: allow per interface TX power setting
[deliverable/linux.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
3ca9d1fc 1034 if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
96f1fadc 1035 ar->fw_capabilities)) {
3ca9d1fc
AT
1036 /*
1037 * If capable of doing P2P mgmt operations using
1038 * station interface, send additional information like
1039 * supported rates to advertise and xmit rates for
1040 * probe requests
1041 */
1042 ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx,
1043 WMI_LONG_SCAN, force_fg_scan,
13423c31
VT
1044 false, 0,
1045 ATH6KL_FG_SCAN_INTERVAL,
1046 n_channels, channels,
1047 request->no_cck,
3ca9d1fc
AT
1048 request->rates);
1049 } else {
1050 ret = ath6kl_wmi_startscan_cmd(ar->wmi, vif->fw_vif_idx,
1051 WMI_LONG_SCAN, force_fg_scan,
13423c31
VT
1052 false, 0,
1053 ATH6KL_FG_SCAN_INTERVAL,
1054 n_channels, channels);
3ca9d1fc 1055 }
5b35dff0 1056 if (ret) {
bdcd8170 1057 ath6kl_err("wmi_startscan_cmd failed\n");
5b35dff0
RM
1058 vif->scan_req = NULL;
1059 }
bdcd8170 1060
1276c9ef
EL
1061 kfree(channels);
1062
bdcd8170
KV
1063 return ret;
1064}
1065
1c17d313 1066void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted)
bdcd8170 1067{
240d2799 1068 struct ath6kl *ar = vif->ar;
6fd1eace 1069 int i;
bdcd8170 1070
1c17d313
KV
1071 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status%s\n", __func__,
1072 aborted ? " aborted" : "");
bdcd8170 1073
14ee6f6b 1074 if (!vif->scan_req)
6fd1eace
KV
1075 return;
1076
1c17d313 1077 if (aborted)
6fd1eace 1078 goto out;
6fd1eace 1079
14ee6f6b
VT
1080 if (vif->scan_req->n_ssids && vif->scan_req->ssids[0].ssid_len) {
1081 for (i = 0; i < vif->scan_req->n_ssids; i++) {
334234b5
VT
1082 ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
1083 i + 1, DISABLE_SSID_FLAG,
6fd1eace 1084 0, NULL);
bdcd8170 1085 }
bdcd8170 1086 }
6fd1eace
KV
1087
1088out:
cb93821a 1089 cfg80211_scan_done(vif->scan_req, aborted);
14ee6f6b 1090 vif->scan_req = NULL;
bdcd8170
KV
1091}
1092
c4f7863e
TP
1093void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
1094 enum wmi_phy_mode mode)
1095{
1096 enum nl80211_channel_type type;
1097
1098 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1099 "channel switch notify nw_type %d freq %d mode %d\n",
1100 vif->nw_type, freq, mode);
1101
1102 type = (mode == WMI_11G_HT20) ? NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT;
1103
1104 cfg80211_ch_switch_notify(vif->ndev, freq, type);
1105}
1106
bdcd8170
KV
1107static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
1108 u8 key_index, bool pairwise,
1109 const u8 *mac_addr,
1110 struct key_params *params)
1111{
d6d5c06c 1112 struct ath6kl *ar = ath6kl_priv(ndev);
59c98449 1113 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170 1114 struct ath6kl_key *key = NULL;
4a8ce2fd 1115 int seq_len;
bdcd8170
KV
1116 u8 key_usage;
1117 u8 key_type;
bdcd8170 1118
990bd915 1119 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1120 return -EIO;
1121
837cb97e
JM
1122 if (params->cipher == CCKM_KRK_CIPHER_SUITE) {
1123 if (params->key_len != WMI_KRK_LEN)
1124 return -EINVAL;
240d2799
VT
1125 return ath6kl_wmi_add_krk_cmd(ar->wmi, vif->fw_vif_idx,
1126 params->key);
837cb97e
JM
1127 }
1128
792ecb33 1129 if (key_index > WMI_MAX_KEY_INDEX) {
bdcd8170
KV
1130 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1131 "%s: key index %d out of bounds\n", __func__,
1132 key_index);
1133 return -ENOENT;
1134 }
1135
6f2a73f9 1136 key = &vif->keys[key_index];
bdcd8170
KV
1137 memset(key, 0, sizeof(struct ath6kl_key));
1138
1139 if (pairwise)
1140 key_usage = PAIRWISE_USAGE;
1141 else
1142 key_usage = GROUP_USAGE;
1143
4a8ce2fd
SM
1144 seq_len = params->seq_len;
1145 if (params->cipher == WLAN_CIPHER_SUITE_SMS4 &&
1146 seq_len > ATH6KL_KEY_SEQ_LEN) {
1147 /* Only first half of the WPI PN is configured */
1148 seq_len = ATH6KL_KEY_SEQ_LEN;
bdcd8170 1149 }
4a8ce2fd
SM
1150 if (params->key_len > WLAN_MAX_KEY_LEN ||
1151 seq_len > sizeof(key->seq))
1152 return -EINVAL;
1153
1154 key->key_len = params->key_len;
1155 memcpy(key->key, params->key, key->key_len);
1156 key->seq_len = seq_len;
1157 memcpy(key->seq, params->seq, key->seq_len);
1158 key->cipher = params->cipher;
bdcd8170
KV
1159
1160 switch (key->cipher) {
1161 case WLAN_CIPHER_SUITE_WEP40:
1162 case WLAN_CIPHER_SUITE_WEP104:
1163 key_type = WEP_CRYPT;
1164 break;
1165
1166 case WLAN_CIPHER_SUITE_TKIP:
1167 key_type = TKIP_CRYPT;
1168 break;
1169
1170 case WLAN_CIPHER_SUITE_CCMP:
1171 key_type = AES_CRYPT;
1172 break;
5e07021e
DS
1173 case WLAN_CIPHER_SUITE_SMS4:
1174 key_type = WAPI_CRYPT;
1175 break;
bdcd8170
KV
1176
1177 default:
1178 return -ENOTSUPP;
1179 }
1180
ddc3d77c
KV
1181 if (((vif->auth_mode == WPA_PSK_AUTH) ||
1182 (vif->auth_mode == WPA2_PSK_AUTH)) &&
1183 (key_usage & GROUP_USAGE))
de3ad713 1184 del_timer(&vif->disconnect_timer);
bdcd8170
KV
1185
1186 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1187 "%s: index %d, key_len %d, key_type 0x%x, key_usage 0x%x, seq_len %d\n",
1188 __func__, key_index, key->key_len, key_type,
1189 key_usage, key->seq_len);
1190
f5938f24 1191 if (vif->nw_type == AP_NETWORK && !pairwise &&
4703290a 1192 (key_type == TKIP_CRYPT || key_type == AES_CRYPT ||
cc4d623d 1193 key_type == WAPI_CRYPT)) {
9a5b1318
JM
1194 ar->ap_mode_bkey.valid = true;
1195 ar->ap_mode_bkey.key_index = key_index;
1196 ar->ap_mode_bkey.key_type = key_type;
1197 ar->ap_mode_bkey.key_len = key->key_len;
1198 memcpy(ar->ap_mode_bkey.key, key->key, key->key_len);
59c98449 1199 if (!test_bit(CONNECTED, &vif->flags)) {
cdeb8602
KV
1200 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1201 "Delay initial group key configuration until AP mode has been started\n");
9a5b1318
JM
1202 /*
1203 * The key will be set in ath6kl_connect_ap_mode() once
1204 * the connected event is received from the target.
1205 */
1206 return 0;
1207 }
1208 }
1209
f5938f24 1210 if (vif->next_mode == AP_NETWORK && key_type == WEP_CRYPT &&
59c98449 1211 !test_bit(CONNECTED, &vif->flags)) {
151411e8
JM
1212 /*
1213 * Store the key locally so that it can be re-configured after
1214 * the AP mode has properly started
1215 * (ath6kl_install_statioc_wep_keys).
1216 */
cdeb8602
KV
1217 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1218 "Delay WEP key configuration until AP mode has been started\n");
6f2a73f9
VT
1219 vif->wep_key_list[key_index].key_len = key->key_len;
1220 memcpy(vif->wep_key_list[key_index].key, key->key,
1221 key->key_len);
151411e8
JM
1222 return 0;
1223 }
1224
7cefa44f 1225 return ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx, key_index,
f3e61ece
JM
1226 key_type, key_usage, key->key_len,
1227 key->seq, key->seq_len, key->key,
1228 KEY_OP_INIT_VAL,
1229 (u8 *) mac_addr, SYNC_BOTH_WMIFLAG);
bdcd8170
KV
1230}
1231
1232static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
1233 u8 key_index, bool pairwise,
1234 const u8 *mac_addr)
1235{
d6d5c06c 1236 struct ath6kl *ar = ath6kl_priv(ndev);
6f2a73f9 1237 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170
KV
1238
1239 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1240
990bd915 1241 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1242 return -EIO;
1243
792ecb33 1244 if (key_index > WMI_MAX_KEY_INDEX) {
bdcd8170
KV
1245 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1246 "%s: key index %d out of bounds\n", __func__,
1247 key_index);
1248 return -ENOENT;
1249 }
1250
6f2a73f9 1251 if (!vif->keys[key_index].key_len) {
bdcd8170
KV
1252 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1253 "%s: index %d is empty\n", __func__, key_index);
1254 return 0;
1255 }
1256
6f2a73f9 1257 vif->keys[key_index].key_len = 0;
bdcd8170 1258
334234b5 1259 return ath6kl_wmi_deletekey_cmd(ar->wmi, vif->fw_vif_idx, key_index);
bdcd8170
KV
1260}
1261
1262static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
1263 u8 key_index, bool pairwise,
1264 const u8 *mac_addr, void *cookie,
1265 void (*callback) (void *cookie,
1266 struct key_params *))
1267{
6f2a73f9 1268 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170
KV
1269 struct ath6kl_key *key = NULL;
1270 struct key_params params;
1271
1272 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1273
990bd915 1274 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1275 return -EIO;
1276
792ecb33 1277 if (key_index > WMI_MAX_KEY_INDEX) {
bdcd8170
KV
1278 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1279 "%s: key index %d out of bounds\n", __func__,
1280 key_index);
1281 return -ENOENT;
1282 }
1283
6f2a73f9 1284 key = &vif->keys[key_index];
bdcd8170
KV
1285 memset(&params, 0, sizeof(params));
1286 params.cipher = key->cipher;
1287 params.key_len = key->key_len;
1288 params.seq_len = key->seq_len;
1289 params.seq = key->seq;
1290 params.key = key->key;
1291
1292 callback(cookie, &params);
1293
1294 return key->key_len ? 0 : -ENOENT;
1295}
1296
1297static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
1298 struct net_device *ndev,
1299 u8 key_index, bool unicast,
1300 bool multicast)
1301{
d6d5c06c 1302 struct ath6kl *ar = ath6kl_priv(ndev);
59c98449 1303 struct ath6kl_vif *vif = netdev_priv(ndev);
bdcd8170 1304 struct ath6kl_key *key = NULL;
bdcd8170 1305 u8 key_usage;
229ed6b5 1306 enum crypto_type key_type = NONE_CRYPT;
bdcd8170
KV
1307
1308 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1309
990bd915 1310 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1311 return -EIO;
1312
792ecb33 1313 if (key_index > WMI_MAX_KEY_INDEX) {
bdcd8170
KV
1314 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1315 "%s: key index %d out of bounds\n",
1316 __func__, key_index);
1317 return -ENOENT;
1318 }
1319
6f2a73f9 1320 if (!vif->keys[key_index].key_len) {
bdcd8170
KV
1321 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: invalid key index %d\n",
1322 __func__, key_index);
1323 return -EINVAL;
1324 }
1325
3450334f 1326 vif->def_txkey_index = key_index;
6f2a73f9 1327 key = &vif->keys[vif->def_txkey_index];
bdcd8170 1328 key_usage = GROUP_USAGE;
3450334f 1329 if (vif->prwise_crypto == WEP_CRYPT)
bdcd8170 1330 key_usage |= TX_USAGE;
229ed6b5 1331 if (unicast)
3450334f 1332 key_type = vif->prwise_crypto;
229ed6b5 1333 if (multicast)
3450334f 1334 key_type = vif->grp_crypto;
bdcd8170 1335
f5938f24 1336 if (vif->next_mode == AP_NETWORK && !test_bit(CONNECTED, &vif->flags))
9a5b1318
JM
1337 return 0; /* Delay until AP mode has been started */
1338
f3e61ece
JM
1339 return ath6kl_wmi_addkey_cmd(ar->wmi, vif->fw_vif_idx,
1340 vif->def_txkey_index,
1341 key_type, key_usage,
1342 key->key_len, key->seq, key->seq_len,
1343 key->key,
1344 KEY_OP_INIT_VAL, NULL,
1345 SYNC_BOTH_WMIFLAG);
bdcd8170
KV
1346}
1347
240d2799 1348void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl_vif *vif, u8 keyid,
bdcd8170
KV
1349 bool ismcast)
1350{
1351 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1352 "%s: keyid %d, ismcast %d\n", __func__, keyid, ismcast);
1353
240d2799 1354 cfg80211_michael_mic_failure(vif->ndev, vif->bssid,
bdcd8170
KV
1355 (ismcast ? NL80211_KEYTYPE_GROUP :
1356 NL80211_KEYTYPE_PAIRWISE), keyid, NULL,
1357 GFP_KERNEL);
1358}
1359
1360static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1361{
1362 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
990bd915 1363 struct ath6kl_vif *vif;
bdcd8170
KV
1364 int ret;
1365
1366 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: changed 0x%x\n", __func__,
1367 changed);
1368
990bd915
VT
1369 vif = ath6kl_vif_first(ar);
1370 if (!vif)
1371 return -EIO;
1372
1373 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1374 return -EIO;
1375
1376 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
1377 ret = ath6kl_wmi_set_rts_cmd(ar->wmi, wiphy->rts_threshold);
1378 if (ret != 0) {
1379 ath6kl_err("ath6kl_wmi_set_rts_cmd failed\n");
1380 return -EIO;
1381 }
1382 }
1383
1384 return 0;
1385}
1386
bdcd8170 1387static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
c8442118 1388 struct wireless_dev *wdev,
bdcd8170 1389 enum nl80211_tx_power_setting type,
b992a285 1390 int mbm)
bdcd8170
KV
1391{
1392 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
990bd915 1393 struct ath6kl_vif *vif;
b992a285 1394 int dbm = MBM_TO_DBM(mbm);
bdcd8170
KV
1395
1396 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__,
1397 type, dbm);
1398
990bd915
VT
1399 vif = ath6kl_vif_first(ar);
1400 if (!vif)
1401 return -EIO;
1402
1403 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1404 return -EIO;
1405
1406 switch (type) {
1407 case NL80211_TX_POWER_AUTOMATIC:
1408 return 0;
1409 case NL80211_TX_POWER_LIMITED:
d0d670ab 1410 ar->tx_pwr = dbm;
bdcd8170
KV
1411 break;
1412 default:
1413 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x not supported\n",
1414 __func__, type);
1415 return -EOPNOTSUPP;
1416 }
1417
d0d670ab 1418 ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx, dbm);
bdcd8170
KV
1419
1420 return 0;
1421}
1422
c8442118
JB
1423static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy,
1424 struct wireless_dev *wdev,
1425 int *dbm)
bdcd8170
KV
1426{
1427 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
990bd915
VT
1428 struct ath6kl_vif *vif;
1429
1430 vif = ath6kl_vif_first(ar);
1431 if (!vif)
1432 return -EIO;
bdcd8170 1433
990bd915 1434 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1435 return -EIO;
1436
59c98449 1437 if (test_bit(CONNECTED, &vif->flags)) {
bdcd8170
KV
1438 ar->tx_pwr = 0;
1439
990bd915 1440 if (ath6kl_wmi_get_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx) != 0) {
bdcd8170
KV
1441 ath6kl_err("ath6kl_wmi_get_tx_pwr_cmd failed\n");
1442 return -EIO;
1443 }
1444
1445 wait_event_interruptible_timeout(ar->event_wq, ar->tx_pwr != 0,
1446 5 * HZ);
1447
1448 if (signal_pending(current)) {
1449 ath6kl_err("target did not respond\n");
1450 return -EINTR;
1451 }
1452 }
1453
1454 *dbm = ar->tx_pwr;
1455 return 0;
1456}
1457
1458static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
1459 struct net_device *dev,
1460 bool pmgmt, int timeout)
1461{
1462 struct ath6kl *ar = ath6kl_priv(dev);
1463 struct wmi_power_mode_cmd mode;
334234b5 1464 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170
KV
1465
1466 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: pmgmt %d, timeout %d\n",
1467 __func__, pmgmt, timeout);
1468
990bd915 1469 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1470 return -EIO;
1471
1472 if (pmgmt) {
1473 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: max perf\n", __func__);
1474 mode.pwr_mode = REC_POWER;
1475 } else {
1476 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: rec power\n", __func__);
1477 mode.pwr_mode = MAX_PERF_POWER;
1478 }
1479
334234b5 1480 if (ath6kl_wmi_powermode_cmd(ar->wmi, vif->fw_vif_idx,
96f1fadc 1481 mode.pwr_mode) != 0) {
bdcd8170
KV
1482 ath6kl_err("wmi_powermode_cmd failed\n");
1483 return -EIO;
1484 }
1485
1486 return 0;
1487}
1488
84efbb84 1489static struct wireless_dev *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
552bff0c 1490 const char *name,
84efbb84
JB
1491 enum nl80211_iftype type,
1492 u32 *flags,
1493 struct vif_params *params)
55055976
VT
1494{
1495 struct ath6kl *ar = wiphy_priv(wiphy);
84efbb84 1496 struct wireless_dev *wdev;
55055976
VT
1497 u8 if_idx, nw_type;
1498
71f96ee6 1499 if (ar->num_vif == ar->vif_max) {
55055976
VT
1500 ath6kl_err("Reached maximum number of supported vif\n");
1501 return ERR_PTR(-EINVAL);
1502 }
1503
1504 if (!ath6kl_is_valid_iftype(ar, type, &if_idx, &nw_type)) {
1505 ath6kl_err("Not a supported interface type\n");
1506 return ERR_PTR(-EINVAL);
1507 }
1508
84efbb84
JB
1509 wdev = ath6kl_interface_add(ar, name, type, if_idx, nw_type);
1510 if (!wdev)
55055976
VT
1511 return ERR_PTR(-ENOMEM);
1512
1513 ar->num_vif++;
1514
84efbb84 1515 return wdev;
55055976
VT
1516}
1517
1518static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy,
84efbb84 1519 struct wireless_dev *wdev)
55055976
VT
1520{
1521 struct ath6kl *ar = wiphy_priv(wiphy);
84efbb84 1522 struct ath6kl_vif *vif = netdev_priv(wdev->netdev);
55055976 1523
11f6e40d 1524 spin_lock_bh(&ar->list_lock);
55055976 1525 list_del(&vif->list);
11f6e40d 1526 spin_unlock_bh(&ar->list_lock);
55055976
VT
1527
1528 ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag));
1529
c25889e8 1530 ath6kl_cfg80211_vif_cleanup(vif);
55055976
VT
1531
1532 return 0;
1533}
1534
bdcd8170
KV
1535static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
1536 struct net_device *ndev,
1537 enum nl80211_iftype type, u32 *flags,
1538 struct vif_params *params)
1539{
f5938f24 1540 struct ath6kl_vif *vif = netdev_priv(ndev);
1e8d13b0 1541 int i;
bdcd8170
KV
1542
1543 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type);
1544
1e8d13b0
VT
1545 /*
1546 * Don't bring up p2p on an interface which is not initialized
1547 * for p2p operation where fw does not have capability to switch
1548 * dynamically between non-p2p and p2p type interface.
1549 */
1550 if (!test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
1551 vif->ar->fw_capabilities) &&
1552 (type == NL80211_IFTYPE_P2P_CLIENT ||
1553 type == NL80211_IFTYPE_P2P_GO)) {
1554 if (vif->ar->vif_max == 1) {
1555 if (vif->fw_vif_idx != 0)
1556 return -EINVAL;
1557 else
1558 goto set_iface_type;
1559 }
1560
1561 for (i = vif->ar->max_norm_iface; i < vif->ar->vif_max; i++) {
1562 if (i == vif->fw_vif_idx)
1563 break;
1564 }
1565
1566 if (i == vif->ar->vif_max) {
1567 ath6kl_err("Invalid interface to bring up P2P\n");
1568 return -EINVAL;
1569 }
1570 }
1571
c422d52d
TP
1572 /* need to clean up enhanced bmiss detection fw state */
1573 ath6kl_cfg80211_sta_bmiss_enhance(vif, false);
1574
1e8d13b0 1575set_iface_type:
bdcd8170
KV
1576 switch (type) {
1577 case NL80211_IFTYPE_STATION:
f5938f24 1578 vif->next_mode = INFRA_NETWORK;
bdcd8170
KV
1579 break;
1580 case NL80211_IFTYPE_ADHOC:
f5938f24 1581 vif->next_mode = ADHOC_NETWORK;
bdcd8170 1582 break;
6e4604c8 1583 case NL80211_IFTYPE_AP:
f5938f24 1584 vif->next_mode = AP_NETWORK;
6e4604c8 1585 break;
6b5e5d25 1586 case NL80211_IFTYPE_P2P_CLIENT:
f5938f24 1587 vif->next_mode = INFRA_NETWORK;
6b5e5d25
JM
1588 break;
1589 case NL80211_IFTYPE_P2P_GO:
f5938f24 1590 vif->next_mode = AP_NETWORK;
6b5e5d25 1591 break;
bdcd8170
KV
1592 default:
1593 ath6kl_err("invalid interface type %u\n", type);
1594 return -EOPNOTSUPP;
1595 }
1596
551959d8 1597 vif->wdev.iftype = type;
bdcd8170
KV
1598
1599 return 0;
1600}
1601
1602static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
1603 struct net_device *dev,
1604 struct cfg80211_ibss_params *ibss_param)
1605{
1606 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 1607 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170
KV
1608 int status;
1609
990bd915 1610 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1611 return -EIO;
1612
3450334f
VT
1613 vif->ssid_len = ibss_param->ssid_len;
1614 memcpy(vif->ssid, ibss_param->ssid, vif->ssid_len);
bdcd8170
KV
1615
1616 if (ibss_param->channel)
f74bac54 1617 vif->ch_hint = ibss_param->channel->center_freq;
bdcd8170
KV
1618
1619 if (ibss_param->channel_fixed) {
1620 /*
1621 * TODO: channel_fixed: The channel should be fixed, do not
1622 * search for IBSSs to join on other channels. Target
1623 * firmware does not support this feature, needs to be
1624 * updated.
1625 */
1626 return -EOPNOTSUPP;
1627 }
1628
8c8b65e3 1629 memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
bdcd8170 1630 if (ibss_param->bssid && !is_broadcast_ether_addr(ibss_param->bssid))
8c8b65e3
VT
1631 memcpy(vif->req_bssid, ibss_param->bssid,
1632 sizeof(vif->req_bssid));
bdcd8170 1633
240d2799 1634 ath6kl_set_wpa_version(vif, 0);
bdcd8170 1635
240d2799 1636 status = ath6kl_set_auth_type(vif, NL80211_AUTHTYPE_OPEN_SYSTEM);
bdcd8170
KV
1637 if (status)
1638 return status;
1639
1640 if (ibss_param->privacy) {
240d2799
VT
1641 ath6kl_set_cipher(vif, WLAN_CIPHER_SUITE_WEP40, true);
1642 ath6kl_set_cipher(vif, WLAN_CIPHER_SUITE_WEP40, false);
bdcd8170 1643 } else {
240d2799
VT
1644 ath6kl_set_cipher(vif, 0, true);
1645 ath6kl_set_cipher(vif, 0, false);
bdcd8170
KV
1646 }
1647
f5938f24 1648 vif->nw_type = vif->next_mode;
bdcd8170
KV
1649
1650 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1651 "%s: connect called with authmode %d dot11 auth %d"
1652 " PW crypto %d PW crypto len %d GRP crypto %d"
1653 " GRP crypto len %d channel hint %u\n",
1654 __func__,
3450334f
VT
1655 vif->auth_mode, vif->dot11_auth_mode, vif->prwise_crypto,
1656 vif->prwise_crypto_len, vif->grp_crypto,
f74bac54 1657 vif->grp_crypto_len, vif->ch_hint);
bdcd8170 1658
334234b5 1659 status = ath6kl_wmi_connect_cmd(ar->wmi, vif->fw_vif_idx, vif->nw_type,
3450334f
VT
1660 vif->dot11_auth_mode, vif->auth_mode,
1661 vif->prwise_crypto,
1662 vif->prwise_crypto_len,
1663 vif->grp_crypto, vif->grp_crypto_len,
1664 vif->ssid_len, vif->ssid,
f74bac54 1665 vif->req_bssid, vif->ch_hint,
3ca9d1fc 1666 ar->connect_ctrl_flags, SUBTYPE_NONE);
59c98449 1667 set_bit(CONNECT_PEND, &vif->flags);
bdcd8170
KV
1668
1669 return 0;
1670}
1671
1672static int ath6kl_cfg80211_leave_ibss(struct wiphy *wiphy,
1673 struct net_device *dev)
1674{
3450334f 1675 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170 1676
990bd915 1677 if (!ath6kl_cfg80211_ready(vif))
bdcd8170
KV
1678 return -EIO;
1679
240d2799 1680 ath6kl_disconnect(vif);
3450334f
VT
1681 memset(vif->ssid, 0, sizeof(vif->ssid));
1682 vif->ssid_len = 0;
bdcd8170
KV
1683
1684 return 0;
1685}
1686
1687static const u32 cipher_suites[] = {
1688 WLAN_CIPHER_SUITE_WEP40,
1689 WLAN_CIPHER_SUITE_WEP104,
1690 WLAN_CIPHER_SUITE_TKIP,
1691 WLAN_CIPHER_SUITE_CCMP,
837cb97e 1692 CCKM_KRK_CIPHER_SUITE,
5e07021e 1693 WLAN_CIPHER_SUITE_SMS4,
bdcd8170
KV
1694};
1695
1696static bool is_rate_legacy(s32 rate)
1697{
1698 static const s32 legacy[] = { 1000, 2000, 5500, 11000,
1699 6000, 9000, 12000, 18000, 24000,
1700 36000, 48000, 54000
1701 };
1702 u8 i;
1703
1704 for (i = 0; i < ARRAY_SIZE(legacy); i++)
1705 if (rate == legacy[i])
1706 return true;
1707
1708 return false;
1709}
1710
1711static bool is_rate_ht20(s32 rate, u8 *mcs, bool *sgi)
1712{
1713 static const s32 ht20[] = { 6500, 13000, 19500, 26000, 39000,
1714 52000, 58500, 65000, 72200
1715 };
1716 u8 i;
1717
1718 for (i = 0; i < ARRAY_SIZE(ht20); i++) {
1719 if (rate == ht20[i]) {
1720 if (i == ARRAY_SIZE(ht20) - 1)
1721 /* last rate uses sgi */
1722 *sgi = true;
1723 else
1724 *sgi = false;
1725
1726 *mcs = i;
1727 return true;
1728 }
1729 }
1730 return false;
1731}
1732
1733static bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi)
1734{
1735 static const s32 ht40[] = { 13500, 27000, 40500, 54000,
1736 81000, 108000, 121500, 135000,
1737 150000
1738 };
1739 u8 i;
1740
1741 for (i = 0; i < ARRAY_SIZE(ht40); i++) {
1742 if (rate == ht40[i]) {
1743 if (i == ARRAY_SIZE(ht40) - 1)
1744 /* last rate uses sgi */
1745 *sgi = true;
1746 else
1747 *sgi = false;
1748
1749 *mcs = i;
1750 return true;
1751 }
1752 }
1753
1754 return false;
1755}
1756
1757static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
1758 u8 *mac, struct station_info *sinfo)
1759{
1760 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 1761 struct ath6kl_vif *vif = netdev_priv(dev);
bdcd8170
KV
1762 long left;
1763 bool sgi;
1764 s32 rate;
1765 int ret;
1766 u8 mcs;
1767
8c8b65e3 1768 if (memcmp(mac, vif->bssid, ETH_ALEN) != 0)
bdcd8170
KV
1769 return -ENOENT;
1770
1771 if (down_interruptible(&ar->sem))
1772 return -EBUSY;
1773
b95907a7 1774 set_bit(STATS_UPDATE_PEND, &vif->flags);
bdcd8170 1775
334234b5 1776 ret = ath6kl_wmi_get_stats_cmd(ar->wmi, vif->fw_vif_idx);
bdcd8170
KV
1777
1778 if (ret != 0) {
1779 up(&ar->sem);
1780 return -EIO;
1781 }
1782
1783 left = wait_event_interruptible_timeout(ar->event_wq,
1784 !test_bit(STATS_UPDATE_PEND,
b95907a7 1785 &vif->flags),
bdcd8170
KV
1786 WMI_TIMEOUT);
1787
1788 up(&ar->sem);
1789
1790 if (left == 0)
1791 return -ETIMEDOUT;
1792 else if (left < 0)
1793 return left;
1794
b95907a7
VT
1795 if (vif->target_stats.rx_byte) {
1796 sinfo->rx_bytes = vif->target_stats.rx_byte;
bdcd8170 1797 sinfo->filled |= STATION_INFO_RX_BYTES;
b95907a7 1798 sinfo->rx_packets = vif->target_stats.rx_pkt;
bdcd8170
KV
1799 sinfo->filled |= STATION_INFO_RX_PACKETS;
1800 }
1801
b95907a7
VT
1802 if (vif->target_stats.tx_byte) {
1803 sinfo->tx_bytes = vif->target_stats.tx_byte;
bdcd8170 1804 sinfo->filled |= STATION_INFO_TX_BYTES;
b95907a7 1805 sinfo->tx_packets = vif->target_stats.tx_pkt;
bdcd8170
KV
1806 sinfo->filled |= STATION_INFO_TX_PACKETS;
1807 }
1808
b95907a7 1809 sinfo->signal = vif->target_stats.cs_rssi;
bdcd8170
KV
1810 sinfo->filled |= STATION_INFO_SIGNAL;
1811
b95907a7 1812 rate = vif->target_stats.tx_ucast_rate;
bdcd8170
KV
1813
1814 if (is_rate_legacy(rate)) {
1815 sinfo->txrate.legacy = rate / 100;
1816 } else if (is_rate_ht20(rate, &mcs, &sgi)) {
1817 if (sgi) {
1818 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
1819 sinfo->txrate.mcs = mcs - 1;
1820 } else {
1821 sinfo->txrate.mcs = mcs;
1822 }
1823
1824 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
1825 } else if (is_rate_ht40(rate, &mcs, &sgi)) {
1826 if (sgi) {
1827 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
1828 sinfo->txrate.mcs = mcs - 1;
1829 } else {
1830 sinfo->txrate.mcs = mcs;
1831 }
1832
1833 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
1834 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
1835 } else {
9a730834
KV
1836 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1837 "invalid rate from stats: %d\n", rate);
1838 ath6kl_debug_war(ar, ATH6KL_WAR_INVALID_RATE);
bdcd8170
KV
1839 return 0;
1840 }
1841
1842 sinfo->filled |= STATION_INFO_TX_BITRATE;
1843
59c98449
VT
1844 if (test_bit(CONNECTED, &vif->flags) &&
1845 test_bit(DTIM_PERIOD_AVAIL, &vif->flags) &&
f5938f24 1846 vif->nw_type == INFRA_NETWORK) {
32c10874
JM
1847 sinfo->filled |= STATION_INFO_BSS_PARAM;
1848 sinfo->bss_param.flags = 0;
cf5333d7
VT
1849 sinfo->bss_param.dtim_period = vif->assoc_bss_dtim_period;
1850 sinfo->bss_param.beacon_interval = vif->assoc_bss_beacon_int;
32c10874
JM
1851 }
1852
bdcd8170
KV
1853 return 0;
1854}
1855
1856static int ath6kl_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1857 struct cfg80211_pmksa *pmksa)
1858{
1859 struct ath6kl *ar = ath6kl_priv(netdev);
334234b5
VT
1860 struct ath6kl_vif *vif = netdev_priv(netdev);
1861
1862 return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx, pmksa->bssid,
bdcd8170
KV
1863 pmksa->pmkid, true);
1864}
1865
1866static int ath6kl_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1867 struct cfg80211_pmksa *pmksa)
1868{
1869 struct ath6kl *ar = ath6kl_priv(netdev);
334234b5
VT
1870 struct ath6kl_vif *vif = netdev_priv(netdev);
1871
1872 return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx, pmksa->bssid,
bdcd8170
KV
1873 pmksa->pmkid, false);
1874}
1875
1876static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
1877{
1878 struct ath6kl *ar = ath6kl_priv(netdev);
59c98449
VT
1879 struct ath6kl_vif *vif = netdev_priv(netdev);
1880
1881 if (test_bit(CONNECTED, &vif->flags))
334234b5
VT
1882 return ath6kl_wmi_setpmkid_cmd(ar->wmi, vif->fw_vif_idx,
1883 vif->bssid, NULL, false);
bdcd8170
KV
1884 return 0;
1885}
1886
d91e8eee
RM
1887static int ath6kl_wow_usr(struct ath6kl *ar, struct ath6kl_vif *vif,
1888 struct cfg80211_wowlan *wow, u32 *filter)
6cb3c714 1889{
d91e8eee
RM
1890 int ret, pos;
1891 u8 mask[WOW_MASK_SIZE];
6cb3c714 1892 u16 i;
6cb3c714 1893
d91e8eee 1894 /* Configure the patterns that we received from the user. */
6cb3c714
RM
1895 for (i = 0; i < wow->n_patterns; i++) {
1896
1897 /*
1898 * Convert given nl80211 specific mask value to equivalent
1899 * driver specific mask value and send it to the chip along
1900 * with patterns. For example, If the mask value defined in
1901 * struct cfg80211_wowlan is 0xA (equivalent binary is 1010),
1902 * then equivalent driver specific mask value is
1903 * "0xFF 0x00 0xFF 0x00".
1904 */
1905 memset(&mask, 0, sizeof(mask));
1906 for (pos = 0; pos < wow->patterns[i].pattern_len; pos++) {
1907 if (wow->patterns[i].mask[pos / 8] & (0x1 << (pos % 8)))
1908 mask[pos] = 0xFF;
1909 }
1910 /*
1911 * Note: Pattern's offset is not passed as part of wowlan
1912 * parameter from CFG layer. So it's always passed as ZERO
1913 * to the firmware. It means, given WOW patterns are always
1914 * matched from the first byte of received pkt in the firmware.
1915 */
1916 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
d91e8eee
RM
1917 vif->fw_vif_idx, WOW_LIST_ID,
1918 wow->patterns[i].pattern_len,
1919 0 /* pattern offset */,
1920 wow->patterns[i].pattern, mask);
6cb3c714
RM
1921 if (ret)
1922 return ret;
1923 }
1924
d91e8eee
RM
1925 if (wow->disconnect)
1926 *filter |= WOW_FILTER_OPTION_NWK_DISASSOC;
1927
1928 if (wow->magic_pkt)
1929 *filter |= WOW_FILTER_OPTION_MAGIC_PACKET;
1930
1931 if (wow->gtk_rekey_failure)
1932 *filter |= WOW_FILTER_OPTION_GTK_ERROR;
1933
1934 if (wow->eap_identity_req)
1935 *filter |= WOW_FILTER_OPTION_EAP_REQ;
1936
1937 if (wow->four_way_handshake)
1938 *filter |= WOW_FILTER_OPTION_8021X_4WAYHS;
1939
1940 return 0;
1941}
1942
1943static int ath6kl_wow_ap(struct ath6kl *ar, struct ath6kl_vif *vif)
1944{
1945 static const u8 unicst_pattern[] = { 0x00, 0x00, 0x00,
1946 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1947 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1948 0x00, 0x08 };
1949 static const u8 unicst_mask[] = { 0x01, 0x00, 0x00,
1950 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1951 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1952 0x00, 0x7f };
1953 u8 unicst_offset = 0;
1954 static const u8 arp_pattern[] = { 0x08, 0x06 };
1955 static const u8 arp_mask[] = { 0xff, 0xff };
1956 u8 arp_offset = 20;
1957 static const u8 discvr_pattern[] = { 0xe0, 0x00, 0x00, 0xf8 };
1958 static const u8 discvr_mask[] = { 0xf0, 0x00, 0x00, 0xf8 };
1959 u8 discvr_offset = 38;
1960 static const u8 dhcp_pattern[] = { 0xff, 0xff, 0xff, 0xff,
1961 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1962 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
1963 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1964 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1965 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 /* port 67 */ };
1966 static const u8 dhcp_mask[] = { 0xff, 0xff, 0xff, 0xff,
1967 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1968 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
1969 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1970 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1971 0x00, 0x00, 0x00, 0x00, 0xff, 0xff /* port 67 */ };
1972 u8 dhcp_offset = 0;
1973 int ret;
1974
1975 /* Setup unicast IP, EAPOL-like and ARP pkt pattern */
1976 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1977 vif->fw_vif_idx, WOW_LIST_ID,
1978 sizeof(unicst_pattern), unicst_offset,
1979 unicst_pattern, unicst_mask);
1980 if (ret) {
1981 ath6kl_err("failed to add WOW unicast IP pattern\n");
1982 return ret;
1983 }
1984
1985 /* Setup all ARP pkt pattern */
1986 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
1987 vif->fw_vif_idx, WOW_LIST_ID,
1988 sizeof(arp_pattern), arp_offset,
1989 arp_pattern, arp_mask);
1990 if (ret) {
1991 ath6kl_err("failed to add WOW ARP pattern\n");
1992 return ret;
1993 }
1994
1995 /*
1996 * Setup multicast pattern for mDNS 224.0.0.251,
1997 * SSDP 239.255.255.250 and LLMNR 224.0.0.252
1998 */
1999 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
2000 vif->fw_vif_idx, WOW_LIST_ID,
2001 sizeof(discvr_pattern), discvr_offset,
2002 discvr_pattern, discvr_mask);
2003 if (ret) {
2004 ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR pattern\n");
2005 return ret;
2006 }
2007
2008 /* Setup all DHCP broadcast pkt pattern */
2009 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
2010 vif->fw_vif_idx, WOW_LIST_ID,
2011 sizeof(dhcp_pattern), dhcp_offset,
2012 dhcp_pattern, dhcp_mask);
2013 if (ret) {
2014 ath6kl_err("failed to add WOW DHCP broadcast pattern\n");
2015 return ret;
2016 }
2017
2018 return 0;
2019}
2020
2021static int ath6kl_wow_sta(struct ath6kl *ar, struct ath6kl_vif *vif)
2022{
2023 struct net_device *ndev = vif->ndev;
2024 static const u8 discvr_pattern[] = { 0xe0, 0x00, 0x00, 0xf8 };
2025 static const u8 discvr_mask[] = { 0xf0, 0x00, 0x00, 0xf8 };
2026 u8 discvr_offset = 38;
2027 u8 mac_mask[ETH_ALEN];
2028 int ret;
2029
2030 /* Setup unicast pkt pattern */
2031 memset(mac_mask, 0xff, ETH_ALEN);
2032 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
2033 vif->fw_vif_idx, WOW_LIST_ID,
2034 ETH_ALEN, 0, ndev->dev_addr,
2035 mac_mask);
2036 if (ret) {
2037 ath6kl_err("failed to add WOW unicast pattern\n");
2038 return ret;
2039 }
2040
2041 /*
2042 * Setup multicast pattern for mDNS 224.0.0.251,
2043 * SSDP 239.255.255.250 and LLMNR 224.0.0.252
2044 */
2045 if ((ndev->flags & IFF_ALLMULTI) ||
2046 (ndev->flags & IFF_MULTICAST && netdev_mc_count(ndev) > 0)) {
2047 ret = ath6kl_wmi_add_wow_pattern_cmd(ar->wmi,
2048 vif->fw_vif_idx, WOW_LIST_ID,
2049 sizeof(discvr_pattern), discvr_offset,
2050 discvr_pattern, discvr_mask);
2051 if (ret) {
cdeb8602 2052 ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR pattern\n");
d91e8eee
RM
2053 return ret;
2054 }
2055 }
2056
2057 return 0;
2058}
2059
055bde49
RM
2060static int is_hsleep_mode_procsed(struct ath6kl_vif *vif)
2061{
2062 return test_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags);
2063}
2064
2065static bool is_ctrl_ep_empty(struct ath6kl *ar)
2066{
2067 return !ar->tx_pending[ar->ctrl_ep];
2068}
2069
2070static int ath6kl_cfg80211_host_sleep(struct ath6kl *ar, struct ath6kl_vif *vif)
2071{
2072 int ret, left;
2073
2074 clear_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags);
2075
2076 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
2077 ATH6KL_HOST_MODE_ASLEEP);
2078 if (ret)
2079 return ret;
2080
2081 left = wait_event_interruptible_timeout(ar->event_wq,
2082 is_hsleep_mode_procsed(vif),
2083 WMI_TIMEOUT);
2084 if (left == 0) {
2085 ath6kl_warn("timeout, didn't get host sleep cmd processed event\n");
2086 ret = -ETIMEDOUT;
2087 } else if (left < 0) {
2088 ath6kl_warn("error while waiting for host sleep cmd processed event %d\n",
2089 left);
2090 ret = left;
2091 }
2092
2093 if (ar->tx_pending[ar->ctrl_ep]) {
2094 left = wait_event_interruptible_timeout(ar->event_wq,
2095 is_ctrl_ep_empty(ar),
2096 WMI_TIMEOUT);
2097 if (left == 0) {
2098 ath6kl_warn("clear wmi ctrl data timeout\n");
2099 ret = -ETIMEDOUT;
2100 } else if (left < 0) {
2101 ath6kl_warn("clear wmi ctrl data failed: %d\n", left);
2102 ret = left;
2103 }
2104 }
2105
2106 return ret;
2107}
2108
d91e8eee
RM
2109static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
2110{
2111 struct in_device *in_dev;
2112 struct in_ifaddr *ifa;
2113 struct ath6kl_vif *vif;
055bde49 2114 int ret;
d91e8eee 2115 u32 filter = 0;
ce0dc0cf 2116 u16 i, bmiss_time;
d91e8eee
RM
2117 u8 index = 0;
2118 __be32 ips[MAX_IP_ADDRS];
2119
77ed4e45
TP
2120 /* The FW currently can't support multi-vif WoW properly. */
2121 if (ar->num_vif > 1)
2122 return -EIO;
2123
d91e8eee
RM
2124 vif = ath6kl_vif_first(ar);
2125 if (!vif)
2126 return -EIO;
2127
2128 if (!ath6kl_cfg80211_ready(vif))
2129 return -EIO;
2130
2131 if (!test_bit(CONNECTED, &vif->flags))
3c411a43 2132 return -ENOTCONN;
d91e8eee
RM
2133
2134 if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
2135 return -EINVAL;
2136
6821d4f0
NG
2137 if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags) &&
2138 test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
2139 ar->fw_capabilities)) {
6251d801
NG
2140 ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
2141 vif->fw_vif_idx, false);
2142 if (ret)
2143 return ret;
2144 }
2145
d91e8eee
RM
2146 /* Clear existing WOW patterns */
2147 for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++)
2148 ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx,
2149 WOW_LIST_ID, i);
2150
2151 /*
2152 * Skip the default WOW pattern configuration
2153 * if the driver receives any WOW patterns from
2154 * the user.
2155 */
2156 if (wow)
2157 ret = ath6kl_wow_usr(ar, vif, wow, &filter);
2158 else if (vif->nw_type == AP_NETWORK)
2159 ret = ath6kl_wow_ap(ar, vif);
2160 else
2161 ret = ath6kl_wow_sta(ar, vif);
2162
2163 if (ret)
2164 return ret;
2165
390a8c8f
RM
2166 netif_stop_queue(vif->ndev);
2167
ce0dc0cf
RM
2168 if (vif->nw_type != AP_NETWORK) {
2169 ret = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
2170 ATH6KL_MAX_WOW_LISTEN_INTL,
2171 0);
2172 if (ret)
2173 return ret;
2174
2175 /* Set listen interval x 15 times as bmiss time */
2176 bmiss_time = ATH6KL_MAX_WOW_LISTEN_INTL * 15;
2177 if (bmiss_time > ATH6KL_MAX_BMISS_TIME)
2178 bmiss_time = ATH6KL_MAX_BMISS_TIME;
2179
2180 ret = ath6kl_wmi_bmisstime_cmd(ar->wmi, vif->fw_vif_idx,
2181 bmiss_time, 0);
2182 if (ret)
2183 return ret;
2184
2185 ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
2186 0xFFFF, 0, 0xFFFF, 0, 0, 0,
2187 0, 0, 0, 0);
2188 if (ret)
2189 return ret;
2190 }
2191
390a8c8f
RM
2192 ar->state = ATH6KL_STATE_SUSPENDING;
2193
c08631c6
RM
2194 /* Setup own IP addr for ARP agent. */
2195 in_dev = __in_dev_get_rtnl(vif->ndev);
2196 if (!in_dev)
2197 goto skip_arp;
2198
2199 ifa = in_dev->ifa_list;
2200 memset(&ips, 0, sizeof(ips));
2201
2202 /* Configure IP addr only if IP address count < MAX_IP_ADDRS */
2203 while (index < MAX_IP_ADDRS && ifa) {
2204 ips[index] = ifa->ifa_local;
2205 ifa = ifa->ifa_next;
2206 index++;
2207 }
2208
2209 if (ifa) {
2210 ath6kl_err("total IP addr count is exceeding fw limit\n");
2211 return -EINVAL;
2212 }
2213
2214 ret = ath6kl_wmi_set_ip_cmd(ar->wmi, vif->fw_vif_idx, ips[0], ips[1]);
2215 if (ret) {
2216 ath6kl_err("fail to setup ip for arp agent\n");
2217 return ret;
2218 }
2219
2220skip_arp:
6cb3c714
RM
2221 ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
2222 ATH6KL_WOW_MODE_ENABLE,
2223 filter,
2224 WOW_HOST_REQ_DELAY);
2225 if (ret)
2226 return ret;
2227
055bde49 2228 ret = ath6kl_cfg80211_host_sleep(ar, vif);
6cb3c714
RM
2229 if (ret)
2230 return ret;
2231
055bde49 2232 return 0;
6cb3c714
RM
2233}
2234
2235static int ath6kl_wow_resume(struct ath6kl *ar)
2236{
2237 struct ath6kl_vif *vif;
2238 int ret;
2239
2240 vif = ath6kl_vif_first(ar);
2241 if (!vif)
2242 return -EIO;
2243
390a8c8f
RM
2244 ar->state = ATH6KL_STATE_RESUMING;
2245
6cb3c714
RM
2246 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
2247 ATH6KL_HOST_MODE_AWAKE);
390a8c8f 2248 if (ret) {
cdeb8602
KV
2249 ath6kl_warn("Failed to configure host sleep mode for wow resume: %d\n",
2250 ret);
390a8c8f
RM
2251 ar->state = ATH6KL_STATE_WOW;
2252 return ret;
2253 }
2254
ce0dc0cf
RM
2255 if (vif->nw_type != AP_NETWORK) {
2256 ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
2257 0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
2258 if (ret)
2259 return ret;
2260
2261 ret = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
2262 vif->listen_intvl_t, 0);
2263 if (ret)
2264 return ret;
2265
2266 ret = ath6kl_wmi_bmisstime_cmd(ar->wmi, vif->fw_vif_idx,
2267 vif->bmiss_time_t, 0);
2268 if (ret)
2269 return ret;
2270 }
2271
390a8c8f
RM
2272 ar->state = ATH6KL_STATE_ON;
2273
6821d4f0
NG
2274 if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags) &&
2275 test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
2276 ar->fw_capabilities)) {
6251d801
NG
2277 ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
2278 vif->fw_vif_idx, true);
2279 if (ret)
2280 return ret;
2281 }
2282
390a8c8f
RM
2283 netif_wake_queue(vif->ndev);
2284
2285 return 0;
6cb3c714
RM
2286}
2287
40abc2de
RM
2288static int ath6kl_cfg80211_deepsleep_suspend(struct ath6kl *ar)
2289{
2290 struct ath6kl_vif *vif;
2291 int ret;
2292
2293 vif = ath6kl_vif_first(ar);
2294 if (!vif)
2295 return -EIO;
2296
48f27587
MJ
2297 if (!test_bit(WMI_READY, &ar->flag)) {
2298 ath6kl_err("deepsleep failed as wmi is not ready\n");
40abc2de 2299 return -EIO;
48f27587 2300 }
40abc2de
RM
2301
2302 ath6kl_cfg80211_stop_all(ar);
2303
2304 /* Save the current power mode before enabling power save */
2305 ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
2306
2307 ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER);
2308 if (ret)
2309 return ret;
2310
2311 /* Disable WOW mode */
2312 ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
2313 ATH6KL_WOW_MODE_DISABLE,
2314 0, 0);
2315 if (ret)
2316 return ret;
2317
2318 /* Flush all non control pkts in TX path */
2319 ath6kl_tx_data_cleanup(ar);
2320
2321 ret = ath6kl_cfg80211_host_sleep(ar, vif);
2322 if (ret)
2323 return ret;
2324
2325 return 0;
2326}
2327
2328static int ath6kl_cfg80211_deepsleep_resume(struct ath6kl *ar)
2329{
2330 struct ath6kl_vif *vif;
2331 int ret;
2332
2333 vif = ath6kl_vif_first(ar);
2334
2335 if (!vif)
2336 return -EIO;
2337
2338 if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) {
2339 ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0,
2340 ar->wmi->saved_pwr_mode);
2341 if (ret)
2342 return ret;
2343 }
2344
2345 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
2346 ATH6KL_HOST_MODE_AWAKE);
2347 if (ret)
2348 return ret;
2349
2350 ar->state = ATH6KL_STATE_ON;
2351
2352 /* Reset scan parameter to default values */
2353 ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
2354 0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
2355 if (ret)
2356 return ret;
2357
2358 return 0;
2359}
2360
52d81a68 2361int ath6kl_cfg80211_suspend(struct ath6kl *ar,
0f60e9f4
RM
2362 enum ath6kl_cfg_suspend_mode mode,
2363 struct cfg80211_wowlan *wow)
52d81a68 2364{
3d79499c 2365 struct ath6kl_vif *vif;
390a8c8f 2366 enum ath6kl_state prev_state;
52d81a68
KV
2367 int ret;
2368
52d81a68 2369 switch (mode) {
d7c44e0b
RM
2370 case ATH6KL_CFG_SUSPEND_WOW:
2371
2372 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "wow mode suspend\n");
2373
2374 /* Flush all non control pkts in TX path */
2375 ath6kl_tx_data_cleanup(ar);
2376
390a8c8f
RM
2377 prev_state = ar->state;
2378
d7c44e0b 2379 ret = ath6kl_wow_suspend(ar, wow);
390a8c8f
RM
2380 if (ret) {
2381 ar->state = prev_state;
d7c44e0b 2382 return ret;
390a8c8f 2383 }
1e9a905d 2384
d7c44e0b
RM
2385 ar->state = ATH6KL_STATE_WOW;
2386 break;
2387
52d81a68 2388 case ATH6KL_CFG_SUSPEND_DEEPSLEEP:
524441e3 2389
40abc2de 2390 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "deep sleep suspend\n");
52d81a68 2391
40abc2de 2392 ret = ath6kl_cfg80211_deepsleep_suspend(ar);
52d81a68 2393 if (ret) {
40abc2de
RM
2394 ath6kl_err("deepsleep suspend failed: %d\n", ret);
2395 return ret;
52d81a68
KV
2396 }
2397
76a9fbe2
KV
2398 ar->state = ATH6KL_STATE_DEEPSLEEP;
2399
52d81a68 2400 break;
b4b2a0b1
KV
2401
2402 case ATH6KL_CFG_SUSPEND_CUTPOWER:
524441e3 2403
7125f01d 2404 ath6kl_cfg80211_stop_all(ar);
524441e3 2405
b4b2a0b1
KV
2406 if (ar->state == ATH6KL_STATE_OFF) {
2407 ath6kl_dbg(ATH6KL_DBG_SUSPEND,
2408 "suspend hw off, no action for cutpower\n");
2409 break;
2410 }
2411
2412 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "suspend cutting power\n");
2413
2414 ret = ath6kl_init_hw_stop(ar);
2415 if (ret) {
2416 ath6kl_warn("failed to stop hw during suspend: %d\n",
2417 ret);
2418 }
2419
2420 ar->state = ATH6KL_STATE_CUTPOWER;
2421
2422 break;
2423
10509f90
KV
2424 case ATH6KL_CFG_SUSPEND_SCHED_SCAN:
2425 /*
2426 * Nothing needed for schedule scan, firmware is already in
2427 * wow mode and sleeping most of the time.
2428 */
2429 break;
2430
b4b2a0b1
KV
2431 default:
2432 break;
52d81a68
KV
2433 }
2434
3d79499c
VN
2435 list_for_each_entry(vif, &ar->vif_list, list)
2436 ath6kl_cfg80211_scan_complete_event(vif, true);
2437
52d81a68
KV
2438 return 0;
2439}
d6a434d6 2440EXPORT_SYMBOL(ath6kl_cfg80211_suspend);
52d81a68
KV
2441
2442int ath6kl_cfg80211_resume(struct ath6kl *ar)
2443{
76a9fbe2
KV
2444 int ret;
2445
2446 switch (ar->state) {
d7c44e0b
RM
2447 case ATH6KL_STATE_WOW:
2448 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "wow mode resume\n");
2449
2450 ret = ath6kl_wow_resume(ar);
2451 if (ret) {
2452 ath6kl_warn("wow mode resume failed: %d\n", ret);
2453 return ret;
2454 }
2455
d7c44e0b
RM
2456 break;
2457
76a9fbe2 2458 case ATH6KL_STATE_DEEPSLEEP:
40abc2de 2459 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "deep sleep resume\n");
76a9fbe2 2460
40abc2de
RM
2461 ret = ath6kl_cfg80211_deepsleep_resume(ar);
2462 if (ret) {
2463 ath6kl_warn("deep sleep resume failed: %d\n", ret);
2464 return ret;
2465 }
76a9fbe2
KV
2466 break;
2467
b4b2a0b1
KV
2468 case ATH6KL_STATE_CUTPOWER:
2469 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "resume restoring power\n");
2470
2471 ret = ath6kl_init_hw_start(ar);
2472 if (ret) {
2473 ath6kl_warn("Failed to boot hw in resume: %d\n", ret);
2474 return ret;
2475 }
d7c44e0b 2476 break;
b4b2a0b1 2477
10509f90
KV
2478 case ATH6KL_STATE_SCHED_SCAN:
2479 break;
2480
76a9fbe2
KV
2481 default:
2482 break;
52d81a68
KV
2483 }
2484
2485 return 0;
2486}
d6a434d6 2487EXPORT_SYMBOL(ath6kl_cfg80211_resume);
52d81a68 2488
abcb344b 2489#ifdef CONFIG_PM
52d81a68
KV
2490
2491/* hif layer decides what suspend mode to use */
2492static int __ath6kl_cfg80211_suspend(struct wiphy *wiphy,
abcb344b
KV
2493 struct cfg80211_wowlan *wow)
2494{
2495 struct ath6kl *ar = wiphy_priv(wiphy);
2496
0f60e9f4 2497 return ath6kl_hif_suspend(ar, wow);
abcb344b 2498}
aa6cffc1 2499
52d81a68 2500static int __ath6kl_cfg80211_resume(struct wiphy *wiphy)
aa6cffc1
CN
2501{
2502 struct ath6kl *ar = wiphy_priv(wiphy);
2503
2504 return ath6kl_hif_resume(ar);
2505}
a918fb3c
RM
2506
2507/*
2508 * FIXME: WOW suspend mode is selected if the host sdio controller supports
2509 * both sdio irq wake up and keep power. The target pulls sdio data line to
2510 * wake up the host when WOW pattern matches. This causes sdio irq handler
2511 * is being called in the host side which internally hits ath6kl's RX path.
2512 *
2513 * Since sdio interrupt is not disabled, RX path executes even before
2514 * the host executes the actual resume operation from PM module.
2515 *
2516 * In the current scenario, WOW resume should happen before start processing
2517 * any data from the target. So It's required to perform WOW resume in RX path.
2518 * Ideally we should perform WOW resume only in the actual platform
2519 * resume path. This area needs bit rework to avoid WOW resume in RX path.
2520 *
2521 * ath6kl_check_wow_status() is called from ath6kl_rx().
2522 */
2523void ath6kl_check_wow_status(struct ath6kl *ar)
2524{
390a8c8f
RM
2525 if (ar->state == ATH6KL_STATE_SUSPENDING)
2526 return;
2527
a918fb3c
RM
2528 if (ar->state == ATH6KL_STATE_WOW)
2529 ath6kl_cfg80211_resume(ar);
2530}
2531
2532#else
2533
2534void ath6kl_check_wow_status(struct ath6kl *ar)
2535{
2536}
abcb344b
KV
2537#endif
2538
df90b369
VT
2539static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band,
2540 bool ht_enable)
6a7c9bad 2541{
67b3f129 2542 struct ath6kl_htcap *htcap = &vif->htcap[band];
6a7c9bad 2543
df90b369
VT
2544 if (htcap->ht_enable == ht_enable)
2545 return 0;
6a7c9bad 2546
df90b369
VT
2547 if (ht_enable) {
2548 /* Set default ht capabilities */
2549 htcap->ht_enable = true;
2550 htcap->cap_info = (band == IEEE80211_BAND_2GHZ) ?
2551 ath6kl_g_htcap : ath6kl_a_htcap;
2552 htcap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K;
2553 } else /* Disable ht */
2554 memset(htcap, 0, sizeof(*htcap));
6a7c9bad 2555
df90b369
VT
2556 return ath6kl_wmi_set_htcap_cmd(vif->ar->wmi, vif->fw_vif_idx,
2557 band, htcap);
6a7c9bad
JM
2558}
2559
37a2f950
TP
2560static int ath6kl_restore_htcap(struct ath6kl_vif *vif)
2561{
2562 struct wiphy *wiphy = vif->ar->wiphy;
2563 int band, ret = 0;
2564
2565 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
2566 if (!wiphy->bands[band])
2567 continue;
2568
2569 ret = ath6kl_set_htcap(vif, band,
2570 wiphy->bands[band]->ht_cap.ht_supported);
2571 if (ret)
2572 return ret;
2573 }
2574
2575 return ret;
2576}
2577
8bdfbf40
JM
2578static bool ath6kl_is_p2p_ie(const u8 *pos)
2579{
2580 return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
2581 pos[2] == 0x50 && pos[3] == 0x6f &&
2582 pos[4] == 0x9a && pos[5] == 0x09;
2583}
2584
334234b5
VT
2585static int ath6kl_set_ap_probe_resp_ies(struct ath6kl_vif *vif,
2586 const u8 *ies, size_t ies_len)
8bdfbf40 2587{
334234b5 2588 struct ath6kl *ar = vif->ar;
8bdfbf40
JM
2589 const u8 *pos;
2590 u8 *buf = NULL;
2591 size_t len = 0;
2592 int ret;
2593
2594 /*
2595 * Filter out P2P IE(s) since they will be included depending on
2596 * the Probe Request frame in ath6kl_send_go_probe_resp().
2597 */
2598
2599 if (ies && ies_len) {
2600 buf = kmalloc(ies_len, GFP_KERNEL);
2601 if (buf == NULL)
2602 return -ENOMEM;
2603 pos = ies;
2604 while (pos + 1 < ies + ies_len) {
2605 if (pos + 2 + pos[1] > ies + ies_len)
2606 break;
2607 if (!ath6kl_is_p2p_ie(pos)) {
2608 memcpy(buf + len, pos, 2 + pos[1]);
2609 len += 2 + pos[1];
2610 }
2611 pos += 2 + pos[1];
2612 }
2613 }
2614
334234b5
VT
2615 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2616 WMI_FRAME_PROBE_RESP, buf, len);
8bdfbf40
JM
2617 kfree(buf);
2618 return ret;
2619}
2620
8860020e
JB
2621static int ath6kl_set_ies(struct ath6kl_vif *vif,
2622 struct cfg80211_beacon_data *info)
6a7c9bad 2623{
8860020e 2624 struct ath6kl *ar = vif->ar;
6a7c9bad 2625 int res;
6a7c9bad 2626
17a7b16d
AT
2627 /* this also clears IE in fw if it's not set */
2628 res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2629 WMI_FRAME_BEACON,
2630 info->beacon_ies,
2631 info->beacon_ies_len);
2632 if (res)
2633 return res;
2634
2635 /* this also clears IE in fw if it's not set */
2636 res = ath6kl_set_ap_probe_resp_ies(vif, info->proberesp_ies,
2637 info->proberesp_ies_len);
2638 if (res)
2639 return res;
2640
2641 /* this also clears IE in fw if it's not set */
2642 res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2643 WMI_FRAME_ASSOC_RESP,
2644 info->assocresp_ies,
2645 info->assocresp_ies_len);
2646 if (res)
2647 return res;
6a7c9bad 2648
8860020e
JB
2649 return 0;
2650}
2651
c422d52d
TP
2652void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable)
2653{
2654 int err;
2655
2656 if (WARN_ON(!test_bit(WMI_READY, &vif->ar->flag)))
2657 return;
2658
2659 if (vif->nw_type != INFRA_NETWORK)
2660 return;
2661
2662 if (!test_bit(ATH6KL_FW_CAPABILITY_BMISS_ENHANCE,
2663 vif->ar->fw_capabilities))
2664 return;
2665
2666 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s fw bmiss enhance\n",
2667 enable ? "enable" : "disable");
2668
2669 err = ath6kl_wmi_sta_bmiss_enhance_cmd(vif->ar->wmi,
2670 vif->fw_vif_idx, enable);
2671 if (err)
2672 ath6kl_err("failed to %s enhanced bmiss detection: %d\n",
2673 enable ? "enable" : "disable", err);
2674}
2675
d97c121b
VT
2676static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon,
2677 u8 *rsn_capab)
2678{
2679 const u8 *rsn_ie;
2680 size_t rsn_ie_len;
2681 u16 cnt;
2682
2683 if (!beacon->tail)
2684 return -EINVAL;
2685
2686 rsn_ie = cfg80211_find_ie(WLAN_EID_RSN, beacon->tail, beacon->tail_len);
2687 if (!rsn_ie)
2688 return -EINVAL;
2689
2690 rsn_ie_len = *(rsn_ie + 1);
2691 /* skip element id and length */
2692 rsn_ie += 2;
2693
9e8b16db
VT
2694 /* skip version */
2695 if (rsn_ie_len < 2)
d97c121b 2696 return -EINVAL;
9e8b16db
VT
2697 rsn_ie += 2;
2698 rsn_ie_len -= 2;
2699
2700 /* skip group cipher suite */
2701 if (rsn_ie_len < 4)
2702 return 0;
2703 rsn_ie += 4;
2704 rsn_ie_len -= 4;
d97c121b
VT
2705
2706 /* skip pairwise cipher suite */
2707 if (rsn_ie_len < 2)
9e8b16db 2708 return 0;
798985c6 2709 cnt = get_unaligned_le16(rsn_ie);
d97c121b
VT
2710 rsn_ie += (2 + cnt * 4);
2711 rsn_ie_len -= (2 + cnt * 4);
2712
2713 /* skip akm suite */
2714 if (rsn_ie_len < 2)
9e8b16db 2715 return 0;
798985c6 2716 cnt = get_unaligned_le16(rsn_ie);
d97c121b
VT
2717 rsn_ie += (2 + cnt * 4);
2718 rsn_ie_len -= (2 + cnt * 4);
2719
2720 if (rsn_ie_len < 2)
9e8b16db 2721 return 0;
d97c121b
VT
2722
2723 memcpy(rsn_capab, rsn_ie, 2);
2724
2725 return 0;
2726}
2727
8860020e
JB
2728static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
2729 struct cfg80211_ap_settings *info)
6a7c9bad
JM
2730{
2731 struct ath6kl *ar = ath6kl_priv(dev);
3450334f 2732 struct ath6kl_vif *vif = netdev_priv(dev);
6a7c9bad 2733 struct ieee80211_mgmt *mgmt;
67cd22e4 2734 bool hidden = false;
6a7c9bad
JM
2735 u8 *ies;
2736 int ies_len;
2737 struct wmi_connect_cmd p;
2738 int res;
be5abaaf 2739 int i, ret;
d97c121b 2740 u16 rsn_capab = 0;
6a7c9bad 2741
8860020e 2742 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s:\n", __func__);
6a7c9bad 2743
990bd915 2744 if (!ath6kl_cfg80211_ready(vif))
6a7c9bad
JM
2745 return -EIO;
2746
f5938f24 2747 if (vif->next_mode != AP_NETWORK)
6a7c9bad
JM
2748 return -EOPNOTSUPP;
2749
8860020e 2750 res = ath6kl_set_ies(vif, &info->beacon);
6a7c9bad 2751
9a5b1318
JM
2752 ar->ap_mode_bkey.valid = false;
2753
6a7c9bad
JM
2754 /* TODO:
2755 * info->interval
6a7c9bad
JM
2756 */
2757
d154f32e
EL
2758 ret = ath6kl_wmi_ap_set_dtim_cmd(ar->wmi, vif->fw_vif_idx,
2759 info->dtim_period);
2760
2761 /* ignore error, just print a warning and continue normally */
2762 if (ret)
2763 ath6kl_warn("Failed to set dtim_period in beacon: %d\n", ret);
2764
8860020e 2765 if (info->beacon.head == NULL)
6a7c9bad 2766 return -EINVAL;
8860020e 2767 mgmt = (struct ieee80211_mgmt *) info->beacon.head;
6a7c9bad 2768 ies = mgmt->u.beacon.variable;
8860020e 2769 if (ies > info->beacon.head + info->beacon.head_len)
6a7c9bad 2770 return -EINVAL;
8860020e 2771 ies_len = info->beacon.head + info->beacon.head_len - ies;
6a7c9bad
JM
2772
2773 if (info->ssid == NULL)
2774 return -EINVAL;
3450334f
VT
2775 memcpy(vif->ssid, info->ssid, info->ssid_len);
2776 vif->ssid_len = info->ssid_len;
6a7c9bad 2777 if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
67cd22e4
TP
2778 hidden = true;
2779
2780 res = ath6kl_wmi_ap_hidden_ssid(ar->wmi, vif->fw_vif_idx, hidden);
2781 if (res)
2782 return res;
6a7c9bad 2783
be5abaaf
VT
2784 ret = ath6kl_set_auth_type(vif, info->auth_type);
2785 if (ret)
2786 return ret;
6a7c9bad
JM
2787
2788 memset(&p, 0, sizeof(p));
2789
2790 for (i = 0; i < info->crypto.n_akm_suites; i++) {
2791 switch (info->crypto.akm_suites[i]) {
2792 case WLAN_AKM_SUITE_8021X:
2793 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1)
2794 p.auth_mode |= WPA_AUTH;
2795 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2)
2796 p.auth_mode |= WPA2_AUTH;
2797 break;
2798 case WLAN_AKM_SUITE_PSK:
2799 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1)
2800 p.auth_mode |= WPA_PSK_AUTH;
2801 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2)
2802 p.auth_mode |= WPA2_PSK_AUTH;
2803 break;
2804 }
2805 }
2806 if (p.auth_mode == 0)
2807 p.auth_mode = NONE_AUTH;
3450334f 2808 vif->auth_mode = p.auth_mode;
6a7c9bad
JM
2809
2810 for (i = 0; i < info->crypto.n_ciphers_pairwise; i++) {
2811 switch (info->crypto.ciphers_pairwise[i]) {
2812 case WLAN_CIPHER_SUITE_WEP40:
2813 case WLAN_CIPHER_SUITE_WEP104:
2814 p.prwise_crypto_type |= WEP_CRYPT;
2815 break;
2816 case WLAN_CIPHER_SUITE_TKIP:
2817 p.prwise_crypto_type |= TKIP_CRYPT;
2818 break;
2819 case WLAN_CIPHER_SUITE_CCMP:
2820 p.prwise_crypto_type |= AES_CRYPT;
2821 break;
b8214df1
DS
2822 case WLAN_CIPHER_SUITE_SMS4:
2823 p.prwise_crypto_type |= WAPI_CRYPT;
2824 break;
6a7c9bad
JM
2825 }
2826 }
229ed6b5 2827 if (p.prwise_crypto_type == 0) {
6a7c9bad 2828 p.prwise_crypto_type = NONE_CRYPT;
240d2799 2829 ath6kl_set_cipher(vif, 0, true);
229ed6b5 2830 } else if (info->crypto.n_ciphers_pairwise == 1)
240d2799 2831 ath6kl_set_cipher(vif, info->crypto.ciphers_pairwise[0], true);
6a7c9bad
JM
2832
2833 switch (info->crypto.cipher_group) {
2834 case WLAN_CIPHER_SUITE_WEP40:
2835 case WLAN_CIPHER_SUITE_WEP104:
2836 p.grp_crypto_type = WEP_CRYPT;
2837 break;
2838 case WLAN_CIPHER_SUITE_TKIP:
2839 p.grp_crypto_type = TKIP_CRYPT;
2840 break;
2841 case WLAN_CIPHER_SUITE_CCMP:
2842 p.grp_crypto_type = AES_CRYPT;
2843 break;
b8214df1
DS
2844 case WLAN_CIPHER_SUITE_SMS4:
2845 p.grp_crypto_type = WAPI_CRYPT;
2846 break;
6a7c9bad
JM
2847 default:
2848 p.grp_crypto_type = NONE_CRYPT;
2849 break;
2850 }
240d2799 2851 ath6kl_set_cipher(vif, info->crypto.cipher_group, false);
6a7c9bad
JM
2852
2853 p.nw_type = AP_NETWORK;
f5938f24 2854 vif->nw_type = vif->next_mode;
6a7c9bad 2855
3450334f
VT
2856 p.ssid_len = vif->ssid_len;
2857 memcpy(p.ssid, vif->ssid, vif->ssid_len);
2858 p.dot11_auth_mode = vif->dot11_auth_mode;
aa430da4 2859 p.ch = cpu_to_le16(info->channel->center_freq);
6a7c9bad 2860
c1762a3f
TP
2861 /* Enable uAPSD support by default */
2862 res = ath6kl_wmi_ap_set_apsd(ar->wmi, vif->fw_vif_idx, true);
2863 if (res < 0)
2864 return res;
2865
3ca9d1fc
AT
2866 if (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) {
2867 p.nw_subtype = SUBTYPE_P2PGO;
2868 } else {
2869 /*
2870 * Due to firmware limitation, it is not possible to
2871 * do P2P mgmt operations in AP mode
2872 */
2873 p.nw_subtype = SUBTYPE_NONE;
2874 }
2875
03bdeb0d
VT
2876 if (info->inactivity_timeout) {
2877 res = ath6kl_wmi_set_inact_period(ar->wmi, vif->fw_vif_idx,
2878 info->inactivity_timeout);
2879 if (res < 0)
2880 return res;
2881 }
2882
aa430da4
JB
2883 if (ath6kl_set_htcap(vif, info->channel->band,
2884 info->channel_type != NL80211_CHAN_NO_HT))
df90b369
VT
2885 return -EIO;
2886
d97c121b
VT
2887 /*
2888 * Get the PTKSA replay counter in the RSN IE. Supplicant
2889 * will use the RSN IE in M3 message and firmware has to
2890 * advertise the same in beacon/probe response. Send
2891 * the complete RSN IE capability field to firmware
2892 */
2893 if (!ath6kl_get_rsn_capab(&info->beacon, (u8 *) &rsn_capab) &&
2894 test_bit(ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE,
2895 ar->fw_capabilities)) {
2896 res = ath6kl_wmi_set_ie_cmd(ar->wmi, vif->fw_vif_idx,
2897 WLAN_EID_RSN, WMI_RSN_IE_CAPB,
2898 (const u8 *) &rsn_capab,
2899 sizeof(rsn_capab));
2900 if (res < 0)
2901 return res;
2902 }
2903
c4f7863e 2904 memcpy(&vif->profile, &p, sizeof(p));
334234b5 2905 res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p);
9a5b1318
JM
2906 if (res < 0)
2907 return res;
2908
2909 return 0;
6a7c9bad
JM
2910}
2911
8860020e
JB
2912static int ath6kl_change_beacon(struct wiphy *wiphy, struct net_device *dev,
2913 struct cfg80211_beacon_data *beacon)
6a7c9bad 2914{
8860020e 2915 struct ath6kl_vif *vif = netdev_priv(dev);
6a7c9bad 2916
8860020e
JB
2917 if (!ath6kl_cfg80211_ready(vif))
2918 return -EIO;
2919
2920 if (vif->next_mode != AP_NETWORK)
2921 return -EOPNOTSUPP;
2922
2923 return ath6kl_set_ies(vif, beacon);
6a7c9bad
JM
2924}
2925
8860020e 2926static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev)
6a7c9bad
JM
2927{
2928 struct ath6kl *ar = ath6kl_priv(dev);
59c98449 2929 struct ath6kl_vif *vif = netdev_priv(dev);
6a7c9bad 2930
f5938f24 2931 if (vif->nw_type != AP_NETWORK)
6a7c9bad 2932 return -EOPNOTSUPP;
59c98449 2933 if (!test_bit(CONNECTED, &vif->flags))
6a7c9bad
JM
2934 return -ENOTCONN;
2935
334234b5 2936 ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
59c98449 2937 clear_bit(CONNECTED, &vif->flags);
6a7c9bad 2938
df90b369 2939 /* Restore ht setting in firmware */
37a2f950 2940 return ath6kl_restore_htcap(vif);
6a7c9bad
JM
2941}
2942
33e5308d
JM
2943static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
2944
2945static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev,
2946 u8 *mac)
2947{
2948 struct ath6kl *ar = ath6kl_priv(dev);
2949 struct ath6kl_vif *vif = netdev_priv(dev);
2950 const u8 *addr = mac ? mac : bcast_addr;
2951
2952 return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx, WMI_AP_DEAUTH,
2953 addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
2954}
2955
23875136
JM
2956static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
2957 u8 *mac, struct station_parameters *params)
2958{
2959 struct ath6kl *ar = ath6kl_priv(dev);
f5938f24 2960 struct ath6kl_vif *vif = netdev_priv(dev);
23875136 2961
f5938f24 2962 if (vif->nw_type != AP_NETWORK)
23875136
JM
2963 return -EOPNOTSUPP;
2964
2965 /* Use this only for authorizing/unauthorizing a station */
2966 if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
2967 return -EOPNOTSUPP;
2968
2969 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
334234b5
VT
2970 return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx,
2971 WMI_AP_MLME_AUTHORIZE, mac, 0);
2972 return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx,
2973 WMI_AP_MLME_UNAUTHORIZE, mac, 0);
23875136
JM
2974}
2975
63fa1e0c 2976static int ath6kl_remain_on_channel(struct wiphy *wiphy,
71bbc994 2977 struct wireless_dev *wdev,
63fa1e0c
JM
2978 struct ieee80211_channel *chan,
2979 enum nl80211_channel_type channel_type,
2980 unsigned int duration,
2981 u64 *cookie)
2982{
71bbc994
JB
2983 struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
2984 struct ath6kl *ar = ath6kl_priv(vif->ndev);
1052261e 2985 u32 id;
63fa1e0c
JM
2986
2987 /* TODO: if already pending or ongoing remain-on-channel,
2988 * return -EBUSY */
1052261e
JM
2989 id = ++vif->last_roc_id;
2990 if (id == 0) {
2991 /* Do not use 0 as the cookie value */
2992 id = ++vif->last_roc_id;
2993 }
2994 *cookie = id;
63fa1e0c 2995
334234b5
VT
2996 return ath6kl_wmi_remain_on_chnl_cmd(ar->wmi, vif->fw_vif_idx,
2997 chan->center_freq, duration);
63fa1e0c
JM
2998}
2999
3000static int ath6kl_cancel_remain_on_channel(struct wiphy *wiphy,
71bbc994 3001 struct wireless_dev *wdev,
63fa1e0c
JM
3002 u64 cookie)
3003{
71bbc994
JB
3004 struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
3005 struct ath6kl *ar = ath6kl_priv(vif->ndev);
63fa1e0c 3006
1052261e 3007 if (cookie != vif->last_roc_id)
63fa1e0c 3008 return -ENOENT;
1052261e 3009 vif->last_cancel_roc_id = cookie;
63fa1e0c 3010
334234b5 3011 return ath6kl_wmi_cancel_remain_on_chnl_cmd(ar->wmi, vif->fw_vif_idx);
63fa1e0c
JM
3012}
3013
334234b5
VT
3014static int ath6kl_send_go_probe_resp(struct ath6kl_vif *vif,
3015 const u8 *buf, size_t len,
3016 unsigned int freq)
8bdfbf40 3017{
334234b5 3018 struct ath6kl *ar = vif->ar;
8bdfbf40
JM
3019 const u8 *pos;
3020 u8 *p2p;
3021 int p2p_len;
3022 int ret;
3023 const struct ieee80211_mgmt *mgmt;
3024
3025 mgmt = (const struct ieee80211_mgmt *) buf;
3026
3027 /* Include P2P IE(s) from the frame generated in user space. */
3028
3029 p2p = kmalloc(len, GFP_KERNEL);
3030 if (p2p == NULL)
3031 return -ENOMEM;
3032 p2p_len = 0;
3033
3034 pos = mgmt->u.probe_resp.variable;
3035 while (pos + 1 < buf + len) {
3036 if (pos + 2 + pos[1] > buf + len)
3037 break;
3038 if (ath6kl_is_p2p_ie(pos)) {
3039 memcpy(p2p + p2p_len, pos, 2 + pos[1]);
3040 p2p_len += 2 + pos[1];
3041 }
3042 pos += 2 + pos[1];
3043 }
3044
334234b5
VT
3045 ret = ath6kl_wmi_send_probe_response_cmd(ar->wmi, vif->fw_vif_idx, freq,
3046 mgmt->da, p2p, p2p_len);
8bdfbf40
JM
3047 kfree(p2p);
3048 return ret;
3049}
3050
d0ff7383
NG
3051static bool ath6kl_mgmt_powersave_ap(struct ath6kl_vif *vif,
3052 u32 id,
3053 u32 freq,
3054 u32 wait,
3055 const u8 *buf,
3056 size_t len,
3057 bool *more_data,
3058 bool no_cck)
3059{
3060 struct ieee80211_mgmt *mgmt;
3061 struct ath6kl_sta *conn;
3062 bool is_psq_empty = false;
3063 struct ath6kl_mgmt_buff *mgmt_buf;
3064 size_t mgmt_buf_size;
3065 struct ath6kl *ar = vif->ar;
3066
3067 mgmt = (struct ieee80211_mgmt *) buf;
3068 if (is_multicast_ether_addr(mgmt->da))
3069 return false;
3070
3071 conn = ath6kl_find_sta(vif, mgmt->da);
3072 if (!conn)
3073 return false;
3074
3075 if (conn->sta_flags & STA_PS_SLEEP) {
3076 if (!(conn->sta_flags & STA_PS_POLLED)) {
3077 /* Queue the frames if the STA is sleeping */
3078 mgmt_buf_size = len + sizeof(struct ath6kl_mgmt_buff);
3079 mgmt_buf = kmalloc(mgmt_buf_size, GFP_KERNEL);
3080 if (!mgmt_buf)
3081 return false;
3082
3083 INIT_LIST_HEAD(&mgmt_buf->list);
3084 mgmt_buf->id = id;
3085 mgmt_buf->freq = freq;
3086 mgmt_buf->wait = wait;
3087 mgmt_buf->len = len;
3088 mgmt_buf->no_cck = no_cck;
3089 memcpy(mgmt_buf->buf, buf, len);
3090 spin_lock_bh(&conn->psq_lock);
3091 is_psq_empty = skb_queue_empty(&conn->psq) &&
3092 (conn->mgmt_psq_len == 0);
3093 list_add_tail(&mgmt_buf->list, &conn->mgmt_psq);
3094 conn->mgmt_psq_len++;
3095 spin_unlock_bh(&conn->psq_lock);
3096
3097 /*
3098 * If this is the first pkt getting queued
3099 * for this STA, update the PVB for this
3100 * STA.
3101 */
3102 if (is_psq_empty)
3103 ath6kl_wmi_set_pvb_cmd(ar->wmi, vif->fw_vif_idx,
3104 conn->aid, 1);
3105 return true;
3106 }
3107
3108 /*
3109 * This tx is because of a PsPoll.
3110 * Determine if MoreData bit has to be set.
3111 */
3112 spin_lock_bh(&conn->psq_lock);
3113 if (!skb_queue_empty(&conn->psq) || (conn->mgmt_psq_len != 0))
3114 *more_data = true;
3115 spin_unlock_bh(&conn->psq_lock);
3116 }
3117
3118 return false;
3119}
3120
c86e4f44
AT
3121/* Check if SSID length is greater than DIRECT- */
3122static bool ath6kl_is_p2p_go_ssid(const u8 *buf, size_t len)
3123{
3124 const struct ieee80211_mgmt *mgmt;
3125 mgmt = (const struct ieee80211_mgmt *) buf;
3126
3127 /* variable[1] contains the SSID tag length */
3128 if (buf + len >= &mgmt->u.probe_resp.variable[1] &&
3129 (mgmt->u.probe_resp.variable[1] > P2P_WILDCARD_SSID_LEN)) {
3130 return true;
3131 }
3132
3133 return false;
3134}
3135
71bbc994 3136static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
8a6c8060
JM
3137 struct ieee80211_channel *chan, bool offchan,
3138 enum nl80211_channel_type channel_type,
3139 bool channel_type_valid, unsigned int wait,
e247bd90
JB
3140 const u8 *buf, size_t len, bool no_cck,
3141 bool dont_wait_for_ack, u64 *cookie)
8a6c8060 3142{
71bbc994
JB
3143 struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
3144 struct ath6kl *ar = ath6kl_priv(vif->ndev);
8a6c8060 3145 u32 id;
8bdfbf40 3146 const struct ieee80211_mgmt *mgmt;
d0ff7383 3147 bool more_data, queued;
8bdfbf40
JM
3148
3149 mgmt = (const struct ieee80211_mgmt *) buf;
c86e4f44
AT
3150 if (vif->nw_type == AP_NETWORK && test_bit(CONNECTED, &vif->flags) &&
3151 ieee80211_is_probe_resp(mgmt->frame_control) &&
3152 ath6kl_is_p2p_go_ssid(buf, len)) {
8bdfbf40 3153 /*
c86e4f44 3154 * Send Probe Response frame in GO mode using a separate WMI
8bdfbf40
JM
3155 * command to allow the target to fill in the generic IEs.
3156 */
3157 *cookie = 0; /* TX status not supported */
334234b5 3158 return ath6kl_send_go_probe_resp(vif, buf, len,
8bdfbf40
JM
3159 chan->center_freq);
3160 }
8a6c8060 3161
cf5333d7 3162 id = vif->send_action_id++;
8a6c8060
JM
3163 if (id == 0) {
3164 /*
3165 * 0 is a reserved value in the WMI command and shall not be
3166 * used for the command.
3167 */
cf5333d7 3168 id = vif->send_action_id++;
8a6c8060
JM
3169 }
3170
3171 *cookie = id;
3ca9d1fc 3172
d0ff7383
NG
3173 /* AP mode Power saving processing */
3174 if (vif->nw_type == AP_NETWORK) {
3175 queued = ath6kl_mgmt_powersave_ap(vif,
3176 id, chan->center_freq,
3177 wait, buf,
3178 len, &more_data, no_cck);
3179 if (queued)
3180 return 0;
3ca9d1fc 3181 }
d0ff7383
NG
3182
3183 return ath6kl_wmi_send_mgmt_cmd(ar->wmi, vif->fw_vif_idx, id,
3184 chan->center_freq, wait,
3185 buf, len, no_cck);
8a6c8060
JM
3186}
3187
ae32c30a 3188static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
71bbc994 3189 struct wireless_dev *wdev,
ae32c30a
JM
3190 u16 frame_type, bool reg)
3191{
71bbc994 3192 struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
ae32c30a
JM
3193
3194 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: frame_type=0x%x reg=%d\n",
3195 __func__, frame_type, reg);
3196 if (frame_type == IEEE80211_STYPE_PROBE_REQ) {
3197 /*
3198 * Note: This notification callback is not allowed to sleep, so
3199 * we cannot send WMI_PROBE_REQ_REPORT_CMD here. Instead, we
3200 * hardcode target to report Probe Request frames all the time.
3201 */
cf5333d7 3202 vif->probe_req_report = reg;
ae32c30a
JM
3203 }
3204}
3205
10509f90
KV
3206static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
3207 struct net_device *dev,
3208 struct cfg80211_sched_scan_request *request)
3209{
3210 struct ath6kl *ar = ath6kl_priv(dev);
3211 struct ath6kl_vif *vif = netdev_priv(dev);
3212 u16 interval;
3213 int ret;
10509f90
KV
3214
3215 if (ar->state != ATH6KL_STATE_ON)
3216 return -EIO;
3217
3218 if (vif->sme_state != SME_DISCONNECTED)
3219 return -EBUSY;
3220
77ed4e45
TP
3221 /* The FW currently can't support multi-vif WoW properly. */
3222 if (ar->num_vif > 1)
3223 return -EIO;
3224
b4d13d3b
KV
3225 ath6kl_cfg80211_scan_complete_event(vif, true);
3226
3b8ffc6a 3227 ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
dd45b759
NS
3228 request->n_ssids,
3229 request->match_sets,
3230 request->n_match_sets);
3b8ffc6a
JM
3231 if (ret < 0)
3232 return ret;
10509f90 3233
dd45b759
NS
3234 if (!request->n_match_sets) {
3235 ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
3236 ALL_BSS_FILTER, 0);
3237 if (ret < 0)
3238 return ret;
3239 } else {
3240 ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
3241 MATCHED_SSID_FILTER, 0);
3242 if (ret < 0)
3243 return ret;
3244 }
3245
10509f90
KV
3246 /* fw uses seconds, also make sure that it's >0 */
3247 interval = max_t(u16, 1, request->interval / 1000);
3248
3249 ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
3250 interval, interval,
d472b5e4 3251 vif->bg_scan_period, 0, 0, 0, 3, 0, 0, 0);
10509f90 3252
10509f90
KV
3253 ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
3254 ATH6KL_WOW_MODE_ENABLE,
3255 WOW_FILTER_SSID,
3256 WOW_HOST_REQ_DELAY);
3257 if (ret) {
3258 ath6kl_warn("Failed to enable wow with ssid filter: %d\n", ret);
3259 return ret;
3260 }
3261
3262 /* this also clears IE in fw if it's not set */
3263 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
3264 WMI_FRAME_PROBE_REQ,
3265 request->ie, request->ie_len);
3266 if (ret) {
f1ff32e8 3267 ath6kl_warn("Failed to set probe request IE for scheduled scan: %d\n",
10509f90
KV
3268 ret);
3269 return ret;
3270 }
3271
3272 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
3273 ATH6KL_HOST_MODE_ASLEEP);
3274 if (ret) {
3275 ath6kl_warn("Failed to enable host sleep mode for sched scan: %d\n",
3276 ret);
3277 return ret;
3278 }
3279
3280 ar->state = ATH6KL_STATE_SCHED_SCAN;
3281
3282 return ret;
3283}
3284
3285static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy,
3286 struct net_device *dev)
3287{
3288 struct ath6kl_vif *vif = netdev_priv(dev);
3289 bool stopped;
3290
3291 stopped = __ath6kl_cfg80211_sscan_stop(vif);
3292
3293 if (!stopped)
3294 return -EIO;
3295
3296 return 0;
3297}
3298
06e360ac
BS
3299static int ath6kl_cfg80211_set_bitrate(struct wiphy *wiphy,
3300 struct net_device *dev,
3301 const u8 *addr,
3302 const struct cfg80211_bitrate_mask *mask)
3303{
3304 struct ath6kl *ar = ath6kl_priv(dev);
3305 struct ath6kl_vif *vif = netdev_priv(dev);
3306
3307 return ath6kl_wmi_set_bitrate_mask(ar->wmi, vif->fw_vif_idx,
3308 mask);
3309}
3310
f80574ae
JM
3311static const struct ieee80211_txrx_stypes
3312ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
3313 [NL80211_IFTYPE_STATION] = {
3314 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
3315 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
3316 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
3317 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
3318 },
ba1f6fe3
JM
3319 [NL80211_IFTYPE_AP] = {
3320 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
3321 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
3322 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
3323 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
3324 },
f80574ae
JM
3325 [NL80211_IFTYPE_P2P_CLIENT] = {
3326 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
3327 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
3328 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
3329 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
3330 },
3331 [NL80211_IFTYPE_P2P_GO] = {
3332 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
3333 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
3334 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
3335 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
3336 },
3337};
3338
bdcd8170 3339static struct cfg80211_ops ath6kl_cfg80211_ops = {
55055976
VT
3340 .add_virtual_intf = ath6kl_cfg80211_add_iface,
3341 .del_virtual_intf = ath6kl_cfg80211_del_iface,
bdcd8170
KV
3342 .change_virtual_intf = ath6kl_cfg80211_change_iface,
3343 .scan = ath6kl_cfg80211_scan,
3344 .connect = ath6kl_cfg80211_connect,
3345 .disconnect = ath6kl_cfg80211_disconnect,
3346 .add_key = ath6kl_cfg80211_add_key,
3347 .get_key = ath6kl_cfg80211_get_key,
3348 .del_key = ath6kl_cfg80211_del_key,
3349 .set_default_key = ath6kl_cfg80211_set_default_key,
3350 .set_wiphy_params = ath6kl_cfg80211_set_wiphy_params,
3351 .set_tx_power = ath6kl_cfg80211_set_txpower,
3352 .get_tx_power = ath6kl_cfg80211_get_txpower,
3353 .set_power_mgmt = ath6kl_cfg80211_set_power_mgmt,
3354 .join_ibss = ath6kl_cfg80211_join_ibss,
3355 .leave_ibss = ath6kl_cfg80211_leave_ibss,
3356 .get_station = ath6kl_get_station,
3357 .set_pmksa = ath6kl_set_pmksa,
3358 .del_pmksa = ath6kl_del_pmksa,
3359 .flush_pmksa = ath6kl_flush_pmksa,
003353b0 3360 CFG80211_TESTMODE_CMD(ath6kl_tm_cmd)
abcb344b 3361#ifdef CONFIG_PM
52d81a68
KV
3362 .suspend = __ath6kl_cfg80211_suspend,
3363 .resume = __ath6kl_cfg80211_resume,
abcb344b 3364#endif
8860020e
JB
3365 .start_ap = ath6kl_start_ap,
3366 .change_beacon = ath6kl_change_beacon,
3367 .stop_ap = ath6kl_stop_ap,
33e5308d 3368 .del_station = ath6kl_del_station,
23875136 3369 .change_station = ath6kl_change_station,
63fa1e0c
JM
3370 .remain_on_channel = ath6kl_remain_on_channel,
3371 .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel,
8a6c8060 3372 .mgmt_tx = ath6kl_mgmt_tx,
ae32c30a 3373 .mgmt_frame_register = ath6kl_mgmt_frame_register,
10509f90
KV
3374 .sched_scan_start = ath6kl_cfg80211_sscan_start,
3375 .sched_scan_stop = ath6kl_cfg80211_sscan_stop,
06e360ac 3376 .set_bitrate_mask = ath6kl_cfg80211_set_bitrate,
bdcd8170
KV
3377};
3378
7125f01d 3379void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
ec4b7f60 3380{
10509f90
KV
3381 ath6kl_cfg80211_sscan_disable(vif);
3382
ec4b7f60 3383 switch (vif->sme_state) {
c97a31b0
KV
3384 case SME_DISCONNECTED:
3385 break;
ec4b7f60
KV
3386 case SME_CONNECTING:
3387 cfg80211_connect_result(vif->ndev, vif->bssid, NULL, 0,
3388 NULL, 0,
3389 WLAN_STATUS_UNSPECIFIED_FAILURE,
3390 GFP_KERNEL);
3391 break;
3392 case SME_CONNECTED:
ec4b7f60
KV
3393 cfg80211_disconnected(vif->ndev, 0, NULL, 0, GFP_KERNEL);
3394 break;
3395 }
3396
3397 if (test_bit(CONNECTED, &vif->flags) ||
3398 test_bit(CONNECT_PEND, &vif->flags))
7125f01d 3399 ath6kl_wmi_disconnect_cmd(vif->ar->wmi, vif->fw_vif_idx);
ec4b7f60
KV
3400
3401 vif->sme_state = SME_DISCONNECTED;
1f405255
KV
3402 clear_bit(CONNECTED, &vif->flags);
3403 clear_bit(CONNECT_PEND, &vif->flags);
ec4b7f60
KV
3404
3405 /* disable scanning */
7125f01d
KV
3406 if (ath6kl_wmi_scanparams_cmd(vif->ar->wmi, vif->fw_vif_idx, 0xFFFF,
3407 0, 0, 0, 0, 0, 0, 0, 0, 0) != 0)
3408 ath6kl_warn("failed to disable scan during stop\n");
ec4b7f60
KV
3409
3410 ath6kl_cfg80211_scan_complete_event(vif, true);
3411}
3412
7125f01d
KV
3413void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
3414{
3415 struct ath6kl_vif *vif;
3416
3417 vif = ath6kl_vif_first(ar);
3418 if (!vif) {
3419 /* save the current power mode before enabling power save */
3420 ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
3421
3422 if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0)
cdeb8602 3423 ath6kl_warn("ath6kl_deep_sleep_enable: wmi_powermode_cmd failed\n");
7125f01d
KV
3424 return;
3425 }
3426
3427 /*
3428 * FIXME: we should take ar->list_lock to protect changes in the
3429 * vif_list, but that's not trivial to do as ath6kl_cfg80211_stop()
3430 * sleeps.
3431 */
3432 list_for_each_entry(vif, &ar->vif_list, list)
3433 ath6kl_cfg80211_stop(vif);
3434}
3435
c25889e8 3436static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif)
bdcd8170 3437{
7baef812 3438 vif->aggr_cntxt = aggr_init(vif);
2132c69c 3439 if (!vif->aggr_cntxt) {
8dafb70e
VT
3440 ath6kl_err("failed to initialize aggr\n");
3441 return -ENOMEM;
3442 }
3443
de3ad713 3444 setup_timer(&vif->disconnect_timer, disconnect_timer_handler,
108438bc 3445 (unsigned long) vif->ndev);
10509f90
KV
3446 setup_timer(&vif->sched_scan_timer, ath6kl_wmi_sscan_timer,
3447 (unsigned long) vif);
3448
de3ad713 3449 set_bit(WMM_ENABLED, &vif->flags);
478ac027 3450 spin_lock_init(&vif->if_lock);
bdcd8170 3451
80abaf9b
VT
3452 INIT_LIST_HEAD(&vif->mc_filter);
3453
8dafb70e
VT
3454 return 0;
3455}
3456
c25889e8 3457void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif)
8dafb70e 3458{
55055976 3459 struct ath6kl *ar = vif->ar;
80abaf9b 3460 struct ath6kl_mc_filter *mc_filter, *tmp;
55055976 3461
2132c69c 3462 aggr_module_destroy(vif->aggr_cntxt);
8dafb70e 3463
55055976
VT
3464 ar->avail_idx_map |= BIT(vif->fw_vif_idx);
3465
3466 if (vif->nw_type == ADHOC_NETWORK)
3467 ar->ibss_if_active = false;
3468
80abaf9b
VT
3469 list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) {
3470 list_del(&mc_filter->list);
3471 kfree(mc_filter);
3472 }
3473
27929723 3474 unregister_netdevice(vif->ndev);
55055976
VT
3475
3476 ar->num_vif--;
8dafb70e
VT
3477}
3478
552bff0c 3479struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name,
84efbb84
JB
3480 enum nl80211_iftype type,
3481 u8 fw_vif_idx, u8 nw_type)
8dafb70e
VT
3482{
3483 struct net_device *ndev;
108438bc 3484 struct ath6kl_vif *vif;
8dafb70e 3485
55055976 3486 ndev = alloc_netdev(sizeof(*vif), name, ether_setup);
8dafb70e
VT
3487 if (!ndev)
3488 return NULL;
3489
108438bc
VT
3490 vif = netdev_priv(ndev);
3491 ndev->ieee80211_ptr = &vif->wdev;
3492 vif->wdev.wiphy = ar->wiphy;
3493 vif->ar = ar;
108438bc
VT
3494 vif->ndev = ndev;
3495 SET_NETDEV_DEV(ndev, wiphy_dev(vif->wdev.wiphy));
3496 vif->wdev.netdev = ndev;
3497 vif->wdev.iftype = type;
334234b5 3498 vif->fw_vif_idx = fw_vif_idx;
d0d670ab
KV
3499 vif->nw_type = nw_type;
3500 vif->next_mode = nw_type;
8f46fccd 3501 vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;
ce0dc0cf 3502 vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME;
eb38987e 3503 vif->bg_scan_period = 0;
67b3f129
KR
3504 vif->htcap[IEEE80211_BAND_2GHZ].ht_enable = true;
3505 vif->htcap[IEEE80211_BAND_5GHZ].ht_enable = true;
8dafb70e 3506
55055976
VT
3507 memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
3508 if (fw_vif_idx != 0)
3509 ndev->dev_addr[0] = (ndev->dev_addr[0] ^ (1 << fw_vif_idx)) |
3510 0x2;
3511
8dafb70e
VT
3512 init_netdev(ndev);
3513
e29f25f5 3514 ath6kl_init_control_info(vif);
8dafb70e 3515
c25889e8 3516 if (ath6kl_cfg80211_vif_init(vif))
8dafb70e
VT
3517 goto err;
3518
27929723 3519 if (register_netdevice(ndev))
8dafb70e
VT
3520 goto err;
3521
55055976 3522 ar->avail_idx_map &= ~BIT(fw_vif_idx);
14ee6f6b 3523 vif->sme_state = SME_DISCONNECTED;
59c98449 3524 set_bit(WLAN_ENABLED, &vif->flags);
8dafb70e 3525 ar->wlan_pwr_state = WLAN_POWER_STATE_ON;
59c98449 3526 set_bit(NETDEV_REGISTERED, &vif->flags);
8dafb70e 3527
55055976
VT
3528 if (type == NL80211_IFTYPE_ADHOC)
3529 ar->ibss_if_active = true;
3530
11f6e40d 3531 spin_lock_bh(&ar->list_lock);
990bd915 3532 list_add_tail(&vif->list, &ar->vif_list);
11f6e40d 3533 spin_unlock_bh(&ar->list_lock);
990bd915 3534
84efbb84 3535 return &vif->wdev;
8dafb70e
VT
3536
3537err:
27929723
VT
3538 aggr_module_destroy(vif->aggr_cntxt);
3539 free_netdev(ndev);
8dafb70e
VT
3540 return NULL;
3541}
3542
46d33a21
KV
3543int ath6kl_cfg80211_init(struct ath6kl *ar)
3544{
3545 struct wiphy *wiphy = ar->wiphy;
d92917e4 3546 bool band_2gig = false, band_5gig = false, ht = false;
46d33a21
KV
3547 int ret;
3548
3549 wiphy->mgmt_stypes = ath6kl_mgmt_stypes;
3550
3551 wiphy->max_remain_on_channel_duration = 5000;
3552
3553 /* set device pointer for wiphy */
3554 set_wiphy_dev(wiphy, ar->dev);
3555
3556 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
3557 BIT(NL80211_IFTYPE_ADHOC) |
3558 BIT(NL80211_IFTYPE_AP);
3559 if (ar->p2p) {
3560 wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_GO) |
3561 BIT(NL80211_IFTYPE_P2P_CLIENT);
3562 }
3563
3564 /* max num of ssids that can be probed during scanning */
8ab5415d 3565 wiphy->max_scan_ssids = MAX_PROBED_SSIDS;
dd45b759
NS
3566
3567 /* max num of ssids that can be matched after scan */
3568 if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST,
3569 ar->fw_capabilities))
3570 wiphy->max_match_sets = MAX_PROBED_SSIDS;
3571
46d33a21 3572 wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
d92917e4
TP
3573 switch (ar->hw.cap) {
3574 case WMI_11AN_CAP:
3575 ht = true;
3576 case WMI_11A_CAP:
3577 band_5gig = true;
3578 break;
3579 case WMI_11GN_CAP:
3580 ht = true;
3581 case WMI_11G_CAP:
3582 band_2gig = true;
3583 break;
3584 case WMI_11AGN_CAP:
3585 ht = true;
3586 case WMI_11AG_CAP:
3587 band_2gig = true;
3588 band_5gig = true;
3589 break;
3590 default:
3591 ath6kl_err("invalid phy capability!\n");
3592 return -EINVAL;
3593 }
3594
7fd1ce7e
VT
3595 /*
3596 * Even if the fw has HT support, advertise HT cap only when
3597 * the firmware has support to override RSN capability, otherwise
3598 * 4-way handshake would fail.
3599 */
3600 if (!(ht &&
3601 test_bit(ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE,
3602 ar->fw_capabilities))) {
d92917e4
TP
3603 ath6kl_band_2ghz.ht_cap.cap = 0;
3604 ath6kl_band_2ghz.ht_cap.ht_supported = false;
3605 ath6kl_band_5ghz.ht_cap.cap = 0;
3606 ath6kl_band_5ghz.ht_cap.ht_supported = false;
3607 }
06e360ac
BS
3608
3609 if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES) {
3610 ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
3611 ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
3612 ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
3613 ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff;
3614 } else {
3615 ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
3616 ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
3617 }
3618
d92917e4
TP
3619 if (band_2gig)
3620 wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
3621 if (band_5gig)
3622 wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz;
3623
46d33a21
KV
3624 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
3625
3626 wiphy->cipher_suites = cipher_suites;
3627 wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
3628
dfb89c56 3629#ifdef CONFIG_PM
46d33a21
KV
3630 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
3631 WIPHY_WOWLAN_DISCONNECT |
3632 WIPHY_WOWLAN_GTK_REKEY_FAILURE |
3633 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
3634 WIPHY_WOWLAN_EAP_IDENTITY_REQ |
3635 WIPHY_WOWLAN_4WAY_HANDSHAKE;
3636 wiphy->wowlan.n_patterns = WOW_MAX_FILTERS_PER_LIST;
3637 wiphy->wowlan.pattern_min_len = 1;
3638 wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE;
dfb89c56 3639#endif
46d33a21 3640
8ab5415d 3641 wiphy->max_sched_scan_ssids = MAX_PROBED_SSIDS;
46d33a21 3642
f2afdac7
VT
3643 ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
3644 WIPHY_FLAG_HAVE_AP_SME |
3645 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
3646 WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
3647
3648 if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities))
3649 ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
3650
03bdeb0d
VT
3651 if (test_bit(ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT,
3652 ar->fw_capabilities))
b292219f 3653 ar->wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
03bdeb0d 3654
f2afdac7
VT
3655 ar->wiphy->probe_resp_offload =
3656 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
3657 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
a432e7cc 3658 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
f2afdac7 3659
46d33a21
KV
3660 ret = wiphy_register(wiphy);
3661 if (ret < 0) {
3662 ath6kl_err("couldn't register wiphy device\n");
3663 return ret;
3664 }
3665
e5348a1e
VT
3666 ar->wiphy_registered = true;
3667
46d33a21
KV
3668 return 0;
3669}
3670
3671void ath6kl_cfg80211_cleanup(struct ath6kl *ar)
8dafb70e 3672{
be98e3a4 3673 wiphy_unregister(ar->wiphy);
e5348a1e
VT
3674
3675 ar->wiphy_registered = false;
45eaa78f 3676}
46d33a21 3677
45eaa78f
KV
3678struct ath6kl *ath6kl_cfg80211_create(void)
3679{
3680 struct ath6kl *ar;
3681 struct wiphy *wiphy;
3682
3683 /* create a new wiphy for use with cfg80211 */
3684 wiphy = wiphy_new(&ath6kl_cfg80211_ops, sizeof(struct ath6kl));
3685
3686 if (!wiphy) {
3687 ath6kl_err("couldn't allocate wiphy device\n");
3688 return NULL;
3689 }
3690
3691 ar = wiphy_priv(wiphy);
3692 ar->wiphy = wiphy;
3693
3694 return ar;
3695}
3696
3697/* Note: ar variable must not be accessed after calling this! */
3698void ath6kl_cfg80211_destroy(struct ath6kl *ar)
3699{
1d2a4456
VT
3700 int i;
3701
3702 for (i = 0; i < AP_MAX_NUM_STA; i++)
3703 kfree(ar->sta_list[i].aggr_conn);
3704
be98e3a4 3705 wiphy_free(ar->wiphy);
bdcd8170 3706}
45eaa78f 3707
This page took 0.42393 seconds and 5 git commands to generate.