brcmfmac: remove two obsolete structure definitions
[deliverable/linux.git] / drivers / net / wireless / brcm80211 / brcmfmac / wl_cfg80211.c
CommitLineData
5b435de0
AS
1/*
2 * Copyright (c) 2010 Broadcom Corporation
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17/* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */
18
02f77195
JP
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
5b435de0
AS
21#include <linux/kernel.h>
22#include <linux/if_arp.h>
23#include <linux/sched.h>
24#include <linux/kthread.h>
25#include <linux/netdevice.h>
26#include <linux/bitops.h>
27#include <linux/etherdevice.h>
28#include <linux/ieee80211.h>
29#include <linux/uaccess.h>
30#include <net/cfg80211.h>
cbaa177d 31#include <net/netlink.h>
5b435de0
AS
32
33#include <brcmu_utils.h>
34#include <defs.h>
35#include <brcmu_wifi.h>
36#include "dhd.h"
37#include "wl_cfg80211.h"
38
e5806072
AS
39#define BRCMF_SCAN_IE_LEN_MAX 2048
40#define BRCMF_PNO_VERSION 2
41#define BRCMF_PNO_TIME 30
42#define BRCMF_PNO_REPEAT 4
43#define BRCMF_PNO_FREQ_EXPO_MAX 3
44#define BRCMF_PNO_MAX_PFN_COUNT 16
45#define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6
46#define BRCMF_PNO_HIDDEN_BIT 2
47#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF
48#define BRCMF_PNO_SCAN_COMPLETE 1
49#define BRCMF_PNO_SCAN_INCOMPLETE 0
50
04012895
HM
51#define TLV_HDR_LEN 2 /* header length */
52
5b435de0
AS
53#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
54 (sizeof(struct brcmf_assoc_params_le) - sizeof(u16))
55
56static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
57
58static u32 brcmf_dbg_level = WL_DBG_ERR;
59
5b435de0
AS
60static bool check_sys_up(struct wiphy *wiphy)
61{
62 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
63 if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) {
64 WL_INFO("device is not ready : status (%d)\n",
65 (int)cfg_priv->status);
66 return false;
67 }
68 return true;
69}
70
71#define CHAN2G(_channel, _freq, _flags) { \
72 .band = IEEE80211_BAND_2GHZ, \
73 .center_freq = (_freq), \
74 .hw_value = (_channel), \
75 .flags = (_flags), \
76 .max_antenna_gain = 0, \
77 .max_power = 30, \
78}
79
80#define CHAN5G(_channel, _flags) { \
81 .band = IEEE80211_BAND_5GHZ, \
82 .center_freq = 5000 + (5 * (_channel)), \
83 .hw_value = (_channel), \
84 .flags = (_flags), \
85 .max_antenna_gain = 0, \
86 .max_power = 30, \
87}
88
89#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
90#define RATETAB_ENT(_rateid, _flags) \
91 { \
92 .bitrate = RATE_TO_BASE100KBPS(_rateid), \
93 .hw_value = (_rateid), \
94 .flags = (_flags), \
95 }
96
97static struct ieee80211_rate __wl_rates[] = {
98 RATETAB_ENT(BRCM_RATE_1M, 0),
99 RATETAB_ENT(BRCM_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
100 RATETAB_ENT(BRCM_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
101 RATETAB_ENT(BRCM_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
102 RATETAB_ENT(BRCM_RATE_6M, 0),
103 RATETAB_ENT(BRCM_RATE_9M, 0),
104 RATETAB_ENT(BRCM_RATE_12M, 0),
105 RATETAB_ENT(BRCM_RATE_18M, 0),
106 RATETAB_ENT(BRCM_RATE_24M, 0),
107 RATETAB_ENT(BRCM_RATE_36M, 0),
108 RATETAB_ENT(BRCM_RATE_48M, 0),
109 RATETAB_ENT(BRCM_RATE_54M, 0),
110};
111
112#define wl_a_rates (__wl_rates + 4)
113#define wl_a_rates_size 8
114#define wl_g_rates (__wl_rates + 0)
115#define wl_g_rates_size 12
116
117static struct ieee80211_channel __wl_2ghz_channels[] = {
118 CHAN2G(1, 2412, 0),
119 CHAN2G(2, 2417, 0),
120 CHAN2G(3, 2422, 0),
121 CHAN2G(4, 2427, 0),
122 CHAN2G(5, 2432, 0),
123 CHAN2G(6, 2437, 0),
124 CHAN2G(7, 2442, 0),
125 CHAN2G(8, 2447, 0),
126 CHAN2G(9, 2452, 0),
127 CHAN2G(10, 2457, 0),
128 CHAN2G(11, 2462, 0),
129 CHAN2G(12, 2467, 0),
130 CHAN2G(13, 2472, 0),
131 CHAN2G(14, 2484, 0),
132};
133
134static struct ieee80211_channel __wl_5ghz_a_channels[] = {
135 CHAN5G(34, 0), CHAN5G(36, 0),
136 CHAN5G(38, 0), CHAN5G(40, 0),
137 CHAN5G(42, 0), CHAN5G(44, 0),
138 CHAN5G(46, 0), CHAN5G(48, 0),
139 CHAN5G(52, 0), CHAN5G(56, 0),
140 CHAN5G(60, 0), CHAN5G(64, 0),
141 CHAN5G(100, 0), CHAN5G(104, 0),
142 CHAN5G(108, 0), CHAN5G(112, 0),
143 CHAN5G(116, 0), CHAN5G(120, 0),
144 CHAN5G(124, 0), CHAN5G(128, 0),
145 CHAN5G(132, 0), CHAN5G(136, 0),
146 CHAN5G(140, 0), CHAN5G(149, 0),
147 CHAN5G(153, 0), CHAN5G(157, 0),
148 CHAN5G(161, 0), CHAN5G(165, 0),
149 CHAN5G(184, 0), CHAN5G(188, 0),
150 CHAN5G(192, 0), CHAN5G(196, 0),
151 CHAN5G(200, 0), CHAN5G(204, 0),
152 CHAN5G(208, 0), CHAN5G(212, 0),
153 CHAN5G(216, 0),
154};
155
156static struct ieee80211_channel __wl_5ghz_n_channels[] = {
157 CHAN5G(32, 0), CHAN5G(34, 0),
158 CHAN5G(36, 0), CHAN5G(38, 0),
159 CHAN5G(40, 0), CHAN5G(42, 0),
160 CHAN5G(44, 0), CHAN5G(46, 0),
161 CHAN5G(48, 0), CHAN5G(50, 0),
162 CHAN5G(52, 0), CHAN5G(54, 0),
163 CHAN5G(56, 0), CHAN5G(58, 0),
164 CHAN5G(60, 0), CHAN5G(62, 0),
165 CHAN5G(64, 0), CHAN5G(66, 0),
166 CHAN5G(68, 0), CHAN5G(70, 0),
167 CHAN5G(72, 0), CHAN5G(74, 0),
168 CHAN5G(76, 0), CHAN5G(78, 0),
169 CHAN5G(80, 0), CHAN5G(82, 0),
170 CHAN5G(84, 0), CHAN5G(86, 0),
171 CHAN5G(88, 0), CHAN5G(90, 0),
172 CHAN5G(92, 0), CHAN5G(94, 0),
173 CHAN5G(96, 0), CHAN5G(98, 0),
174 CHAN5G(100, 0), CHAN5G(102, 0),
175 CHAN5G(104, 0), CHAN5G(106, 0),
176 CHAN5G(108, 0), CHAN5G(110, 0),
177 CHAN5G(112, 0), CHAN5G(114, 0),
178 CHAN5G(116, 0), CHAN5G(118, 0),
179 CHAN5G(120, 0), CHAN5G(122, 0),
180 CHAN5G(124, 0), CHAN5G(126, 0),
181 CHAN5G(128, 0), CHAN5G(130, 0),
182 CHAN5G(132, 0), CHAN5G(134, 0),
183 CHAN5G(136, 0), CHAN5G(138, 0),
184 CHAN5G(140, 0), CHAN5G(142, 0),
185 CHAN5G(144, 0), CHAN5G(145, 0),
186 CHAN5G(146, 0), CHAN5G(147, 0),
187 CHAN5G(148, 0), CHAN5G(149, 0),
188 CHAN5G(150, 0), CHAN5G(151, 0),
189 CHAN5G(152, 0), CHAN5G(153, 0),
190 CHAN5G(154, 0), CHAN5G(155, 0),
191 CHAN5G(156, 0), CHAN5G(157, 0),
192 CHAN5G(158, 0), CHAN5G(159, 0),
193 CHAN5G(160, 0), CHAN5G(161, 0),
194 CHAN5G(162, 0), CHAN5G(163, 0),
195 CHAN5G(164, 0), CHAN5G(165, 0),
196 CHAN5G(166, 0), CHAN5G(168, 0),
197 CHAN5G(170, 0), CHAN5G(172, 0),
198 CHAN5G(174, 0), CHAN5G(176, 0),
199 CHAN5G(178, 0), CHAN5G(180, 0),
200 CHAN5G(182, 0), CHAN5G(184, 0),
201 CHAN5G(186, 0), CHAN5G(188, 0),
202 CHAN5G(190, 0), CHAN5G(192, 0),
203 CHAN5G(194, 0), CHAN5G(196, 0),
204 CHAN5G(198, 0), CHAN5G(200, 0),
205 CHAN5G(202, 0), CHAN5G(204, 0),
206 CHAN5G(206, 0), CHAN5G(208, 0),
207 CHAN5G(210, 0), CHAN5G(212, 0),
208 CHAN5G(214, 0), CHAN5G(216, 0),
209 CHAN5G(218, 0), CHAN5G(220, 0),
210 CHAN5G(222, 0), CHAN5G(224, 0),
211 CHAN5G(226, 0), CHAN5G(228, 0),
212};
213
214static struct ieee80211_supported_band __wl_band_2ghz = {
215 .band = IEEE80211_BAND_2GHZ,
216 .channels = __wl_2ghz_channels,
217 .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
218 .bitrates = wl_g_rates,
219 .n_bitrates = wl_g_rates_size,
220};
221
222static struct ieee80211_supported_band __wl_band_5ghz_a = {
223 .band = IEEE80211_BAND_5GHZ,
224 .channels = __wl_5ghz_a_channels,
225 .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
226 .bitrates = wl_a_rates,
227 .n_bitrates = wl_a_rates_size,
228};
229
230static struct ieee80211_supported_band __wl_band_5ghz_n = {
231 .band = IEEE80211_BAND_5GHZ,
232 .channels = __wl_5ghz_n_channels,
233 .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
234 .bitrates = wl_a_rates,
235 .n_bitrates = wl_a_rates_size,
236};
237
238static const u32 __wl_cipher_suites[] = {
239 WLAN_CIPHER_SUITE_WEP40,
240 WLAN_CIPHER_SUITE_WEP104,
241 WLAN_CIPHER_SUITE_TKIP,
242 WLAN_CIPHER_SUITE_CCMP,
243 WLAN_CIPHER_SUITE_AES_CMAC,
244};
245
f8e4b412
AB
246/* tag_ID/length/value_buffer tuple */
247struct brcmf_tlv {
248 u8 id;
249 u8 len;
250 u8 data[1];
251};
252
ef6ac17a
AB
253/* Quarter dBm units to mW
254 * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
255 * Table is offset so the last entry is largest mW value that fits in
256 * a u16.
257 */
258
259#define QDBM_OFFSET 153 /* Offset for first entry */
260#define QDBM_TABLE_LEN 40 /* Table size */
261
262/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
263 * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
264 */
265#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */
266
267/* Largest mW value that will round down to the last table entry,
268 * QDBM_OFFSET + QDBM_TABLE_LEN-1.
269 * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) +
270 * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
271 */
272#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */
273
274static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
275/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */
276/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
277/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
278/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
279/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
280/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
281};
282
283static u16 brcmf_qdbm_to_mw(u8 qdbm)
284{
285 uint factor = 1;
286 int idx = qdbm - QDBM_OFFSET;
287
288 if (idx >= QDBM_TABLE_LEN)
289 /* clamp to max u16 mW value */
290 return 0xFFFF;
291
292 /* scale the qdBm index up to the range of the table 0-40
293 * where an offset of 40 qdBm equals a factor of 10 mW.
294 */
295 while (idx < 0) {
296 idx += 40;
297 factor *= 10;
298 }
299
300 /* return the mW value scaled down to the correct factor of 10,
301 * adding in factor/2 to get proper rounding.
302 */
303 return (nqdBm_to_mW_map[idx] + factor / 2) / factor;
304}
305
306static u8 brcmf_mw_to_qdbm(u16 mw)
307{
308 u8 qdbm;
309 int offset;
310 uint mw_uint = mw;
311 uint boundary;
312
313 /* handle boundary case */
314 if (mw_uint <= 1)
315 return 0;
316
317 offset = QDBM_OFFSET;
318
319 /* move mw into the range of the table */
320 while (mw_uint < QDBM_TABLE_LOW_BOUND) {
321 mw_uint *= 10;
322 offset -= 40;
323 }
324
325 for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) {
326 boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] -
327 nqdBm_to_mW_map[qdbm]) / 2;
328 if (mw_uint < boundary)
329 break;
330 }
331
332 qdbm += (u8) offset;
333
334 return qdbm;
335}
336
5b435de0
AS
337/* function for reading/writing a single u32 from/to the dongle */
338static int
339brcmf_exec_dcmd_u32(struct net_device *ndev, u32 cmd, u32 *par)
340{
341 int err;
342 __le32 par_le = cpu_to_le32(*par);
343
344 err = brcmf_exec_dcmd(ndev, cmd, &par_le, sizeof(__le32));
345 *par = le32_to_cpu(par_le);
346
347 return err;
348}
349
f09d0c02
HM
350static s32
351brcmf_dev_iovar_setbuf_bsscfg(struct net_device *ndev, s8 *name,
352 void *param, s32 paramlen,
353 void *buf, s32 buflen, s32 bssidx)
354{
355 s32 err = -ENOMEM;
356 u32 len;
357
358 len = brcmf_c_mkiovar_bsscfg(name, param, paramlen,
359 buf, buflen, bssidx);
360 BUG_ON(!len);
361 if (len > 0)
362 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len);
363 if (err)
364 WL_ERR("error (%d)\n", err);
365
366 return err;
367}
368
369static s32
370brcmf_dev_iovar_getbuf_bsscfg(struct net_device *ndev, s8 *name,
371 void *param, s32 paramlen,
372 void *buf, s32 buflen, s32 bssidx)
373{
374 s32 err = -ENOMEM;
375 u32 len;
376
377 len = brcmf_c_mkiovar_bsscfg(name, param, paramlen,
378 buf, buflen, bssidx);
379 BUG_ON(!len);
380 if (len > 0)
381 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, buf, len);
382 if (err)
383 WL_ERR("error (%d)\n", err);
384
385 return err;
386}
387
5b435de0
AS
388static void convert_key_from_CPU(struct brcmf_wsec_key *key,
389 struct brcmf_wsec_key_le *key_le)
390{
391 key_le->index = cpu_to_le32(key->index);
392 key_le->len = cpu_to_le32(key->len);
393 key_le->algo = cpu_to_le32(key->algo);
394 key_le->flags = cpu_to_le32(key->flags);
395 key_le->rxiv.hi = cpu_to_le32(key->rxiv.hi);
396 key_le->rxiv.lo = cpu_to_le16(key->rxiv.lo);
397 key_le->iv_initialized = cpu_to_le32(key->iv_initialized);
398 memcpy(key_le->data, key->data, sizeof(key->data));
399 memcpy(key_le->ea, key->ea, sizeof(key->ea));
400}
401
f09d0c02
HM
402static int
403send_key_to_dongle(struct brcmf_cfg80211_priv *cfg_priv, s32 bssidx,
404 struct net_device *ndev, struct brcmf_wsec_key *key)
5b435de0
AS
405{
406 int err;
407 struct brcmf_wsec_key_le key_le;
408
409 convert_key_from_CPU(key, &key_le);
f09d0c02
HM
410
411 err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "wsec_key", &key_le,
412 sizeof(key_le),
413 cfg_priv->extra_buf,
414 WL_EXTRA_BUF_MAX, bssidx);
415
5b435de0 416 if (err)
f09d0c02 417 WL_ERR("wsec_key error (%d)\n", err);
5b435de0
AS
418 return err;
419}
420
421static s32
422brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
423 enum nl80211_iftype type, u32 *flags,
424 struct vif_params *params)
425{
426 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
427 struct wireless_dev *wdev;
428 s32 infra = 0;
429 s32 err = 0;
430
431 WL_TRACE("Enter\n");
432 if (!check_sys_up(wiphy))
433 return -EIO;
434
435 switch (type) {
436 case NL80211_IFTYPE_MONITOR:
437 case NL80211_IFTYPE_WDS:
438 WL_ERR("type (%d) : currently we do not support this type\n",
439 type);
440 return -EOPNOTSUPP;
441 case NL80211_IFTYPE_ADHOC:
442 cfg_priv->conf->mode = WL_MODE_IBSS;
443 infra = 0;
444 break;
445 case NL80211_IFTYPE_STATION:
446 cfg_priv->conf->mode = WL_MODE_BSS;
447 infra = 1;
448 break;
449 default:
450 err = -EINVAL;
451 goto done;
452 }
453
454 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
455 if (err) {
456 WL_ERR("WLC_SET_INFRA error (%d)\n", err);
457 err = -EAGAIN;
458 } else {
459 wdev = ndev->ieee80211_ptr;
460 wdev->iftype = type;
461 }
462
463 WL_INFO("IF Type = %s\n",
464 (cfg_priv->conf->mode == WL_MODE_IBSS) ? "Adhoc" : "Infra");
465
466done:
467 WL_TRACE("Exit\n");
468
469 return err;
470}
471
472static s32 brcmf_dev_intvar_set(struct net_device *ndev, s8 *name, s32 val)
473{
474 s8 buf[BRCMF_DCMD_SMLEN];
475 u32 len;
476 s32 err = 0;
477 __le32 val_le;
478
479 val_le = cpu_to_le32(val);
53a2277d 480 len = brcmf_c_mkiovar(name, (char *)(&val_le), sizeof(val_le), buf,
5b435de0
AS
481 sizeof(buf));
482 BUG_ON(!len);
483
484 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len);
485 if (err)
486 WL_ERR("error (%d)\n", err);
487
488 return err;
489}
490
491static s32
492brcmf_dev_intvar_get(struct net_device *ndev, s8 *name, s32 *retval)
493{
494 union {
495 s8 buf[BRCMF_DCMD_SMLEN];
496 __le32 val;
497 } var;
498 u32 len;
499 u32 data_null;
500 s32 err = 0;
501
502 len =
53a2277d 503 brcmf_c_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
5b435de0
AS
504 sizeof(var.buf));
505 BUG_ON(!len);
506 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, &var, len);
507 if (err)
508 WL_ERR("error (%d)\n", err);
509
510 *retval = le32_to_cpu(var.val);
511
512 return err;
513}
514
f09d0c02
HM
515static s32
516brcmf_dev_intvar_set_bsscfg(struct net_device *ndev, s8 *name, u32 val,
517 s32 bssidx)
518{
519 s8 buf[BRCMF_DCMD_SMLEN];
520 __le32 val_le;
521
522 val_le = cpu_to_le32(val);
523
524 return brcmf_dev_iovar_setbuf_bsscfg(ndev, name, &val_le,
525 sizeof(val_le), buf, sizeof(buf),
526 bssidx);
527}
528
529static s32
530brcmf_dev_intvar_get_bsscfg(struct net_device *ndev, s8 *name, s32 *val,
531 s32 bssidx)
532{
533 s8 buf[BRCMF_DCMD_SMLEN];
534 s32 err;
535 __le32 val_le;
536
537 memset(buf, 0, sizeof(buf));
538 err = brcmf_dev_iovar_getbuf_bsscfg(ndev, name, val, sizeof(*val), buf,
539 sizeof(buf), bssidx);
540 if (err == 0) {
541 memcpy(&val_le, buf, sizeof(val_le));
542 *val = le32_to_cpu(val_le);
543 }
544 return err;
545}
546
547
548/*
549 * For now brcmf_find_bssidx will return 0. Once p2p gets implemented this
550 * should return the ndev matching bssidx.
551 */
552static s32
553brcmf_find_bssidx(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev)
554{
555 return 0;
556}
557
5b435de0
AS
558static void brcmf_set_mpc(struct net_device *ndev, int mpc)
559{
560 s32 err = 0;
561 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
562
563 if (test_bit(WL_STATUS_READY, &cfg_priv->status)) {
564 err = brcmf_dev_intvar_set(ndev, "mpc", mpc);
565 if (err) {
566 WL_ERR("fail to set mpc\n");
567 return;
568 }
569 WL_INFO("MPC : %d\n", mpc);
570 }
571}
572
35aafa9d
HM
573static void brcmf_iscan_prep(struct brcmf_scan_params_le *params_le,
574 struct brcmf_ssid *ssid)
5b435de0
AS
575{
576 memcpy(params_le->bssid, ether_bcast, ETH_ALEN);
577 params_le->bss_type = DOT11_BSSTYPE_ANY;
578 params_le->scan_type = 0;
579 params_le->channel_num = 0;
580 params_le->nprobes = cpu_to_le32(-1);
581 params_le->active_time = cpu_to_le32(-1);
582 params_le->passive_time = cpu_to_le32(-1);
583 params_le->home_time = cpu_to_le32(-1);
584 if (ssid && ssid->SSID_len)
585 memcpy(&params_le->ssid_le, ssid, sizeof(struct brcmf_ssid));
586}
587
588static s32
589brcmf_dev_iovar_setbuf(struct net_device *ndev, s8 * iovar, void *param,
590 s32 paramlen, void *bufptr, s32 buflen)
591{
592 s32 iolen;
593
53a2277d 594 iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
5b435de0
AS
595 BUG_ON(!iolen);
596
597 return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, bufptr, iolen);
598}
599
600static s32
601brcmf_dev_iovar_getbuf(struct net_device *ndev, s8 * iovar, void *param,
602 s32 paramlen, void *bufptr, s32 buflen)
603{
604 s32 iolen;
605
53a2277d 606 iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
5b435de0
AS
607 BUG_ON(!iolen);
608
609 return brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, bufptr, buflen);
610}
611
612static s32
613brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan,
614 struct brcmf_ssid *ssid, u16 action)
615{
616 s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
617 offsetof(struct brcmf_iscan_params_le, params_le);
618 struct brcmf_iscan_params_le *params;
619 s32 err = 0;
620
621 if (ssid && ssid->SSID_len)
622 params_size += sizeof(struct brcmf_ssid);
623 params = kzalloc(params_size, GFP_KERNEL);
624 if (!params)
625 return -ENOMEM;
626 BUG_ON(params_size >= BRCMF_DCMD_SMLEN);
627
35aafa9d 628 brcmf_iscan_prep(&params->params_le, ssid);
5b435de0
AS
629
630 params->version = cpu_to_le32(BRCMF_ISCAN_REQ_VERSION);
631 params->action = cpu_to_le16(action);
632 params->scan_duration = cpu_to_le16(0);
633
634 err = brcmf_dev_iovar_setbuf(iscan->ndev, "iscan", params, params_size,
635 iscan->dcmd_buf, BRCMF_DCMD_SMLEN);
636 if (err) {
637 if (err == -EBUSY)
638 WL_INFO("system busy : iscan canceled\n");
639 else
640 WL_ERR("error (%d)\n", err);
641 }
642
643 kfree(params);
644 return err;
645}
646
647static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv)
648{
649 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
650 struct net_device *ndev = cfg_to_ndev(cfg_priv);
651 struct brcmf_ssid ssid;
66831075 652 __le32 passive_scan;
5b435de0
AS
653 s32 err = 0;
654
655 /* Broadcast scan by default */
656 memset(&ssid, 0, sizeof(ssid));
657
658 iscan->state = WL_ISCAN_STATE_SCANING;
659
66831075 660 passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
5b435de0
AS
661 err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_SET_PASSIVE_SCAN,
662 &passive_scan, sizeof(passive_scan));
663 if (err) {
664 WL_ERR("error (%d)\n", err);
665 return err;
666 }
667 brcmf_set_mpc(ndev, 0);
668 cfg_priv->iscan_kickstart = true;
669 err = brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START);
670 if (err) {
671 brcmf_set_mpc(ndev, 1);
672 cfg_priv->iscan_kickstart = false;
673 return err;
674 }
675 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
676 iscan->timer_on = 1;
677 return err;
678}
679
680static s32
35aafa9d
HM
681brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev,
682 struct cfg80211_scan_request *request,
683 struct cfg80211_ssid *this_ssid)
5b435de0
AS
684{
685 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
686 struct cfg80211_ssid *ssids;
687 struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int;
66831075 688 __le32 passive_scan;
5b435de0
AS
689 bool iscan_req;
690 bool spec_scan;
691 s32 err = 0;
692 u32 SSID_len;
693
694 if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
695 WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status);
696 return -EAGAIN;
697 }
698 if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status)) {
699 WL_ERR("Scanning being aborted : status (%lu)\n",
700 cfg_priv->status);
701 return -EAGAIN;
702 }
703 if (test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
704 WL_ERR("Connecting : status (%lu)\n",
705 cfg_priv->status);
706 return -EAGAIN;
707 }
708
709 iscan_req = false;
710 spec_scan = false;
711 if (request) {
712 /* scan bss */
713 ssids = request->ssids;
714 if (cfg_priv->iscan_on && (!ssids || !ssids->ssid_len))
715 iscan_req = true;
716 } else {
717 /* scan in ibss */
718 /* we don't do iscan in ibss */
719 ssids = this_ssid;
720 }
721
722 cfg_priv->scan_request = request;
723 set_bit(WL_STATUS_SCANNING, &cfg_priv->status);
724 if (iscan_req) {
725 err = brcmf_do_iscan(cfg_priv);
726 if (!err)
727 return err;
728 else
729 goto scan_out;
730 } else {
731 WL_SCAN("ssid \"%s\", ssid_len (%d)\n",
732 ssids->ssid, ssids->ssid_len);
733 memset(&sr->ssid_le, 0, sizeof(sr->ssid_le));
734 SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len);
735 sr->ssid_le.SSID_len = cpu_to_le32(0);
736 if (SSID_len) {
737 memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len);
738 sr->ssid_le.SSID_len = cpu_to_le32(SSID_len);
739 spec_scan = true;
740 } else {
741 WL_SCAN("Broadcast scan\n");
742 }
743
66831075 744 passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
5b435de0
AS
745 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
746 &passive_scan, sizeof(passive_scan));
747 if (err) {
748 WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
749 goto scan_out;
750 }
751 brcmf_set_mpc(ndev, 0);
752 err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le,
753 sizeof(sr->ssid_le));
754 if (err) {
755 if (err == -EBUSY)
756 WL_INFO("system busy : scan for \"%s\" "
757 "canceled\n", sr->ssid_le.SSID);
758 else
759 WL_ERR("WLC_SCAN error (%d)\n", err);
760
761 brcmf_set_mpc(ndev, 1);
762 goto scan_out;
763 }
764 }
765
766 return 0;
767
768scan_out:
769 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
770 cfg_priv->scan_request = NULL;
771 return err;
772}
773
e756af5b
HM
774static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
775 struct cfg80211_scan_request *request)
776{
777 u32 n_ssids;
778 u32 n_channels;
779 s32 i;
780 s32 offset;
029591f3 781 u16 chanspec;
e756af5b
HM
782 u16 channel;
783 struct ieee80211_channel *req_channel;
784 char *ptr;
029591f3 785 struct brcmf_ssid_le ssid_le;
e756af5b
HM
786
787 memcpy(params_le->bssid, ether_bcast, ETH_ALEN);
788 params_le->bss_type = DOT11_BSSTYPE_ANY;
789 params_le->scan_type = 0;
790 params_le->channel_num = 0;
791 params_le->nprobes = cpu_to_le32(-1);
792 params_le->active_time = cpu_to_le32(-1);
793 params_le->passive_time = cpu_to_le32(-1);
794 params_le->home_time = cpu_to_le32(-1);
795 memset(&params_le->ssid_le, 0, sizeof(params_le->ssid_le));
796
797 /* if request is null exit so it will be all channel broadcast scan */
798 if (!request)
799 return;
800
801 n_ssids = request->n_ssids;
802 n_channels = request->n_channels;
803 /* Copy channel array if applicable */
804 WL_SCAN("### List of channelspecs to scan ### %d\n", n_channels);
805 if (n_channels > 0) {
806 for (i = 0; i < n_channels; i++) {
807 chanspec = 0;
808 req_channel = request->channels[i];
809 channel = ieee80211_frequency_to_channel(
810 req_channel->center_freq);
811 if (req_channel->band == IEEE80211_BAND_2GHZ)
812 chanspec |= WL_CHANSPEC_BAND_2G;
813 else
814 chanspec |= WL_CHANSPEC_BAND_5G;
815
816 if (req_channel->flags & IEEE80211_CHAN_NO_HT40) {
817 chanspec |= WL_CHANSPEC_BW_20;
818 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
819 } else {
820 chanspec |= WL_CHANSPEC_BW_40;
821 if (req_channel->flags &
822 IEEE80211_CHAN_NO_HT40PLUS)
823 chanspec |= WL_CHANSPEC_CTL_SB_LOWER;
824 else
825 chanspec |= WL_CHANSPEC_CTL_SB_UPPER;
826 }
827
029591f3 828 chanspec |= (channel & WL_CHANSPEC_CHAN_MASK);
e756af5b 829 WL_SCAN("Chan : %d, Channel spec: %x\n",
029591f3
AS
830 channel, chanspec);
831 params_le->channel_list[i] = cpu_to_le16(chanspec);
e756af5b
HM
832 }
833 } else {
834 WL_SCAN("Scanning all channels\n");
835 }
836 /* Copy ssid array if applicable */
837 WL_SCAN("### List of SSIDs to scan ### %d\n", n_ssids);
838 if (n_ssids > 0) {
839 offset = offsetof(struct brcmf_scan_params_le, channel_list) +
840 n_channels * sizeof(u16);
841 offset = roundup(offset, sizeof(u32));
842 ptr = (char *)params_le + offset;
843 for (i = 0; i < n_ssids; i++) {
029591f3
AS
844 memset(&ssid_le, 0, sizeof(ssid_le));
845 ssid_le.SSID_len =
846 cpu_to_le32(request->ssids[i].ssid_len);
847 memcpy(ssid_le.SSID, request->ssids[i].ssid,
848 request->ssids[i].ssid_len);
849 if (!ssid_le.SSID_len)
e756af5b
HM
850 WL_SCAN("%d: Broadcast scan\n", i);
851 else
852 WL_SCAN("%d: scan for %s size =%d\n", i,
029591f3
AS
853 ssid_le.SSID, ssid_le.SSID_len);
854 memcpy(ptr, &ssid_le, sizeof(ssid_le));
855 ptr += sizeof(ssid_le);
e756af5b
HM
856 }
857 } else {
858 WL_SCAN("Broadcast scan %p\n", request->ssids);
859 if ((request->ssids) && request->ssids->ssid_len) {
860 WL_SCAN("SSID %s len=%d\n", params_le->ssid_le.SSID,
861 request->ssids->ssid_len);
862 params_le->ssid_le.SSID_len =
863 cpu_to_le32(request->ssids->ssid_len);
864 memcpy(&params_le->ssid_le.SSID, request->ssids->ssid,
865 request->ssids->ssid_len);
866 }
867 }
868 /* Adding mask to channel numbers */
869 params_le->channel_num =
870 cpu_to_le32((n_ssids << BRCMF_SCAN_PARAMS_NSSID_SHIFT) |
871 (n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK));
872}
873
874static s32
875brcmf_notify_escan_complete(struct brcmf_cfg80211_priv *cfg_priv,
876 struct net_device *ndev,
877 bool aborted, bool fw_abort)
878{
879 struct brcmf_scan_params_le params_le;
880 struct cfg80211_scan_request *scan_request;
881 s32 err = 0;
882
883 WL_SCAN("Enter\n");
884
885 /* clear scan request, because the FW abort can cause a second call */
886 /* to this functon and might cause a double cfg80211_scan_done */
887 scan_request = cfg_priv->scan_request;
888 cfg_priv->scan_request = NULL;
889
890 if (timer_pending(&cfg_priv->escan_timeout))
891 del_timer_sync(&cfg_priv->escan_timeout);
892
893 if (fw_abort) {
894 /* Do a scan abort to stop the driver's scan engine */
895 WL_SCAN("ABORT scan in firmware\n");
896 memset(&params_le, 0, sizeof(params_le));
897 memcpy(params_le.bssid, ether_bcast, ETH_ALEN);
898 params_le.bss_type = DOT11_BSSTYPE_ANY;
899 params_le.scan_type = 0;
900 params_le.channel_num = cpu_to_le32(1);
901 params_le.nprobes = cpu_to_le32(1);
902 params_le.active_time = cpu_to_le32(-1);
903 params_le.passive_time = cpu_to_le32(-1);
904 params_le.home_time = cpu_to_le32(-1);
905 /* Scan is aborted by setting channel_list[0] to -1 */
906 params_le.channel_list[0] = cpu_to_le16(-1);
907 /* E-Scan (or anyother type) can be aborted by SCAN */
908 err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &params_le,
909 sizeof(params_le));
910 if (err)
911 WL_ERR("Scan abort failed\n");
912 }
e5806072
AS
913 /*
914 * e-scan can be initiated by scheduled scan
915 * which takes precedence.
916 */
917 if (cfg_priv->sched_escan) {
918 WL_SCAN("scheduled scan completed\n");
919 cfg_priv->sched_escan = false;
920 if (!aborted)
921 cfg80211_sched_scan_results(cfg_to_wiphy(cfg_priv));
922 brcmf_set_mpc(ndev, 1);
923 } else if (scan_request) {
e756af5b
HM
924 WL_SCAN("ESCAN Completed scan: %s\n",
925 aborted ? "Aborted" : "Done");
926 cfg80211_scan_done(scan_request, aborted);
927 brcmf_set_mpc(ndev, 1);
928 }
929 if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
930 WL_ERR("Scan complete while device not scanning\n");
931 return -EPERM;
932 }
933
934 return err;
935}
936
937static s32
938brcmf_run_escan(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev,
939 struct cfg80211_scan_request *request, u16 action)
940{
941 s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
942 offsetof(struct brcmf_escan_params_le, params_le);
943 struct brcmf_escan_params_le *params;
944 s32 err = 0;
945
946 WL_SCAN("E-SCAN START\n");
947
948 if (request != NULL) {
949 /* Allocate space for populating ssids in struct */
950 params_size += sizeof(u32) * ((request->n_channels + 1) / 2);
951
952 /* Allocate space for populating ssids in struct */
953 params_size += sizeof(struct brcmf_ssid) * request->n_ssids;
954 }
955
956 params = kzalloc(params_size, GFP_KERNEL);
957 if (!params) {
958 err = -ENOMEM;
959 goto exit;
960 }
961 BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN);
962 brcmf_escan_prep(&params->params_le, request);
963 params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
964 params->action = cpu_to_le16(action);
965 params->sync_id = cpu_to_le16(0x1234);
966
967 err = brcmf_dev_iovar_setbuf(ndev, "escan", params, params_size,
968 cfg_priv->escan_ioctl_buf, BRCMF_DCMD_MEDLEN);
969 if (err) {
970 if (err == -EBUSY)
971 WL_INFO("system busy : escan canceled\n");
972 else
973 WL_ERR("error (%d)\n", err);
974 }
975
976 kfree(params);
977exit:
978 return err;
979}
980
981static s32
982brcmf_do_escan(struct brcmf_cfg80211_priv *cfg_priv, struct wiphy *wiphy,
983 struct net_device *ndev, struct cfg80211_scan_request *request)
984{
985 s32 err;
986 __le32 passive_scan;
987 struct brcmf_scan_results *results;
988
989 WL_SCAN("Enter\n");
990 cfg_priv->escan_info.ndev = ndev;
991 cfg_priv->escan_info.wiphy = wiphy;
992 cfg_priv->escan_info.escan_state = WL_ESCAN_STATE_SCANNING;
993 passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
994 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
995 &passive_scan, sizeof(passive_scan));
996 if (err) {
997 WL_ERR("error (%d)\n", err);
998 return err;
999 }
1000 brcmf_set_mpc(ndev, 0);
1001 results = (struct brcmf_scan_results *)cfg_priv->escan_info.escan_buf;
1002 results->version = 0;
1003 results->count = 0;
1004 results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE;
1005
1006 err = brcmf_run_escan(cfg_priv, ndev, request, WL_ESCAN_ACTION_START);
1007 if (err)
1008 brcmf_set_mpc(ndev, 1);
1009 return err;
1010}
1011
1012static s32
1013brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
1014 struct cfg80211_scan_request *request,
1015 struct cfg80211_ssid *this_ssid)
1016{
1017 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1018 struct cfg80211_ssid *ssids;
1019 struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int;
1020 __le32 passive_scan;
1021 bool escan_req;
1022 bool spec_scan;
1023 s32 err;
1024 u32 SSID_len;
1025
1026 WL_SCAN("START ESCAN\n");
1027
1028 if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
1029 WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status);
1030 return -EAGAIN;
1031 }
1032 if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status)) {
1033 WL_ERR("Scanning being aborted : status (%lu)\n",
1034 cfg_priv->status);
1035 return -EAGAIN;
1036 }
1037 if (test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
1038 WL_ERR("Connecting : status (%lu)\n",
1039 cfg_priv->status);
1040 return -EAGAIN;
1041 }
1042
1043 /* Arm scan timeout timer */
1044 mod_timer(&cfg_priv->escan_timeout, jiffies +
1045 WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000);
1046
1047 escan_req = false;
1048 if (request) {
1049 /* scan bss */
1050 ssids = request->ssids;
1051 escan_req = true;
1052 } else {
1053 /* scan in ibss */
1054 /* we don't do escan in ibss */
1055 ssids = this_ssid;
1056 }
1057
1058 cfg_priv->scan_request = request;
1059 set_bit(WL_STATUS_SCANNING, &cfg_priv->status);
1060 if (escan_req) {
1061 err = brcmf_do_escan(cfg_priv, wiphy, ndev, request);
1062 if (!err)
1063 return err;
1064 else
1065 goto scan_out;
1066 } else {
1067 WL_SCAN("ssid \"%s\", ssid_len (%d)\n",
1068 ssids->ssid, ssids->ssid_len);
1069 memset(&sr->ssid_le, 0, sizeof(sr->ssid_le));
1070 SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len);
1071 sr->ssid_le.SSID_len = cpu_to_le32(0);
1072 spec_scan = false;
1073 if (SSID_len) {
1074 memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len);
1075 sr->ssid_le.SSID_len = cpu_to_le32(SSID_len);
1076 spec_scan = true;
1077 } else
1078 WL_SCAN("Broadcast scan\n");
1079
1080 passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
1081 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
1082 &passive_scan, sizeof(passive_scan));
1083 if (err) {
1084 WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
1085 goto scan_out;
1086 }
1087 brcmf_set_mpc(ndev, 0);
1088 err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le,
1089 sizeof(sr->ssid_le));
1090 if (err) {
1091 if (err == -EBUSY)
1092 WL_INFO("BUSY: scan for \"%s\" canceled\n",
1093 sr->ssid_le.SSID);
1094 else
1095 WL_ERR("WLC_SCAN error (%d)\n", err);
1096
1097 brcmf_set_mpc(ndev, 1);
1098 goto scan_out;
1099 }
1100 }
1101
1102 return 0;
1103
1104scan_out:
1105 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
1106 if (timer_pending(&cfg_priv->escan_timeout))
1107 del_timer_sync(&cfg_priv->escan_timeout);
1108 cfg_priv->scan_request = NULL;
1109 return err;
1110}
1111
5b435de0 1112static s32
fd014284 1113brcmf_cfg80211_scan(struct wiphy *wiphy,
5b435de0
AS
1114 struct cfg80211_scan_request *request)
1115{
fd014284 1116 struct net_device *ndev = request->wdev->netdev;
e756af5b 1117 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
5b435de0
AS
1118 s32 err = 0;
1119
1120 WL_TRACE("Enter\n");
1121
1122 if (!check_sys_up(wiphy))
1123 return -EIO;
1124
e756af5b
HM
1125 if (cfg_priv->iscan_on)
1126 err = brcmf_cfg80211_iscan(wiphy, ndev, request, NULL);
1127 else if (cfg_priv->escan_on)
1128 err = brcmf_cfg80211_escan(wiphy, ndev, request, NULL);
1129
5b435de0
AS
1130 if (err)
1131 WL_ERR("scan error (%d)\n", err);
1132
1133 WL_TRACE("Exit\n");
1134 return err;
1135}
1136
1137static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold)
1138{
1139 s32 err = 0;
1140
1141 err = brcmf_dev_intvar_set(ndev, "rtsthresh", rts_threshold);
1142 if (err)
1143 WL_ERR("Error (%d)\n", err);
1144
1145 return err;
1146}
1147
1148static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold)
1149{
1150 s32 err = 0;
1151
1152 err = brcmf_dev_intvar_set(ndev, "fragthresh", frag_threshold);
1153 if (err)
1154 WL_ERR("Error (%d)\n", err);
1155
1156 return err;
1157}
1158
1159static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l)
1160{
1161 s32 err = 0;
1162 u32 cmd = (l ? BRCM_SET_LRL : BRCM_SET_SRL);
1163
1164 err = brcmf_exec_dcmd_u32(ndev, cmd, &retry);
1165 if (err) {
1166 WL_ERR("cmd (%d) , error (%d)\n", cmd, err);
1167 return err;
1168 }
1169 return err;
1170}
1171
1172static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1173{
1174 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1175 struct net_device *ndev = cfg_to_ndev(cfg_priv);
1176 s32 err = 0;
1177
1178 WL_TRACE("Enter\n");
1179 if (!check_sys_up(wiphy))
1180 return -EIO;
1181
1182 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
1183 (cfg_priv->conf->rts_threshold != wiphy->rts_threshold)) {
1184 cfg_priv->conf->rts_threshold = wiphy->rts_threshold;
1185 err = brcmf_set_rts(ndev, cfg_priv->conf->rts_threshold);
1186 if (!err)
1187 goto done;
1188 }
1189 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
1190 (cfg_priv->conf->frag_threshold != wiphy->frag_threshold)) {
1191 cfg_priv->conf->frag_threshold = wiphy->frag_threshold;
1192 err = brcmf_set_frag(ndev, cfg_priv->conf->frag_threshold);
1193 if (!err)
1194 goto done;
1195 }
1196 if (changed & WIPHY_PARAM_RETRY_LONG
1197 && (cfg_priv->conf->retry_long != wiphy->retry_long)) {
1198 cfg_priv->conf->retry_long = wiphy->retry_long;
1199 err = brcmf_set_retry(ndev, cfg_priv->conf->retry_long, true);
1200 if (!err)
1201 goto done;
1202 }
1203 if (changed & WIPHY_PARAM_RETRY_SHORT
1204 && (cfg_priv->conf->retry_short != wiphy->retry_short)) {
1205 cfg_priv->conf->retry_short = wiphy->retry_short;
1206 err = brcmf_set_retry(ndev, cfg_priv->conf->retry_short, false);
1207 if (!err)
1208 goto done;
1209 }
1210
1211done:
1212 WL_TRACE("Exit\n");
1213 return err;
1214}
1215
1216static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item)
1217{
1218 switch (item) {
1219 case WL_PROF_SEC:
1220 return &cfg_priv->profile->sec;
1221 case WL_PROF_BSSID:
1222 return &cfg_priv->profile->bssid;
1223 case WL_PROF_SSID:
1224 return &cfg_priv->profile->ssid;
1225 }
1226 WL_ERR("invalid item (%d)\n", item);
1227 return NULL;
1228}
1229
1230static s32
1231brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv,
1232 const struct brcmf_event_msg *e, void *data, s32 item)
1233{
1234 s32 err = 0;
1235 struct brcmf_ssid *ssid;
1236
1237 switch (item) {
1238 case WL_PROF_SSID:
1239 ssid = (struct brcmf_ssid *) data;
1240 memset(cfg_priv->profile->ssid.SSID, 0,
1241 sizeof(cfg_priv->profile->ssid.SSID));
1242 memcpy(cfg_priv->profile->ssid.SSID,
1243 ssid->SSID, ssid->SSID_len);
1244 cfg_priv->profile->ssid.SSID_len = ssid->SSID_len;
1245 break;
1246 case WL_PROF_BSSID:
1247 if (data)
1248 memcpy(cfg_priv->profile->bssid, data, ETH_ALEN);
1249 else
1250 memset(cfg_priv->profile->bssid, 0, ETH_ALEN);
1251 break;
1252 case WL_PROF_SEC:
1253 memcpy(&cfg_priv->profile->sec, data,
1254 sizeof(cfg_priv->profile->sec));
1255 break;
1256 case WL_PROF_BEACONINT:
1257 cfg_priv->profile->beacon_interval = *(u16 *)data;
1258 break;
1259 case WL_PROF_DTIMPERIOD:
1260 cfg_priv->profile->dtim_period = *(u8 *)data;
1261 break;
1262 default:
1263 WL_ERR("unsupported item (%d)\n", item);
1264 err = -EOPNOTSUPP;
1265 break;
1266 }
1267
1268 return err;
1269}
1270
1271static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
1272{
1273 memset(prof, 0, sizeof(*prof));
1274}
1275
1276static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params,
1277 size_t *join_params_size)
1278{
1279 u16 chanspec = 0;
1280
1281 if (ch != 0) {
1282 if (ch <= CH_MAX_2G_CHANNEL)
1283 chanspec |= WL_CHANSPEC_BAND_2G;
1284 else
1285 chanspec |= WL_CHANSPEC_BAND_5G;
1286
1287 chanspec |= WL_CHANSPEC_BW_20;
1288 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
1289
1290 *join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE +
1291 sizeof(u16);
1292
1293 chanspec |= (ch & WL_CHANSPEC_CHAN_MASK);
1294 join_params->params_le.chanspec_list[0] = cpu_to_le16(chanspec);
1295 join_params->params_le.chanspec_num = cpu_to_le32(1);
1296
1297 WL_CONN("join_params->params.chanspec_list[0]= %#X,"
1298 "channel %d, chanspec %#X\n",
1299 chanspec, ch, chanspec);
1300 }
1301}
1302
1303static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv)
1304{
1305 struct net_device *ndev = NULL;
1306 s32 err = 0;
1307
1308 WL_TRACE("Enter\n");
1309
1310 if (cfg_priv->link_up) {
1311 ndev = cfg_to_ndev(cfg_priv);
1312 WL_INFO("Call WLC_DISASSOC to stop excess roaming\n ");
1313 err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, NULL, 0);
1314 if (err)
1315 WL_ERR("WLC_DISASSOC failed (%d)\n", err);
1316 cfg_priv->link_up = false;
1317 }
1318 WL_TRACE("Exit\n");
1319}
1320
1321static s32
1322brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
1323 struct cfg80211_ibss_params *params)
1324{
1325 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1326 struct brcmf_join_params join_params;
1327 size_t join_params_size = 0;
1328 s32 err = 0;
1329 s32 wsec = 0;
1330 s32 bcnprd;
1331 struct brcmf_ssid ssid;
1332
1333 WL_TRACE("Enter\n");
1334 if (!check_sys_up(wiphy))
1335 return -EIO;
1336
1337 if (params->ssid)
1338 WL_CONN("SSID: %s\n", params->ssid);
1339 else {
1340 WL_CONN("SSID: NULL, Not supported\n");
1341 return -EOPNOTSUPP;
1342 }
1343
1344 set_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
1345
1346 if (params->bssid)
040a7831 1347 WL_CONN("BSSID: %pM\n", params->bssid);
5b435de0
AS
1348 else
1349 WL_CONN("No BSSID specified\n");
1350
1351 if (params->channel)
1352 WL_CONN("channel: %d\n", params->channel->center_freq);
1353 else
1354 WL_CONN("no channel specified\n");
1355
1356 if (params->channel_fixed)
1357 WL_CONN("fixed channel required\n");
1358 else
1359 WL_CONN("no fixed channel required\n");
1360
1361 if (params->ie && params->ie_len)
1362 WL_CONN("ie len: %d\n", params->ie_len);
1363 else
1364 WL_CONN("no ie specified\n");
1365
1366 if (params->beacon_interval)
1367 WL_CONN("beacon interval: %d\n", params->beacon_interval);
1368 else
1369 WL_CONN("no beacon interval specified\n");
1370
1371 if (params->basic_rates)
1372 WL_CONN("basic rates: %08X\n", params->basic_rates);
1373 else
1374 WL_CONN("no basic rates specified\n");
1375
1376 if (params->privacy)
1377 WL_CONN("privacy required\n");
1378 else
1379 WL_CONN("no privacy required\n");
1380
1381 /* Configure Privacy for starter */
1382 if (params->privacy)
1383 wsec |= WEP_ENABLED;
1384
1385 err = brcmf_dev_intvar_set(ndev, "wsec", wsec);
1386 if (err) {
1387 WL_ERR("wsec failed (%d)\n", err);
1388 goto done;
1389 }
1390
1391 /* Configure Beacon Interval for starter */
1392 if (params->beacon_interval)
1393 bcnprd = params->beacon_interval;
1394 else
1395 bcnprd = 100;
1396
1397 err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_BCNPRD, &bcnprd);
1398 if (err) {
1399 WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err);
1400 goto done;
1401 }
1402
1403 /* Configure required join parameter */
1404 memset(&join_params, 0, sizeof(struct brcmf_join_params));
1405
1406 /* SSID */
1407 ssid.SSID_len = min_t(u32, params->ssid_len, 32);
1408 memcpy(ssid.SSID, params->ssid, ssid.SSID_len);
1409 memcpy(join_params.ssid_le.SSID, params->ssid, ssid.SSID_len);
1410 join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len);
1411 join_params_size = sizeof(join_params.ssid_le);
1412 brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID);
1413
1414 /* BSSID */
1415 if (params->bssid) {
1416 memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN);
1417 join_params_size = sizeof(join_params.ssid_le) +
1418 BRCMF_ASSOC_PARAMS_FIXED_SIZE;
1419 } else {
1420 memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN);
1421 }
1422
1423 brcmf_update_prof(cfg_priv, NULL,
1424 &join_params.params_le.bssid, WL_PROF_BSSID);
1425
1426 /* Channel */
1427 if (params->channel) {
1428 u32 target_channel;
1429
1430 cfg_priv->channel =
1431 ieee80211_frequency_to_channel(
1432 params->channel->center_freq);
1433 if (params->channel_fixed) {
1434 /* adding chanspec */
1435 brcmf_ch_to_chanspec(cfg_priv->channel,
1436 &join_params, &join_params_size);
1437 }
1438
1439 /* set channel for starter */
1440 target_channel = cfg_priv->channel;
1441 err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_CHANNEL,
1442 &target_channel);
1443 if (err) {
1444 WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err);
1445 goto done;
1446 }
1447 } else
1448 cfg_priv->channel = 0;
1449
1450 cfg_priv->ibss_starter = false;
1451
1452
1453 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID,
1454 &join_params, join_params_size);
1455 if (err) {
1456 WL_ERR("WLC_SET_SSID failed (%d)\n", err);
1457 goto done;
1458 }
1459
1460done:
1461 if (err)
1462 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
1463 WL_TRACE("Exit\n");
1464 return err;
1465}
1466
1467static s32
1468brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
1469{
1470 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1471 s32 err = 0;
1472
1473 WL_TRACE("Enter\n");
1474 if (!check_sys_up(wiphy))
1475 return -EIO;
1476
1477 brcmf_link_down(cfg_priv);
1478
1479 WL_TRACE("Exit\n");
1480
1481 return err;
1482}
1483
1484static s32 brcmf_set_wpa_version(struct net_device *ndev,
1485 struct cfg80211_connect_params *sme)
1486{
1487 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1488 struct brcmf_cfg80211_security *sec;
1489 s32 val = 0;
1490 s32 err = 0;
1491
1492 if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1493 val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
1494 else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1495 val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
1496 else
1497 val = WPA_AUTH_DISABLED;
1498 WL_CONN("setting wpa_auth to 0x%0x\n", val);
1499 err = brcmf_dev_intvar_set(ndev, "wpa_auth", val);
1500 if (err) {
1501 WL_ERR("set wpa_auth failed (%d)\n", err);
1502 return err;
1503 }
1504 sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1505 sec->wpa_versions = sme->crypto.wpa_versions;
1506 return err;
1507}
1508
1509static s32 brcmf_set_auth_type(struct net_device *ndev,
1510 struct cfg80211_connect_params *sme)
1511{
1512 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1513 struct brcmf_cfg80211_security *sec;
1514 s32 val = 0;
1515 s32 err = 0;
1516
1517 switch (sme->auth_type) {
1518 case NL80211_AUTHTYPE_OPEN_SYSTEM:
1519 val = 0;
1520 WL_CONN("open system\n");
1521 break;
1522 case NL80211_AUTHTYPE_SHARED_KEY:
1523 val = 1;
1524 WL_CONN("shared key\n");
1525 break;
1526 case NL80211_AUTHTYPE_AUTOMATIC:
1527 val = 2;
1528 WL_CONN("automatic\n");
1529 break;
1530 case NL80211_AUTHTYPE_NETWORK_EAP:
1531 WL_CONN("network eap\n");
1532 default:
1533 val = 2;
1534 WL_ERR("invalid auth type (%d)\n", sme->auth_type);
1535 break;
1536 }
1537
1538 err = brcmf_dev_intvar_set(ndev, "auth", val);
1539 if (err) {
1540 WL_ERR("set auth failed (%d)\n", err);
1541 return err;
1542 }
1543 sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1544 sec->auth_type = sme->auth_type;
1545 return err;
1546}
1547
1548static s32
1549brcmf_set_set_cipher(struct net_device *ndev,
1550 struct cfg80211_connect_params *sme)
1551{
1552 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1553 struct brcmf_cfg80211_security *sec;
1554 s32 pval = 0;
1555 s32 gval = 0;
1556 s32 err = 0;
1557
1558 if (sme->crypto.n_ciphers_pairwise) {
1559 switch (sme->crypto.ciphers_pairwise[0]) {
1560 case WLAN_CIPHER_SUITE_WEP40:
1561 case WLAN_CIPHER_SUITE_WEP104:
1562 pval = WEP_ENABLED;
1563 break;
1564 case WLAN_CIPHER_SUITE_TKIP:
1565 pval = TKIP_ENABLED;
1566 break;
1567 case WLAN_CIPHER_SUITE_CCMP:
1568 pval = AES_ENABLED;
1569 break;
1570 case WLAN_CIPHER_SUITE_AES_CMAC:
1571 pval = AES_ENABLED;
1572 break;
1573 default:
1574 WL_ERR("invalid cipher pairwise (%d)\n",
1575 sme->crypto.ciphers_pairwise[0]);
1576 return -EINVAL;
1577 }
1578 }
1579 if (sme->crypto.cipher_group) {
1580 switch (sme->crypto.cipher_group) {
1581 case WLAN_CIPHER_SUITE_WEP40:
1582 case WLAN_CIPHER_SUITE_WEP104:
1583 gval = WEP_ENABLED;
1584 break;
1585 case WLAN_CIPHER_SUITE_TKIP:
1586 gval = TKIP_ENABLED;
1587 break;
1588 case WLAN_CIPHER_SUITE_CCMP:
1589 gval = AES_ENABLED;
1590 break;
1591 case WLAN_CIPHER_SUITE_AES_CMAC:
1592 gval = AES_ENABLED;
1593 break;
1594 default:
1595 WL_ERR("invalid cipher group (%d)\n",
1596 sme->crypto.cipher_group);
1597 return -EINVAL;
1598 }
1599 }
1600
1601 WL_CONN("pval (%d) gval (%d)\n", pval, gval);
1602 err = brcmf_dev_intvar_set(ndev, "wsec", pval | gval);
1603 if (err) {
1604 WL_ERR("error (%d)\n", err);
1605 return err;
1606 }
1607
1608 sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1609 sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
1610 sec->cipher_group = sme->crypto.cipher_group;
1611
1612 return err;
1613}
1614
1615static s32
1616brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
1617{
1618 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1619 struct brcmf_cfg80211_security *sec;
1620 s32 val = 0;
1621 s32 err = 0;
1622
1623 if (sme->crypto.n_akm_suites) {
1624 err = brcmf_dev_intvar_get(ndev, "wpa_auth", &val);
1625 if (err) {
1626 WL_ERR("could not get wpa_auth (%d)\n", err);
1627 return err;
1628 }
1629 if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
1630 switch (sme->crypto.akm_suites[0]) {
1631 case WLAN_AKM_SUITE_8021X:
1632 val = WPA_AUTH_UNSPECIFIED;
1633 break;
1634 case WLAN_AKM_SUITE_PSK:
1635 val = WPA_AUTH_PSK;
1636 break;
1637 default:
1638 WL_ERR("invalid cipher group (%d)\n",
1639 sme->crypto.cipher_group);
1640 return -EINVAL;
1641 }
1642 } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
1643 switch (sme->crypto.akm_suites[0]) {
1644 case WLAN_AKM_SUITE_8021X:
1645 val = WPA2_AUTH_UNSPECIFIED;
1646 break;
1647 case WLAN_AKM_SUITE_PSK:
1648 val = WPA2_AUTH_PSK;
1649 break;
1650 default:
1651 WL_ERR("invalid cipher group (%d)\n",
1652 sme->crypto.cipher_group);
1653 return -EINVAL;
1654 }
1655 }
1656
1657 WL_CONN("setting wpa_auth to %d\n", val);
1658 err = brcmf_dev_intvar_set(ndev, "wpa_auth", val);
1659 if (err) {
1660 WL_ERR("could not set wpa_auth (%d)\n", err);
1661 return err;
1662 }
1663 }
1664 sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1665 sec->wpa_auth = sme->crypto.akm_suites[0];
1666
1667 return err;
1668}
1669
1670static s32
f09d0c02
HM
1671brcmf_set_sharedkey(struct net_device *ndev,
1672 struct cfg80211_connect_params *sme)
5b435de0
AS
1673{
1674 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1675 struct brcmf_cfg80211_security *sec;
1676 struct brcmf_wsec_key key;
1677 s32 val;
1678 s32 err = 0;
f09d0c02 1679 s32 bssidx;
5b435de0
AS
1680
1681 WL_CONN("key len (%d)\n", sme->key_len);
5b435de0 1682
a718e2fe
RV
1683 if (sme->key_len == 0)
1684 return 0;
1685
1686 sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1687 WL_CONN("wpa_versions 0x%x cipher_pairwise 0x%x\n",
1688 sec->wpa_versions, sec->cipher_pairwise);
1689
1690 if (sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))
1691 return 0;
1692
f09d0c02
HM
1693 if (!(sec->cipher_pairwise &
1694 (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104)))
1695 return 0;
a718e2fe 1696
f09d0c02
HM
1697 memset(&key, 0, sizeof(key));
1698 key.len = (u32) sme->key_len;
1699 key.index = (u32) sme->key_idx;
1700 if (key.len > sizeof(key.data)) {
1701 WL_ERR("Too long key length (%u)\n", key.len);
1702 return -EINVAL;
1703 }
1704 memcpy(key.data, sme->key, key.len);
1705 key.flags = BRCMF_PRIMARY_KEY;
1706 switch (sec->cipher_pairwise) {
1707 case WLAN_CIPHER_SUITE_WEP40:
1708 key.algo = CRYPTO_ALGO_WEP1;
1709 break;
1710 case WLAN_CIPHER_SUITE_WEP104:
1711 key.algo = CRYPTO_ALGO_WEP128;
1712 break;
1713 default:
1714 WL_ERR("Invalid algorithm (%d)\n",
1715 sme->crypto.ciphers_pairwise[0]);
1716 return -EINVAL;
1717 }
1718 /* Set the new key/index */
1719 WL_CONN("key length (%d) key index (%d) algo (%d)\n",
1720 key.len, key.index, key.algo);
1721 WL_CONN("key \"%s\"\n", key.data);
1722 bssidx = brcmf_find_bssidx(cfg_priv, ndev);
1723 err = send_key_to_dongle(cfg_priv, bssidx, ndev, &key);
1724 if (err)
1725 return err;
1726
1727 if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
1728 WL_CONN("set auth_type to shared key\n");
1729 val = WL_AUTH_SHARED_KEY; /* shared key */
1730 err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", val, bssidx);
1731 if (err)
1732 WL_ERR("set auth failed (%d)\n", err);
5b435de0
AS
1733 }
1734 return err;
1735}
1736
1737static s32
1738brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
1739 struct cfg80211_connect_params *sme)
1740{
1741 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1742 struct ieee80211_channel *chan = sme->channel;
1743 struct brcmf_join_params join_params;
1744 size_t join_params_size;
1745 struct brcmf_ssid ssid;
1746
1747 s32 err = 0;
1748
1749 WL_TRACE("Enter\n");
1750 if (!check_sys_up(wiphy))
1751 return -EIO;
1752
1753 if (!sme->ssid) {
1754 WL_ERR("Invalid ssid\n");
1755 return -EOPNOTSUPP;
1756 }
1757
1758 set_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
1759
1760 if (chan) {
1761 cfg_priv->channel =
1762 ieee80211_frequency_to_channel(chan->center_freq);
1763 WL_CONN("channel (%d), center_req (%d)\n",
1764 cfg_priv->channel, chan->center_freq);
1765 } else
1766 cfg_priv->channel = 0;
1767
1768 WL_INFO("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);
1769
1770 err = brcmf_set_wpa_version(ndev, sme);
1771 if (err) {
1772 WL_ERR("wl_set_wpa_version failed (%d)\n", err);
1773 goto done;
1774 }
1775
1776 err = brcmf_set_auth_type(ndev, sme);
1777 if (err) {
1778 WL_ERR("wl_set_auth_type failed (%d)\n", err);
1779 goto done;
1780 }
1781
1782 err = brcmf_set_set_cipher(ndev, sme);
1783 if (err) {
1784 WL_ERR("wl_set_set_cipher failed (%d)\n", err);
1785 goto done;
1786 }
1787
1788 err = brcmf_set_key_mgmt(ndev, sme);
1789 if (err) {
1790 WL_ERR("wl_set_key_mgmt failed (%d)\n", err);
1791 goto done;
1792 }
1793
f09d0c02 1794 err = brcmf_set_sharedkey(ndev, sme);
5b435de0 1795 if (err) {
f09d0c02 1796 WL_ERR("brcmf_set_sharedkey failed (%d)\n", err);
5b435de0
AS
1797 goto done;
1798 }
1799
1800 memset(&join_params, 0, sizeof(join_params));
1801 join_params_size = sizeof(join_params.ssid_le);
1802
2315992c 1803 ssid.SSID_len = min_t(u32, sizeof(ssid.SSID), (u32)sme->ssid_len);
5b435de0
AS
1804 memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid.SSID_len);
1805 memcpy(&ssid.SSID, sme->ssid, ssid.SSID_len);
1806 join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len);
1807 brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID);
1808
1809 memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN);
1810
1811 if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN)
1812 WL_CONN("ssid \"%s\", len (%d)\n",
1813 ssid.SSID, ssid.SSID_len);
1814
1815 brcmf_ch_to_chanspec(cfg_priv->channel,
1816 &join_params, &join_params_size);
1817 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID,
1818 &join_params, join_params_size);
1819 if (err)
1820 WL_ERR("WLC_SET_SSID failed (%d)\n", err);
1821
1822done:
1823 if (err)
1824 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
1825 WL_TRACE("Exit\n");
1826 return err;
1827}
1828
1829static s32
1830brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,
1831 u16 reason_code)
1832{
1833 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1834 struct brcmf_scb_val_le scbval;
1835 s32 err = 0;
1836
1837 WL_TRACE("Enter. Reason code = %d\n", reason_code);
1838 if (!check_sys_up(wiphy))
1839 return -EIO;
1840
1841 clear_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
1842
1843 memcpy(&scbval.ea, brcmf_read_prof(cfg_priv, WL_PROF_BSSID), ETH_ALEN);
1844 scbval.val = cpu_to_le32(reason_code);
1845 err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, &scbval,
1846 sizeof(struct brcmf_scb_val_le));
1847 if (err)
1848 WL_ERR("error (%d)\n", err);
1849
1850 cfg_priv->link_up = false;
1851
1852 WL_TRACE("Exit\n");
1853 return err;
1854}
1855
1856static s32
1857brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
d3f31134 1858 enum nl80211_tx_power_setting type, s32 mbm)
5b435de0
AS
1859{
1860
1861 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1862 struct net_device *ndev = cfg_to_ndev(cfg_priv);
1863 u16 txpwrmw;
1864 s32 err = 0;
1865 s32 disable = 0;
d3f31134 1866 s32 dbm = MBM_TO_DBM(mbm);
5b435de0
AS
1867
1868 WL_TRACE("Enter\n");
1869 if (!check_sys_up(wiphy))
1870 return -EIO;
1871
1872 switch (type) {
1873 case NL80211_TX_POWER_AUTOMATIC:
1874 break;
1875 case NL80211_TX_POWER_LIMITED:
5b435de0
AS
1876 case NL80211_TX_POWER_FIXED:
1877 if (dbm < 0) {
1878 WL_ERR("TX_POWER_FIXED - dbm is negative\n");
1879 err = -EINVAL;
1880 goto done;
1881 }
1882 break;
1883 }
1884 /* Make sure radio is off or on as far as software is concerned */
1885 disable = WL_RADIO_SW_DISABLE << 16;
1886 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_RADIO, &disable);
1887 if (err)
1888 WL_ERR("WLC_SET_RADIO error (%d)\n", err);
1889
1890 if (dbm > 0xffff)
1891 txpwrmw = 0xffff;
1892 else
1893 txpwrmw = (u16) dbm;
1894 err = brcmf_dev_intvar_set(ndev, "qtxpower",
ef6ac17a 1895 (s32) (brcmf_mw_to_qdbm(txpwrmw)));
5b435de0
AS
1896 if (err)
1897 WL_ERR("qtxpower error (%d)\n", err);
1898 cfg_priv->conf->tx_power = dbm;
1899
1900done:
1901 WL_TRACE("Exit\n");
1902 return err;
1903}
1904
1905static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
1906{
1907 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1908 struct net_device *ndev = cfg_to_ndev(cfg_priv);
1909 s32 txpwrdbm;
1910 u8 result;
1911 s32 err = 0;
1912
1913 WL_TRACE("Enter\n");
1914 if (!check_sys_up(wiphy))
1915 return -EIO;
1916
1917 err = brcmf_dev_intvar_get(ndev, "qtxpower", &txpwrdbm);
1918 if (err) {
1919 WL_ERR("error (%d)\n", err);
1920 goto done;
1921 }
1922
1923 result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
ef6ac17a 1924 *dbm = (s32) brcmf_qdbm_to_mw(result);
5b435de0
AS
1925
1926done:
1927 WL_TRACE("Exit\n");
1928 return err;
1929}
1930
1931static s32
1932brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
1933 u8 key_idx, bool unicast, bool multicast)
1934{
f09d0c02 1935 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
5b435de0
AS
1936 u32 index;
1937 u32 wsec;
1938 s32 err = 0;
f09d0c02 1939 s32 bssidx;
5b435de0
AS
1940
1941 WL_TRACE("Enter\n");
1942 WL_CONN("key index (%d)\n", key_idx);
1943 if (!check_sys_up(wiphy))
1944 return -EIO;
1945
f09d0c02
HM
1946 bssidx = brcmf_find_bssidx(cfg_priv, ndev);
1947 err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx);
5b435de0
AS
1948 if (err) {
1949 WL_ERR("WLC_GET_WSEC error (%d)\n", err);
1950 goto done;
1951 }
1952
1953 if (wsec & WEP_ENABLED) {
1954 /* Just select a new current key */
1955 index = key_idx;
1956 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_KEY_PRIMARY,
1957 &index);
1958 if (err)
1959 WL_ERR("error (%d)\n", err);
1960 }
1961done:
1962 WL_TRACE("Exit\n");
1963 return err;
1964}
1965
1966static s32
1967brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
1968 u8 key_idx, const u8 *mac_addr, struct key_params *params)
1969{
f09d0c02 1970 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
5b435de0
AS
1971 struct brcmf_wsec_key key;
1972 struct brcmf_wsec_key_le key_le;
1973 s32 err = 0;
f09d0c02 1974 s32 bssidx;
5b435de0
AS
1975
1976 memset(&key, 0, sizeof(key));
1977 key.index = (u32) key_idx;
1978 /* Instead of bcast for ea address for default wep keys,
1979 driver needs it to be Null */
1980 if (!is_multicast_ether_addr(mac_addr))
1981 memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN);
1982 key.len = (u32) params->key_len;
f09d0c02 1983 bssidx = brcmf_find_bssidx(cfg_priv, ndev);
5b435de0
AS
1984 /* check for key index change */
1985 if (key.len == 0) {
1986 /* key delete */
f09d0c02 1987 err = send_key_to_dongle(cfg_priv, bssidx, ndev, &key);
5b435de0 1988 if (err)
f09d0c02 1989 WL_ERR("key delete error (%d)\n", err);
5b435de0
AS
1990 } else {
1991 if (key.len > sizeof(key.data)) {
1992 WL_ERR("Invalid key length (%d)\n", key.len);
1993 return -EINVAL;
1994 }
1995
1996 WL_CONN("Setting the key index %d\n", key.index);
1997 memcpy(key.data, params->key, key.len);
1998
1999 if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
2000 u8 keybuf[8];
2001 memcpy(keybuf, &key.data[24], sizeof(keybuf));
2002 memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
2003 memcpy(&key.data[16], keybuf, sizeof(keybuf));
2004 }
2005
2006 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
2007 if (params->seq && params->seq_len == 6) {
2008 /* rx iv */
2009 u8 *ivptr;
2010 ivptr = (u8 *) params->seq;
2011 key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
2012 (ivptr[3] << 8) | ivptr[2];
2013 key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
2014 key.iv_initialized = true;
2015 }
2016
2017 switch (params->cipher) {
2018 case WLAN_CIPHER_SUITE_WEP40:
2019 key.algo = CRYPTO_ALGO_WEP1;
2020 WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
2021 break;
2022 case WLAN_CIPHER_SUITE_WEP104:
2023 key.algo = CRYPTO_ALGO_WEP128;
2024 WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
2025 break;
2026 case WLAN_CIPHER_SUITE_TKIP:
2027 key.algo = CRYPTO_ALGO_TKIP;
2028 WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
2029 break;
2030 case WLAN_CIPHER_SUITE_AES_CMAC:
2031 key.algo = CRYPTO_ALGO_AES_CCM;
2032 WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
2033 break;
2034 case WLAN_CIPHER_SUITE_CCMP:
2035 key.algo = CRYPTO_ALGO_AES_CCM;
2036 WL_CONN("WLAN_CIPHER_SUITE_CCMP\n");
2037 break;
2038 default:
2039 WL_ERR("Invalid cipher (0x%x)\n", params->cipher);
2040 return -EINVAL;
2041 }
2042 convert_key_from_CPU(&key, &key_le);
2043
2044 brcmf_netdev_wait_pend8021x(ndev);
f09d0c02
HM
2045 err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "wsec_key", &key_le,
2046 sizeof(key_le),
2047 cfg_priv->extra_buf,
2048 WL_EXTRA_BUF_MAX, bssidx);
2049 if (err)
2050 WL_ERR("wsec_key error (%d)\n", err);
5b435de0
AS
2051 }
2052 return err;
2053}
2054
2055static s32
2056brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
2057 u8 key_idx, bool pairwise, const u8 *mac_addr,
2058 struct key_params *params)
2059{
f09d0c02 2060 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
5b435de0
AS
2061 struct brcmf_wsec_key key;
2062 s32 val;
2063 s32 wsec;
2064 s32 err = 0;
2065 u8 keybuf[8];
f09d0c02 2066 s32 bssidx;
5b435de0
AS
2067
2068 WL_TRACE("Enter\n");
2069 WL_CONN("key index (%d)\n", key_idx);
2070 if (!check_sys_up(wiphy))
2071 return -EIO;
2072
2073 if (mac_addr) {
2074 WL_TRACE("Exit");
2075 return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params);
2076 }
2077 memset(&key, 0, sizeof(key));
2078
2079 key.len = (u32) params->key_len;
2080 key.index = (u32) key_idx;
2081
2082 if (key.len > sizeof(key.data)) {
2083 WL_ERR("Too long key length (%u)\n", key.len);
2084 err = -EINVAL;
2085 goto done;
2086 }
2087 memcpy(key.data, params->key, key.len);
2088
2089 key.flags = BRCMF_PRIMARY_KEY;
2090 switch (params->cipher) {
2091 case WLAN_CIPHER_SUITE_WEP40:
2092 key.algo = CRYPTO_ALGO_WEP1;
f09d0c02 2093 val = WEP_ENABLED;
5b435de0
AS
2094 WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
2095 break;
2096 case WLAN_CIPHER_SUITE_WEP104:
2097 key.algo = CRYPTO_ALGO_WEP128;
f09d0c02 2098 val = WEP_ENABLED;
5b435de0
AS
2099 WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
2100 break;
2101 case WLAN_CIPHER_SUITE_TKIP:
2102 memcpy(keybuf, &key.data[24], sizeof(keybuf));
2103 memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
2104 memcpy(&key.data[16], keybuf, sizeof(keybuf));
2105 key.algo = CRYPTO_ALGO_TKIP;
f09d0c02 2106 val = TKIP_ENABLED;
5b435de0
AS
2107 WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
2108 break;
2109 case WLAN_CIPHER_SUITE_AES_CMAC:
2110 key.algo = CRYPTO_ALGO_AES_CCM;
f09d0c02 2111 val = AES_ENABLED;
5b435de0
AS
2112 WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
2113 break;
2114 case WLAN_CIPHER_SUITE_CCMP:
2115 key.algo = CRYPTO_ALGO_AES_CCM;
f09d0c02 2116 val = AES_ENABLED;
5b435de0
AS
2117 WL_CONN("WLAN_CIPHER_SUITE_CCMP\n");
2118 break;
2119 default:
2120 WL_ERR("Invalid cipher (0x%x)\n", params->cipher);
2121 err = -EINVAL;
2122 goto done;
2123 }
2124
f09d0c02
HM
2125 bssidx = brcmf_find_bssidx(cfg_priv, ndev);
2126 err = send_key_to_dongle(cfg_priv, bssidx, ndev, &key);
5b435de0
AS
2127 if (err)
2128 goto done;
2129
f09d0c02 2130 err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx);
5b435de0
AS
2131 if (err) {
2132 WL_ERR("get wsec error (%d)\n", err);
2133 goto done;
2134 }
5b435de0 2135 wsec |= val;
f09d0c02 2136 err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", wsec, bssidx);
5b435de0
AS
2137 if (err) {
2138 WL_ERR("set wsec error (%d)\n", err);
2139 goto done;
2140 }
2141
5b435de0
AS
2142done:
2143 WL_TRACE("Exit\n");
2144 return err;
2145}
2146
2147static s32
2148brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
2149 u8 key_idx, bool pairwise, const u8 *mac_addr)
2150{
f09d0c02 2151 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
5b435de0
AS
2152 struct brcmf_wsec_key key;
2153 s32 err = 0;
f09d0c02 2154 s32 bssidx;
5b435de0
AS
2155
2156 WL_TRACE("Enter\n");
2157 if (!check_sys_up(wiphy))
2158 return -EIO;
2159
2160 memset(&key, 0, sizeof(key));
2161
2162 key.index = (u32) key_idx;
2163 key.flags = BRCMF_PRIMARY_KEY;
2164 key.algo = CRYPTO_ALGO_OFF;
2165
2166 WL_CONN("key index (%d)\n", key_idx);
2167
2168 /* Set the new key/index */
f09d0c02
HM
2169 bssidx = brcmf_find_bssidx(cfg_priv, ndev);
2170 err = send_key_to_dongle(cfg_priv, bssidx, ndev, &key);
5b435de0
AS
2171 if (err) {
2172 if (err == -EINVAL) {
2173 if (key.index >= DOT11_MAX_DEFAULT_KEYS)
2174 /* we ignore this key index in this case */
2175 WL_ERR("invalid key index (%d)\n", key_idx);
2176 }
2177 /* Ignore this error, may happen during DISASSOC */
2178 err = -EAGAIN;
5b435de0
AS
2179 }
2180
5b435de0
AS
2181 WL_TRACE("Exit\n");
2182 return err;
2183}
2184
2185static s32
2186brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
2187 u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
2188 void (*callback) (void *cookie, struct key_params * params))
2189{
2190 struct key_params params;
2191 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2192 struct brcmf_cfg80211_security *sec;
2193 s32 wsec;
2194 s32 err = 0;
f09d0c02 2195 s32 bssidx;
5b435de0
AS
2196
2197 WL_TRACE("Enter\n");
2198 WL_CONN("key index (%d)\n", key_idx);
2199 if (!check_sys_up(wiphy))
2200 return -EIO;
2201
2202 memset(&params, 0, sizeof(params));
2203
f09d0c02
HM
2204 bssidx = brcmf_find_bssidx(cfg_priv, ndev);
2205 err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx);
5b435de0
AS
2206 if (err) {
2207 WL_ERR("WLC_GET_WSEC error (%d)\n", err);
2208 /* Ignore this error, may happen during DISASSOC */
2209 err = -EAGAIN;
2210 goto done;
2211 }
f09d0c02 2212 switch (wsec & ~SES_OW_ENABLED) {
5b435de0
AS
2213 case WEP_ENABLED:
2214 sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
2215 if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
2216 params.cipher = WLAN_CIPHER_SUITE_WEP40;
2217 WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
2218 } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
2219 params.cipher = WLAN_CIPHER_SUITE_WEP104;
2220 WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
2221 }
2222 break;
2223 case TKIP_ENABLED:
2224 params.cipher = WLAN_CIPHER_SUITE_TKIP;
2225 WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
2226 break;
2227 case AES_ENABLED:
2228 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
2229 WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
2230 break;
2231 default:
2232 WL_ERR("Invalid algo (0x%x)\n", wsec);
2233 err = -EINVAL;
2234 goto done;
2235 }
2236 callback(cookie, &params);
2237
2238done:
2239 WL_TRACE("Exit\n");
2240 return err;
2241}
2242
2243static s32
2244brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
2245 struct net_device *ndev, u8 key_idx)
2246{
2247 WL_INFO("Not supported\n");
2248
2249 return -EOPNOTSUPP;
2250}
2251
2252static s32
2253brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
2254 u8 *mac, struct station_info *sinfo)
2255{
2256 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2257 struct brcmf_scb_val_le scb_val;
2258 int rssi;
2259 s32 rate;
2260 s32 err = 0;
2261 u8 *bssid = brcmf_read_prof(cfg_priv, WL_PROF_BSSID);
2262
2263 WL_TRACE("Enter\n");
2264 if (!check_sys_up(wiphy))
2265 return -EIO;
2266
2267 if (memcmp(mac, bssid, ETH_ALEN)) {
2268 WL_ERR("Wrong Mac address cfg_mac-%X:%X:%X:%X:%X:%X"
2269 "wl_bssid-%X:%X:%X:%X:%X:%X\n",
2270 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
2271 bssid[0], bssid[1], bssid[2], bssid[3],
2272 bssid[4], bssid[5]);
2273 err = -ENOENT;
2274 goto done;
2275 }
2276
2277 /* Report the current tx rate */
2278 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_RATE, &rate);
2279 if (err) {
2280 WL_ERR("Could not get rate (%d)\n", err);
2281 } else {
2282 sinfo->filled |= STATION_INFO_TX_BITRATE;
2283 sinfo->txrate.legacy = rate * 5;
2284 WL_CONN("Rate %d Mbps\n", rate / 2);
2285 }
2286
2287 if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) {
7f6c562d 2288 memset(&scb_val, 0, sizeof(scb_val));
5b435de0
AS
2289 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val,
2290 sizeof(struct brcmf_scb_val_le));
7f6c562d 2291 if (err) {
5b435de0 2292 WL_ERR("Could not get rssi (%d)\n", err);
7f6c562d
HM
2293 } else {
2294 rssi = le32_to_cpu(scb_val.val);
2295 sinfo->filled |= STATION_INFO_SIGNAL;
2296 sinfo->signal = rssi;
2297 WL_CONN("RSSI %d dBm\n", rssi);
2298 }
5b435de0
AS
2299 }
2300
2301done:
2302 WL_TRACE("Exit\n");
2303 return err;
2304}
2305
2306static s32
2307brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
2308 bool enabled, s32 timeout)
2309{
2310 s32 pm;
2311 s32 err = 0;
2312 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2313
2314 WL_TRACE("Enter\n");
2315
2316 /*
2317 * Powersave enable/disable request is coming from the
2318 * cfg80211 even before the interface is up. In that
2319 * scenario, driver will be storing the power save
2320 * preference in cfg_priv struct to apply this to
2321 * FW later while initializing the dongle
2322 */
2323 cfg_priv->pwr_save = enabled;
2324 if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) {
2325
2326 WL_INFO("Device is not ready,"
2327 "storing the value in cfg_priv struct\n");
2328 goto done;
2329 }
2330
2331 pm = enabled ? PM_FAST : PM_OFF;
2332 WL_INFO("power save %s\n", (pm ? "enabled" : "disabled"));
2333
2334 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &pm);
2335 if (err) {
2336 if (err == -ENODEV)
2337 WL_ERR("net_device is not ready yet\n");
2338 else
2339 WL_ERR("error (%d)\n", err);
2340 }
2341done:
2342 WL_TRACE("Exit\n");
2343 return err;
2344}
2345
2346static s32
2347brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev,
2348 const u8 *addr,
2349 const struct cfg80211_bitrate_mask *mask)
2350{
2351 struct brcm_rateset_le rateset_le;
2352 s32 rate;
2353 s32 val;
2354 s32 err_bg;
2355 s32 err_a;
2356 u32 legacy;
2357 s32 err = 0;
2358
2359 WL_TRACE("Enter\n");
2360 if (!check_sys_up(wiphy))
2361 return -EIO;
2362
2363 /* addr param is always NULL. ignore it */
2364 /* Get current rateset */
2365 err = brcmf_exec_dcmd(ndev, BRCM_GET_CURR_RATESET, &rateset_le,
2366 sizeof(rateset_le));
2367 if (err) {
2368 WL_ERR("could not get current rateset (%d)\n", err);
2369 goto done;
2370 }
2371
2372 legacy = ffs(mask->control[IEEE80211_BAND_2GHZ].legacy & 0xFFFF);
2373 if (!legacy)
2374 legacy = ffs(mask->control[IEEE80211_BAND_5GHZ].legacy &
2375 0xFFFF);
2376
2377 val = wl_g_rates[legacy - 1].bitrate * 100000;
2378
2379 if (val < le32_to_cpu(rateset_le.count))
2380 /* Select rate by rateset index */
2381 rate = rateset_le.rates[val] & 0x7f;
2382 else
2383 /* Specified rate in bps */
2384 rate = val / 500000;
2385
2386 WL_CONN("rate %d mbps\n", rate / 2);
2387
2388 /*
2389 *
2390 * Set rate override,
2391 * Since the is a/b/g-blind, both a/bg_rate are enforced.
2392 */
2393 err_bg = brcmf_dev_intvar_set(ndev, "bg_rate", rate);
2394 err_a = brcmf_dev_intvar_set(ndev, "a_rate", rate);
2395 if (err_bg && err_a) {
2396 WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a);
2397 err = err_bg | err_a;
2398 }
2399
2400done:
2401 WL_TRACE("Exit\n");
2402 return err;
2403}
2404
2405static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
d34bf64f 2406 struct brcmf_bss_info_le *bi)
5b435de0
AS
2407{
2408 struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
2409 struct ieee80211_channel *notify_channel;
2410 struct cfg80211_bss *bss;
2411 struct ieee80211_supported_band *band;
2412 s32 err = 0;
2413 u16 channel;
2414 u32 freq;
5b435de0
AS
2415 u16 notify_capability;
2416 u16 notify_interval;
2417 u8 *notify_ie;
2418 size_t notify_ielen;
2419 s32 notify_signal;
2420
2421 if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) {
2422 WL_ERR("Bss info is larger than buffer. Discarding\n");
2423 return 0;
2424 }
2425
2426 channel = bi->ctl_ch ? bi->ctl_ch :
2427 CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
2428
2429 if (channel <= CH_MAX_2G_CHANNEL)
2430 band = wiphy->bands[IEEE80211_BAND_2GHZ];
2431 else
2432 band = wiphy->bands[IEEE80211_BAND_5GHZ];
2433
2434 freq = ieee80211_channel_to_frequency(channel, band->band);
2435 notify_channel = ieee80211_get_channel(wiphy, freq);
2436
5b435de0
AS
2437 notify_capability = le16_to_cpu(bi->capability);
2438 notify_interval = le16_to_cpu(bi->beacon_period);
2439 notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
2440 notify_ielen = le32_to_cpu(bi->ie_length);
2441 notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
2442
2443 WL_CONN("bssid: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
2444 bi->BSSID[0], bi->BSSID[1], bi->BSSID[2],
2445 bi->BSSID[3], bi->BSSID[4], bi->BSSID[5]);
2446 WL_CONN("Channel: %d(%d)\n", channel, freq);
2447 WL_CONN("Capability: %X\n", notify_capability);
2448 WL_CONN("Beacon interval: %d\n", notify_interval);
2449 WL_CONN("Signal: %d\n", notify_signal);
5b435de0
AS
2450
2451 bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID,
8e6cffb3 2452 0, notify_capability, notify_interval, notify_ie,
5b435de0
AS
2453 notify_ielen, notify_signal, GFP_KERNEL);
2454
e78946e1
FL
2455 if (!bss)
2456 return -ENOMEM;
2457
2458 cfg80211_put_bss(bss);
5b435de0
AS
2459
2460 return err;
2461}
2462
6f09be0a
RV
2463static struct brcmf_bss_info_le *
2464next_bss_le(struct brcmf_scan_results *list, struct brcmf_bss_info_le *bss)
2465{
2466 if (bss == NULL)
2467 return list->bss_info_le;
2468 return (struct brcmf_bss_info_le *)((unsigned long)bss +
2469 le32_to_cpu(bss->length));
2470}
2471
5b435de0
AS
2472static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv)
2473{
2474 struct brcmf_scan_results *bss_list;
d34bf64f 2475 struct brcmf_bss_info_le *bi = NULL; /* must be initialized */
5b435de0
AS
2476 s32 err = 0;
2477 int i;
2478
2479 bss_list = cfg_priv->bss_list;
2480 if (bss_list->version != BRCMF_BSS_INFO_VERSION) {
2481 WL_ERR("Version %d != WL_BSS_INFO_VERSION\n",
2482 bss_list->version);
2483 return -EOPNOTSUPP;
2484 }
2485 WL_SCAN("scanned AP count (%d)\n", bss_list->count);
2486 for (i = 0; i < bss_list->count && i < WL_AP_MAX; i++) {
6f09be0a 2487 bi = next_bss_le(bss_list, bi);
5b435de0
AS
2488 err = brcmf_inform_single_bss(cfg_priv, bi);
2489 if (err)
2490 break;
2491 }
2492 return err;
2493}
2494
2495static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
2496 struct net_device *ndev, const u8 *bssid)
2497{
2498 struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
2499 struct ieee80211_channel *notify_channel;
d34bf64f 2500 struct brcmf_bss_info_le *bi = NULL;
5b435de0 2501 struct ieee80211_supported_band *band;
e78946e1 2502 struct cfg80211_bss *bss;
5b435de0
AS
2503 u8 *buf = NULL;
2504 s32 err = 0;
2505 u16 channel;
2506 u32 freq;
5b435de0
AS
2507 u16 notify_capability;
2508 u16 notify_interval;
2509 u8 *notify_ie;
2510 size_t notify_ielen;
2511 s32 notify_signal;
2512
2513 WL_TRACE("Enter\n");
2514
2515 buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
2516 if (buf == NULL) {
2517 err = -ENOMEM;
2518 goto CleanUp;
2519 }
2520
2521 *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
2522
2523 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
2524 if (err) {
2525 WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err);
2526 goto CleanUp;
2527 }
2528
d34bf64f 2529 bi = (struct brcmf_bss_info_le *)(buf + 4);
5b435de0
AS
2530
2531 channel = bi->ctl_ch ? bi->ctl_ch :
2532 CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
2533
2534 if (channel <= CH_MAX_2G_CHANNEL)
2535 band = wiphy->bands[IEEE80211_BAND_2GHZ];
2536 else
2537 band = wiphy->bands[IEEE80211_BAND_5GHZ];
2538
2539 freq = ieee80211_channel_to_frequency(channel, band->band);
2540 notify_channel = ieee80211_get_channel(wiphy, freq);
2541
5b435de0
AS
2542 notify_capability = le16_to_cpu(bi->capability);
2543 notify_interval = le16_to_cpu(bi->beacon_period);
2544 notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
2545 notify_ielen = le32_to_cpu(bi->ie_length);
2546 notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
2547
2548 WL_CONN("channel: %d(%d)\n", channel, freq);
2549 WL_CONN("capability: %X\n", notify_capability);
2550 WL_CONN("beacon interval: %d\n", notify_interval);
2551 WL_CONN("signal: %d\n", notify_signal);
5b435de0 2552
e78946e1 2553 bss = cfg80211_inform_bss(wiphy, notify_channel, bssid,
8e6cffb3 2554 0, notify_capability, notify_interval,
5b435de0
AS
2555 notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
2556
e78946e1
FL
2557 if (!bss) {
2558 err = -ENOMEM;
2559 goto CleanUp;
2560 }
2561
2562 cfg80211_put_bss(bss);
2563
5b435de0
AS
2564CleanUp:
2565
2566 kfree(buf);
2567
2568 WL_TRACE("Exit\n");
2569
2570 return err;
2571}
2572
2573static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv)
2574{
2575 return cfg_priv->conf->mode == WL_MODE_IBSS;
2576}
2577
f8e4b412
AB
2578/*
2579 * Traverse a string of 1-byte tag/1-byte length/variable-length value
2580 * triples, returning a pointer to the substring whose first element
2581 * matches tag
2582 */
2583static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key)
2584{
2585 struct brcmf_tlv *elt;
2586 int totlen;
2587
2588 elt = (struct brcmf_tlv *) buf;
2589 totlen = buflen;
2590
2591 /* find tagged parameter */
04012895 2592 while (totlen >= TLV_HDR_LEN) {
f8e4b412
AB
2593 int len = elt->len;
2594
2595 /* validate remaining totlen */
04012895 2596 if ((elt->id == key) && (totlen >= (len + TLV_HDR_LEN)))
f8e4b412
AB
2597 return elt;
2598
04012895
HM
2599 elt = (struct brcmf_tlv *) ((u8 *) elt + (len + TLV_HDR_LEN));
2600 totlen -= (len + TLV_HDR_LEN);
f8e4b412
AB
2601 }
2602
2603 return NULL;
2604}
2605
5b435de0
AS
2606static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv)
2607{
d34bf64f 2608 struct brcmf_bss_info_le *bi;
5b435de0 2609 struct brcmf_ssid *ssid;
f8e4b412 2610 struct brcmf_tlv *tim;
5b435de0
AS
2611 u16 beacon_interval;
2612 u8 dtim_period;
2613 size_t ie_len;
2614 u8 *ie;
2615 s32 err = 0;
2616
2617 WL_TRACE("Enter\n");
2618 if (brcmf_is_ibssmode(cfg_priv))
2619 return err;
2620
2621 ssid = (struct brcmf_ssid *)brcmf_read_prof(cfg_priv, WL_PROF_SSID);
2622
2623 *(__le32 *)cfg_priv->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
2624 err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_GET_BSS_INFO,
2625 cfg_priv->extra_buf, WL_EXTRA_BUF_MAX);
2626 if (err) {
2627 WL_ERR("Could not get bss info %d\n", err);
2628 goto update_bss_info_out;
2629 }
2630
d34bf64f 2631 bi = (struct brcmf_bss_info_le *)(cfg_priv->extra_buf + 4);
5b435de0
AS
2632 err = brcmf_inform_single_bss(cfg_priv, bi);
2633 if (err)
2634 goto update_bss_info_out;
2635
2636 ie = ((u8 *)bi) + le16_to_cpu(bi->ie_offset);
2637 ie_len = le32_to_cpu(bi->ie_length);
2638 beacon_interval = le16_to_cpu(bi->beacon_period);
2639
f8e4b412 2640 tim = brcmf_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
5b435de0
AS
2641 if (tim)
2642 dtim_period = tim->data[1];
2643 else {
2644 /*
2645 * active scan was done so we could not get dtim
2646 * information out of probe response.
2647 * so we speficially query dtim information to dongle.
2648 */
2649 u32 var;
2650 err = brcmf_dev_intvar_get(cfg_to_ndev(cfg_priv),
2651 "dtim_assoc", &var);
2652 if (err) {
2653 WL_ERR("wl dtim_assoc failed (%d)\n", err);
2654 goto update_bss_info_out;
2655 }
2656 dtim_period = (u8)var;
2657 }
2658
2659 brcmf_update_prof(cfg_priv, NULL, &beacon_interval, WL_PROF_BEACONINT);
2660 brcmf_update_prof(cfg_priv, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
2661
2662update_bss_info_out:
2663 WL_TRACE("Exit");
2664 return err;
2665}
2666
108a4bee 2667static void brcmf_abort_scanning(struct brcmf_cfg80211_priv *cfg_priv)
5b435de0
AS
2668{
2669 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
108a4bee 2670 struct escan_info *escan = &cfg_priv->escan_info;
5b435de0
AS
2671 struct brcmf_ssid ssid;
2672
108a4bee 2673 set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
5b435de0
AS
2674 if (cfg_priv->iscan_on) {
2675 iscan->state = WL_ISCAN_STATE_IDLE;
2676
2677 if (iscan->timer_on) {
2678 del_timer_sync(&iscan->timer);
2679 iscan->timer_on = 0;
2680 }
2681
2682 cancel_work_sync(&iscan->work);
2683
2684 /* Abort iscan running in FW */
2685 memset(&ssid, 0, sizeof(ssid));
2686 brcmf_run_iscan(iscan, &ssid, WL_SCAN_ACTION_ABORT);
108a4bee
AS
2687
2688 if (cfg_priv->scan_request) {
2689 /* Indidate scan abort to cfg80211 layer */
2690 WL_INFO("Terminating scan in progress\n");
2691 cfg80211_scan_done(cfg_priv->scan_request, true);
2692 cfg_priv->scan_request = NULL;
2693 }
2694 }
2695 if (cfg_priv->escan_on && cfg_priv->scan_request) {
2696 escan->escan_state = WL_ESCAN_STATE_IDLE;
2697 brcmf_notify_escan_complete(cfg_priv, escan->ndev, true, true);
5b435de0 2698 }
108a4bee
AS
2699 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
2700 clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
5b435de0
AS
2701}
2702
2703static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
2704 bool aborted)
2705{
2706 struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
2707 struct net_device *ndev = cfg_to_ndev(cfg_priv);
2708
2709 if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
2710 WL_ERR("Scan complete while device not scanning\n");
2711 return;
2712 }
2713 if (cfg_priv->scan_request) {
2714 WL_SCAN("ISCAN Completed scan: %s\n",
2715 aborted ? "Aborted" : "Done");
2716 cfg80211_scan_done(cfg_priv->scan_request, aborted);
2717 brcmf_set_mpc(ndev, 1);
2718 cfg_priv->scan_request = NULL;
2719 }
2720 cfg_priv->iscan_kickstart = false;
2721}
2722
2723static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan)
2724{
2725 if (iscan->state != WL_ISCAN_STATE_IDLE) {
2726 WL_SCAN("wake up iscan\n");
2727 schedule_work(&iscan->work);
2728 return 0;
2729 }
2730
2731 return -EIO;
2732}
2733
2734static s32
2735brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status,
2736 struct brcmf_scan_results **bss_list)
2737{
2738 struct brcmf_iscan_results list;
2739 struct brcmf_scan_results *results;
2740 struct brcmf_scan_results_le *results_le;
2741 struct brcmf_iscan_results *list_buf;
2742 s32 err = 0;
2743
2744 memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
2745 list_buf = (struct brcmf_iscan_results *)iscan->scan_buf;
2746 results = &list_buf->results;
2747 results_le = &list_buf->results_le;
2748 results->buflen = BRCMF_ISCAN_RESULTS_FIXED_SIZE;
2749 results->version = 0;
2750 results->count = 0;
2751
2752 memset(&list, 0, sizeof(list));
2753 list.results_le.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX);
2754 err = brcmf_dev_iovar_getbuf(iscan->ndev, "iscanresults", &list,
2755 BRCMF_ISCAN_RESULTS_FIXED_SIZE,
2756 iscan->scan_buf, WL_ISCAN_BUF_MAX);
2757 if (err) {
2758 WL_ERR("error (%d)\n", err);
2759 return err;
2760 }
2761 results->buflen = le32_to_cpu(results_le->buflen);
2762 results->version = le32_to_cpu(results_le->version);
2763 results->count = le32_to_cpu(results_le->count);
2764 WL_SCAN("results->count = %d\n", results_le->count);
2765 WL_SCAN("results->buflen = %d\n", results_le->buflen);
2766 *status = le32_to_cpu(list_buf->status_le);
2767 WL_SCAN("status = %d\n", *status);
2768 *bss_list = results;
2769
2770 return err;
2771}
2772
2773static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv)
2774{
2775 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2776 s32 err = 0;
2777
2778 iscan->state = WL_ISCAN_STATE_IDLE;
2779 brcmf_inform_bss(cfg_priv);
2780 brcmf_notify_iscan_complete(iscan, false);
2781
2782 return err;
2783}
2784
2785static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv)
2786{
2787 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2788 s32 err = 0;
2789
2790 /* Reschedule the timer */
2791 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
2792 iscan->timer_on = 1;
2793
2794 return err;
2795}
2796
2797static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv)
2798{
2799 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2800 s32 err = 0;
2801
2802 brcmf_inform_bss(cfg_priv);
2803 brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE);
2804 /* Reschedule the timer */
2805 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
2806 iscan->timer_on = 1;
2807
2808 return err;
2809}
2810
2811static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv)
2812{
2813 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2814 s32 err = 0;
2815
2816 iscan->state = WL_ISCAN_STATE_IDLE;
2817 brcmf_notify_iscan_complete(iscan, true);
2818
2819 return err;
2820}
2821
2822static void brcmf_cfg80211_iscan_handler(struct work_struct *work)
2823{
2824 struct brcmf_cfg80211_iscan_ctrl *iscan =
2825 container_of(work, struct brcmf_cfg80211_iscan_ctrl,
2826 work);
2827 struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
2828 struct brcmf_cfg80211_iscan_eloop *el = &iscan->el;
2829 u32 status = BRCMF_SCAN_RESULTS_PARTIAL;
2830
2831 if (iscan->timer_on) {
2832 del_timer_sync(&iscan->timer);
2833 iscan->timer_on = 0;
2834 }
2835
2836 if (brcmf_get_iscan_results(iscan, &status, &cfg_priv->bss_list)) {
2837 status = BRCMF_SCAN_RESULTS_ABORTED;
2838 WL_ERR("Abort iscan\n");
2839 }
2840
2841 el->handler[status](cfg_priv);
2842}
2843
2844static void brcmf_iscan_timer(unsigned long data)
2845{
2846 struct brcmf_cfg80211_iscan_ctrl *iscan =
2847 (struct brcmf_cfg80211_iscan_ctrl *)data;
2848
2849 if (iscan) {
2850 iscan->timer_on = 0;
2851 WL_SCAN("timer expired\n");
2852 brcmf_wakeup_iscan(iscan);
2853 }
2854}
2855
2856static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv)
2857{
2858 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
2859
2860 if (cfg_priv->iscan_on) {
2861 iscan->state = WL_ISCAN_STATE_IDLE;
2862 INIT_WORK(&iscan->work, brcmf_cfg80211_iscan_handler);
2863 }
2864
2865 return 0;
2866}
2867
2868static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el)
2869{
2870 memset(el, 0, sizeof(*el));
2871 el->handler[BRCMF_SCAN_RESULTS_SUCCESS] = brcmf_iscan_done;
2872 el->handler[BRCMF_SCAN_RESULTS_PARTIAL] = brcmf_iscan_inprogress;
2873 el->handler[BRCMF_SCAN_RESULTS_PENDING] = brcmf_iscan_pending;
2874 el->handler[BRCMF_SCAN_RESULTS_ABORTED] = brcmf_iscan_aborted;
2875 el->handler[BRCMF_SCAN_RESULTS_NO_MEM] = brcmf_iscan_aborted;
2876}
2877
2878static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv)
2879{
2880 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
2881 int err = 0;
2882
2883 if (cfg_priv->iscan_on) {
2884 iscan->ndev = cfg_to_ndev(cfg_priv);
2885 brcmf_init_iscan_eloop(&iscan->el);
2886 iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
2887 init_timer(&iscan->timer);
2888 iscan->timer.data = (unsigned long) iscan;
2889 iscan->timer.function = brcmf_iscan_timer;
2890 err = brcmf_invoke_iscan(cfg_priv);
2891 if (!err)
2892 iscan->data = cfg_priv;
2893 }
2894
2895 return err;
2896}
2897
e756af5b
HM
2898static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work)
2899{
2900 struct brcmf_cfg80211_priv *cfg_priv =
2901 container_of(work, struct brcmf_cfg80211_priv,
2902 escan_timeout_work);
2903
2904 brcmf_notify_escan_complete(cfg_priv,
2905 cfg_priv->escan_info.ndev, true, true);
2906}
2907
2908static void brcmf_escan_timeout(unsigned long data)
2909{
2910 struct brcmf_cfg80211_priv *cfg_priv =
2911 (struct brcmf_cfg80211_priv *)data;
2912
2913 if (cfg_priv->scan_request) {
2914 WL_ERR("timer expired\n");
2915 if (cfg_priv->escan_on)
2916 schedule_work(&cfg_priv->escan_timeout_work);
2917 }
2918}
2919
2920static s32
2921brcmf_compare_update_same_bss(struct brcmf_bss_info_le *bss,
2922 struct brcmf_bss_info_le *bss_info_le)
2923{
2924 if (!memcmp(&bss_info_le->BSSID, &bss->BSSID, ETH_ALEN) &&
2925 (CHSPEC_BAND(le16_to_cpu(bss_info_le->chanspec)) ==
2926 CHSPEC_BAND(le16_to_cpu(bss->chanspec))) &&
2927 bss_info_le->SSID_len == bss->SSID_len &&
2928 !memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) {
2929 if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) ==
2930 (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL)) {
029591f3
AS
2931 s16 bss_rssi = le16_to_cpu(bss->RSSI);
2932 s16 bss_info_rssi = le16_to_cpu(bss_info_le->RSSI);
2933
e756af5b
HM
2934 /* preserve max RSSI if the measurements are
2935 * both on-channel or both off-channel
2936 */
029591f3 2937 if (bss_info_rssi > bss_rssi)
e756af5b
HM
2938 bss->RSSI = bss_info_le->RSSI;
2939 } else if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) &&
2940 (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL) == 0) {
2941 /* preserve the on-channel rssi measurement
2942 * if the new measurement is off channel
2943 */
2944 bss->RSSI = bss_info_le->RSSI;
2945 bss->flags |= WLC_BSS_RSSI_ON_CHANNEL;
2946 }
2947 return 1;
2948 }
2949 return 0;
2950}
2951
2952static s32
2953brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_priv *cfg_priv,
2954 struct net_device *ndev,
2955 const struct brcmf_event_msg *e, void *data)
2956{
2957 s32 status;
2958 s32 err = 0;
2959 struct brcmf_escan_result_le *escan_result_le;
2960 struct brcmf_bss_info_le *bss_info_le;
2961 struct brcmf_bss_info_le *bss = NULL;
2962 u32 bi_length;
2963 struct brcmf_scan_results *list;
2964 u32 i;
97ed15c7 2965 bool aborted;
e756af5b
HM
2966
2967 status = be32_to_cpu(e->status);
2968
2969 if (!ndev || !cfg_priv->escan_on ||
2970 !test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
2971 WL_ERR("scan not ready ndev %p wl->escan_on %d drv_status %x\n",
2972 ndev, cfg_priv->escan_on,
2973 !test_bit(WL_STATUS_SCANNING, &cfg_priv->status));
2974 return -EPERM;
2975 }
2976
2977 if (status == BRCMF_E_STATUS_PARTIAL) {
2978 WL_SCAN("ESCAN Partial result\n");
2979 escan_result_le = (struct brcmf_escan_result_le *) data;
2980 if (!escan_result_le) {
2981 WL_ERR("Invalid escan result (NULL pointer)\n");
2982 goto exit;
2983 }
2984 if (!cfg_priv->scan_request) {
2985 WL_SCAN("result without cfg80211 request\n");
2986 goto exit;
2987 }
2988
2989 if (le16_to_cpu(escan_result_le->bss_count) != 1) {
2990 WL_ERR("Invalid bss_count %d: ignoring\n",
2991 escan_result_le->bss_count);
2992 goto exit;
2993 }
2994 bss_info_le = &escan_result_le->bss_info_le;
2995
2996 bi_length = le32_to_cpu(bss_info_le->length);
2997 if (bi_length != (le32_to_cpu(escan_result_le->buflen) -
2998 WL_ESCAN_RESULTS_FIXED_SIZE)) {
2999 WL_ERR("Invalid bss_info length %d: ignoring\n",
3000 bi_length);
3001 goto exit;
3002 }
3003
3004 if (!(cfg_to_wiphy(cfg_priv)->interface_modes &
3005 BIT(NL80211_IFTYPE_ADHOC))) {
3006 if (le16_to_cpu(bss_info_le->capability) &
3007 WLAN_CAPABILITY_IBSS) {
3008 WL_ERR("Ignoring IBSS result\n");
3009 goto exit;
3010 }
3011 }
3012
3013 list = (struct brcmf_scan_results *)
3014 cfg_priv->escan_info.escan_buf;
3015 if (bi_length > WL_ESCAN_BUF_SIZE - list->buflen) {
3016 WL_ERR("Buffer is too small: ignoring\n");
3017 goto exit;
3018 }
3019
3020 for (i = 0; i < list->count; i++) {
3021 bss = bss ? (struct brcmf_bss_info_le *)
3022 ((unsigned char *)bss +
3023 le32_to_cpu(bss->length)) : list->bss_info_le;
3024 if (brcmf_compare_update_same_bss(bss, bss_info_le))
3025 goto exit;
3026 }
3027 memcpy(&(cfg_priv->escan_info.escan_buf[list->buflen]),
3028 bss_info_le, bi_length);
3029 list->version = le32_to_cpu(bss_info_le->version);
3030 list->buflen += bi_length;
3031 list->count++;
3032 } else {
3033 cfg_priv->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
3034 if (cfg_priv->scan_request) {
3035 cfg_priv->bss_list = (struct brcmf_scan_results *)
3036 cfg_priv->escan_info.escan_buf;
3037 brcmf_inform_bss(cfg_priv);
97ed15c7
AS
3038 aborted = status != BRCMF_E_STATUS_SUCCESS;
3039 brcmf_notify_escan_complete(cfg_priv, ndev, aborted,
3040 false);
e756af5b
HM
3041 } else
3042 WL_ERR("Unexpected scan result 0x%x\n", status);
3043 }
3044exit:
3045 return err;
3046}
3047
3048static void brcmf_init_escan(struct brcmf_cfg80211_priv *cfg_priv)
3049{
3050
3051 if (cfg_priv->escan_on) {
3052 cfg_priv->el.handler[BRCMF_E_ESCAN_RESULT] =
3053 brcmf_cfg80211_escan_handler;
3054 cfg_priv->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
3055 /* Init scan_timeout timer */
3056 init_timer(&cfg_priv->escan_timeout);
3057 cfg_priv->escan_timeout.data = (unsigned long) cfg_priv;
3058 cfg_priv->escan_timeout.function = brcmf_escan_timeout;
3059 INIT_WORK(&cfg_priv->escan_timeout_work,
3060 brcmf_cfg80211_escan_timeout_worker);
3061 }
3062}
3063
5addc0de 3064static __always_inline void brcmf_delay(u32 ms)
5b435de0
AS
3065{
3066 if (ms < 1000 / HZ) {
3067 cond_resched();
3068 mdelay(ms);
3069 } else {
3070 msleep(ms);
3071 }
3072}
3073
3074static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
3075{
3076 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3077
3078 /*
3079 * Check for WL_STATUS_READY before any function call which
3080 * could result is bus access. Don't block the resume for
3081 * any driver error conditions
3082 */
3083 WL_TRACE("Enter\n");
3084
3085 if (test_bit(WL_STATUS_READY, &cfg_priv->status))
3086 brcmf_invoke_iscan(wiphy_to_cfg(wiphy));
3087
3088 WL_TRACE("Exit\n");
3089 return 0;
3090}
3091
3092static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
3093 struct cfg80211_wowlan *wow)
3094{
3095 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3096 struct net_device *ndev = cfg_to_ndev(cfg_priv);
3097
3098 WL_TRACE("Enter\n");
3099
3100 /*
3101 * Check for WL_STATUS_READY before any function call which
3102 * could result is bus access. Don't block the suspend for
3103 * any driver error conditions
3104 */
3105
3106 /*
3107 * While going to suspend if associated with AP disassociate
3108 * from AP to save power while system is in suspended state
3109 */
3110 if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
3111 test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
3112 test_bit(WL_STATUS_READY, &cfg_priv->status)) {
3113 WL_INFO("Disassociating from AP"
3114 " while entering suspend state\n");
3115 brcmf_link_down(cfg_priv);
3116
3117 /*
3118 * Make sure WPA_Supplicant receives all the event
3119 * generated due to DISASSOC call to the fw to keep
3120 * the state fw and WPA_Supplicant state consistent
3121 */
3122 brcmf_delay(500);
3123 }
3124
5b435de0 3125 if (test_bit(WL_STATUS_READY, &cfg_priv->status))
108a4bee
AS
3126 brcmf_abort_scanning(cfg_priv);
3127 else
3128 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
5b435de0
AS
3129
3130 /* Turn off watchdog timer */
35aafa9d 3131 if (test_bit(WL_STATUS_READY, &cfg_priv->status))
5b435de0 3132 brcmf_set_mpc(ndev, 1);
5b435de0
AS
3133
3134 WL_TRACE("Exit\n");
3135
3136 return 0;
3137}
3138
3139static __used s32
3140brcmf_dev_bufvar_set(struct net_device *ndev, s8 *name, s8 *buf, s32 len)
3141{
3142 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
3143 u32 buflen;
3144
53a2277d 3145 buflen = brcmf_c_mkiovar(name, buf, len, cfg_priv->dcmd_buf,
5b435de0
AS
3146 WL_DCMD_LEN_MAX);
3147 BUG_ON(!buflen);
3148
3149 return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg_priv->dcmd_buf,
3150 buflen);
3151}
3152
3153static s32
3154brcmf_dev_bufvar_get(struct net_device *ndev, s8 *name, s8 *buf,
3155 s32 buf_len)
3156{
3157 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
3158 u32 len;
3159 s32 err = 0;
3160
53a2277d 3161 len = brcmf_c_mkiovar(name, NULL, 0, cfg_priv->dcmd_buf,
5b435de0
AS
3162 WL_DCMD_LEN_MAX);
3163 BUG_ON(!len);
3164 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg_priv->dcmd_buf,
3165 WL_DCMD_LEN_MAX);
3166 if (err) {
3167 WL_ERR("error (%d)\n", err);
3168 return err;
3169 }
3170 memcpy(buf, cfg_priv->dcmd_buf, buf_len);
3171
3172 return err;
3173}
3174
3175static __used s32
3176brcmf_update_pmklist(struct net_device *ndev,
3177 struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
3178{
3179 int i, j;
40c8e95a 3180 int pmkid_len;
5b435de0 3181
40c8e95a
AS
3182 pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid);
3183
3184 WL_CONN("No of elements %d\n", pmkid_len);
3185 for (i = 0; i < pmkid_len; i++) {
5b435de0
AS
3186 WL_CONN("PMKID[%d]: %pM =\n", i,
3187 &pmk_list->pmkids.pmkid[i].BSSID);
3188 for (j = 0; j < WLAN_PMKID_LEN; j++)
3189 WL_CONN("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]);
3190 }
3191
3192 if (!err)
3193 brcmf_dev_bufvar_set(ndev, "pmkid_info", (char *)pmk_list,
3194 sizeof(*pmk_list));
3195
3196 return err;
3197}
3198
3199static s32
3200brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
3201 struct cfg80211_pmksa *pmksa)
3202{
3203 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3204 struct pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids;
3205 s32 err = 0;
3206 int i;
40c8e95a 3207 int pmkid_len;
5b435de0
AS
3208
3209 WL_TRACE("Enter\n");
3210 if (!check_sys_up(wiphy))
3211 return -EIO;
3212
40c8e95a
AS
3213 pmkid_len = le32_to_cpu(pmkids->npmkid);
3214 for (i = 0; i < pmkid_len; i++)
5b435de0
AS
3215 if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN))
3216 break;
3217 if (i < WL_NUM_PMKIDS_MAX) {
3218 memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN);
3219 memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
40c8e95a
AS
3220 if (i == pmkid_len) {
3221 pmkid_len++;
3222 pmkids->npmkid = cpu_to_le32(pmkid_len);
3223 }
5b435de0
AS
3224 } else
3225 err = -EINVAL;
3226
3227 WL_CONN("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
40c8e95a 3228 pmkids->pmkid[pmkid_len].BSSID);
5b435de0 3229 for (i = 0; i < WLAN_PMKID_LEN; i++)
40c8e95a 3230 WL_CONN("%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]);
5b435de0
AS
3231
3232 err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
3233
3234 WL_TRACE("Exit\n");
3235 return err;
3236}
3237
3238static s32
3239brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
3240 struct cfg80211_pmksa *pmksa)
3241{
3242 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3243 struct pmkid_list pmkid;
3244 s32 err = 0;
40c8e95a 3245 int i, pmkid_len;
5b435de0
AS
3246
3247 WL_TRACE("Enter\n");
3248 if (!check_sys_up(wiphy))
3249 return -EIO;
3250
3251 memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
3252 memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
3253
3254 WL_CONN("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
3255 &pmkid.pmkid[0].BSSID);
3256 for (i = 0; i < WLAN_PMKID_LEN; i++)
3257 WL_CONN("%02x\n", pmkid.pmkid[0].PMKID[i]);
3258
40c8e95a
AS
3259 pmkid_len = le32_to_cpu(cfg_priv->pmk_list->pmkids.npmkid);
3260 for (i = 0; i < pmkid_len; i++)
5b435de0
AS
3261 if (!memcmp
3262 (pmksa->bssid, &cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
3263 ETH_ALEN))
3264 break;
3265
40c8e95a
AS
3266 if ((pmkid_len > 0)
3267 && (i < pmkid_len)) {
5b435de0
AS
3268 memset(&cfg_priv->pmk_list->pmkids.pmkid[i], 0,
3269 sizeof(struct pmkid));
40c8e95a 3270 for (; i < (pmkid_len - 1); i++) {
5b435de0
AS
3271 memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
3272 &cfg_priv->pmk_list->pmkids.pmkid[i + 1].BSSID,
3273 ETH_ALEN);
3274 memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].PMKID,
3275 &cfg_priv->pmk_list->pmkids.pmkid[i + 1].PMKID,
3276 WLAN_PMKID_LEN);
3277 }
40c8e95a 3278 cfg_priv->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1);
5b435de0
AS
3279 } else
3280 err = -EINVAL;
3281
3282 err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
3283
3284 WL_TRACE("Exit\n");
3285 return err;
3286
3287}
3288
3289static s32
3290brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
3291{
3292 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3293 s32 err = 0;
3294
3295 WL_TRACE("Enter\n");
3296 if (!check_sys_up(wiphy))
3297 return -EIO;
3298
3299 memset(cfg_priv->pmk_list, 0, sizeof(*cfg_priv->pmk_list));
3300 err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
3301
3302 WL_TRACE("Exit\n");
3303 return err;
3304
3305}
3306
e5806072
AS
3307/*
3308 * PFN result doesn't have all the info which are
3309 * required by the supplicant
3310 * (For e.g IEs) Do a target Escan so that sched scan results are reported
3311 * via wl_inform_single_bss in the required format. Escan does require the
3312 * scan request in the form of cfg80211_scan_request. For timebeing, create
3313 * cfg80211_scan_request one out of the received PNO event.
3314 */
3315static s32
3316brcmf_notify_sched_scan_results(struct brcmf_cfg80211_priv *cfg_priv,
3317 struct net_device *ndev,
3318 const struct brcmf_event_msg *e, void *data)
3319{
3320 struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
3321 struct cfg80211_scan_request *request = NULL;
3322 struct cfg80211_ssid *ssid = NULL;
3323 struct ieee80211_channel *channel = NULL;
3324 struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
3325 int err = 0;
3326 int channel_req = 0;
3327 int band = 0;
3328 struct brcmf_pno_scanresults_le *pfn_result;
3329 u32 result_count;
3330 u32 status;
3331
3332 WL_SCAN("Enter\n");
3333
3334 if (e->event_type == cpu_to_be32(BRCMF_E_PFN_NET_LOST)) {
3335 WL_SCAN("PFN NET LOST event. Do Nothing\n");
3336 return 0;
3337 }
3338
3339 pfn_result = (struct brcmf_pno_scanresults_le *)data;
3340 result_count = le32_to_cpu(pfn_result->count);
3341 status = le32_to_cpu(pfn_result->status);
3342
3343 /*
3344 * PFN event is limited to fit 512 bytes so we may get
3345 * multiple NET_FOUND events. For now place a warning here.
3346 */
3347 WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE);
3348 WL_SCAN("PFN NET FOUND event. count: %d\n", result_count);
3349 if (result_count > 0) {
3350 int i;
3351
3352 request = kzalloc(sizeof(*request), GFP_KERNEL);
58901d18
DC
3353 ssid = kcalloc(result_count, sizeof(*ssid), GFP_KERNEL);
3354 channel = kcalloc(result_count, sizeof(*channel), GFP_KERNEL);
e5806072
AS
3355 if (!request || !ssid || !channel) {
3356 err = -ENOMEM;
3357 goto out_err;
3358 }
3359
3360 request->wiphy = wiphy;
3361 data += sizeof(struct brcmf_pno_scanresults_le);
3362 netinfo_start = (struct brcmf_pno_net_info_le *)data;
3363
3364 for (i = 0; i < result_count; i++) {
3365 netinfo = &netinfo_start[i];
3366 if (!netinfo) {
3367 WL_ERR("Invalid netinfo ptr. index: %d\n", i);
3368 err = -EINVAL;
3369 goto out_err;
3370 }
3371
3372 WL_SCAN("SSID:%s Channel:%d\n",
3373 netinfo->SSID, netinfo->channel);
3374 memcpy(ssid[i].ssid, netinfo->SSID, netinfo->SSID_len);
3375 ssid[i].ssid_len = netinfo->SSID_len;
3376 request->n_ssids++;
3377
3378 channel_req = netinfo->channel;
3379 if (channel_req <= CH_MAX_2G_CHANNEL)
3380 band = NL80211_BAND_2GHZ;
3381 else
3382 band = NL80211_BAND_5GHZ;
3383 channel[i].center_freq =
3384 ieee80211_channel_to_frequency(channel_req,
3385 band);
3386 channel[i].band = band;
3387 channel[i].flags |= IEEE80211_CHAN_NO_HT40;
3388 request->channels[i] = &channel[i];
3389 request->n_channels++;
3390 }
3391
3392 /* assign parsed ssid array */
3393 if (request->n_ssids)
3394 request->ssids = &ssid[0];
3395
3396 if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
3397 /* Abort any on-going scan */
3398 brcmf_abort_scanning(cfg_priv);
3399 }
3400
3401 set_bit(WL_STATUS_SCANNING, &cfg_priv->status);
3402 err = brcmf_do_escan(cfg_priv, wiphy, ndev, request);
3403 if (err) {
3404 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
3405 goto out_err;
3406 }
3407 cfg_priv->sched_escan = true;
3408 cfg_priv->scan_request = request;
3409 } else {
3410 WL_ERR("FALSE PNO Event. (pfn_count == 0)\n");
3411 goto out_err;
3412 }
3413
3414 kfree(ssid);
3415 kfree(channel);
3416 kfree(request);
3417 return 0;
3418
3419out_err:
3420 kfree(ssid);
3421 kfree(channel);
3422 kfree(request);
3423 cfg80211_sched_scan_stopped(wiphy);
3424 return err;
3425}
3426
3427#ifndef CONFIG_BRCMISCAN
3428static int brcmf_dev_pno_clean(struct net_device *ndev)
3429{
3430 char iovbuf[128];
3431 int ret;
3432
3433 /* Disable pfn */
3434 ret = brcmf_dev_intvar_set(ndev, "pfn", 0);
3435 if (ret == 0) {
3436 /* clear pfn */
3437 ret = brcmf_dev_iovar_setbuf(ndev, "pfnclear", NULL, 0,
3438 iovbuf, sizeof(iovbuf));
3439 }
3440 if (ret < 0)
3441 WL_ERR("failed code %d\n", ret);
3442
3443 return ret;
3444}
3445
3446static int brcmf_dev_pno_config(struct net_device *ndev)
3447{
3448 struct brcmf_pno_param_le pfn_param;
3449 char iovbuf[128];
3450
3451 memset(&pfn_param, 0, sizeof(pfn_param));
3452 pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION);
3453
3454 /* set extra pno params */
3455 pfn_param.flags = cpu_to_le16(1 << BRCMF_PNO_ENABLE_ADAPTSCAN_BIT);
3456 pfn_param.repeat = BRCMF_PNO_REPEAT;
3457 pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX;
3458
3459 /* set up pno scan fr */
3460 pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME);
3461
3462 return brcmf_dev_iovar_setbuf(ndev, "pfn_set",
3463 &pfn_param, sizeof(pfn_param),
3464 iovbuf, sizeof(iovbuf));
3465}
3466
3467static int
3468brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
3469 struct net_device *ndev,
3470 struct cfg80211_sched_scan_request *request)
3471{
3472 char iovbuf[128];
3473 struct brcmf_cfg80211_priv *cfg_priv = wiphy_priv(wiphy);
3474 struct brcmf_pno_net_param_le pfn;
3475 int i;
3476 int ret = 0;
3477
3478 WL_SCAN("Enter n_match_sets:%d n_ssids:%d\n",
3479 request->n_match_sets, request->n_ssids);
3480 if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
3481 WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status);
3482 return -EAGAIN;
3483 }
3484
3485 if (!request || !request->n_ssids || !request->n_match_sets) {
3486 WL_ERR("Invalid sched scan req!! n_ssids:%d\n",
3487 request->n_ssids);
3488 return -EINVAL;
3489 }
3490
3491 if (request->n_ssids > 0) {
3492 for (i = 0; i < request->n_ssids; i++) {
3493 /* Active scan req for ssids */
3494 WL_SCAN(">>> Active scan req for ssid (%s)\n",
3495 request->ssids[i].ssid);
3496
3497 /*
3498 * match_set ssids is a supert set of n_ssid list,
3499 * so we need not add these set seperately.
3500 */
3501 }
3502 }
3503
3504 if (request->n_match_sets > 0) {
3505 /* clean up everything */
3506 ret = brcmf_dev_pno_clean(ndev);
3507 if (ret < 0) {
3508 WL_ERR("failed error=%d\n", ret);
3509 return ret;
3510 }
3511
3512 /* configure pno */
3513 ret = brcmf_dev_pno_config(ndev);
3514 if (ret < 0) {
3515 WL_ERR("PNO setup failed!! ret=%d\n", ret);
3516 return -EINVAL;
3517 }
3518
3519 /* configure each match set */
3520 for (i = 0; i < request->n_match_sets; i++) {
3521 struct cfg80211_ssid *ssid;
3522 u32 ssid_len;
3523
3524 ssid = &request->match_sets[i].ssid;
3525 ssid_len = ssid->ssid_len;
3526
3527 if (!ssid_len) {
3528 WL_ERR("skip broadcast ssid\n");
3529 continue;
3530 }
3531 pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN);
3532 pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY);
3533 pfn.wsec = cpu_to_le32(0);
3534 pfn.infra = cpu_to_le32(1);
3535 pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
3536 pfn.ssid.SSID_len = cpu_to_le32(ssid_len);
3537 memcpy(pfn.ssid.SSID, ssid->ssid, ssid_len);
3538 ret = brcmf_dev_iovar_setbuf(ndev, "pfn_add",
3539 &pfn, sizeof(pfn),
3540 iovbuf, sizeof(iovbuf));
3541 WL_SCAN(">>> PNO filter %s for ssid (%s)\n",
3542 ret == 0 ? "set" : "failed",
3543 ssid->ssid);
3544 }
3545 /* Enable the PNO */
3546 if (brcmf_dev_intvar_set(ndev, "pfn", 1) < 0) {
3547 WL_ERR("PNO enable failed!! ret=%d\n", ret);
3548 return -EINVAL;
3549 }
3550 } else {
3551 return -EINVAL;
3552 }
3553
3554 return 0;
3555}
3556
3557static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
3558 struct net_device *ndev)
3559{
3560 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3561
3562 WL_SCAN("enter\n");
3563 brcmf_dev_pno_clean(ndev);
3564 if (cfg_priv->sched_escan)
3565 brcmf_notify_escan_complete(cfg_priv, ndev, true, true);
3566 return 0;
3567}
3568#endif /* CONFIG_BRCMISCAN */
3569
cbaa177d
AS
3570#ifdef CONFIG_NL80211_TESTMODE
3571static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
3572{
3573 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
3574 struct net_device *ndev = cfg_priv->wdev->netdev;
3575 struct brcmf_dcmd *dcmd = data;
3576 struct sk_buff *reply;
3577 int ret;
3578
3579 ret = brcmf_netlink_dcmd(ndev, dcmd);
3580 if (ret == 0) {
3581 reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*dcmd));
3582 nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*dcmd), dcmd);
3583 ret = cfg80211_testmode_reply(reply);
3584 }
3585 return ret;
3586}
3587#endif
3588
5b435de0
AS
3589static struct cfg80211_ops wl_cfg80211_ops = {
3590 .change_virtual_intf = brcmf_cfg80211_change_iface,
3591 .scan = brcmf_cfg80211_scan,
3592 .set_wiphy_params = brcmf_cfg80211_set_wiphy_params,
3593 .join_ibss = brcmf_cfg80211_join_ibss,
3594 .leave_ibss = brcmf_cfg80211_leave_ibss,
3595 .get_station = brcmf_cfg80211_get_station,
3596 .set_tx_power = brcmf_cfg80211_set_tx_power,
3597 .get_tx_power = brcmf_cfg80211_get_tx_power,
3598 .add_key = brcmf_cfg80211_add_key,
3599 .del_key = brcmf_cfg80211_del_key,
3600 .get_key = brcmf_cfg80211_get_key,
3601 .set_default_key = brcmf_cfg80211_config_default_key,
3602 .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key,
3603 .set_power_mgmt = brcmf_cfg80211_set_power_mgmt,
3604 .set_bitrate_mask = brcmf_cfg80211_set_bitrate_mask,
3605 .connect = brcmf_cfg80211_connect,
3606 .disconnect = brcmf_cfg80211_disconnect,
3607 .suspend = brcmf_cfg80211_suspend,
3608 .resume = brcmf_cfg80211_resume,
3609 .set_pmksa = brcmf_cfg80211_set_pmksa,
3610 .del_pmksa = brcmf_cfg80211_del_pmksa,
cbaa177d 3611 .flush_pmksa = brcmf_cfg80211_flush_pmksa,
e5806072
AS
3612#ifndef CONFIG_BRCMISCAN
3613 /* scheduled scan need e-scan, which is mutual exclusive with i-scan */
3614 .sched_scan_start = brcmf_cfg80211_sched_scan_start,
3615 .sched_scan_stop = brcmf_cfg80211_sched_scan_stop,
3616#endif
cbaa177d
AS
3617#ifdef CONFIG_NL80211_TESTMODE
3618 .testmode_cmd = brcmf_cfg80211_testmode
3619#endif
5b435de0
AS
3620};
3621
3622static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
3623{
3624 s32 err = 0;
3625
3626 switch (mode) {
3627 case WL_MODE_BSS:
3628 return NL80211_IFTYPE_STATION;
3629 case WL_MODE_IBSS:
3630 return NL80211_IFTYPE_ADHOC;
3631 default:
3632 return NL80211_IFTYPE_UNSPECIFIED;
3633 }
3634
3635 return err;
3636}
3637
e5806072
AS
3638static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
3639{
3640#ifndef CONFIG_BRCMFISCAN
3641 /* scheduled scan settings */
3642 wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
3643 wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
3644 wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
3645 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
3646#endif
3647}
3648
5db6e956 3649static struct wireless_dev *brcmf_alloc_wdev(struct device *ndev)
5b435de0
AS
3650{
3651 struct wireless_dev *wdev;
3652 s32 err = 0;
3653
3654 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
3655 if (!wdev)
3656 return ERR_PTR(-ENOMEM);
3657
5db6e956
AS
3658 wdev->wiphy = wiphy_new(&wl_cfg80211_ops,
3659 sizeof(struct brcmf_cfg80211_priv));
5b435de0 3660 if (!wdev->wiphy) {
bfeb4dbc 3661 WL_ERR("Could not allocate wiphy device\n");
5b435de0
AS
3662 err = -ENOMEM;
3663 goto wiphy_new_out;
3664 }
3665 set_wiphy_dev(wdev->wiphy, ndev);
3666 wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
3667 wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
3668 wdev->wiphy->interface_modes =
3669 BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
3670 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
3671 wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set
3672 * it as 11a by default.
3673 * This will be updated with
3674 * 11n phy tables in
3675 * "ifconfig up"
3676 * if phy has 11n capability
3677 */
3678 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
3679 wdev->wiphy->cipher_suites = __wl_cipher_suites;
3680 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
3681 wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power
3682 * save mode
3683 * by default
3684 */
e5806072 3685 brcmf_wiphy_pno_params(wdev->wiphy);
5b435de0
AS
3686 err = wiphy_register(wdev->wiphy);
3687 if (err < 0) {
bfeb4dbc 3688 WL_ERR("Could not register wiphy device (%d)\n", err);
5b435de0
AS
3689 goto wiphy_register_out;
3690 }
3691 return wdev;
3692
3693wiphy_register_out:
3694 wiphy_free(wdev->wiphy);
3695
3696wiphy_new_out:
3697 kfree(wdev);
3698
3699 return ERR_PTR(err);
3700}
3701
3702static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv)
3703{
3704 struct wireless_dev *wdev = cfg_priv->wdev;
3705
3706 if (!wdev) {
3707 WL_ERR("wdev is invalid\n");
3708 return;
3709 }
3710 wiphy_unregister(wdev->wiphy);
3711 wiphy_free(wdev->wiphy);
3712 kfree(wdev);
3713 cfg_priv->wdev = NULL;
3714}
3715
3716static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv,
3717 const struct brcmf_event_msg *e)
3718{
3719 u32 event = be32_to_cpu(e->event_type);
3720 u32 status = be32_to_cpu(e->status);
3721
3722 if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
3723 WL_CONN("Processing set ssid\n");
3724 cfg_priv->link_up = true;
3725 return true;
3726 }
3727
3728 return false;
3729}
3730
3731static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv,
3732 const struct brcmf_event_msg *e)
3733{
3734 u32 event = be32_to_cpu(e->event_type);
3735 u16 flags = be16_to_cpu(e->flags);
3736
3737 if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) {
3738 WL_CONN("Processing link down\n");
3739 return true;
3740 }
3741 return false;
3742}
3743
3744static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv,
3745 const struct brcmf_event_msg *e)
3746{
3747 u32 event = be32_to_cpu(e->event_type);
3748 u32 status = be32_to_cpu(e->status);
3749
3750 if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) {
3751 WL_CONN("Processing Link %s & no network found\n",
3752 be16_to_cpu(e->flags) & BRCMF_EVENT_MSG_LINK ?
3753 "up" : "down");
3754 return true;
3755 }
3756
3757 if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) {
3758 WL_CONN("Processing connecting & no network found\n");
3759 return true;
3760 }
3761
3762 return false;
3763}
3764
3765static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
3766{
3767 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
3768
3769 kfree(conn_info->req_ie);
3770 conn_info->req_ie = NULL;
3771 conn_info->req_ie_len = 0;
3772 kfree(conn_info->resp_ie);
3773 conn_info->resp_ie = NULL;
3774 conn_info->resp_ie_len = 0;
3775}
3776
3777static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
3778{
3779 struct net_device *ndev = cfg_to_ndev(cfg_priv);
c4e382d2 3780 struct brcmf_cfg80211_assoc_ielen_le *assoc_info;
5b435de0
AS
3781 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
3782 u32 req_len;
3783 u32 resp_len;
3784 s32 err = 0;
3785
3786 brcmf_clear_assoc_ies(cfg_priv);
3787
3788 err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg_priv->extra_buf,
3789 WL_ASSOC_INFO_MAX);
3790 if (err) {
3791 WL_ERR("could not get assoc info (%d)\n", err);
3792 return err;
3793 }
c4e382d2
AS
3794 assoc_info =
3795 (struct brcmf_cfg80211_assoc_ielen_le *)cfg_priv->extra_buf;
3796 req_len = le32_to_cpu(assoc_info->req_len);
3797 resp_len = le32_to_cpu(assoc_info->resp_len);
5b435de0
AS
3798 if (req_len) {
3799 err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies",
3800 cfg_priv->extra_buf,
3801 WL_ASSOC_INFO_MAX);
3802 if (err) {
3803 WL_ERR("could not get assoc req (%d)\n", err);
3804 return err;
3805 }
3806 conn_info->req_ie_len = req_len;
3807 conn_info->req_ie =
3808 kmemdup(cfg_priv->extra_buf, conn_info->req_ie_len,
3809 GFP_KERNEL);
3810 } else {
3811 conn_info->req_ie_len = 0;
3812 conn_info->req_ie = NULL;
3813 }
3814 if (resp_len) {
3815 err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies",
3816 cfg_priv->extra_buf,
3817 WL_ASSOC_INFO_MAX);
3818 if (err) {
3819 WL_ERR("could not get assoc resp (%d)\n", err);
3820 return err;
3821 }
3822 conn_info->resp_ie_len = resp_len;
3823 conn_info->resp_ie =
3824 kmemdup(cfg_priv->extra_buf, conn_info->resp_ie_len,
3825 GFP_KERNEL);
3826 } else {
3827 conn_info->resp_ie_len = 0;
3828 conn_info->resp_ie = NULL;
3829 }
3830 WL_CONN("req len (%d) resp len (%d)\n",
3831 conn_info->req_ie_len, conn_info->resp_ie_len);
3832
3833 return err;
3834}
3835
3836static s32
3837brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
3838 struct net_device *ndev,
3839 const struct brcmf_event_msg *e)
3840{
3841 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
3842 struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
3843 struct brcmf_channel_info_le channel_le;
3844 struct ieee80211_channel *notify_channel;
3845 struct ieee80211_supported_band *band;
3846 u32 freq;
3847 s32 err = 0;
3848 u32 target_channel;
3849
3850 WL_TRACE("Enter\n");
3851
3852 brcmf_get_assoc_ies(cfg_priv);
3853 brcmf_update_prof(cfg_priv, NULL, &e->addr, WL_PROF_BSSID);
3854 brcmf_update_bss_info(cfg_priv);
3855
3856 brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le,
3857 sizeof(channel_le));
3858
3859 target_channel = le32_to_cpu(channel_le.target_channel);
3860 WL_CONN("Roamed to channel %d\n", target_channel);
3861
3862 if (target_channel <= CH_MAX_2G_CHANNEL)
3863 band = wiphy->bands[IEEE80211_BAND_2GHZ];
3864 else
3865 band = wiphy->bands[IEEE80211_BAND_5GHZ];
3866
3867 freq = ieee80211_channel_to_frequency(target_channel, band->band);
3868 notify_channel = ieee80211_get_channel(wiphy, freq);
3869
3870 cfg80211_roamed(ndev, notify_channel,
3871 (u8 *)brcmf_read_prof(cfg_priv, WL_PROF_BSSID),
3872 conn_info->req_ie, conn_info->req_ie_len,
3873 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
3874 WL_CONN("Report roaming result\n");
3875
3876 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
3877 WL_TRACE("Exit\n");
3878 return err;
3879}
3880
3881static s32
3882brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
3883 struct net_device *ndev, const struct brcmf_event_msg *e,
3884 bool completed)
3885{
3886 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
3887 s32 err = 0;
3888
3889 WL_TRACE("Enter\n");
3890
3891 if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
3892 if (completed) {
3893 brcmf_get_assoc_ies(cfg_priv);
3894 brcmf_update_prof(cfg_priv, NULL, &e->addr,
3895 WL_PROF_BSSID);
3896 brcmf_update_bss_info(cfg_priv);
3897 }
3898 cfg80211_connect_result(ndev,
3899 (u8 *)brcmf_read_prof(cfg_priv,
3900 WL_PROF_BSSID),
3901 conn_info->req_ie,
3902 conn_info->req_ie_len,
3903 conn_info->resp_ie,
3904 conn_info->resp_ie_len,
3905 completed ? WLAN_STATUS_SUCCESS :
3906 WLAN_STATUS_AUTH_TIMEOUT,
3907 GFP_KERNEL);
3908 if (completed)
3909 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
3910 WL_CONN("Report connect result - connection %s\n",
3911 completed ? "succeeded" : "failed");
3912 }
3913 WL_TRACE("Exit\n");
3914 return err;
3915}
3916
3917static s32
3918brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv,
3919 struct net_device *ndev,
3920 const struct brcmf_event_msg *e, void *data)
3921{
3922 s32 err = 0;
3923
3924 if (brcmf_is_linkup(cfg_priv, e)) {
3925 WL_CONN("Linkup\n");
3926 if (brcmf_is_ibssmode(cfg_priv)) {
3927 brcmf_update_prof(cfg_priv, NULL, (void *)e->addr,
3928 WL_PROF_BSSID);
3929 wl_inform_ibss(cfg_priv, ndev, e->addr);
3930 cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
3931 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
3932 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
3933 } else
3934 brcmf_bss_connect_done(cfg_priv, ndev, e, true);
3935 } else if (brcmf_is_linkdown(cfg_priv, e)) {
3936 WL_CONN("Linkdown\n");
3937 if (brcmf_is_ibssmode(cfg_priv)) {
3938 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
3939 if (test_and_clear_bit(WL_STATUS_CONNECTED,
3940 &cfg_priv->status))
3941 brcmf_link_down(cfg_priv);
3942 } else {
3943 brcmf_bss_connect_done(cfg_priv, ndev, e, false);
3944 if (test_and_clear_bit(WL_STATUS_CONNECTED,
3945 &cfg_priv->status)) {
3946 cfg80211_disconnected(ndev, 0, NULL, 0,
3947 GFP_KERNEL);
3948 brcmf_link_down(cfg_priv);
3949 }
3950 }
3951 brcmf_init_prof(cfg_priv->profile);
3952 } else if (brcmf_is_nonetwork(cfg_priv, e)) {
3953 if (brcmf_is_ibssmode(cfg_priv))
3954 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
3955 else
3956 brcmf_bss_connect_done(cfg_priv, ndev, e, false);
3957 }
3958
3959 return err;
3960}
3961
3962static s32
3963brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv,
3964 struct net_device *ndev,
3965 const struct brcmf_event_msg *e, void *data)
3966{
3967 s32 err = 0;
3968 u32 event = be32_to_cpu(e->event_type);
3969 u32 status = be32_to_cpu(e->status);
3970
3971 if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
3972 if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status))
3973 brcmf_bss_roaming_done(cfg_priv, ndev, e);
3974 else
3975 brcmf_bss_connect_done(cfg_priv, ndev, e, true);
3976 }
3977
3978 return err;
3979}
3980
3981static s32
3982brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
3983 struct net_device *ndev,
3984 const struct brcmf_event_msg *e, void *data)
3985{
3986 u16 flags = be16_to_cpu(e->flags);
3987 enum nl80211_key_type key_type;
3988
3989 if (flags & BRCMF_EVENT_MSG_GROUP)
3990 key_type = NL80211_KEYTYPE_GROUP;
3991 else
3992 key_type = NL80211_KEYTYPE_PAIRWISE;
3993
3994 cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
3995 NULL, GFP_KERNEL);
3996
3997 return 0;
3998}
3999
4000static s32
4001brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
4002 struct net_device *ndev,
4003 const struct brcmf_event_msg *e, void *data)
4004{
4005 struct brcmf_channel_info_le channel_inform_le;
4006 struct brcmf_scan_results_le *bss_list_le;
4007 u32 len = WL_SCAN_BUF_MAX;
4008 s32 err = 0;
4009 bool scan_abort = false;
4010 u32 scan_channel;
4011
4012 WL_TRACE("Enter\n");
4013
4014 if (cfg_priv->iscan_on && cfg_priv->iscan_kickstart) {
4015 WL_TRACE("Exit\n");
4016 return brcmf_wakeup_iscan(cfg_to_iscan(cfg_priv));
4017 }
4018
4019 if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
4020 WL_ERR("Scan complete while device not scanning\n");
4021 scan_abort = true;
4022 err = -EINVAL;
4023 goto scan_done_out;
4024 }
4025
4026 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_inform_le,
4027 sizeof(channel_inform_le));
4028 if (err) {
4029 WL_ERR("scan busy (%d)\n", err);
4030 scan_abort = true;
4031 goto scan_done_out;
4032 }
4033 scan_channel = le32_to_cpu(channel_inform_le.scan_channel);
4034 if (scan_channel)
4035 WL_CONN("channel_inform.scan_channel (%d)\n", scan_channel);
4036 cfg_priv->bss_list = cfg_priv->scan_results;
4037 bss_list_le = (struct brcmf_scan_results_le *) cfg_priv->bss_list;
4038
4039 memset(cfg_priv->scan_results, 0, len);
4040 bss_list_le->buflen = cpu_to_le32(len);
4041 err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS,
4042 cfg_priv->scan_results, len);
4043 if (err) {
4044 WL_ERR("%s Scan_results error (%d)\n", ndev->name, err);
4045 err = -EINVAL;
4046 scan_abort = true;
4047 goto scan_done_out;
4048 }
4049 cfg_priv->scan_results->buflen = le32_to_cpu(bss_list_le->buflen);
4050 cfg_priv->scan_results->version = le32_to_cpu(bss_list_le->version);
4051 cfg_priv->scan_results->count = le32_to_cpu(bss_list_le->count);
4052
4053 err = brcmf_inform_bss(cfg_priv);
35aafa9d 4054 if (err)
5b435de0 4055 scan_abort = true;
5b435de0
AS
4056
4057scan_done_out:
4058 if (cfg_priv->scan_request) {
4059 WL_SCAN("calling cfg80211_scan_done\n");
4060 cfg80211_scan_done(cfg_priv->scan_request, scan_abort);
4061 brcmf_set_mpc(ndev, 1);
4062 cfg_priv->scan_request = NULL;
4063 }
4064
4065 WL_TRACE("Exit\n");
4066
4067 return err;
4068}
4069
4070static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
4071{
4072 conf->mode = (u32)-1;
4073 conf->frag_threshold = (u32)-1;
4074 conf->rts_threshold = (u32)-1;
4075 conf->retry_short = (u32)-1;
4076 conf->retry_long = (u32)-1;
4077 conf->tx_power = -1;
4078}
4079
4080static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el)
4081{
4082 memset(el, 0, sizeof(*el));
4083 el->handler[BRCMF_E_SCAN_COMPLETE] = brcmf_notify_scan_status;
4084 el->handler[BRCMF_E_LINK] = brcmf_notify_connect_status;
4085 el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status;
4086 el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status;
4087 el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status;
e5806072 4088 el->handler[BRCMF_E_PFN_NET_FOUND] = brcmf_notify_sched_scan_results;
5b435de0
AS
4089}
4090
4091static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
4092{
4093 kfree(cfg_priv->scan_results);
4094 cfg_priv->scan_results = NULL;
4095 kfree(cfg_priv->bss_info);
4096 cfg_priv->bss_info = NULL;
4097 kfree(cfg_priv->conf);
4098 cfg_priv->conf = NULL;
4099 kfree(cfg_priv->profile);
4100 cfg_priv->profile = NULL;
4101 kfree(cfg_priv->scan_req_int);
4102 cfg_priv->scan_req_int = NULL;
e756af5b
HM
4103 kfree(cfg_priv->escan_ioctl_buf);
4104 cfg_priv->escan_ioctl_buf = NULL;
5b435de0
AS
4105 kfree(cfg_priv->dcmd_buf);
4106 cfg_priv->dcmd_buf = NULL;
4107 kfree(cfg_priv->extra_buf);
4108 cfg_priv->extra_buf = NULL;
4109 kfree(cfg_priv->iscan);
4110 cfg_priv->iscan = NULL;
4111 kfree(cfg_priv->pmk_list);
4112 cfg_priv->pmk_list = NULL;
4113}
4114
4115static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
4116{
4117 cfg_priv->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
4118 if (!cfg_priv->scan_results)
4119 goto init_priv_mem_out;
4120 cfg_priv->conf = kzalloc(sizeof(*cfg_priv->conf), GFP_KERNEL);
4121 if (!cfg_priv->conf)
4122 goto init_priv_mem_out;
4123 cfg_priv->profile = kzalloc(sizeof(*cfg_priv->profile), GFP_KERNEL);
4124 if (!cfg_priv->profile)
4125 goto init_priv_mem_out;
4126 cfg_priv->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
4127 if (!cfg_priv->bss_info)
4128 goto init_priv_mem_out;
4129 cfg_priv->scan_req_int = kzalloc(sizeof(*cfg_priv->scan_req_int),
4130 GFP_KERNEL);
4131 if (!cfg_priv->scan_req_int)
4132 goto init_priv_mem_out;
e756af5b
HM
4133 cfg_priv->escan_ioctl_buf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
4134 if (!cfg_priv->escan_ioctl_buf)
4135 goto init_priv_mem_out;
5b435de0
AS
4136 cfg_priv->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL);
4137 if (!cfg_priv->dcmd_buf)
4138 goto init_priv_mem_out;
4139 cfg_priv->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
4140 if (!cfg_priv->extra_buf)
4141 goto init_priv_mem_out;
4142 cfg_priv->iscan = kzalloc(sizeof(*cfg_priv->iscan), GFP_KERNEL);
4143 if (!cfg_priv->iscan)
4144 goto init_priv_mem_out;
4145 cfg_priv->pmk_list = kzalloc(sizeof(*cfg_priv->pmk_list), GFP_KERNEL);
4146 if (!cfg_priv->pmk_list)
4147 goto init_priv_mem_out;
4148
4149 return 0;
4150
4151init_priv_mem_out:
4152 brcmf_deinit_priv_mem(cfg_priv);
4153
4154 return -ENOMEM;
4155}
4156
4157/*
4158* retrieve first queued event from head
4159*/
4160
4161static struct brcmf_cfg80211_event_q *brcmf_deq_event(
4162 struct brcmf_cfg80211_priv *cfg_priv)
4163{
4164 struct brcmf_cfg80211_event_q *e = NULL;
4165
4166 spin_lock_irq(&cfg_priv->evt_q_lock);
4167 if (!list_empty(&cfg_priv->evt_q_list)) {
4168 e = list_first_entry(&cfg_priv->evt_q_list,
4169 struct brcmf_cfg80211_event_q, evt_q_list);
4170 list_del(&e->evt_q_list);
4171 }
4172 spin_unlock_irq(&cfg_priv->evt_q_lock);
4173
4174 return e;
4175}
4176
4177/*
bcbec9e7
AS
4178* push event to tail of the queue
4179*
4180* remark: this function may not sleep as it is called in atomic context.
5b435de0
AS
4181*/
4182
4183static s32
4184brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event,
c4fdb056 4185 const struct brcmf_event_msg *msg, void *data)
5b435de0
AS
4186{
4187 struct brcmf_cfg80211_event_q *e;
4188 s32 err = 0;
cf44066a 4189 ulong flags;
c4fdb056
HM
4190 u32 data_len;
4191 u32 total_len;
5b435de0 4192
c4fdb056
HM
4193 total_len = sizeof(struct brcmf_cfg80211_event_q);
4194 if (data)
4195 data_len = be32_to_cpu(msg->datalen);
4196 else
4197 data_len = 0;
4198 total_len += data_len;
4199 e = kzalloc(total_len, GFP_ATOMIC);
5b435de0
AS
4200 if (!e)
4201 return -ENOMEM;
4202
4203 e->etype = event;
4204 memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
c4fdb056
HM
4205 if (data)
4206 memcpy(&e->edata, data, data_len);
5b435de0 4207
cf44066a 4208 spin_lock_irqsave(&cfg_priv->evt_q_lock, flags);
5b435de0 4209 list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list);
cf44066a 4210 spin_unlock_irqrestore(&cfg_priv->evt_q_lock, flags);
5b435de0
AS
4211
4212 return err;
4213}
4214
4215static void brcmf_put_event(struct brcmf_cfg80211_event_q *e)
4216{
4217 kfree(e);
4218}
4219
4220static void brcmf_cfg80211_event_handler(struct work_struct *work)
4221{
4222 struct brcmf_cfg80211_priv *cfg_priv =
4223 container_of(work, struct brcmf_cfg80211_priv,
4224 event_work);
4225 struct brcmf_cfg80211_event_q *e;
4226
4227 e = brcmf_deq_event(cfg_priv);
4228 if (unlikely(!e)) {
4229 WL_ERR("event queue empty...\n");
4230 return;
4231 }
4232
4233 do {
4234 WL_INFO("event type (%d)\n", e->etype);
4235 if (cfg_priv->el.handler[e->etype])
4236 cfg_priv->el.handler[e->etype](cfg_priv,
4237 cfg_to_ndev(cfg_priv),
4238 &e->emsg, e->edata);
4239 else
4240 WL_INFO("Unknown Event (%d): ignoring\n", e->etype);
4241 brcmf_put_event(e);
4242 } while ((e = brcmf_deq_event(cfg_priv)));
4243
4244}
4245
4246static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv)
4247{
4248 spin_lock_init(&cfg_priv->evt_q_lock);
4249 INIT_LIST_HEAD(&cfg_priv->evt_q_list);
4250}
4251
4252static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv)
4253{
4254 struct brcmf_cfg80211_event_q *e;
4255
4256 spin_lock_irq(&cfg_priv->evt_q_lock);
4257 while (!list_empty(&cfg_priv->evt_q_list)) {
4258 e = list_first_entry(&cfg_priv->evt_q_list,
4259 struct brcmf_cfg80211_event_q, evt_q_list);
4260 list_del(&e->evt_q_list);
4261 kfree(e);
4262 }
4263 spin_unlock_irq(&cfg_priv->evt_q_lock);
4264}
4265
4266static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv)
4267{
4268 s32 err = 0;
4269
4270 cfg_priv->scan_request = NULL;
4271 cfg_priv->pwr_save = true;
e756af5b 4272#ifdef CONFIG_BRCMISCAN
5b435de0
AS
4273 cfg_priv->iscan_on = true; /* iscan on & off switch.
4274 we enable iscan per default */
e756af5b
HM
4275 cfg_priv->escan_on = false; /* escan on & off switch.
4276 we disable escan per default */
4277#else
4278 cfg_priv->iscan_on = false; /* iscan on & off switch.
4279 we disable iscan per default */
4280 cfg_priv->escan_on = true; /* escan on & off switch.
4281 we enable escan per default */
4282#endif
5b435de0
AS
4283 cfg_priv->roam_on = true; /* roam on & off switch.
4284 we enable roam per default */
4285
4286 cfg_priv->iscan_kickstart = false;
4287 cfg_priv->active_scan = true; /* we do active scan for
4288 specific scan per default */
4289 cfg_priv->dongle_up = false; /* dongle is not up yet */
4290 brcmf_init_eq(cfg_priv);
4291 err = brcmf_init_priv_mem(cfg_priv);
4292 if (err)
4293 return err;
4294 INIT_WORK(&cfg_priv->event_work, brcmf_cfg80211_event_handler);
4295 brcmf_init_eloop_handler(&cfg_priv->el);
4296 mutex_init(&cfg_priv->usr_sync);
4297 err = brcmf_init_iscan(cfg_priv);
4298 if (err)
4299 return err;
e756af5b 4300 brcmf_init_escan(cfg_priv);
5b435de0
AS
4301 brcmf_init_conf(cfg_priv->conf);
4302 brcmf_init_prof(cfg_priv->profile);
4303 brcmf_link_down(cfg_priv);
4304
4305 return err;
4306}
4307
4308static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv)
4309{
4310 cancel_work_sync(&cfg_priv->event_work);
4311 cfg_priv->dongle_up = false; /* dongle down */
4312 brcmf_flush_eq(cfg_priv);
4313 brcmf_link_down(cfg_priv);
108a4bee 4314 brcmf_abort_scanning(cfg_priv);
5b435de0
AS
4315 brcmf_deinit_priv_mem(cfg_priv);
4316}
4317
b451ec94
AS
4318struct brcmf_cfg80211_priv *brcmf_cfg80211_attach(struct net_device *ndev,
4319 struct device *busdev,
4320 struct brcmf_pub *drvr)
5b435de0
AS
4321{
4322 struct wireless_dev *wdev;
4323 struct brcmf_cfg80211_priv *cfg_priv;
5b435de0
AS
4324 s32 err = 0;
4325
4326 if (!ndev) {
4327 WL_ERR("ndev is invalid\n");
4328 return NULL;
4329 }
5b435de0 4330
5db6e956 4331 wdev = brcmf_alloc_wdev(busdev);
5b435de0 4332 if (IS_ERR(wdev)) {
5b435de0
AS
4333 return NULL;
4334 }
4335
4336 wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS);
4337 cfg_priv = wdev_to_cfg(wdev);
4338 cfg_priv->wdev = wdev;
ee928381 4339 cfg_priv->pub = drvr;
5b435de0
AS
4340 ndev->ieee80211_ptr = wdev;
4341 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
4342 wdev->netdev = ndev;
4343 err = wl_init_priv(cfg_priv);
4344 if (err) {
4345 WL_ERR("Failed to init iwm_priv (%d)\n", err);
4346 goto cfg80211_attach_out;
4347 }
5db6e956 4348
b451ec94 4349 return cfg_priv;
5b435de0
AS
4350
4351cfg80211_attach_out:
4352 brcmf_free_wdev(cfg_priv);
5b435de0
AS
4353 return NULL;
4354}
4355
b451ec94 4356void brcmf_cfg80211_detach(struct brcmf_cfg80211_priv *cfg_priv)
5b435de0 4357{
5b435de0
AS
4358 wl_deinit_priv(cfg_priv);
4359 brcmf_free_wdev(cfg_priv);
5b435de0
AS
4360}
4361
4362void
4363brcmf_cfg80211_event(struct net_device *ndev,
4364 const struct brcmf_event_msg *e, void *data)
4365{
4366 u32 event_type = be32_to_cpu(e->event_type);
4367 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
4368
c4fdb056 4369 if (!brcmf_enq_event(cfg_priv, event_type, e, data))
5b435de0
AS
4370 schedule_work(&cfg_priv->event_work);
4371}
4372
4373static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
4374{
4375 s32 infra = 0;
4376 s32 err = 0;
4377
4378 switch (iftype) {
4379 case NL80211_IFTYPE_MONITOR:
4380 case NL80211_IFTYPE_WDS:
4381 WL_ERR("type (%d) : currently we do not support this mode\n",
4382 iftype);
4383 err = -EINVAL;
4384 return err;
4385 case NL80211_IFTYPE_ADHOC:
4386 infra = 0;
4387 break;
4388 case NL80211_IFTYPE_STATION:
4389 infra = 1;
4390 break;
4391 default:
4392 err = -EINVAL;
4393 WL_ERR("invalid type (%d)\n", iftype);
4394 return err;
4395 }
4396 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
4397 if (err) {
4398 WL_ERR("WLC_SET_INFRA error (%d)\n", err);
4399 return err;
4400 }
4401
4402 return 0;
4403}
4404
4405static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
4406{
4407 /* Room for "event_msgs" + '\0' + bitvec */
4408 s8 iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
4409 s8 eventmask[BRCMF_EVENTING_MASK_LEN];
4410 s32 err = 0;
4411
4412 WL_TRACE("Enter\n");
4413
4414 /* Setup event_msgs */
53a2277d
AB
4415 brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
4416 iovbuf, sizeof(iovbuf));
5b435de0
AS
4417 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf));
4418 if (err) {
4419 WL_ERR("Get event_msgs error (%d)\n", err);
4420 goto dongle_eventmsg_out;
4421 }
4422 memcpy(eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN);
4423
4424 setbit(eventmask, BRCMF_E_SET_SSID);
4425 setbit(eventmask, BRCMF_E_ROAM);
4426 setbit(eventmask, BRCMF_E_PRUNE);
4427 setbit(eventmask, BRCMF_E_AUTH);
4428 setbit(eventmask, BRCMF_E_REASSOC);
4429 setbit(eventmask, BRCMF_E_REASSOC_IND);
4430 setbit(eventmask, BRCMF_E_DEAUTH_IND);
4431 setbit(eventmask, BRCMF_E_DISASSOC_IND);
4432 setbit(eventmask, BRCMF_E_DISASSOC);
4433 setbit(eventmask, BRCMF_E_JOIN);
4434 setbit(eventmask, BRCMF_E_ASSOC_IND);
4435 setbit(eventmask, BRCMF_E_PSK_SUP);
4436 setbit(eventmask, BRCMF_E_LINK);
4437 setbit(eventmask, BRCMF_E_NDIS_LINK);
4438 setbit(eventmask, BRCMF_E_MIC_ERROR);
4439 setbit(eventmask, BRCMF_E_PMKID_CACHE);
4440 setbit(eventmask, BRCMF_E_TXFAIL);
4441 setbit(eventmask, BRCMF_E_JOIN_START);
4442 setbit(eventmask, BRCMF_E_SCAN_COMPLETE);
e756af5b 4443 setbit(eventmask, BRCMF_E_ESCAN_RESULT);
e5806072 4444 setbit(eventmask, BRCMF_E_PFN_NET_FOUND);
5b435de0 4445
53a2277d
AB
4446 brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
4447 iovbuf, sizeof(iovbuf));
5b435de0
AS
4448 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
4449 if (err) {
4450 WL_ERR("Set event_msgs error (%d)\n", err);
4451 goto dongle_eventmsg_out;
4452 }
4453
4454dongle_eventmsg_out:
4455 WL_TRACE("Exit\n");
4456 return err;
4457}
4458
4459static s32
4460brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
4461{
4462 s8 iovbuf[32];
5b435de0 4463 s32 err = 0;
f588bc0c
AS
4464 __le32 roamtrigger[2];
4465 __le32 roam_delta[2];
4466 __le32 bcn_to_le;
4467 __le32 roamvar_le;
5b435de0
AS
4468
4469 /*
4470 * Setup timeout if Beacons are lost and roam is
4471 * off to report link down
4472 */
4473 if (roamvar) {
f588bc0c 4474 bcn_to_le = cpu_to_le32(bcn_timeout);
53a2277d 4475 brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_to_le,
f588bc0c 4476 sizeof(bcn_to_le), iovbuf, sizeof(iovbuf));
5b435de0
AS
4477 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR,
4478 iovbuf, sizeof(iovbuf));
4479 if (err) {
4480 WL_ERR("bcn_timeout error (%d)\n", err);
4481 goto dongle_rom_out;
4482 }
4483 }
4484
4485 /*
4486 * Enable/Disable built-in roaming to allow supplicant
4487 * to take care of roaming
4488 */
4489 WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On");
f588bc0c 4490 roamvar_le = cpu_to_le32(roamvar);
53a2277d 4491 brcmf_c_mkiovar("roam_off", (char *)&roamvar_le,
f588bc0c 4492 sizeof(roamvar_le), iovbuf, sizeof(iovbuf));
5b435de0
AS
4493 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
4494 if (err) {
4495 WL_ERR("roam_off error (%d)\n", err);
4496 goto dongle_rom_out;
4497 }
4498
f588bc0c
AS
4499 roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL);
4500 roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL);
5b435de0
AS
4501 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_TRIGGER,
4502 (void *)roamtrigger, sizeof(roamtrigger));
4503 if (err) {
4504 WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
4505 goto dongle_rom_out;
4506 }
4507
f588bc0c
AS
4508 roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA);
4509 roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL);
5b435de0
AS
4510 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_DELTA,
4511 (void *)roam_delta, sizeof(roam_delta));
4512 if (err) {
4513 WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err);
4514 goto dongle_rom_out;
4515 }
4516
4517dongle_rom_out:
4518 return err;
4519}
4520
4521static s32
4522brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
c68cdc0f 4523 s32 scan_unassoc_time, s32 scan_passive_time)
5b435de0
AS
4524{
4525 s32 err = 0;
c68cdc0f
AS
4526 __le32 scan_assoc_tm_le = cpu_to_le32(scan_assoc_time);
4527 __le32 scan_unassoc_tm_le = cpu_to_le32(scan_unassoc_time);
4528 __le32 scan_passive_tm_le = cpu_to_le32(scan_passive_time);
5b435de0
AS
4529
4530 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME,
c68cdc0f 4531 &scan_assoc_tm_le, sizeof(scan_assoc_tm_le));
5b435de0
AS
4532 if (err) {
4533 if (err == -EOPNOTSUPP)
4534 WL_INFO("Scan assoc time is not supported\n");
4535 else
4536 WL_ERR("Scan assoc time error (%d)\n", err);
4537 goto dongle_scantime_out;
4538 }
4539 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME,
c68cdc0f 4540 &scan_unassoc_tm_le, sizeof(scan_unassoc_tm_le));
5b435de0
AS
4541 if (err) {
4542 if (err == -EOPNOTSUPP)
4543 WL_INFO("Scan unassoc time is not supported\n");
4544 else
4545 WL_ERR("Scan unassoc time error (%d)\n", err);
4546 goto dongle_scantime_out;
4547 }
4548
4549 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME,
c68cdc0f 4550 &scan_passive_tm_le, sizeof(scan_passive_tm_le));
5b435de0
AS
4551 if (err) {
4552 if (err == -EOPNOTSUPP)
4553 WL_INFO("Scan passive time is not supported\n");
4554 else
4555 WL_ERR("Scan passive time error (%d)\n", err);
4556 goto dongle_scantime_out;
4557 }
4558
4559dongle_scantime_out:
4560 return err;
4561}
4562
4563static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv)
4564{
4565 struct wiphy *wiphy;
4566 s32 phy_list;
4567 s8 phy;
4568 s32 err = 0;
4569
4570 err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST,
4571 &phy_list, sizeof(phy_list));
4572 if (err) {
4573 WL_ERR("error (%d)\n", err);
4574 return err;
4575 }
4576
3ba81376 4577 phy = ((char *)&phy_list)[0];
5b435de0
AS
4578 WL_INFO("%c phy\n", phy);
4579 if (phy == 'n' || phy == 'a') {
4580 wiphy = cfg_to_wiphy(cfg_priv);
4581 wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
4582 }
4583
4584 return err;
4585}
4586
4587static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv)
4588{
4589 return wl_update_wiphybands(cfg_priv);
4590}
4591
4592static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv)
4593{
4594 struct net_device *ndev;
4595 struct wireless_dev *wdev;
4596 s32 power_mode;
4597 s32 err = 0;
4598
4599 if (cfg_priv->dongle_up)
4600 return err;
4601
4602 ndev = cfg_to_ndev(cfg_priv);
4603 wdev = ndev->ieee80211_ptr;
4604
4605 brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
4606 WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
4607
4608 err = brcmf_dongle_eventmsg(ndev);
4609 if (err)
4610 goto default_conf_out;
4611
4612 power_mode = cfg_priv->pwr_save ? PM_FAST : PM_OFF;
4613 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &power_mode);
4614 if (err)
4615 goto default_conf_out;
4616 WL_INFO("power save set to %s\n",
4617 (power_mode ? "enabled" : "disabled"));
4618
4619 err = brcmf_dongle_roam(ndev, (cfg_priv->roam_on ? 0 : 1),
4620 WL_BEACON_TIMEOUT);
4621 if (err)
4622 goto default_conf_out;
4623 err = brcmf_dongle_mode(ndev, wdev->iftype);
4624 if (err && err != -EINPROGRESS)
4625 goto default_conf_out;
4626 err = brcmf_dongle_probecap(cfg_priv);
4627 if (err)
4628 goto default_conf_out;
4629
4630 /* -EINPROGRESS: Call commit handler */
4631
4632default_conf_out:
4633
4634 cfg_priv->dongle_up = true;
4635
4636 return err;
4637
4638}
4639
4640static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv)
4641{
4642 char buf[10+IFNAMSIZ];
4643 struct dentry *fd;
4644 s32 err = 0;
4645
4646 sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name);
4647 cfg_priv->debugfsdir = debugfs_create_dir(buf,
4648 cfg_to_wiphy(cfg_priv)->debugfsdir);
4649
4650 fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir,
4651 (u16 *)&cfg_priv->profile->beacon_interval);
4652 if (!fd) {
4653 err = -ENOMEM;
4654 goto err_out;
4655 }
4656
4657 fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir,
4658 (u8 *)&cfg_priv->profile->dtim_period);
4659 if (!fd) {
4660 err = -ENOMEM;
4661 goto err_out;
4662 }
4663
4664err_out:
4665 return err;
4666}
4667
4668static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv)
4669{
4670 debugfs_remove_recursive(cfg_priv->debugfsdir);
4671 cfg_priv->debugfsdir = NULL;
4672}
4673
4674static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv)
4675{
4676 s32 err = 0;
4677
4678 set_bit(WL_STATUS_READY, &cfg_priv->status);
4679
4680 brcmf_debugfs_add_netdev_params(cfg_priv);
4681
4682 err = brcmf_config_dongle(cfg_priv);
4683 if (err)
4684 return err;
4685
4686 brcmf_invoke_iscan(cfg_priv);
4687
4688 return err;
4689}
4690
4691static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv)
4692{
4693 /*
4694 * While going down, if associated with AP disassociate
4695 * from AP to save power
4696 */
4697 if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
4698 test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
4699 test_bit(WL_STATUS_READY, &cfg_priv->status)) {
4700 WL_INFO("Disassociating from AP");
4701 brcmf_link_down(cfg_priv);
4702
4703 /* Make sure WPA_Supplicant receives all the event
4704 generated due to DISASSOC call to the fw to keep
4705 the state fw and WPA_Supplicant state consistent
4706 */
4707 brcmf_delay(500);
4708 }
4709
108a4bee 4710 brcmf_abort_scanning(cfg_priv);
5b435de0 4711 clear_bit(WL_STATUS_READY, &cfg_priv->status);
5b435de0
AS
4712
4713 brcmf_debugfs_remove_netdev(cfg_priv);
4714
4715 return 0;
4716}
4717
b451ec94 4718s32 brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv)
5b435de0 4719{
5b435de0
AS
4720 s32 err = 0;
4721
5b435de0
AS
4722 mutex_lock(&cfg_priv->usr_sync);
4723 err = __brcmf_cfg80211_up(cfg_priv);
4724 mutex_unlock(&cfg_priv->usr_sync);
4725
4726 return err;
4727}
4728
b451ec94 4729s32 brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv)
5b435de0 4730{
5b435de0
AS
4731 s32 err = 0;
4732
5b435de0
AS
4733 mutex_lock(&cfg_priv->usr_sync);
4734 err = __brcmf_cfg80211_down(cfg_priv);
4735 mutex_unlock(&cfg_priv->usr_sync);
4736
4737 return err;
4738}
4739
This page took 0.307724 seconds and 5 git commands to generate.