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