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