brcm80211: Use pr_fmt and pr_<level>
[GitHub/mt8127/android_kernel_alcatel_ttab.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>
31
32#include <brcmu_utils.h>
33#include <defs.h>
34#include <brcmu_wifi.h>
35#include "dhd.h"
36#include "wl_cfg80211.h"
37
38#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
39 (sizeof(struct brcmf_assoc_params_le) - sizeof(u16))
40
41static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
42
43static u32 brcmf_dbg_level = WL_DBG_ERR;
44
45static void brcmf_set_drvdata(struct brcmf_cfg80211_dev *dev, void *data)
46{
47 dev->driver_data = data;
48}
49
50static void *brcmf_get_drvdata(struct brcmf_cfg80211_dev *dev)
51{
52 void *data = NULL;
53
54 if (dev)
55 data = dev->driver_data;
56 return data;
57}
58
59static
60struct brcmf_cfg80211_priv *brcmf_priv_get(struct brcmf_cfg80211_dev *cfg_dev)
61{
62 struct brcmf_cfg80211_iface *ci = brcmf_get_drvdata(cfg_dev);
63 return ci->cfg_priv;
64}
65
66static bool check_sys_up(struct wiphy *wiphy)
67{
68 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
69 if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) {
70 WL_INFO("device is not ready : status (%d)\n",
71 (int)cfg_priv->status);
72 return false;
73 }
74 return true;
75}
76
77#define CHAN2G(_channel, _freq, _flags) { \
78 .band = IEEE80211_BAND_2GHZ, \
79 .center_freq = (_freq), \
80 .hw_value = (_channel), \
81 .flags = (_flags), \
82 .max_antenna_gain = 0, \
83 .max_power = 30, \
84}
85
86#define CHAN5G(_channel, _flags) { \
87 .band = IEEE80211_BAND_5GHZ, \
88 .center_freq = 5000 + (5 * (_channel)), \
89 .hw_value = (_channel), \
90 .flags = (_flags), \
91 .max_antenna_gain = 0, \
92 .max_power = 30, \
93}
94
95#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
96#define RATETAB_ENT(_rateid, _flags) \
97 { \
98 .bitrate = RATE_TO_BASE100KBPS(_rateid), \
99 .hw_value = (_rateid), \
100 .flags = (_flags), \
101 }
102
103static struct ieee80211_rate __wl_rates[] = {
104 RATETAB_ENT(BRCM_RATE_1M, 0),
105 RATETAB_ENT(BRCM_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
106 RATETAB_ENT(BRCM_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
107 RATETAB_ENT(BRCM_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
108 RATETAB_ENT(BRCM_RATE_6M, 0),
109 RATETAB_ENT(BRCM_RATE_9M, 0),
110 RATETAB_ENT(BRCM_RATE_12M, 0),
111 RATETAB_ENT(BRCM_RATE_18M, 0),
112 RATETAB_ENT(BRCM_RATE_24M, 0),
113 RATETAB_ENT(BRCM_RATE_36M, 0),
114 RATETAB_ENT(BRCM_RATE_48M, 0),
115 RATETAB_ENT(BRCM_RATE_54M, 0),
116};
117
118#define wl_a_rates (__wl_rates + 4)
119#define wl_a_rates_size 8
120#define wl_g_rates (__wl_rates + 0)
121#define wl_g_rates_size 12
122
123static struct ieee80211_channel __wl_2ghz_channels[] = {
124 CHAN2G(1, 2412, 0),
125 CHAN2G(2, 2417, 0),
126 CHAN2G(3, 2422, 0),
127 CHAN2G(4, 2427, 0),
128 CHAN2G(5, 2432, 0),
129 CHAN2G(6, 2437, 0),
130 CHAN2G(7, 2442, 0),
131 CHAN2G(8, 2447, 0),
132 CHAN2G(9, 2452, 0),
133 CHAN2G(10, 2457, 0),
134 CHAN2G(11, 2462, 0),
135 CHAN2G(12, 2467, 0),
136 CHAN2G(13, 2472, 0),
137 CHAN2G(14, 2484, 0),
138};
139
140static struct ieee80211_channel __wl_5ghz_a_channels[] = {
141 CHAN5G(34, 0), CHAN5G(36, 0),
142 CHAN5G(38, 0), CHAN5G(40, 0),
143 CHAN5G(42, 0), CHAN5G(44, 0),
144 CHAN5G(46, 0), CHAN5G(48, 0),
145 CHAN5G(52, 0), CHAN5G(56, 0),
146 CHAN5G(60, 0), CHAN5G(64, 0),
147 CHAN5G(100, 0), CHAN5G(104, 0),
148 CHAN5G(108, 0), CHAN5G(112, 0),
149 CHAN5G(116, 0), CHAN5G(120, 0),
150 CHAN5G(124, 0), CHAN5G(128, 0),
151 CHAN5G(132, 0), CHAN5G(136, 0),
152 CHAN5G(140, 0), CHAN5G(149, 0),
153 CHAN5G(153, 0), CHAN5G(157, 0),
154 CHAN5G(161, 0), CHAN5G(165, 0),
155 CHAN5G(184, 0), CHAN5G(188, 0),
156 CHAN5G(192, 0), CHAN5G(196, 0),
157 CHAN5G(200, 0), CHAN5G(204, 0),
158 CHAN5G(208, 0), CHAN5G(212, 0),
159 CHAN5G(216, 0),
160};
161
162static struct ieee80211_channel __wl_5ghz_n_channels[] = {
163 CHAN5G(32, 0), CHAN5G(34, 0),
164 CHAN5G(36, 0), CHAN5G(38, 0),
165 CHAN5G(40, 0), CHAN5G(42, 0),
166 CHAN5G(44, 0), CHAN5G(46, 0),
167 CHAN5G(48, 0), CHAN5G(50, 0),
168 CHAN5G(52, 0), CHAN5G(54, 0),
169 CHAN5G(56, 0), CHAN5G(58, 0),
170 CHAN5G(60, 0), CHAN5G(62, 0),
171 CHAN5G(64, 0), CHAN5G(66, 0),
172 CHAN5G(68, 0), CHAN5G(70, 0),
173 CHAN5G(72, 0), CHAN5G(74, 0),
174 CHAN5G(76, 0), CHAN5G(78, 0),
175 CHAN5G(80, 0), CHAN5G(82, 0),
176 CHAN5G(84, 0), CHAN5G(86, 0),
177 CHAN5G(88, 0), CHAN5G(90, 0),
178 CHAN5G(92, 0), CHAN5G(94, 0),
179 CHAN5G(96, 0), CHAN5G(98, 0),
180 CHAN5G(100, 0), CHAN5G(102, 0),
181 CHAN5G(104, 0), CHAN5G(106, 0),
182 CHAN5G(108, 0), CHAN5G(110, 0),
183 CHAN5G(112, 0), CHAN5G(114, 0),
184 CHAN5G(116, 0), CHAN5G(118, 0),
185 CHAN5G(120, 0), CHAN5G(122, 0),
186 CHAN5G(124, 0), CHAN5G(126, 0),
187 CHAN5G(128, 0), CHAN5G(130, 0),
188 CHAN5G(132, 0), CHAN5G(134, 0),
189 CHAN5G(136, 0), CHAN5G(138, 0),
190 CHAN5G(140, 0), CHAN5G(142, 0),
191 CHAN5G(144, 0), CHAN5G(145, 0),
192 CHAN5G(146, 0), CHAN5G(147, 0),
193 CHAN5G(148, 0), CHAN5G(149, 0),
194 CHAN5G(150, 0), CHAN5G(151, 0),
195 CHAN5G(152, 0), CHAN5G(153, 0),
196 CHAN5G(154, 0), CHAN5G(155, 0),
197 CHAN5G(156, 0), CHAN5G(157, 0),
198 CHAN5G(158, 0), CHAN5G(159, 0),
199 CHAN5G(160, 0), CHAN5G(161, 0),
200 CHAN5G(162, 0), CHAN5G(163, 0),
201 CHAN5G(164, 0), CHAN5G(165, 0),
202 CHAN5G(166, 0), CHAN5G(168, 0),
203 CHAN5G(170, 0), CHAN5G(172, 0),
204 CHAN5G(174, 0), CHAN5G(176, 0),
205 CHAN5G(178, 0), CHAN5G(180, 0),
206 CHAN5G(182, 0), CHAN5G(184, 0),
207 CHAN5G(186, 0), CHAN5G(188, 0),
208 CHAN5G(190, 0), CHAN5G(192, 0),
209 CHAN5G(194, 0), CHAN5G(196, 0),
210 CHAN5G(198, 0), CHAN5G(200, 0),
211 CHAN5G(202, 0), CHAN5G(204, 0),
212 CHAN5G(206, 0), CHAN5G(208, 0),
213 CHAN5G(210, 0), CHAN5G(212, 0),
214 CHAN5G(214, 0), CHAN5G(216, 0),
215 CHAN5G(218, 0), CHAN5G(220, 0),
216 CHAN5G(222, 0), CHAN5G(224, 0),
217 CHAN5G(226, 0), CHAN5G(228, 0),
218};
219
220static struct ieee80211_supported_band __wl_band_2ghz = {
221 .band = IEEE80211_BAND_2GHZ,
222 .channels = __wl_2ghz_channels,
223 .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
224 .bitrates = wl_g_rates,
225 .n_bitrates = wl_g_rates_size,
226};
227
228static struct ieee80211_supported_band __wl_band_5ghz_a = {
229 .band = IEEE80211_BAND_5GHZ,
230 .channels = __wl_5ghz_a_channels,
231 .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
232 .bitrates = wl_a_rates,
233 .n_bitrates = wl_a_rates_size,
234};
235
236static struct ieee80211_supported_band __wl_band_5ghz_n = {
237 .band = IEEE80211_BAND_5GHZ,
238 .channels = __wl_5ghz_n_channels,
239 .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
240 .bitrates = wl_a_rates,
241 .n_bitrates = wl_a_rates_size,
242};
243
244static const u32 __wl_cipher_suites[] = {
245 WLAN_CIPHER_SUITE_WEP40,
246 WLAN_CIPHER_SUITE_WEP104,
247 WLAN_CIPHER_SUITE_TKIP,
248 WLAN_CIPHER_SUITE_CCMP,
249 WLAN_CIPHER_SUITE_AES_CMAC,
250};
251
f8e4b412
AB
252/* tag_ID/length/value_buffer tuple */
253struct brcmf_tlv {
254 u8 id;
255 u8 len;
256 u8 data[1];
257};
258
ef6ac17a
AB
259/* Quarter dBm units to mW
260 * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
261 * Table is offset so the last entry is largest mW value that fits in
262 * a u16.
263 */
264
265#define QDBM_OFFSET 153 /* Offset for first entry */
266#define QDBM_TABLE_LEN 40 /* Table size */
267
268/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
269 * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
270 */
271#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */
272
273/* Largest mW value that will round down to the last table entry,
274 * QDBM_OFFSET + QDBM_TABLE_LEN-1.
275 * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) +
276 * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
277 */
278#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */
279
280static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
281/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */
282/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
283/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
284/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
285/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
286/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
287};
288
289static u16 brcmf_qdbm_to_mw(u8 qdbm)
290{
291 uint factor = 1;
292 int idx = qdbm - QDBM_OFFSET;
293
294 if (idx >= QDBM_TABLE_LEN)
295 /* clamp to max u16 mW value */
296 return 0xFFFF;
297
298 /* scale the qdBm index up to the range of the table 0-40
299 * where an offset of 40 qdBm equals a factor of 10 mW.
300 */
301 while (idx < 0) {
302 idx += 40;
303 factor *= 10;
304 }
305
306 /* return the mW value scaled down to the correct factor of 10,
307 * adding in factor/2 to get proper rounding.
308 */
309 return (nqdBm_to_mW_map[idx] + factor / 2) / factor;
310}
311
312static u8 brcmf_mw_to_qdbm(u16 mw)
313{
314 u8 qdbm;
315 int offset;
316 uint mw_uint = mw;
317 uint boundary;
318
319 /* handle boundary case */
320 if (mw_uint <= 1)
321 return 0;
322
323 offset = QDBM_OFFSET;
324
325 /* move mw into the range of the table */
326 while (mw_uint < QDBM_TABLE_LOW_BOUND) {
327 mw_uint *= 10;
328 offset -= 40;
329 }
330
331 for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) {
332 boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] -
333 nqdBm_to_mW_map[qdbm]) / 2;
334 if (mw_uint < boundary)
335 break;
336 }
337
338 qdbm += (u8) offset;
339
340 return qdbm;
341}
342
5b435de0
AS
343/* function for reading/writing a single u32 from/to the dongle */
344static int
345brcmf_exec_dcmd_u32(struct net_device *ndev, u32 cmd, u32 *par)
346{
347 int err;
348 __le32 par_le = cpu_to_le32(*par);
349
350 err = brcmf_exec_dcmd(ndev, cmd, &par_le, sizeof(__le32));
351 *par = le32_to_cpu(par_le);
352
353 return err;
354}
355
356static void convert_key_from_CPU(struct brcmf_wsec_key *key,
357 struct brcmf_wsec_key_le *key_le)
358{
359 key_le->index = cpu_to_le32(key->index);
360 key_le->len = cpu_to_le32(key->len);
361 key_le->algo = cpu_to_le32(key->algo);
362 key_le->flags = cpu_to_le32(key->flags);
363 key_le->rxiv.hi = cpu_to_le32(key->rxiv.hi);
364 key_le->rxiv.lo = cpu_to_le16(key->rxiv.lo);
365 key_le->iv_initialized = cpu_to_le32(key->iv_initialized);
366 memcpy(key_le->data, key->data, sizeof(key->data));
367 memcpy(key_le->ea, key->ea, sizeof(key->ea));
368}
369
370static int send_key_to_dongle(struct net_device *ndev,
371 struct brcmf_wsec_key *key)
372{
373 int err;
374 struct brcmf_wsec_key_le key_le;
375
376 convert_key_from_CPU(key, &key_le);
377 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le, sizeof(key_le));
378 if (err)
379 WL_ERR("WLC_SET_KEY error (%d)\n", err);
380 return err;
381}
382
383static s32
384brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
385 enum nl80211_iftype type, u32 *flags,
386 struct vif_params *params)
387{
388 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
389 struct wireless_dev *wdev;
390 s32 infra = 0;
391 s32 err = 0;
392
393 WL_TRACE("Enter\n");
394 if (!check_sys_up(wiphy))
395 return -EIO;
396
397 switch (type) {
398 case NL80211_IFTYPE_MONITOR:
399 case NL80211_IFTYPE_WDS:
400 WL_ERR("type (%d) : currently we do not support this type\n",
401 type);
402 return -EOPNOTSUPP;
403 case NL80211_IFTYPE_ADHOC:
404 cfg_priv->conf->mode = WL_MODE_IBSS;
405 infra = 0;
406 break;
407 case NL80211_IFTYPE_STATION:
408 cfg_priv->conf->mode = WL_MODE_BSS;
409 infra = 1;
410 break;
411 default:
412 err = -EINVAL;
413 goto done;
414 }
415
416 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
417 if (err) {
418 WL_ERR("WLC_SET_INFRA error (%d)\n", err);
419 err = -EAGAIN;
420 } else {
421 wdev = ndev->ieee80211_ptr;
422 wdev->iftype = type;
423 }
424
425 WL_INFO("IF Type = %s\n",
426 (cfg_priv->conf->mode == WL_MODE_IBSS) ? "Adhoc" : "Infra");
427
428done:
429 WL_TRACE("Exit\n");
430
431 return err;
432}
433
434static s32 brcmf_dev_intvar_set(struct net_device *ndev, s8 *name, s32 val)
435{
436 s8 buf[BRCMF_DCMD_SMLEN];
437 u32 len;
438 s32 err = 0;
439 __le32 val_le;
440
441 val_le = cpu_to_le32(val);
53a2277d 442 len = brcmf_c_mkiovar(name, (char *)(&val_le), sizeof(val_le), buf,
5b435de0
AS
443 sizeof(buf));
444 BUG_ON(!len);
445
446 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len);
447 if (err)
448 WL_ERR("error (%d)\n", err);
449
450 return err;
451}
452
453static s32
454brcmf_dev_intvar_get(struct net_device *ndev, s8 *name, s32 *retval)
455{
456 union {
457 s8 buf[BRCMF_DCMD_SMLEN];
458 __le32 val;
459 } var;
460 u32 len;
461 u32 data_null;
462 s32 err = 0;
463
464 len =
53a2277d 465 brcmf_c_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
5b435de0
AS
466 sizeof(var.buf));
467 BUG_ON(!len);
468 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, &var, len);
469 if (err)
470 WL_ERR("error (%d)\n", err);
471
472 *retval = le32_to_cpu(var.val);
473
474 return err;
475}
476
477static void brcmf_set_mpc(struct net_device *ndev, int mpc)
478{
479 s32 err = 0;
480 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
481
482 if (test_bit(WL_STATUS_READY, &cfg_priv->status)) {
483 err = brcmf_dev_intvar_set(ndev, "mpc", mpc);
484 if (err) {
485 WL_ERR("fail to set mpc\n");
486 return;
487 }
488 WL_INFO("MPC : %d\n", mpc);
489 }
490}
491
492static void wl_iscan_prep(struct brcmf_scan_params_le *params_le,
493 struct brcmf_ssid *ssid)
494{
495 memcpy(params_le->bssid, ether_bcast, ETH_ALEN);
496 params_le->bss_type = DOT11_BSSTYPE_ANY;
497 params_le->scan_type = 0;
498 params_le->channel_num = 0;
499 params_le->nprobes = cpu_to_le32(-1);
500 params_le->active_time = cpu_to_le32(-1);
501 params_le->passive_time = cpu_to_le32(-1);
502 params_le->home_time = cpu_to_le32(-1);
503 if (ssid && ssid->SSID_len)
504 memcpy(&params_le->ssid_le, ssid, sizeof(struct brcmf_ssid));
505}
506
507static s32
508brcmf_dev_iovar_setbuf(struct net_device *ndev, s8 * iovar, void *param,
509 s32 paramlen, void *bufptr, s32 buflen)
510{
511 s32 iolen;
512
53a2277d 513 iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
5b435de0
AS
514 BUG_ON(!iolen);
515
516 return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, bufptr, iolen);
517}
518
519static s32
520brcmf_dev_iovar_getbuf(struct net_device *ndev, s8 * iovar, void *param,
521 s32 paramlen, void *bufptr, s32 buflen)
522{
523 s32 iolen;
524
53a2277d 525 iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
5b435de0
AS
526 BUG_ON(!iolen);
527
528 return brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, bufptr, buflen);
529}
530
531static s32
532brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan,
533 struct brcmf_ssid *ssid, u16 action)
534{
535 s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
536 offsetof(struct brcmf_iscan_params_le, params_le);
537 struct brcmf_iscan_params_le *params;
538 s32 err = 0;
539
540 if (ssid && ssid->SSID_len)
541 params_size += sizeof(struct brcmf_ssid);
542 params = kzalloc(params_size, GFP_KERNEL);
543 if (!params)
544 return -ENOMEM;
545 BUG_ON(params_size >= BRCMF_DCMD_SMLEN);
546
547 wl_iscan_prep(&params->params_le, ssid);
548
549 params->version = cpu_to_le32(BRCMF_ISCAN_REQ_VERSION);
550 params->action = cpu_to_le16(action);
551 params->scan_duration = cpu_to_le16(0);
552
553 err = brcmf_dev_iovar_setbuf(iscan->ndev, "iscan", params, params_size,
554 iscan->dcmd_buf, BRCMF_DCMD_SMLEN);
555 if (err) {
556 if (err == -EBUSY)
557 WL_INFO("system busy : iscan canceled\n");
558 else
559 WL_ERR("error (%d)\n", err);
560 }
561
562 kfree(params);
563 return err;
564}
565
566static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv)
567{
568 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
569 struct net_device *ndev = cfg_to_ndev(cfg_priv);
570 struct brcmf_ssid ssid;
66831075 571 __le32 passive_scan;
5b435de0
AS
572 s32 err = 0;
573
574 /* Broadcast scan by default */
575 memset(&ssid, 0, sizeof(ssid));
576
577 iscan->state = WL_ISCAN_STATE_SCANING;
578
66831075 579 passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
5b435de0
AS
580 err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_SET_PASSIVE_SCAN,
581 &passive_scan, sizeof(passive_scan));
582 if (err) {
583 WL_ERR("error (%d)\n", err);
584 return err;
585 }
586 brcmf_set_mpc(ndev, 0);
587 cfg_priv->iscan_kickstart = true;
588 err = brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START);
589 if (err) {
590 brcmf_set_mpc(ndev, 1);
591 cfg_priv->iscan_kickstart = false;
592 return err;
593 }
594 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
595 iscan->timer_on = 1;
596 return err;
597}
598
599static s32
600__brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
601 struct cfg80211_scan_request *request,
602 struct cfg80211_ssid *this_ssid)
603{
604 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
605 struct cfg80211_ssid *ssids;
606 struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int;
66831075 607 __le32 passive_scan;
5b435de0
AS
608 bool iscan_req;
609 bool spec_scan;
610 s32 err = 0;
611 u32 SSID_len;
612
613 if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
614 WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status);
615 return -EAGAIN;
616 }
617 if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status)) {
618 WL_ERR("Scanning being aborted : status (%lu)\n",
619 cfg_priv->status);
620 return -EAGAIN;
621 }
622 if (test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
623 WL_ERR("Connecting : status (%lu)\n",
624 cfg_priv->status);
625 return -EAGAIN;
626 }
627
628 iscan_req = false;
629 spec_scan = false;
630 if (request) {
631 /* scan bss */
632 ssids = request->ssids;
633 if (cfg_priv->iscan_on && (!ssids || !ssids->ssid_len))
634 iscan_req = true;
635 } else {
636 /* scan in ibss */
637 /* we don't do iscan in ibss */
638 ssids = this_ssid;
639 }
640
641 cfg_priv->scan_request = request;
642 set_bit(WL_STATUS_SCANNING, &cfg_priv->status);
643 if (iscan_req) {
644 err = brcmf_do_iscan(cfg_priv);
645 if (!err)
646 return err;
647 else
648 goto scan_out;
649 } else {
650 WL_SCAN("ssid \"%s\", ssid_len (%d)\n",
651 ssids->ssid, ssids->ssid_len);
652 memset(&sr->ssid_le, 0, sizeof(sr->ssid_le));
653 SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len);
654 sr->ssid_le.SSID_len = cpu_to_le32(0);
655 if (SSID_len) {
656 memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len);
657 sr->ssid_le.SSID_len = cpu_to_le32(SSID_len);
658 spec_scan = true;
659 } else {
660 WL_SCAN("Broadcast scan\n");
661 }
662
66831075 663 passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
5b435de0
AS
664 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
665 &passive_scan, sizeof(passive_scan));
666 if (err) {
667 WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
668 goto scan_out;
669 }
670 brcmf_set_mpc(ndev, 0);
671 err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le,
672 sizeof(sr->ssid_le));
673 if (err) {
674 if (err == -EBUSY)
675 WL_INFO("system busy : scan for \"%s\" "
676 "canceled\n", sr->ssid_le.SSID);
677 else
678 WL_ERR("WLC_SCAN error (%d)\n", err);
679
680 brcmf_set_mpc(ndev, 1);
681 goto scan_out;
682 }
683 }
684
685 return 0;
686
687scan_out:
688 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
689 cfg_priv->scan_request = NULL;
690 return err;
691}
692
693static s32
694brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
695 struct cfg80211_scan_request *request)
696{
697 s32 err = 0;
698
699 WL_TRACE("Enter\n");
700
701 if (!check_sys_up(wiphy))
702 return -EIO;
703
704 err = __brcmf_cfg80211_scan(wiphy, ndev, request, NULL);
705 if (err)
706 WL_ERR("scan error (%d)\n", err);
707
708 WL_TRACE("Exit\n");
709 return err;
710}
711
712static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold)
713{
714 s32 err = 0;
715
716 err = brcmf_dev_intvar_set(ndev, "rtsthresh", rts_threshold);
717 if (err)
718 WL_ERR("Error (%d)\n", err);
719
720 return err;
721}
722
723static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold)
724{
725 s32 err = 0;
726
727 err = brcmf_dev_intvar_set(ndev, "fragthresh", frag_threshold);
728 if (err)
729 WL_ERR("Error (%d)\n", err);
730
731 return err;
732}
733
734static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l)
735{
736 s32 err = 0;
737 u32 cmd = (l ? BRCM_SET_LRL : BRCM_SET_SRL);
738
739 err = brcmf_exec_dcmd_u32(ndev, cmd, &retry);
740 if (err) {
741 WL_ERR("cmd (%d) , error (%d)\n", cmd, err);
742 return err;
743 }
744 return err;
745}
746
747static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
748{
749 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
750 struct net_device *ndev = cfg_to_ndev(cfg_priv);
751 s32 err = 0;
752
753 WL_TRACE("Enter\n");
754 if (!check_sys_up(wiphy))
755 return -EIO;
756
757 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
758 (cfg_priv->conf->rts_threshold != wiphy->rts_threshold)) {
759 cfg_priv->conf->rts_threshold = wiphy->rts_threshold;
760 err = brcmf_set_rts(ndev, cfg_priv->conf->rts_threshold);
761 if (!err)
762 goto done;
763 }
764 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
765 (cfg_priv->conf->frag_threshold != wiphy->frag_threshold)) {
766 cfg_priv->conf->frag_threshold = wiphy->frag_threshold;
767 err = brcmf_set_frag(ndev, cfg_priv->conf->frag_threshold);
768 if (!err)
769 goto done;
770 }
771 if (changed & WIPHY_PARAM_RETRY_LONG
772 && (cfg_priv->conf->retry_long != wiphy->retry_long)) {
773 cfg_priv->conf->retry_long = wiphy->retry_long;
774 err = brcmf_set_retry(ndev, cfg_priv->conf->retry_long, true);
775 if (!err)
776 goto done;
777 }
778 if (changed & WIPHY_PARAM_RETRY_SHORT
779 && (cfg_priv->conf->retry_short != wiphy->retry_short)) {
780 cfg_priv->conf->retry_short = wiphy->retry_short;
781 err = brcmf_set_retry(ndev, cfg_priv->conf->retry_short, false);
782 if (!err)
783 goto done;
784 }
785
786done:
787 WL_TRACE("Exit\n");
788 return err;
789}
790
791static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item)
792{
793 switch (item) {
794 case WL_PROF_SEC:
795 return &cfg_priv->profile->sec;
796 case WL_PROF_BSSID:
797 return &cfg_priv->profile->bssid;
798 case WL_PROF_SSID:
799 return &cfg_priv->profile->ssid;
800 }
801 WL_ERR("invalid item (%d)\n", item);
802 return NULL;
803}
804
805static s32
806brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv,
807 const struct brcmf_event_msg *e, void *data, s32 item)
808{
809 s32 err = 0;
810 struct brcmf_ssid *ssid;
811
812 switch (item) {
813 case WL_PROF_SSID:
814 ssid = (struct brcmf_ssid *) data;
815 memset(cfg_priv->profile->ssid.SSID, 0,
816 sizeof(cfg_priv->profile->ssid.SSID));
817 memcpy(cfg_priv->profile->ssid.SSID,
818 ssid->SSID, ssid->SSID_len);
819 cfg_priv->profile->ssid.SSID_len = ssid->SSID_len;
820 break;
821 case WL_PROF_BSSID:
822 if (data)
823 memcpy(cfg_priv->profile->bssid, data, ETH_ALEN);
824 else
825 memset(cfg_priv->profile->bssid, 0, ETH_ALEN);
826 break;
827 case WL_PROF_SEC:
828 memcpy(&cfg_priv->profile->sec, data,
829 sizeof(cfg_priv->profile->sec));
830 break;
831 case WL_PROF_BEACONINT:
832 cfg_priv->profile->beacon_interval = *(u16 *)data;
833 break;
834 case WL_PROF_DTIMPERIOD:
835 cfg_priv->profile->dtim_period = *(u8 *)data;
836 break;
837 default:
838 WL_ERR("unsupported item (%d)\n", item);
839 err = -EOPNOTSUPP;
840 break;
841 }
842
843 return err;
844}
845
846static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
847{
848 memset(prof, 0, sizeof(*prof));
849}
850
851static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params,
852 size_t *join_params_size)
853{
854 u16 chanspec = 0;
855
856 if (ch != 0) {
857 if (ch <= CH_MAX_2G_CHANNEL)
858 chanspec |= WL_CHANSPEC_BAND_2G;
859 else
860 chanspec |= WL_CHANSPEC_BAND_5G;
861
862 chanspec |= WL_CHANSPEC_BW_20;
863 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
864
865 *join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE +
866 sizeof(u16);
867
868 chanspec |= (ch & WL_CHANSPEC_CHAN_MASK);
869 join_params->params_le.chanspec_list[0] = cpu_to_le16(chanspec);
870 join_params->params_le.chanspec_num = cpu_to_le32(1);
871
872 WL_CONN("join_params->params.chanspec_list[0]= %#X,"
873 "channel %d, chanspec %#X\n",
874 chanspec, ch, chanspec);
875 }
876}
877
878static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv)
879{
880 struct net_device *ndev = NULL;
881 s32 err = 0;
882
883 WL_TRACE("Enter\n");
884
885 if (cfg_priv->link_up) {
886 ndev = cfg_to_ndev(cfg_priv);
887 WL_INFO("Call WLC_DISASSOC to stop excess roaming\n ");
888 err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, NULL, 0);
889 if (err)
890 WL_ERR("WLC_DISASSOC failed (%d)\n", err);
891 cfg_priv->link_up = false;
892 }
893 WL_TRACE("Exit\n");
894}
895
896static s32
897brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
898 struct cfg80211_ibss_params *params)
899{
900 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
901 struct brcmf_join_params join_params;
902 size_t join_params_size = 0;
903 s32 err = 0;
904 s32 wsec = 0;
905 s32 bcnprd;
906 struct brcmf_ssid ssid;
907
908 WL_TRACE("Enter\n");
909 if (!check_sys_up(wiphy))
910 return -EIO;
911
912 if (params->ssid)
913 WL_CONN("SSID: %s\n", params->ssid);
914 else {
915 WL_CONN("SSID: NULL, Not supported\n");
916 return -EOPNOTSUPP;
917 }
918
919 set_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
920
921 if (params->bssid)
922 WL_CONN("BSSID: %02X %02X %02X %02X %02X %02X\n",
923 params->bssid[0], params->bssid[1], params->bssid[2],
924 params->bssid[3], params->bssid[4], params->bssid[5]);
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
1379 ssid.SSID_len = min_t(u32, sizeof(ssid.SSID), sme->ssid_len);
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)) {
1880 scb_val.val = cpu_to_le32(0);
1881 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val,
1882 sizeof(struct brcmf_scb_val_le));
1883 if (err)
1884 WL_ERR("Could not get rssi (%d)\n", err);
1885
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 }
1891
1892done:
1893 WL_TRACE("Exit\n");
1894 return err;
1895}
1896
1897static s32
1898brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
1899 bool enabled, s32 timeout)
1900{
1901 s32 pm;
1902 s32 err = 0;
1903 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1904
1905 WL_TRACE("Enter\n");
1906
1907 /*
1908 * Powersave enable/disable request is coming from the
1909 * cfg80211 even before the interface is up. In that
1910 * scenario, driver will be storing the power save
1911 * preference in cfg_priv struct to apply this to
1912 * FW later while initializing the dongle
1913 */
1914 cfg_priv->pwr_save = enabled;
1915 if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) {
1916
1917 WL_INFO("Device is not ready,"
1918 "storing the value in cfg_priv struct\n");
1919 goto done;
1920 }
1921
1922 pm = enabled ? PM_FAST : PM_OFF;
1923 WL_INFO("power save %s\n", (pm ? "enabled" : "disabled"));
1924
1925 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &pm);
1926 if (err) {
1927 if (err == -ENODEV)
1928 WL_ERR("net_device is not ready yet\n");
1929 else
1930 WL_ERR("error (%d)\n", err);
1931 }
1932done:
1933 WL_TRACE("Exit\n");
1934 return err;
1935}
1936
1937static s32
1938brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev,
1939 const u8 *addr,
1940 const struct cfg80211_bitrate_mask *mask)
1941{
1942 struct brcm_rateset_le rateset_le;
1943 s32 rate;
1944 s32 val;
1945 s32 err_bg;
1946 s32 err_a;
1947 u32 legacy;
1948 s32 err = 0;
1949
1950 WL_TRACE("Enter\n");
1951 if (!check_sys_up(wiphy))
1952 return -EIO;
1953
1954 /* addr param is always NULL. ignore it */
1955 /* Get current rateset */
1956 err = brcmf_exec_dcmd(ndev, BRCM_GET_CURR_RATESET, &rateset_le,
1957 sizeof(rateset_le));
1958 if (err) {
1959 WL_ERR("could not get current rateset (%d)\n", err);
1960 goto done;
1961 }
1962
1963 legacy = ffs(mask->control[IEEE80211_BAND_2GHZ].legacy & 0xFFFF);
1964 if (!legacy)
1965 legacy = ffs(mask->control[IEEE80211_BAND_5GHZ].legacy &
1966 0xFFFF);
1967
1968 val = wl_g_rates[legacy - 1].bitrate * 100000;
1969
1970 if (val < le32_to_cpu(rateset_le.count))
1971 /* Select rate by rateset index */
1972 rate = rateset_le.rates[val] & 0x7f;
1973 else
1974 /* Specified rate in bps */
1975 rate = val / 500000;
1976
1977 WL_CONN("rate %d mbps\n", rate / 2);
1978
1979 /*
1980 *
1981 * Set rate override,
1982 * Since the is a/b/g-blind, both a/bg_rate are enforced.
1983 */
1984 err_bg = brcmf_dev_intvar_set(ndev, "bg_rate", rate);
1985 err_a = brcmf_dev_intvar_set(ndev, "a_rate", rate);
1986 if (err_bg && err_a) {
1987 WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a);
1988 err = err_bg | err_a;
1989 }
1990
1991done:
1992 WL_TRACE("Exit\n");
1993 return err;
1994}
1995
1996static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
d34bf64f 1997 struct brcmf_bss_info_le *bi)
5b435de0
AS
1998{
1999 struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
2000 struct ieee80211_channel *notify_channel;
2001 struct cfg80211_bss *bss;
2002 struct ieee80211_supported_band *band;
2003 s32 err = 0;
2004 u16 channel;
2005 u32 freq;
2006 u64 notify_timestamp;
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
2029 notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
2030 notify_capability = le16_to_cpu(bi->capability);
2031 notify_interval = le16_to_cpu(bi->beacon_period);
2032 notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
2033 notify_ielen = le32_to_cpu(bi->ie_length);
2034 notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
2035
2036 WL_CONN("bssid: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
2037 bi->BSSID[0], bi->BSSID[1], bi->BSSID[2],
2038 bi->BSSID[3], bi->BSSID[4], bi->BSSID[5]);
2039 WL_CONN("Channel: %d(%d)\n", channel, freq);
2040 WL_CONN("Capability: %X\n", notify_capability);
2041 WL_CONN("Beacon interval: %d\n", notify_interval);
2042 WL_CONN("Signal: %d\n", notify_signal);
2043 WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
2044
2045 bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID,
2046 notify_timestamp, notify_capability, notify_interval, notify_ie,
2047 notify_ielen, notify_signal, GFP_KERNEL);
2048
e78946e1
FL
2049 if (!bss)
2050 return -ENOMEM;
2051
2052 cfg80211_put_bss(bss);
5b435de0
AS
2053
2054 return err;
2055}
2056
6f09be0a
RV
2057static struct brcmf_bss_info_le *
2058next_bss_le(struct brcmf_scan_results *list, struct brcmf_bss_info_le *bss)
2059{
2060 if (bss == NULL)
2061 return list->bss_info_le;
2062 return (struct brcmf_bss_info_le *)((unsigned long)bss +
2063 le32_to_cpu(bss->length));
2064}
2065
5b435de0
AS
2066static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv)
2067{
2068 struct brcmf_scan_results *bss_list;
d34bf64f 2069 struct brcmf_bss_info_le *bi = NULL; /* must be initialized */
5b435de0
AS
2070 s32 err = 0;
2071 int i;
2072
2073 bss_list = cfg_priv->bss_list;
2074 if (bss_list->version != BRCMF_BSS_INFO_VERSION) {
2075 WL_ERR("Version %d != WL_BSS_INFO_VERSION\n",
2076 bss_list->version);
2077 return -EOPNOTSUPP;
2078 }
2079 WL_SCAN("scanned AP count (%d)\n", bss_list->count);
2080 for (i = 0; i < bss_list->count && i < WL_AP_MAX; i++) {
6f09be0a 2081 bi = next_bss_le(bss_list, bi);
5b435de0
AS
2082 err = brcmf_inform_single_bss(cfg_priv, bi);
2083 if (err)
2084 break;
2085 }
2086 return err;
2087}
2088
2089static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
2090 struct net_device *ndev, const u8 *bssid)
2091{
2092 struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
2093 struct ieee80211_channel *notify_channel;
d34bf64f 2094 struct brcmf_bss_info_le *bi = NULL;
5b435de0 2095 struct ieee80211_supported_band *band;
e78946e1 2096 struct cfg80211_bss *bss;
5b435de0
AS
2097 u8 *buf = NULL;
2098 s32 err = 0;
2099 u16 channel;
2100 u32 freq;
2101 u64 notify_timestamp;
2102 u16 notify_capability;
2103 u16 notify_interval;
2104 u8 *notify_ie;
2105 size_t notify_ielen;
2106 s32 notify_signal;
2107
2108 WL_TRACE("Enter\n");
2109
2110 buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
2111 if (buf == NULL) {
2112 err = -ENOMEM;
2113 goto CleanUp;
2114 }
2115
2116 *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
2117
2118 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
2119 if (err) {
2120 WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err);
2121 goto CleanUp;
2122 }
2123
d34bf64f 2124 bi = (struct brcmf_bss_info_le *)(buf + 4);
5b435de0
AS
2125
2126 channel = bi->ctl_ch ? bi->ctl_ch :
2127 CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
2128
2129 if (channel <= CH_MAX_2G_CHANNEL)
2130 band = wiphy->bands[IEEE80211_BAND_2GHZ];
2131 else
2132 band = wiphy->bands[IEEE80211_BAND_5GHZ];
2133
2134 freq = ieee80211_channel_to_frequency(channel, band->band);
2135 notify_channel = ieee80211_get_channel(wiphy, freq);
2136
2137 notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
2138 notify_capability = le16_to_cpu(bi->capability);
2139 notify_interval = le16_to_cpu(bi->beacon_period);
2140 notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
2141 notify_ielen = le32_to_cpu(bi->ie_length);
2142 notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
2143
2144 WL_CONN("channel: %d(%d)\n", channel, freq);
2145 WL_CONN("capability: %X\n", notify_capability);
2146 WL_CONN("beacon interval: %d\n", notify_interval);
2147 WL_CONN("signal: %d\n", notify_signal);
2148 WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
2149
e78946e1 2150 bss = cfg80211_inform_bss(wiphy, notify_channel, bssid,
5b435de0
AS
2151 notify_timestamp, notify_capability, notify_interval,
2152 notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
2153
e78946e1
FL
2154 if (!bss) {
2155 err = -ENOMEM;
2156 goto CleanUp;
2157 }
2158
2159 cfg80211_put_bss(bss);
2160
5b435de0
AS
2161CleanUp:
2162
2163 kfree(buf);
2164
2165 WL_TRACE("Exit\n");
2166
2167 return err;
2168}
2169
2170static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv)
2171{
2172 return cfg_priv->conf->mode == WL_MODE_IBSS;
2173}
2174
f8e4b412
AB
2175/*
2176 * Traverse a string of 1-byte tag/1-byte length/variable-length value
2177 * triples, returning a pointer to the substring whose first element
2178 * matches tag
2179 */
2180static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key)
2181{
2182 struct brcmf_tlv *elt;
2183 int totlen;
2184
2185 elt = (struct brcmf_tlv *) buf;
2186 totlen = buflen;
2187
2188 /* find tagged parameter */
2189 while (totlen >= 2) {
2190 int len = elt->len;
2191
2192 /* validate remaining totlen */
2193 if ((elt->id == key) && (totlen >= (len + 2)))
2194 return elt;
2195
2196 elt = (struct brcmf_tlv *) ((u8 *) elt + (len + 2));
2197 totlen -= (len + 2);
2198 }
2199
2200 return NULL;
2201}
2202
5b435de0
AS
2203static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv)
2204{
d34bf64f 2205 struct brcmf_bss_info_le *bi;
5b435de0 2206 struct brcmf_ssid *ssid;
f8e4b412 2207 struct brcmf_tlv *tim;
5b435de0
AS
2208 u16 beacon_interval;
2209 u8 dtim_period;
2210 size_t ie_len;
2211 u8 *ie;
2212 s32 err = 0;
2213
2214 WL_TRACE("Enter\n");
2215 if (brcmf_is_ibssmode(cfg_priv))
2216 return err;
2217
2218 ssid = (struct brcmf_ssid *)brcmf_read_prof(cfg_priv, WL_PROF_SSID);
2219
2220 *(__le32 *)cfg_priv->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
2221 err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_GET_BSS_INFO,
2222 cfg_priv->extra_buf, WL_EXTRA_BUF_MAX);
2223 if (err) {
2224 WL_ERR("Could not get bss info %d\n", err);
2225 goto update_bss_info_out;
2226 }
2227
d34bf64f 2228 bi = (struct brcmf_bss_info_le *)(cfg_priv->extra_buf + 4);
5b435de0
AS
2229 err = brcmf_inform_single_bss(cfg_priv, bi);
2230 if (err)
2231 goto update_bss_info_out;
2232
2233 ie = ((u8 *)bi) + le16_to_cpu(bi->ie_offset);
2234 ie_len = le32_to_cpu(bi->ie_length);
2235 beacon_interval = le16_to_cpu(bi->beacon_period);
2236
f8e4b412 2237 tim = brcmf_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
5b435de0
AS
2238 if (tim)
2239 dtim_period = tim->data[1];
2240 else {
2241 /*
2242 * active scan was done so we could not get dtim
2243 * information out of probe response.
2244 * so we speficially query dtim information to dongle.
2245 */
2246 u32 var;
2247 err = brcmf_dev_intvar_get(cfg_to_ndev(cfg_priv),
2248 "dtim_assoc", &var);
2249 if (err) {
2250 WL_ERR("wl dtim_assoc failed (%d)\n", err);
2251 goto update_bss_info_out;
2252 }
2253 dtim_period = (u8)var;
2254 }
2255
2256 brcmf_update_prof(cfg_priv, NULL, &beacon_interval, WL_PROF_BEACONINT);
2257 brcmf_update_prof(cfg_priv, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
2258
2259update_bss_info_out:
2260 WL_TRACE("Exit");
2261 return err;
2262}
2263
2264static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv)
2265{
2266 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
2267 struct brcmf_ssid ssid;
2268
2269 if (cfg_priv->iscan_on) {
2270 iscan->state = WL_ISCAN_STATE_IDLE;
2271
2272 if (iscan->timer_on) {
2273 del_timer_sync(&iscan->timer);
2274 iscan->timer_on = 0;
2275 }
2276
2277 cancel_work_sync(&iscan->work);
2278
2279 /* Abort iscan running in FW */
2280 memset(&ssid, 0, sizeof(ssid));
2281 brcmf_run_iscan(iscan, &ssid, WL_SCAN_ACTION_ABORT);
2282 }
2283}
2284
2285static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
2286 bool aborted)
2287{
2288 struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
2289 struct net_device *ndev = cfg_to_ndev(cfg_priv);
2290
2291 if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
2292 WL_ERR("Scan complete while device not scanning\n");
2293 return;
2294 }
2295 if (cfg_priv->scan_request) {
2296 WL_SCAN("ISCAN Completed scan: %s\n",
2297 aborted ? "Aborted" : "Done");
2298 cfg80211_scan_done(cfg_priv->scan_request, aborted);
2299 brcmf_set_mpc(ndev, 1);
2300 cfg_priv->scan_request = NULL;
2301 }
2302 cfg_priv->iscan_kickstart = false;
2303}
2304
2305static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan)
2306{
2307 if (iscan->state != WL_ISCAN_STATE_IDLE) {
2308 WL_SCAN("wake up iscan\n");
2309 schedule_work(&iscan->work);
2310 return 0;
2311 }
2312
2313 return -EIO;
2314}
2315
2316static s32
2317brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status,
2318 struct brcmf_scan_results **bss_list)
2319{
2320 struct brcmf_iscan_results list;
2321 struct brcmf_scan_results *results;
2322 struct brcmf_scan_results_le *results_le;
2323 struct brcmf_iscan_results *list_buf;
2324 s32 err = 0;
2325
2326 memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
2327 list_buf = (struct brcmf_iscan_results *)iscan->scan_buf;
2328 results = &list_buf->results;
2329 results_le = &list_buf->results_le;
2330 results->buflen = BRCMF_ISCAN_RESULTS_FIXED_SIZE;
2331 results->version = 0;
2332 results->count = 0;
2333
2334 memset(&list, 0, sizeof(list));
2335 list.results_le.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX);
2336 err = brcmf_dev_iovar_getbuf(iscan->ndev, "iscanresults", &list,
2337 BRCMF_ISCAN_RESULTS_FIXED_SIZE,
2338 iscan->scan_buf, WL_ISCAN_BUF_MAX);
2339 if (err) {
2340 WL_ERR("error (%d)\n", err);
2341 return err;
2342 }
2343 results->buflen = le32_to_cpu(results_le->buflen);
2344 results->version = le32_to_cpu(results_le->version);
2345 results->count = le32_to_cpu(results_le->count);
2346 WL_SCAN("results->count = %d\n", results_le->count);
2347 WL_SCAN("results->buflen = %d\n", results_le->buflen);
2348 *status = le32_to_cpu(list_buf->status_le);
2349 WL_SCAN("status = %d\n", *status);
2350 *bss_list = results;
2351
2352 return err;
2353}
2354
2355static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv)
2356{
2357 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2358 s32 err = 0;
2359
2360 iscan->state = WL_ISCAN_STATE_IDLE;
2361 brcmf_inform_bss(cfg_priv);
2362 brcmf_notify_iscan_complete(iscan, false);
2363
2364 return err;
2365}
2366
2367static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv)
2368{
2369 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2370 s32 err = 0;
2371
2372 /* Reschedule the timer */
2373 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
2374 iscan->timer_on = 1;
2375
2376 return err;
2377}
2378
2379static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv)
2380{
2381 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2382 s32 err = 0;
2383
2384 brcmf_inform_bss(cfg_priv);
2385 brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE);
2386 /* Reschedule the timer */
2387 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
2388 iscan->timer_on = 1;
2389
2390 return err;
2391}
2392
2393static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv)
2394{
2395 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2396 s32 err = 0;
2397
2398 iscan->state = WL_ISCAN_STATE_IDLE;
2399 brcmf_notify_iscan_complete(iscan, true);
2400
2401 return err;
2402}
2403
2404static void brcmf_cfg80211_iscan_handler(struct work_struct *work)
2405{
2406 struct brcmf_cfg80211_iscan_ctrl *iscan =
2407 container_of(work, struct brcmf_cfg80211_iscan_ctrl,
2408 work);
2409 struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
2410 struct brcmf_cfg80211_iscan_eloop *el = &iscan->el;
2411 u32 status = BRCMF_SCAN_RESULTS_PARTIAL;
2412
2413 if (iscan->timer_on) {
2414 del_timer_sync(&iscan->timer);
2415 iscan->timer_on = 0;
2416 }
2417
2418 if (brcmf_get_iscan_results(iscan, &status, &cfg_priv->bss_list)) {
2419 status = BRCMF_SCAN_RESULTS_ABORTED;
2420 WL_ERR("Abort iscan\n");
2421 }
2422
2423 el->handler[status](cfg_priv);
2424}
2425
2426static void brcmf_iscan_timer(unsigned long data)
2427{
2428 struct brcmf_cfg80211_iscan_ctrl *iscan =
2429 (struct brcmf_cfg80211_iscan_ctrl *)data;
2430
2431 if (iscan) {
2432 iscan->timer_on = 0;
2433 WL_SCAN("timer expired\n");
2434 brcmf_wakeup_iscan(iscan);
2435 }
2436}
2437
2438static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv)
2439{
2440 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
2441
2442 if (cfg_priv->iscan_on) {
2443 iscan->state = WL_ISCAN_STATE_IDLE;
2444 INIT_WORK(&iscan->work, brcmf_cfg80211_iscan_handler);
2445 }
2446
2447 return 0;
2448}
2449
2450static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el)
2451{
2452 memset(el, 0, sizeof(*el));
2453 el->handler[BRCMF_SCAN_RESULTS_SUCCESS] = brcmf_iscan_done;
2454 el->handler[BRCMF_SCAN_RESULTS_PARTIAL] = brcmf_iscan_inprogress;
2455 el->handler[BRCMF_SCAN_RESULTS_PENDING] = brcmf_iscan_pending;
2456 el->handler[BRCMF_SCAN_RESULTS_ABORTED] = brcmf_iscan_aborted;
2457 el->handler[BRCMF_SCAN_RESULTS_NO_MEM] = brcmf_iscan_aborted;
2458}
2459
2460static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv)
2461{
2462 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
2463 int err = 0;
2464
2465 if (cfg_priv->iscan_on) {
2466 iscan->ndev = cfg_to_ndev(cfg_priv);
2467 brcmf_init_iscan_eloop(&iscan->el);
2468 iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
2469 init_timer(&iscan->timer);
2470 iscan->timer.data = (unsigned long) iscan;
2471 iscan->timer.function = brcmf_iscan_timer;
2472 err = brcmf_invoke_iscan(cfg_priv);
2473 if (!err)
2474 iscan->data = cfg_priv;
2475 }
2476
2477 return err;
2478}
2479
5addc0de 2480static __always_inline void brcmf_delay(u32 ms)
5b435de0
AS
2481{
2482 if (ms < 1000 / HZ) {
2483 cond_resched();
2484 mdelay(ms);
2485 } else {
2486 msleep(ms);
2487 }
2488}
2489
2490static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
2491{
2492 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2493
2494 /*
2495 * Check for WL_STATUS_READY before any function call which
2496 * could result is bus access. Don't block the resume for
2497 * any driver error conditions
2498 */
2499 WL_TRACE("Enter\n");
2500
2501 if (test_bit(WL_STATUS_READY, &cfg_priv->status))
2502 brcmf_invoke_iscan(wiphy_to_cfg(wiphy));
2503
2504 WL_TRACE("Exit\n");
2505 return 0;
2506}
2507
2508static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
2509 struct cfg80211_wowlan *wow)
2510{
2511 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2512 struct net_device *ndev = cfg_to_ndev(cfg_priv);
2513
2514 WL_TRACE("Enter\n");
2515
2516 /*
2517 * Check for WL_STATUS_READY before any function call which
2518 * could result is bus access. Don't block the suspend for
2519 * any driver error conditions
2520 */
2521
2522 /*
2523 * While going to suspend if associated with AP disassociate
2524 * from AP to save power while system is in suspended state
2525 */
2526 if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
2527 test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
2528 test_bit(WL_STATUS_READY, &cfg_priv->status)) {
2529 WL_INFO("Disassociating from AP"
2530 " while entering suspend state\n");
2531 brcmf_link_down(cfg_priv);
2532
2533 /*
2534 * Make sure WPA_Supplicant receives all the event
2535 * generated due to DISASSOC call to the fw to keep
2536 * the state fw and WPA_Supplicant state consistent
2537 */
2538 brcmf_delay(500);
2539 }
2540
2541 set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
2542 if (test_bit(WL_STATUS_READY, &cfg_priv->status))
2543 brcmf_term_iscan(cfg_priv);
2544
2545 if (cfg_priv->scan_request) {
2546 /* Indidate scan abort to cfg80211 layer */
2547 WL_INFO("Terminating scan in progress\n");
2548 cfg80211_scan_done(cfg_priv->scan_request, true);
2549 cfg_priv->scan_request = NULL;
2550 }
2551 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
2552 clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
2553
2554 /* Turn off watchdog timer */
2555 if (test_bit(WL_STATUS_READY, &cfg_priv->status)) {
2556 WL_INFO("Enable MPC\n");
2557 brcmf_set_mpc(ndev, 1);
2558 }
2559
2560 WL_TRACE("Exit\n");
2561
2562 return 0;
2563}
2564
2565static __used s32
2566brcmf_dev_bufvar_set(struct net_device *ndev, s8 *name, s8 *buf, s32 len)
2567{
2568 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
2569 u32 buflen;
2570
53a2277d 2571 buflen = brcmf_c_mkiovar(name, buf, len, cfg_priv->dcmd_buf,
5b435de0
AS
2572 WL_DCMD_LEN_MAX);
2573 BUG_ON(!buflen);
2574
2575 return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg_priv->dcmd_buf,
2576 buflen);
2577}
2578
2579static s32
2580brcmf_dev_bufvar_get(struct net_device *ndev, s8 *name, s8 *buf,
2581 s32 buf_len)
2582{
2583 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
2584 u32 len;
2585 s32 err = 0;
2586
53a2277d 2587 len = brcmf_c_mkiovar(name, NULL, 0, cfg_priv->dcmd_buf,
5b435de0
AS
2588 WL_DCMD_LEN_MAX);
2589 BUG_ON(!len);
2590 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg_priv->dcmd_buf,
2591 WL_DCMD_LEN_MAX);
2592 if (err) {
2593 WL_ERR("error (%d)\n", err);
2594 return err;
2595 }
2596 memcpy(buf, cfg_priv->dcmd_buf, buf_len);
2597
2598 return err;
2599}
2600
2601static __used s32
2602brcmf_update_pmklist(struct net_device *ndev,
2603 struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
2604{
2605 int i, j;
40c8e95a 2606 int pmkid_len;
5b435de0 2607
40c8e95a
AS
2608 pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid);
2609
2610 WL_CONN("No of elements %d\n", pmkid_len);
2611 for (i = 0; i < pmkid_len; i++) {
5b435de0
AS
2612 WL_CONN("PMKID[%d]: %pM =\n", i,
2613 &pmk_list->pmkids.pmkid[i].BSSID);
2614 for (j = 0; j < WLAN_PMKID_LEN; j++)
2615 WL_CONN("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]);
2616 }
2617
2618 if (!err)
2619 brcmf_dev_bufvar_set(ndev, "pmkid_info", (char *)pmk_list,
2620 sizeof(*pmk_list));
2621
2622 return err;
2623}
2624
2625static s32
2626brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
2627 struct cfg80211_pmksa *pmksa)
2628{
2629 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2630 struct pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids;
2631 s32 err = 0;
2632 int i;
40c8e95a 2633 int pmkid_len;
5b435de0
AS
2634
2635 WL_TRACE("Enter\n");
2636 if (!check_sys_up(wiphy))
2637 return -EIO;
2638
40c8e95a
AS
2639 pmkid_len = le32_to_cpu(pmkids->npmkid);
2640 for (i = 0; i < pmkid_len; i++)
5b435de0
AS
2641 if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN))
2642 break;
2643 if (i < WL_NUM_PMKIDS_MAX) {
2644 memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN);
2645 memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
40c8e95a
AS
2646 if (i == pmkid_len) {
2647 pmkid_len++;
2648 pmkids->npmkid = cpu_to_le32(pmkid_len);
2649 }
5b435de0
AS
2650 } else
2651 err = -EINVAL;
2652
2653 WL_CONN("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
40c8e95a 2654 pmkids->pmkid[pmkid_len].BSSID);
5b435de0 2655 for (i = 0; i < WLAN_PMKID_LEN; i++)
40c8e95a 2656 WL_CONN("%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]);
5b435de0
AS
2657
2658 err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
2659
2660 WL_TRACE("Exit\n");
2661 return err;
2662}
2663
2664static s32
2665brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
2666 struct cfg80211_pmksa *pmksa)
2667{
2668 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2669 struct pmkid_list pmkid;
2670 s32 err = 0;
40c8e95a 2671 int i, pmkid_len;
5b435de0
AS
2672
2673 WL_TRACE("Enter\n");
2674 if (!check_sys_up(wiphy))
2675 return -EIO;
2676
2677 memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
2678 memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2679
2680 WL_CONN("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
2681 &pmkid.pmkid[0].BSSID);
2682 for (i = 0; i < WLAN_PMKID_LEN; i++)
2683 WL_CONN("%02x\n", pmkid.pmkid[0].PMKID[i]);
2684
40c8e95a
AS
2685 pmkid_len = le32_to_cpu(cfg_priv->pmk_list->pmkids.npmkid);
2686 for (i = 0; i < pmkid_len; i++)
5b435de0
AS
2687 if (!memcmp
2688 (pmksa->bssid, &cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
2689 ETH_ALEN))
2690 break;
2691
40c8e95a
AS
2692 if ((pmkid_len > 0)
2693 && (i < pmkid_len)) {
5b435de0
AS
2694 memset(&cfg_priv->pmk_list->pmkids.pmkid[i], 0,
2695 sizeof(struct pmkid));
40c8e95a 2696 for (; i < (pmkid_len - 1); i++) {
5b435de0
AS
2697 memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
2698 &cfg_priv->pmk_list->pmkids.pmkid[i + 1].BSSID,
2699 ETH_ALEN);
2700 memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].PMKID,
2701 &cfg_priv->pmk_list->pmkids.pmkid[i + 1].PMKID,
2702 WLAN_PMKID_LEN);
2703 }
40c8e95a 2704 cfg_priv->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1);
5b435de0
AS
2705 } else
2706 err = -EINVAL;
2707
2708 err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
2709
2710 WL_TRACE("Exit\n");
2711 return err;
2712
2713}
2714
2715static s32
2716brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
2717{
2718 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2719 s32 err = 0;
2720
2721 WL_TRACE("Enter\n");
2722 if (!check_sys_up(wiphy))
2723 return -EIO;
2724
2725 memset(cfg_priv->pmk_list, 0, sizeof(*cfg_priv->pmk_list));
2726 err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
2727
2728 WL_TRACE("Exit\n");
2729 return err;
2730
2731}
2732
2733static struct cfg80211_ops wl_cfg80211_ops = {
2734 .change_virtual_intf = brcmf_cfg80211_change_iface,
2735 .scan = brcmf_cfg80211_scan,
2736 .set_wiphy_params = brcmf_cfg80211_set_wiphy_params,
2737 .join_ibss = brcmf_cfg80211_join_ibss,
2738 .leave_ibss = brcmf_cfg80211_leave_ibss,
2739 .get_station = brcmf_cfg80211_get_station,
2740 .set_tx_power = brcmf_cfg80211_set_tx_power,
2741 .get_tx_power = brcmf_cfg80211_get_tx_power,
2742 .add_key = brcmf_cfg80211_add_key,
2743 .del_key = brcmf_cfg80211_del_key,
2744 .get_key = brcmf_cfg80211_get_key,
2745 .set_default_key = brcmf_cfg80211_config_default_key,
2746 .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key,
2747 .set_power_mgmt = brcmf_cfg80211_set_power_mgmt,
2748 .set_bitrate_mask = brcmf_cfg80211_set_bitrate_mask,
2749 .connect = brcmf_cfg80211_connect,
2750 .disconnect = brcmf_cfg80211_disconnect,
2751 .suspend = brcmf_cfg80211_suspend,
2752 .resume = brcmf_cfg80211_resume,
2753 .set_pmksa = brcmf_cfg80211_set_pmksa,
2754 .del_pmksa = brcmf_cfg80211_del_pmksa,
2755 .flush_pmksa = brcmf_cfg80211_flush_pmksa
2756};
2757
2758static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
2759{
2760 s32 err = 0;
2761
2762 switch (mode) {
2763 case WL_MODE_BSS:
2764 return NL80211_IFTYPE_STATION;
2765 case WL_MODE_IBSS:
2766 return NL80211_IFTYPE_ADHOC;
2767 default:
2768 return NL80211_IFTYPE_UNSPECIFIED;
2769 }
2770
2771 return err;
2772}
2773
2774static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface,
2775 struct device *ndev)
2776{
2777 struct wireless_dev *wdev;
2778 s32 err = 0;
2779
2780 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
2781 if (!wdev)
2782 return ERR_PTR(-ENOMEM);
2783
2784 wdev->wiphy =
2785 wiphy_new(&wl_cfg80211_ops,
2786 sizeof(struct brcmf_cfg80211_priv) + sizeof_iface);
2787 if (!wdev->wiphy) {
2788 WL_ERR("Couldn not allocate wiphy device\n");
2789 err = -ENOMEM;
2790 goto wiphy_new_out;
2791 }
2792 set_wiphy_dev(wdev->wiphy, ndev);
2793 wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
2794 wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
2795 wdev->wiphy->interface_modes =
2796 BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
2797 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
2798 wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set
2799 * it as 11a by default.
2800 * This will be updated with
2801 * 11n phy tables in
2802 * "ifconfig up"
2803 * if phy has 11n capability
2804 */
2805 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
2806 wdev->wiphy->cipher_suites = __wl_cipher_suites;
2807 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
2808 wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power
2809 * save mode
2810 * by default
2811 */
2812 err = wiphy_register(wdev->wiphy);
2813 if (err < 0) {
2814 WL_ERR("Couldn not register wiphy device (%d)\n", err);
2815 goto wiphy_register_out;
2816 }
2817 return wdev;
2818
2819wiphy_register_out:
2820 wiphy_free(wdev->wiphy);
2821
2822wiphy_new_out:
2823 kfree(wdev);
2824
2825 return ERR_PTR(err);
2826}
2827
2828static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv)
2829{
2830 struct wireless_dev *wdev = cfg_priv->wdev;
2831
2832 if (!wdev) {
2833 WL_ERR("wdev is invalid\n");
2834 return;
2835 }
2836 wiphy_unregister(wdev->wiphy);
2837 wiphy_free(wdev->wiphy);
2838 kfree(wdev);
2839 cfg_priv->wdev = NULL;
2840}
2841
2842static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv,
2843 const struct brcmf_event_msg *e)
2844{
2845 u32 event = be32_to_cpu(e->event_type);
2846 u32 status = be32_to_cpu(e->status);
2847
2848 if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
2849 WL_CONN("Processing set ssid\n");
2850 cfg_priv->link_up = true;
2851 return true;
2852 }
2853
2854 return false;
2855}
2856
2857static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv,
2858 const struct brcmf_event_msg *e)
2859{
2860 u32 event = be32_to_cpu(e->event_type);
2861 u16 flags = be16_to_cpu(e->flags);
2862
2863 if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) {
2864 WL_CONN("Processing link down\n");
2865 return true;
2866 }
2867 return false;
2868}
2869
2870static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv,
2871 const struct brcmf_event_msg *e)
2872{
2873 u32 event = be32_to_cpu(e->event_type);
2874 u32 status = be32_to_cpu(e->status);
2875
2876 if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) {
2877 WL_CONN("Processing Link %s & no network found\n",
2878 be16_to_cpu(e->flags) & BRCMF_EVENT_MSG_LINK ?
2879 "up" : "down");
2880 return true;
2881 }
2882
2883 if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) {
2884 WL_CONN("Processing connecting & no network found\n");
2885 return true;
2886 }
2887
2888 return false;
2889}
2890
2891static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
2892{
2893 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2894
2895 kfree(conn_info->req_ie);
2896 conn_info->req_ie = NULL;
2897 conn_info->req_ie_len = 0;
2898 kfree(conn_info->resp_ie);
2899 conn_info->resp_ie = NULL;
2900 conn_info->resp_ie_len = 0;
2901}
2902
2903static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
2904{
2905 struct net_device *ndev = cfg_to_ndev(cfg_priv);
c4e382d2 2906 struct brcmf_cfg80211_assoc_ielen_le *assoc_info;
5b435de0
AS
2907 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2908 u32 req_len;
2909 u32 resp_len;
2910 s32 err = 0;
2911
2912 brcmf_clear_assoc_ies(cfg_priv);
2913
2914 err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg_priv->extra_buf,
2915 WL_ASSOC_INFO_MAX);
2916 if (err) {
2917 WL_ERR("could not get assoc info (%d)\n", err);
2918 return err;
2919 }
c4e382d2
AS
2920 assoc_info =
2921 (struct brcmf_cfg80211_assoc_ielen_le *)cfg_priv->extra_buf;
2922 req_len = le32_to_cpu(assoc_info->req_len);
2923 resp_len = le32_to_cpu(assoc_info->resp_len);
5b435de0
AS
2924 if (req_len) {
2925 err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies",
2926 cfg_priv->extra_buf,
2927 WL_ASSOC_INFO_MAX);
2928 if (err) {
2929 WL_ERR("could not get assoc req (%d)\n", err);
2930 return err;
2931 }
2932 conn_info->req_ie_len = req_len;
2933 conn_info->req_ie =
2934 kmemdup(cfg_priv->extra_buf, conn_info->req_ie_len,
2935 GFP_KERNEL);
2936 } else {
2937 conn_info->req_ie_len = 0;
2938 conn_info->req_ie = NULL;
2939 }
2940 if (resp_len) {
2941 err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies",
2942 cfg_priv->extra_buf,
2943 WL_ASSOC_INFO_MAX);
2944 if (err) {
2945 WL_ERR("could not get assoc resp (%d)\n", err);
2946 return err;
2947 }
2948 conn_info->resp_ie_len = resp_len;
2949 conn_info->resp_ie =
2950 kmemdup(cfg_priv->extra_buf, conn_info->resp_ie_len,
2951 GFP_KERNEL);
2952 } else {
2953 conn_info->resp_ie_len = 0;
2954 conn_info->resp_ie = NULL;
2955 }
2956 WL_CONN("req len (%d) resp len (%d)\n",
2957 conn_info->req_ie_len, conn_info->resp_ie_len);
2958
2959 return err;
2960}
2961
2962static s32
2963brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
2964 struct net_device *ndev,
2965 const struct brcmf_event_msg *e)
2966{
2967 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2968 struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
2969 struct brcmf_channel_info_le channel_le;
2970 struct ieee80211_channel *notify_channel;
2971 struct ieee80211_supported_band *band;
2972 u32 freq;
2973 s32 err = 0;
2974 u32 target_channel;
2975
2976 WL_TRACE("Enter\n");
2977
2978 brcmf_get_assoc_ies(cfg_priv);
2979 brcmf_update_prof(cfg_priv, NULL, &e->addr, WL_PROF_BSSID);
2980 brcmf_update_bss_info(cfg_priv);
2981
2982 brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le,
2983 sizeof(channel_le));
2984
2985 target_channel = le32_to_cpu(channel_le.target_channel);
2986 WL_CONN("Roamed to channel %d\n", target_channel);
2987
2988 if (target_channel <= CH_MAX_2G_CHANNEL)
2989 band = wiphy->bands[IEEE80211_BAND_2GHZ];
2990 else
2991 band = wiphy->bands[IEEE80211_BAND_5GHZ];
2992
2993 freq = ieee80211_channel_to_frequency(target_channel, band->band);
2994 notify_channel = ieee80211_get_channel(wiphy, freq);
2995
2996 cfg80211_roamed(ndev, notify_channel,
2997 (u8 *)brcmf_read_prof(cfg_priv, WL_PROF_BSSID),
2998 conn_info->req_ie, conn_info->req_ie_len,
2999 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
3000 WL_CONN("Report roaming result\n");
3001
3002 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
3003 WL_TRACE("Exit\n");
3004 return err;
3005}
3006
3007static s32
3008brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
3009 struct net_device *ndev, const struct brcmf_event_msg *e,
3010 bool completed)
3011{
3012 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
3013 s32 err = 0;
3014
3015 WL_TRACE("Enter\n");
3016
3017 if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
3018 if (completed) {
3019 brcmf_get_assoc_ies(cfg_priv);
3020 brcmf_update_prof(cfg_priv, NULL, &e->addr,
3021 WL_PROF_BSSID);
3022 brcmf_update_bss_info(cfg_priv);
3023 }
3024 cfg80211_connect_result(ndev,
3025 (u8 *)brcmf_read_prof(cfg_priv,
3026 WL_PROF_BSSID),
3027 conn_info->req_ie,
3028 conn_info->req_ie_len,
3029 conn_info->resp_ie,
3030 conn_info->resp_ie_len,
3031 completed ? WLAN_STATUS_SUCCESS :
3032 WLAN_STATUS_AUTH_TIMEOUT,
3033 GFP_KERNEL);
3034 if (completed)
3035 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
3036 WL_CONN("Report connect result - connection %s\n",
3037 completed ? "succeeded" : "failed");
3038 }
3039 WL_TRACE("Exit\n");
3040 return err;
3041}
3042
3043static s32
3044brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv,
3045 struct net_device *ndev,
3046 const struct brcmf_event_msg *e, void *data)
3047{
3048 s32 err = 0;
3049
3050 if (brcmf_is_linkup(cfg_priv, e)) {
3051 WL_CONN("Linkup\n");
3052 if (brcmf_is_ibssmode(cfg_priv)) {
3053 brcmf_update_prof(cfg_priv, NULL, (void *)e->addr,
3054 WL_PROF_BSSID);
3055 wl_inform_ibss(cfg_priv, ndev, e->addr);
3056 cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
3057 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
3058 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
3059 } else
3060 brcmf_bss_connect_done(cfg_priv, ndev, e, true);
3061 } else if (brcmf_is_linkdown(cfg_priv, e)) {
3062 WL_CONN("Linkdown\n");
3063 if (brcmf_is_ibssmode(cfg_priv)) {
3064 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
3065 if (test_and_clear_bit(WL_STATUS_CONNECTED,
3066 &cfg_priv->status))
3067 brcmf_link_down(cfg_priv);
3068 } else {
3069 brcmf_bss_connect_done(cfg_priv, ndev, e, false);
3070 if (test_and_clear_bit(WL_STATUS_CONNECTED,
3071 &cfg_priv->status)) {
3072 cfg80211_disconnected(ndev, 0, NULL, 0,
3073 GFP_KERNEL);
3074 brcmf_link_down(cfg_priv);
3075 }
3076 }
3077 brcmf_init_prof(cfg_priv->profile);
3078 } else if (brcmf_is_nonetwork(cfg_priv, e)) {
3079 if (brcmf_is_ibssmode(cfg_priv))
3080 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
3081 else
3082 brcmf_bss_connect_done(cfg_priv, ndev, e, false);
3083 }
3084
3085 return err;
3086}
3087
3088static s32
3089brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv,
3090 struct net_device *ndev,
3091 const struct brcmf_event_msg *e, void *data)
3092{
3093 s32 err = 0;
3094 u32 event = be32_to_cpu(e->event_type);
3095 u32 status = be32_to_cpu(e->status);
3096
3097 if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
3098 if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status))
3099 brcmf_bss_roaming_done(cfg_priv, ndev, e);
3100 else
3101 brcmf_bss_connect_done(cfg_priv, ndev, e, true);
3102 }
3103
3104 return err;
3105}
3106
3107static s32
3108brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
3109 struct net_device *ndev,
3110 const struct brcmf_event_msg *e, void *data)
3111{
3112 u16 flags = be16_to_cpu(e->flags);
3113 enum nl80211_key_type key_type;
3114
3115 if (flags & BRCMF_EVENT_MSG_GROUP)
3116 key_type = NL80211_KEYTYPE_GROUP;
3117 else
3118 key_type = NL80211_KEYTYPE_PAIRWISE;
3119
3120 cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
3121 NULL, GFP_KERNEL);
3122
3123 return 0;
3124}
3125
3126static s32
3127brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
3128 struct net_device *ndev,
3129 const struct brcmf_event_msg *e, void *data)
3130{
3131 struct brcmf_channel_info_le channel_inform_le;
3132 struct brcmf_scan_results_le *bss_list_le;
3133 u32 len = WL_SCAN_BUF_MAX;
3134 s32 err = 0;
3135 bool scan_abort = false;
3136 u32 scan_channel;
3137
3138 WL_TRACE("Enter\n");
3139
3140 if (cfg_priv->iscan_on && cfg_priv->iscan_kickstart) {
3141 WL_TRACE("Exit\n");
3142 return brcmf_wakeup_iscan(cfg_to_iscan(cfg_priv));
3143 }
3144
3145 if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
3146 WL_ERR("Scan complete while device not scanning\n");
3147 scan_abort = true;
3148 err = -EINVAL;
3149 goto scan_done_out;
3150 }
3151
3152 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_inform_le,
3153 sizeof(channel_inform_le));
3154 if (err) {
3155 WL_ERR("scan busy (%d)\n", err);
3156 scan_abort = true;
3157 goto scan_done_out;
3158 }
3159 scan_channel = le32_to_cpu(channel_inform_le.scan_channel);
3160 if (scan_channel)
3161 WL_CONN("channel_inform.scan_channel (%d)\n", scan_channel);
3162 cfg_priv->bss_list = cfg_priv->scan_results;
3163 bss_list_le = (struct brcmf_scan_results_le *) cfg_priv->bss_list;
3164
3165 memset(cfg_priv->scan_results, 0, len);
3166 bss_list_le->buflen = cpu_to_le32(len);
3167 err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS,
3168 cfg_priv->scan_results, len);
3169 if (err) {
3170 WL_ERR("%s Scan_results error (%d)\n", ndev->name, err);
3171 err = -EINVAL;
3172 scan_abort = true;
3173 goto scan_done_out;
3174 }
3175 cfg_priv->scan_results->buflen = le32_to_cpu(bss_list_le->buflen);
3176 cfg_priv->scan_results->version = le32_to_cpu(bss_list_le->version);
3177 cfg_priv->scan_results->count = le32_to_cpu(bss_list_le->count);
3178
3179 err = brcmf_inform_bss(cfg_priv);
3180 if (err) {
3181 scan_abort = true;
3182 goto scan_done_out;
3183 }
3184
3185scan_done_out:
3186 if (cfg_priv->scan_request) {
3187 WL_SCAN("calling cfg80211_scan_done\n");
3188 cfg80211_scan_done(cfg_priv->scan_request, scan_abort);
3189 brcmf_set_mpc(ndev, 1);
3190 cfg_priv->scan_request = NULL;
3191 }
3192
3193 WL_TRACE("Exit\n");
3194
3195 return err;
3196}
3197
3198static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
3199{
3200 conf->mode = (u32)-1;
3201 conf->frag_threshold = (u32)-1;
3202 conf->rts_threshold = (u32)-1;
3203 conf->retry_short = (u32)-1;
3204 conf->retry_long = (u32)-1;
3205 conf->tx_power = -1;
3206}
3207
3208static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el)
3209{
3210 memset(el, 0, sizeof(*el));
3211 el->handler[BRCMF_E_SCAN_COMPLETE] = brcmf_notify_scan_status;
3212 el->handler[BRCMF_E_LINK] = brcmf_notify_connect_status;
3213 el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status;
3214 el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status;
3215 el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status;
3216}
3217
3218static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
3219{
3220 kfree(cfg_priv->scan_results);
3221 cfg_priv->scan_results = NULL;
3222 kfree(cfg_priv->bss_info);
3223 cfg_priv->bss_info = NULL;
3224 kfree(cfg_priv->conf);
3225 cfg_priv->conf = NULL;
3226 kfree(cfg_priv->profile);
3227 cfg_priv->profile = NULL;
3228 kfree(cfg_priv->scan_req_int);
3229 cfg_priv->scan_req_int = NULL;
3230 kfree(cfg_priv->dcmd_buf);
3231 cfg_priv->dcmd_buf = NULL;
3232 kfree(cfg_priv->extra_buf);
3233 cfg_priv->extra_buf = NULL;
3234 kfree(cfg_priv->iscan);
3235 cfg_priv->iscan = NULL;
3236 kfree(cfg_priv->pmk_list);
3237 cfg_priv->pmk_list = NULL;
3238}
3239
3240static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
3241{
3242 cfg_priv->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
3243 if (!cfg_priv->scan_results)
3244 goto init_priv_mem_out;
3245 cfg_priv->conf = kzalloc(sizeof(*cfg_priv->conf), GFP_KERNEL);
3246 if (!cfg_priv->conf)
3247 goto init_priv_mem_out;
3248 cfg_priv->profile = kzalloc(sizeof(*cfg_priv->profile), GFP_KERNEL);
3249 if (!cfg_priv->profile)
3250 goto init_priv_mem_out;
3251 cfg_priv->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
3252 if (!cfg_priv->bss_info)
3253 goto init_priv_mem_out;
3254 cfg_priv->scan_req_int = kzalloc(sizeof(*cfg_priv->scan_req_int),
3255 GFP_KERNEL);
3256 if (!cfg_priv->scan_req_int)
3257 goto init_priv_mem_out;
3258 cfg_priv->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL);
3259 if (!cfg_priv->dcmd_buf)
3260 goto init_priv_mem_out;
3261 cfg_priv->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
3262 if (!cfg_priv->extra_buf)
3263 goto init_priv_mem_out;
3264 cfg_priv->iscan = kzalloc(sizeof(*cfg_priv->iscan), GFP_KERNEL);
3265 if (!cfg_priv->iscan)
3266 goto init_priv_mem_out;
3267 cfg_priv->pmk_list = kzalloc(sizeof(*cfg_priv->pmk_list), GFP_KERNEL);
3268 if (!cfg_priv->pmk_list)
3269 goto init_priv_mem_out;
3270
3271 return 0;
3272
3273init_priv_mem_out:
3274 brcmf_deinit_priv_mem(cfg_priv);
3275
3276 return -ENOMEM;
3277}
3278
3279/*
3280* retrieve first queued event from head
3281*/
3282
3283static struct brcmf_cfg80211_event_q *brcmf_deq_event(
3284 struct brcmf_cfg80211_priv *cfg_priv)
3285{
3286 struct brcmf_cfg80211_event_q *e = NULL;
3287
3288 spin_lock_irq(&cfg_priv->evt_q_lock);
3289 if (!list_empty(&cfg_priv->evt_q_list)) {
3290 e = list_first_entry(&cfg_priv->evt_q_list,
3291 struct brcmf_cfg80211_event_q, evt_q_list);
3292 list_del(&e->evt_q_list);
3293 }
3294 spin_unlock_irq(&cfg_priv->evt_q_lock);
3295
3296 return e;
3297}
3298
3299/*
3300** push event to tail of the queue
3301*/
3302
3303static s32
3304brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event,
3305 const struct brcmf_event_msg *msg)
3306{
3307 struct brcmf_cfg80211_event_q *e;
3308 s32 err = 0;
3309
3310 e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_KERNEL);
3311 if (!e)
3312 return -ENOMEM;
3313
3314 e->etype = event;
3315 memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
3316
3317 spin_lock_irq(&cfg_priv->evt_q_lock);
3318 list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list);
3319 spin_unlock_irq(&cfg_priv->evt_q_lock);
3320
3321 return err;
3322}
3323
3324static void brcmf_put_event(struct brcmf_cfg80211_event_q *e)
3325{
3326 kfree(e);
3327}
3328
3329static void brcmf_cfg80211_event_handler(struct work_struct *work)
3330{
3331 struct brcmf_cfg80211_priv *cfg_priv =
3332 container_of(work, struct brcmf_cfg80211_priv,
3333 event_work);
3334 struct brcmf_cfg80211_event_q *e;
3335
3336 e = brcmf_deq_event(cfg_priv);
3337 if (unlikely(!e)) {
3338 WL_ERR("event queue empty...\n");
3339 return;
3340 }
3341
3342 do {
3343 WL_INFO("event type (%d)\n", e->etype);
3344 if (cfg_priv->el.handler[e->etype])
3345 cfg_priv->el.handler[e->etype](cfg_priv,
3346 cfg_to_ndev(cfg_priv),
3347 &e->emsg, e->edata);
3348 else
3349 WL_INFO("Unknown Event (%d): ignoring\n", e->etype);
3350 brcmf_put_event(e);
3351 } while ((e = brcmf_deq_event(cfg_priv)));
3352
3353}
3354
3355static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv)
3356{
3357 spin_lock_init(&cfg_priv->evt_q_lock);
3358 INIT_LIST_HEAD(&cfg_priv->evt_q_list);
3359}
3360
3361static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv)
3362{
3363 struct brcmf_cfg80211_event_q *e;
3364
3365 spin_lock_irq(&cfg_priv->evt_q_lock);
3366 while (!list_empty(&cfg_priv->evt_q_list)) {
3367 e = list_first_entry(&cfg_priv->evt_q_list,
3368 struct brcmf_cfg80211_event_q, evt_q_list);
3369 list_del(&e->evt_q_list);
3370 kfree(e);
3371 }
3372 spin_unlock_irq(&cfg_priv->evt_q_lock);
3373}
3374
3375static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv)
3376{
3377 s32 err = 0;
3378
3379 cfg_priv->scan_request = NULL;
3380 cfg_priv->pwr_save = true;
3381 cfg_priv->iscan_on = true; /* iscan on & off switch.
3382 we enable iscan per default */
3383 cfg_priv->roam_on = true; /* roam on & off switch.
3384 we enable roam per default */
3385
3386 cfg_priv->iscan_kickstart = false;
3387 cfg_priv->active_scan = true; /* we do active scan for
3388 specific scan per default */
3389 cfg_priv->dongle_up = false; /* dongle is not up yet */
3390 brcmf_init_eq(cfg_priv);
3391 err = brcmf_init_priv_mem(cfg_priv);
3392 if (err)
3393 return err;
3394 INIT_WORK(&cfg_priv->event_work, brcmf_cfg80211_event_handler);
3395 brcmf_init_eloop_handler(&cfg_priv->el);
3396 mutex_init(&cfg_priv->usr_sync);
3397 err = brcmf_init_iscan(cfg_priv);
3398 if (err)
3399 return err;
3400 brcmf_init_conf(cfg_priv->conf);
3401 brcmf_init_prof(cfg_priv->profile);
3402 brcmf_link_down(cfg_priv);
3403
3404 return err;
3405}
3406
3407static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv)
3408{
3409 cancel_work_sync(&cfg_priv->event_work);
3410 cfg_priv->dongle_up = false; /* dongle down */
3411 brcmf_flush_eq(cfg_priv);
3412 brcmf_link_down(cfg_priv);
3413 brcmf_term_iscan(cfg_priv);
3414 brcmf_deinit_priv_mem(cfg_priv);
3415}
3416
3417struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev,
3418 struct device *busdev,
3419 void *data)
3420{
3421 struct wireless_dev *wdev;
3422 struct brcmf_cfg80211_priv *cfg_priv;
3423 struct brcmf_cfg80211_iface *ci;
3424 struct brcmf_cfg80211_dev *cfg_dev;
3425 s32 err = 0;
3426
3427 if (!ndev) {
3428 WL_ERR("ndev is invalid\n");
3429 return NULL;
3430 }
3431 cfg_dev = kzalloc(sizeof(struct brcmf_cfg80211_dev), GFP_KERNEL);
3432 if (!cfg_dev)
3433 return NULL;
3434
3435 wdev = brcmf_alloc_wdev(sizeof(struct brcmf_cfg80211_iface), busdev);
3436 if (IS_ERR(wdev)) {
3437 kfree(cfg_dev);
3438 return NULL;
3439 }
3440
3441 wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS);
3442 cfg_priv = wdev_to_cfg(wdev);
3443 cfg_priv->wdev = wdev;
3444 cfg_priv->pub = data;
3445 ci = (struct brcmf_cfg80211_iface *)&cfg_priv->ci;
3446 ci->cfg_priv = cfg_priv;
3447 ndev->ieee80211_ptr = wdev;
3448 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
3449 wdev->netdev = ndev;
3450 err = wl_init_priv(cfg_priv);
3451 if (err) {
3452 WL_ERR("Failed to init iwm_priv (%d)\n", err);
3453 goto cfg80211_attach_out;
3454 }
3455 brcmf_set_drvdata(cfg_dev, ci);
3456
3457 return cfg_dev;
3458
3459cfg80211_attach_out:
3460 brcmf_free_wdev(cfg_priv);
3461 kfree(cfg_dev);
3462 return NULL;
3463}
3464
3465void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg_dev)
3466{
3467 struct brcmf_cfg80211_priv *cfg_priv;
3468
3469 cfg_priv = brcmf_priv_get(cfg_dev);
3470
3471 wl_deinit_priv(cfg_priv);
3472 brcmf_free_wdev(cfg_priv);
3473 brcmf_set_drvdata(cfg_dev, NULL);
3474 kfree(cfg_dev);
3475}
3476
3477void
3478brcmf_cfg80211_event(struct net_device *ndev,
3479 const struct brcmf_event_msg *e, void *data)
3480{
3481 u32 event_type = be32_to_cpu(e->event_type);
3482 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
3483
3484 if (!brcmf_enq_event(cfg_priv, event_type, e))
3485 schedule_work(&cfg_priv->event_work);
3486}
3487
3488static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
3489{
3490 s32 infra = 0;
3491 s32 err = 0;
3492
3493 switch (iftype) {
3494 case NL80211_IFTYPE_MONITOR:
3495 case NL80211_IFTYPE_WDS:
3496 WL_ERR("type (%d) : currently we do not support this mode\n",
3497 iftype);
3498 err = -EINVAL;
3499 return err;
3500 case NL80211_IFTYPE_ADHOC:
3501 infra = 0;
3502 break;
3503 case NL80211_IFTYPE_STATION:
3504 infra = 1;
3505 break;
3506 default:
3507 err = -EINVAL;
3508 WL_ERR("invalid type (%d)\n", iftype);
3509 return err;
3510 }
3511 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
3512 if (err) {
3513 WL_ERR("WLC_SET_INFRA error (%d)\n", err);
3514 return err;
3515 }
3516
3517 return 0;
3518}
3519
3520static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
3521{
3522 /* Room for "event_msgs" + '\0' + bitvec */
3523 s8 iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
3524 s8 eventmask[BRCMF_EVENTING_MASK_LEN];
3525 s32 err = 0;
3526
3527 WL_TRACE("Enter\n");
3528
3529 /* Setup event_msgs */
53a2277d
AB
3530 brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
3531 iovbuf, sizeof(iovbuf));
5b435de0
AS
3532 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf));
3533 if (err) {
3534 WL_ERR("Get event_msgs error (%d)\n", err);
3535 goto dongle_eventmsg_out;
3536 }
3537 memcpy(eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN);
3538
3539 setbit(eventmask, BRCMF_E_SET_SSID);
3540 setbit(eventmask, BRCMF_E_ROAM);
3541 setbit(eventmask, BRCMF_E_PRUNE);
3542 setbit(eventmask, BRCMF_E_AUTH);
3543 setbit(eventmask, BRCMF_E_REASSOC);
3544 setbit(eventmask, BRCMF_E_REASSOC_IND);
3545 setbit(eventmask, BRCMF_E_DEAUTH_IND);
3546 setbit(eventmask, BRCMF_E_DISASSOC_IND);
3547 setbit(eventmask, BRCMF_E_DISASSOC);
3548 setbit(eventmask, BRCMF_E_JOIN);
3549 setbit(eventmask, BRCMF_E_ASSOC_IND);
3550 setbit(eventmask, BRCMF_E_PSK_SUP);
3551 setbit(eventmask, BRCMF_E_LINK);
3552 setbit(eventmask, BRCMF_E_NDIS_LINK);
3553 setbit(eventmask, BRCMF_E_MIC_ERROR);
3554 setbit(eventmask, BRCMF_E_PMKID_CACHE);
3555 setbit(eventmask, BRCMF_E_TXFAIL);
3556 setbit(eventmask, BRCMF_E_JOIN_START);
3557 setbit(eventmask, BRCMF_E_SCAN_COMPLETE);
3558
53a2277d
AB
3559 brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
3560 iovbuf, sizeof(iovbuf));
5b435de0
AS
3561 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
3562 if (err) {
3563 WL_ERR("Set event_msgs error (%d)\n", err);
3564 goto dongle_eventmsg_out;
3565 }
3566
3567dongle_eventmsg_out:
3568 WL_TRACE("Exit\n");
3569 return err;
3570}
3571
3572static s32
3573brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
3574{
3575 s8 iovbuf[32];
5b435de0 3576 s32 err = 0;
f588bc0c
AS
3577 __le32 roamtrigger[2];
3578 __le32 roam_delta[2];
3579 __le32 bcn_to_le;
3580 __le32 roamvar_le;
5b435de0
AS
3581
3582 /*
3583 * Setup timeout if Beacons are lost and roam is
3584 * off to report link down
3585 */
3586 if (roamvar) {
f588bc0c 3587 bcn_to_le = cpu_to_le32(bcn_timeout);
53a2277d 3588 brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_to_le,
f588bc0c 3589 sizeof(bcn_to_le), iovbuf, sizeof(iovbuf));
5b435de0
AS
3590 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR,
3591 iovbuf, sizeof(iovbuf));
3592 if (err) {
3593 WL_ERR("bcn_timeout error (%d)\n", err);
3594 goto dongle_rom_out;
3595 }
3596 }
3597
3598 /*
3599 * Enable/Disable built-in roaming to allow supplicant
3600 * to take care of roaming
3601 */
3602 WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On");
f588bc0c 3603 roamvar_le = cpu_to_le32(roamvar);
53a2277d 3604 brcmf_c_mkiovar("roam_off", (char *)&roamvar_le,
f588bc0c 3605 sizeof(roamvar_le), iovbuf, sizeof(iovbuf));
5b435de0
AS
3606 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
3607 if (err) {
3608 WL_ERR("roam_off error (%d)\n", err);
3609 goto dongle_rom_out;
3610 }
3611
f588bc0c
AS
3612 roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL);
3613 roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL);
5b435de0
AS
3614 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_TRIGGER,
3615 (void *)roamtrigger, sizeof(roamtrigger));
3616 if (err) {
3617 WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
3618 goto dongle_rom_out;
3619 }
3620
f588bc0c
AS
3621 roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA);
3622 roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL);
5b435de0
AS
3623 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_DELTA,
3624 (void *)roam_delta, sizeof(roam_delta));
3625 if (err) {
3626 WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err);
3627 goto dongle_rom_out;
3628 }
3629
3630dongle_rom_out:
3631 return err;
3632}
3633
3634static s32
3635brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
c68cdc0f 3636 s32 scan_unassoc_time, s32 scan_passive_time)
5b435de0
AS
3637{
3638 s32 err = 0;
c68cdc0f
AS
3639 __le32 scan_assoc_tm_le = cpu_to_le32(scan_assoc_time);
3640 __le32 scan_unassoc_tm_le = cpu_to_le32(scan_unassoc_time);
3641 __le32 scan_passive_tm_le = cpu_to_le32(scan_passive_time);
5b435de0
AS
3642
3643 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME,
c68cdc0f 3644 &scan_assoc_tm_le, sizeof(scan_assoc_tm_le));
5b435de0
AS
3645 if (err) {
3646 if (err == -EOPNOTSUPP)
3647 WL_INFO("Scan assoc time is not supported\n");
3648 else
3649 WL_ERR("Scan assoc time error (%d)\n", err);
3650 goto dongle_scantime_out;
3651 }
3652 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME,
c68cdc0f 3653 &scan_unassoc_tm_le, sizeof(scan_unassoc_tm_le));
5b435de0
AS
3654 if (err) {
3655 if (err == -EOPNOTSUPP)
3656 WL_INFO("Scan unassoc time is not supported\n");
3657 else
3658 WL_ERR("Scan unassoc time error (%d)\n", err);
3659 goto dongle_scantime_out;
3660 }
3661
3662 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME,
c68cdc0f 3663 &scan_passive_tm_le, sizeof(scan_passive_tm_le));
5b435de0
AS
3664 if (err) {
3665 if (err == -EOPNOTSUPP)
3666 WL_INFO("Scan passive time is not supported\n");
3667 else
3668 WL_ERR("Scan passive time error (%d)\n", err);
3669 goto dongle_scantime_out;
3670 }
3671
3672dongle_scantime_out:
3673 return err;
3674}
3675
3676static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv)
3677{
3678 struct wiphy *wiphy;
3679 s32 phy_list;
3680 s8 phy;
3681 s32 err = 0;
3682
3683 err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST,
3684 &phy_list, sizeof(phy_list));
3685 if (err) {
3686 WL_ERR("error (%d)\n", err);
3687 return err;
3688 }
3689
3690 phy = ((char *)&phy_list)[1];
3691 WL_INFO("%c phy\n", phy);
3692 if (phy == 'n' || phy == 'a') {
3693 wiphy = cfg_to_wiphy(cfg_priv);
3694 wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
3695 }
3696
3697 return err;
3698}
3699
3700static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv)
3701{
3702 return wl_update_wiphybands(cfg_priv);
3703}
3704
3705static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv)
3706{
3707 struct net_device *ndev;
3708 struct wireless_dev *wdev;
3709 s32 power_mode;
3710 s32 err = 0;
3711
3712 if (cfg_priv->dongle_up)
3713 return err;
3714
3715 ndev = cfg_to_ndev(cfg_priv);
3716 wdev = ndev->ieee80211_ptr;
3717
3718 brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
3719 WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
3720
3721 err = brcmf_dongle_eventmsg(ndev);
3722 if (err)
3723 goto default_conf_out;
3724
3725 power_mode = cfg_priv->pwr_save ? PM_FAST : PM_OFF;
3726 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &power_mode);
3727 if (err)
3728 goto default_conf_out;
3729 WL_INFO("power save set to %s\n",
3730 (power_mode ? "enabled" : "disabled"));
3731
3732 err = brcmf_dongle_roam(ndev, (cfg_priv->roam_on ? 0 : 1),
3733 WL_BEACON_TIMEOUT);
3734 if (err)
3735 goto default_conf_out;
3736 err = brcmf_dongle_mode(ndev, wdev->iftype);
3737 if (err && err != -EINPROGRESS)
3738 goto default_conf_out;
3739 err = brcmf_dongle_probecap(cfg_priv);
3740 if (err)
3741 goto default_conf_out;
3742
3743 /* -EINPROGRESS: Call commit handler */
3744
3745default_conf_out:
3746
3747 cfg_priv->dongle_up = true;
3748
3749 return err;
3750
3751}
3752
3753static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv)
3754{
3755 char buf[10+IFNAMSIZ];
3756 struct dentry *fd;
3757 s32 err = 0;
3758
3759 sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name);
3760 cfg_priv->debugfsdir = debugfs_create_dir(buf,
3761 cfg_to_wiphy(cfg_priv)->debugfsdir);
3762
3763 fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir,
3764 (u16 *)&cfg_priv->profile->beacon_interval);
3765 if (!fd) {
3766 err = -ENOMEM;
3767 goto err_out;
3768 }
3769
3770 fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir,
3771 (u8 *)&cfg_priv->profile->dtim_period);
3772 if (!fd) {
3773 err = -ENOMEM;
3774 goto err_out;
3775 }
3776
3777err_out:
3778 return err;
3779}
3780
3781static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv)
3782{
3783 debugfs_remove_recursive(cfg_priv->debugfsdir);
3784 cfg_priv->debugfsdir = NULL;
3785}
3786
3787static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv)
3788{
3789 s32 err = 0;
3790
3791 set_bit(WL_STATUS_READY, &cfg_priv->status);
3792
3793 brcmf_debugfs_add_netdev_params(cfg_priv);
3794
3795 err = brcmf_config_dongle(cfg_priv);
3796 if (err)
3797 return err;
3798
3799 brcmf_invoke_iscan(cfg_priv);
3800
3801 return err;
3802}
3803
3804static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv)
3805{
3806 /*
3807 * While going down, if associated with AP disassociate
3808 * from AP to save power
3809 */
3810 if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
3811 test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
3812 test_bit(WL_STATUS_READY, &cfg_priv->status)) {
3813 WL_INFO("Disassociating from AP");
3814 brcmf_link_down(cfg_priv);
3815
3816 /* Make sure WPA_Supplicant receives all the event
3817 generated due to DISASSOC call to the fw to keep
3818 the state fw and WPA_Supplicant state consistent
3819 */
3820 brcmf_delay(500);
3821 }
3822
3823 set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
3824 brcmf_term_iscan(cfg_priv);
3825 if (cfg_priv->scan_request) {
3826 cfg80211_scan_done(cfg_priv->scan_request, true);
3827 /* May need to perform this to cover rmmod */
3828 /* wl_set_mpc(cfg_to_ndev(wl), 1); */
3829 cfg_priv->scan_request = NULL;
3830 }
3831 clear_bit(WL_STATUS_READY, &cfg_priv->status);
3832 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
3833 clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
3834
3835 brcmf_debugfs_remove_netdev(cfg_priv);
3836
3837 return 0;
3838}
3839
3840s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev)
3841{
3842 struct brcmf_cfg80211_priv *cfg_priv;
3843 s32 err = 0;
3844
3845 cfg_priv = brcmf_priv_get(cfg_dev);
3846 mutex_lock(&cfg_priv->usr_sync);
3847 err = __brcmf_cfg80211_up(cfg_priv);
3848 mutex_unlock(&cfg_priv->usr_sync);
3849
3850 return err;
3851}
3852
3853s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev)
3854{
3855 struct brcmf_cfg80211_priv *cfg_priv;
3856 s32 err = 0;
3857
3858 cfg_priv = brcmf_priv_get(cfg_dev);
3859 mutex_lock(&cfg_priv->usr_sync);
3860 err = __brcmf_cfg80211_down(cfg_priv);
3861 mutex_unlock(&cfg_priv->usr_sync);
3862
3863 return err;
3864}
3865
3866static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv,
3867 u8 t, u8 l, u8 *v)
3868{
3869 struct brcmf_cfg80211_ie *ie = &cfg_priv->ie;
3870 s32 err = 0;
3871
3872 if (ie->offset + l + 2 > WL_TLV_INFO_MAX) {
3873 WL_ERR("ei crosses buffer boundary\n");
3874 return -ENOSPC;
3875 }
3876 ie->buf[ie->offset] = t;
3877 ie->buf[ie->offset + 1] = l;
3878 memcpy(&ie->buf[ie->offset + 2], v, l);
3879 ie->offset += l + 2;
3880
3881 return err;
3882}