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