ath6kl: Add debugfs control for keepalive and disconnection timeout
[linux-2.6-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
17#include "core.h"
18#include "cfg80211.h"
19#include "debug.h"
abcb344b 20#include "hif-ops.h"
003353b0 21#include "testmode.h"
bdcd8170 22
6bbc7c35
JM
23static unsigned int ath6kl_p2p;
24
25module_param(ath6kl_p2p, uint, 0644);
26
bdcd8170
KV
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
124static int ath6kl_set_wpa_version(struct ath6kl *ar,
125 enum nl80211_wpa_versions wpa_version)
126{
127 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: %u\n", __func__, wpa_version);
128
129 if (!wpa_version) {
130 ar->auth_mode = NONE_AUTH;
131 } else if (wpa_version & NL80211_WPA_VERSION_2) {
132 ar->auth_mode = WPA2_AUTH;
133 } else if (wpa_version & NL80211_WPA_VERSION_1) {
134 ar->auth_mode = WPA_AUTH;
135 } else {
136 ath6kl_err("%s: %u not supported\n", __func__, wpa_version);
137 return -ENOTSUPP;
138 }
139
140 return 0;
141}
142
143static int ath6kl_set_auth_type(struct ath6kl *ar,
144 enum nl80211_auth_type auth_type)
145{
146
147 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: 0x%x\n", __func__, auth_type);
148
149 switch (auth_type) {
150 case NL80211_AUTHTYPE_OPEN_SYSTEM:
151 ar->dot11_auth_mode = OPEN_AUTH;
152 break;
153 case NL80211_AUTHTYPE_SHARED_KEY:
154 ar->dot11_auth_mode = SHARED_AUTH;
155 break;
156 case NL80211_AUTHTYPE_NETWORK_EAP:
157 ar->dot11_auth_mode = LEAP_AUTH;
158 break;
159
160 case NL80211_AUTHTYPE_AUTOMATIC:
ac59a2b2 161 ar->dot11_auth_mode = OPEN_AUTH | SHARED_AUTH;
bdcd8170
KV
162 break;
163
164 default:
165 ath6kl_err("%s: 0x%x not spported\n", __func__, auth_type);
166 return -ENOTSUPP;
167 }
168
169 return 0;
170}
171
172static int ath6kl_set_cipher(struct ath6kl *ar, u32 cipher, bool ucast)
173{
174 u8 *ar_cipher = ucast ? &ar->prwise_crypto : &ar->grp_crypto;
38acde3c
EL
175 u8 *ar_cipher_len = ucast ? &ar->prwise_crypto_len :
176 &ar->grp_crypto_len;
bdcd8170
KV
177
178 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: cipher 0x%x, ucast %u\n",
179 __func__, cipher, ucast);
180
181 switch (cipher) {
182 case 0:
183 /* our own hack to use value 0 as no crypto used */
184 *ar_cipher = NONE_CRYPT;
185 *ar_cipher_len = 0;
186 break;
187 case WLAN_CIPHER_SUITE_WEP40:
188 *ar_cipher = WEP_CRYPT;
189 *ar_cipher_len = 5;
190 break;
191 case WLAN_CIPHER_SUITE_WEP104:
192 *ar_cipher = WEP_CRYPT;
193 *ar_cipher_len = 13;
194 break;
195 case WLAN_CIPHER_SUITE_TKIP:
196 *ar_cipher = TKIP_CRYPT;
197 *ar_cipher_len = 0;
198 break;
199 case WLAN_CIPHER_SUITE_CCMP:
200 *ar_cipher = AES_CRYPT;
201 *ar_cipher_len = 0;
202 break;
203 default:
204 ath6kl_err("cipher 0x%x not supported\n", cipher);
205 return -ENOTSUPP;
206 }
207
208 return 0;
209}
210
211static void ath6kl_set_key_mgmt(struct ath6kl *ar, u32 key_mgmt)
212{
213 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: 0x%x\n", __func__, key_mgmt);
214
215 if (key_mgmt == WLAN_AKM_SUITE_PSK) {
216 if (ar->auth_mode == WPA_AUTH)
217 ar->auth_mode = WPA_PSK_AUTH;
218 else if (ar->auth_mode == WPA2_AUTH)
219 ar->auth_mode = WPA2_PSK_AUTH;
220 } else if (key_mgmt != WLAN_AKM_SUITE_8021X) {
221 ar->auth_mode = NONE_AUTH;
222 }
223}
224
225static bool ath6kl_cfg80211_ready(struct ath6kl *ar)
226{
227 if (!test_bit(WMI_READY, &ar->flag)) {
228 ath6kl_err("wmi is not ready\n");
229 return false;
230 }
231
575b5f34 232 if (!test_bit(WLAN_ENABLED, &ar->flag)) {
bdcd8170
KV
233 ath6kl_err("wlan disabled\n");
234 return false;
235 }
236
237 return true;
238}
239
6981ffdc
KF
240static bool ath6kl_is_wpa_ie(const u8 *pos)
241{
242 return pos[0] == WLAN_EID_WPA && pos[1] >= 4 &&
243 pos[2] == 0x00 && pos[3] == 0x50 &&
244 pos[4] == 0xf2 && pos[5] == 0x01;
245}
246
247static bool ath6kl_is_rsn_ie(const u8 *pos)
248{
249 return pos[0] == WLAN_EID_RSN;
250}
251
252static int ath6kl_set_assoc_req_ies(struct ath6kl *ar, const u8 *ies,
253 size_t ies_len)
254{
255 const u8 *pos;
256 u8 *buf = NULL;
257 size_t len = 0;
258 int ret;
259
260 /*
261 * Filter out RSN/WPA IE(s)
262 */
263
264 if (ies && ies_len) {
265 buf = kmalloc(ies_len, GFP_KERNEL);
266 if (buf == NULL)
267 return -ENOMEM;
268 pos = ies;
269
270 while (pos + 1 < ies + ies_len) {
271 if (pos + 2 + pos[1] > ies + ies_len)
272 break;
273 if (!(ath6kl_is_wpa_ie(pos) || ath6kl_is_rsn_ie(pos))) {
274 memcpy(buf + len, pos, 2 + pos[1]);
275 len += 2 + pos[1];
276 }
277 pos += 2 + pos[1];
278 }
279 }
280
281 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_ASSOC_REQ,
282 buf, len);
283 kfree(buf);
284 return ret;
285}
286
bdcd8170
KV
287static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
288 struct cfg80211_connect_params *sme)
289{
290 struct ath6kl *ar = ath6kl_priv(dev);
291 int status;
292
293 ar->sme_state = SME_CONNECTING;
294
295 if (!ath6kl_cfg80211_ready(ar))
296 return -EIO;
297
298 if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
299 ath6kl_err("destroy in progress\n");
300 return -EBUSY;
301 }
302
303 if (test_bit(SKIP_SCAN, &ar->flag) &&
304 ((sme->channel && sme->channel->center_freq == 0) ||
305 (sme->bssid && is_zero_ether_addr(sme->bssid)))) {
306 ath6kl_err("SkipScan: channel or bssid invalid\n");
307 return -EINVAL;
308 }
309
310 if (down_interruptible(&ar->sem)) {
311 ath6kl_err("busy, couldn't get access\n");
312 return -ERESTARTSYS;
313 }
314
315 if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
316 ath6kl_err("busy, destroy in progress\n");
317 up(&ar->sem);
318 return -EBUSY;
319 }
320
321 if (ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)]) {
322 /*
323 * sleep until the command queue drains
324 */
325 wait_event_interruptible_timeout(ar->event_wq,
326 ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)] == 0,
327 WMI_TIMEOUT);
328 if (signal_pending(current)) {
329 ath6kl_err("cmd queue drain timeout\n");
330 up(&ar->sem);
331 return -EINTR;
332 }
333 }
334
6981ffdc
KF
335 if (sme->ie && (sme->ie_len > 0)) {
336 status = ath6kl_set_assoc_req_ies(ar, sme->ie, sme->ie_len);
337 if (status)
338 return status;
339 }
340
bdcd8170
KV
341 if (test_bit(CONNECTED, &ar->flag) &&
342 ar->ssid_len == sme->ssid_len &&
343 !memcmp(ar->ssid, sme->ssid, ar->ssid_len)) {
344 ar->reconnect_flag = true;
345 status = ath6kl_wmi_reconnect_cmd(ar->wmi, ar->req_bssid,
346 ar->ch_hint);
347
348 up(&ar->sem);
349 if (status) {
350 ath6kl_err("wmi_reconnect_cmd failed\n");
351 return -EIO;
352 }
353 return 0;
354 } else if (ar->ssid_len == sme->ssid_len &&
355 !memcmp(ar->ssid, sme->ssid, ar->ssid_len)) {
356 ath6kl_disconnect(ar);
357 }
358
359 memset(ar->ssid, 0, sizeof(ar->ssid));
360 ar->ssid_len = sme->ssid_len;
361 memcpy(ar->ssid, sme->ssid, sme->ssid_len);
362
363 if (sme->channel)
364 ar->ch_hint = sme->channel->center_freq;
365
366 memset(ar->req_bssid, 0, sizeof(ar->req_bssid));
367 if (sme->bssid && !is_broadcast_ether_addr(sme->bssid))
368 memcpy(ar->req_bssid, sme->bssid, sizeof(ar->req_bssid));
369
370 ath6kl_set_wpa_version(ar, sme->crypto.wpa_versions);
371
372 status = ath6kl_set_auth_type(ar, sme->auth_type);
373 if (status) {
374 up(&ar->sem);
375 return status;
376 }
377
378 if (sme->crypto.n_ciphers_pairwise)
379 ath6kl_set_cipher(ar, sme->crypto.ciphers_pairwise[0], true);
380 else
381 ath6kl_set_cipher(ar, 0, true);
382
383 ath6kl_set_cipher(ar, sme->crypto.cipher_group, false);
384
385 if (sme->crypto.n_akm_suites)
386 ath6kl_set_key_mgmt(ar, sme->crypto.akm_suites[0]);
387
388 if ((sme->key_len) &&
389 (ar->auth_mode == NONE_AUTH) && (ar->prwise_crypto == WEP_CRYPT)) {
390 struct ath6kl_key *key = NULL;
391
392 if (sme->key_idx < WMI_MIN_KEY_INDEX ||
393 sme->key_idx > WMI_MAX_KEY_INDEX) {
394 ath6kl_err("key index %d out of bounds\n",
395 sme->key_idx);
396 up(&ar->sem);
397 return -ENOENT;
398 }
399
400 key = &ar->keys[sme->key_idx];
401 key->key_len = sme->key_len;
402 memcpy(key->key, sme->key, key->key_len);
403 key->cipher = ar->prwise_crypto;
404 ar->def_txkey_index = sme->key_idx;
405
406 ath6kl_wmi_addkey_cmd(ar->wmi, sme->key_idx,
407 ar->prwise_crypto,
408 GROUP_USAGE | TX_USAGE,
409 key->key_len,
410 NULL,
411 key->key, KEY_OP_INIT_VAL, NULL,
412 NO_SYNC_WMIFLAG);
413 }
414
415 if (!ar->usr_bss_filter) {
551185ca 416 clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag);
bdcd8170
KV
417 if (ath6kl_wmi_bssfilter_cmd(ar->wmi, ALL_BSS_FILTER, 0) != 0) {
418 ath6kl_err("couldn't set bss filtering\n");
419 up(&ar->sem);
420 return -EIO;
421 }
422 }
423
424 ar->nw_type = ar->next_mode;
425
426 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
427 "%s: connect called with authmode %d dot11 auth %d"
428 " PW crypto %d PW crypto len %d GRP crypto %d"
429 " GRP crypto len %d channel hint %u\n",
430 __func__,
431 ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto,
432 ar->prwise_crypto_len, ar->grp_crypto,
38acde3c 433 ar->grp_crypto_len, ar->ch_hint);
bdcd8170
KV
434
435 ar->reconnect_flag = 0;
436 status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type,
437 ar->dot11_auth_mode, ar->auth_mode,
438 ar->prwise_crypto,
439 ar->prwise_crypto_len,
38acde3c 440 ar->grp_crypto, ar->grp_crypto_len,
bdcd8170
KV
441 ar->ssid_len, ar->ssid,
442 ar->req_bssid, ar->ch_hint,
443 ar->connect_ctrl_flags);
444
445 up(&ar->sem);
446
447 if (status == -EINVAL) {
448 memset(ar->ssid, 0, sizeof(ar->ssid));
449 ar->ssid_len = 0;
450 ath6kl_err("invalid request\n");
451 return -ENOENT;
452 } else if (status) {
453 ath6kl_err("ath6kl_wmi_connect_cmd failed\n");
454 return -EIO;
455 }
456
457 if ((!(ar->connect_ctrl_flags & CONNECT_DO_WPA_OFFLOAD)) &&
458 ((ar->auth_mode == WPA_PSK_AUTH)
459 || (ar->auth_mode == WPA2_PSK_AUTH))) {
460 mod_timer(&ar->disconnect_timer,
461 jiffies + msecs_to_jiffies(DISCON_TIMER_INTVAL));
462 }
463
464 ar->connect_ctrl_flags &= ~CONNECT_DO_WPA_OFFLOAD;
465 set_bit(CONNECT_PEND, &ar->flag);
466
467 return 0;
468}
469
01cac476
JM
470static int ath6kl_add_bss_if_needed(struct ath6kl *ar, const u8 *bssid,
471 struct ieee80211_channel *chan,
472 const u8 *beacon_ie, size_t beacon_ie_len)
473{
474 struct cfg80211_bss *bss;
475 u8 *ie;
476
477 bss = cfg80211_get_bss(ar->wdev->wiphy, chan, bssid,
478 ar->ssid, ar->ssid_len, WLAN_CAPABILITY_ESS,
479 WLAN_CAPABILITY_ESS);
480 if (bss == NULL) {
481 /*
482 * Since cfg80211 may not yet know about the BSS,
483 * generate a partial entry until the first BSS info
484 * event becomes available.
485 *
486 * Prepend SSID element since it is not included in the Beacon
487 * IEs from the target.
488 */
489 ie = kmalloc(2 + ar->ssid_len + beacon_ie_len, GFP_KERNEL);
490 if (ie == NULL)
491 return -ENOMEM;
492 ie[0] = WLAN_EID_SSID;
493 ie[1] = ar->ssid_len;
494 memcpy(ie + 2, ar->ssid, ar->ssid_len);
495 memcpy(ie + 2 + ar->ssid_len, beacon_ie, beacon_ie_len);
496 bss = cfg80211_inform_bss(ar->wdev->wiphy, chan,
497 bssid, 0, WLAN_CAPABILITY_ESS, 100,
498 ie, 2 + ar->ssid_len + beacon_ie_len,
499 0, GFP_KERNEL);
500 if (bss)
501 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added dummy bss for "
502 "%pM prior to indicating connect/roamed "
503 "event\n", bssid);
504 kfree(ie);
505 } else
506 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss "
507 "entry\n");
508
509 if (bss == NULL)
510 return -ENOMEM;
511
512 cfg80211_put_bss(bss);
513
514 return 0;
515}
516
bdcd8170
KV
517void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel,
518 u8 *bssid, u16 listen_intvl,
519 u16 beacon_intvl,
520 enum network_type nw_type,
521 u8 beacon_ie_len, u8 assoc_req_len,
522 u8 assoc_resp_len, u8 *assoc_info)
523{
01cac476 524 struct ieee80211_channel *chan;
bdcd8170
KV
525
526 /* capinfo + listen interval */
527 u8 assoc_req_ie_offset = sizeof(u16) + sizeof(u16);
528
529 /* capinfo + status code + associd */
530 u8 assoc_resp_ie_offset = sizeof(u16) + sizeof(u16) + sizeof(u16);
531
532 u8 *assoc_req_ie = assoc_info + beacon_ie_len + assoc_req_ie_offset;
533 u8 *assoc_resp_ie = assoc_info + beacon_ie_len + assoc_req_len +
534 assoc_resp_ie_offset;
535
536 assoc_req_len -= assoc_req_ie_offset;
537 assoc_resp_len -= assoc_resp_ie_offset;
538
32c10874
JM
539 /*
540 * Store Beacon interval here; DTIM period will be available only once
541 * a Beacon frame from the AP is seen.
542 */
543 ar->assoc_bss_beacon_int = beacon_intvl;
544 clear_bit(DTIM_PERIOD_AVAIL, &ar->flag);
545
bdcd8170
KV
546 if (nw_type & ADHOC_NETWORK) {
547 if (ar->wdev->iftype != NL80211_IFTYPE_ADHOC) {
548 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
549 "%s: ath6k not in ibss mode\n", __func__);
550 return;
551 }
552 }
553
554 if (nw_type & INFRA_NETWORK) {
6b5e5d25
JM
555 if (ar->wdev->iftype != NL80211_IFTYPE_STATION &&
556 ar->wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) {
bdcd8170
KV
557 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
558 "%s: ath6k not in station mode\n", __func__);
559 return;
560 }
561 }
562
01cac476 563 chan = ieee80211_get_channel(ar->wdev->wiphy, (int) channel);
bdcd8170 564
bdcd8170 565
01cac476
JM
566 if (nw_type & ADHOC_NETWORK) {
567 cfg80211_ibss_joined(ar->net_dev, bssid, GFP_KERNEL);
bdcd8170
KV
568 return;
569 }
570
01cac476
JM
571 if (ath6kl_add_bss_if_needed(ar, bssid, chan, assoc_info,
572 beacon_ie_len) < 0) {
573 ath6kl_err("could not add cfg80211 bss entry for "
574 "connect/roamed notification\n");
bdcd8170
KV
575 return;
576 }
577
9aa60357 578 if (ar->sme_state == SME_CONNECTING) {
bdcd8170 579 /* inform connect result to cfg80211 */
9aa60357 580 ar->sme_state = SME_CONNECTED;
bdcd8170
KV
581 cfg80211_connect_result(ar->net_dev, bssid,
582 assoc_req_ie, assoc_req_len,
583 assoc_resp_ie, assoc_resp_len,
584 WLAN_STATUS_SUCCESS, GFP_KERNEL);
9aa60357 585 } else if (ar->sme_state == SME_CONNECTED) {
bdcd8170 586 /* inform roam event to cfg80211 */
01cac476 587 cfg80211_roamed(ar->net_dev, chan, bssid,
bdcd8170
KV
588 assoc_req_ie, assoc_req_len,
589 assoc_resp_ie, assoc_resp_len, GFP_KERNEL);
590 }
591}
592
593static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy,
594 struct net_device *dev, u16 reason_code)
595{
596 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(dev);
597
598 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: reason=%u\n", __func__,
599 reason_code);
600
601 if (!ath6kl_cfg80211_ready(ar))
602 return -EIO;
603
604 if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
605 ath6kl_err("busy, destroy in progress\n");
606 return -EBUSY;
607 }
608
609 if (down_interruptible(&ar->sem)) {
610 ath6kl_err("busy, couldn't get access\n");
611 return -ERESTARTSYS;
612 }
613
614 ar->reconnect_flag = 0;
615 ath6kl_disconnect(ar);
616 memset(ar->ssid, 0, sizeof(ar->ssid));
617 ar->ssid_len = 0;
618
619 if (!test_bit(SKIP_SCAN, &ar->flag))
620 memset(ar->req_bssid, 0, sizeof(ar->req_bssid));
621
622 up(&ar->sem);
623
170826dd
VT
624 ar->sme_state = SME_DISCONNECTED;
625
bdcd8170
KV
626 return 0;
627}
628
629void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason,
630 u8 *bssid, u8 assoc_resp_len,
631 u8 *assoc_info, u16 proto_reason)
632{
bdcd8170
KV
633 if (ar->scan_req) {
634 cfg80211_scan_done(ar->scan_req, true);
635 ar->scan_req = NULL;
636 }
637
638 if (ar->nw_type & ADHOC_NETWORK) {
639 if (ar->wdev->iftype != NL80211_IFTYPE_ADHOC) {
640 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
641 "%s: ath6k not in ibss mode\n", __func__);
642 return;
643 }
644 memset(bssid, 0, ETH_ALEN);
645 cfg80211_ibss_joined(ar->net_dev, bssid, GFP_KERNEL);
646 return;
647 }
648
649 if (ar->nw_type & INFRA_NETWORK) {
6b5e5d25
JM
650 if (ar->wdev->iftype != NL80211_IFTYPE_STATION &&
651 ar->wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) {
bdcd8170
KV
652 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
653 "%s: ath6k not in station mode\n", __func__);
654 return;
655 }
656 }
657
1de547d6
VT
658 /*
659 * Send a disconnect command to target when a disconnect event is
660 * received with reason code other than 3 (DISCONNECT_CMD - disconnect
661 * request from host) to make the firmware stop trying to connect even
662 * after giving disconnect event. There will be one more disconnect
663 * event for this disconnect command with reason code DISCONNECT_CMD
664 * which will be notified to cfg80211.
665 */
bdcd8170 666
1de547d6 667 if (reason != DISCONNECT_CMD) {
bdcd8170
KV
668 ath6kl_wmi_disconnect_cmd(ar->wmi);
669 return;
670 }
671
ac59a2b2 672 clear_bit(CONNECT_PEND, &ar->flag);
bdcd8170 673
ac59a2b2
VT
674 if (ar->sme_state == SME_CONNECTING) {
675 cfg80211_connect_result(ar->net_dev,
676 bssid, NULL, 0,
677 NULL, 0,
678 WLAN_STATUS_UNSPECIFIED_FAILURE,
679 GFP_KERNEL);
680 } else if (ar->sme_state == SME_CONNECTED) {
681 cfg80211_disconnected(ar->net_dev, reason,
682 NULL, 0, GFP_KERNEL);
bdcd8170
KV
683 }
684
ac59a2b2 685 ar->sme_state = SME_DISCONNECTED;
bdcd8170
KV
686}
687
bdcd8170
KV
688static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
689 struct cfg80211_scan_request *request)
690{
691 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
1276c9ef
EL
692 s8 n_channels = 0;
693 u16 *channels = NULL;
bdcd8170 694 int ret = 0;
f1f92179 695 u32 force_fg_scan = 0;
bdcd8170
KV
696
697 if (!ath6kl_cfg80211_ready(ar))
698 return -EIO;
699
700 if (!ar->usr_bss_filter) {
551185ca 701 clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag);
1b1e6ee3
JM
702 ret = ath6kl_wmi_bssfilter_cmd(
703 ar->wmi,
704 (test_bit(CONNECTED, &ar->flag) ?
705 ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), 0);
706 if (ret) {
bdcd8170 707 ath6kl_err("couldn't set bss filtering\n");
1b1e6ee3 708 return ret;
bdcd8170
KV
709 }
710 }
711
712 if (request->n_ssids && request->ssids[0].ssid_len) {
713 u8 i;
714
715 if (request->n_ssids > (MAX_PROBED_SSID_INDEX - 1))
716 request->n_ssids = MAX_PROBED_SSID_INDEX - 1;
717
718 for (i = 0; i < request->n_ssids; i++)
719 ath6kl_wmi_probedssid_cmd(ar->wmi, i + 1,
720 SPECIFIC_SSID_FLAG,
721 request->ssids[i].ssid_len,
722 request->ssids[i].ssid);
723 }
724
b84da8c7
JM
725 if (request->ie) {
726 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_PROBE_REQ,
727 request->ie, request->ie_len);
728 if (ret) {
729 ath6kl_err("failed to set Probe Request appie for "
730 "scan");
731 return ret;
732 }
733 }
734
11869bef
JM
735 /*
736 * Scan only the requested channels if the request specifies a set of
737 * channels. If the list is longer than the target supports, do not
738 * configure the list and instead, scan all available channels.
739 */
740 if (request->n_channels > 0 &&
741 request->n_channels <= WMI_MAX_CHANNELS) {
1276c9ef
EL
742 u8 i;
743
11869bef 744 n_channels = request->n_channels;
1276c9ef
EL
745
746 channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL);
747 if (channels == NULL) {
748 ath6kl_warn("failed to set scan channels, "
749 "scan all channels");
750 n_channels = 0;
751 }
752
753 for (i = 0; i < n_channels; i++)
754 channels[i] = request->channels[i]->center_freq;
755 }
756
f1f92179
VT
757 if (test_bit(CONNECTED, &ar->flag))
758 force_fg_scan = 1;
759
760 ret = ath6kl_wmi_startscan_cmd(ar->wmi, WMI_LONG_SCAN, force_fg_scan,
1b1e6ee3
JM
761 false, 0, 0, n_channels, channels);
762 if (ret)
bdcd8170 763 ath6kl_err("wmi_startscan_cmd failed\n");
11869bef
JM
764 else
765 ar->scan_req = request;
bdcd8170 766
1276c9ef
EL
767 kfree(channels);
768
bdcd8170
KV
769 return ret;
770}
771
772void ath6kl_cfg80211_scan_complete_event(struct ath6kl *ar, int status)
773{
6fd1eace 774 int i;
bdcd8170
KV
775
776 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status %d\n", __func__, status);
777
6fd1eace
KV
778 if (!ar->scan_req)
779 return;
780
781 if ((status == -ECANCELED) || (status == -EBUSY)) {
782 cfg80211_scan_done(ar->scan_req, true);
783 goto out;
784 }
6fd1eace
KV
785
786 cfg80211_scan_done(ar->scan_req, false);
787
788 if (ar->scan_req->n_ssids && ar->scan_req->ssids[0].ssid_len) {
789 for (i = 0; i < ar->scan_req->n_ssids; i++) {
790 ath6kl_wmi_probedssid_cmd(ar->wmi, i + 1,
791 DISABLE_SSID_FLAG,
792 0, NULL);
bdcd8170 793 }
bdcd8170 794 }
6fd1eace
KV
795
796out:
797 ar->scan_req = NULL;
bdcd8170
KV
798}
799
800static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
801 u8 key_index, bool pairwise,
802 const u8 *mac_addr,
803 struct key_params *params)
804{
805 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
806 struct ath6kl_key *key = NULL;
807 u8 key_usage;
808 u8 key_type;
809 int status = 0;
810
811 if (!ath6kl_cfg80211_ready(ar))
812 return -EIO;
813
814 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
815 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
816 "%s: key index %d out of bounds\n", __func__,
817 key_index);
818 return -ENOENT;
819 }
820
821 key = &ar->keys[key_index];
822 memset(key, 0, sizeof(struct ath6kl_key));
823
824 if (pairwise)
825 key_usage = PAIRWISE_USAGE;
826 else
827 key_usage = GROUP_USAGE;
828
829 if (params) {
830 if (params->key_len > WLAN_MAX_KEY_LEN ||
831 params->seq_len > sizeof(key->seq))
832 return -EINVAL;
833
834 key->key_len = params->key_len;
835 memcpy(key->key, params->key, key->key_len);
836 key->seq_len = params->seq_len;
837 memcpy(key->seq, params->seq, key->seq_len);
838 key->cipher = params->cipher;
839 }
840
841 switch (key->cipher) {
842 case WLAN_CIPHER_SUITE_WEP40:
843 case WLAN_CIPHER_SUITE_WEP104:
844 key_type = WEP_CRYPT;
845 break;
846
847 case WLAN_CIPHER_SUITE_TKIP:
848 key_type = TKIP_CRYPT;
849 break;
850
851 case WLAN_CIPHER_SUITE_CCMP:
852 key_type = AES_CRYPT;
853 break;
854
855 default:
856 return -ENOTSUPP;
857 }
858
859 if (((ar->auth_mode == WPA_PSK_AUTH)
860 || (ar->auth_mode == WPA2_PSK_AUTH))
861 && (key_usage & GROUP_USAGE))
862 del_timer(&ar->disconnect_timer);
863
864 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
865 "%s: index %d, key_len %d, key_type 0x%x, key_usage 0x%x, seq_len %d\n",
866 __func__, key_index, key->key_len, key_type,
867 key_usage, key->seq_len);
868
869 ar->def_txkey_index = key_index;
9a5b1318
JM
870
871 if (ar->nw_type == AP_NETWORK && !pairwise &&
872 (key_type == TKIP_CRYPT || key_type == AES_CRYPT) && params) {
873 ar->ap_mode_bkey.valid = true;
874 ar->ap_mode_bkey.key_index = key_index;
875 ar->ap_mode_bkey.key_type = key_type;
876 ar->ap_mode_bkey.key_len = key->key_len;
877 memcpy(ar->ap_mode_bkey.key, key->key, key->key_len);
878 if (!test_bit(CONNECTED, &ar->flag)) {
879 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group "
880 "key configuration until AP mode has been "
881 "started\n");
882 /*
883 * The key will be set in ath6kl_connect_ap_mode() once
884 * the connected event is received from the target.
885 */
886 return 0;
887 }
888 }
889
151411e8
JM
890 if (ar->next_mode == AP_NETWORK && key_type == WEP_CRYPT &&
891 !test_bit(CONNECTED, &ar->flag)) {
892 /*
893 * Store the key locally so that it can be re-configured after
894 * the AP mode has properly started
895 * (ath6kl_install_statioc_wep_keys).
896 */
897 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay WEP key configuration "
898 "until AP mode has been started\n");
899 ar->wep_key_list[key_index].key_len = key->key_len;
900 memcpy(ar->wep_key_list[key_index].key, key->key, key->key_len);
901 return 0;
902 }
903
bdcd8170
KV
904 status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index,
905 key_type, key_usage, key->key_len,
906 key->seq, key->key, KEY_OP_INIT_VAL,
907 (u8 *) mac_addr, SYNC_BOTH_WMIFLAG);
908
909 if (status)
910 return -EIO;
911
912 return 0;
913}
914
915static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
916 u8 key_index, bool pairwise,
917 const u8 *mac_addr)
918{
919 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
920
921 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
922
923 if (!ath6kl_cfg80211_ready(ar))
924 return -EIO;
925
926 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
927 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
928 "%s: key index %d out of bounds\n", __func__,
929 key_index);
930 return -ENOENT;
931 }
932
933 if (!ar->keys[key_index].key_len) {
934 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
935 "%s: index %d is empty\n", __func__, key_index);
936 return 0;
937 }
938
939 ar->keys[key_index].key_len = 0;
940
941 return ath6kl_wmi_deletekey_cmd(ar->wmi, key_index);
942}
943
944static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
945 u8 key_index, bool pairwise,
946 const u8 *mac_addr, void *cookie,
947 void (*callback) (void *cookie,
948 struct key_params *))
949{
950 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
951 struct ath6kl_key *key = NULL;
952 struct key_params params;
953
954 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
955
956 if (!ath6kl_cfg80211_ready(ar))
957 return -EIO;
958
959 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
960 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
961 "%s: key index %d out of bounds\n", __func__,
962 key_index);
963 return -ENOENT;
964 }
965
966 key = &ar->keys[key_index];
967 memset(&params, 0, sizeof(params));
968 params.cipher = key->cipher;
969 params.key_len = key->key_len;
970 params.seq_len = key->seq_len;
971 params.seq = key->seq;
972 params.key = key->key;
973
974 callback(cookie, &params);
975
976 return key->key_len ? 0 : -ENOENT;
977}
978
979static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
980 struct net_device *ndev,
981 u8 key_index, bool unicast,
982 bool multicast)
983{
984 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
985 struct ath6kl_key *key = NULL;
986 int status = 0;
987 u8 key_usage;
229ed6b5 988 enum crypto_type key_type = NONE_CRYPT;
bdcd8170
KV
989
990 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
991
992 if (!ath6kl_cfg80211_ready(ar))
993 return -EIO;
994
995 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
996 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
997 "%s: key index %d out of bounds\n",
998 __func__, key_index);
999 return -ENOENT;
1000 }
1001
1002 if (!ar->keys[key_index].key_len) {
1003 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: invalid key index %d\n",
1004 __func__, key_index);
1005 return -EINVAL;
1006 }
1007
1008 ar->def_txkey_index = key_index;
1009 key = &ar->keys[ar->def_txkey_index];
1010 key_usage = GROUP_USAGE;
1011 if (ar->prwise_crypto == WEP_CRYPT)
1012 key_usage |= TX_USAGE;
229ed6b5
EL
1013 if (unicast)
1014 key_type = ar->prwise_crypto;
1015 if (multicast)
1016 key_type = ar->grp_crypto;
bdcd8170 1017
151411e8 1018 if (ar->next_mode == AP_NETWORK && !test_bit(CONNECTED, &ar->flag))
9a5b1318
JM
1019 return 0; /* Delay until AP mode has been started */
1020
bdcd8170 1021 status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index,
229ed6b5 1022 key_type, key_usage,
bdcd8170
KV
1023 key->key_len, key->seq, key->key,
1024 KEY_OP_INIT_VAL, NULL,
1025 SYNC_BOTH_WMIFLAG);
1026 if (status)
1027 return -EIO;
1028
1029 return 0;
1030}
1031
1032void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl *ar, u8 keyid,
1033 bool ismcast)
1034{
1035 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1036 "%s: keyid %d, ismcast %d\n", __func__, keyid, ismcast);
1037
1038 cfg80211_michael_mic_failure(ar->net_dev, ar->bssid,
1039 (ismcast ? NL80211_KEYTYPE_GROUP :
1040 NL80211_KEYTYPE_PAIRWISE), keyid, NULL,
1041 GFP_KERNEL);
1042}
1043
1044static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1045{
1046 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
1047 int ret;
1048
1049 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: changed 0x%x\n", __func__,
1050 changed);
1051
1052 if (!ath6kl_cfg80211_ready(ar))
1053 return -EIO;
1054
1055 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
1056 ret = ath6kl_wmi_set_rts_cmd(ar->wmi, wiphy->rts_threshold);
1057 if (ret != 0) {
1058 ath6kl_err("ath6kl_wmi_set_rts_cmd failed\n");
1059 return -EIO;
1060 }
1061 }
1062
1063 return 0;
1064}
1065
1066/*
1067 * The type nl80211_tx_power_setting replaces the following
1068 * data type from 2.6.36 onwards
1069*/
1070static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
1071 enum nl80211_tx_power_setting type,
1072 int dbm)
1073{
1074 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
1075 u8 ath6kl_dbm;
1076
1077 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__,
1078 type, dbm);
1079
1080 if (!ath6kl_cfg80211_ready(ar))
1081 return -EIO;
1082
1083 switch (type) {
1084 case NL80211_TX_POWER_AUTOMATIC:
1085 return 0;
1086 case NL80211_TX_POWER_LIMITED:
1087 ar->tx_pwr = ath6kl_dbm = dbm;
1088 break;
1089 default:
1090 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x not supported\n",
1091 __func__, type);
1092 return -EOPNOTSUPP;
1093 }
1094
1095 ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, ath6kl_dbm);
1096
1097 return 0;
1098}
1099
1100static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
1101{
1102 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
1103
1104 if (!ath6kl_cfg80211_ready(ar))
1105 return -EIO;
1106
1107 if (test_bit(CONNECTED, &ar->flag)) {
1108 ar->tx_pwr = 0;
1109
1110 if (ath6kl_wmi_get_tx_pwr_cmd(ar->wmi) != 0) {
1111 ath6kl_err("ath6kl_wmi_get_tx_pwr_cmd failed\n");
1112 return -EIO;
1113 }
1114
1115 wait_event_interruptible_timeout(ar->event_wq, ar->tx_pwr != 0,
1116 5 * HZ);
1117
1118 if (signal_pending(current)) {
1119 ath6kl_err("target did not respond\n");
1120 return -EINTR;
1121 }
1122 }
1123
1124 *dbm = ar->tx_pwr;
1125 return 0;
1126}
1127
1128static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
1129 struct net_device *dev,
1130 bool pmgmt, int timeout)
1131{
1132 struct ath6kl *ar = ath6kl_priv(dev);
1133 struct wmi_power_mode_cmd mode;
1134
1135 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: pmgmt %d, timeout %d\n",
1136 __func__, pmgmt, timeout);
1137
1138 if (!ath6kl_cfg80211_ready(ar))
1139 return -EIO;
1140
1141 if (pmgmt) {
1142 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: max perf\n", __func__);
1143 mode.pwr_mode = REC_POWER;
1144 } else {
1145 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: rec power\n", __func__);
1146 mode.pwr_mode = MAX_PERF_POWER;
1147 }
1148
1149 if (ath6kl_wmi_powermode_cmd(ar->wmi, mode.pwr_mode) != 0) {
1150 ath6kl_err("wmi_powermode_cmd failed\n");
1151 return -EIO;
1152 }
1153
1154 return 0;
1155}
1156
1157static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
1158 struct net_device *ndev,
1159 enum nl80211_iftype type, u32 *flags,
1160 struct vif_params *params)
1161{
1162 struct ath6kl *ar = ath6kl_priv(ndev);
1163 struct wireless_dev *wdev = ar->wdev;
1164
1165 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type);
1166
1167 if (!ath6kl_cfg80211_ready(ar))
1168 return -EIO;
1169
1170 switch (type) {
1171 case NL80211_IFTYPE_STATION:
1172 ar->next_mode = INFRA_NETWORK;
1173 break;
1174 case NL80211_IFTYPE_ADHOC:
1175 ar->next_mode = ADHOC_NETWORK;
1176 break;
6e4604c8
JM
1177 case NL80211_IFTYPE_AP:
1178 ar->next_mode = AP_NETWORK;
1179 break;
6b5e5d25
JM
1180 case NL80211_IFTYPE_P2P_CLIENT:
1181 ar->next_mode = INFRA_NETWORK;
1182 break;
1183 case NL80211_IFTYPE_P2P_GO:
1184 ar->next_mode = AP_NETWORK;
1185 break;
bdcd8170
KV
1186 default:
1187 ath6kl_err("invalid interface type %u\n", type);
1188 return -EOPNOTSUPP;
1189 }
1190
1191 wdev->iftype = type;
1192
1193 return 0;
1194}
1195
1196static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
1197 struct net_device *dev,
1198 struct cfg80211_ibss_params *ibss_param)
1199{
1200 struct ath6kl *ar = ath6kl_priv(dev);
1201 int status;
1202
1203 if (!ath6kl_cfg80211_ready(ar))
1204 return -EIO;
1205
1206 ar->ssid_len = ibss_param->ssid_len;
1207 memcpy(ar->ssid, ibss_param->ssid, ar->ssid_len);
1208
1209 if (ibss_param->channel)
1210 ar->ch_hint = ibss_param->channel->center_freq;
1211
1212 if (ibss_param->channel_fixed) {
1213 /*
1214 * TODO: channel_fixed: The channel should be fixed, do not
1215 * search for IBSSs to join on other channels. Target
1216 * firmware does not support this feature, needs to be
1217 * updated.
1218 */
1219 return -EOPNOTSUPP;
1220 }
1221
1222 memset(ar->req_bssid, 0, sizeof(ar->req_bssid));
1223 if (ibss_param->bssid && !is_broadcast_ether_addr(ibss_param->bssid))
1224 memcpy(ar->req_bssid, ibss_param->bssid, sizeof(ar->req_bssid));
1225
1226 ath6kl_set_wpa_version(ar, 0);
1227
1228 status = ath6kl_set_auth_type(ar, NL80211_AUTHTYPE_OPEN_SYSTEM);
1229 if (status)
1230 return status;
1231
1232 if (ibss_param->privacy) {
1233 ath6kl_set_cipher(ar, WLAN_CIPHER_SUITE_WEP40, true);
1234 ath6kl_set_cipher(ar, WLAN_CIPHER_SUITE_WEP40, false);
1235 } else {
1236 ath6kl_set_cipher(ar, 0, true);
1237 ath6kl_set_cipher(ar, 0, false);
1238 }
1239
1240 ar->nw_type = ar->next_mode;
1241
1242 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1243 "%s: connect called with authmode %d dot11 auth %d"
1244 " PW crypto %d PW crypto len %d GRP crypto %d"
1245 " GRP crypto len %d channel hint %u\n",
1246 __func__,
1247 ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto,
1248 ar->prwise_crypto_len, ar->grp_crypto,
38acde3c 1249 ar->grp_crypto_len, ar->ch_hint);
bdcd8170
KV
1250
1251 status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type,
1252 ar->dot11_auth_mode, ar->auth_mode,
1253 ar->prwise_crypto,
1254 ar->prwise_crypto_len,
38acde3c 1255 ar->grp_crypto, ar->grp_crypto_len,
bdcd8170
KV
1256 ar->ssid_len, ar->ssid,
1257 ar->req_bssid, ar->ch_hint,
1258 ar->connect_ctrl_flags);
1259 set_bit(CONNECT_PEND, &ar->flag);
1260
1261 return 0;
1262}
1263
1264static int ath6kl_cfg80211_leave_ibss(struct wiphy *wiphy,
1265 struct net_device *dev)
1266{
1267 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(dev);
1268
1269 if (!ath6kl_cfg80211_ready(ar))
1270 return -EIO;
1271
1272 ath6kl_disconnect(ar);
1273 memset(ar->ssid, 0, sizeof(ar->ssid));
1274 ar->ssid_len = 0;
1275
1276 return 0;
1277}
1278
1279static const u32 cipher_suites[] = {
1280 WLAN_CIPHER_SUITE_WEP40,
1281 WLAN_CIPHER_SUITE_WEP104,
1282 WLAN_CIPHER_SUITE_TKIP,
1283 WLAN_CIPHER_SUITE_CCMP,
1284};
1285
1286static bool is_rate_legacy(s32 rate)
1287{
1288 static const s32 legacy[] = { 1000, 2000, 5500, 11000,
1289 6000, 9000, 12000, 18000, 24000,
1290 36000, 48000, 54000
1291 };
1292 u8 i;
1293
1294 for (i = 0; i < ARRAY_SIZE(legacy); i++)
1295 if (rate == legacy[i])
1296 return true;
1297
1298 return false;
1299}
1300
1301static bool is_rate_ht20(s32 rate, u8 *mcs, bool *sgi)
1302{
1303 static const s32 ht20[] = { 6500, 13000, 19500, 26000, 39000,
1304 52000, 58500, 65000, 72200
1305 };
1306 u8 i;
1307
1308 for (i = 0; i < ARRAY_SIZE(ht20); i++) {
1309 if (rate == ht20[i]) {
1310 if (i == ARRAY_SIZE(ht20) - 1)
1311 /* last rate uses sgi */
1312 *sgi = true;
1313 else
1314 *sgi = false;
1315
1316 *mcs = i;
1317 return true;
1318 }
1319 }
1320 return false;
1321}
1322
1323static bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi)
1324{
1325 static const s32 ht40[] = { 13500, 27000, 40500, 54000,
1326 81000, 108000, 121500, 135000,
1327 150000
1328 };
1329 u8 i;
1330
1331 for (i = 0; i < ARRAY_SIZE(ht40); i++) {
1332 if (rate == ht40[i]) {
1333 if (i == ARRAY_SIZE(ht40) - 1)
1334 /* last rate uses sgi */
1335 *sgi = true;
1336 else
1337 *sgi = false;
1338
1339 *mcs = i;
1340 return true;
1341 }
1342 }
1343
1344 return false;
1345}
1346
1347static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
1348 u8 *mac, struct station_info *sinfo)
1349{
1350 struct ath6kl *ar = ath6kl_priv(dev);
1351 long left;
1352 bool sgi;
1353 s32 rate;
1354 int ret;
1355 u8 mcs;
1356
1357 if (memcmp(mac, ar->bssid, ETH_ALEN) != 0)
1358 return -ENOENT;
1359
1360 if (down_interruptible(&ar->sem))
1361 return -EBUSY;
1362
1363 set_bit(STATS_UPDATE_PEND, &ar->flag);
1364
1365 ret = ath6kl_wmi_get_stats_cmd(ar->wmi);
1366
1367 if (ret != 0) {
1368 up(&ar->sem);
1369 return -EIO;
1370 }
1371
1372 left = wait_event_interruptible_timeout(ar->event_wq,
1373 !test_bit(STATS_UPDATE_PEND,
1374 &ar->flag),
1375 WMI_TIMEOUT);
1376
1377 up(&ar->sem);
1378
1379 if (left == 0)
1380 return -ETIMEDOUT;
1381 else if (left < 0)
1382 return left;
1383
1384 if (ar->target_stats.rx_byte) {
1385 sinfo->rx_bytes = ar->target_stats.rx_byte;
1386 sinfo->filled |= STATION_INFO_RX_BYTES;
1387 sinfo->rx_packets = ar->target_stats.rx_pkt;
1388 sinfo->filled |= STATION_INFO_RX_PACKETS;
1389 }
1390
1391 if (ar->target_stats.tx_byte) {
1392 sinfo->tx_bytes = ar->target_stats.tx_byte;
1393 sinfo->filled |= STATION_INFO_TX_BYTES;
1394 sinfo->tx_packets = ar->target_stats.tx_pkt;
1395 sinfo->filled |= STATION_INFO_TX_PACKETS;
1396 }
1397
1398 sinfo->signal = ar->target_stats.cs_rssi;
1399 sinfo->filled |= STATION_INFO_SIGNAL;
1400
1401 rate = ar->target_stats.tx_ucast_rate;
1402
1403 if (is_rate_legacy(rate)) {
1404 sinfo->txrate.legacy = rate / 100;
1405 } else if (is_rate_ht20(rate, &mcs, &sgi)) {
1406 if (sgi) {
1407 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
1408 sinfo->txrate.mcs = mcs - 1;
1409 } else {
1410 sinfo->txrate.mcs = mcs;
1411 }
1412
1413 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
1414 } else if (is_rate_ht40(rate, &mcs, &sgi)) {
1415 if (sgi) {
1416 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
1417 sinfo->txrate.mcs = mcs - 1;
1418 } else {
1419 sinfo->txrate.mcs = mcs;
1420 }
1421
1422 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
1423 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
1424 } else {
9a730834
KV
1425 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1426 "invalid rate from stats: %d\n", rate);
1427 ath6kl_debug_war(ar, ATH6KL_WAR_INVALID_RATE);
bdcd8170
KV
1428 return 0;
1429 }
1430
1431 sinfo->filled |= STATION_INFO_TX_BITRATE;
1432
32c10874
JM
1433 if (test_bit(CONNECTED, &ar->flag) &&
1434 test_bit(DTIM_PERIOD_AVAIL, &ar->flag) &&
1435 ar->nw_type == INFRA_NETWORK) {
1436 sinfo->filled |= STATION_INFO_BSS_PARAM;
1437 sinfo->bss_param.flags = 0;
1438 sinfo->bss_param.dtim_period = ar->assoc_bss_dtim_period;
1439 sinfo->bss_param.beacon_interval = ar->assoc_bss_beacon_int;
1440 }
1441
bdcd8170
KV
1442 return 0;
1443}
1444
1445static int ath6kl_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1446 struct cfg80211_pmksa *pmksa)
1447{
1448 struct ath6kl *ar = ath6kl_priv(netdev);
1449 return ath6kl_wmi_setpmkid_cmd(ar->wmi, pmksa->bssid,
1450 pmksa->pmkid, true);
1451}
1452
1453static int ath6kl_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1454 struct cfg80211_pmksa *pmksa)
1455{
1456 struct ath6kl *ar = ath6kl_priv(netdev);
1457 return ath6kl_wmi_setpmkid_cmd(ar->wmi, pmksa->bssid,
1458 pmksa->pmkid, false);
1459}
1460
1461static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
1462{
1463 struct ath6kl *ar = ath6kl_priv(netdev);
1464 if (test_bit(CONNECTED, &ar->flag))
1465 return ath6kl_wmi_setpmkid_cmd(ar->wmi, ar->bssid, NULL, false);
1466 return 0;
1467}
1468
abcb344b
KV
1469#ifdef CONFIG_PM
1470static int ar6k_cfg80211_suspend(struct wiphy *wiphy,
1471 struct cfg80211_wowlan *wow)
1472{
1473 struct ath6kl *ar = wiphy_priv(wiphy);
1474
1475 return ath6kl_hif_suspend(ar);
1476}
aa6cffc1
CN
1477
1478static int ar6k_cfg80211_resume(struct wiphy *wiphy)
1479{
1480 struct ath6kl *ar = wiphy_priv(wiphy);
1481
1482 return ath6kl_hif_resume(ar);
1483}
abcb344b
KV
1484#endif
1485
6a7c9bad
JM
1486static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev,
1487 struct ieee80211_channel *chan,
1488 enum nl80211_channel_type channel_type)
1489{
1490 struct ath6kl *ar = ath6kl_priv(dev);
1491
1492 if (!ath6kl_cfg80211_ready(ar))
1493 return -EIO;
1494
1495 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: center_freq=%u hw_value=%u\n",
1496 __func__, chan->center_freq, chan->hw_value);
1497 ar->next_chan = chan->center_freq;
1498
1499 return 0;
1500}
1501
8bdfbf40
JM
1502static bool ath6kl_is_p2p_ie(const u8 *pos)
1503{
1504 return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
1505 pos[2] == 0x50 && pos[3] == 0x6f &&
1506 pos[4] == 0x9a && pos[5] == 0x09;
1507}
1508
1509static int ath6kl_set_ap_probe_resp_ies(struct ath6kl *ar, const u8 *ies,
1510 size_t ies_len)
1511{
1512 const u8 *pos;
1513 u8 *buf = NULL;
1514 size_t len = 0;
1515 int ret;
1516
1517 /*
1518 * Filter out P2P IE(s) since they will be included depending on
1519 * the Probe Request frame in ath6kl_send_go_probe_resp().
1520 */
1521
1522 if (ies && ies_len) {
1523 buf = kmalloc(ies_len, GFP_KERNEL);
1524 if (buf == NULL)
1525 return -ENOMEM;
1526 pos = ies;
1527 while (pos + 1 < ies + ies_len) {
1528 if (pos + 2 + pos[1] > ies + ies_len)
1529 break;
1530 if (!ath6kl_is_p2p_ie(pos)) {
1531 memcpy(buf + len, pos, 2 + pos[1]);
1532 len += 2 + pos[1];
1533 }
1534 pos += 2 + pos[1];
1535 }
1536 }
1537
1538 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_PROBE_RESP,
1539 buf, len);
1540 kfree(buf);
1541 return ret;
1542}
1543
6a7c9bad
JM
1544static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev,
1545 struct beacon_parameters *info, bool add)
1546{
1547 struct ath6kl *ar = ath6kl_priv(dev);
1548 struct ieee80211_mgmt *mgmt;
1549 u8 *ies;
1550 int ies_len;
1551 struct wmi_connect_cmd p;
1552 int res;
1553 int i;
1554
1555 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: add=%d\n", __func__, add);
1556
1557 if (!ath6kl_cfg80211_ready(ar))
1558 return -EIO;
1559
1560 if (ar->next_mode != AP_NETWORK)
1561 return -EOPNOTSUPP;
1562
1563 if (info->beacon_ies) {
1564 res = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_BEACON,
1565 info->beacon_ies,
1566 info->beacon_ies_len);
1567 if (res)
1568 return res;
1569 }
1570 if (info->proberesp_ies) {
8bdfbf40
JM
1571 res = ath6kl_set_ap_probe_resp_ies(ar, info->proberesp_ies,
1572 info->proberesp_ies_len);
6a7c9bad
JM
1573 if (res)
1574 return res;
1575 }
1576 if (info->assocresp_ies) {
1577 res = ath6kl_wmi_set_appie_cmd(ar->wmi, WMI_FRAME_ASSOC_RESP,
1578 info->assocresp_ies,
1579 info->assocresp_ies_len);
1580 if (res)
1581 return res;
1582 }
1583
1584 if (!add)
1585 return 0;
1586
9a5b1318
JM
1587 ar->ap_mode_bkey.valid = false;
1588
6a7c9bad
JM
1589 /* TODO:
1590 * info->interval
1591 * info->dtim_period
1592 */
1593
1594 if (info->head == NULL)
1595 return -EINVAL;
1596 mgmt = (struct ieee80211_mgmt *) info->head;
1597 ies = mgmt->u.beacon.variable;
1598 if (ies > info->head + info->head_len)
1599 return -EINVAL;
1600 ies_len = info->head + info->head_len - ies;
1601
1602 if (info->ssid == NULL)
1603 return -EINVAL;
1604 memcpy(ar->ssid, info->ssid, info->ssid_len);
1605 ar->ssid_len = info->ssid_len;
1606 if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
1607 return -EOPNOTSUPP; /* TODO */
1608
1609 ar->dot11_auth_mode = OPEN_AUTH;
1610
1611 memset(&p, 0, sizeof(p));
1612
1613 for (i = 0; i < info->crypto.n_akm_suites; i++) {
1614 switch (info->crypto.akm_suites[i]) {
1615 case WLAN_AKM_SUITE_8021X:
1616 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1617 p.auth_mode |= WPA_AUTH;
1618 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1619 p.auth_mode |= WPA2_AUTH;
1620 break;
1621 case WLAN_AKM_SUITE_PSK:
1622 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1623 p.auth_mode |= WPA_PSK_AUTH;
1624 if (info->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1625 p.auth_mode |= WPA2_PSK_AUTH;
1626 break;
1627 }
1628 }
1629 if (p.auth_mode == 0)
1630 p.auth_mode = NONE_AUTH;
1631 ar->auth_mode = p.auth_mode;
1632
1633 for (i = 0; i < info->crypto.n_ciphers_pairwise; i++) {
1634 switch (info->crypto.ciphers_pairwise[i]) {
1635 case WLAN_CIPHER_SUITE_WEP40:
1636 case WLAN_CIPHER_SUITE_WEP104:
1637 p.prwise_crypto_type |= WEP_CRYPT;
1638 break;
1639 case WLAN_CIPHER_SUITE_TKIP:
1640 p.prwise_crypto_type |= TKIP_CRYPT;
1641 break;
1642 case WLAN_CIPHER_SUITE_CCMP:
1643 p.prwise_crypto_type |= AES_CRYPT;
1644 break;
1645 }
1646 }
229ed6b5 1647 if (p.prwise_crypto_type == 0) {
6a7c9bad 1648 p.prwise_crypto_type = NONE_CRYPT;
229ed6b5
EL
1649 ath6kl_set_cipher(ar, 0, true);
1650 } else if (info->crypto.n_ciphers_pairwise == 1)
1651 ath6kl_set_cipher(ar, info->crypto.ciphers_pairwise[0], true);
6a7c9bad
JM
1652
1653 switch (info->crypto.cipher_group) {
1654 case WLAN_CIPHER_SUITE_WEP40:
1655 case WLAN_CIPHER_SUITE_WEP104:
1656 p.grp_crypto_type = WEP_CRYPT;
1657 break;
1658 case WLAN_CIPHER_SUITE_TKIP:
1659 p.grp_crypto_type = TKIP_CRYPT;
1660 break;
1661 case WLAN_CIPHER_SUITE_CCMP:
1662 p.grp_crypto_type = AES_CRYPT;
1663 break;
1664 default:
1665 p.grp_crypto_type = NONE_CRYPT;
1666 break;
1667 }
229ed6b5 1668 ath6kl_set_cipher(ar, info->crypto.cipher_group, false);
6a7c9bad
JM
1669
1670 p.nw_type = AP_NETWORK;
1671 ar->nw_type = ar->next_mode;
1672
1673 p.ssid_len = ar->ssid_len;
1674 memcpy(p.ssid, ar->ssid, ar->ssid_len);
1675 p.dot11_auth_mode = ar->dot11_auth_mode;
1676 p.ch = cpu_to_le16(ar->next_chan);
1677
9a5b1318
JM
1678 res = ath6kl_wmi_ap_profile_commit(ar->wmi, &p);
1679 if (res < 0)
1680 return res;
1681
1682 return 0;
6a7c9bad
JM
1683}
1684
1685static int ath6kl_add_beacon(struct wiphy *wiphy, struct net_device *dev,
1686 struct beacon_parameters *info)
1687{
1688 return ath6kl_ap_beacon(wiphy, dev, info, true);
1689}
1690
1691static int ath6kl_set_beacon(struct wiphy *wiphy, struct net_device *dev,
1692 struct beacon_parameters *info)
1693{
1694 return ath6kl_ap_beacon(wiphy, dev, info, false);
1695}
1696
1697static int ath6kl_del_beacon(struct wiphy *wiphy, struct net_device *dev)
1698{
1699 struct ath6kl *ar = ath6kl_priv(dev);
1700
1701 if (ar->nw_type != AP_NETWORK)
1702 return -EOPNOTSUPP;
1703 if (!test_bit(CONNECTED, &ar->flag))
1704 return -ENOTCONN;
1705
1706 ath6kl_wmi_disconnect_cmd(ar->wmi);
1707 clear_bit(CONNECTED, &ar->flag);
1708
1709 return 0;
1710}
1711
23875136
JM
1712static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
1713 u8 *mac, struct station_parameters *params)
1714{
1715 struct ath6kl *ar = ath6kl_priv(dev);
1716
1717 if (ar->nw_type != AP_NETWORK)
1718 return -EOPNOTSUPP;
1719
1720 /* Use this only for authorizing/unauthorizing a station */
1721 if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
1722 return -EOPNOTSUPP;
1723
1724 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
1725 return ath6kl_wmi_ap_set_mlme(ar->wmi, WMI_AP_MLME_AUTHORIZE,
1726 mac, 0);
1727 return ath6kl_wmi_ap_set_mlme(ar->wmi, WMI_AP_MLME_UNAUTHORIZE, mac,
1728 0);
1729}
1730
63fa1e0c
JM
1731static int ath6kl_remain_on_channel(struct wiphy *wiphy,
1732 struct net_device *dev,
1733 struct ieee80211_channel *chan,
1734 enum nl80211_channel_type channel_type,
1735 unsigned int duration,
1736 u64 *cookie)
1737{
1738 struct ath6kl *ar = ath6kl_priv(dev);
1739
1740 /* TODO: if already pending or ongoing remain-on-channel,
1741 * return -EBUSY */
1742 *cookie = 1; /* only a single pending request is supported */
1743
1744 return ath6kl_wmi_remain_on_chnl_cmd(ar->wmi, chan->center_freq,
1745 duration);
1746}
1747
1748static int ath6kl_cancel_remain_on_channel(struct wiphy *wiphy,
1749 struct net_device *dev,
1750 u64 cookie)
1751{
1752 struct ath6kl *ar = ath6kl_priv(dev);
1753
1754 if (cookie != 1)
1755 return -ENOENT;
1756
1757 return ath6kl_wmi_cancel_remain_on_chnl_cmd(ar->wmi);
1758}
1759
8bdfbf40
JM
1760static int ath6kl_send_go_probe_resp(struct ath6kl *ar, const u8 *buf,
1761 size_t len, unsigned int freq)
1762{
1763 const u8 *pos;
1764 u8 *p2p;
1765 int p2p_len;
1766 int ret;
1767 const struct ieee80211_mgmt *mgmt;
1768
1769 mgmt = (const struct ieee80211_mgmt *) buf;
1770
1771 /* Include P2P IE(s) from the frame generated in user space. */
1772
1773 p2p = kmalloc(len, GFP_KERNEL);
1774 if (p2p == NULL)
1775 return -ENOMEM;
1776 p2p_len = 0;
1777
1778 pos = mgmt->u.probe_resp.variable;
1779 while (pos + 1 < buf + len) {
1780 if (pos + 2 + pos[1] > buf + len)
1781 break;
1782 if (ath6kl_is_p2p_ie(pos)) {
1783 memcpy(p2p + p2p_len, pos, 2 + pos[1]);
1784 p2p_len += 2 + pos[1];
1785 }
1786 pos += 2 + pos[1];
1787 }
1788
1789 ret = ath6kl_wmi_send_probe_response_cmd(ar->wmi, freq, mgmt->da,
1790 p2p, p2p_len);
1791 kfree(p2p);
1792 return ret;
1793}
1794
8a6c8060
JM
1795static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
1796 struct ieee80211_channel *chan, bool offchan,
1797 enum nl80211_channel_type channel_type,
1798 bool channel_type_valid, unsigned int wait,
e247bd90
JB
1799 const u8 *buf, size_t len, bool no_cck,
1800 bool dont_wait_for_ack, u64 *cookie)
8a6c8060
JM
1801{
1802 struct ath6kl *ar = ath6kl_priv(dev);
1803 u32 id;
8bdfbf40
JM
1804 const struct ieee80211_mgmt *mgmt;
1805
1806 mgmt = (const struct ieee80211_mgmt *) buf;
1807 if (buf + len >= mgmt->u.probe_resp.variable &&
1808 ar->nw_type == AP_NETWORK && test_bit(CONNECTED, &ar->flag) &&
1809 ieee80211_is_probe_resp(mgmt->frame_control)) {
1810 /*
1811 * Send Probe Response frame in AP mode using a separate WMI
1812 * command to allow the target to fill in the generic IEs.
1813 */
1814 *cookie = 0; /* TX status not supported */
1815 return ath6kl_send_go_probe_resp(ar, buf, len,
1816 chan->center_freq);
1817 }
8a6c8060
JM
1818
1819 id = ar->send_action_id++;
1820 if (id == 0) {
1821 /*
1822 * 0 is a reserved value in the WMI command and shall not be
1823 * used for the command.
1824 */
1825 id = ar->send_action_id++;
1826 }
1827
1828 *cookie = id;
1829 return ath6kl_wmi_send_action_cmd(ar->wmi, id, chan->center_freq, wait,
1830 buf, len);
1831}
1832
ae32c30a
JM
1833static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
1834 struct net_device *dev,
1835 u16 frame_type, bool reg)
1836{
1837 struct ath6kl *ar = ath6kl_priv(dev);
1838
1839 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: frame_type=0x%x reg=%d\n",
1840 __func__, frame_type, reg);
1841 if (frame_type == IEEE80211_STYPE_PROBE_REQ) {
1842 /*
1843 * Note: This notification callback is not allowed to sleep, so
1844 * we cannot send WMI_PROBE_REQ_REPORT_CMD here. Instead, we
1845 * hardcode target to report Probe Request frames all the time.
1846 */
1847 ar->probe_req_report = reg;
1848 }
1849}
1850
f80574ae
JM
1851static const struct ieee80211_txrx_stypes
1852ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
1853 [NL80211_IFTYPE_STATION] = {
1854 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1855 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
1856 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1857 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
1858 },
1859 [NL80211_IFTYPE_P2P_CLIENT] = {
1860 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1861 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
1862 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1863 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
1864 },
1865 [NL80211_IFTYPE_P2P_GO] = {
1866 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1867 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
1868 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1869 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
1870 },
1871};
1872
bdcd8170
KV
1873static struct cfg80211_ops ath6kl_cfg80211_ops = {
1874 .change_virtual_intf = ath6kl_cfg80211_change_iface,
1875 .scan = ath6kl_cfg80211_scan,
1876 .connect = ath6kl_cfg80211_connect,
1877 .disconnect = ath6kl_cfg80211_disconnect,
1878 .add_key = ath6kl_cfg80211_add_key,
1879 .get_key = ath6kl_cfg80211_get_key,
1880 .del_key = ath6kl_cfg80211_del_key,
1881 .set_default_key = ath6kl_cfg80211_set_default_key,
1882 .set_wiphy_params = ath6kl_cfg80211_set_wiphy_params,
1883 .set_tx_power = ath6kl_cfg80211_set_txpower,
1884 .get_tx_power = ath6kl_cfg80211_get_txpower,
1885 .set_power_mgmt = ath6kl_cfg80211_set_power_mgmt,
1886 .join_ibss = ath6kl_cfg80211_join_ibss,
1887 .leave_ibss = ath6kl_cfg80211_leave_ibss,
1888 .get_station = ath6kl_get_station,
1889 .set_pmksa = ath6kl_set_pmksa,
1890 .del_pmksa = ath6kl_del_pmksa,
1891 .flush_pmksa = ath6kl_flush_pmksa,
003353b0 1892 CFG80211_TESTMODE_CMD(ath6kl_tm_cmd)
abcb344b
KV
1893#ifdef CONFIG_PM
1894 .suspend = ar6k_cfg80211_suspend,
aa6cffc1 1895 .resume = ar6k_cfg80211_resume,
abcb344b 1896#endif
6a7c9bad
JM
1897 .set_channel = ath6kl_set_channel,
1898 .add_beacon = ath6kl_add_beacon,
1899 .set_beacon = ath6kl_set_beacon,
1900 .del_beacon = ath6kl_del_beacon,
23875136 1901 .change_station = ath6kl_change_station,
63fa1e0c
JM
1902 .remain_on_channel = ath6kl_remain_on_channel,
1903 .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel,
8a6c8060 1904 .mgmt_tx = ath6kl_mgmt_tx,
ae32c30a 1905 .mgmt_frame_register = ath6kl_mgmt_frame_register,
bdcd8170
KV
1906};
1907
1908struct wireless_dev *ath6kl_cfg80211_init(struct device *dev)
1909{
1910 int ret = 0;
1911 struct wireless_dev *wdev;
6bbc7c35 1912 struct ath6kl *ar;
bdcd8170
KV
1913
1914 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
1915 if (!wdev) {
1916 ath6kl_err("couldn't allocate wireless device\n");
1917 return NULL;
1918 }
1919
1920 /* create a new wiphy for use with cfg80211 */
1921 wdev->wiphy = wiphy_new(&ath6kl_cfg80211_ops, sizeof(struct ath6kl));
1922 if (!wdev->wiphy) {
1923 ath6kl_err("couldn't allocate wiphy device\n");
1924 kfree(wdev);
1925 return NULL;
1926 }
1927
6bbc7c35
JM
1928 ar = wiphy_priv(wdev->wiphy);
1929 ar->p2p = !!ath6kl_p2p;
1930
f80574ae
JM
1931 wdev->wiphy->mgmt_stypes = ath6kl_mgmt_stypes;
1932
63fa1e0c
JM
1933 wdev->wiphy->max_remain_on_channel_duration = 5000;
1934
bdcd8170
KV
1935 /* set device pointer for wiphy */
1936 set_wiphy_dev(wdev->wiphy, dev);
1937
1938 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
6e4604c8 1939 BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
6bbc7c35
JM
1940 if (ar->p2p) {
1941 wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_GO) |
1942 BIT(NL80211_IFTYPE_P2P_CLIENT);
1943 }
bdcd8170
KV
1944 /* max num of ssids that can be probed during scanning */
1945 wdev->wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
b84da8c7 1946 wdev->wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
bdcd8170
KV
1947 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
1948 wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz;
1949 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
1950
1951 wdev->wiphy->cipher_suites = cipher_suites;
1952 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
1953
1954 ret = wiphy_register(wdev->wiphy);
1955 if (ret < 0) {
1956 ath6kl_err("couldn't register wiphy device\n");
1957 wiphy_free(wdev->wiphy);
1958 kfree(wdev);
1959 return NULL;
1960 }
1961
1962 return wdev;
1963}
1964
1965void ath6kl_cfg80211_deinit(struct ath6kl *ar)
1966{
1967 struct wireless_dev *wdev = ar->wdev;
1968
1969 if (ar->scan_req) {
1970 cfg80211_scan_done(ar->scan_req, true);
1971 ar->scan_req = NULL;
1972 }
1973
1974 if (!wdev)
1975 return;
1976
1977 wiphy_unregister(wdev->wiphy);
1978 wiphy_free(wdev->wiphy);
1979 kfree(wdev);
1980}