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