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