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