brcmfmac: fix sparse warnings in e-scan related code
[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
2592static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv)
2593{
2594 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
2595 struct brcmf_ssid ssid;
2596
2597 if (cfg_priv->iscan_on) {
2598 iscan->state = WL_ISCAN_STATE_IDLE;
2599
2600 if (iscan->timer_on) {
2601 del_timer_sync(&iscan->timer);
2602 iscan->timer_on = 0;
2603 }
2604
2605 cancel_work_sync(&iscan->work);
2606
2607 /* Abort iscan running in FW */
2608 memset(&ssid, 0, sizeof(ssid));
2609 brcmf_run_iscan(iscan, &ssid, WL_SCAN_ACTION_ABORT);
2610 }
2611}
2612
2613static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
2614 bool aborted)
2615{
2616 struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
2617 struct net_device *ndev = cfg_to_ndev(cfg_priv);
2618
2619 if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
2620 WL_ERR("Scan complete while device not scanning\n");
2621 return;
2622 }
2623 if (cfg_priv->scan_request) {
2624 WL_SCAN("ISCAN Completed scan: %s\n",
2625 aborted ? "Aborted" : "Done");
2626 cfg80211_scan_done(cfg_priv->scan_request, aborted);
2627 brcmf_set_mpc(ndev, 1);
2628 cfg_priv->scan_request = NULL;
2629 }
2630 cfg_priv->iscan_kickstart = false;
2631}
2632
2633static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan)
2634{
2635 if (iscan->state != WL_ISCAN_STATE_IDLE) {
2636 WL_SCAN("wake up iscan\n");
2637 schedule_work(&iscan->work);
2638 return 0;
2639 }
2640
2641 return -EIO;
2642}
2643
2644static s32
2645brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status,
2646 struct brcmf_scan_results **bss_list)
2647{
2648 struct brcmf_iscan_results list;
2649 struct brcmf_scan_results *results;
2650 struct brcmf_scan_results_le *results_le;
2651 struct brcmf_iscan_results *list_buf;
2652 s32 err = 0;
2653
2654 memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
2655 list_buf = (struct brcmf_iscan_results *)iscan->scan_buf;
2656 results = &list_buf->results;
2657 results_le = &list_buf->results_le;
2658 results->buflen = BRCMF_ISCAN_RESULTS_FIXED_SIZE;
2659 results->version = 0;
2660 results->count = 0;
2661
2662 memset(&list, 0, sizeof(list));
2663 list.results_le.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX);
2664 err = brcmf_dev_iovar_getbuf(iscan->ndev, "iscanresults", &list,
2665 BRCMF_ISCAN_RESULTS_FIXED_SIZE,
2666 iscan->scan_buf, WL_ISCAN_BUF_MAX);
2667 if (err) {
2668 WL_ERR("error (%d)\n", err);
2669 return err;
2670 }
2671 results->buflen = le32_to_cpu(results_le->buflen);
2672 results->version = le32_to_cpu(results_le->version);
2673 results->count = le32_to_cpu(results_le->count);
2674 WL_SCAN("results->count = %d\n", results_le->count);
2675 WL_SCAN("results->buflen = %d\n", results_le->buflen);
2676 *status = le32_to_cpu(list_buf->status_le);
2677 WL_SCAN("status = %d\n", *status);
2678 *bss_list = results;
2679
2680 return err;
2681}
2682
2683static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv)
2684{
2685 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2686 s32 err = 0;
2687
2688 iscan->state = WL_ISCAN_STATE_IDLE;
2689 brcmf_inform_bss(cfg_priv);
2690 brcmf_notify_iscan_complete(iscan, false);
2691
2692 return err;
2693}
2694
2695static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv)
2696{
2697 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2698 s32 err = 0;
2699
2700 /* Reschedule the timer */
2701 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
2702 iscan->timer_on = 1;
2703
2704 return err;
2705}
2706
2707static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv)
2708{
2709 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2710 s32 err = 0;
2711
2712 brcmf_inform_bss(cfg_priv);
2713 brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE);
2714 /* Reschedule the timer */
2715 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
2716 iscan->timer_on = 1;
2717
2718 return err;
2719}
2720
2721static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv)
2722{
2723 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2724 s32 err = 0;
2725
2726 iscan->state = WL_ISCAN_STATE_IDLE;
2727 brcmf_notify_iscan_complete(iscan, true);
2728
2729 return err;
2730}
2731
2732static void brcmf_cfg80211_iscan_handler(struct work_struct *work)
2733{
2734 struct brcmf_cfg80211_iscan_ctrl *iscan =
2735 container_of(work, struct brcmf_cfg80211_iscan_ctrl,
2736 work);
2737 struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
2738 struct brcmf_cfg80211_iscan_eloop *el = &iscan->el;
2739 u32 status = BRCMF_SCAN_RESULTS_PARTIAL;
2740
2741 if (iscan->timer_on) {
2742 del_timer_sync(&iscan->timer);
2743 iscan->timer_on = 0;
2744 }
2745
2746 if (brcmf_get_iscan_results(iscan, &status, &cfg_priv->bss_list)) {
2747 status = BRCMF_SCAN_RESULTS_ABORTED;
2748 WL_ERR("Abort iscan\n");
2749 }
2750
2751 el->handler[status](cfg_priv);
2752}
2753
2754static void brcmf_iscan_timer(unsigned long data)
2755{
2756 struct brcmf_cfg80211_iscan_ctrl *iscan =
2757 (struct brcmf_cfg80211_iscan_ctrl *)data;
2758
2759 if (iscan) {
2760 iscan->timer_on = 0;
2761 WL_SCAN("timer expired\n");
2762 brcmf_wakeup_iscan(iscan);
2763 }
2764}
2765
2766static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv)
2767{
2768 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
2769
2770 if (cfg_priv->iscan_on) {
2771 iscan->state = WL_ISCAN_STATE_IDLE;
2772 INIT_WORK(&iscan->work, brcmf_cfg80211_iscan_handler);
2773 }
2774
2775 return 0;
2776}
2777
2778static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el)
2779{
2780 memset(el, 0, sizeof(*el));
2781 el->handler[BRCMF_SCAN_RESULTS_SUCCESS] = brcmf_iscan_done;
2782 el->handler[BRCMF_SCAN_RESULTS_PARTIAL] = brcmf_iscan_inprogress;
2783 el->handler[BRCMF_SCAN_RESULTS_PENDING] = brcmf_iscan_pending;
2784 el->handler[BRCMF_SCAN_RESULTS_ABORTED] = brcmf_iscan_aborted;
2785 el->handler[BRCMF_SCAN_RESULTS_NO_MEM] = brcmf_iscan_aborted;
2786}
2787
2788static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv)
2789{
2790 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
2791 int err = 0;
2792
2793 if (cfg_priv->iscan_on) {
2794 iscan->ndev = cfg_to_ndev(cfg_priv);
2795 brcmf_init_iscan_eloop(&iscan->el);
2796 iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
2797 init_timer(&iscan->timer);
2798 iscan->timer.data = (unsigned long) iscan;
2799 iscan->timer.function = brcmf_iscan_timer;
2800 err = brcmf_invoke_iscan(cfg_priv);
2801 if (!err)
2802 iscan->data = cfg_priv;
2803 }
2804
2805 return err;
2806}
2807
e756af5b
HM
2808static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work)
2809{
2810 struct brcmf_cfg80211_priv *cfg_priv =
2811 container_of(work, struct brcmf_cfg80211_priv,
2812 escan_timeout_work);
2813
2814 brcmf_notify_escan_complete(cfg_priv,
2815 cfg_priv->escan_info.ndev, true, true);
2816}
2817
2818static void brcmf_escan_timeout(unsigned long data)
2819{
2820 struct brcmf_cfg80211_priv *cfg_priv =
2821 (struct brcmf_cfg80211_priv *)data;
2822
2823 if (cfg_priv->scan_request) {
2824 WL_ERR("timer expired\n");
2825 if (cfg_priv->escan_on)
2826 schedule_work(&cfg_priv->escan_timeout_work);
2827 }
2828}
2829
2830static s32
2831brcmf_compare_update_same_bss(struct brcmf_bss_info_le *bss,
2832 struct brcmf_bss_info_le *bss_info_le)
2833{
2834 if (!memcmp(&bss_info_le->BSSID, &bss->BSSID, ETH_ALEN) &&
2835 (CHSPEC_BAND(le16_to_cpu(bss_info_le->chanspec)) ==
2836 CHSPEC_BAND(le16_to_cpu(bss->chanspec))) &&
2837 bss_info_le->SSID_len == bss->SSID_len &&
2838 !memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) {
2839 if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) ==
2840 (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL)) {
029591f3
AS
2841 s16 bss_rssi = le16_to_cpu(bss->RSSI);
2842 s16 bss_info_rssi = le16_to_cpu(bss_info_le->RSSI);
2843
e756af5b
HM
2844 /* preserve max RSSI if the measurements are
2845 * both on-channel or both off-channel
2846 */
029591f3 2847 if (bss_info_rssi > bss_rssi)
e756af5b
HM
2848 bss->RSSI = bss_info_le->RSSI;
2849 } else if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) &&
2850 (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL) == 0) {
2851 /* preserve the on-channel rssi measurement
2852 * if the new measurement is off channel
2853 */
2854 bss->RSSI = bss_info_le->RSSI;
2855 bss->flags |= WLC_BSS_RSSI_ON_CHANNEL;
2856 }
2857 return 1;
2858 }
2859 return 0;
2860}
2861
2862static s32
2863brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_priv *cfg_priv,
2864 struct net_device *ndev,
2865 const struct brcmf_event_msg *e, void *data)
2866{
2867 s32 status;
2868 s32 err = 0;
2869 struct brcmf_escan_result_le *escan_result_le;
2870 struct brcmf_bss_info_le *bss_info_le;
2871 struct brcmf_bss_info_le *bss = NULL;
2872 u32 bi_length;
2873 struct brcmf_scan_results *list;
2874 u32 i;
97ed15c7 2875 bool aborted;
e756af5b
HM
2876
2877 status = be32_to_cpu(e->status);
2878
2879 if (!ndev || !cfg_priv->escan_on ||
2880 !test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
2881 WL_ERR("scan not ready ndev %p wl->escan_on %d drv_status %x\n",
2882 ndev, cfg_priv->escan_on,
2883 !test_bit(WL_STATUS_SCANNING, &cfg_priv->status));
2884 return -EPERM;
2885 }
2886
2887 if (status == BRCMF_E_STATUS_PARTIAL) {
2888 WL_SCAN("ESCAN Partial result\n");
2889 escan_result_le = (struct brcmf_escan_result_le *) data;
2890 if (!escan_result_le) {
2891 WL_ERR("Invalid escan result (NULL pointer)\n");
2892 goto exit;
2893 }
2894 if (!cfg_priv->scan_request) {
2895 WL_SCAN("result without cfg80211 request\n");
2896 goto exit;
2897 }
2898
2899 if (le16_to_cpu(escan_result_le->bss_count) != 1) {
2900 WL_ERR("Invalid bss_count %d: ignoring\n",
2901 escan_result_le->bss_count);
2902 goto exit;
2903 }
2904 bss_info_le = &escan_result_le->bss_info_le;
2905
2906 bi_length = le32_to_cpu(bss_info_le->length);
2907 if (bi_length != (le32_to_cpu(escan_result_le->buflen) -
2908 WL_ESCAN_RESULTS_FIXED_SIZE)) {
2909 WL_ERR("Invalid bss_info length %d: ignoring\n",
2910 bi_length);
2911 goto exit;
2912 }
2913
2914 if (!(cfg_to_wiphy(cfg_priv)->interface_modes &
2915 BIT(NL80211_IFTYPE_ADHOC))) {
2916 if (le16_to_cpu(bss_info_le->capability) &
2917 WLAN_CAPABILITY_IBSS) {
2918 WL_ERR("Ignoring IBSS result\n");
2919 goto exit;
2920 }
2921 }
2922
2923 list = (struct brcmf_scan_results *)
2924 cfg_priv->escan_info.escan_buf;
2925 if (bi_length > WL_ESCAN_BUF_SIZE - list->buflen) {
2926 WL_ERR("Buffer is too small: ignoring\n");
2927 goto exit;
2928 }
2929
2930 for (i = 0; i < list->count; i++) {
2931 bss = bss ? (struct brcmf_bss_info_le *)
2932 ((unsigned char *)bss +
2933 le32_to_cpu(bss->length)) : list->bss_info_le;
2934 if (brcmf_compare_update_same_bss(bss, bss_info_le))
2935 goto exit;
2936 }
2937 memcpy(&(cfg_priv->escan_info.escan_buf[list->buflen]),
2938 bss_info_le, bi_length);
2939 list->version = le32_to_cpu(bss_info_le->version);
2940 list->buflen += bi_length;
2941 list->count++;
2942 } else {
2943 cfg_priv->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
2944 if (cfg_priv->scan_request) {
2945 cfg_priv->bss_list = (struct brcmf_scan_results *)
2946 cfg_priv->escan_info.escan_buf;
2947 brcmf_inform_bss(cfg_priv);
97ed15c7
AS
2948 aborted = status != BRCMF_E_STATUS_SUCCESS;
2949 brcmf_notify_escan_complete(cfg_priv, ndev, aborted,
2950 false);
e756af5b
HM
2951 } else
2952 WL_ERR("Unexpected scan result 0x%x\n", status);
2953 }
2954exit:
2955 return err;
2956}
2957
2958static void brcmf_init_escan(struct brcmf_cfg80211_priv *cfg_priv)
2959{
2960
2961 if (cfg_priv->escan_on) {
2962 cfg_priv->el.handler[BRCMF_E_ESCAN_RESULT] =
2963 brcmf_cfg80211_escan_handler;
2964 cfg_priv->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
2965 /* Init scan_timeout timer */
2966 init_timer(&cfg_priv->escan_timeout);
2967 cfg_priv->escan_timeout.data = (unsigned long) cfg_priv;
2968 cfg_priv->escan_timeout.function = brcmf_escan_timeout;
2969 INIT_WORK(&cfg_priv->escan_timeout_work,
2970 brcmf_cfg80211_escan_timeout_worker);
2971 }
2972}
2973
5addc0de 2974static __always_inline void brcmf_delay(u32 ms)
5b435de0
AS
2975{
2976 if (ms < 1000 / HZ) {
2977 cond_resched();
2978 mdelay(ms);
2979 } else {
2980 msleep(ms);
2981 }
2982}
2983
2984static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
2985{
2986 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2987
2988 /*
2989 * Check for WL_STATUS_READY before any function call which
2990 * could result is bus access. Don't block the resume for
2991 * any driver error conditions
2992 */
2993 WL_TRACE("Enter\n");
2994
2995 if (test_bit(WL_STATUS_READY, &cfg_priv->status))
2996 brcmf_invoke_iscan(wiphy_to_cfg(wiphy));
2997
2998 WL_TRACE("Exit\n");
2999 return 0;
3000}
3001
3002static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
3003 struct cfg80211_wowlan *wow)
3004{
3005 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3006 struct net_device *ndev = cfg_to_ndev(cfg_priv);
3007
3008 WL_TRACE("Enter\n");
3009
3010 /*
3011 * Check for WL_STATUS_READY before any function call which
3012 * could result is bus access. Don't block the suspend for
3013 * any driver error conditions
3014 */
3015
3016 /*
3017 * While going to suspend if associated with AP disassociate
3018 * from AP to save power while system is in suspended state
3019 */
3020 if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
3021 test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
3022 test_bit(WL_STATUS_READY, &cfg_priv->status)) {
3023 WL_INFO("Disassociating from AP"
3024 " while entering suspend state\n");
3025 brcmf_link_down(cfg_priv);
3026
3027 /*
3028 * Make sure WPA_Supplicant receives all the event
3029 * generated due to DISASSOC call to the fw to keep
3030 * the state fw and WPA_Supplicant state consistent
3031 */
3032 brcmf_delay(500);
3033 }
3034
3035 set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
3036 if (test_bit(WL_STATUS_READY, &cfg_priv->status))
3037 brcmf_term_iscan(cfg_priv);
3038
3039 if (cfg_priv->scan_request) {
3040 /* Indidate scan abort to cfg80211 layer */
3041 WL_INFO("Terminating scan in progress\n");
3042 cfg80211_scan_done(cfg_priv->scan_request, true);
3043 cfg_priv->scan_request = NULL;
3044 }
3045 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
3046 clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
3047
3048 /* Turn off watchdog timer */
35aafa9d 3049 if (test_bit(WL_STATUS_READY, &cfg_priv->status))
5b435de0 3050 brcmf_set_mpc(ndev, 1);
5b435de0
AS
3051
3052 WL_TRACE("Exit\n");
3053
3054 return 0;
3055}
3056
3057static __used s32
3058brcmf_dev_bufvar_set(struct net_device *ndev, s8 *name, s8 *buf, s32 len)
3059{
3060 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
3061 u32 buflen;
3062
53a2277d 3063 buflen = brcmf_c_mkiovar(name, buf, len, cfg_priv->dcmd_buf,
5b435de0
AS
3064 WL_DCMD_LEN_MAX);
3065 BUG_ON(!buflen);
3066
3067 return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg_priv->dcmd_buf,
3068 buflen);
3069}
3070
3071static s32
3072brcmf_dev_bufvar_get(struct net_device *ndev, s8 *name, s8 *buf,
3073 s32 buf_len)
3074{
3075 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
3076 u32 len;
3077 s32 err = 0;
3078
53a2277d 3079 len = brcmf_c_mkiovar(name, NULL, 0, cfg_priv->dcmd_buf,
5b435de0
AS
3080 WL_DCMD_LEN_MAX);
3081 BUG_ON(!len);
3082 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg_priv->dcmd_buf,
3083 WL_DCMD_LEN_MAX);
3084 if (err) {
3085 WL_ERR("error (%d)\n", err);
3086 return err;
3087 }
3088 memcpy(buf, cfg_priv->dcmd_buf, buf_len);
3089
3090 return err;
3091}
3092
3093static __used s32
3094brcmf_update_pmklist(struct net_device *ndev,
3095 struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
3096{
3097 int i, j;
40c8e95a 3098 int pmkid_len;
5b435de0 3099
40c8e95a
AS
3100 pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid);
3101
3102 WL_CONN("No of elements %d\n", pmkid_len);
3103 for (i = 0; i < pmkid_len; i++) {
5b435de0
AS
3104 WL_CONN("PMKID[%d]: %pM =\n", i,
3105 &pmk_list->pmkids.pmkid[i].BSSID);
3106 for (j = 0; j < WLAN_PMKID_LEN; j++)
3107 WL_CONN("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]);
3108 }
3109
3110 if (!err)
3111 brcmf_dev_bufvar_set(ndev, "pmkid_info", (char *)pmk_list,
3112 sizeof(*pmk_list));
3113
3114 return err;
3115}
3116
3117static s32
3118brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
3119 struct cfg80211_pmksa *pmksa)
3120{
3121 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3122 struct pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids;
3123 s32 err = 0;
3124 int i;
40c8e95a 3125 int pmkid_len;
5b435de0
AS
3126
3127 WL_TRACE("Enter\n");
3128 if (!check_sys_up(wiphy))
3129 return -EIO;
3130
40c8e95a
AS
3131 pmkid_len = le32_to_cpu(pmkids->npmkid);
3132 for (i = 0; i < pmkid_len; i++)
5b435de0
AS
3133 if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN))
3134 break;
3135 if (i < WL_NUM_PMKIDS_MAX) {
3136 memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN);
3137 memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
40c8e95a
AS
3138 if (i == pmkid_len) {
3139 pmkid_len++;
3140 pmkids->npmkid = cpu_to_le32(pmkid_len);
3141 }
5b435de0
AS
3142 } else
3143 err = -EINVAL;
3144
3145 WL_CONN("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
40c8e95a 3146 pmkids->pmkid[pmkid_len].BSSID);
5b435de0 3147 for (i = 0; i < WLAN_PMKID_LEN; i++)
40c8e95a 3148 WL_CONN("%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]);
5b435de0
AS
3149
3150 err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
3151
3152 WL_TRACE("Exit\n");
3153 return err;
3154}
3155
3156static s32
3157brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
3158 struct cfg80211_pmksa *pmksa)
3159{
3160 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3161 struct pmkid_list pmkid;
3162 s32 err = 0;
40c8e95a 3163 int i, pmkid_len;
5b435de0
AS
3164
3165 WL_TRACE("Enter\n");
3166 if (!check_sys_up(wiphy))
3167 return -EIO;
3168
3169 memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
3170 memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
3171
3172 WL_CONN("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
3173 &pmkid.pmkid[0].BSSID);
3174 for (i = 0; i < WLAN_PMKID_LEN; i++)
3175 WL_CONN("%02x\n", pmkid.pmkid[0].PMKID[i]);
3176
40c8e95a
AS
3177 pmkid_len = le32_to_cpu(cfg_priv->pmk_list->pmkids.npmkid);
3178 for (i = 0; i < pmkid_len; i++)
5b435de0
AS
3179 if (!memcmp
3180 (pmksa->bssid, &cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
3181 ETH_ALEN))
3182 break;
3183
40c8e95a
AS
3184 if ((pmkid_len > 0)
3185 && (i < pmkid_len)) {
5b435de0
AS
3186 memset(&cfg_priv->pmk_list->pmkids.pmkid[i], 0,
3187 sizeof(struct pmkid));
40c8e95a 3188 for (; i < (pmkid_len - 1); i++) {
5b435de0
AS
3189 memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
3190 &cfg_priv->pmk_list->pmkids.pmkid[i + 1].BSSID,
3191 ETH_ALEN);
3192 memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].PMKID,
3193 &cfg_priv->pmk_list->pmkids.pmkid[i + 1].PMKID,
3194 WLAN_PMKID_LEN);
3195 }
40c8e95a 3196 cfg_priv->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1);
5b435de0
AS
3197 } else
3198 err = -EINVAL;
3199
3200 err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
3201
3202 WL_TRACE("Exit\n");
3203 return err;
3204
3205}
3206
3207static s32
3208brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
3209{
3210 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3211 s32 err = 0;
3212
3213 WL_TRACE("Enter\n");
3214 if (!check_sys_up(wiphy))
3215 return -EIO;
3216
3217 memset(cfg_priv->pmk_list, 0, sizeof(*cfg_priv->pmk_list));
3218 err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
3219
3220 WL_TRACE("Exit\n");
3221 return err;
3222
3223}
3224
cbaa177d
AS
3225#ifdef CONFIG_NL80211_TESTMODE
3226static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
3227{
3228 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3229 struct net_device *ndev = cfg_priv->wdev->netdev;
3230 struct brcmf_dcmd *dcmd = data;
3231 struct sk_buff *reply;
3232 int ret;
3233
3234 ret = brcmf_netlink_dcmd(ndev, dcmd);
3235 if (ret == 0) {
3236 reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*dcmd));
3237 nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*dcmd), dcmd);
3238 ret = cfg80211_testmode_reply(reply);
3239 }
3240 return ret;
3241}
3242#endif
3243
5b435de0
AS
3244static struct cfg80211_ops wl_cfg80211_ops = {
3245 .change_virtual_intf = brcmf_cfg80211_change_iface,
3246 .scan = brcmf_cfg80211_scan,
3247 .set_wiphy_params = brcmf_cfg80211_set_wiphy_params,
3248 .join_ibss = brcmf_cfg80211_join_ibss,
3249 .leave_ibss = brcmf_cfg80211_leave_ibss,
3250 .get_station = brcmf_cfg80211_get_station,
3251 .set_tx_power = brcmf_cfg80211_set_tx_power,
3252 .get_tx_power = brcmf_cfg80211_get_tx_power,
3253 .add_key = brcmf_cfg80211_add_key,
3254 .del_key = brcmf_cfg80211_del_key,
3255 .get_key = brcmf_cfg80211_get_key,
3256 .set_default_key = brcmf_cfg80211_config_default_key,
3257 .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key,
3258 .set_power_mgmt = brcmf_cfg80211_set_power_mgmt,
3259 .set_bitrate_mask = brcmf_cfg80211_set_bitrate_mask,
3260 .connect = brcmf_cfg80211_connect,
3261 .disconnect = brcmf_cfg80211_disconnect,
3262 .suspend = brcmf_cfg80211_suspend,
3263 .resume = brcmf_cfg80211_resume,
3264 .set_pmksa = brcmf_cfg80211_set_pmksa,
3265 .del_pmksa = brcmf_cfg80211_del_pmksa,
cbaa177d
AS
3266 .flush_pmksa = brcmf_cfg80211_flush_pmksa,
3267#ifdef CONFIG_NL80211_TESTMODE
3268 .testmode_cmd = brcmf_cfg80211_testmode
3269#endif
5b435de0
AS
3270};
3271
3272static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
3273{
3274 s32 err = 0;
3275
3276 switch (mode) {
3277 case WL_MODE_BSS:
3278 return NL80211_IFTYPE_STATION;
3279 case WL_MODE_IBSS:
3280 return NL80211_IFTYPE_ADHOC;
3281 default:
3282 return NL80211_IFTYPE_UNSPECIFIED;
3283 }
3284
3285 return err;
3286}
3287
3288static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface,
3289 struct device *ndev)
3290{
3291 struct wireless_dev *wdev;
3292 s32 err = 0;
3293
3294 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
3295 if (!wdev)
3296 return ERR_PTR(-ENOMEM);
3297
3298 wdev->wiphy =
3299 wiphy_new(&wl_cfg80211_ops,
3300 sizeof(struct brcmf_cfg80211_priv) + sizeof_iface);
3301 if (!wdev->wiphy) {
bfeb4dbc 3302 WL_ERR("Could not allocate wiphy device\n");
5b435de0
AS
3303 err = -ENOMEM;
3304 goto wiphy_new_out;
3305 }
3306 set_wiphy_dev(wdev->wiphy, ndev);
3307 wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
3308 wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
3309 wdev->wiphy->interface_modes =
3310 BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
3311 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
3312 wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set
3313 * it as 11a by default.
3314 * This will be updated with
3315 * 11n phy tables in
3316 * "ifconfig up"
3317 * if phy has 11n capability
3318 */
3319 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
3320 wdev->wiphy->cipher_suites = __wl_cipher_suites;
3321 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
3322 wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power
3323 * save mode
3324 * by default
3325 */
3326 err = wiphy_register(wdev->wiphy);
3327 if (err < 0) {
bfeb4dbc 3328 WL_ERR("Could not register wiphy device (%d)\n", err);
5b435de0
AS
3329 goto wiphy_register_out;
3330 }
3331 return wdev;
3332
3333wiphy_register_out:
3334 wiphy_free(wdev->wiphy);
3335
3336wiphy_new_out:
3337 kfree(wdev);
3338
3339 return ERR_PTR(err);
3340}
3341
3342static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv)
3343{
3344 struct wireless_dev *wdev = cfg_priv->wdev;
3345
3346 if (!wdev) {
3347 WL_ERR("wdev is invalid\n");
3348 return;
3349 }
3350 wiphy_unregister(wdev->wiphy);
3351 wiphy_free(wdev->wiphy);
3352 kfree(wdev);
3353 cfg_priv->wdev = NULL;
3354}
3355
3356static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv,
3357 const struct brcmf_event_msg *e)
3358{
3359 u32 event = be32_to_cpu(e->event_type);
3360 u32 status = be32_to_cpu(e->status);
3361
3362 if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
3363 WL_CONN("Processing set ssid\n");
3364 cfg_priv->link_up = true;
3365 return true;
3366 }
3367
3368 return false;
3369}
3370
3371static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv,
3372 const struct brcmf_event_msg *e)
3373{
3374 u32 event = be32_to_cpu(e->event_type);
3375 u16 flags = be16_to_cpu(e->flags);
3376
3377 if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) {
3378 WL_CONN("Processing link down\n");
3379 return true;
3380 }
3381 return false;
3382}
3383
3384static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv,
3385 const struct brcmf_event_msg *e)
3386{
3387 u32 event = be32_to_cpu(e->event_type);
3388 u32 status = be32_to_cpu(e->status);
3389
3390 if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) {
3391 WL_CONN("Processing Link %s & no network found\n",
3392 be16_to_cpu(e->flags) & BRCMF_EVENT_MSG_LINK ?
3393 "up" : "down");
3394 return true;
3395 }
3396
3397 if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) {
3398 WL_CONN("Processing connecting & no network found\n");
3399 return true;
3400 }
3401
3402 return false;
3403}
3404
3405static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
3406{
3407 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
3408
3409 kfree(conn_info->req_ie);
3410 conn_info->req_ie = NULL;
3411 conn_info->req_ie_len = 0;
3412 kfree(conn_info->resp_ie);
3413 conn_info->resp_ie = NULL;
3414 conn_info->resp_ie_len = 0;
3415}
3416
3417static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
3418{
3419 struct net_device *ndev = cfg_to_ndev(cfg_priv);
c4e382d2 3420 struct brcmf_cfg80211_assoc_ielen_le *assoc_info;
5b435de0
AS
3421 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
3422 u32 req_len;
3423 u32 resp_len;
3424 s32 err = 0;
3425
3426 brcmf_clear_assoc_ies(cfg_priv);
3427
3428 err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg_priv->extra_buf,
3429 WL_ASSOC_INFO_MAX);
3430 if (err) {
3431 WL_ERR("could not get assoc info (%d)\n", err);
3432 return err;
3433 }
c4e382d2
AS
3434 assoc_info =
3435 (struct brcmf_cfg80211_assoc_ielen_le *)cfg_priv->extra_buf;
3436 req_len = le32_to_cpu(assoc_info->req_len);
3437 resp_len = le32_to_cpu(assoc_info->resp_len);
5b435de0
AS
3438 if (req_len) {
3439 err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies",
3440 cfg_priv->extra_buf,
3441 WL_ASSOC_INFO_MAX);
3442 if (err) {
3443 WL_ERR("could not get assoc req (%d)\n", err);
3444 return err;
3445 }
3446 conn_info->req_ie_len = req_len;
3447 conn_info->req_ie =
3448 kmemdup(cfg_priv->extra_buf, conn_info->req_ie_len,
3449 GFP_KERNEL);
3450 } else {
3451 conn_info->req_ie_len = 0;
3452 conn_info->req_ie = NULL;
3453 }
3454 if (resp_len) {
3455 err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies",
3456 cfg_priv->extra_buf,
3457 WL_ASSOC_INFO_MAX);
3458 if (err) {
3459 WL_ERR("could not get assoc resp (%d)\n", err);
3460 return err;
3461 }
3462 conn_info->resp_ie_len = resp_len;
3463 conn_info->resp_ie =
3464 kmemdup(cfg_priv->extra_buf, conn_info->resp_ie_len,
3465 GFP_KERNEL);
3466 } else {
3467 conn_info->resp_ie_len = 0;
3468 conn_info->resp_ie = NULL;
3469 }
3470 WL_CONN("req len (%d) resp len (%d)\n",
3471 conn_info->req_ie_len, conn_info->resp_ie_len);
3472
3473 return err;
3474}
3475
3476static s32
3477brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
3478 struct net_device *ndev,
3479 const struct brcmf_event_msg *e)
3480{
3481 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
3482 struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
3483 struct brcmf_channel_info_le channel_le;
3484 struct ieee80211_channel *notify_channel;
3485 struct ieee80211_supported_band *band;
3486 u32 freq;
3487 s32 err = 0;
3488 u32 target_channel;
3489
3490 WL_TRACE("Enter\n");
3491
3492 brcmf_get_assoc_ies(cfg_priv);
3493 brcmf_update_prof(cfg_priv, NULL, &e->addr, WL_PROF_BSSID);
3494 brcmf_update_bss_info(cfg_priv);
3495
3496 brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le,
3497 sizeof(channel_le));
3498
3499 target_channel = le32_to_cpu(channel_le.target_channel);
3500 WL_CONN("Roamed to channel %d\n", target_channel);
3501
3502 if (target_channel <= CH_MAX_2G_CHANNEL)
3503 band = wiphy->bands[IEEE80211_BAND_2GHZ];
3504 else
3505 band = wiphy->bands[IEEE80211_BAND_5GHZ];
3506
3507 freq = ieee80211_channel_to_frequency(target_channel, band->band);
3508 notify_channel = ieee80211_get_channel(wiphy, freq);
3509
3510 cfg80211_roamed(ndev, notify_channel,
3511 (u8 *)brcmf_read_prof(cfg_priv, WL_PROF_BSSID),
3512 conn_info->req_ie, conn_info->req_ie_len,
3513 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
3514 WL_CONN("Report roaming result\n");
3515
3516 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
3517 WL_TRACE("Exit\n");
3518 return err;
3519}
3520
3521static s32
3522brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
3523 struct net_device *ndev, const struct brcmf_event_msg *e,
3524 bool completed)
3525{
3526 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
3527 s32 err = 0;
3528
3529 WL_TRACE("Enter\n");
3530
3531 if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
3532 if (completed) {
3533 brcmf_get_assoc_ies(cfg_priv);
3534 brcmf_update_prof(cfg_priv, NULL, &e->addr,
3535 WL_PROF_BSSID);
3536 brcmf_update_bss_info(cfg_priv);
3537 }
3538 cfg80211_connect_result(ndev,
3539 (u8 *)brcmf_read_prof(cfg_priv,
3540 WL_PROF_BSSID),
3541 conn_info->req_ie,
3542 conn_info->req_ie_len,
3543 conn_info->resp_ie,
3544 conn_info->resp_ie_len,
3545 completed ? WLAN_STATUS_SUCCESS :
3546 WLAN_STATUS_AUTH_TIMEOUT,
3547 GFP_KERNEL);
3548 if (completed)
3549 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
3550 WL_CONN("Report connect result - connection %s\n",
3551 completed ? "succeeded" : "failed");
3552 }
3553 WL_TRACE("Exit\n");
3554 return err;
3555}
3556
3557static s32
3558brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv,
3559 struct net_device *ndev,
3560 const struct brcmf_event_msg *e, void *data)
3561{
3562 s32 err = 0;
3563
3564 if (brcmf_is_linkup(cfg_priv, e)) {
3565 WL_CONN("Linkup\n");
3566 if (brcmf_is_ibssmode(cfg_priv)) {
3567 brcmf_update_prof(cfg_priv, NULL, (void *)e->addr,
3568 WL_PROF_BSSID);
3569 wl_inform_ibss(cfg_priv, ndev, e->addr);
3570 cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
3571 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
3572 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
3573 } else
3574 brcmf_bss_connect_done(cfg_priv, ndev, e, true);
3575 } else if (brcmf_is_linkdown(cfg_priv, e)) {
3576 WL_CONN("Linkdown\n");
3577 if (brcmf_is_ibssmode(cfg_priv)) {
3578 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
3579 if (test_and_clear_bit(WL_STATUS_CONNECTED,
3580 &cfg_priv->status))
3581 brcmf_link_down(cfg_priv);
3582 } else {
3583 brcmf_bss_connect_done(cfg_priv, ndev, e, false);
3584 if (test_and_clear_bit(WL_STATUS_CONNECTED,
3585 &cfg_priv->status)) {
3586 cfg80211_disconnected(ndev, 0, NULL, 0,
3587 GFP_KERNEL);
3588 brcmf_link_down(cfg_priv);
3589 }
3590 }
3591 brcmf_init_prof(cfg_priv->profile);
3592 } else if (brcmf_is_nonetwork(cfg_priv, e)) {
3593 if (brcmf_is_ibssmode(cfg_priv))
3594 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
3595 else
3596 brcmf_bss_connect_done(cfg_priv, ndev, e, false);
3597 }
3598
3599 return err;
3600}
3601
3602static s32
3603brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv,
3604 struct net_device *ndev,
3605 const struct brcmf_event_msg *e, void *data)
3606{
3607 s32 err = 0;
3608 u32 event = be32_to_cpu(e->event_type);
3609 u32 status = be32_to_cpu(e->status);
3610
3611 if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
3612 if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status))
3613 brcmf_bss_roaming_done(cfg_priv, ndev, e);
3614 else
3615 brcmf_bss_connect_done(cfg_priv, ndev, e, true);
3616 }
3617
3618 return err;
3619}
3620
3621static s32
3622brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
3623 struct net_device *ndev,
3624 const struct brcmf_event_msg *e, void *data)
3625{
3626 u16 flags = be16_to_cpu(e->flags);
3627 enum nl80211_key_type key_type;
3628
3629 if (flags & BRCMF_EVENT_MSG_GROUP)
3630 key_type = NL80211_KEYTYPE_GROUP;
3631 else
3632 key_type = NL80211_KEYTYPE_PAIRWISE;
3633
3634 cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
3635 NULL, GFP_KERNEL);
3636
3637 return 0;
3638}
3639
3640static s32
3641brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
3642 struct net_device *ndev,
3643 const struct brcmf_event_msg *e, void *data)
3644{
3645 struct brcmf_channel_info_le channel_inform_le;
3646 struct brcmf_scan_results_le *bss_list_le;
3647 u32 len = WL_SCAN_BUF_MAX;
3648 s32 err = 0;
3649 bool scan_abort = false;
3650 u32 scan_channel;
3651
3652 WL_TRACE("Enter\n");
3653
3654 if (cfg_priv->iscan_on && cfg_priv->iscan_kickstart) {
3655 WL_TRACE("Exit\n");
3656 return brcmf_wakeup_iscan(cfg_to_iscan(cfg_priv));
3657 }
3658
3659 if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
3660 WL_ERR("Scan complete while device not scanning\n");
3661 scan_abort = true;
3662 err = -EINVAL;
3663 goto scan_done_out;
3664 }
3665
3666 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_inform_le,
3667 sizeof(channel_inform_le));
3668 if (err) {
3669 WL_ERR("scan busy (%d)\n", err);
3670 scan_abort = true;
3671 goto scan_done_out;
3672 }
3673 scan_channel = le32_to_cpu(channel_inform_le.scan_channel);
3674 if (scan_channel)
3675 WL_CONN("channel_inform.scan_channel (%d)\n", scan_channel);
3676 cfg_priv->bss_list = cfg_priv->scan_results;
3677 bss_list_le = (struct brcmf_scan_results_le *) cfg_priv->bss_list;
3678
3679 memset(cfg_priv->scan_results, 0, len);
3680 bss_list_le->buflen = cpu_to_le32(len);
3681 err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS,
3682 cfg_priv->scan_results, len);
3683 if (err) {
3684 WL_ERR("%s Scan_results error (%d)\n", ndev->name, err);
3685 err = -EINVAL;
3686 scan_abort = true;
3687 goto scan_done_out;
3688 }
3689 cfg_priv->scan_results->buflen = le32_to_cpu(bss_list_le->buflen);
3690 cfg_priv->scan_results->version = le32_to_cpu(bss_list_le->version);
3691 cfg_priv->scan_results->count = le32_to_cpu(bss_list_le->count);
3692
3693 err = brcmf_inform_bss(cfg_priv);
35aafa9d 3694 if (err)
5b435de0 3695 scan_abort = true;
5b435de0
AS
3696
3697scan_done_out:
3698 if (cfg_priv->scan_request) {
3699 WL_SCAN("calling cfg80211_scan_done\n");
3700 cfg80211_scan_done(cfg_priv->scan_request, scan_abort);
3701 brcmf_set_mpc(ndev, 1);
3702 cfg_priv->scan_request = NULL;
3703 }
3704
3705 WL_TRACE("Exit\n");
3706
3707 return err;
3708}
3709
3710static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
3711{
3712 conf->mode = (u32)-1;
3713 conf->frag_threshold = (u32)-1;
3714 conf->rts_threshold = (u32)-1;
3715 conf->retry_short = (u32)-1;
3716 conf->retry_long = (u32)-1;
3717 conf->tx_power = -1;
3718}
3719
3720static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el)
3721{
3722 memset(el, 0, sizeof(*el));
3723 el->handler[BRCMF_E_SCAN_COMPLETE] = brcmf_notify_scan_status;
3724 el->handler[BRCMF_E_LINK] = brcmf_notify_connect_status;
3725 el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status;
3726 el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status;
3727 el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status;
3728}
3729
3730static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
3731{
3732 kfree(cfg_priv->scan_results);
3733 cfg_priv->scan_results = NULL;
3734 kfree(cfg_priv->bss_info);
3735 cfg_priv->bss_info = NULL;
3736 kfree(cfg_priv->conf);
3737 cfg_priv->conf = NULL;
3738 kfree(cfg_priv->profile);
3739 cfg_priv->profile = NULL;
3740 kfree(cfg_priv->scan_req_int);
3741 cfg_priv->scan_req_int = NULL;
e756af5b
HM
3742 kfree(cfg_priv->escan_ioctl_buf);
3743 cfg_priv->escan_ioctl_buf = NULL;
5b435de0
AS
3744 kfree(cfg_priv->dcmd_buf);
3745 cfg_priv->dcmd_buf = NULL;
3746 kfree(cfg_priv->extra_buf);
3747 cfg_priv->extra_buf = NULL;
3748 kfree(cfg_priv->iscan);
3749 cfg_priv->iscan = NULL;
3750 kfree(cfg_priv->pmk_list);
3751 cfg_priv->pmk_list = NULL;
3752}
3753
3754static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
3755{
3756 cfg_priv->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
3757 if (!cfg_priv->scan_results)
3758 goto init_priv_mem_out;
3759 cfg_priv->conf = kzalloc(sizeof(*cfg_priv->conf), GFP_KERNEL);
3760 if (!cfg_priv->conf)
3761 goto init_priv_mem_out;
3762 cfg_priv->profile = kzalloc(sizeof(*cfg_priv->profile), GFP_KERNEL);
3763 if (!cfg_priv->profile)
3764 goto init_priv_mem_out;
3765 cfg_priv->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
3766 if (!cfg_priv->bss_info)
3767 goto init_priv_mem_out;
3768 cfg_priv->scan_req_int = kzalloc(sizeof(*cfg_priv->scan_req_int),
3769 GFP_KERNEL);
3770 if (!cfg_priv->scan_req_int)
3771 goto init_priv_mem_out;
e756af5b
HM
3772 cfg_priv->escan_ioctl_buf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
3773 if (!cfg_priv->escan_ioctl_buf)
3774 goto init_priv_mem_out;
5b435de0
AS
3775 cfg_priv->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL);
3776 if (!cfg_priv->dcmd_buf)
3777 goto init_priv_mem_out;
3778 cfg_priv->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
3779 if (!cfg_priv->extra_buf)
3780 goto init_priv_mem_out;
3781 cfg_priv->iscan = kzalloc(sizeof(*cfg_priv->iscan), GFP_KERNEL);
3782 if (!cfg_priv->iscan)
3783 goto init_priv_mem_out;
3784 cfg_priv->pmk_list = kzalloc(sizeof(*cfg_priv->pmk_list), GFP_KERNEL);
3785 if (!cfg_priv->pmk_list)
3786 goto init_priv_mem_out;
3787
3788 return 0;
3789
3790init_priv_mem_out:
3791 brcmf_deinit_priv_mem(cfg_priv);
3792
3793 return -ENOMEM;
3794}
3795
3796/*
3797* retrieve first queued event from head
3798*/
3799
3800static struct brcmf_cfg80211_event_q *brcmf_deq_event(
3801 struct brcmf_cfg80211_priv *cfg_priv)
3802{
3803 struct brcmf_cfg80211_event_q *e = NULL;
3804
3805 spin_lock_irq(&cfg_priv->evt_q_lock);
3806 if (!list_empty(&cfg_priv->evt_q_list)) {
3807 e = list_first_entry(&cfg_priv->evt_q_list,
3808 struct brcmf_cfg80211_event_q, evt_q_list);
3809 list_del(&e->evt_q_list);
3810 }
3811 spin_unlock_irq(&cfg_priv->evt_q_lock);
3812
3813 return e;
3814}
3815
3816/*
bcbec9e7
AS
3817* push event to tail of the queue
3818*
3819* remark: this function may not sleep as it is called in atomic context.
5b435de0
AS
3820*/
3821
3822static s32
3823brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event,
c4fdb056 3824 const struct brcmf_event_msg *msg, void *data)
5b435de0
AS
3825{
3826 struct brcmf_cfg80211_event_q *e;
3827 s32 err = 0;
cf44066a 3828 ulong flags;
c4fdb056
HM
3829 u32 data_len;
3830 u32 total_len;
5b435de0 3831
c4fdb056
HM
3832 total_len = sizeof(struct brcmf_cfg80211_event_q);
3833 if (data)
3834 data_len = be32_to_cpu(msg->datalen);
3835 else
3836 data_len = 0;
3837 total_len += data_len;
3838 e = kzalloc(total_len, GFP_ATOMIC);
5b435de0
AS
3839 if (!e)
3840 return -ENOMEM;
3841
3842 e->etype = event;
3843 memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
c4fdb056
HM
3844 if (data)
3845 memcpy(&e->edata, data, data_len);
5b435de0 3846
cf44066a 3847 spin_lock_irqsave(&cfg_priv->evt_q_lock, flags);
5b435de0 3848 list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list);
cf44066a 3849 spin_unlock_irqrestore(&cfg_priv->evt_q_lock, flags);
5b435de0
AS
3850
3851 return err;
3852}
3853
3854static void brcmf_put_event(struct brcmf_cfg80211_event_q *e)
3855{
3856 kfree(e);
3857}
3858
3859static void brcmf_cfg80211_event_handler(struct work_struct *work)
3860{
3861 struct brcmf_cfg80211_priv *cfg_priv =
3862 container_of(work, struct brcmf_cfg80211_priv,
3863 event_work);
3864 struct brcmf_cfg80211_event_q *e;
3865
3866 e = brcmf_deq_event(cfg_priv);
3867 if (unlikely(!e)) {
3868 WL_ERR("event queue empty...\n");
3869 return;
3870 }
3871
3872 do {
3873 WL_INFO("event type (%d)\n", e->etype);
3874 if (cfg_priv->el.handler[e->etype])
3875 cfg_priv->el.handler[e->etype](cfg_priv,
3876 cfg_to_ndev(cfg_priv),
3877 &e->emsg, e->edata);
3878 else
3879 WL_INFO("Unknown Event (%d): ignoring\n", e->etype);
3880 brcmf_put_event(e);
3881 } while ((e = brcmf_deq_event(cfg_priv)));
3882
3883}
3884
3885static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv)
3886{
3887 spin_lock_init(&cfg_priv->evt_q_lock);
3888 INIT_LIST_HEAD(&cfg_priv->evt_q_list);
3889}
3890
3891static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv)
3892{
3893 struct brcmf_cfg80211_event_q *e;
3894
3895 spin_lock_irq(&cfg_priv->evt_q_lock);
3896 while (!list_empty(&cfg_priv->evt_q_list)) {
3897 e = list_first_entry(&cfg_priv->evt_q_list,
3898 struct brcmf_cfg80211_event_q, evt_q_list);
3899 list_del(&e->evt_q_list);
3900 kfree(e);
3901 }
3902 spin_unlock_irq(&cfg_priv->evt_q_lock);
3903}
3904
3905static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv)
3906{
3907 s32 err = 0;
3908
3909 cfg_priv->scan_request = NULL;
3910 cfg_priv->pwr_save = true;
e756af5b 3911#ifdef CONFIG_BRCMISCAN
5b435de0
AS
3912 cfg_priv->iscan_on = true; /* iscan on & off switch.
3913 we enable iscan per default */
e756af5b
HM
3914 cfg_priv->escan_on = false; /* escan on & off switch.
3915 we disable escan per default */
3916#else
3917 cfg_priv->iscan_on = false; /* iscan on & off switch.
3918 we disable iscan per default */
3919 cfg_priv->escan_on = true; /* escan on & off switch.
3920 we enable escan per default */
3921#endif
5b435de0
AS
3922 cfg_priv->roam_on = true; /* roam on & off switch.
3923 we enable roam per default */
3924
3925 cfg_priv->iscan_kickstart = false;
3926 cfg_priv->active_scan = true; /* we do active scan for
3927 specific scan per default */
3928 cfg_priv->dongle_up = false; /* dongle is not up yet */
3929 brcmf_init_eq(cfg_priv);
3930 err = brcmf_init_priv_mem(cfg_priv);
3931 if (err)
3932 return err;
3933 INIT_WORK(&cfg_priv->event_work, brcmf_cfg80211_event_handler);
3934 brcmf_init_eloop_handler(&cfg_priv->el);
3935 mutex_init(&cfg_priv->usr_sync);
3936 err = brcmf_init_iscan(cfg_priv);
3937 if (err)
3938 return err;
e756af5b 3939 brcmf_init_escan(cfg_priv);
5b435de0
AS
3940 brcmf_init_conf(cfg_priv->conf);
3941 brcmf_init_prof(cfg_priv->profile);
3942 brcmf_link_down(cfg_priv);
3943
3944 return err;
3945}
3946
3947static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv)
3948{
3949 cancel_work_sync(&cfg_priv->event_work);
3950 cfg_priv->dongle_up = false; /* dongle down */
3951 brcmf_flush_eq(cfg_priv);
3952 brcmf_link_down(cfg_priv);
3953 brcmf_term_iscan(cfg_priv);
3954 brcmf_deinit_priv_mem(cfg_priv);
3955}
3956
3957struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev,
3958 struct device *busdev,
3959 void *data)
3960{
3961 struct wireless_dev *wdev;
3962 struct brcmf_cfg80211_priv *cfg_priv;
3963 struct brcmf_cfg80211_iface *ci;
3964 struct brcmf_cfg80211_dev *cfg_dev;
3965 s32 err = 0;
3966
3967 if (!ndev) {
3968 WL_ERR("ndev is invalid\n");
3969 return NULL;
3970 }
3971 cfg_dev = kzalloc(sizeof(struct brcmf_cfg80211_dev), GFP_KERNEL);
3972 if (!cfg_dev)
3973 return NULL;
3974
3975 wdev = brcmf_alloc_wdev(sizeof(struct brcmf_cfg80211_iface), busdev);
3976 if (IS_ERR(wdev)) {
3977 kfree(cfg_dev);
3978 return NULL;
3979 }
3980
3981 wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS);
3982 cfg_priv = wdev_to_cfg(wdev);
3983 cfg_priv->wdev = wdev;
3984 cfg_priv->pub = data;
3985 ci = (struct brcmf_cfg80211_iface *)&cfg_priv->ci;
3986 ci->cfg_priv = cfg_priv;
3987 ndev->ieee80211_ptr = wdev;
3988 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
3989 wdev->netdev = ndev;
3990 err = wl_init_priv(cfg_priv);
3991 if (err) {
3992 WL_ERR("Failed to init iwm_priv (%d)\n", err);
3993 goto cfg80211_attach_out;
3994 }
3995 brcmf_set_drvdata(cfg_dev, ci);
3996
3997 return cfg_dev;
3998
3999cfg80211_attach_out:
4000 brcmf_free_wdev(cfg_priv);
4001 kfree(cfg_dev);
4002 return NULL;
4003}
4004
4005void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg_dev)
4006{
4007 struct brcmf_cfg80211_priv *cfg_priv;
4008
4009 cfg_priv = brcmf_priv_get(cfg_dev);
4010
4011 wl_deinit_priv(cfg_priv);
4012 brcmf_free_wdev(cfg_priv);
4013 brcmf_set_drvdata(cfg_dev, NULL);
4014 kfree(cfg_dev);
4015}
4016
4017void
4018brcmf_cfg80211_event(struct net_device *ndev,
4019 const struct brcmf_event_msg *e, void *data)
4020{
4021 u32 event_type = be32_to_cpu(e->event_type);
4022 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
4023
c4fdb056 4024 if (!brcmf_enq_event(cfg_priv, event_type, e, data))
5b435de0
AS
4025 schedule_work(&cfg_priv->event_work);
4026}
4027
4028static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
4029{
4030 s32 infra = 0;
4031 s32 err = 0;
4032
4033 switch (iftype) {
4034 case NL80211_IFTYPE_MONITOR:
4035 case NL80211_IFTYPE_WDS:
4036 WL_ERR("type (%d) : currently we do not support this mode\n",
4037 iftype);
4038 err = -EINVAL;
4039 return err;
4040 case NL80211_IFTYPE_ADHOC:
4041 infra = 0;
4042 break;
4043 case NL80211_IFTYPE_STATION:
4044 infra = 1;
4045 break;
4046 default:
4047 err = -EINVAL;
4048 WL_ERR("invalid type (%d)\n", iftype);
4049 return err;
4050 }
4051 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
4052 if (err) {
4053 WL_ERR("WLC_SET_INFRA error (%d)\n", err);
4054 return err;
4055 }
4056
4057 return 0;
4058}
4059
4060static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
4061{
4062 /* Room for "event_msgs" + '\0' + bitvec */
4063 s8 iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
4064 s8 eventmask[BRCMF_EVENTING_MASK_LEN];
4065 s32 err = 0;
4066
4067 WL_TRACE("Enter\n");
4068
4069 /* Setup event_msgs */
53a2277d
AB
4070 brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
4071 iovbuf, sizeof(iovbuf));
5b435de0
AS
4072 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf));
4073 if (err) {
4074 WL_ERR("Get event_msgs error (%d)\n", err);
4075 goto dongle_eventmsg_out;
4076 }
4077 memcpy(eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN);
4078
4079 setbit(eventmask, BRCMF_E_SET_SSID);
4080 setbit(eventmask, BRCMF_E_ROAM);
4081 setbit(eventmask, BRCMF_E_PRUNE);
4082 setbit(eventmask, BRCMF_E_AUTH);
4083 setbit(eventmask, BRCMF_E_REASSOC);
4084 setbit(eventmask, BRCMF_E_REASSOC_IND);
4085 setbit(eventmask, BRCMF_E_DEAUTH_IND);
4086 setbit(eventmask, BRCMF_E_DISASSOC_IND);
4087 setbit(eventmask, BRCMF_E_DISASSOC);
4088 setbit(eventmask, BRCMF_E_JOIN);
4089 setbit(eventmask, BRCMF_E_ASSOC_IND);
4090 setbit(eventmask, BRCMF_E_PSK_SUP);
4091 setbit(eventmask, BRCMF_E_LINK);
4092 setbit(eventmask, BRCMF_E_NDIS_LINK);
4093 setbit(eventmask, BRCMF_E_MIC_ERROR);
4094 setbit(eventmask, BRCMF_E_PMKID_CACHE);
4095 setbit(eventmask, BRCMF_E_TXFAIL);
4096 setbit(eventmask, BRCMF_E_JOIN_START);
4097 setbit(eventmask, BRCMF_E_SCAN_COMPLETE);
e756af5b 4098 setbit(eventmask, BRCMF_E_ESCAN_RESULT);
5b435de0 4099
53a2277d
AB
4100 brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
4101 iovbuf, sizeof(iovbuf));
5b435de0
AS
4102 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
4103 if (err) {
4104 WL_ERR("Set event_msgs error (%d)\n", err);
4105 goto dongle_eventmsg_out;
4106 }
4107
4108dongle_eventmsg_out:
4109 WL_TRACE("Exit\n");
4110 return err;
4111}
4112
4113static s32
4114brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
4115{
4116 s8 iovbuf[32];
5b435de0 4117 s32 err = 0;
f588bc0c
AS
4118 __le32 roamtrigger[2];
4119 __le32 roam_delta[2];
4120 __le32 bcn_to_le;
4121 __le32 roamvar_le;
5b435de0
AS
4122
4123 /*
4124 * Setup timeout if Beacons are lost and roam is
4125 * off to report link down
4126 */
4127 if (roamvar) {
f588bc0c 4128 bcn_to_le = cpu_to_le32(bcn_timeout);
53a2277d 4129 brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_to_le,
f588bc0c 4130 sizeof(bcn_to_le), iovbuf, sizeof(iovbuf));
5b435de0
AS
4131 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR,
4132 iovbuf, sizeof(iovbuf));
4133 if (err) {
4134 WL_ERR("bcn_timeout error (%d)\n", err);
4135 goto dongle_rom_out;
4136 }
4137 }
4138
4139 /*
4140 * Enable/Disable built-in roaming to allow supplicant
4141 * to take care of roaming
4142 */
4143 WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On");
f588bc0c 4144 roamvar_le = cpu_to_le32(roamvar);
53a2277d 4145 brcmf_c_mkiovar("roam_off", (char *)&roamvar_le,
f588bc0c 4146 sizeof(roamvar_le), iovbuf, sizeof(iovbuf));
5b435de0
AS
4147 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
4148 if (err) {
4149 WL_ERR("roam_off error (%d)\n", err);
4150 goto dongle_rom_out;
4151 }
4152
f588bc0c
AS
4153 roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL);
4154 roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL);
5b435de0
AS
4155 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_TRIGGER,
4156 (void *)roamtrigger, sizeof(roamtrigger));
4157 if (err) {
4158 WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
4159 goto dongle_rom_out;
4160 }
4161
f588bc0c
AS
4162 roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA);
4163 roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL);
5b435de0
AS
4164 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_DELTA,
4165 (void *)roam_delta, sizeof(roam_delta));
4166 if (err) {
4167 WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err);
4168 goto dongle_rom_out;
4169 }
4170
4171dongle_rom_out:
4172 return err;
4173}
4174
4175static s32
4176brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
c68cdc0f 4177 s32 scan_unassoc_time, s32 scan_passive_time)
5b435de0
AS
4178{
4179 s32 err = 0;
c68cdc0f
AS
4180 __le32 scan_assoc_tm_le = cpu_to_le32(scan_assoc_time);
4181 __le32 scan_unassoc_tm_le = cpu_to_le32(scan_unassoc_time);
4182 __le32 scan_passive_tm_le = cpu_to_le32(scan_passive_time);
5b435de0
AS
4183
4184 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME,
c68cdc0f 4185 &scan_assoc_tm_le, sizeof(scan_assoc_tm_le));
5b435de0
AS
4186 if (err) {
4187 if (err == -EOPNOTSUPP)
4188 WL_INFO("Scan assoc time is not supported\n");
4189 else
4190 WL_ERR("Scan assoc time error (%d)\n", err);
4191 goto dongle_scantime_out;
4192 }
4193 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME,
c68cdc0f 4194 &scan_unassoc_tm_le, sizeof(scan_unassoc_tm_le));
5b435de0
AS
4195 if (err) {
4196 if (err == -EOPNOTSUPP)
4197 WL_INFO("Scan unassoc time is not supported\n");
4198 else
4199 WL_ERR("Scan unassoc time error (%d)\n", err);
4200 goto dongle_scantime_out;
4201 }
4202
4203 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME,
c68cdc0f 4204 &scan_passive_tm_le, sizeof(scan_passive_tm_le));
5b435de0
AS
4205 if (err) {
4206 if (err == -EOPNOTSUPP)
4207 WL_INFO("Scan passive time is not supported\n");
4208 else
4209 WL_ERR("Scan passive time error (%d)\n", err);
4210 goto dongle_scantime_out;
4211 }
4212
4213dongle_scantime_out:
4214 return err;
4215}
4216
4217static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv)
4218{
4219 struct wiphy *wiphy;
4220 s32 phy_list;
4221 s8 phy;
4222 s32 err = 0;
4223
4224 err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST,
4225 &phy_list, sizeof(phy_list));
4226 if (err) {
4227 WL_ERR("error (%d)\n", err);
4228 return err;
4229 }
4230
4231 phy = ((char *)&phy_list)[1];
4232 WL_INFO("%c phy\n", phy);
4233 if (phy == 'n' || phy == 'a') {
4234 wiphy = cfg_to_wiphy(cfg_priv);
4235 wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
4236 }
4237
4238 return err;
4239}
4240
4241static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv)
4242{
4243 return wl_update_wiphybands(cfg_priv);
4244}
4245
4246static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv)
4247{
4248 struct net_device *ndev;
4249 struct wireless_dev *wdev;
4250 s32 power_mode;
4251 s32 err = 0;
4252
4253 if (cfg_priv->dongle_up)
4254 return err;
4255
4256 ndev = cfg_to_ndev(cfg_priv);
4257 wdev = ndev->ieee80211_ptr;
4258
4259 brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
4260 WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
4261
4262 err = brcmf_dongle_eventmsg(ndev);
4263 if (err)
4264 goto default_conf_out;
4265
4266 power_mode = cfg_priv->pwr_save ? PM_FAST : PM_OFF;
4267 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &power_mode);
4268 if (err)
4269 goto default_conf_out;
4270 WL_INFO("power save set to %s\n",
4271 (power_mode ? "enabled" : "disabled"));
4272
4273 err = brcmf_dongle_roam(ndev, (cfg_priv->roam_on ? 0 : 1),
4274 WL_BEACON_TIMEOUT);
4275 if (err)
4276 goto default_conf_out;
4277 err = brcmf_dongle_mode(ndev, wdev->iftype);
4278 if (err && err != -EINPROGRESS)
4279 goto default_conf_out;
4280 err = brcmf_dongle_probecap(cfg_priv);
4281 if (err)
4282 goto default_conf_out;
4283
4284 /* -EINPROGRESS: Call commit handler */
4285
4286default_conf_out:
4287
4288 cfg_priv->dongle_up = true;
4289
4290 return err;
4291
4292}
4293
4294static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv)
4295{
4296 char buf[10+IFNAMSIZ];
4297 struct dentry *fd;
4298 s32 err = 0;
4299
4300 sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name);
4301 cfg_priv->debugfsdir = debugfs_create_dir(buf,
4302 cfg_to_wiphy(cfg_priv)->debugfsdir);
4303
4304 fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir,
4305 (u16 *)&cfg_priv->profile->beacon_interval);
4306 if (!fd) {
4307 err = -ENOMEM;
4308 goto err_out;
4309 }
4310
4311 fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir,
4312 (u8 *)&cfg_priv->profile->dtim_period);
4313 if (!fd) {
4314 err = -ENOMEM;
4315 goto err_out;
4316 }
4317
4318err_out:
4319 return err;
4320}
4321
4322static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv)
4323{
4324 debugfs_remove_recursive(cfg_priv->debugfsdir);
4325 cfg_priv->debugfsdir = NULL;
4326}
4327
4328static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv)
4329{
4330 s32 err = 0;
4331
4332 set_bit(WL_STATUS_READY, &cfg_priv->status);
4333
4334 brcmf_debugfs_add_netdev_params(cfg_priv);
4335
4336 err = brcmf_config_dongle(cfg_priv);
4337 if (err)
4338 return err;
4339
4340 brcmf_invoke_iscan(cfg_priv);
4341
4342 return err;
4343}
4344
4345static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv)
4346{
4347 /*
4348 * While going down, if associated with AP disassociate
4349 * from AP to save power
4350 */
4351 if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
4352 test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
4353 test_bit(WL_STATUS_READY, &cfg_priv->status)) {
4354 WL_INFO("Disassociating from AP");
4355 brcmf_link_down(cfg_priv);
4356
4357 /* Make sure WPA_Supplicant receives all the event
4358 generated due to DISASSOC call to the fw to keep
4359 the state fw and WPA_Supplicant state consistent
4360 */
4361 brcmf_delay(500);
4362 }
4363
4364 set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
4365 brcmf_term_iscan(cfg_priv);
4366 if (cfg_priv->scan_request) {
4367 cfg80211_scan_done(cfg_priv->scan_request, true);
4368 /* May need to perform this to cover rmmod */
4369 /* wl_set_mpc(cfg_to_ndev(wl), 1); */
4370 cfg_priv->scan_request = NULL;
4371 }
4372 clear_bit(WL_STATUS_READY, &cfg_priv->status);
4373 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
4374 clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
4375
4376 brcmf_debugfs_remove_netdev(cfg_priv);
4377
4378 return 0;
4379}
4380
4381s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev)
4382{
4383 struct brcmf_cfg80211_priv *cfg_priv;
4384 s32 err = 0;
4385
4386 cfg_priv = brcmf_priv_get(cfg_dev);
4387 mutex_lock(&cfg_priv->usr_sync);
4388 err = __brcmf_cfg80211_up(cfg_priv);
4389 mutex_unlock(&cfg_priv->usr_sync);
4390
4391 return err;
4392}
4393
4394s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev)
4395{
4396 struct brcmf_cfg80211_priv *cfg_priv;
4397 s32 err = 0;
4398
4399 cfg_priv = brcmf_priv_get(cfg_dev);
4400 mutex_lock(&cfg_priv->usr_sync);
4401 err = __brcmf_cfg80211_down(cfg_priv);
4402 mutex_unlock(&cfg_priv->usr_sync);
4403
4404 return err;
4405}
4406
4407static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv,
4408 u8 t, u8 l, u8 *v)
4409{
4410 struct brcmf_cfg80211_ie *ie = &cfg_priv->ie;
4411 s32 err = 0;
4412
4413 if (ie->offset + l + 2 > WL_TLV_INFO_MAX) {
4414 WL_ERR("ei crosses buffer boundary\n");
4415 return -ENOSPC;
4416 }
4417 ie->buf[ie->offset] = t;
4418 ie->buf[ie->offset + 1] = l;
4419 memcpy(&ie->buf[ie->offset + 2], v, l);
4420 ie->offset += l + 2;
4421
4422 return err;
4423}
This page took 0.285422 seconds and 5 git commands to generate.