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