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