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