brcmfmac: add hostap supoort.
[deliverable/linux.git] / drivers / net / wireless / brcm80211 / brcmfmac / wl_cfg80211.c
CommitLineData
5b435de0
AS
1/*
2 * Copyright (c) 2010 Broadcom Corporation
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17/* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */
18
02f77195
JP
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
5b435de0
AS
21#include <linux/kernel.h>
22#include <linux/if_arp.h>
23#include <linux/sched.h>
24#include <linux/kthread.h>
25#include <linux/netdevice.h>
26#include <linux/bitops.h>
27#include <linux/etherdevice.h>
28#include <linux/ieee80211.h>
29#include <linux/uaccess.h>
30#include <net/cfg80211.h>
cbaa177d 31#include <net/netlink.h>
5b435de0
AS
32
33#include <brcmu_utils.h>
34#include <defs.h>
35#include <brcmu_wifi.h>
36#include "dhd.h"
37#include "wl_cfg80211.h"
38
e5806072
AS
39#define BRCMF_SCAN_IE_LEN_MAX 2048
40#define BRCMF_PNO_VERSION 2
41#define BRCMF_PNO_TIME 30
42#define BRCMF_PNO_REPEAT 4
43#define BRCMF_PNO_FREQ_EXPO_MAX 3
44#define BRCMF_PNO_MAX_PFN_COUNT 16
45#define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6
46#define BRCMF_PNO_HIDDEN_BIT 2
47#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF
48#define BRCMF_PNO_SCAN_COMPLETE 1
49#define BRCMF_PNO_SCAN_INCOMPLETE 0
50
1a873342 51#define TLV_LEN_OFF 1 /* length offset */
04012895 52#define TLV_HDR_LEN 2 /* header length */
1a873342
HM
53#define TLV_BODY_OFF 2 /* body offset */
54#define TLV_OUI_LEN 3 /* oui id length */
55#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */
56#define WPA_OUI_TYPE 1
57#define RSN_OUI "\x00\x0F\xAC" /* RSN OUI */
58#define WME_OUI_TYPE 2
59
60#define VS_IE_FIXED_HDR_LEN 6
61#define WPA_IE_VERSION_LEN 2
62#define WPA_IE_MIN_OUI_LEN 4
63#define WPA_IE_SUITE_COUNT_LEN 2
64
65#define WPA_CIPHER_NONE 0 /* None */
66#define WPA_CIPHER_WEP_40 1 /* WEP (40-bit) */
67#define WPA_CIPHER_TKIP 2 /* TKIP: default for WPA */
68#define WPA_CIPHER_AES_CCM 4 /* AES (CCM) */
69#define WPA_CIPHER_WEP_104 5 /* WEP (104-bit) */
70
71#define RSN_AKM_NONE 0 /* None (IBSS) */
72#define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */
73#define RSN_AKM_PSK 2 /* Pre-shared Key */
74#define RSN_CAP_LEN 2 /* Length of RSN capabilities */
75#define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C
76
77#define VNDR_IE_CMD_LEN 4 /* length of the set command
78 * string :"add", "del" (+ NUL)
79 */
80#define VNDR_IE_COUNT_OFFSET 4
81#define VNDR_IE_PKTFLAG_OFFSET 8
82#define VNDR_IE_VSIE_OFFSET 12
83#define VNDR_IE_HDR_SIZE 12
84#define VNDR_IE_BEACON_FLAG 0x1
85#define VNDR_IE_PRBRSP_FLAG 0x2
86#define MAX_VNDR_IE_NUMBER 5
87
88#define DOT11_MGMT_HDR_LEN 24 /* d11 management header len */
89#define DOT11_BCN_PRB_FIXED_LEN 12 /* beacon/probe fixed length */
04012895 90
5b435de0
AS
91#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
92 (sizeof(struct brcmf_assoc_params_le) - sizeof(u16))
93
94static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
95
96static u32 brcmf_dbg_level = WL_DBG_ERR;
97
5b435de0
AS
98static bool check_sys_up(struct wiphy *wiphy)
99{
100 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
101 if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) {
102 WL_INFO("device is not ready : status (%d)\n",
103 (int)cfg_priv->status);
104 return false;
105 }
106 return true;
107}
108
109#define CHAN2G(_channel, _freq, _flags) { \
110 .band = IEEE80211_BAND_2GHZ, \
111 .center_freq = (_freq), \
112 .hw_value = (_channel), \
113 .flags = (_flags), \
114 .max_antenna_gain = 0, \
115 .max_power = 30, \
116}
117
118#define CHAN5G(_channel, _flags) { \
119 .band = IEEE80211_BAND_5GHZ, \
120 .center_freq = 5000 + (5 * (_channel)), \
121 .hw_value = (_channel), \
122 .flags = (_flags), \
123 .max_antenna_gain = 0, \
124 .max_power = 30, \
125}
126
127#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
128#define RATETAB_ENT(_rateid, _flags) \
129 { \
130 .bitrate = RATE_TO_BASE100KBPS(_rateid), \
131 .hw_value = (_rateid), \
132 .flags = (_flags), \
133 }
134
135static struct ieee80211_rate __wl_rates[] = {
136 RATETAB_ENT(BRCM_RATE_1M, 0),
137 RATETAB_ENT(BRCM_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
138 RATETAB_ENT(BRCM_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
139 RATETAB_ENT(BRCM_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
140 RATETAB_ENT(BRCM_RATE_6M, 0),
141 RATETAB_ENT(BRCM_RATE_9M, 0),
142 RATETAB_ENT(BRCM_RATE_12M, 0),
143 RATETAB_ENT(BRCM_RATE_18M, 0),
144 RATETAB_ENT(BRCM_RATE_24M, 0),
145 RATETAB_ENT(BRCM_RATE_36M, 0),
146 RATETAB_ENT(BRCM_RATE_48M, 0),
147 RATETAB_ENT(BRCM_RATE_54M, 0),
148};
149
150#define wl_a_rates (__wl_rates + 4)
151#define wl_a_rates_size 8
152#define wl_g_rates (__wl_rates + 0)
153#define wl_g_rates_size 12
154
155static struct ieee80211_channel __wl_2ghz_channels[] = {
156 CHAN2G(1, 2412, 0),
157 CHAN2G(2, 2417, 0),
158 CHAN2G(3, 2422, 0),
159 CHAN2G(4, 2427, 0),
160 CHAN2G(5, 2432, 0),
161 CHAN2G(6, 2437, 0),
162 CHAN2G(7, 2442, 0),
163 CHAN2G(8, 2447, 0),
164 CHAN2G(9, 2452, 0),
165 CHAN2G(10, 2457, 0),
166 CHAN2G(11, 2462, 0),
167 CHAN2G(12, 2467, 0),
168 CHAN2G(13, 2472, 0),
169 CHAN2G(14, 2484, 0),
170};
171
172static struct ieee80211_channel __wl_5ghz_a_channels[] = {
173 CHAN5G(34, 0), CHAN5G(36, 0),
174 CHAN5G(38, 0), CHAN5G(40, 0),
175 CHAN5G(42, 0), CHAN5G(44, 0),
176 CHAN5G(46, 0), CHAN5G(48, 0),
177 CHAN5G(52, 0), CHAN5G(56, 0),
178 CHAN5G(60, 0), CHAN5G(64, 0),
179 CHAN5G(100, 0), CHAN5G(104, 0),
180 CHAN5G(108, 0), CHAN5G(112, 0),
181 CHAN5G(116, 0), CHAN5G(120, 0),
182 CHAN5G(124, 0), CHAN5G(128, 0),
183 CHAN5G(132, 0), CHAN5G(136, 0),
184 CHAN5G(140, 0), CHAN5G(149, 0),
185 CHAN5G(153, 0), CHAN5G(157, 0),
186 CHAN5G(161, 0), CHAN5G(165, 0),
187 CHAN5G(184, 0), CHAN5G(188, 0),
188 CHAN5G(192, 0), CHAN5G(196, 0),
189 CHAN5G(200, 0), CHAN5G(204, 0),
190 CHAN5G(208, 0), CHAN5G(212, 0),
191 CHAN5G(216, 0),
192};
193
194static struct ieee80211_channel __wl_5ghz_n_channels[] = {
195 CHAN5G(32, 0), CHAN5G(34, 0),
196 CHAN5G(36, 0), CHAN5G(38, 0),
197 CHAN5G(40, 0), CHAN5G(42, 0),
198 CHAN5G(44, 0), CHAN5G(46, 0),
199 CHAN5G(48, 0), CHAN5G(50, 0),
200 CHAN5G(52, 0), CHAN5G(54, 0),
201 CHAN5G(56, 0), CHAN5G(58, 0),
202 CHAN5G(60, 0), CHAN5G(62, 0),
203 CHAN5G(64, 0), CHAN5G(66, 0),
204 CHAN5G(68, 0), CHAN5G(70, 0),
205 CHAN5G(72, 0), CHAN5G(74, 0),
206 CHAN5G(76, 0), CHAN5G(78, 0),
207 CHAN5G(80, 0), CHAN5G(82, 0),
208 CHAN5G(84, 0), CHAN5G(86, 0),
209 CHAN5G(88, 0), CHAN5G(90, 0),
210 CHAN5G(92, 0), CHAN5G(94, 0),
211 CHAN5G(96, 0), CHAN5G(98, 0),
212 CHAN5G(100, 0), CHAN5G(102, 0),
213 CHAN5G(104, 0), CHAN5G(106, 0),
214 CHAN5G(108, 0), CHAN5G(110, 0),
215 CHAN5G(112, 0), CHAN5G(114, 0),
216 CHAN5G(116, 0), CHAN5G(118, 0),
217 CHAN5G(120, 0), CHAN5G(122, 0),
218 CHAN5G(124, 0), CHAN5G(126, 0),
219 CHAN5G(128, 0), CHAN5G(130, 0),
220 CHAN5G(132, 0), CHAN5G(134, 0),
221 CHAN5G(136, 0), CHAN5G(138, 0),
222 CHAN5G(140, 0), CHAN5G(142, 0),
223 CHAN5G(144, 0), CHAN5G(145, 0),
224 CHAN5G(146, 0), CHAN5G(147, 0),
225 CHAN5G(148, 0), CHAN5G(149, 0),
226 CHAN5G(150, 0), CHAN5G(151, 0),
227 CHAN5G(152, 0), CHAN5G(153, 0),
228 CHAN5G(154, 0), CHAN5G(155, 0),
229 CHAN5G(156, 0), CHAN5G(157, 0),
230 CHAN5G(158, 0), CHAN5G(159, 0),
231 CHAN5G(160, 0), CHAN5G(161, 0),
232 CHAN5G(162, 0), CHAN5G(163, 0),
233 CHAN5G(164, 0), CHAN5G(165, 0),
234 CHAN5G(166, 0), CHAN5G(168, 0),
235 CHAN5G(170, 0), CHAN5G(172, 0),
236 CHAN5G(174, 0), CHAN5G(176, 0),
237 CHAN5G(178, 0), CHAN5G(180, 0),
238 CHAN5G(182, 0), CHAN5G(184, 0),
239 CHAN5G(186, 0), CHAN5G(188, 0),
240 CHAN5G(190, 0), CHAN5G(192, 0),
241 CHAN5G(194, 0), CHAN5G(196, 0),
242 CHAN5G(198, 0), CHAN5G(200, 0),
243 CHAN5G(202, 0), CHAN5G(204, 0),
244 CHAN5G(206, 0), CHAN5G(208, 0),
245 CHAN5G(210, 0), CHAN5G(212, 0),
246 CHAN5G(214, 0), CHAN5G(216, 0),
247 CHAN5G(218, 0), CHAN5G(220, 0),
248 CHAN5G(222, 0), CHAN5G(224, 0),
249 CHAN5G(226, 0), CHAN5G(228, 0),
250};
251
252static struct ieee80211_supported_band __wl_band_2ghz = {
253 .band = IEEE80211_BAND_2GHZ,
254 .channels = __wl_2ghz_channels,
255 .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
256 .bitrates = wl_g_rates,
257 .n_bitrates = wl_g_rates_size,
258};
259
260static struct ieee80211_supported_band __wl_band_5ghz_a = {
261 .band = IEEE80211_BAND_5GHZ,
262 .channels = __wl_5ghz_a_channels,
263 .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
264 .bitrates = wl_a_rates,
265 .n_bitrates = wl_a_rates_size,
266};
267
268static struct ieee80211_supported_band __wl_band_5ghz_n = {
269 .band = IEEE80211_BAND_5GHZ,
270 .channels = __wl_5ghz_n_channels,
271 .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
272 .bitrates = wl_a_rates,
273 .n_bitrates = wl_a_rates_size,
274};
275
276static const u32 __wl_cipher_suites[] = {
277 WLAN_CIPHER_SUITE_WEP40,
278 WLAN_CIPHER_SUITE_WEP104,
279 WLAN_CIPHER_SUITE_TKIP,
280 WLAN_CIPHER_SUITE_CCMP,
281 WLAN_CIPHER_SUITE_AES_CMAC,
282};
283
f8e4b412
AB
284/* tag_ID/length/value_buffer tuple */
285struct brcmf_tlv {
286 u8 id;
287 u8 len;
288 u8 data[1];
289};
290
1a873342
HM
291/* Vendor specific ie. id = 221, oui and type defines exact ie */
292struct brcmf_vs_tlv {
293 u8 id;
294 u8 len;
295 u8 oui[3];
296 u8 oui_type;
297};
298
299struct parsed_vndr_ie_info {
300 u8 *ie_ptr;
301 u32 ie_len; /* total length including id & length field */
302 struct brcmf_vs_tlv vndrie;
303};
304
305struct parsed_vndr_ies {
306 u32 count;
307 struct parsed_vndr_ie_info ie_info[MAX_VNDR_IE_NUMBER];
308};
309
ef6ac17a
AB
310/* Quarter dBm units to mW
311 * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
312 * Table is offset so the last entry is largest mW value that fits in
313 * a u16.
314 */
315
316#define QDBM_OFFSET 153 /* Offset for first entry */
317#define QDBM_TABLE_LEN 40 /* Table size */
318
319/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
320 * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
321 */
322#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */
323
324/* Largest mW value that will round down to the last table entry,
325 * QDBM_OFFSET + QDBM_TABLE_LEN-1.
326 * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) +
327 * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
328 */
329#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */
330
331static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
332/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */
333/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
334/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
335/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
336/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
337/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
338};
339
340static u16 brcmf_qdbm_to_mw(u8 qdbm)
341{
342 uint factor = 1;
343 int idx = qdbm - QDBM_OFFSET;
344
345 if (idx >= QDBM_TABLE_LEN)
346 /* clamp to max u16 mW value */
347 return 0xFFFF;
348
349 /* scale the qdBm index up to the range of the table 0-40
350 * where an offset of 40 qdBm equals a factor of 10 mW.
351 */
352 while (idx < 0) {
353 idx += 40;
354 factor *= 10;
355 }
356
357 /* return the mW value scaled down to the correct factor of 10,
358 * adding in factor/2 to get proper rounding.
359 */
360 return (nqdBm_to_mW_map[idx] + factor / 2) / factor;
361}
362
363static u8 brcmf_mw_to_qdbm(u16 mw)
364{
365 u8 qdbm;
366 int offset;
367 uint mw_uint = mw;
368 uint boundary;
369
370 /* handle boundary case */
371 if (mw_uint <= 1)
372 return 0;
373
374 offset = QDBM_OFFSET;
375
376 /* move mw into the range of the table */
377 while (mw_uint < QDBM_TABLE_LOW_BOUND) {
378 mw_uint *= 10;
379 offset -= 40;
380 }
381
382 for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) {
383 boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] -
384 nqdBm_to_mW_map[qdbm]) / 2;
385 if (mw_uint < boundary)
386 break;
387 }
388
389 qdbm += (u8) offset;
390
391 return qdbm;
392}
393
5b435de0
AS
394/* function for reading/writing a single u32 from/to the dongle */
395static int
396brcmf_exec_dcmd_u32(struct net_device *ndev, u32 cmd, u32 *par)
397{
398 int err;
399 __le32 par_le = cpu_to_le32(*par);
400
401 err = brcmf_exec_dcmd(ndev, cmd, &par_le, sizeof(__le32));
402 *par = le32_to_cpu(par_le);
403
404 return err;
405}
406
f09d0c02
HM
407static s32
408brcmf_dev_iovar_setbuf_bsscfg(struct net_device *ndev, s8 *name,
409 void *param, s32 paramlen,
410 void *buf, s32 buflen, s32 bssidx)
411{
412 s32 err = -ENOMEM;
413 u32 len;
414
415 len = brcmf_c_mkiovar_bsscfg(name, param, paramlen,
416 buf, buflen, bssidx);
417 BUG_ON(!len);
418 if (len > 0)
419 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len);
420 if (err)
421 WL_ERR("error (%d)\n", err);
422
423 return err;
424}
425
426static s32
427brcmf_dev_iovar_getbuf_bsscfg(struct net_device *ndev, s8 *name,
428 void *param, s32 paramlen,
429 void *buf, s32 buflen, s32 bssidx)
430{
431 s32 err = -ENOMEM;
432 u32 len;
433
434 len = brcmf_c_mkiovar_bsscfg(name, param, paramlen,
435 buf, buflen, bssidx);
436 BUG_ON(!len);
437 if (len > 0)
438 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, buf, len);
439 if (err)
440 WL_ERR("error (%d)\n", err);
441
442 return err;
443}
444
5b435de0
AS
445static void convert_key_from_CPU(struct brcmf_wsec_key *key,
446 struct brcmf_wsec_key_le *key_le)
447{
448 key_le->index = cpu_to_le32(key->index);
449 key_le->len = cpu_to_le32(key->len);
450 key_le->algo = cpu_to_le32(key->algo);
451 key_le->flags = cpu_to_le32(key->flags);
452 key_le->rxiv.hi = cpu_to_le32(key->rxiv.hi);
453 key_le->rxiv.lo = cpu_to_le16(key->rxiv.lo);
454 key_le->iv_initialized = cpu_to_le32(key->iv_initialized);
455 memcpy(key_le->data, key->data, sizeof(key->data));
456 memcpy(key_le->ea, key->ea, sizeof(key->ea));
457}
458
f09d0c02
HM
459static int
460send_key_to_dongle(struct brcmf_cfg80211_priv *cfg_priv, s32 bssidx,
461 struct net_device *ndev, struct brcmf_wsec_key *key)
5b435de0
AS
462{
463 int err;
464 struct brcmf_wsec_key_le key_le;
465
466 convert_key_from_CPU(key, &key_le);
f09d0c02
HM
467
468 err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "wsec_key", &key_le,
469 sizeof(key_le),
470 cfg_priv->extra_buf,
471 WL_EXTRA_BUF_MAX, bssidx);
472
5b435de0 473 if (err)
f09d0c02 474 WL_ERR("wsec_key error (%d)\n", err);
5b435de0
AS
475 return err;
476}
477
478static s32
479brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
480 enum nl80211_iftype type, u32 *flags,
481 struct vif_params *params)
482{
483 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
5b435de0 484 s32 infra = 0;
1a873342 485 s32 ap = 0;
5b435de0
AS
486 s32 err = 0;
487
1a873342 488 WL_TRACE("Enter, ndev=%p, type=%d\n", ndev, type);
5b435de0
AS
489
490 switch (type) {
491 case NL80211_IFTYPE_MONITOR:
492 case NL80211_IFTYPE_WDS:
493 WL_ERR("type (%d) : currently we do not support this type\n",
494 type);
495 return -EOPNOTSUPP;
496 case NL80211_IFTYPE_ADHOC:
497 cfg_priv->conf->mode = WL_MODE_IBSS;
498 infra = 0;
499 break;
500 case NL80211_IFTYPE_STATION:
501 cfg_priv->conf->mode = WL_MODE_BSS;
502 infra = 1;
503 break;
1a873342
HM
504 case NL80211_IFTYPE_AP:
505 cfg_priv->conf->mode = WL_MODE_AP;
506 ap = 1;
507 break;
5b435de0
AS
508 default:
509 err = -EINVAL;
510 goto done;
511 }
512
1a873342
HM
513 if (ap) {
514 set_bit(WL_STATUS_AP_CREATING, &cfg_priv->status);
515 if (!cfg_priv->ap_info)
516 cfg_priv->ap_info = kzalloc(sizeof(*cfg_priv->ap_info),
517 GFP_KERNEL);
518 if (!cfg_priv->ap_info) {
519 err = -ENOMEM;
520 goto done;
521 }
522 WL_INFO("IF Type = AP\n");
5b435de0 523 } else {
1a873342
HM
524 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
525 if (err) {
526 WL_ERR("WLC_SET_INFRA error (%d)\n", err);
527 err = -EAGAIN;
528 goto done;
529 }
530 WL_INFO("IF Type = %s\n",
531 (cfg_priv->conf->mode == WL_MODE_IBSS) ?
532 "Adhoc" : "Infra");
5b435de0 533 }
1a873342 534 ndev->ieee80211_ptr->iftype = type;
5b435de0
AS
535
536done:
537 WL_TRACE("Exit\n");
538
539 return err;
540}
541
542static s32 brcmf_dev_intvar_set(struct net_device *ndev, s8 *name, s32 val)
543{
544 s8 buf[BRCMF_DCMD_SMLEN];
545 u32 len;
546 s32 err = 0;
547 __le32 val_le;
548
549 val_le = cpu_to_le32(val);
53a2277d 550 len = brcmf_c_mkiovar(name, (char *)(&val_le), sizeof(val_le), buf,
5b435de0
AS
551 sizeof(buf));
552 BUG_ON(!len);
553
554 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len);
555 if (err)
556 WL_ERR("error (%d)\n", err);
557
558 return err;
559}
560
561static s32
562brcmf_dev_intvar_get(struct net_device *ndev, s8 *name, s32 *retval)
563{
564 union {
565 s8 buf[BRCMF_DCMD_SMLEN];
566 __le32 val;
567 } var;
568 u32 len;
569 u32 data_null;
570 s32 err = 0;
571
572 len =
53a2277d 573 brcmf_c_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
5b435de0
AS
574 sizeof(var.buf));
575 BUG_ON(!len);
576 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, &var, len);
577 if (err)
578 WL_ERR("error (%d)\n", err);
579
580 *retval = le32_to_cpu(var.val);
581
582 return err;
583}
584
f09d0c02
HM
585static s32
586brcmf_dev_intvar_set_bsscfg(struct net_device *ndev, s8 *name, u32 val,
587 s32 bssidx)
588{
589 s8 buf[BRCMF_DCMD_SMLEN];
590 __le32 val_le;
591
592 val_le = cpu_to_le32(val);
593
594 return brcmf_dev_iovar_setbuf_bsscfg(ndev, name, &val_le,
595 sizeof(val_le), buf, sizeof(buf),
596 bssidx);
597}
598
599static s32
600brcmf_dev_intvar_get_bsscfg(struct net_device *ndev, s8 *name, s32 *val,
601 s32 bssidx)
602{
603 s8 buf[BRCMF_DCMD_SMLEN];
604 s32 err;
605 __le32 val_le;
606
607 memset(buf, 0, sizeof(buf));
608 err = brcmf_dev_iovar_getbuf_bsscfg(ndev, name, val, sizeof(*val), buf,
609 sizeof(buf), bssidx);
610 if (err == 0) {
611 memcpy(&val_le, buf, sizeof(val_le));
612 *val = le32_to_cpu(val_le);
613 }
614 return err;
615}
616
617
618/*
619 * For now brcmf_find_bssidx will return 0. Once p2p gets implemented this
620 * should return the ndev matching bssidx.
621 */
622static s32
623brcmf_find_bssidx(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev)
624{
625 return 0;
626}
627
5b435de0
AS
628static void brcmf_set_mpc(struct net_device *ndev, int mpc)
629{
630 s32 err = 0;
631 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
632
633 if (test_bit(WL_STATUS_READY, &cfg_priv->status)) {
634 err = brcmf_dev_intvar_set(ndev, "mpc", mpc);
635 if (err) {
636 WL_ERR("fail to set mpc\n");
637 return;
638 }
639 WL_INFO("MPC : %d\n", mpc);
640 }
641}
642
35aafa9d
HM
643static void brcmf_iscan_prep(struct brcmf_scan_params_le *params_le,
644 struct brcmf_ssid *ssid)
5b435de0
AS
645{
646 memcpy(params_le->bssid, ether_bcast, ETH_ALEN);
647 params_le->bss_type = DOT11_BSSTYPE_ANY;
648 params_le->scan_type = 0;
649 params_le->channel_num = 0;
650 params_le->nprobes = cpu_to_le32(-1);
651 params_le->active_time = cpu_to_le32(-1);
652 params_le->passive_time = cpu_to_le32(-1);
653 params_le->home_time = cpu_to_le32(-1);
654 if (ssid && ssid->SSID_len)
655 memcpy(&params_le->ssid_le, ssid, sizeof(struct brcmf_ssid));
656}
657
658static s32
659brcmf_dev_iovar_setbuf(struct net_device *ndev, s8 * iovar, void *param,
660 s32 paramlen, void *bufptr, s32 buflen)
661{
662 s32 iolen;
663
53a2277d 664 iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
5b435de0
AS
665 BUG_ON(!iolen);
666
667 return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, bufptr, iolen);
668}
669
670static s32
671brcmf_dev_iovar_getbuf(struct net_device *ndev, s8 * iovar, void *param,
672 s32 paramlen, void *bufptr, s32 buflen)
673{
674 s32 iolen;
675
53a2277d 676 iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
5b435de0
AS
677 BUG_ON(!iolen);
678
679 return brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, bufptr, buflen);
680}
681
682static s32
683brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan,
684 struct brcmf_ssid *ssid, u16 action)
685{
686 s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
687 offsetof(struct brcmf_iscan_params_le, params_le);
688 struct brcmf_iscan_params_le *params;
689 s32 err = 0;
690
691 if (ssid && ssid->SSID_len)
692 params_size += sizeof(struct brcmf_ssid);
693 params = kzalloc(params_size, GFP_KERNEL);
694 if (!params)
695 return -ENOMEM;
696 BUG_ON(params_size >= BRCMF_DCMD_SMLEN);
697
35aafa9d 698 brcmf_iscan_prep(&params->params_le, ssid);
5b435de0
AS
699
700 params->version = cpu_to_le32(BRCMF_ISCAN_REQ_VERSION);
701 params->action = cpu_to_le16(action);
702 params->scan_duration = cpu_to_le16(0);
703
704 err = brcmf_dev_iovar_setbuf(iscan->ndev, "iscan", params, params_size,
705 iscan->dcmd_buf, BRCMF_DCMD_SMLEN);
706 if (err) {
707 if (err == -EBUSY)
708 WL_INFO("system busy : iscan canceled\n");
709 else
710 WL_ERR("error (%d)\n", err);
711 }
712
713 kfree(params);
714 return err;
715}
716
717static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv)
718{
719 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
720 struct net_device *ndev = cfg_to_ndev(cfg_priv);
721 struct brcmf_ssid ssid;
66831075 722 __le32 passive_scan;
5b435de0
AS
723 s32 err = 0;
724
725 /* Broadcast scan by default */
726 memset(&ssid, 0, sizeof(ssid));
727
728 iscan->state = WL_ISCAN_STATE_SCANING;
729
66831075 730 passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
5b435de0
AS
731 err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_SET_PASSIVE_SCAN,
732 &passive_scan, sizeof(passive_scan));
733 if (err) {
734 WL_ERR("error (%d)\n", err);
735 return err;
736 }
737 brcmf_set_mpc(ndev, 0);
738 cfg_priv->iscan_kickstart = true;
739 err = brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START);
740 if (err) {
741 brcmf_set_mpc(ndev, 1);
742 cfg_priv->iscan_kickstart = false;
743 return err;
744 }
745 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
746 iscan->timer_on = 1;
747 return err;
748}
749
750static s32
35aafa9d
HM
751brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev,
752 struct cfg80211_scan_request *request,
753 struct cfg80211_ssid *this_ssid)
5b435de0
AS
754{
755 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
756 struct cfg80211_ssid *ssids;
757 struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int;
66831075 758 __le32 passive_scan;
5b435de0
AS
759 bool iscan_req;
760 bool spec_scan;
761 s32 err = 0;
762 u32 SSID_len;
763
764 if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
765 WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status);
766 return -EAGAIN;
767 }
768 if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status)) {
769 WL_ERR("Scanning being aborted : status (%lu)\n",
770 cfg_priv->status);
771 return -EAGAIN;
772 }
773 if (test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
774 WL_ERR("Connecting : status (%lu)\n",
775 cfg_priv->status);
776 return -EAGAIN;
777 }
778
779 iscan_req = false;
780 spec_scan = false;
781 if (request) {
782 /* scan bss */
783 ssids = request->ssids;
784 if (cfg_priv->iscan_on && (!ssids || !ssids->ssid_len))
785 iscan_req = true;
786 } else {
787 /* scan in ibss */
788 /* we don't do iscan in ibss */
789 ssids = this_ssid;
790 }
791
792 cfg_priv->scan_request = request;
793 set_bit(WL_STATUS_SCANNING, &cfg_priv->status);
794 if (iscan_req) {
795 err = brcmf_do_iscan(cfg_priv);
796 if (!err)
797 return err;
798 else
799 goto scan_out;
800 } else {
801 WL_SCAN("ssid \"%s\", ssid_len (%d)\n",
802 ssids->ssid, ssids->ssid_len);
803 memset(&sr->ssid_le, 0, sizeof(sr->ssid_le));
804 SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len);
805 sr->ssid_le.SSID_len = cpu_to_le32(0);
806 if (SSID_len) {
807 memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len);
808 sr->ssid_le.SSID_len = cpu_to_le32(SSID_len);
809 spec_scan = true;
810 } else {
811 WL_SCAN("Broadcast scan\n");
812 }
813
66831075 814 passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
5b435de0
AS
815 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
816 &passive_scan, sizeof(passive_scan));
817 if (err) {
818 WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
819 goto scan_out;
820 }
821 brcmf_set_mpc(ndev, 0);
822 err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le,
823 sizeof(sr->ssid_le));
824 if (err) {
825 if (err == -EBUSY)
826 WL_INFO("system busy : scan for \"%s\" "
827 "canceled\n", sr->ssid_le.SSID);
828 else
829 WL_ERR("WLC_SCAN error (%d)\n", err);
830
831 brcmf_set_mpc(ndev, 1);
832 goto scan_out;
833 }
834 }
835
836 return 0;
837
838scan_out:
839 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
840 cfg_priv->scan_request = NULL;
841 return err;
842}
843
e756af5b
HM
844static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
845 struct cfg80211_scan_request *request)
846{
847 u32 n_ssids;
848 u32 n_channels;
849 s32 i;
850 s32 offset;
029591f3 851 u16 chanspec;
e756af5b
HM
852 u16 channel;
853 struct ieee80211_channel *req_channel;
854 char *ptr;
029591f3 855 struct brcmf_ssid_le ssid_le;
e756af5b
HM
856
857 memcpy(params_le->bssid, ether_bcast, ETH_ALEN);
858 params_le->bss_type = DOT11_BSSTYPE_ANY;
859 params_le->scan_type = 0;
860 params_le->channel_num = 0;
861 params_le->nprobes = cpu_to_le32(-1);
862 params_le->active_time = cpu_to_le32(-1);
863 params_le->passive_time = cpu_to_le32(-1);
864 params_le->home_time = cpu_to_le32(-1);
865 memset(&params_le->ssid_le, 0, sizeof(params_le->ssid_le));
866
867 /* if request is null exit so it will be all channel broadcast scan */
868 if (!request)
869 return;
870
871 n_ssids = request->n_ssids;
872 n_channels = request->n_channels;
873 /* Copy channel array if applicable */
874 WL_SCAN("### List of channelspecs to scan ### %d\n", n_channels);
875 if (n_channels > 0) {
876 for (i = 0; i < n_channels; i++) {
877 chanspec = 0;
878 req_channel = request->channels[i];
879 channel = ieee80211_frequency_to_channel(
880 req_channel->center_freq);
881 if (req_channel->band == IEEE80211_BAND_2GHZ)
882 chanspec |= WL_CHANSPEC_BAND_2G;
883 else
884 chanspec |= WL_CHANSPEC_BAND_5G;
885
886 if (req_channel->flags & IEEE80211_CHAN_NO_HT40) {
887 chanspec |= WL_CHANSPEC_BW_20;
888 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
889 } else {
890 chanspec |= WL_CHANSPEC_BW_40;
891 if (req_channel->flags &
892 IEEE80211_CHAN_NO_HT40PLUS)
893 chanspec |= WL_CHANSPEC_CTL_SB_LOWER;
894 else
895 chanspec |= WL_CHANSPEC_CTL_SB_UPPER;
896 }
897
029591f3 898 chanspec |= (channel & WL_CHANSPEC_CHAN_MASK);
e756af5b 899 WL_SCAN("Chan : %d, Channel spec: %x\n",
029591f3
AS
900 channel, chanspec);
901 params_le->channel_list[i] = cpu_to_le16(chanspec);
e756af5b
HM
902 }
903 } else {
904 WL_SCAN("Scanning all channels\n");
905 }
906 /* Copy ssid array if applicable */
907 WL_SCAN("### List of SSIDs to scan ### %d\n", n_ssids);
908 if (n_ssids > 0) {
909 offset = offsetof(struct brcmf_scan_params_le, channel_list) +
910 n_channels * sizeof(u16);
911 offset = roundup(offset, sizeof(u32));
912 ptr = (char *)params_le + offset;
913 for (i = 0; i < n_ssids; i++) {
029591f3
AS
914 memset(&ssid_le, 0, sizeof(ssid_le));
915 ssid_le.SSID_len =
916 cpu_to_le32(request->ssids[i].ssid_len);
917 memcpy(ssid_le.SSID, request->ssids[i].ssid,
918 request->ssids[i].ssid_len);
919 if (!ssid_le.SSID_len)
e756af5b
HM
920 WL_SCAN("%d: Broadcast scan\n", i);
921 else
922 WL_SCAN("%d: scan for %s size =%d\n", i,
029591f3
AS
923 ssid_le.SSID, ssid_le.SSID_len);
924 memcpy(ptr, &ssid_le, sizeof(ssid_le));
925 ptr += sizeof(ssid_le);
e756af5b
HM
926 }
927 } else {
928 WL_SCAN("Broadcast scan %p\n", request->ssids);
929 if ((request->ssids) && request->ssids->ssid_len) {
930 WL_SCAN("SSID %s len=%d\n", params_le->ssid_le.SSID,
931 request->ssids->ssid_len);
932 params_le->ssid_le.SSID_len =
933 cpu_to_le32(request->ssids->ssid_len);
934 memcpy(&params_le->ssid_le.SSID, request->ssids->ssid,
935 request->ssids->ssid_len);
936 }
937 }
938 /* Adding mask to channel numbers */
939 params_le->channel_num =
940 cpu_to_le32((n_ssids << BRCMF_SCAN_PARAMS_NSSID_SHIFT) |
941 (n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK));
942}
943
944static s32
945brcmf_notify_escan_complete(struct brcmf_cfg80211_priv *cfg_priv,
946 struct net_device *ndev,
947 bool aborted, bool fw_abort)
948{
949 struct brcmf_scan_params_le params_le;
950 struct cfg80211_scan_request *scan_request;
951 s32 err = 0;
952
953 WL_SCAN("Enter\n");
954
955 /* clear scan request, because the FW abort can cause a second call */
956 /* to this functon and might cause a double cfg80211_scan_done */
957 scan_request = cfg_priv->scan_request;
958 cfg_priv->scan_request = NULL;
959
960 if (timer_pending(&cfg_priv->escan_timeout))
961 del_timer_sync(&cfg_priv->escan_timeout);
962
963 if (fw_abort) {
964 /* Do a scan abort to stop the driver's scan engine */
965 WL_SCAN("ABORT scan in firmware\n");
966 memset(&params_le, 0, sizeof(params_le));
967 memcpy(params_le.bssid, ether_bcast, ETH_ALEN);
968 params_le.bss_type = DOT11_BSSTYPE_ANY;
969 params_le.scan_type = 0;
970 params_le.channel_num = cpu_to_le32(1);
971 params_le.nprobes = cpu_to_le32(1);
972 params_le.active_time = cpu_to_le32(-1);
973 params_le.passive_time = cpu_to_le32(-1);
974 params_le.home_time = cpu_to_le32(-1);
975 /* Scan is aborted by setting channel_list[0] to -1 */
976 params_le.channel_list[0] = cpu_to_le16(-1);
977 /* E-Scan (or anyother type) can be aborted by SCAN */
978 err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &params_le,
979 sizeof(params_le));
980 if (err)
981 WL_ERR("Scan abort failed\n");
982 }
e5806072
AS
983 /*
984 * e-scan can be initiated by scheduled scan
985 * which takes precedence.
986 */
987 if (cfg_priv->sched_escan) {
988 WL_SCAN("scheduled scan completed\n");
989 cfg_priv->sched_escan = false;
990 if (!aborted)
991 cfg80211_sched_scan_results(cfg_to_wiphy(cfg_priv));
992 brcmf_set_mpc(ndev, 1);
993 } else if (scan_request) {
e756af5b
HM
994 WL_SCAN("ESCAN Completed scan: %s\n",
995 aborted ? "Aborted" : "Done");
996 cfg80211_scan_done(scan_request, aborted);
997 brcmf_set_mpc(ndev, 1);
998 }
999 if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
1000 WL_ERR("Scan complete while device not scanning\n");
1001 return -EPERM;
1002 }
1003
1004 return err;
1005}
1006
1007static s32
1008brcmf_run_escan(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev,
1009 struct cfg80211_scan_request *request, u16 action)
1010{
1011 s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
1012 offsetof(struct brcmf_escan_params_le, params_le);
1013 struct brcmf_escan_params_le *params;
1014 s32 err = 0;
1015
1016 WL_SCAN("E-SCAN START\n");
1017
1018 if (request != NULL) {
1019 /* Allocate space for populating ssids in struct */
1020 params_size += sizeof(u32) * ((request->n_channels + 1) / 2);
1021
1022 /* Allocate space for populating ssids in struct */
1023 params_size += sizeof(struct brcmf_ssid) * request->n_ssids;
1024 }
1025
1026 params = kzalloc(params_size, GFP_KERNEL);
1027 if (!params) {
1028 err = -ENOMEM;
1029 goto exit;
1030 }
1031 BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN);
1032 brcmf_escan_prep(&params->params_le, request);
1033 params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
1034 params->action = cpu_to_le16(action);
1035 params->sync_id = cpu_to_le16(0x1234);
1036
1037 err = brcmf_dev_iovar_setbuf(ndev, "escan", params, params_size,
1038 cfg_priv->escan_ioctl_buf, BRCMF_DCMD_MEDLEN);
1039 if (err) {
1040 if (err == -EBUSY)
1041 WL_INFO("system busy : escan canceled\n");
1042 else
1043 WL_ERR("error (%d)\n", err);
1044 }
1045
1046 kfree(params);
1047exit:
1048 return err;
1049}
1050
1051static s32
1052brcmf_do_escan(struct brcmf_cfg80211_priv *cfg_priv, struct wiphy *wiphy,
1053 struct net_device *ndev, struct cfg80211_scan_request *request)
1054{
1055 s32 err;
1056 __le32 passive_scan;
1057 struct brcmf_scan_results *results;
1058
1059 WL_SCAN("Enter\n");
1060 cfg_priv->escan_info.ndev = ndev;
1061 cfg_priv->escan_info.wiphy = wiphy;
1062 cfg_priv->escan_info.escan_state = WL_ESCAN_STATE_SCANNING;
1063 passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
1064 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
1065 &passive_scan, sizeof(passive_scan));
1066 if (err) {
1067 WL_ERR("error (%d)\n", err);
1068 return err;
1069 }
1070 brcmf_set_mpc(ndev, 0);
1071 results = (struct brcmf_scan_results *)cfg_priv->escan_info.escan_buf;
1072 results->version = 0;
1073 results->count = 0;
1074 results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE;
1075
1076 err = brcmf_run_escan(cfg_priv, ndev, request, WL_ESCAN_ACTION_START);
1077 if (err)
1078 brcmf_set_mpc(ndev, 1);
1079 return err;
1080}
1081
1082static s32
1083brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
1084 struct cfg80211_scan_request *request,
1085 struct cfg80211_ssid *this_ssid)
1086{
1087 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1088 struct cfg80211_ssid *ssids;
1089 struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int;
1090 __le32 passive_scan;
1091 bool escan_req;
1092 bool spec_scan;
1093 s32 err;
1094 u32 SSID_len;
1095
1096 WL_SCAN("START ESCAN\n");
1097
1098 if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
1099 WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status);
1100 return -EAGAIN;
1101 }
1102 if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status)) {
1103 WL_ERR("Scanning being aborted : status (%lu)\n",
1104 cfg_priv->status);
1105 return -EAGAIN;
1106 }
1107 if (test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
1108 WL_ERR("Connecting : status (%lu)\n",
1109 cfg_priv->status);
1110 return -EAGAIN;
1111 }
1112
1113 /* Arm scan timeout timer */
1114 mod_timer(&cfg_priv->escan_timeout, jiffies +
1115 WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000);
1116
1117 escan_req = false;
1118 if (request) {
1119 /* scan bss */
1120 ssids = request->ssids;
1121 escan_req = true;
1122 } else {
1123 /* scan in ibss */
1124 /* we don't do escan in ibss */
1125 ssids = this_ssid;
1126 }
1127
1128 cfg_priv->scan_request = request;
1129 set_bit(WL_STATUS_SCANNING, &cfg_priv->status);
1130 if (escan_req) {
1131 err = brcmf_do_escan(cfg_priv, wiphy, ndev, request);
1132 if (!err)
1133 return err;
1134 else
1135 goto scan_out;
1136 } else {
1137 WL_SCAN("ssid \"%s\", ssid_len (%d)\n",
1138 ssids->ssid, ssids->ssid_len);
1139 memset(&sr->ssid_le, 0, sizeof(sr->ssid_le));
1140 SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len);
1141 sr->ssid_le.SSID_len = cpu_to_le32(0);
1142 spec_scan = false;
1143 if (SSID_len) {
1144 memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len);
1145 sr->ssid_le.SSID_len = cpu_to_le32(SSID_len);
1146 spec_scan = true;
1147 } else
1148 WL_SCAN("Broadcast scan\n");
1149
1150 passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
1151 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
1152 &passive_scan, sizeof(passive_scan));
1153 if (err) {
1154 WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
1155 goto scan_out;
1156 }
1157 brcmf_set_mpc(ndev, 0);
1158 err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le,
1159 sizeof(sr->ssid_le));
1160 if (err) {
1161 if (err == -EBUSY)
1162 WL_INFO("BUSY: scan for \"%s\" canceled\n",
1163 sr->ssid_le.SSID);
1164 else
1165 WL_ERR("WLC_SCAN error (%d)\n", err);
1166
1167 brcmf_set_mpc(ndev, 1);
1168 goto scan_out;
1169 }
1170 }
1171
1172 return 0;
1173
1174scan_out:
1175 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
1176 if (timer_pending(&cfg_priv->escan_timeout))
1177 del_timer_sync(&cfg_priv->escan_timeout);
1178 cfg_priv->scan_request = NULL;
1179 return err;
1180}
1181
5b435de0 1182static s32
fd014284 1183brcmf_cfg80211_scan(struct wiphy *wiphy,
5b435de0
AS
1184 struct cfg80211_scan_request *request)
1185{
fd014284 1186 struct net_device *ndev = request->wdev->netdev;
e756af5b 1187 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
5b435de0
AS
1188 s32 err = 0;
1189
1190 WL_TRACE("Enter\n");
1191
1192 if (!check_sys_up(wiphy))
1193 return -EIO;
1194
e756af5b
HM
1195 if (cfg_priv->iscan_on)
1196 err = brcmf_cfg80211_iscan(wiphy, ndev, request, NULL);
1197 else if (cfg_priv->escan_on)
1198 err = brcmf_cfg80211_escan(wiphy, ndev, request, NULL);
1199
5b435de0
AS
1200 if (err)
1201 WL_ERR("scan error (%d)\n", err);
1202
1203 WL_TRACE("Exit\n");
1204 return err;
1205}
1206
1207static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold)
1208{
1209 s32 err = 0;
1210
1211 err = brcmf_dev_intvar_set(ndev, "rtsthresh", rts_threshold);
1212 if (err)
1213 WL_ERR("Error (%d)\n", err);
1214
1215 return err;
1216}
1217
1218static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold)
1219{
1220 s32 err = 0;
1221
1222 err = brcmf_dev_intvar_set(ndev, "fragthresh", frag_threshold);
1223 if (err)
1224 WL_ERR("Error (%d)\n", err);
1225
1226 return err;
1227}
1228
1229static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l)
1230{
1231 s32 err = 0;
1232 u32 cmd = (l ? BRCM_SET_LRL : BRCM_SET_SRL);
1233
1234 err = brcmf_exec_dcmd_u32(ndev, cmd, &retry);
1235 if (err) {
1236 WL_ERR("cmd (%d) , error (%d)\n", cmd, err);
1237 return err;
1238 }
1239 return err;
1240}
1241
1242static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1243{
1244 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1245 struct net_device *ndev = cfg_to_ndev(cfg_priv);
1246 s32 err = 0;
1247
1248 WL_TRACE("Enter\n");
1249 if (!check_sys_up(wiphy))
1250 return -EIO;
1251
1252 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
1253 (cfg_priv->conf->rts_threshold != wiphy->rts_threshold)) {
1254 cfg_priv->conf->rts_threshold = wiphy->rts_threshold;
1255 err = brcmf_set_rts(ndev, cfg_priv->conf->rts_threshold);
1256 if (!err)
1257 goto done;
1258 }
1259 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
1260 (cfg_priv->conf->frag_threshold != wiphy->frag_threshold)) {
1261 cfg_priv->conf->frag_threshold = wiphy->frag_threshold;
1262 err = brcmf_set_frag(ndev, cfg_priv->conf->frag_threshold);
1263 if (!err)
1264 goto done;
1265 }
1266 if (changed & WIPHY_PARAM_RETRY_LONG
1267 && (cfg_priv->conf->retry_long != wiphy->retry_long)) {
1268 cfg_priv->conf->retry_long = wiphy->retry_long;
1269 err = brcmf_set_retry(ndev, cfg_priv->conf->retry_long, true);
1270 if (!err)
1271 goto done;
1272 }
1273 if (changed & WIPHY_PARAM_RETRY_SHORT
1274 && (cfg_priv->conf->retry_short != wiphy->retry_short)) {
1275 cfg_priv->conf->retry_short = wiphy->retry_short;
1276 err = brcmf_set_retry(ndev, cfg_priv->conf->retry_short, false);
1277 if (!err)
1278 goto done;
1279 }
1280
1281done:
1282 WL_TRACE("Exit\n");
1283 return err;
1284}
1285
1286static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item)
1287{
1288 switch (item) {
1289 case WL_PROF_SEC:
1290 return &cfg_priv->profile->sec;
1291 case WL_PROF_BSSID:
1292 return &cfg_priv->profile->bssid;
1293 case WL_PROF_SSID:
1294 return &cfg_priv->profile->ssid;
1295 }
1296 WL_ERR("invalid item (%d)\n", item);
1297 return NULL;
1298}
1299
1300static s32
1301brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv,
1302 const struct brcmf_event_msg *e, void *data, s32 item)
1303{
1304 s32 err = 0;
1305 struct brcmf_ssid *ssid;
1306
1307 switch (item) {
1308 case WL_PROF_SSID:
1309 ssid = (struct brcmf_ssid *) data;
1310 memset(cfg_priv->profile->ssid.SSID, 0,
1311 sizeof(cfg_priv->profile->ssid.SSID));
1312 memcpy(cfg_priv->profile->ssid.SSID,
1313 ssid->SSID, ssid->SSID_len);
1314 cfg_priv->profile->ssid.SSID_len = ssid->SSID_len;
1315 break;
1316 case WL_PROF_BSSID:
1317 if (data)
1318 memcpy(cfg_priv->profile->bssid, data, ETH_ALEN);
1319 else
1320 memset(cfg_priv->profile->bssid, 0, ETH_ALEN);
1321 break;
1322 case WL_PROF_SEC:
1323 memcpy(&cfg_priv->profile->sec, data,
1324 sizeof(cfg_priv->profile->sec));
1325 break;
1326 case WL_PROF_BEACONINT:
1327 cfg_priv->profile->beacon_interval = *(u16 *)data;
1328 break;
1329 case WL_PROF_DTIMPERIOD:
1330 cfg_priv->profile->dtim_period = *(u8 *)data;
1331 break;
1332 default:
1333 WL_ERR("unsupported item (%d)\n", item);
1334 err = -EOPNOTSUPP;
1335 break;
1336 }
1337
1338 return err;
1339}
1340
1341static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
1342{
1343 memset(prof, 0, sizeof(*prof));
1344}
1345
1346static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params,
1347 size_t *join_params_size)
1348{
1349 u16 chanspec = 0;
1350
1351 if (ch != 0) {
1352 if (ch <= CH_MAX_2G_CHANNEL)
1353 chanspec |= WL_CHANSPEC_BAND_2G;
1354 else
1355 chanspec |= WL_CHANSPEC_BAND_5G;
1356
1357 chanspec |= WL_CHANSPEC_BW_20;
1358 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
1359
1360 *join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE +
1361 sizeof(u16);
1362
1363 chanspec |= (ch & WL_CHANSPEC_CHAN_MASK);
1364 join_params->params_le.chanspec_list[0] = cpu_to_le16(chanspec);
1365 join_params->params_le.chanspec_num = cpu_to_le32(1);
1366
1367 WL_CONN("join_params->params.chanspec_list[0]= %#X,"
1368 "channel %d, chanspec %#X\n",
1369 chanspec, ch, chanspec);
1370 }
1371}
1372
1373static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv)
1374{
1375 struct net_device *ndev = NULL;
1376 s32 err = 0;
1377
1378 WL_TRACE("Enter\n");
1379
1380 if (cfg_priv->link_up) {
1381 ndev = cfg_to_ndev(cfg_priv);
1382 WL_INFO("Call WLC_DISASSOC to stop excess roaming\n ");
1383 err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, NULL, 0);
1384 if (err)
1385 WL_ERR("WLC_DISASSOC failed (%d)\n", err);
1386 cfg_priv->link_up = false;
1387 }
1388 WL_TRACE("Exit\n");
1389}
1390
1391static s32
1392brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
1393 struct cfg80211_ibss_params *params)
1394{
1395 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1396 struct brcmf_join_params join_params;
1397 size_t join_params_size = 0;
1398 s32 err = 0;
1399 s32 wsec = 0;
1400 s32 bcnprd;
1401 struct brcmf_ssid ssid;
1402
1403 WL_TRACE("Enter\n");
1404 if (!check_sys_up(wiphy))
1405 return -EIO;
1406
1407 if (params->ssid)
1408 WL_CONN("SSID: %s\n", params->ssid);
1409 else {
1410 WL_CONN("SSID: NULL, Not supported\n");
1411 return -EOPNOTSUPP;
1412 }
1413
1414 set_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
1415
1416 if (params->bssid)
040a7831 1417 WL_CONN("BSSID: %pM\n", params->bssid);
5b435de0
AS
1418 else
1419 WL_CONN("No BSSID specified\n");
1420
1421 if (params->channel)
1422 WL_CONN("channel: %d\n", params->channel->center_freq);
1423 else
1424 WL_CONN("no channel specified\n");
1425
1426 if (params->channel_fixed)
1427 WL_CONN("fixed channel required\n");
1428 else
1429 WL_CONN("no fixed channel required\n");
1430
1431 if (params->ie && params->ie_len)
1432 WL_CONN("ie len: %d\n", params->ie_len);
1433 else
1434 WL_CONN("no ie specified\n");
1435
1436 if (params->beacon_interval)
1437 WL_CONN("beacon interval: %d\n", params->beacon_interval);
1438 else
1439 WL_CONN("no beacon interval specified\n");
1440
1441 if (params->basic_rates)
1442 WL_CONN("basic rates: %08X\n", params->basic_rates);
1443 else
1444 WL_CONN("no basic rates specified\n");
1445
1446 if (params->privacy)
1447 WL_CONN("privacy required\n");
1448 else
1449 WL_CONN("no privacy required\n");
1450
1451 /* Configure Privacy for starter */
1452 if (params->privacy)
1453 wsec |= WEP_ENABLED;
1454
1455 err = brcmf_dev_intvar_set(ndev, "wsec", wsec);
1456 if (err) {
1457 WL_ERR("wsec failed (%d)\n", err);
1458 goto done;
1459 }
1460
1461 /* Configure Beacon Interval for starter */
1462 if (params->beacon_interval)
1463 bcnprd = params->beacon_interval;
1464 else
1465 bcnprd = 100;
1466
1467 err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_BCNPRD, &bcnprd);
1468 if (err) {
1469 WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err);
1470 goto done;
1471 }
1472
1473 /* Configure required join parameter */
1474 memset(&join_params, 0, sizeof(struct brcmf_join_params));
1475
1476 /* SSID */
1477 ssid.SSID_len = min_t(u32, params->ssid_len, 32);
1478 memcpy(ssid.SSID, params->ssid, ssid.SSID_len);
1479 memcpy(join_params.ssid_le.SSID, params->ssid, ssid.SSID_len);
1480 join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len);
1481 join_params_size = sizeof(join_params.ssid_le);
1482 brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID);
1483
1484 /* BSSID */
1485 if (params->bssid) {
1486 memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN);
1487 join_params_size = sizeof(join_params.ssid_le) +
1488 BRCMF_ASSOC_PARAMS_FIXED_SIZE;
1489 } else {
1490 memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN);
1491 }
1492
1493 brcmf_update_prof(cfg_priv, NULL,
1494 &join_params.params_le.bssid, WL_PROF_BSSID);
1495
1496 /* Channel */
1497 if (params->channel) {
1498 u32 target_channel;
1499
1500 cfg_priv->channel =
1501 ieee80211_frequency_to_channel(
1502 params->channel->center_freq);
1503 if (params->channel_fixed) {
1504 /* adding chanspec */
1505 brcmf_ch_to_chanspec(cfg_priv->channel,
1506 &join_params, &join_params_size);
1507 }
1508
1509 /* set channel for starter */
1510 target_channel = cfg_priv->channel;
1511 err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_CHANNEL,
1512 &target_channel);
1513 if (err) {
1514 WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err);
1515 goto done;
1516 }
1517 } else
1518 cfg_priv->channel = 0;
1519
1520 cfg_priv->ibss_starter = false;
1521
1522
1523 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID,
1524 &join_params, join_params_size);
1525 if (err) {
1526 WL_ERR("WLC_SET_SSID failed (%d)\n", err);
1527 goto done;
1528 }
1529
1530done:
1531 if (err)
1532 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
1533 WL_TRACE("Exit\n");
1534 return err;
1535}
1536
1537static s32
1538brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
1539{
1540 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1541 s32 err = 0;
1542
1543 WL_TRACE("Enter\n");
1544 if (!check_sys_up(wiphy))
1545 return -EIO;
1546
1547 brcmf_link_down(cfg_priv);
1548
1549 WL_TRACE("Exit\n");
1550
1551 return err;
1552}
1553
1554static s32 brcmf_set_wpa_version(struct net_device *ndev,
1555 struct cfg80211_connect_params *sme)
1556{
1557 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1558 struct brcmf_cfg80211_security *sec;
1559 s32 val = 0;
1560 s32 err = 0;
1561
1562 if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1563 val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
1564 else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1565 val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
1566 else
1567 val = WPA_AUTH_DISABLED;
1568 WL_CONN("setting wpa_auth to 0x%0x\n", val);
1569 err = brcmf_dev_intvar_set(ndev, "wpa_auth", val);
1570 if (err) {
1571 WL_ERR("set wpa_auth failed (%d)\n", err);
1572 return err;
1573 }
1574 sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1575 sec->wpa_versions = sme->crypto.wpa_versions;
1576 return err;
1577}
1578
1579static s32 brcmf_set_auth_type(struct net_device *ndev,
1580 struct cfg80211_connect_params *sme)
1581{
1582 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1583 struct brcmf_cfg80211_security *sec;
1584 s32 val = 0;
1585 s32 err = 0;
1586
1587 switch (sme->auth_type) {
1588 case NL80211_AUTHTYPE_OPEN_SYSTEM:
1589 val = 0;
1590 WL_CONN("open system\n");
1591 break;
1592 case NL80211_AUTHTYPE_SHARED_KEY:
1593 val = 1;
1594 WL_CONN("shared key\n");
1595 break;
1596 case NL80211_AUTHTYPE_AUTOMATIC:
1597 val = 2;
1598 WL_CONN("automatic\n");
1599 break;
1600 case NL80211_AUTHTYPE_NETWORK_EAP:
1601 WL_CONN("network eap\n");
1602 default:
1603 val = 2;
1604 WL_ERR("invalid auth type (%d)\n", sme->auth_type);
1605 break;
1606 }
1607
1608 err = brcmf_dev_intvar_set(ndev, "auth", val);
1609 if (err) {
1610 WL_ERR("set auth failed (%d)\n", err);
1611 return err;
1612 }
1613 sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1614 sec->auth_type = sme->auth_type;
1615 return err;
1616}
1617
1618static s32
1619brcmf_set_set_cipher(struct net_device *ndev,
1620 struct cfg80211_connect_params *sme)
1621{
1622 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1623 struct brcmf_cfg80211_security *sec;
1624 s32 pval = 0;
1625 s32 gval = 0;
1626 s32 err = 0;
1627
1628 if (sme->crypto.n_ciphers_pairwise) {
1629 switch (sme->crypto.ciphers_pairwise[0]) {
1630 case WLAN_CIPHER_SUITE_WEP40:
1631 case WLAN_CIPHER_SUITE_WEP104:
1632 pval = WEP_ENABLED;
1633 break;
1634 case WLAN_CIPHER_SUITE_TKIP:
1635 pval = TKIP_ENABLED;
1636 break;
1637 case WLAN_CIPHER_SUITE_CCMP:
1638 pval = AES_ENABLED;
1639 break;
1640 case WLAN_CIPHER_SUITE_AES_CMAC:
1641 pval = AES_ENABLED;
1642 break;
1643 default:
1644 WL_ERR("invalid cipher pairwise (%d)\n",
1645 sme->crypto.ciphers_pairwise[0]);
1646 return -EINVAL;
1647 }
1648 }
1649 if (sme->crypto.cipher_group) {
1650 switch (sme->crypto.cipher_group) {
1651 case WLAN_CIPHER_SUITE_WEP40:
1652 case WLAN_CIPHER_SUITE_WEP104:
1653 gval = WEP_ENABLED;
1654 break;
1655 case WLAN_CIPHER_SUITE_TKIP:
1656 gval = TKIP_ENABLED;
1657 break;
1658 case WLAN_CIPHER_SUITE_CCMP:
1659 gval = AES_ENABLED;
1660 break;
1661 case WLAN_CIPHER_SUITE_AES_CMAC:
1662 gval = AES_ENABLED;
1663 break;
1664 default:
1665 WL_ERR("invalid cipher group (%d)\n",
1666 sme->crypto.cipher_group);
1667 return -EINVAL;
1668 }
1669 }
1670
1671 WL_CONN("pval (%d) gval (%d)\n", pval, gval);
1672 err = brcmf_dev_intvar_set(ndev, "wsec", pval | gval);
1673 if (err) {
1674 WL_ERR("error (%d)\n", err);
1675 return err;
1676 }
1677
1678 sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1679 sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
1680 sec->cipher_group = sme->crypto.cipher_group;
1681
1682 return err;
1683}
1684
1685static s32
1686brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
1687{
1688 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1689 struct brcmf_cfg80211_security *sec;
1690 s32 val = 0;
1691 s32 err = 0;
1692
1693 if (sme->crypto.n_akm_suites) {
1694 err = brcmf_dev_intvar_get(ndev, "wpa_auth", &val);
1695 if (err) {
1696 WL_ERR("could not get wpa_auth (%d)\n", err);
1697 return err;
1698 }
1699 if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
1700 switch (sme->crypto.akm_suites[0]) {
1701 case WLAN_AKM_SUITE_8021X:
1702 val = WPA_AUTH_UNSPECIFIED;
1703 break;
1704 case WLAN_AKM_SUITE_PSK:
1705 val = WPA_AUTH_PSK;
1706 break;
1707 default:
1708 WL_ERR("invalid cipher group (%d)\n",
1709 sme->crypto.cipher_group);
1710 return -EINVAL;
1711 }
1712 } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
1713 switch (sme->crypto.akm_suites[0]) {
1714 case WLAN_AKM_SUITE_8021X:
1715 val = WPA2_AUTH_UNSPECIFIED;
1716 break;
1717 case WLAN_AKM_SUITE_PSK:
1718 val = WPA2_AUTH_PSK;
1719 break;
1720 default:
1721 WL_ERR("invalid cipher group (%d)\n",
1722 sme->crypto.cipher_group);
1723 return -EINVAL;
1724 }
1725 }
1726
1727 WL_CONN("setting wpa_auth to %d\n", val);
1728 err = brcmf_dev_intvar_set(ndev, "wpa_auth", val);
1729 if (err) {
1730 WL_ERR("could not set wpa_auth (%d)\n", err);
1731 return err;
1732 }
1733 }
1734 sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1735 sec->wpa_auth = sme->crypto.akm_suites[0];
1736
1737 return err;
1738}
1739
1740static s32
f09d0c02
HM
1741brcmf_set_sharedkey(struct net_device *ndev,
1742 struct cfg80211_connect_params *sme)
5b435de0
AS
1743{
1744 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1745 struct brcmf_cfg80211_security *sec;
1746 struct brcmf_wsec_key key;
1747 s32 val;
1748 s32 err = 0;
f09d0c02 1749 s32 bssidx;
5b435de0
AS
1750
1751 WL_CONN("key len (%d)\n", sme->key_len);
5b435de0 1752
a718e2fe
RV
1753 if (sme->key_len == 0)
1754 return 0;
1755
1756 sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1757 WL_CONN("wpa_versions 0x%x cipher_pairwise 0x%x\n",
1758 sec->wpa_versions, sec->cipher_pairwise);
1759
1760 if (sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))
1761 return 0;
1762
f09d0c02
HM
1763 if (!(sec->cipher_pairwise &
1764 (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104)))
1765 return 0;
a718e2fe 1766
f09d0c02
HM
1767 memset(&key, 0, sizeof(key));
1768 key.len = (u32) sme->key_len;
1769 key.index = (u32) sme->key_idx;
1770 if (key.len > sizeof(key.data)) {
1771 WL_ERR("Too long key length (%u)\n", key.len);
1772 return -EINVAL;
1773 }
1774 memcpy(key.data, sme->key, key.len);
1775 key.flags = BRCMF_PRIMARY_KEY;
1776 switch (sec->cipher_pairwise) {
1777 case WLAN_CIPHER_SUITE_WEP40:
1778 key.algo = CRYPTO_ALGO_WEP1;
1779 break;
1780 case WLAN_CIPHER_SUITE_WEP104:
1781 key.algo = CRYPTO_ALGO_WEP128;
1782 break;
1783 default:
1784 WL_ERR("Invalid algorithm (%d)\n",
1785 sme->crypto.ciphers_pairwise[0]);
1786 return -EINVAL;
1787 }
1788 /* Set the new key/index */
1789 WL_CONN("key length (%d) key index (%d) algo (%d)\n",
1790 key.len, key.index, key.algo);
1791 WL_CONN("key \"%s\"\n", key.data);
1792 bssidx = brcmf_find_bssidx(cfg_priv, ndev);
1793 err = send_key_to_dongle(cfg_priv, bssidx, ndev, &key);
1794 if (err)
1795 return err;
1796
1797 if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
1798 WL_CONN("set auth_type to shared key\n");
1799 val = WL_AUTH_SHARED_KEY; /* shared key */
1800 err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", val, bssidx);
1801 if (err)
1802 WL_ERR("set auth failed (%d)\n", err);
5b435de0
AS
1803 }
1804 return err;
1805}
1806
1807static s32
1808brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
1809 struct cfg80211_connect_params *sme)
1810{
1811 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1812 struct ieee80211_channel *chan = sme->channel;
1813 struct brcmf_join_params join_params;
1814 size_t join_params_size;
1815 struct brcmf_ssid ssid;
1816
1817 s32 err = 0;
1818
1819 WL_TRACE("Enter\n");
1820 if (!check_sys_up(wiphy))
1821 return -EIO;
1822
1823 if (!sme->ssid) {
1824 WL_ERR("Invalid ssid\n");
1825 return -EOPNOTSUPP;
1826 }
1827
1828 set_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
1829
1830 if (chan) {
1831 cfg_priv->channel =
1832 ieee80211_frequency_to_channel(chan->center_freq);
1833 WL_CONN("channel (%d), center_req (%d)\n",
1834 cfg_priv->channel, chan->center_freq);
1835 } else
1836 cfg_priv->channel = 0;
1837
1838 WL_INFO("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);
1839
1840 err = brcmf_set_wpa_version(ndev, sme);
1841 if (err) {
1842 WL_ERR("wl_set_wpa_version failed (%d)\n", err);
1843 goto done;
1844 }
1845
1846 err = brcmf_set_auth_type(ndev, sme);
1847 if (err) {
1848 WL_ERR("wl_set_auth_type failed (%d)\n", err);
1849 goto done;
1850 }
1851
1852 err = brcmf_set_set_cipher(ndev, sme);
1853 if (err) {
1854 WL_ERR("wl_set_set_cipher failed (%d)\n", err);
1855 goto done;
1856 }
1857
1858 err = brcmf_set_key_mgmt(ndev, sme);
1859 if (err) {
1860 WL_ERR("wl_set_key_mgmt failed (%d)\n", err);
1861 goto done;
1862 }
1863
f09d0c02 1864 err = brcmf_set_sharedkey(ndev, sme);
5b435de0 1865 if (err) {
f09d0c02 1866 WL_ERR("brcmf_set_sharedkey failed (%d)\n", err);
5b435de0
AS
1867 goto done;
1868 }
1869
1870 memset(&join_params, 0, sizeof(join_params));
1871 join_params_size = sizeof(join_params.ssid_le);
1872
2315992c 1873 ssid.SSID_len = min_t(u32, sizeof(ssid.SSID), (u32)sme->ssid_len);
5b435de0
AS
1874 memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid.SSID_len);
1875 memcpy(&ssid.SSID, sme->ssid, ssid.SSID_len);
1876 join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len);
1877 brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID);
1878
1879 memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN);
1880
1881 if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN)
1882 WL_CONN("ssid \"%s\", len (%d)\n",
1883 ssid.SSID, ssid.SSID_len);
1884
1885 brcmf_ch_to_chanspec(cfg_priv->channel,
1886 &join_params, &join_params_size);
1887 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID,
1888 &join_params, join_params_size);
1889 if (err)
1890 WL_ERR("WLC_SET_SSID failed (%d)\n", err);
1891
1892done:
1893 if (err)
1894 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
1895 WL_TRACE("Exit\n");
1896 return err;
1897}
1898
1899static s32
1900brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,
1901 u16 reason_code)
1902{
1903 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1904 struct brcmf_scb_val_le scbval;
1905 s32 err = 0;
1906
1907 WL_TRACE("Enter. Reason code = %d\n", reason_code);
1908 if (!check_sys_up(wiphy))
1909 return -EIO;
1910
1911 clear_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
1912
1913 memcpy(&scbval.ea, brcmf_read_prof(cfg_priv, WL_PROF_BSSID), ETH_ALEN);
1914 scbval.val = cpu_to_le32(reason_code);
1915 err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, &scbval,
1916 sizeof(struct brcmf_scb_val_le));
1917 if (err)
1918 WL_ERR("error (%d)\n", err);
1919
1920 cfg_priv->link_up = false;
1921
1922 WL_TRACE("Exit\n");
1923 return err;
1924}
1925
1926static s32
1927brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
d3f31134 1928 enum nl80211_tx_power_setting type, s32 mbm)
5b435de0
AS
1929{
1930
1931 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1932 struct net_device *ndev = cfg_to_ndev(cfg_priv);
1933 u16 txpwrmw;
1934 s32 err = 0;
1935 s32 disable = 0;
d3f31134 1936 s32 dbm = MBM_TO_DBM(mbm);
5b435de0
AS
1937
1938 WL_TRACE("Enter\n");
1939 if (!check_sys_up(wiphy))
1940 return -EIO;
1941
1942 switch (type) {
1943 case NL80211_TX_POWER_AUTOMATIC:
1944 break;
1945 case NL80211_TX_POWER_LIMITED:
5b435de0
AS
1946 case NL80211_TX_POWER_FIXED:
1947 if (dbm < 0) {
1948 WL_ERR("TX_POWER_FIXED - dbm is negative\n");
1949 err = -EINVAL;
1950 goto done;
1951 }
1952 break;
1953 }
1954 /* Make sure radio is off or on as far as software is concerned */
1955 disable = WL_RADIO_SW_DISABLE << 16;
1956 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_RADIO, &disable);
1957 if (err)
1958 WL_ERR("WLC_SET_RADIO error (%d)\n", err);
1959
1960 if (dbm > 0xffff)
1961 txpwrmw = 0xffff;
1962 else
1963 txpwrmw = (u16) dbm;
1964 err = brcmf_dev_intvar_set(ndev, "qtxpower",
ef6ac17a 1965 (s32) (brcmf_mw_to_qdbm(txpwrmw)));
5b435de0
AS
1966 if (err)
1967 WL_ERR("qtxpower error (%d)\n", err);
1968 cfg_priv->conf->tx_power = dbm;
1969
1970done:
1971 WL_TRACE("Exit\n");
1972 return err;
1973}
1974
1975static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
1976{
1977 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1978 struct net_device *ndev = cfg_to_ndev(cfg_priv);
1979 s32 txpwrdbm;
1980 u8 result;
1981 s32 err = 0;
1982
1983 WL_TRACE("Enter\n");
1984 if (!check_sys_up(wiphy))
1985 return -EIO;
1986
1987 err = brcmf_dev_intvar_get(ndev, "qtxpower", &txpwrdbm);
1988 if (err) {
1989 WL_ERR("error (%d)\n", err);
1990 goto done;
1991 }
1992
1993 result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
ef6ac17a 1994 *dbm = (s32) brcmf_qdbm_to_mw(result);
5b435de0
AS
1995
1996done:
1997 WL_TRACE("Exit\n");
1998 return err;
1999}
2000
2001static s32
2002brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
2003 u8 key_idx, bool unicast, bool multicast)
2004{
f09d0c02 2005 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
5b435de0
AS
2006 u32 index;
2007 u32 wsec;
2008 s32 err = 0;
f09d0c02 2009 s32 bssidx;
5b435de0
AS
2010
2011 WL_TRACE("Enter\n");
2012 WL_CONN("key index (%d)\n", key_idx);
2013 if (!check_sys_up(wiphy))
2014 return -EIO;
2015
f09d0c02
HM
2016 bssidx = brcmf_find_bssidx(cfg_priv, ndev);
2017 err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx);
5b435de0
AS
2018 if (err) {
2019 WL_ERR("WLC_GET_WSEC error (%d)\n", err);
2020 goto done;
2021 }
2022
2023 if (wsec & WEP_ENABLED) {
2024 /* Just select a new current key */
2025 index = key_idx;
2026 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_KEY_PRIMARY,
2027 &index);
2028 if (err)
2029 WL_ERR("error (%d)\n", err);
2030 }
2031done:
2032 WL_TRACE("Exit\n");
2033 return err;
2034}
2035
2036static s32
2037brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
2038 u8 key_idx, const u8 *mac_addr, struct key_params *params)
2039{
f09d0c02 2040 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
5b435de0
AS
2041 struct brcmf_wsec_key key;
2042 struct brcmf_wsec_key_le key_le;
2043 s32 err = 0;
f09d0c02 2044 s32 bssidx;
5b435de0
AS
2045
2046 memset(&key, 0, sizeof(key));
2047 key.index = (u32) key_idx;
2048 /* Instead of bcast for ea address for default wep keys,
2049 driver needs it to be Null */
2050 if (!is_multicast_ether_addr(mac_addr))
2051 memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN);
2052 key.len = (u32) params->key_len;
f09d0c02 2053 bssidx = brcmf_find_bssidx(cfg_priv, ndev);
5b435de0
AS
2054 /* check for key index change */
2055 if (key.len == 0) {
2056 /* key delete */
f09d0c02 2057 err = send_key_to_dongle(cfg_priv, bssidx, ndev, &key);
5b435de0 2058 if (err)
f09d0c02 2059 WL_ERR("key delete error (%d)\n", err);
5b435de0
AS
2060 } else {
2061 if (key.len > sizeof(key.data)) {
2062 WL_ERR("Invalid key length (%d)\n", key.len);
2063 return -EINVAL;
2064 }
2065
2066 WL_CONN("Setting the key index %d\n", key.index);
2067 memcpy(key.data, params->key, key.len);
2068
2069 if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
2070 u8 keybuf[8];
2071 memcpy(keybuf, &key.data[24], sizeof(keybuf));
2072 memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
2073 memcpy(&key.data[16], keybuf, sizeof(keybuf));
2074 }
2075
2076 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
2077 if (params->seq && params->seq_len == 6) {
2078 /* rx iv */
2079 u8 *ivptr;
2080 ivptr = (u8 *) params->seq;
2081 key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
2082 (ivptr[3] << 8) | ivptr[2];
2083 key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
2084 key.iv_initialized = true;
2085 }
2086
2087 switch (params->cipher) {
2088 case WLAN_CIPHER_SUITE_WEP40:
2089 key.algo = CRYPTO_ALGO_WEP1;
2090 WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
2091 break;
2092 case WLAN_CIPHER_SUITE_WEP104:
2093 key.algo = CRYPTO_ALGO_WEP128;
2094 WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
2095 break;
2096 case WLAN_CIPHER_SUITE_TKIP:
2097 key.algo = CRYPTO_ALGO_TKIP;
2098 WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
2099 break;
2100 case WLAN_CIPHER_SUITE_AES_CMAC:
2101 key.algo = CRYPTO_ALGO_AES_CCM;
2102 WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
2103 break;
2104 case WLAN_CIPHER_SUITE_CCMP:
2105 key.algo = CRYPTO_ALGO_AES_CCM;
2106 WL_CONN("WLAN_CIPHER_SUITE_CCMP\n");
2107 break;
2108 default:
2109 WL_ERR("Invalid cipher (0x%x)\n", params->cipher);
2110 return -EINVAL;
2111 }
2112 convert_key_from_CPU(&key, &key_le);
2113
2114 brcmf_netdev_wait_pend8021x(ndev);
f09d0c02
HM
2115 err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "wsec_key", &key_le,
2116 sizeof(key_le),
2117 cfg_priv->extra_buf,
2118 WL_EXTRA_BUF_MAX, bssidx);
2119 if (err)
2120 WL_ERR("wsec_key error (%d)\n", err);
5b435de0
AS
2121 }
2122 return err;
2123}
2124
2125static s32
2126brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
2127 u8 key_idx, bool pairwise, const u8 *mac_addr,
2128 struct key_params *params)
2129{
f09d0c02 2130 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
5b435de0
AS
2131 struct brcmf_wsec_key key;
2132 s32 val;
2133 s32 wsec;
2134 s32 err = 0;
2135 u8 keybuf[8];
f09d0c02 2136 s32 bssidx;
5b435de0
AS
2137
2138 WL_TRACE("Enter\n");
2139 WL_CONN("key index (%d)\n", key_idx);
2140 if (!check_sys_up(wiphy))
2141 return -EIO;
2142
2143 if (mac_addr) {
2144 WL_TRACE("Exit");
2145 return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params);
2146 }
2147 memset(&key, 0, sizeof(key));
2148
2149 key.len = (u32) params->key_len;
2150 key.index = (u32) key_idx;
2151
2152 if (key.len > sizeof(key.data)) {
2153 WL_ERR("Too long key length (%u)\n", key.len);
2154 err = -EINVAL;
2155 goto done;
2156 }
2157 memcpy(key.data, params->key, key.len);
2158
2159 key.flags = BRCMF_PRIMARY_KEY;
2160 switch (params->cipher) {
2161 case WLAN_CIPHER_SUITE_WEP40:
2162 key.algo = CRYPTO_ALGO_WEP1;
f09d0c02 2163 val = WEP_ENABLED;
5b435de0
AS
2164 WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
2165 break;
2166 case WLAN_CIPHER_SUITE_WEP104:
2167 key.algo = CRYPTO_ALGO_WEP128;
f09d0c02 2168 val = WEP_ENABLED;
5b435de0
AS
2169 WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
2170 break;
2171 case WLAN_CIPHER_SUITE_TKIP:
1a873342
HM
2172 if (cfg_priv->conf->mode != WL_MODE_AP) {
2173 WL_CONN("Swapping key\n");
2174 memcpy(keybuf, &key.data[24], sizeof(keybuf));
2175 memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
2176 memcpy(&key.data[16], keybuf, sizeof(keybuf));
2177 }
5b435de0 2178 key.algo = CRYPTO_ALGO_TKIP;
f09d0c02 2179 val = TKIP_ENABLED;
5b435de0
AS
2180 WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
2181 break;
2182 case WLAN_CIPHER_SUITE_AES_CMAC:
2183 key.algo = CRYPTO_ALGO_AES_CCM;
f09d0c02 2184 val = AES_ENABLED;
5b435de0
AS
2185 WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
2186 break;
2187 case WLAN_CIPHER_SUITE_CCMP:
2188 key.algo = CRYPTO_ALGO_AES_CCM;
f09d0c02 2189 val = AES_ENABLED;
5b435de0
AS
2190 WL_CONN("WLAN_CIPHER_SUITE_CCMP\n");
2191 break;
2192 default:
2193 WL_ERR("Invalid cipher (0x%x)\n", params->cipher);
2194 err = -EINVAL;
2195 goto done;
2196 }
2197
f09d0c02
HM
2198 bssidx = brcmf_find_bssidx(cfg_priv, ndev);
2199 err = send_key_to_dongle(cfg_priv, bssidx, ndev, &key);
5b435de0
AS
2200 if (err)
2201 goto done;
2202
f09d0c02 2203 err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx);
5b435de0
AS
2204 if (err) {
2205 WL_ERR("get wsec error (%d)\n", err);
2206 goto done;
2207 }
5b435de0 2208 wsec |= val;
f09d0c02 2209 err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", wsec, bssidx);
5b435de0
AS
2210 if (err) {
2211 WL_ERR("set wsec error (%d)\n", err);
2212 goto done;
2213 }
2214
5b435de0
AS
2215done:
2216 WL_TRACE("Exit\n");
2217 return err;
2218}
2219
2220static s32
2221brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
2222 u8 key_idx, bool pairwise, const u8 *mac_addr)
2223{
f09d0c02 2224 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
5b435de0
AS
2225 struct brcmf_wsec_key key;
2226 s32 err = 0;
f09d0c02 2227 s32 bssidx;
5b435de0
AS
2228
2229 WL_TRACE("Enter\n");
2230 if (!check_sys_up(wiphy))
2231 return -EIO;
2232
2233 memset(&key, 0, sizeof(key));
2234
2235 key.index = (u32) key_idx;
2236 key.flags = BRCMF_PRIMARY_KEY;
2237 key.algo = CRYPTO_ALGO_OFF;
2238
2239 WL_CONN("key index (%d)\n", key_idx);
2240
2241 /* Set the new key/index */
f09d0c02
HM
2242 bssidx = brcmf_find_bssidx(cfg_priv, ndev);
2243 err = send_key_to_dongle(cfg_priv, bssidx, ndev, &key);
5b435de0
AS
2244 if (err) {
2245 if (err == -EINVAL) {
2246 if (key.index >= DOT11_MAX_DEFAULT_KEYS)
2247 /* we ignore this key index in this case */
2248 WL_ERR("invalid key index (%d)\n", key_idx);
2249 }
2250 /* Ignore this error, may happen during DISASSOC */
2251 err = -EAGAIN;
5b435de0
AS
2252 }
2253
5b435de0
AS
2254 WL_TRACE("Exit\n");
2255 return err;
2256}
2257
2258static s32
2259brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
2260 u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
2261 void (*callback) (void *cookie, struct key_params * params))
2262{
2263 struct key_params params;
2264 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2265 struct brcmf_cfg80211_security *sec;
2266 s32 wsec;
2267 s32 err = 0;
f09d0c02 2268 s32 bssidx;
5b435de0
AS
2269
2270 WL_TRACE("Enter\n");
2271 WL_CONN("key index (%d)\n", key_idx);
2272 if (!check_sys_up(wiphy))
2273 return -EIO;
2274
2275 memset(&params, 0, sizeof(params));
2276
f09d0c02
HM
2277 bssidx = brcmf_find_bssidx(cfg_priv, ndev);
2278 err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx);
5b435de0
AS
2279 if (err) {
2280 WL_ERR("WLC_GET_WSEC error (%d)\n", err);
2281 /* Ignore this error, may happen during DISASSOC */
2282 err = -EAGAIN;
2283 goto done;
2284 }
f09d0c02 2285 switch (wsec & ~SES_OW_ENABLED) {
5b435de0
AS
2286 case WEP_ENABLED:
2287 sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
2288 if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
2289 params.cipher = WLAN_CIPHER_SUITE_WEP40;
2290 WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
2291 } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
2292 params.cipher = WLAN_CIPHER_SUITE_WEP104;
2293 WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
2294 }
2295 break;
2296 case TKIP_ENABLED:
2297 params.cipher = WLAN_CIPHER_SUITE_TKIP;
2298 WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
2299 break;
2300 case AES_ENABLED:
2301 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
2302 WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
2303 break;
2304 default:
2305 WL_ERR("Invalid algo (0x%x)\n", wsec);
2306 err = -EINVAL;
2307 goto done;
2308 }
2309 callback(cookie, &params);
2310
2311done:
2312 WL_TRACE("Exit\n");
2313 return err;
2314}
2315
2316static s32
2317brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
2318 struct net_device *ndev, u8 key_idx)
2319{
2320 WL_INFO("Not supported\n");
2321
2322 return -EOPNOTSUPP;
2323}
2324
2325static s32
2326brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
1a873342 2327 u8 *mac, struct station_info *sinfo)
5b435de0
AS
2328{
2329 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2330 struct brcmf_scb_val_le scb_val;
2331 int rssi;
2332 s32 rate;
2333 s32 err = 0;
2334 u8 *bssid = brcmf_read_prof(cfg_priv, WL_PROF_BSSID);
1a873342 2335 struct brcmf_sta_info_le *sta_info_le;
5b435de0 2336
1a873342 2337 WL_TRACE("Enter, MAC %pM\n", mac);
5b435de0
AS
2338 if (!check_sys_up(wiphy))
2339 return -EIO;
2340
1a873342
HM
2341 if (cfg_priv->conf->mode == WL_MODE_AP) {
2342 err = brcmf_dev_iovar_getbuf(ndev, "sta_info", mac, ETH_ALEN,
2343 cfg_priv->dcmd_buf,
2344 WL_DCMD_LEN_MAX);
2345 if (err < 0) {
2346 WL_ERR("GET STA INFO failed, %d\n", err);
2347 goto done;
2348 }
2349 sta_info_le = (struct brcmf_sta_info_le *)cfg_priv->dcmd_buf;
5b435de0 2350
1a873342
HM
2351 sinfo->filled = STATION_INFO_INACTIVE_TIME;
2352 sinfo->inactive_time = le32_to_cpu(sta_info_le->idle) * 1000;
2353 if (le32_to_cpu(sta_info_le->flags) & BRCMF_STA_ASSOC) {
2354 sinfo->filled |= STATION_INFO_CONNECTED_TIME;
2355 sinfo->connected_time = le32_to_cpu(sta_info_le->in);
2356 }
2357 WL_TRACE("STA idle time : %d ms, connected time :%d sec\n",
2358 sinfo->inactive_time, sinfo->connected_time);
2359 } else if (cfg_priv->conf->mode == WL_MODE_BSS) {
2360 if (memcmp(mac, bssid, ETH_ALEN)) {
2361 WL_ERR("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n",
2362 mac, bssid);
2363 err = -ENOENT;
2364 goto done;
2365 }
2366 /* Report the current tx rate */
2367 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_RATE, &rate);
7f6c562d 2368 if (err) {
1a873342
HM
2369 WL_ERR("Could not get rate (%d)\n", err);
2370 goto done;
7f6c562d 2371 } else {
1a873342
HM
2372 sinfo->filled |= STATION_INFO_TX_BITRATE;
2373 sinfo->txrate.legacy = rate * 5;
2374 WL_CONN("Rate %d Mbps\n", rate / 2);
7f6c562d 2375 }
5b435de0 2376
1a873342
HM
2377 if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) {
2378 memset(&scb_val, 0, sizeof(scb_val));
2379 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val,
2380 sizeof(scb_val));
2381 if (err) {
2382 WL_ERR("Could not get rssi (%d)\n", err);
2383 goto done;
2384 } else {
2385 rssi = le32_to_cpu(scb_val.val);
2386 sinfo->filled |= STATION_INFO_SIGNAL;
2387 sinfo->signal = rssi;
2388 WL_CONN("RSSI %d dBm\n", rssi);
2389 }
2390 }
2391 } else
2392 err = -EPERM;
5b435de0
AS
2393done:
2394 WL_TRACE("Exit\n");
2395 return err;
2396}
2397
2398static s32
2399brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
2400 bool enabled, s32 timeout)
2401{
2402 s32 pm;
2403 s32 err = 0;
2404 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2405
2406 WL_TRACE("Enter\n");
2407
2408 /*
2409 * Powersave enable/disable request is coming from the
2410 * cfg80211 even before the interface is up. In that
2411 * scenario, driver will be storing the power save
2412 * preference in cfg_priv struct to apply this to
2413 * FW later while initializing the dongle
2414 */
2415 cfg_priv->pwr_save = enabled;
2416 if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) {
2417
2418 WL_INFO("Device is not ready,"
2419 "storing the value in cfg_priv struct\n");
2420 goto done;
2421 }
2422
2423 pm = enabled ? PM_FAST : PM_OFF;
2424 WL_INFO("power save %s\n", (pm ? "enabled" : "disabled"));
2425
2426 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &pm);
2427 if (err) {
2428 if (err == -ENODEV)
2429 WL_ERR("net_device is not ready yet\n");
2430 else
2431 WL_ERR("error (%d)\n", err);
2432 }
2433done:
2434 WL_TRACE("Exit\n");
2435 return err;
2436}
2437
2438static s32
2439brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev,
2440 const u8 *addr,
2441 const struct cfg80211_bitrate_mask *mask)
2442{
2443 struct brcm_rateset_le rateset_le;
2444 s32 rate;
2445 s32 val;
2446 s32 err_bg;
2447 s32 err_a;
2448 u32 legacy;
2449 s32 err = 0;
2450
2451 WL_TRACE("Enter\n");
2452 if (!check_sys_up(wiphy))
2453 return -EIO;
2454
2455 /* addr param is always NULL. ignore it */
2456 /* Get current rateset */
2457 err = brcmf_exec_dcmd(ndev, BRCM_GET_CURR_RATESET, &rateset_le,
2458 sizeof(rateset_le));
2459 if (err) {
2460 WL_ERR("could not get current rateset (%d)\n", err);
2461 goto done;
2462 }
2463
2464 legacy = ffs(mask->control[IEEE80211_BAND_2GHZ].legacy & 0xFFFF);
2465 if (!legacy)
2466 legacy = ffs(mask->control[IEEE80211_BAND_5GHZ].legacy &
2467 0xFFFF);
2468
2469 val = wl_g_rates[legacy - 1].bitrate * 100000;
2470
2471 if (val < le32_to_cpu(rateset_le.count))
2472 /* Select rate by rateset index */
2473 rate = rateset_le.rates[val] & 0x7f;
2474 else
2475 /* Specified rate in bps */
2476 rate = val / 500000;
2477
2478 WL_CONN("rate %d mbps\n", rate / 2);
2479
2480 /*
2481 *
2482 * Set rate override,
2483 * Since the is a/b/g-blind, both a/bg_rate are enforced.
2484 */
2485 err_bg = brcmf_dev_intvar_set(ndev, "bg_rate", rate);
2486 err_a = brcmf_dev_intvar_set(ndev, "a_rate", rate);
2487 if (err_bg && err_a) {
2488 WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a);
2489 err = err_bg | err_a;
2490 }
2491
2492done:
2493 WL_TRACE("Exit\n");
2494 return err;
2495}
2496
2497static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
d34bf64f 2498 struct brcmf_bss_info_le *bi)
5b435de0
AS
2499{
2500 struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
2501 struct ieee80211_channel *notify_channel;
2502 struct cfg80211_bss *bss;
2503 struct ieee80211_supported_band *band;
2504 s32 err = 0;
2505 u16 channel;
2506 u32 freq;
5b435de0
AS
2507 u16 notify_capability;
2508 u16 notify_interval;
2509 u8 *notify_ie;
2510 size_t notify_ielen;
2511 s32 notify_signal;
2512
2513 if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) {
2514 WL_ERR("Bss info is larger than buffer. Discarding\n");
2515 return 0;
2516 }
2517
2518 channel = bi->ctl_ch ? bi->ctl_ch :
2519 CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
2520
2521 if (channel <= CH_MAX_2G_CHANNEL)
2522 band = wiphy->bands[IEEE80211_BAND_2GHZ];
2523 else
2524 band = wiphy->bands[IEEE80211_BAND_5GHZ];
2525
2526 freq = ieee80211_channel_to_frequency(channel, band->band);
2527 notify_channel = ieee80211_get_channel(wiphy, freq);
2528
5b435de0
AS
2529 notify_capability = le16_to_cpu(bi->capability);
2530 notify_interval = le16_to_cpu(bi->beacon_period);
2531 notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
2532 notify_ielen = le32_to_cpu(bi->ie_length);
2533 notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
2534
2535 WL_CONN("bssid: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
2536 bi->BSSID[0], bi->BSSID[1], bi->BSSID[2],
2537 bi->BSSID[3], bi->BSSID[4], bi->BSSID[5]);
2538 WL_CONN("Channel: %d(%d)\n", channel, freq);
2539 WL_CONN("Capability: %X\n", notify_capability);
2540 WL_CONN("Beacon interval: %d\n", notify_interval);
2541 WL_CONN("Signal: %d\n", notify_signal);
5b435de0
AS
2542
2543 bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID,
8e6cffb3 2544 0, notify_capability, notify_interval, notify_ie,
5b435de0
AS
2545 notify_ielen, notify_signal, GFP_KERNEL);
2546
e78946e1
FL
2547 if (!bss)
2548 return -ENOMEM;
2549
2550 cfg80211_put_bss(bss);
5b435de0
AS
2551
2552 return err;
2553}
2554
6f09be0a
RV
2555static struct brcmf_bss_info_le *
2556next_bss_le(struct brcmf_scan_results *list, struct brcmf_bss_info_le *bss)
2557{
2558 if (bss == NULL)
2559 return list->bss_info_le;
2560 return (struct brcmf_bss_info_le *)((unsigned long)bss +
2561 le32_to_cpu(bss->length));
2562}
2563
5b435de0
AS
2564static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv)
2565{
2566 struct brcmf_scan_results *bss_list;
d34bf64f 2567 struct brcmf_bss_info_le *bi = NULL; /* must be initialized */
5b435de0
AS
2568 s32 err = 0;
2569 int i;
2570
2571 bss_list = cfg_priv->bss_list;
2572 if (bss_list->version != BRCMF_BSS_INFO_VERSION) {
2573 WL_ERR("Version %d != WL_BSS_INFO_VERSION\n",
2574 bss_list->version);
2575 return -EOPNOTSUPP;
2576 }
2577 WL_SCAN("scanned AP count (%d)\n", bss_list->count);
2578 for (i = 0; i < bss_list->count && i < WL_AP_MAX; i++) {
6f09be0a 2579 bi = next_bss_le(bss_list, bi);
5b435de0
AS
2580 err = brcmf_inform_single_bss(cfg_priv, bi);
2581 if (err)
2582 break;
2583 }
2584 return err;
2585}
2586
2587static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
2588 struct net_device *ndev, const u8 *bssid)
2589{
2590 struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
2591 struct ieee80211_channel *notify_channel;
d34bf64f 2592 struct brcmf_bss_info_le *bi = NULL;
5b435de0 2593 struct ieee80211_supported_band *band;
e78946e1 2594 struct cfg80211_bss *bss;
5b435de0
AS
2595 u8 *buf = NULL;
2596 s32 err = 0;
2597 u16 channel;
2598 u32 freq;
5b435de0
AS
2599 u16 notify_capability;
2600 u16 notify_interval;
2601 u8 *notify_ie;
2602 size_t notify_ielen;
2603 s32 notify_signal;
2604
2605 WL_TRACE("Enter\n");
2606
2607 buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
2608 if (buf == NULL) {
2609 err = -ENOMEM;
2610 goto CleanUp;
2611 }
2612
2613 *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
2614
2615 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
2616 if (err) {
2617 WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err);
2618 goto CleanUp;
2619 }
2620
d34bf64f 2621 bi = (struct brcmf_bss_info_le *)(buf + 4);
5b435de0
AS
2622
2623 channel = bi->ctl_ch ? bi->ctl_ch :
2624 CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
2625
2626 if (channel <= CH_MAX_2G_CHANNEL)
2627 band = wiphy->bands[IEEE80211_BAND_2GHZ];
2628 else
2629 band = wiphy->bands[IEEE80211_BAND_5GHZ];
2630
2631 freq = ieee80211_channel_to_frequency(channel, band->band);
2632 notify_channel = ieee80211_get_channel(wiphy, freq);
2633
5b435de0
AS
2634 notify_capability = le16_to_cpu(bi->capability);
2635 notify_interval = le16_to_cpu(bi->beacon_period);
2636 notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
2637 notify_ielen = le32_to_cpu(bi->ie_length);
2638 notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
2639
2640 WL_CONN("channel: %d(%d)\n", channel, freq);
2641 WL_CONN("capability: %X\n", notify_capability);
2642 WL_CONN("beacon interval: %d\n", notify_interval);
2643 WL_CONN("signal: %d\n", notify_signal);
5b435de0 2644
e78946e1 2645 bss = cfg80211_inform_bss(wiphy, notify_channel, bssid,
8e6cffb3 2646 0, notify_capability, notify_interval,
5b435de0
AS
2647 notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
2648
e78946e1
FL
2649 if (!bss) {
2650 err = -ENOMEM;
2651 goto CleanUp;
2652 }
2653
2654 cfg80211_put_bss(bss);
2655
5b435de0
AS
2656CleanUp:
2657
2658 kfree(buf);
2659
2660 WL_TRACE("Exit\n");
2661
2662 return err;
2663}
2664
2665static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv)
2666{
2667 return cfg_priv->conf->mode == WL_MODE_IBSS;
2668}
2669
f8e4b412
AB
2670/*
2671 * Traverse a string of 1-byte tag/1-byte length/variable-length value
2672 * triples, returning a pointer to the substring whose first element
2673 * matches tag
2674 */
2675static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key)
2676{
2677 struct brcmf_tlv *elt;
2678 int totlen;
2679
2680 elt = (struct brcmf_tlv *) buf;
2681 totlen = buflen;
2682
2683 /* find tagged parameter */
04012895 2684 while (totlen >= TLV_HDR_LEN) {
f8e4b412
AB
2685 int len = elt->len;
2686
2687 /* validate remaining totlen */
04012895 2688 if ((elt->id == key) && (totlen >= (len + TLV_HDR_LEN)))
f8e4b412
AB
2689 return elt;
2690
04012895
HM
2691 elt = (struct brcmf_tlv *) ((u8 *) elt + (len + TLV_HDR_LEN));
2692 totlen -= (len + TLV_HDR_LEN);
f8e4b412
AB
2693 }
2694
2695 return NULL;
2696}
2697
1a873342
HM
2698/* Is any of the tlvs the expected entry? If
2699 * not update the tlvs buffer pointer/length.
2700 */
2701static bool
2702brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len,
2703 u8 *oui, u32 oui_len, u8 type)
2704{
2705 /* If the contents match the OUI and the type */
2706 if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
2707 !memcmp(&ie[TLV_BODY_OFF], oui, oui_len) &&
2708 type == ie[TLV_BODY_OFF + oui_len]) {
2709 return true;
2710 }
2711
2712 if (tlvs == NULL)
2713 return false;
2714 /* point to the next ie */
2715 ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
2716 /* calculate the length of the rest of the buffer */
2717 *tlvs_len -= (int)(ie - *tlvs);
2718 /* update the pointer to the start of the buffer */
2719 *tlvs = ie;
2720
2721 return false;
2722}
2723
2724struct brcmf_vs_tlv *
2725brcmf_find_wpaie(u8 *parse, u32 len)
2726{
2727 struct brcmf_tlv *ie;
2728
2729 while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_WPA))) {
2730 if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len,
2731 WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE))
2732 return (struct brcmf_vs_tlv *)ie;
2733 }
2734 return NULL;
2735}
2736
5b435de0
AS
2737static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv)
2738{
d34bf64f 2739 struct brcmf_bss_info_le *bi;
5b435de0 2740 struct brcmf_ssid *ssid;
f8e4b412 2741 struct brcmf_tlv *tim;
5b435de0
AS
2742 u16 beacon_interval;
2743 u8 dtim_period;
2744 size_t ie_len;
2745 u8 *ie;
2746 s32 err = 0;
2747
2748 WL_TRACE("Enter\n");
2749 if (brcmf_is_ibssmode(cfg_priv))
2750 return err;
2751
2752 ssid = (struct brcmf_ssid *)brcmf_read_prof(cfg_priv, WL_PROF_SSID);
2753
2754 *(__le32 *)cfg_priv->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
2755 err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_GET_BSS_INFO,
2756 cfg_priv->extra_buf, WL_EXTRA_BUF_MAX);
2757 if (err) {
2758 WL_ERR("Could not get bss info %d\n", err);
2759 goto update_bss_info_out;
2760 }
2761
d34bf64f 2762 bi = (struct brcmf_bss_info_le *)(cfg_priv->extra_buf + 4);
5b435de0
AS
2763 err = brcmf_inform_single_bss(cfg_priv, bi);
2764 if (err)
2765 goto update_bss_info_out;
2766
2767 ie = ((u8 *)bi) + le16_to_cpu(bi->ie_offset);
2768 ie_len = le32_to_cpu(bi->ie_length);
2769 beacon_interval = le16_to_cpu(bi->beacon_period);
2770
f8e4b412 2771 tim = brcmf_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
5b435de0
AS
2772 if (tim)
2773 dtim_period = tim->data[1];
2774 else {
2775 /*
2776 * active scan was done so we could not get dtim
2777 * information out of probe response.
2778 * so we speficially query dtim information to dongle.
2779 */
2780 u32 var;
2781 err = brcmf_dev_intvar_get(cfg_to_ndev(cfg_priv),
2782 "dtim_assoc", &var);
2783 if (err) {
2784 WL_ERR("wl dtim_assoc failed (%d)\n", err);
2785 goto update_bss_info_out;
2786 }
2787 dtim_period = (u8)var;
2788 }
2789
2790 brcmf_update_prof(cfg_priv, NULL, &beacon_interval, WL_PROF_BEACONINT);
2791 brcmf_update_prof(cfg_priv, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
2792
2793update_bss_info_out:
2794 WL_TRACE("Exit");
2795 return err;
2796}
2797
108a4bee 2798static void brcmf_abort_scanning(struct brcmf_cfg80211_priv *cfg_priv)
5b435de0
AS
2799{
2800 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
108a4bee 2801 struct escan_info *escan = &cfg_priv->escan_info;
5b435de0
AS
2802 struct brcmf_ssid ssid;
2803
108a4bee 2804 set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
5b435de0
AS
2805 if (cfg_priv->iscan_on) {
2806 iscan->state = WL_ISCAN_STATE_IDLE;
2807
2808 if (iscan->timer_on) {
2809 del_timer_sync(&iscan->timer);
2810 iscan->timer_on = 0;
2811 }
2812
2813 cancel_work_sync(&iscan->work);
2814
2815 /* Abort iscan running in FW */
2816 memset(&ssid, 0, sizeof(ssid));
2817 brcmf_run_iscan(iscan, &ssid, WL_SCAN_ACTION_ABORT);
108a4bee
AS
2818
2819 if (cfg_priv->scan_request) {
2820 /* Indidate scan abort to cfg80211 layer */
2821 WL_INFO("Terminating scan in progress\n");
2822 cfg80211_scan_done(cfg_priv->scan_request, true);
2823 cfg_priv->scan_request = NULL;
2824 }
2825 }
2826 if (cfg_priv->escan_on && cfg_priv->scan_request) {
2827 escan->escan_state = WL_ESCAN_STATE_IDLE;
2828 brcmf_notify_escan_complete(cfg_priv, escan->ndev, true, true);
5b435de0 2829 }
108a4bee
AS
2830 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
2831 clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
5b435de0
AS
2832}
2833
2834static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
2835 bool aborted)
2836{
2837 struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
2838 struct net_device *ndev = cfg_to_ndev(cfg_priv);
2839
2840 if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
2841 WL_ERR("Scan complete while device not scanning\n");
2842 return;
2843 }
2844 if (cfg_priv->scan_request) {
2845 WL_SCAN("ISCAN Completed scan: %s\n",
2846 aborted ? "Aborted" : "Done");
2847 cfg80211_scan_done(cfg_priv->scan_request, aborted);
2848 brcmf_set_mpc(ndev, 1);
2849 cfg_priv->scan_request = NULL;
2850 }
2851 cfg_priv->iscan_kickstart = false;
2852}
2853
2854static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan)
2855{
2856 if (iscan->state != WL_ISCAN_STATE_IDLE) {
2857 WL_SCAN("wake up iscan\n");
2858 schedule_work(&iscan->work);
2859 return 0;
2860 }
2861
2862 return -EIO;
2863}
2864
2865static s32
2866brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status,
2867 struct brcmf_scan_results **bss_list)
2868{
2869 struct brcmf_iscan_results list;
2870 struct brcmf_scan_results *results;
2871 struct brcmf_scan_results_le *results_le;
2872 struct brcmf_iscan_results *list_buf;
2873 s32 err = 0;
2874
2875 memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
2876 list_buf = (struct brcmf_iscan_results *)iscan->scan_buf;
2877 results = &list_buf->results;
2878 results_le = &list_buf->results_le;
2879 results->buflen = BRCMF_ISCAN_RESULTS_FIXED_SIZE;
2880 results->version = 0;
2881 results->count = 0;
2882
2883 memset(&list, 0, sizeof(list));
2884 list.results_le.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX);
2885 err = brcmf_dev_iovar_getbuf(iscan->ndev, "iscanresults", &list,
2886 BRCMF_ISCAN_RESULTS_FIXED_SIZE,
2887 iscan->scan_buf, WL_ISCAN_BUF_MAX);
2888 if (err) {
2889 WL_ERR("error (%d)\n", err);
2890 return err;
2891 }
2892 results->buflen = le32_to_cpu(results_le->buflen);
2893 results->version = le32_to_cpu(results_le->version);
2894 results->count = le32_to_cpu(results_le->count);
2895 WL_SCAN("results->count = %d\n", results_le->count);
2896 WL_SCAN("results->buflen = %d\n", results_le->buflen);
2897 *status = le32_to_cpu(list_buf->status_le);
2898 WL_SCAN("status = %d\n", *status);
2899 *bss_list = results;
2900
2901 return err;
2902}
2903
2904static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv)
2905{
2906 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2907 s32 err = 0;
2908
2909 iscan->state = WL_ISCAN_STATE_IDLE;
2910 brcmf_inform_bss(cfg_priv);
2911 brcmf_notify_iscan_complete(iscan, false);
2912
2913 return err;
2914}
2915
2916static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv)
2917{
2918 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2919 s32 err = 0;
2920
2921 /* Reschedule the timer */
2922 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
2923 iscan->timer_on = 1;
2924
2925 return err;
2926}
2927
2928static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv)
2929{
2930 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2931 s32 err = 0;
2932
2933 brcmf_inform_bss(cfg_priv);
2934 brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE);
2935 /* Reschedule the timer */
2936 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
2937 iscan->timer_on = 1;
2938
2939 return err;
2940}
2941
2942static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv)
2943{
2944 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2945 s32 err = 0;
2946
2947 iscan->state = WL_ISCAN_STATE_IDLE;
2948 brcmf_notify_iscan_complete(iscan, true);
2949
2950 return err;
2951}
2952
2953static void brcmf_cfg80211_iscan_handler(struct work_struct *work)
2954{
2955 struct brcmf_cfg80211_iscan_ctrl *iscan =
2956 container_of(work, struct brcmf_cfg80211_iscan_ctrl,
2957 work);
2958 struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
2959 struct brcmf_cfg80211_iscan_eloop *el = &iscan->el;
2960 u32 status = BRCMF_SCAN_RESULTS_PARTIAL;
2961
2962 if (iscan->timer_on) {
2963 del_timer_sync(&iscan->timer);
2964 iscan->timer_on = 0;
2965 }
2966
2967 if (brcmf_get_iscan_results(iscan, &status, &cfg_priv->bss_list)) {
2968 status = BRCMF_SCAN_RESULTS_ABORTED;
2969 WL_ERR("Abort iscan\n");
2970 }
2971
2972 el->handler[status](cfg_priv);
2973}
2974
2975static void brcmf_iscan_timer(unsigned long data)
2976{
2977 struct brcmf_cfg80211_iscan_ctrl *iscan =
2978 (struct brcmf_cfg80211_iscan_ctrl *)data;
2979
2980 if (iscan) {
2981 iscan->timer_on = 0;
2982 WL_SCAN("timer expired\n");
2983 brcmf_wakeup_iscan(iscan);
2984 }
2985}
2986
2987static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv)
2988{
2989 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
2990
2991 if (cfg_priv->iscan_on) {
2992 iscan->state = WL_ISCAN_STATE_IDLE;
2993 INIT_WORK(&iscan->work, brcmf_cfg80211_iscan_handler);
2994 }
2995
2996 return 0;
2997}
2998
2999static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el)
3000{
3001 memset(el, 0, sizeof(*el));
3002 el->handler[BRCMF_SCAN_RESULTS_SUCCESS] = brcmf_iscan_done;
3003 el->handler[BRCMF_SCAN_RESULTS_PARTIAL] = brcmf_iscan_inprogress;
3004 el->handler[BRCMF_SCAN_RESULTS_PENDING] = brcmf_iscan_pending;
3005 el->handler[BRCMF_SCAN_RESULTS_ABORTED] = brcmf_iscan_aborted;
3006 el->handler[BRCMF_SCAN_RESULTS_NO_MEM] = brcmf_iscan_aborted;
3007}
3008
3009static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv)
3010{
3011 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
3012 int err = 0;
3013
3014 if (cfg_priv->iscan_on) {
3015 iscan->ndev = cfg_to_ndev(cfg_priv);
3016 brcmf_init_iscan_eloop(&iscan->el);
3017 iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
3018 init_timer(&iscan->timer);
3019 iscan->timer.data = (unsigned long) iscan;
3020 iscan->timer.function = brcmf_iscan_timer;
3021 err = brcmf_invoke_iscan(cfg_priv);
3022 if (!err)
3023 iscan->data = cfg_priv;
3024 }
3025
3026 return err;
3027}
3028
e756af5b
HM
3029static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work)
3030{
3031 struct brcmf_cfg80211_priv *cfg_priv =
3032 container_of(work, struct brcmf_cfg80211_priv,
3033 escan_timeout_work);
3034
3035 brcmf_notify_escan_complete(cfg_priv,
3036 cfg_priv->escan_info.ndev, true, true);
3037}
3038
3039static void brcmf_escan_timeout(unsigned long data)
3040{
3041 struct brcmf_cfg80211_priv *cfg_priv =
3042 (struct brcmf_cfg80211_priv *)data;
3043
3044 if (cfg_priv->scan_request) {
3045 WL_ERR("timer expired\n");
3046 if (cfg_priv->escan_on)
3047 schedule_work(&cfg_priv->escan_timeout_work);
3048 }
3049}
3050
3051static s32
3052brcmf_compare_update_same_bss(struct brcmf_bss_info_le *bss,
3053 struct brcmf_bss_info_le *bss_info_le)
3054{
3055 if (!memcmp(&bss_info_le->BSSID, &bss->BSSID, ETH_ALEN) &&
3056 (CHSPEC_BAND(le16_to_cpu(bss_info_le->chanspec)) ==
3057 CHSPEC_BAND(le16_to_cpu(bss->chanspec))) &&
3058 bss_info_le->SSID_len == bss->SSID_len &&
3059 !memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) {
3060 if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) ==
3061 (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL)) {
029591f3
AS
3062 s16 bss_rssi = le16_to_cpu(bss->RSSI);
3063 s16 bss_info_rssi = le16_to_cpu(bss_info_le->RSSI);
3064
e756af5b
HM
3065 /* preserve max RSSI if the measurements are
3066 * both on-channel or both off-channel
3067 */
029591f3 3068 if (bss_info_rssi > bss_rssi)
e756af5b
HM
3069 bss->RSSI = bss_info_le->RSSI;
3070 } else if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) &&
3071 (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL) == 0) {
3072 /* preserve the on-channel rssi measurement
3073 * if the new measurement is off channel
3074 */
3075 bss->RSSI = bss_info_le->RSSI;
3076 bss->flags |= WLC_BSS_RSSI_ON_CHANNEL;
3077 }
3078 return 1;
3079 }
3080 return 0;
3081}
3082
3083static s32
3084brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_priv *cfg_priv,
3085 struct net_device *ndev,
3086 const struct brcmf_event_msg *e, void *data)
3087{
3088 s32 status;
3089 s32 err = 0;
3090 struct brcmf_escan_result_le *escan_result_le;
3091 struct brcmf_bss_info_le *bss_info_le;
3092 struct brcmf_bss_info_le *bss = NULL;
3093 u32 bi_length;
3094 struct brcmf_scan_results *list;
3095 u32 i;
97ed15c7 3096 bool aborted;
e756af5b
HM
3097
3098 status = be32_to_cpu(e->status);
3099
3100 if (!ndev || !cfg_priv->escan_on ||
3101 !test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
3102 WL_ERR("scan not ready ndev %p wl->escan_on %d drv_status %x\n",
3103 ndev, cfg_priv->escan_on,
3104 !test_bit(WL_STATUS_SCANNING, &cfg_priv->status));
3105 return -EPERM;
3106 }
3107
3108 if (status == BRCMF_E_STATUS_PARTIAL) {
3109 WL_SCAN("ESCAN Partial result\n");
3110 escan_result_le = (struct brcmf_escan_result_le *) data;
3111 if (!escan_result_le) {
3112 WL_ERR("Invalid escan result (NULL pointer)\n");
3113 goto exit;
3114 }
3115 if (!cfg_priv->scan_request) {
3116 WL_SCAN("result without cfg80211 request\n");
3117 goto exit;
3118 }
3119
3120 if (le16_to_cpu(escan_result_le->bss_count) != 1) {
3121 WL_ERR("Invalid bss_count %d: ignoring\n",
3122 escan_result_le->bss_count);
3123 goto exit;
3124 }
3125 bss_info_le = &escan_result_le->bss_info_le;
3126
3127 bi_length = le32_to_cpu(bss_info_le->length);
3128 if (bi_length != (le32_to_cpu(escan_result_le->buflen) -
3129 WL_ESCAN_RESULTS_FIXED_SIZE)) {
3130 WL_ERR("Invalid bss_info length %d: ignoring\n",
3131 bi_length);
3132 goto exit;
3133 }
3134
3135 if (!(cfg_to_wiphy(cfg_priv)->interface_modes &
3136 BIT(NL80211_IFTYPE_ADHOC))) {
3137 if (le16_to_cpu(bss_info_le->capability) &
3138 WLAN_CAPABILITY_IBSS) {
3139 WL_ERR("Ignoring IBSS result\n");
3140 goto exit;
3141 }
3142 }
3143
3144 list = (struct brcmf_scan_results *)
3145 cfg_priv->escan_info.escan_buf;
3146 if (bi_length > WL_ESCAN_BUF_SIZE - list->buflen) {
3147 WL_ERR("Buffer is too small: ignoring\n");
3148 goto exit;
3149 }
3150
3151 for (i = 0; i < list->count; i++) {
3152 bss = bss ? (struct brcmf_bss_info_le *)
3153 ((unsigned char *)bss +
3154 le32_to_cpu(bss->length)) : list->bss_info_le;
3155 if (brcmf_compare_update_same_bss(bss, bss_info_le))
3156 goto exit;
3157 }
3158 memcpy(&(cfg_priv->escan_info.escan_buf[list->buflen]),
3159 bss_info_le, bi_length);
3160 list->version = le32_to_cpu(bss_info_le->version);
3161 list->buflen += bi_length;
3162 list->count++;
3163 } else {
3164 cfg_priv->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
3165 if (cfg_priv->scan_request) {
3166 cfg_priv->bss_list = (struct brcmf_scan_results *)
3167 cfg_priv->escan_info.escan_buf;
3168 brcmf_inform_bss(cfg_priv);
97ed15c7
AS
3169 aborted = status != BRCMF_E_STATUS_SUCCESS;
3170 brcmf_notify_escan_complete(cfg_priv, ndev, aborted,
3171 false);
e756af5b
HM
3172 } else
3173 WL_ERR("Unexpected scan result 0x%x\n", status);
3174 }
3175exit:
3176 return err;
3177}
3178
3179static void brcmf_init_escan(struct brcmf_cfg80211_priv *cfg_priv)
3180{
3181
3182 if (cfg_priv->escan_on) {
3183 cfg_priv->el.handler[BRCMF_E_ESCAN_RESULT] =
3184 brcmf_cfg80211_escan_handler;
3185 cfg_priv->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
3186 /* Init scan_timeout timer */
3187 init_timer(&cfg_priv->escan_timeout);
3188 cfg_priv->escan_timeout.data = (unsigned long) cfg_priv;
3189 cfg_priv->escan_timeout.function = brcmf_escan_timeout;
3190 INIT_WORK(&cfg_priv->escan_timeout_work,
3191 brcmf_cfg80211_escan_timeout_worker);
3192 }
3193}
3194
5addc0de 3195static __always_inline void brcmf_delay(u32 ms)
5b435de0
AS
3196{
3197 if (ms < 1000 / HZ) {
3198 cond_resched();
3199 mdelay(ms);
3200 } else {
3201 msleep(ms);
3202 }
3203}
3204
3205static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
3206{
3207 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3208
3209 /*
3210 * Check for WL_STATUS_READY before any function call which
3211 * could result is bus access. Don't block the resume for
3212 * any driver error conditions
3213 */
3214 WL_TRACE("Enter\n");
3215
3216 if (test_bit(WL_STATUS_READY, &cfg_priv->status))
3217 brcmf_invoke_iscan(wiphy_to_cfg(wiphy));
3218
3219 WL_TRACE("Exit\n");
3220 return 0;
3221}
3222
3223static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
3224 struct cfg80211_wowlan *wow)
3225{
3226 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3227 struct net_device *ndev = cfg_to_ndev(cfg_priv);
3228
3229 WL_TRACE("Enter\n");
3230
3231 /*
3232 * Check for WL_STATUS_READY before any function call which
3233 * could result is bus access. Don't block the suspend for
3234 * any driver error conditions
3235 */
3236
3237 /*
3238 * While going to suspend if associated with AP disassociate
3239 * from AP to save power while system is in suspended state
3240 */
3241 if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
3242 test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
3243 test_bit(WL_STATUS_READY, &cfg_priv->status)) {
3244 WL_INFO("Disassociating from AP"
3245 " while entering suspend state\n");
3246 brcmf_link_down(cfg_priv);
3247
3248 /*
3249 * Make sure WPA_Supplicant receives all the event
3250 * generated due to DISASSOC call to the fw to keep
3251 * the state fw and WPA_Supplicant state consistent
3252 */
3253 brcmf_delay(500);
3254 }
3255
5b435de0 3256 if (test_bit(WL_STATUS_READY, &cfg_priv->status))
108a4bee
AS
3257 brcmf_abort_scanning(cfg_priv);
3258 else
3259 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
5b435de0
AS
3260
3261 /* Turn off watchdog timer */
35aafa9d 3262 if (test_bit(WL_STATUS_READY, &cfg_priv->status))
5b435de0 3263 brcmf_set_mpc(ndev, 1);
5b435de0
AS
3264
3265 WL_TRACE("Exit\n");
3266
3267 return 0;
3268}
3269
3270static __used s32
3271brcmf_dev_bufvar_set(struct net_device *ndev, s8 *name, s8 *buf, s32 len)
3272{
3273 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
3274 u32 buflen;
3275
53a2277d 3276 buflen = brcmf_c_mkiovar(name, buf, len, cfg_priv->dcmd_buf,
5b435de0
AS
3277 WL_DCMD_LEN_MAX);
3278 BUG_ON(!buflen);
3279
3280 return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg_priv->dcmd_buf,
3281 buflen);
3282}
3283
3284static s32
3285brcmf_dev_bufvar_get(struct net_device *ndev, s8 *name, s8 *buf,
3286 s32 buf_len)
3287{
3288 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
3289 u32 len;
3290 s32 err = 0;
3291
53a2277d 3292 len = brcmf_c_mkiovar(name, NULL, 0, cfg_priv->dcmd_buf,
5b435de0
AS
3293 WL_DCMD_LEN_MAX);
3294 BUG_ON(!len);
3295 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg_priv->dcmd_buf,
3296 WL_DCMD_LEN_MAX);
3297 if (err) {
3298 WL_ERR("error (%d)\n", err);
3299 return err;
3300 }
3301 memcpy(buf, cfg_priv->dcmd_buf, buf_len);
3302
3303 return err;
3304}
3305
3306static __used s32
3307brcmf_update_pmklist(struct net_device *ndev,
3308 struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
3309{
3310 int i, j;
40c8e95a 3311 int pmkid_len;
5b435de0 3312
40c8e95a
AS
3313 pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid);
3314
3315 WL_CONN("No of elements %d\n", pmkid_len);
3316 for (i = 0; i < pmkid_len; i++) {
5b435de0
AS
3317 WL_CONN("PMKID[%d]: %pM =\n", i,
3318 &pmk_list->pmkids.pmkid[i].BSSID);
3319 for (j = 0; j < WLAN_PMKID_LEN; j++)
3320 WL_CONN("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]);
3321 }
3322
3323 if (!err)
3324 brcmf_dev_bufvar_set(ndev, "pmkid_info", (char *)pmk_list,
3325 sizeof(*pmk_list));
3326
3327 return err;
3328}
3329
3330static s32
3331brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
3332 struct cfg80211_pmksa *pmksa)
3333{
3334 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3335 struct pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids;
3336 s32 err = 0;
3337 int i;
40c8e95a 3338 int pmkid_len;
5b435de0
AS
3339
3340 WL_TRACE("Enter\n");
3341 if (!check_sys_up(wiphy))
3342 return -EIO;
3343
40c8e95a
AS
3344 pmkid_len = le32_to_cpu(pmkids->npmkid);
3345 for (i = 0; i < pmkid_len; i++)
5b435de0
AS
3346 if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN))
3347 break;
3348 if (i < WL_NUM_PMKIDS_MAX) {
3349 memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN);
3350 memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
40c8e95a
AS
3351 if (i == pmkid_len) {
3352 pmkid_len++;
3353 pmkids->npmkid = cpu_to_le32(pmkid_len);
3354 }
5b435de0
AS
3355 } else
3356 err = -EINVAL;
3357
3358 WL_CONN("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
40c8e95a 3359 pmkids->pmkid[pmkid_len].BSSID);
5b435de0 3360 for (i = 0; i < WLAN_PMKID_LEN; i++)
40c8e95a 3361 WL_CONN("%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]);
5b435de0
AS
3362
3363 err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
3364
3365 WL_TRACE("Exit\n");
3366 return err;
3367}
3368
3369static s32
3370brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
3371 struct cfg80211_pmksa *pmksa)
3372{
3373 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3374 struct pmkid_list pmkid;
3375 s32 err = 0;
40c8e95a 3376 int i, pmkid_len;
5b435de0
AS
3377
3378 WL_TRACE("Enter\n");
3379 if (!check_sys_up(wiphy))
3380 return -EIO;
3381
3382 memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
3383 memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
3384
3385 WL_CONN("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
3386 &pmkid.pmkid[0].BSSID);
3387 for (i = 0; i < WLAN_PMKID_LEN; i++)
3388 WL_CONN("%02x\n", pmkid.pmkid[0].PMKID[i]);
3389
40c8e95a
AS
3390 pmkid_len = le32_to_cpu(cfg_priv->pmk_list->pmkids.npmkid);
3391 for (i = 0; i < pmkid_len; i++)
5b435de0
AS
3392 if (!memcmp
3393 (pmksa->bssid, &cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
3394 ETH_ALEN))
3395 break;
3396
40c8e95a
AS
3397 if ((pmkid_len > 0)
3398 && (i < pmkid_len)) {
5b435de0
AS
3399 memset(&cfg_priv->pmk_list->pmkids.pmkid[i], 0,
3400 sizeof(struct pmkid));
40c8e95a 3401 for (; i < (pmkid_len - 1); i++) {
5b435de0
AS
3402 memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
3403 &cfg_priv->pmk_list->pmkids.pmkid[i + 1].BSSID,
3404 ETH_ALEN);
3405 memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].PMKID,
3406 &cfg_priv->pmk_list->pmkids.pmkid[i + 1].PMKID,
3407 WLAN_PMKID_LEN);
3408 }
40c8e95a 3409 cfg_priv->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1);
5b435de0
AS
3410 } else
3411 err = -EINVAL;
3412
3413 err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
3414
3415 WL_TRACE("Exit\n");
3416 return err;
3417
3418}
3419
3420static s32
3421brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
3422{
3423 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3424 s32 err = 0;
3425
3426 WL_TRACE("Enter\n");
3427 if (!check_sys_up(wiphy))
3428 return -EIO;
3429
3430 memset(cfg_priv->pmk_list, 0, sizeof(*cfg_priv->pmk_list));
3431 err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
3432
3433 WL_TRACE("Exit\n");
3434 return err;
3435
3436}
3437
e5806072
AS
3438/*
3439 * PFN result doesn't have all the info which are
3440 * required by the supplicant
3441 * (For e.g IEs) Do a target Escan so that sched scan results are reported
3442 * via wl_inform_single_bss in the required format. Escan does require the
3443 * scan request in the form of cfg80211_scan_request. For timebeing, create
3444 * cfg80211_scan_request one out of the received PNO event.
3445 */
3446static s32
3447brcmf_notify_sched_scan_results(struct brcmf_cfg80211_priv *cfg_priv,
3448 struct net_device *ndev,
3449 const struct brcmf_event_msg *e, void *data)
3450{
3451 struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
3452 struct cfg80211_scan_request *request = NULL;
3453 struct cfg80211_ssid *ssid = NULL;
3454 struct ieee80211_channel *channel = NULL;
3455 struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
3456 int err = 0;
3457 int channel_req = 0;
3458 int band = 0;
3459 struct brcmf_pno_scanresults_le *pfn_result;
3460 u32 result_count;
3461 u32 status;
3462
3463 WL_SCAN("Enter\n");
3464
3465 if (e->event_type == cpu_to_be32(BRCMF_E_PFN_NET_LOST)) {
3466 WL_SCAN("PFN NET LOST event. Do Nothing\n");
3467 return 0;
3468 }
3469
3470 pfn_result = (struct brcmf_pno_scanresults_le *)data;
3471 result_count = le32_to_cpu(pfn_result->count);
3472 status = le32_to_cpu(pfn_result->status);
3473
3474 /*
3475 * PFN event is limited to fit 512 bytes so we may get
3476 * multiple NET_FOUND events. For now place a warning here.
3477 */
3478 WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE);
3479 WL_SCAN("PFN NET FOUND event. count: %d\n", result_count);
3480 if (result_count > 0) {
3481 int i;
3482
3483 request = kzalloc(sizeof(*request), GFP_KERNEL);
58901d18
DC
3484 ssid = kcalloc(result_count, sizeof(*ssid), GFP_KERNEL);
3485 channel = kcalloc(result_count, sizeof(*channel), GFP_KERNEL);
e5806072
AS
3486 if (!request || !ssid || !channel) {
3487 err = -ENOMEM;
3488 goto out_err;
3489 }
3490
3491 request->wiphy = wiphy;
3492 data += sizeof(struct brcmf_pno_scanresults_le);
3493 netinfo_start = (struct brcmf_pno_net_info_le *)data;
3494
3495 for (i = 0; i < result_count; i++) {
3496 netinfo = &netinfo_start[i];
3497 if (!netinfo) {
3498 WL_ERR("Invalid netinfo ptr. index: %d\n", i);
3499 err = -EINVAL;
3500 goto out_err;
3501 }
3502
3503 WL_SCAN("SSID:%s Channel:%d\n",
3504 netinfo->SSID, netinfo->channel);
3505 memcpy(ssid[i].ssid, netinfo->SSID, netinfo->SSID_len);
3506 ssid[i].ssid_len = netinfo->SSID_len;
3507 request->n_ssids++;
3508
3509 channel_req = netinfo->channel;
3510 if (channel_req <= CH_MAX_2G_CHANNEL)
3511 band = NL80211_BAND_2GHZ;
3512 else
3513 band = NL80211_BAND_5GHZ;
3514 channel[i].center_freq =
3515 ieee80211_channel_to_frequency(channel_req,
3516 band);
3517 channel[i].band = band;
3518 channel[i].flags |= IEEE80211_CHAN_NO_HT40;
3519 request->channels[i] = &channel[i];
3520 request->n_channels++;
3521 }
3522
3523 /* assign parsed ssid array */
3524 if (request->n_ssids)
3525 request->ssids = &ssid[0];
3526
3527 if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
3528 /* Abort any on-going scan */
3529 brcmf_abort_scanning(cfg_priv);
3530 }
3531
3532 set_bit(WL_STATUS_SCANNING, &cfg_priv->status);
3533 err = brcmf_do_escan(cfg_priv, wiphy, ndev, request);
3534 if (err) {
3535 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
3536 goto out_err;
3537 }
3538 cfg_priv->sched_escan = true;
3539 cfg_priv->scan_request = request;
3540 } else {
3541 WL_ERR("FALSE PNO Event. (pfn_count == 0)\n");
3542 goto out_err;
3543 }
3544
3545 kfree(ssid);
3546 kfree(channel);
3547 kfree(request);
3548 return 0;
3549
3550out_err:
3551 kfree(ssid);
3552 kfree(channel);
3553 kfree(request);
3554 cfg80211_sched_scan_stopped(wiphy);
3555 return err;
3556}
3557
3558#ifndef CONFIG_BRCMISCAN
3559static int brcmf_dev_pno_clean(struct net_device *ndev)
3560{
3561 char iovbuf[128];
3562 int ret;
3563
3564 /* Disable pfn */
3565 ret = brcmf_dev_intvar_set(ndev, "pfn", 0);
3566 if (ret == 0) {
3567 /* clear pfn */
3568 ret = brcmf_dev_iovar_setbuf(ndev, "pfnclear", NULL, 0,
3569 iovbuf, sizeof(iovbuf));
3570 }
3571 if (ret < 0)
3572 WL_ERR("failed code %d\n", ret);
3573
3574 return ret;
3575}
3576
3577static int brcmf_dev_pno_config(struct net_device *ndev)
3578{
3579 struct brcmf_pno_param_le pfn_param;
3580 char iovbuf[128];
3581
3582 memset(&pfn_param, 0, sizeof(pfn_param));
3583 pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION);
3584
3585 /* set extra pno params */
3586 pfn_param.flags = cpu_to_le16(1 << BRCMF_PNO_ENABLE_ADAPTSCAN_BIT);
3587 pfn_param.repeat = BRCMF_PNO_REPEAT;
3588 pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX;
3589
3590 /* set up pno scan fr */
3591 pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME);
3592
3593 return brcmf_dev_iovar_setbuf(ndev, "pfn_set",
3594 &pfn_param, sizeof(pfn_param),
3595 iovbuf, sizeof(iovbuf));
3596}
3597
3598static int
3599brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
3600 struct net_device *ndev,
3601 struct cfg80211_sched_scan_request *request)
3602{
3603 char iovbuf[128];
3604 struct brcmf_cfg80211_priv *cfg_priv = wiphy_priv(wiphy);
3605 struct brcmf_pno_net_param_le pfn;
3606 int i;
3607 int ret = 0;
3608
3609 WL_SCAN("Enter n_match_sets:%d n_ssids:%d\n",
3610 request->n_match_sets, request->n_ssids);
3611 if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
3612 WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status);
3613 return -EAGAIN;
3614 }
3615
3616 if (!request || !request->n_ssids || !request->n_match_sets) {
3617 WL_ERR("Invalid sched scan req!! n_ssids:%d\n",
3618 request->n_ssids);
3619 return -EINVAL;
3620 }
3621
3622 if (request->n_ssids > 0) {
3623 for (i = 0; i < request->n_ssids; i++) {
3624 /* Active scan req for ssids */
3625 WL_SCAN(">>> Active scan req for ssid (%s)\n",
3626 request->ssids[i].ssid);
3627
3628 /*
3629 * match_set ssids is a supert set of n_ssid list,
3630 * so we need not add these set seperately.
3631 */
3632 }
3633 }
3634
3635 if (request->n_match_sets > 0) {
3636 /* clean up everything */
3637 ret = brcmf_dev_pno_clean(ndev);
3638 if (ret < 0) {
3639 WL_ERR("failed error=%d\n", ret);
3640 return ret;
3641 }
3642
3643 /* configure pno */
3644 ret = brcmf_dev_pno_config(ndev);
3645 if (ret < 0) {
3646 WL_ERR("PNO setup failed!! ret=%d\n", ret);
3647 return -EINVAL;
3648 }
3649
3650 /* configure each match set */
3651 for (i = 0; i < request->n_match_sets; i++) {
3652 struct cfg80211_ssid *ssid;
3653 u32 ssid_len;
3654
3655 ssid = &request->match_sets[i].ssid;
3656 ssid_len = ssid->ssid_len;
3657
3658 if (!ssid_len) {
3659 WL_ERR("skip broadcast ssid\n");
3660 continue;
3661 }
3662 pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN);
3663 pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY);
3664 pfn.wsec = cpu_to_le32(0);
3665 pfn.infra = cpu_to_le32(1);
3666 pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
3667 pfn.ssid.SSID_len = cpu_to_le32(ssid_len);
3668 memcpy(pfn.ssid.SSID, ssid->ssid, ssid_len);
3669 ret = brcmf_dev_iovar_setbuf(ndev, "pfn_add",
3670 &pfn, sizeof(pfn),
3671 iovbuf, sizeof(iovbuf));
3672 WL_SCAN(">>> PNO filter %s for ssid (%s)\n",
3673 ret == 0 ? "set" : "failed",
3674 ssid->ssid);
3675 }
3676 /* Enable the PNO */
3677 if (brcmf_dev_intvar_set(ndev, "pfn", 1) < 0) {
3678 WL_ERR("PNO enable failed!! ret=%d\n", ret);
3679 return -EINVAL;
3680 }
3681 } else {
3682 return -EINVAL;
3683 }
3684
3685 return 0;
3686}
3687
3688static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
3689 struct net_device *ndev)
3690{
3691 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3692
3693 WL_SCAN("enter\n");
3694 brcmf_dev_pno_clean(ndev);
3695 if (cfg_priv->sched_escan)
3696 brcmf_notify_escan_complete(cfg_priv, ndev, true, true);
3697 return 0;
3698}
3699#endif /* CONFIG_BRCMISCAN */
3700
cbaa177d
AS
3701#ifdef CONFIG_NL80211_TESTMODE
3702static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
3703{
3704 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3705 struct net_device *ndev = cfg_priv->wdev->netdev;
3706 struct brcmf_dcmd *dcmd = data;
3707 struct sk_buff *reply;
3708 int ret;
3709
3710 ret = brcmf_netlink_dcmd(ndev, dcmd);
3711 if (ret == 0) {
3712 reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*dcmd));
3713 nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*dcmd), dcmd);
3714 ret = cfg80211_testmode_reply(reply);
3715 }
3716 return ret;
3717}
3718#endif
3719
1a873342
HM
3720static s32 brcmf_configure_opensecurity(struct net_device *ndev, s32 bssidx)
3721{
3722 s32 err;
3723
3724 /* set auth */
3725 err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", 0, bssidx);
3726 if (err < 0) {
3727 WL_ERR("auth error %d\n", err);
3728 return err;
3729 }
3730 /* set wsec */
3731 err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", 0, bssidx);
3732 if (err < 0) {
3733 WL_ERR("wsec error %d\n", err);
3734 return err;
3735 }
3736 /* set upper-layer auth */
3737 err = brcmf_dev_intvar_set_bsscfg(ndev, "wpa_auth",
3738 WPA_AUTH_NONE, bssidx);
3739 if (err < 0) {
3740 WL_ERR("wpa_auth error %d\n", err);
3741 return err;
3742 }
3743
3744 return 0;
3745}
3746
3747static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie)
3748{
3749 if (is_rsn_ie)
3750 return (memcmp(oui, RSN_OUI, TLV_OUI_LEN) == 0);
3751
3752 return (memcmp(oui, WPA_OUI, TLV_OUI_LEN) == 0);
3753}
3754
3755static s32
3756brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
3757 bool is_rsn_ie, s32 bssidx)
3758{
3759 u32 auth = 0; /* d11 open authentication */
3760 u16 count;
3761 s32 err = 0;
3762 s32 len = 0;
3763 u32 i;
3764 u32 wsec;
3765 u32 pval = 0;
3766 u32 gval = 0;
3767 u32 wpa_auth = 0;
3768 u32 offset;
3769 u8 *data;
3770 u16 rsn_cap;
3771 u32 wme_bss_disable;
3772
3773 WL_TRACE("Enter\n");
3774 if (wpa_ie == NULL)
3775 goto exit;
3776
3777 len = wpa_ie->len + TLV_HDR_LEN;
3778 data = (u8 *)wpa_ie;
3779 offset = 0;
3780 if (!is_rsn_ie)
3781 offset += VS_IE_FIXED_HDR_LEN;
3782 offset += WPA_IE_VERSION_LEN;
3783
3784 /* check for multicast cipher suite */
3785 if (offset + WPA_IE_MIN_OUI_LEN > len) {
3786 err = -EINVAL;
3787 WL_ERR("no multicast cipher suite\n");
3788 goto exit;
3789 }
3790
3791 if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
3792 err = -EINVAL;
3793 WL_ERR("ivalid OUI\n");
3794 goto exit;
3795 }
3796 offset += TLV_OUI_LEN;
3797
3798 /* pick up multicast cipher */
3799 switch (data[offset]) {
3800 case WPA_CIPHER_NONE:
3801 gval = 0;
3802 break;
3803 case WPA_CIPHER_WEP_40:
3804 case WPA_CIPHER_WEP_104:
3805 gval = WEP_ENABLED;
3806 break;
3807 case WPA_CIPHER_TKIP:
3808 gval = TKIP_ENABLED;
3809 break;
3810 case WPA_CIPHER_AES_CCM:
3811 gval = AES_ENABLED;
3812 break;
3813 default:
3814 err = -EINVAL;
3815 WL_ERR("Invalid multi cast cipher info\n");
3816 goto exit;
3817 }
3818
3819 offset++;
3820 /* walk thru unicast cipher list and pick up what we recognize */
3821 count = data[offset] + (data[offset + 1] << 8);
3822 offset += WPA_IE_SUITE_COUNT_LEN;
3823 /* Check for unicast suite(s) */
3824 if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) {
3825 err = -EINVAL;
3826 WL_ERR("no unicast cipher suite\n");
3827 goto exit;
3828 }
3829 for (i = 0; i < count; i++) {
3830 if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
3831 err = -EINVAL;
3832 WL_ERR("ivalid OUI\n");
3833 goto exit;
3834 }
3835 offset += TLV_OUI_LEN;
3836 switch (data[offset]) {
3837 case WPA_CIPHER_NONE:
3838 break;
3839 case WPA_CIPHER_WEP_40:
3840 case WPA_CIPHER_WEP_104:
3841 pval |= WEP_ENABLED;
3842 break;
3843 case WPA_CIPHER_TKIP:
3844 pval |= TKIP_ENABLED;
3845 break;
3846 case WPA_CIPHER_AES_CCM:
3847 pval |= AES_ENABLED;
3848 break;
3849 default:
3850 WL_ERR("Ivalid unicast security info\n");
3851 }
3852 offset++;
3853 }
3854 /* walk thru auth management suite list and pick up what we recognize */
3855 count = data[offset] + (data[offset + 1] << 8);
3856 offset += WPA_IE_SUITE_COUNT_LEN;
3857 /* Check for auth key management suite(s) */
3858 if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) {
3859 err = -EINVAL;
3860 WL_ERR("no auth key mgmt suite\n");
3861 goto exit;
3862 }
3863 for (i = 0; i < count; i++) {
3864 if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
3865 err = -EINVAL;
3866 WL_ERR("ivalid OUI\n");
3867 goto exit;
3868 }
3869 offset += TLV_OUI_LEN;
3870 switch (data[offset]) {
3871 case RSN_AKM_NONE:
3872 WL_TRACE("RSN_AKM_NONE\n");
3873 wpa_auth |= WPA_AUTH_NONE;
3874 break;
3875 case RSN_AKM_UNSPECIFIED:
3876 WL_TRACE("RSN_AKM_UNSPECIFIED\n");
3877 is_rsn_ie ? (wpa_auth |= WPA2_AUTH_UNSPECIFIED) :
3878 (wpa_auth |= WPA_AUTH_UNSPECIFIED);
3879 break;
3880 case RSN_AKM_PSK:
3881 WL_TRACE("RSN_AKM_PSK\n");
3882 is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) :
3883 (wpa_auth |= WPA_AUTH_PSK);
3884 break;
3885 default:
3886 WL_ERR("Ivalid key mgmt info\n");
3887 }
3888 offset++;
3889 }
3890
3891 if (is_rsn_ie) {
3892 wme_bss_disable = 1;
3893 if ((offset + RSN_CAP_LEN) <= len) {
3894 rsn_cap = data[offset] + (data[offset + 1] << 8);
3895 if (rsn_cap & RSN_CAP_PTK_REPLAY_CNTR_MASK)
3896 wme_bss_disable = 0;
3897 }
3898 /* set wme_bss_disable to sync RSN Capabilities */
3899 err = brcmf_dev_intvar_set_bsscfg(ndev, "wme_bss_disable",
3900 wme_bss_disable, bssidx);
3901 if (err < 0) {
3902 WL_ERR("wme_bss_disable error %d\n", err);
3903 goto exit;
3904 }
3905 }
3906 /* FOR WPS , set SES_OW_ENABLED */
3907 wsec = (pval | gval | SES_OW_ENABLED);
3908
3909 /* set auth */
3910 err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", auth, bssidx);
3911 if (err < 0) {
3912 WL_ERR("auth error %d\n", err);
3913 goto exit;
3914 }
3915 /* set wsec */
3916 err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", wsec, bssidx);
3917 if (err < 0) {
3918 WL_ERR("wsec error %d\n", err);
3919 goto exit;
3920 }
3921 /* set upper-layer auth */
3922 err = brcmf_dev_intvar_set_bsscfg(ndev, "wpa_auth", wpa_auth, bssidx);
3923 if (err < 0) {
3924 WL_ERR("wpa_auth error %d\n", err);
3925 goto exit;
3926 }
3927
3928exit:
3929 return err;
3930}
3931
3932static s32
3933brcmf_parse_vndr_ies(u8 *vndr_ie_buf, u32 vndr_ie_len,
3934 struct parsed_vndr_ies *vndr_ies)
3935{
3936 s32 err = 0;
3937 struct brcmf_vs_tlv *vndrie;
3938 struct brcmf_tlv *ie;
3939 struct parsed_vndr_ie_info *parsed_info;
3940 s32 remaining_len;
3941
3942 remaining_len = (s32)vndr_ie_len;
3943 memset(vndr_ies, 0, sizeof(*vndr_ies));
3944
3945 ie = (struct brcmf_tlv *)vndr_ie_buf;
3946 while (ie) {
3947 if (ie->id != WLAN_EID_VENDOR_SPECIFIC)
3948 goto next;
3949 vndrie = (struct brcmf_vs_tlv *)ie;
3950 /* len should be bigger than OUI length + one */
3951 if (vndrie->len < (VS_IE_FIXED_HDR_LEN - TLV_HDR_LEN + 1)) {
3952 WL_ERR("invalid vndr ie. length is too small %d\n",
3953 vndrie->len);
3954 goto next;
3955 }
3956 /* if wpa or wme ie, do not add ie */
3957 if (!memcmp(vndrie->oui, (u8 *)WPA_OUI, TLV_OUI_LEN) &&
3958 ((vndrie->oui_type == WPA_OUI_TYPE) ||
3959 (vndrie->oui_type == WME_OUI_TYPE))) {
3960 WL_TRACE("Found WPA/WME oui. Do not add it\n");
3961 goto next;
3962 }
3963
3964 parsed_info = &vndr_ies->ie_info[vndr_ies->count];
3965
3966 /* save vndr ie information */
3967 parsed_info->ie_ptr = (char *)vndrie;
3968 parsed_info->ie_len = vndrie->len + TLV_HDR_LEN;
3969 memcpy(&parsed_info->vndrie, vndrie, sizeof(*vndrie));
3970
3971 vndr_ies->count++;
3972
3973 WL_TRACE("** OUI %02x %02x %02x, type 0x%02x\n",
3974 parsed_info->vndrie.oui[0],
3975 parsed_info->vndrie.oui[1],
3976 parsed_info->vndrie.oui[2],
3977 parsed_info->vndrie.oui_type);
3978
3979 if (vndr_ies->count >= MAX_VNDR_IE_NUMBER)
3980 break;
3981next:
3982 remaining_len -= ie->len;
3983 if (remaining_len <= 2)
3984 ie = NULL;
3985 else
3986 ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len);
3987 }
3988 return err;
3989}
3990
3991static u32
3992brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd)
3993{
3994
3995 __le32 iecount_le;
3996 __le32 pktflag_le;
3997
3998 strncpy(iebuf, add_del_cmd, VNDR_IE_CMD_LEN - 1);
3999 iebuf[VNDR_IE_CMD_LEN - 1] = '\0';
4000
4001 iecount_le = cpu_to_le32(1);
4002 memcpy(&iebuf[VNDR_IE_COUNT_OFFSET], &iecount_le, sizeof(iecount_le));
4003
4004 pktflag_le = cpu_to_le32(pktflag);
4005 memcpy(&iebuf[VNDR_IE_PKTFLAG_OFFSET], &pktflag_le, sizeof(pktflag_le));
4006
4007 memcpy(&iebuf[VNDR_IE_VSIE_OFFSET], ie_ptr, ie_len);
4008
4009 return ie_len + VNDR_IE_HDR_SIZE;
4010}
4011
4012s32
4013brcmf_set_management_ie(struct brcmf_cfg80211_priv *cfg_priv,
4014 struct net_device *ndev, s32 bssidx, s32 pktflag,
4015 u8 *vndr_ie_buf, u32 vndr_ie_len)
4016{
4017 s32 err = 0;
4018 u8 *iovar_ie_buf;
4019 u8 *curr_ie_buf;
4020 u8 *mgmt_ie_buf = NULL;
4021 u32 mgmt_ie_buf_len = 0;
4022 u32 *mgmt_ie_len = 0;
4023 u32 del_add_ie_buf_len = 0;
4024 u32 total_ie_buf_len = 0;
4025 u32 parsed_ie_buf_len = 0;
4026 struct parsed_vndr_ies old_vndr_ies;
4027 struct parsed_vndr_ies new_vndr_ies;
4028 struct parsed_vndr_ie_info *vndrie_info;
4029 s32 i;
4030 u8 *ptr;
4031 u32 remained_buf_len;
4032
4033 WL_TRACE("bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag);
4034 iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
4035 if (!iovar_ie_buf)
4036 return -ENOMEM;
4037 curr_ie_buf = iovar_ie_buf;
4038 if (test_bit(WL_STATUS_AP_CREATING, &cfg_priv->status) ||
4039 test_bit(WL_STATUS_AP_CREATED, &cfg_priv->status)) {
4040 switch (pktflag) {
4041 case VNDR_IE_PRBRSP_FLAG:
4042 mgmt_ie_buf = cfg_priv->ap_info->probe_res_ie;
4043 mgmt_ie_len = &cfg_priv->ap_info->probe_res_ie_len;
4044 mgmt_ie_buf_len =
4045 sizeof(cfg_priv->ap_info->probe_res_ie);
4046 break;
4047 case VNDR_IE_BEACON_FLAG:
4048 mgmt_ie_buf = cfg_priv->ap_info->beacon_ie;
4049 mgmt_ie_len = &cfg_priv->ap_info->beacon_ie_len;
4050 mgmt_ie_buf_len = sizeof(cfg_priv->ap_info->beacon_ie);
4051 break;
4052 default:
4053 err = -EPERM;
4054 WL_ERR("not suitable type\n");
4055 goto exit;
4056 }
4057 bssidx = 0;
4058 } else {
4059 err = -EPERM;
4060 WL_ERR("not suitable type\n");
4061 goto exit;
4062 }
4063
4064 if (vndr_ie_len > mgmt_ie_buf_len) {
4065 err = -ENOMEM;
4066 WL_ERR("extra IE size too big\n");
4067 goto exit;
4068 }
4069
4070 /* parse and save new vndr_ie in curr_ie_buff before comparing it */
4071 if (vndr_ie_buf && vndr_ie_len && curr_ie_buf) {
4072 ptr = curr_ie_buf;
4073 brcmf_parse_vndr_ies(vndr_ie_buf, vndr_ie_len, &new_vndr_ies);
4074 for (i = 0; i < new_vndr_ies.count; i++) {
4075 vndrie_info = &new_vndr_ies.ie_info[i];
4076 memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr,
4077 vndrie_info->ie_len);
4078 parsed_ie_buf_len += vndrie_info->ie_len;
4079 }
4080 }
4081
4082 if (mgmt_ie_buf != NULL) {
4083 if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) &&
4084 (memcmp(mgmt_ie_buf, curr_ie_buf,
4085 parsed_ie_buf_len) == 0)) {
4086 WL_TRACE("Previous mgmt IE is equals to current IE");
4087 goto exit;
4088 }
4089
4090 /* parse old vndr_ie */
4091 brcmf_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len, &old_vndr_ies);
4092
4093 /* make a command to delete old ie */
4094 for (i = 0; i < old_vndr_ies.count; i++) {
4095 vndrie_info = &old_vndr_ies.ie_info[i];
4096
4097 WL_TRACE("DEL ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
4098 vndrie_info->vndrie.id,
4099 vndrie_info->vndrie.len,
4100 vndrie_info->vndrie.oui[0],
4101 vndrie_info->vndrie.oui[1],
4102 vndrie_info->vndrie.oui[2]);
4103
4104 del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag,
4105 vndrie_info->ie_ptr,
4106 vndrie_info->ie_len,
4107 "del");
4108 curr_ie_buf += del_add_ie_buf_len;
4109 total_ie_buf_len += del_add_ie_buf_len;
4110 }
4111 }
4112
4113 *mgmt_ie_len = 0;
4114 /* Add if there is any extra IE */
4115 if (mgmt_ie_buf && parsed_ie_buf_len) {
4116 ptr = mgmt_ie_buf;
4117
4118 remained_buf_len = mgmt_ie_buf_len;
4119
4120 /* make a command to add new ie */
4121 for (i = 0; i < new_vndr_ies.count; i++) {
4122 vndrie_info = &new_vndr_ies.ie_info[i];
4123
4124 WL_TRACE("ADDED ID : %d, Len: %d, OUI:%02x:%02x:%02x\n",
4125 vndrie_info->vndrie.id,
4126 vndrie_info->vndrie.len,
4127 vndrie_info->vndrie.oui[0],
4128 vndrie_info->vndrie.oui[1],
4129 vndrie_info->vndrie.oui[2]);
4130
4131 del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag,
4132 vndrie_info->ie_ptr,
4133 vndrie_info->ie_len,
4134 "add");
4135 /* verify remained buf size before copy data */
4136 remained_buf_len -= vndrie_info->ie_len;
4137 if (remained_buf_len < 0) {
4138 WL_ERR("no space in mgmt_ie_buf: len left %d",
4139 remained_buf_len);
4140 break;
4141 }
4142
4143 /* save the parsed IE in wl struct */
4144 memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr,
4145 vndrie_info->ie_len);
4146 *mgmt_ie_len += vndrie_info->ie_len;
4147
4148 curr_ie_buf += del_add_ie_buf_len;
4149 total_ie_buf_len += del_add_ie_buf_len;
4150 }
4151 }
4152 if (total_ie_buf_len) {
4153 err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "vndr_ie",
4154 iovar_ie_buf,
4155 total_ie_buf_len,
4156 cfg_priv->extra_buf,
4157 WL_EXTRA_BUF_MAX, bssidx);
4158 if (err)
4159 WL_ERR("vndr ie set error : %d\n", err);
4160 }
4161
4162exit:
4163 kfree(iovar_ie_buf);
4164 return err;
4165}
4166
4167static s32
4168brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
4169 struct cfg80211_ap_settings *settings)
4170{
4171 s32 ie_offset;
4172 struct brcmf_tlv *ssid_ie;
4173 struct brcmf_ssid_le ssid_le;
4174 s32 ioctl_value;
4175 s32 err = -EPERM;
4176 struct brcmf_tlv *rsn_ie;
4177 struct brcmf_vs_tlv *wpa_ie;
4178 struct brcmf_join_params join_params;
4179 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
4180 s32 bssidx = 0;
4181
4182 WL_TRACE("channel_type=%d, beacon_interval=%d, dtim_period=%d,\n",
4183 settings->channel_type, settings->beacon_interval,
4184 settings->dtim_period);
4185 WL_TRACE("ssid=%s(%d), auth_type=%d, inactivity_timeout=%d\n",
4186 settings->ssid, settings->ssid_len, settings->auth_type,
4187 settings->inactivity_timeout);
4188
4189 if (!test_bit(WL_STATUS_AP_CREATING, &cfg_priv->status)) {
4190 WL_ERR("Not in AP creation mode\n");
4191 return -EPERM;
4192 }
4193
4194 memset(&ssid_le, 0, sizeof(ssid_le));
4195 if (settings->ssid == NULL || settings->ssid_len == 0) {
4196 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
4197 ssid_ie = brcmf_parse_tlvs(
4198 (u8 *)&settings->beacon.head[ie_offset],
4199 settings->beacon.head_len - ie_offset,
4200 WLAN_EID_SSID);
4201 if (!ssid_ie)
4202 return -EINVAL;
4203
4204 memcpy(ssid_le.SSID, ssid_ie->data, ssid_ie->len);
4205 ssid_le.SSID_len = cpu_to_le32(ssid_ie->len);
4206 WL_TRACE("SSID is (%s) in Head\n", ssid_le.SSID);
4207 } else {
4208 memcpy(ssid_le.SSID, settings->ssid, settings->ssid_len);
4209 ssid_le.SSID_len = cpu_to_le32((u32)settings->ssid_len);
4210 }
4211
4212 brcmf_set_mpc(ndev, 0);
4213 ioctl_value = 1;
4214 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_DOWN, &ioctl_value);
4215 if (err < 0) {
4216 WL_ERR("BRCMF_C_DOWN error %d\n", err);
4217 goto exit;
4218 }
4219 ioctl_value = 1;
4220 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &ioctl_value);
4221 if (err < 0) {
4222 WL_ERR("SET INFRA error %d\n", err);
4223 goto exit;
4224 }
4225 ioctl_value = 1;
4226 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AP, &ioctl_value);
4227 if (err < 0) {
4228 WL_ERR("setting AP mode failed %d\n", err);
4229 goto exit;
4230 }
4231
4232 /* find the RSN_IE */
4233 rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
4234 settings->beacon.tail_len, WLAN_EID_RSN);
4235
4236 /* find the WPA_IE */
4237 wpa_ie = brcmf_find_wpaie((u8 *)settings->beacon.tail,
4238 settings->beacon.tail_len);
4239
4240 kfree(cfg_priv->ap_info->rsn_ie);
4241 cfg_priv->ap_info->rsn_ie = NULL;
4242 kfree(cfg_priv->ap_info->wpa_ie);
4243 cfg_priv->ap_info->wpa_ie = NULL;
4244
4245 if ((wpa_ie != NULL || rsn_ie != NULL)) {
4246 WL_TRACE("WPA(2) IE is found\n");
4247 if (wpa_ie != NULL) {
4248 /* WPA IE */
4249 err = brcmf_configure_wpaie(ndev, wpa_ie, false,
4250 bssidx);
4251 if (err < 0)
4252 goto exit;
4253 cfg_priv->ap_info->wpa_ie = kmemdup(wpa_ie,
4254 wpa_ie->len +
4255 TLV_HDR_LEN,
4256 GFP_KERNEL);
4257 } else {
4258 /* RSN IE */
4259 err = brcmf_configure_wpaie(ndev,
4260 (struct brcmf_vs_tlv *)rsn_ie, true, bssidx);
4261 if (err < 0)
4262 goto exit;
4263 cfg_priv->ap_info->rsn_ie = kmemdup(rsn_ie,
4264 rsn_ie->len +
4265 TLV_HDR_LEN,
4266 GFP_KERNEL);
4267 }
4268 cfg_priv->ap_info->security_mode = true;
4269 } else {
4270 WL_TRACE("No WPA(2) IEs found\n");
4271 brcmf_configure_opensecurity(ndev, bssidx);
4272 cfg_priv->ap_info->security_mode = false;
4273 }
4274 /* Set Beacon IEs to FW */
4275 err = brcmf_set_management_ie(cfg_priv, ndev, bssidx,
4276 VNDR_IE_BEACON_FLAG,
4277 (u8 *)settings->beacon.tail,
4278 settings->beacon.tail_len);
4279 if (err)
4280 WL_ERR("Set Beacon IE Failed\n");
4281 else
4282 WL_TRACE("Applied Vndr IEs for Beacon\n");
4283
4284 /* Set Probe Response IEs to FW */
4285 err = brcmf_set_management_ie(cfg_priv, ndev, bssidx,
4286 VNDR_IE_PRBRSP_FLAG,
4287 (u8 *)settings->beacon.proberesp_ies,
4288 settings->beacon.proberesp_ies_len);
4289 if (err)
4290 WL_ERR("Set Probe Resp IE Failed\n");
4291 else
4292 WL_TRACE("Applied Vndr IEs for Probe Resp\n");
4293
4294 if (settings->beacon_interval) {
4295 ioctl_value = settings->beacon_interval;
4296 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_BCNPRD,
4297 &ioctl_value);
4298 if (err < 0) {
4299 WL_ERR("Beacon Interval Set Error, %d\n", err);
4300 goto exit;
4301 }
4302 }
4303 if (settings->dtim_period) {
4304 ioctl_value = settings->dtim_period;
4305 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_DTIMPRD,
4306 &ioctl_value);
4307 if (err < 0) {
4308 WL_ERR("DTIM Interval Set Error, %d\n", err);
4309 goto exit;
4310 }
4311 }
4312 ioctl_value = 1;
4313 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_UP, &ioctl_value);
4314 if (err < 0) {
4315 WL_ERR("BRCMF_C_UP error (%d)\n", err);
4316 goto exit;
4317 }
4318
4319 memset(&join_params, 0, sizeof(join_params));
4320 /* join parameters starts with ssid */
4321 memcpy(&join_params.ssid_le, &ssid_le, sizeof(ssid_le));
4322 /* create softap */
4323 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, &join_params,
4324 sizeof(join_params));
4325 if (err < 0) {
4326 WL_ERR("SET SSID error (%d)\n", err);
4327 goto exit;
4328 }
4329 clear_bit(WL_STATUS_AP_CREATING, &cfg_priv->status);
4330 set_bit(WL_STATUS_AP_CREATED, &cfg_priv->status);
4331
4332exit:
4333 if (err)
4334 brcmf_set_mpc(ndev, 1);
4335 return err;
4336}
4337
4338static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
4339{
4340 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
4341 s32 ioctl_value;
4342 s32 err = -EPERM;
4343
4344 WL_TRACE("Enter\n");
4345
4346 if (cfg_priv->conf->mode == WL_MODE_AP) {
4347 /* Due to most likely deauths outstanding we sleep */
4348 /* first to make sure they get processed by fw. */
4349 msleep(400);
4350 ioctl_value = 0;
4351 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AP, &ioctl_value);
4352 if (err < 0) {
4353 WL_ERR("setting AP mode failed %d\n", err);
4354 goto exit;
4355 }
4356 ioctl_value = 0;
4357 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_UP, &ioctl_value);
4358 if (err < 0) {
4359 WL_ERR("BRCMF_C_UP error %d\n", err);
4360 goto exit;
4361 }
4362 brcmf_set_mpc(ndev, 1);
4363 clear_bit(WL_STATUS_AP_CREATING, &cfg_priv->status);
4364 clear_bit(WL_STATUS_AP_CREATED, &cfg_priv->status);
4365 }
4366exit:
4367 return err;
4368}
4369
4370static int
4371brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
4372 u8 *mac)
4373{
4374 struct brcmf_scb_val_le scbval;
4375 s32 err;
4376
4377 if (!mac)
4378 return -EFAULT;
4379
4380 WL_TRACE("Enter %pM\n", mac);
4381
4382 if (!check_sys_up(wiphy))
4383 return -EIO;
4384
4385 memcpy(&scbval.ea, mac, ETH_ALEN);
4386 scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING);
4387 err = brcmf_exec_dcmd(ndev, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON,
4388 &scbval, sizeof(scbval));
4389 if (err)
4390 WL_ERR("SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err);
4391
4392 WL_TRACE("Exit\n");
4393 return err;
4394}
4395
5b435de0
AS
4396static struct cfg80211_ops wl_cfg80211_ops = {
4397 .change_virtual_intf = brcmf_cfg80211_change_iface,
4398 .scan = brcmf_cfg80211_scan,
4399 .set_wiphy_params = brcmf_cfg80211_set_wiphy_params,
4400 .join_ibss = brcmf_cfg80211_join_ibss,
4401 .leave_ibss = brcmf_cfg80211_leave_ibss,
4402 .get_station = brcmf_cfg80211_get_station,
4403 .set_tx_power = brcmf_cfg80211_set_tx_power,
4404 .get_tx_power = brcmf_cfg80211_get_tx_power,
4405 .add_key = brcmf_cfg80211_add_key,
4406 .del_key = brcmf_cfg80211_del_key,
4407 .get_key = brcmf_cfg80211_get_key,
4408 .set_default_key = brcmf_cfg80211_config_default_key,
4409 .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key,
4410 .set_power_mgmt = brcmf_cfg80211_set_power_mgmt,
4411 .set_bitrate_mask = brcmf_cfg80211_set_bitrate_mask,
4412 .connect = brcmf_cfg80211_connect,
4413 .disconnect = brcmf_cfg80211_disconnect,
4414 .suspend = brcmf_cfg80211_suspend,
4415 .resume = brcmf_cfg80211_resume,
4416 .set_pmksa = brcmf_cfg80211_set_pmksa,
4417 .del_pmksa = brcmf_cfg80211_del_pmksa,
cbaa177d 4418 .flush_pmksa = brcmf_cfg80211_flush_pmksa,
1a873342
HM
4419 .start_ap = brcmf_cfg80211_start_ap,
4420 .stop_ap = brcmf_cfg80211_stop_ap,
4421 .del_station = brcmf_cfg80211_del_station,
e5806072
AS
4422#ifndef CONFIG_BRCMISCAN
4423 /* scheduled scan need e-scan, which is mutual exclusive with i-scan */
4424 .sched_scan_start = brcmf_cfg80211_sched_scan_start,
4425 .sched_scan_stop = brcmf_cfg80211_sched_scan_stop,
4426#endif
cbaa177d
AS
4427#ifdef CONFIG_NL80211_TESTMODE
4428 .testmode_cmd = brcmf_cfg80211_testmode
4429#endif
5b435de0
AS
4430};
4431
4432static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
4433{
4434 s32 err = 0;
4435
4436 switch (mode) {
4437 case WL_MODE_BSS:
4438 return NL80211_IFTYPE_STATION;
4439 case WL_MODE_IBSS:
4440 return NL80211_IFTYPE_ADHOC;
4441 default:
4442 return NL80211_IFTYPE_UNSPECIFIED;
4443 }
4444
4445 return err;
4446}
4447
e5806072
AS
4448static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
4449{
4450#ifndef CONFIG_BRCMFISCAN
4451 /* scheduled scan settings */
4452 wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
4453 wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
4454 wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
4455 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
4456#endif
4457}
4458
5db6e956 4459static struct wireless_dev *brcmf_alloc_wdev(struct device *ndev)
5b435de0
AS
4460{
4461 struct wireless_dev *wdev;
4462 s32 err = 0;
4463
4464 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
4465 if (!wdev)
4466 return ERR_PTR(-ENOMEM);
4467
5db6e956
AS
4468 wdev->wiphy = wiphy_new(&wl_cfg80211_ops,
4469 sizeof(struct brcmf_cfg80211_priv));
5b435de0 4470 if (!wdev->wiphy) {
bfeb4dbc 4471 WL_ERR("Could not allocate wiphy device\n");
5b435de0
AS
4472 err = -ENOMEM;
4473 goto wiphy_new_out;
4474 }
4475 set_wiphy_dev(wdev->wiphy, ndev);
4476 wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
4477 wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
1a873342
HM
4478 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
4479 BIT(NL80211_IFTYPE_ADHOC) |
4480 BIT(NL80211_IFTYPE_AP);
5b435de0
AS
4481 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
4482 wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set
4483 * it as 11a by default.
4484 * This will be updated with
4485 * 11n phy tables in
4486 * "ifconfig up"
4487 * if phy has 11n capability
4488 */
4489 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
4490 wdev->wiphy->cipher_suites = __wl_cipher_suites;
4491 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
4492 wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power
4493 * save mode
4494 * by default
4495 */
e5806072 4496 brcmf_wiphy_pno_params(wdev->wiphy);
5b435de0
AS
4497 err = wiphy_register(wdev->wiphy);
4498 if (err < 0) {
bfeb4dbc 4499 WL_ERR("Could not register wiphy device (%d)\n", err);
5b435de0
AS
4500 goto wiphy_register_out;
4501 }
4502 return wdev;
4503
4504wiphy_register_out:
4505 wiphy_free(wdev->wiphy);
4506
4507wiphy_new_out:
4508 kfree(wdev);
4509
4510 return ERR_PTR(err);
4511}
4512
4513static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv)
4514{
4515 struct wireless_dev *wdev = cfg_priv->wdev;
4516
4517 if (!wdev) {
4518 WL_ERR("wdev is invalid\n");
4519 return;
4520 }
4521 wiphy_unregister(wdev->wiphy);
4522 wiphy_free(wdev->wiphy);
4523 kfree(wdev);
4524 cfg_priv->wdev = NULL;
4525}
4526
4527static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv,
4528 const struct brcmf_event_msg *e)
4529{
4530 u32 event = be32_to_cpu(e->event_type);
4531 u32 status = be32_to_cpu(e->status);
4532
4533 if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
4534 WL_CONN("Processing set ssid\n");
4535 cfg_priv->link_up = true;
4536 return true;
4537 }
4538
4539 return false;
4540}
4541
4542static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv,
4543 const struct brcmf_event_msg *e)
4544{
4545 u32 event = be32_to_cpu(e->event_type);
4546 u16 flags = be16_to_cpu(e->flags);
4547
4548 if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) {
4549 WL_CONN("Processing link down\n");
4550 return true;
4551 }
4552 return false;
4553}
4554
4555static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv,
4556 const struct brcmf_event_msg *e)
4557{
4558 u32 event = be32_to_cpu(e->event_type);
4559 u32 status = be32_to_cpu(e->status);
4560
4561 if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) {
4562 WL_CONN("Processing Link %s & no network found\n",
4563 be16_to_cpu(e->flags) & BRCMF_EVENT_MSG_LINK ?
4564 "up" : "down");
4565 return true;
4566 }
4567
4568 if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) {
4569 WL_CONN("Processing connecting & no network found\n");
4570 return true;
4571 }
4572
4573 return false;
4574}
4575
4576static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
4577{
4578 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
4579
4580 kfree(conn_info->req_ie);
4581 conn_info->req_ie = NULL;
4582 conn_info->req_ie_len = 0;
4583 kfree(conn_info->resp_ie);
4584 conn_info->resp_ie = NULL;
4585 conn_info->resp_ie_len = 0;
4586}
4587
4588static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
4589{
4590 struct net_device *ndev = cfg_to_ndev(cfg_priv);
c4e382d2 4591 struct brcmf_cfg80211_assoc_ielen_le *assoc_info;
5b435de0
AS
4592 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
4593 u32 req_len;
4594 u32 resp_len;
4595 s32 err = 0;
4596
4597 brcmf_clear_assoc_ies(cfg_priv);
4598
4599 err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg_priv->extra_buf,
4600 WL_ASSOC_INFO_MAX);
4601 if (err) {
4602 WL_ERR("could not get assoc info (%d)\n", err);
4603 return err;
4604 }
c4e382d2
AS
4605 assoc_info =
4606 (struct brcmf_cfg80211_assoc_ielen_le *)cfg_priv->extra_buf;
4607 req_len = le32_to_cpu(assoc_info->req_len);
4608 resp_len = le32_to_cpu(assoc_info->resp_len);
5b435de0
AS
4609 if (req_len) {
4610 err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies",
4611 cfg_priv->extra_buf,
4612 WL_ASSOC_INFO_MAX);
4613 if (err) {
4614 WL_ERR("could not get assoc req (%d)\n", err);
4615 return err;
4616 }
4617 conn_info->req_ie_len = req_len;
4618 conn_info->req_ie =
4619 kmemdup(cfg_priv->extra_buf, conn_info->req_ie_len,
4620 GFP_KERNEL);
4621 } else {
4622 conn_info->req_ie_len = 0;
4623 conn_info->req_ie = NULL;
4624 }
4625 if (resp_len) {
4626 err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies",
4627 cfg_priv->extra_buf,
4628 WL_ASSOC_INFO_MAX);
4629 if (err) {
4630 WL_ERR("could not get assoc resp (%d)\n", err);
4631 return err;
4632 }
4633 conn_info->resp_ie_len = resp_len;
4634 conn_info->resp_ie =
4635 kmemdup(cfg_priv->extra_buf, conn_info->resp_ie_len,
4636 GFP_KERNEL);
4637 } else {
4638 conn_info->resp_ie_len = 0;
4639 conn_info->resp_ie = NULL;
4640 }
4641 WL_CONN("req len (%d) resp len (%d)\n",
4642 conn_info->req_ie_len, conn_info->resp_ie_len);
4643
4644 return err;
4645}
4646
4647static s32
4648brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
4649 struct net_device *ndev,
4650 const struct brcmf_event_msg *e)
4651{
4652 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
4653 struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
4654 struct brcmf_channel_info_le channel_le;
4655 struct ieee80211_channel *notify_channel;
4656 struct ieee80211_supported_band *band;
4657 u32 freq;
4658 s32 err = 0;
4659 u32 target_channel;
4660
4661 WL_TRACE("Enter\n");
4662
4663 brcmf_get_assoc_ies(cfg_priv);
4664 brcmf_update_prof(cfg_priv, NULL, &e->addr, WL_PROF_BSSID);
4665 brcmf_update_bss_info(cfg_priv);
4666
4667 brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le,
4668 sizeof(channel_le));
4669
4670 target_channel = le32_to_cpu(channel_le.target_channel);
4671 WL_CONN("Roamed to channel %d\n", target_channel);
4672
4673 if (target_channel <= CH_MAX_2G_CHANNEL)
4674 band = wiphy->bands[IEEE80211_BAND_2GHZ];
4675 else
4676 band = wiphy->bands[IEEE80211_BAND_5GHZ];
4677
4678 freq = ieee80211_channel_to_frequency(target_channel, band->band);
4679 notify_channel = ieee80211_get_channel(wiphy, freq);
4680
4681 cfg80211_roamed(ndev, notify_channel,
4682 (u8 *)brcmf_read_prof(cfg_priv, WL_PROF_BSSID),
4683 conn_info->req_ie, conn_info->req_ie_len,
4684 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
4685 WL_CONN("Report roaming result\n");
4686
4687 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
4688 WL_TRACE("Exit\n");
4689 return err;
4690}
4691
4692static s32
4693brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
4694 struct net_device *ndev, const struct brcmf_event_msg *e,
4695 bool completed)
4696{
4697 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
4698 s32 err = 0;
4699
4700 WL_TRACE("Enter\n");
4701
4702 if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
4703 if (completed) {
4704 brcmf_get_assoc_ies(cfg_priv);
4705 brcmf_update_prof(cfg_priv, NULL, &e->addr,
4706 WL_PROF_BSSID);
4707 brcmf_update_bss_info(cfg_priv);
4708 }
4709 cfg80211_connect_result(ndev,
4710 (u8 *)brcmf_read_prof(cfg_priv,
4711 WL_PROF_BSSID),
4712 conn_info->req_ie,
4713 conn_info->req_ie_len,
4714 conn_info->resp_ie,
4715 conn_info->resp_ie_len,
4716 completed ? WLAN_STATUS_SUCCESS :
4717 WLAN_STATUS_AUTH_TIMEOUT,
4718 GFP_KERNEL);
4719 if (completed)
4720 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
4721 WL_CONN("Report connect result - connection %s\n",
4722 completed ? "succeeded" : "failed");
4723 }
4724 WL_TRACE("Exit\n");
4725 return err;
4726}
4727
1a873342
HM
4728static s32
4729brcmf_notify_connect_status_ap(struct brcmf_cfg80211_priv *cfg_priv,
4730 struct net_device *ndev,
4731 const struct brcmf_event_msg *e, void *data)
4732{
4733 s32 err = 0;
4734 u32 event = be32_to_cpu(e->event_type);
4735 u32 reason = be32_to_cpu(e->reason);
4736 u32 len = be32_to_cpu(e->datalen);
4737 static int generation;
4738
4739 struct station_info sinfo;
4740
4741 WL_CONN("event %d, reason %d\n", event, reason);
4742 memset(&sinfo, 0, sizeof(sinfo));
4743
4744 sinfo.filled = 0;
4745 if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) &&
4746 reason == BRCMF_E_STATUS_SUCCESS) {
4747 sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
4748 if (!data) {
4749 WL_ERR("No IEs present in ASSOC/REASSOC_IND");
4750 return -EINVAL;
4751 }
4752 sinfo.assoc_req_ies = data;
4753 sinfo.assoc_req_ies_len = len;
4754 generation++;
4755 sinfo.generation = generation;
4756 cfg80211_new_sta(ndev, e->addr, &sinfo, GFP_ATOMIC);
4757 } else if ((event == BRCMF_E_DISASSOC_IND) ||
4758 (event == BRCMF_E_DEAUTH_IND) ||
4759 (event == BRCMF_E_DEAUTH)) {
4760 generation++;
4761 sinfo.generation = generation;
4762 cfg80211_del_sta(ndev, e->addr, GFP_ATOMIC);
4763 }
4764 return err;
4765}
4766
5b435de0
AS
4767static s32
4768brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv,
4769 struct net_device *ndev,
4770 const struct brcmf_event_msg *e, void *data)
4771{
4772 s32 err = 0;
4773
1a873342
HM
4774 if (cfg_priv->conf->mode == WL_MODE_AP) {
4775 err = brcmf_notify_connect_status_ap(cfg_priv, ndev, e, data);
4776 } else if (brcmf_is_linkup(cfg_priv, e)) {
5b435de0
AS
4777 WL_CONN("Linkup\n");
4778 if (brcmf_is_ibssmode(cfg_priv)) {
4779 brcmf_update_prof(cfg_priv, NULL, (void *)e->addr,
4780 WL_PROF_BSSID);
4781 wl_inform_ibss(cfg_priv, ndev, e->addr);
4782 cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
4783 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
4784 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
4785 } else
4786 brcmf_bss_connect_done(cfg_priv, ndev, e, true);
4787 } else if (brcmf_is_linkdown(cfg_priv, e)) {
4788 WL_CONN("Linkdown\n");
4789 if (brcmf_is_ibssmode(cfg_priv)) {
4790 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
4791 if (test_and_clear_bit(WL_STATUS_CONNECTED,
4792 &cfg_priv->status))
4793 brcmf_link_down(cfg_priv);
4794 } else {
4795 brcmf_bss_connect_done(cfg_priv, ndev, e, false);
4796 if (test_and_clear_bit(WL_STATUS_CONNECTED,
4797 &cfg_priv->status)) {
4798 cfg80211_disconnected(ndev, 0, NULL, 0,
4799 GFP_KERNEL);
4800 brcmf_link_down(cfg_priv);
4801 }
4802 }
4803 brcmf_init_prof(cfg_priv->profile);
4804 } else if (brcmf_is_nonetwork(cfg_priv, e)) {
4805 if (brcmf_is_ibssmode(cfg_priv))
4806 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
4807 else
4808 brcmf_bss_connect_done(cfg_priv, ndev, e, false);
4809 }
4810
4811 return err;
4812}
4813
4814static s32
4815brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv,
4816 struct net_device *ndev,
4817 const struct brcmf_event_msg *e, void *data)
4818{
4819 s32 err = 0;
4820 u32 event = be32_to_cpu(e->event_type);
4821 u32 status = be32_to_cpu(e->status);
4822
4823 if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
4824 if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status))
4825 brcmf_bss_roaming_done(cfg_priv, ndev, e);
4826 else
4827 brcmf_bss_connect_done(cfg_priv, ndev, e, true);
4828 }
4829
4830 return err;
4831}
4832
4833static s32
4834brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
4835 struct net_device *ndev,
4836 const struct brcmf_event_msg *e, void *data)
4837{
4838 u16 flags = be16_to_cpu(e->flags);
4839 enum nl80211_key_type key_type;
4840
4841 if (flags & BRCMF_EVENT_MSG_GROUP)
4842 key_type = NL80211_KEYTYPE_GROUP;
4843 else
4844 key_type = NL80211_KEYTYPE_PAIRWISE;
4845
4846 cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
4847 NULL, GFP_KERNEL);
4848
4849 return 0;
4850}
4851
4852static s32
4853brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
4854 struct net_device *ndev,
4855 const struct brcmf_event_msg *e, void *data)
4856{
4857 struct brcmf_channel_info_le channel_inform_le;
4858 struct brcmf_scan_results_le *bss_list_le;
4859 u32 len = WL_SCAN_BUF_MAX;
4860 s32 err = 0;
4861 bool scan_abort = false;
4862 u32 scan_channel;
4863
4864 WL_TRACE("Enter\n");
4865
4866 if (cfg_priv->iscan_on && cfg_priv->iscan_kickstart) {
4867 WL_TRACE("Exit\n");
4868 return brcmf_wakeup_iscan(cfg_to_iscan(cfg_priv));
4869 }
4870
4871 if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
4872 WL_ERR("Scan complete while device not scanning\n");
4873 scan_abort = true;
4874 err = -EINVAL;
4875 goto scan_done_out;
4876 }
4877
4878 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_inform_le,
4879 sizeof(channel_inform_le));
4880 if (err) {
4881 WL_ERR("scan busy (%d)\n", err);
4882 scan_abort = true;
4883 goto scan_done_out;
4884 }
4885 scan_channel = le32_to_cpu(channel_inform_le.scan_channel);
4886 if (scan_channel)
4887 WL_CONN("channel_inform.scan_channel (%d)\n", scan_channel);
4888 cfg_priv->bss_list = cfg_priv->scan_results;
4889 bss_list_le = (struct brcmf_scan_results_le *) cfg_priv->bss_list;
4890
4891 memset(cfg_priv->scan_results, 0, len);
4892 bss_list_le->buflen = cpu_to_le32(len);
4893 err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS,
4894 cfg_priv->scan_results, len);
4895 if (err) {
4896 WL_ERR("%s Scan_results error (%d)\n", ndev->name, err);
4897 err = -EINVAL;
4898 scan_abort = true;
4899 goto scan_done_out;
4900 }
4901 cfg_priv->scan_results->buflen = le32_to_cpu(bss_list_le->buflen);
4902 cfg_priv->scan_results->version = le32_to_cpu(bss_list_le->version);
4903 cfg_priv->scan_results->count = le32_to_cpu(bss_list_le->count);
4904
4905 err = brcmf_inform_bss(cfg_priv);
35aafa9d 4906 if (err)
5b435de0 4907 scan_abort = true;
5b435de0
AS
4908
4909scan_done_out:
4910 if (cfg_priv->scan_request) {
4911 WL_SCAN("calling cfg80211_scan_done\n");
4912 cfg80211_scan_done(cfg_priv->scan_request, scan_abort);
4913 brcmf_set_mpc(ndev, 1);
4914 cfg_priv->scan_request = NULL;
4915 }
4916
4917 WL_TRACE("Exit\n");
4918
4919 return err;
4920}
4921
4922static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
4923{
4924 conf->mode = (u32)-1;
4925 conf->frag_threshold = (u32)-1;
4926 conf->rts_threshold = (u32)-1;
4927 conf->retry_short = (u32)-1;
4928 conf->retry_long = (u32)-1;
4929 conf->tx_power = -1;
4930}
4931
4932static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el)
4933{
4934 memset(el, 0, sizeof(*el));
4935 el->handler[BRCMF_E_SCAN_COMPLETE] = brcmf_notify_scan_status;
4936 el->handler[BRCMF_E_LINK] = brcmf_notify_connect_status;
1a873342
HM
4937 el->handler[BRCMF_E_DEAUTH_IND] = brcmf_notify_connect_status;
4938 el->handler[BRCMF_E_DEAUTH] = brcmf_notify_connect_status;
4939 el->handler[BRCMF_E_DISASSOC_IND] = brcmf_notify_connect_status;
4940 el->handler[BRCMF_E_ASSOC_IND] = brcmf_notify_connect_status;
4941 el->handler[BRCMF_E_REASSOC_IND] = brcmf_notify_connect_status;
5b435de0
AS
4942 el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status;
4943 el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status;
4944 el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status;
e5806072 4945 el->handler[BRCMF_E_PFN_NET_FOUND] = brcmf_notify_sched_scan_results;
5b435de0
AS
4946}
4947
4948static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
4949{
4950 kfree(cfg_priv->scan_results);
4951 cfg_priv->scan_results = NULL;
4952 kfree(cfg_priv->bss_info);
4953 cfg_priv->bss_info = NULL;
4954 kfree(cfg_priv->conf);
4955 cfg_priv->conf = NULL;
4956 kfree(cfg_priv->profile);
4957 cfg_priv->profile = NULL;
4958 kfree(cfg_priv->scan_req_int);
4959 cfg_priv->scan_req_int = NULL;
e756af5b
HM
4960 kfree(cfg_priv->escan_ioctl_buf);
4961 cfg_priv->escan_ioctl_buf = NULL;
5b435de0
AS
4962 kfree(cfg_priv->dcmd_buf);
4963 cfg_priv->dcmd_buf = NULL;
4964 kfree(cfg_priv->extra_buf);
4965 cfg_priv->extra_buf = NULL;
4966 kfree(cfg_priv->iscan);
4967 cfg_priv->iscan = NULL;
4968 kfree(cfg_priv->pmk_list);
4969 cfg_priv->pmk_list = NULL;
1a873342
HM
4970 if (cfg_priv->ap_info) {
4971 kfree(cfg_priv->ap_info->wpa_ie);
4972 kfree(cfg_priv->ap_info->rsn_ie);
4973 kfree(cfg_priv->ap_info);
4974 cfg_priv->ap_info = NULL;
4975 }
5b435de0
AS
4976}
4977
4978static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
4979{
4980 cfg_priv->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
4981 if (!cfg_priv->scan_results)
4982 goto init_priv_mem_out;
4983 cfg_priv->conf = kzalloc(sizeof(*cfg_priv->conf), GFP_KERNEL);
4984 if (!cfg_priv->conf)
4985 goto init_priv_mem_out;
4986 cfg_priv->profile = kzalloc(sizeof(*cfg_priv->profile), GFP_KERNEL);
4987 if (!cfg_priv->profile)
4988 goto init_priv_mem_out;
4989 cfg_priv->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
4990 if (!cfg_priv->bss_info)
4991 goto init_priv_mem_out;
4992 cfg_priv->scan_req_int = kzalloc(sizeof(*cfg_priv->scan_req_int),
4993 GFP_KERNEL);
4994 if (!cfg_priv->scan_req_int)
4995 goto init_priv_mem_out;
e756af5b
HM
4996 cfg_priv->escan_ioctl_buf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
4997 if (!cfg_priv->escan_ioctl_buf)
4998 goto init_priv_mem_out;
5b435de0
AS
4999 cfg_priv->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL);
5000 if (!cfg_priv->dcmd_buf)
5001 goto init_priv_mem_out;
5002 cfg_priv->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
5003 if (!cfg_priv->extra_buf)
5004 goto init_priv_mem_out;
5005 cfg_priv->iscan = kzalloc(sizeof(*cfg_priv->iscan), GFP_KERNEL);
5006 if (!cfg_priv->iscan)
5007 goto init_priv_mem_out;
5008 cfg_priv->pmk_list = kzalloc(sizeof(*cfg_priv->pmk_list), GFP_KERNEL);
5009 if (!cfg_priv->pmk_list)
5010 goto init_priv_mem_out;
5011
5012 return 0;
5013
5014init_priv_mem_out:
5015 brcmf_deinit_priv_mem(cfg_priv);
5016
5017 return -ENOMEM;
5018}
5019
5020/*
5021* retrieve first queued event from head
5022*/
5023
5024static struct brcmf_cfg80211_event_q *brcmf_deq_event(
5025 struct brcmf_cfg80211_priv *cfg_priv)
5026{
5027 struct brcmf_cfg80211_event_q *e = NULL;
5028
5029 spin_lock_irq(&cfg_priv->evt_q_lock);
5030 if (!list_empty(&cfg_priv->evt_q_list)) {
5031 e = list_first_entry(&cfg_priv->evt_q_list,
5032 struct brcmf_cfg80211_event_q, evt_q_list);
5033 list_del(&e->evt_q_list);
5034 }
5035 spin_unlock_irq(&cfg_priv->evt_q_lock);
5036
5037 return e;
5038}
5039
5040/*
bcbec9e7
AS
5041* push event to tail of the queue
5042*
5043* remark: this function may not sleep as it is called in atomic context.
5b435de0
AS
5044*/
5045
5046static s32
5047brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event,
c4fdb056 5048 const struct brcmf_event_msg *msg, void *data)
5b435de0
AS
5049{
5050 struct brcmf_cfg80211_event_q *e;
5051 s32 err = 0;
cf44066a 5052 ulong flags;
c4fdb056
HM
5053 u32 data_len;
5054 u32 total_len;
5b435de0 5055
c4fdb056
HM
5056 total_len = sizeof(struct brcmf_cfg80211_event_q);
5057 if (data)
5058 data_len = be32_to_cpu(msg->datalen);
5059 else
5060 data_len = 0;
5061 total_len += data_len;
5062 e = kzalloc(total_len, GFP_ATOMIC);
5b435de0
AS
5063 if (!e)
5064 return -ENOMEM;
5065
5066 e->etype = event;
5067 memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
c4fdb056
HM
5068 if (data)
5069 memcpy(&e->edata, data, data_len);
5b435de0 5070
cf44066a 5071 spin_lock_irqsave(&cfg_priv->evt_q_lock, flags);
5b435de0 5072 list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list);
cf44066a 5073 spin_unlock_irqrestore(&cfg_priv->evt_q_lock, flags);
5b435de0
AS
5074
5075 return err;
5076}
5077
5078static void brcmf_put_event(struct brcmf_cfg80211_event_q *e)
5079{
5080 kfree(e);
5081}
5082
5083static void brcmf_cfg80211_event_handler(struct work_struct *work)
5084{
5085 struct brcmf_cfg80211_priv *cfg_priv =
5086 container_of(work, struct brcmf_cfg80211_priv,
5087 event_work);
5088 struct brcmf_cfg80211_event_q *e;
5089
5090 e = brcmf_deq_event(cfg_priv);
5091 if (unlikely(!e)) {
5092 WL_ERR("event queue empty...\n");
5093 return;
5094 }
5095
5096 do {
5097 WL_INFO("event type (%d)\n", e->etype);
5098 if (cfg_priv->el.handler[e->etype])
5099 cfg_priv->el.handler[e->etype](cfg_priv,
5100 cfg_to_ndev(cfg_priv),
5101 &e->emsg, e->edata);
5102 else
5103 WL_INFO("Unknown Event (%d): ignoring\n", e->etype);
5104 brcmf_put_event(e);
5105 } while ((e = brcmf_deq_event(cfg_priv)));
5106
5107}
5108
5109static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv)
5110{
5111 spin_lock_init(&cfg_priv->evt_q_lock);
5112 INIT_LIST_HEAD(&cfg_priv->evt_q_list);
5113}
5114
5115static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv)
5116{
5117 struct brcmf_cfg80211_event_q *e;
5118
5119 spin_lock_irq(&cfg_priv->evt_q_lock);
5120 while (!list_empty(&cfg_priv->evt_q_list)) {
5121 e = list_first_entry(&cfg_priv->evt_q_list,
5122 struct brcmf_cfg80211_event_q, evt_q_list);
5123 list_del(&e->evt_q_list);
5124 kfree(e);
5125 }
5126 spin_unlock_irq(&cfg_priv->evt_q_lock);
5127}
5128
5129static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv)
5130{
5131 s32 err = 0;
5132
5133 cfg_priv->scan_request = NULL;
5134 cfg_priv->pwr_save = true;
e756af5b 5135#ifdef CONFIG_BRCMISCAN
5b435de0
AS
5136 cfg_priv->iscan_on = true; /* iscan on & off switch.
5137 we enable iscan per default */
e756af5b
HM
5138 cfg_priv->escan_on = false; /* escan on & off switch.
5139 we disable escan per default */
5140#else
5141 cfg_priv->iscan_on = false; /* iscan on & off switch.
5142 we disable iscan per default */
5143 cfg_priv->escan_on = true; /* escan on & off switch.
5144 we enable escan per default */
5145#endif
5b435de0
AS
5146 cfg_priv->roam_on = true; /* roam on & off switch.
5147 we enable roam per default */
5148
5149 cfg_priv->iscan_kickstart = false;
5150 cfg_priv->active_scan = true; /* we do active scan for
5151 specific scan per default */
5152 cfg_priv->dongle_up = false; /* dongle is not up yet */
5153 brcmf_init_eq(cfg_priv);
5154 err = brcmf_init_priv_mem(cfg_priv);
5155 if (err)
5156 return err;
5157 INIT_WORK(&cfg_priv->event_work, brcmf_cfg80211_event_handler);
5158 brcmf_init_eloop_handler(&cfg_priv->el);
5159 mutex_init(&cfg_priv->usr_sync);
5160 err = brcmf_init_iscan(cfg_priv);
5161 if (err)
5162 return err;
e756af5b 5163 brcmf_init_escan(cfg_priv);
5b435de0
AS
5164 brcmf_init_conf(cfg_priv->conf);
5165 brcmf_init_prof(cfg_priv->profile);
5166 brcmf_link_down(cfg_priv);
5167
5168 return err;
5169}
5170
5171static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv)
5172{
5173 cancel_work_sync(&cfg_priv->event_work);
5174 cfg_priv->dongle_up = false; /* dongle down */
5175 brcmf_flush_eq(cfg_priv);
5176 brcmf_link_down(cfg_priv);
108a4bee 5177 brcmf_abort_scanning(cfg_priv);
5b435de0
AS
5178 brcmf_deinit_priv_mem(cfg_priv);
5179}
5180
b451ec94
AS
5181struct brcmf_cfg80211_priv *brcmf_cfg80211_attach(struct net_device *ndev,
5182 struct device *busdev,
5183 struct brcmf_pub *drvr)
5b435de0
AS
5184{
5185 struct wireless_dev *wdev;
5186 struct brcmf_cfg80211_priv *cfg_priv;
5b435de0
AS
5187 s32 err = 0;
5188
5189 if (!ndev) {
5190 WL_ERR("ndev is invalid\n");
5191 return NULL;
5192 }
5b435de0 5193
5db6e956 5194 wdev = brcmf_alloc_wdev(busdev);
5b435de0 5195 if (IS_ERR(wdev)) {
5b435de0
AS
5196 return NULL;
5197 }
5198
5199 wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS);
5200 cfg_priv = wdev_to_cfg(wdev);
5201 cfg_priv->wdev = wdev;
ee928381 5202 cfg_priv->pub = drvr;
5b435de0
AS
5203 ndev->ieee80211_ptr = wdev;
5204 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
5205 wdev->netdev = ndev;
5206 err = wl_init_priv(cfg_priv);
5207 if (err) {
5208 WL_ERR("Failed to init iwm_priv (%d)\n", err);
5209 goto cfg80211_attach_out;
5210 }
5db6e956 5211
b451ec94 5212 return cfg_priv;
5b435de0
AS
5213
5214cfg80211_attach_out:
5215 brcmf_free_wdev(cfg_priv);
5b435de0
AS
5216 return NULL;
5217}
5218
b451ec94 5219void brcmf_cfg80211_detach(struct brcmf_cfg80211_priv *cfg_priv)
5b435de0 5220{
5b435de0
AS
5221 wl_deinit_priv(cfg_priv);
5222 brcmf_free_wdev(cfg_priv);
5b435de0
AS
5223}
5224
5225void
5226brcmf_cfg80211_event(struct net_device *ndev,
5227 const struct brcmf_event_msg *e, void *data)
5228{
5229 u32 event_type = be32_to_cpu(e->event_type);
5230 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
5231
c4fdb056 5232 if (!brcmf_enq_event(cfg_priv, event_type, e, data))
5b435de0
AS
5233 schedule_work(&cfg_priv->event_work);
5234}
5235
5236static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
5237{
5238 s32 infra = 0;
5239 s32 err = 0;
5240
5241 switch (iftype) {
5242 case NL80211_IFTYPE_MONITOR:
5243 case NL80211_IFTYPE_WDS:
5244 WL_ERR("type (%d) : currently we do not support this mode\n",
5245 iftype);
5246 err = -EINVAL;
5247 return err;
5248 case NL80211_IFTYPE_ADHOC:
5249 infra = 0;
5250 break;
5251 case NL80211_IFTYPE_STATION:
5252 infra = 1;
5253 break;
1a873342
HM
5254 case NL80211_IFTYPE_AP:
5255 infra = 1;
5256 break;
5b435de0
AS
5257 default:
5258 err = -EINVAL;
5259 WL_ERR("invalid type (%d)\n", iftype);
5260 return err;
5261 }
5262 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
5263 if (err) {
5264 WL_ERR("WLC_SET_INFRA error (%d)\n", err);
5265 return err;
5266 }
5267
5268 return 0;
5269}
5270
5271static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
5272{
5273 /* Room for "event_msgs" + '\0' + bitvec */
5274 s8 iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
5275 s8 eventmask[BRCMF_EVENTING_MASK_LEN];
5276 s32 err = 0;
5277
5278 WL_TRACE("Enter\n");
5279
5280 /* Setup event_msgs */
53a2277d
AB
5281 brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
5282 iovbuf, sizeof(iovbuf));
5b435de0
AS
5283 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf));
5284 if (err) {
5285 WL_ERR("Get event_msgs error (%d)\n", err);
5286 goto dongle_eventmsg_out;
5287 }
5288 memcpy(eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN);
5289
5290 setbit(eventmask, BRCMF_E_SET_SSID);
5291 setbit(eventmask, BRCMF_E_ROAM);
5292 setbit(eventmask, BRCMF_E_PRUNE);
5293 setbit(eventmask, BRCMF_E_AUTH);
5294 setbit(eventmask, BRCMF_E_REASSOC);
5295 setbit(eventmask, BRCMF_E_REASSOC_IND);
5296 setbit(eventmask, BRCMF_E_DEAUTH_IND);
5297 setbit(eventmask, BRCMF_E_DISASSOC_IND);
5298 setbit(eventmask, BRCMF_E_DISASSOC);
5299 setbit(eventmask, BRCMF_E_JOIN);
5300 setbit(eventmask, BRCMF_E_ASSOC_IND);
5301 setbit(eventmask, BRCMF_E_PSK_SUP);
5302 setbit(eventmask, BRCMF_E_LINK);
5303 setbit(eventmask, BRCMF_E_NDIS_LINK);
5304 setbit(eventmask, BRCMF_E_MIC_ERROR);
5305 setbit(eventmask, BRCMF_E_PMKID_CACHE);
5306 setbit(eventmask, BRCMF_E_TXFAIL);
5307 setbit(eventmask, BRCMF_E_JOIN_START);
5308 setbit(eventmask, BRCMF_E_SCAN_COMPLETE);
e756af5b 5309 setbit(eventmask, BRCMF_E_ESCAN_RESULT);
e5806072 5310 setbit(eventmask, BRCMF_E_PFN_NET_FOUND);
5b435de0 5311
53a2277d
AB
5312 brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
5313 iovbuf, sizeof(iovbuf));
5b435de0
AS
5314 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
5315 if (err) {
5316 WL_ERR("Set event_msgs error (%d)\n", err);
5317 goto dongle_eventmsg_out;
5318 }
5319
5320dongle_eventmsg_out:
5321 WL_TRACE("Exit\n");
5322 return err;
5323}
5324
5325static s32
5326brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
5327{
5328 s8 iovbuf[32];
5b435de0 5329 s32 err = 0;
f588bc0c
AS
5330 __le32 roamtrigger[2];
5331 __le32 roam_delta[2];
5332 __le32 bcn_to_le;
5333 __le32 roamvar_le;
5b435de0
AS
5334
5335 /*
5336 * Setup timeout if Beacons are lost and roam is
5337 * off to report link down
5338 */
5339 if (roamvar) {
f588bc0c 5340 bcn_to_le = cpu_to_le32(bcn_timeout);
53a2277d 5341 brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_to_le,
f588bc0c 5342 sizeof(bcn_to_le), iovbuf, sizeof(iovbuf));
5b435de0
AS
5343 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR,
5344 iovbuf, sizeof(iovbuf));
5345 if (err) {
5346 WL_ERR("bcn_timeout error (%d)\n", err);
5347 goto dongle_rom_out;
5348 }
5349 }
5350
5351 /*
5352 * Enable/Disable built-in roaming to allow supplicant
5353 * to take care of roaming
5354 */
5355 WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On");
f588bc0c 5356 roamvar_le = cpu_to_le32(roamvar);
53a2277d 5357 brcmf_c_mkiovar("roam_off", (char *)&roamvar_le,
f588bc0c 5358 sizeof(roamvar_le), iovbuf, sizeof(iovbuf));
5b435de0
AS
5359 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
5360 if (err) {
5361 WL_ERR("roam_off error (%d)\n", err);
5362 goto dongle_rom_out;
5363 }
5364
f588bc0c
AS
5365 roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL);
5366 roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL);
5b435de0
AS
5367 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_TRIGGER,
5368 (void *)roamtrigger, sizeof(roamtrigger));
5369 if (err) {
5370 WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
5371 goto dongle_rom_out;
5372 }
5373
f588bc0c
AS
5374 roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA);
5375 roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL);
5b435de0
AS
5376 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_DELTA,
5377 (void *)roam_delta, sizeof(roam_delta));
5378 if (err) {
5379 WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err);
5380 goto dongle_rom_out;
5381 }
5382
5383dongle_rom_out:
5384 return err;
5385}
5386
5387static s32
5388brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
c68cdc0f 5389 s32 scan_unassoc_time, s32 scan_passive_time)
5b435de0
AS
5390{
5391 s32 err = 0;
c68cdc0f
AS
5392 __le32 scan_assoc_tm_le = cpu_to_le32(scan_assoc_time);
5393 __le32 scan_unassoc_tm_le = cpu_to_le32(scan_unassoc_time);
5394 __le32 scan_passive_tm_le = cpu_to_le32(scan_passive_time);
5b435de0
AS
5395
5396 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME,
c68cdc0f 5397 &scan_assoc_tm_le, sizeof(scan_assoc_tm_le));
5b435de0
AS
5398 if (err) {
5399 if (err == -EOPNOTSUPP)
5400 WL_INFO("Scan assoc time is not supported\n");
5401 else
5402 WL_ERR("Scan assoc time error (%d)\n", err);
5403 goto dongle_scantime_out;
5404 }
5405 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME,
c68cdc0f 5406 &scan_unassoc_tm_le, sizeof(scan_unassoc_tm_le));
5b435de0
AS
5407 if (err) {
5408 if (err == -EOPNOTSUPP)
5409 WL_INFO("Scan unassoc time is not supported\n");
5410 else
5411 WL_ERR("Scan unassoc time error (%d)\n", err);
5412 goto dongle_scantime_out;
5413 }
5414
5415 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME,
c68cdc0f 5416 &scan_passive_tm_le, sizeof(scan_passive_tm_le));
5b435de0
AS
5417 if (err) {
5418 if (err == -EOPNOTSUPP)
5419 WL_INFO("Scan passive time is not supported\n");
5420 else
5421 WL_ERR("Scan passive time error (%d)\n", err);
5422 goto dongle_scantime_out;
5423 }
5424
5425dongle_scantime_out:
5426 return err;
5427}
5428
5429static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv)
5430{
5431 struct wiphy *wiphy;
5432 s32 phy_list;
5433 s8 phy;
5434 s32 err = 0;
5435
5436 err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST,
5437 &phy_list, sizeof(phy_list));
5438 if (err) {
5439 WL_ERR("error (%d)\n", err);
5440 return err;
5441 }
5442
3ba81376 5443 phy = ((char *)&phy_list)[0];
5b435de0
AS
5444 WL_INFO("%c phy\n", phy);
5445 if (phy == 'n' || phy == 'a') {
5446 wiphy = cfg_to_wiphy(cfg_priv);
5447 wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
5448 }
5449
5450 return err;
5451}
5452
5453static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv)
5454{
5455 return wl_update_wiphybands(cfg_priv);
5456}
5457
5458static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv)
5459{
5460 struct net_device *ndev;
5461 struct wireless_dev *wdev;
5462 s32 power_mode;
5463 s32 err = 0;
5464
5465 if (cfg_priv->dongle_up)
5466 return err;
5467
5468 ndev = cfg_to_ndev(cfg_priv);
5469 wdev = ndev->ieee80211_ptr;
5470
5471 brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
5472 WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
5473
5474 err = brcmf_dongle_eventmsg(ndev);
5475 if (err)
5476 goto default_conf_out;
5477
5478 power_mode = cfg_priv->pwr_save ? PM_FAST : PM_OFF;
5479 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &power_mode);
5480 if (err)
5481 goto default_conf_out;
5482 WL_INFO("power save set to %s\n",
5483 (power_mode ? "enabled" : "disabled"));
5484
5485 err = brcmf_dongle_roam(ndev, (cfg_priv->roam_on ? 0 : 1),
5486 WL_BEACON_TIMEOUT);
5487 if (err)
5488 goto default_conf_out;
5489 err = brcmf_dongle_mode(ndev, wdev->iftype);
5490 if (err && err != -EINPROGRESS)
5491 goto default_conf_out;
5492 err = brcmf_dongle_probecap(cfg_priv);
5493 if (err)
5494 goto default_conf_out;
5495
5496 /* -EINPROGRESS: Call commit handler */
5497
5498default_conf_out:
5499
5500 cfg_priv->dongle_up = true;
5501
5502 return err;
5503
5504}
5505
5506static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv)
5507{
5508 char buf[10+IFNAMSIZ];
5509 struct dentry *fd;
5510 s32 err = 0;
5511
5512 sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name);
5513 cfg_priv->debugfsdir = debugfs_create_dir(buf,
5514 cfg_to_wiphy(cfg_priv)->debugfsdir);
5515
5516 fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir,
5517 (u16 *)&cfg_priv->profile->beacon_interval);
5518 if (!fd) {
5519 err = -ENOMEM;
5520 goto err_out;
5521 }
5522
5523 fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir,
5524 (u8 *)&cfg_priv->profile->dtim_period);
5525 if (!fd) {
5526 err = -ENOMEM;
5527 goto err_out;
5528 }
5529
5530err_out:
5531 return err;
5532}
5533
5534static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv)
5535{
5536 debugfs_remove_recursive(cfg_priv->debugfsdir);
5537 cfg_priv->debugfsdir = NULL;
5538}
5539
5540static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv)
5541{
5542 s32 err = 0;
5543
5544 set_bit(WL_STATUS_READY, &cfg_priv->status);
5545
5546 brcmf_debugfs_add_netdev_params(cfg_priv);
5547
5548 err = brcmf_config_dongle(cfg_priv);
5549 if (err)
5550 return err;
5551
5552 brcmf_invoke_iscan(cfg_priv);
5553
5554 return err;
5555}
5556
5557static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv)
5558{
5559 /*
5560 * While going down, if associated with AP disassociate
5561 * from AP to save power
5562 */
5563 if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
5564 test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
5565 test_bit(WL_STATUS_READY, &cfg_priv->status)) {
5566 WL_INFO("Disassociating from AP");
5567 brcmf_link_down(cfg_priv);
5568
5569 /* Make sure WPA_Supplicant receives all the event
5570 generated due to DISASSOC call to the fw to keep
5571 the state fw and WPA_Supplicant state consistent
5572 */
5573 brcmf_delay(500);
5574 }
5575
108a4bee 5576 brcmf_abort_scanning(cfg_priv);
5b435de0 5577 clear_bit(WL_STATUS_READY, &cfg_priv->status);
5b435de0
AS
5578
5579 brcmf_debugfs_remove_netdev(cfg_priv);
5580
5581 return 0;
5582}
5583
b451ec94 5584s32 brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv)
5b435de0 5585{
5b435de0
AS
5586 s32 err = 0;
5587
5b435de0
AS
5588 mutex_lock(&cfg_priv->usr_sync);
5589 err = __brcmf_cfg80211_up(cfg_priv);
5590 mutex_unlock(&cfg_priv->usr_sync);
5591
5592 return err;
5593}
5594
b451ec94 5595s32 brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv)
5b435de0 5596{
5b435de0
AS
5597 s32 err = 0;
5598
5b435de0
AS
5599 mutex_lock(&cfg_priv->usr_sync);
5600 err = __brcmf_cfg80211_down(cfg_priv);
5601 mutex_unlock(&cfg_priv->usr_sync);
5602
5603 return err;
5604}
5605
This page took 0.416529 seconds and 5 git commands to generate.