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