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