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