blob: 9e69cd725d59ba53b1772d8fc90b3de94f28e16a [file] [log] [blame]
Arend van Spriel5b435de2011-10-05 13:19:03 +02001/*
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;
Arend van Spriel66831072011-10-12 20:51:19 +0200478 __le32 passive_scan;
Arend van Spriel5b435de2011-10-05 13:19:03 +0200479 s32 err = 0;
480
481 /* Broadcast scan by default */
482 memset(&ssid, 0, sizeof(ssid));
483
484 iscan->state = WL_ISCAN_STATE_SCANING;
485
Arend van Spriel66831072011-10-12 20:51:19 +0200486 passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
Arend van Spriel5b435de2011-10-05 13:19:03 +0200487 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;
Arend van Spriel66831072011-10-12 20:51:19 +0200514 __le32 passive_scan;
Arend van Spriel5b435de2011-10-05 13:19:03 +0200515 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
Arend van Spriel66831072011-10-12 20:51:19 +0200570 passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
Arend van Spriel5b435de2011-10-05 13:19:03 +0200571 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;
Arend van Spriel40c8e952011-10-12 20:51:20 +02002470 int pmkid_len;
Arend van Spriel5b435de2011-10-05 13:19:03 +02002471
Arend van Spriel40c8e952011-10-12 20:51:20 +02002472 pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid);
2473
2474 WL_CONN("No of elements %d\n", pmkid_len);
2475 for (i = 0; i < pmkid_len; i++) {
Arend van Spriel5b435de2011-10-05 13:19:03 +02002476 WL_CONN("PMKID[%d]: %pM =\n", i,
2477 &pmk_list->pmkids.pmkid[i].BSSID);
2478 for (j = 0; j < WLAN_PMKID_LEN; j++)
2479 WL_CONN("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]);
2480 }
2481
2482 if (!err)
2483 brcmf_dev_bufvar_set(ndev, "pmkid_info", (char *)pmk_list,
2484 sizeof(*pmk_list));
2485
2486 return err;
2487}
2488
2489static s32
2490brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
2491 struct cfg80211_pmksa *pmksa)
2492{
2493 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2494 struct pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids;
2495 s32 err = 0;
2496 int i;
Arend van Spriel40c8e952011-10-12 20:51:20 +02002497 int pmkid_len;
Arend van Spriel5b435de2011-10-05 13:19:03 +02002498
2499 WL_TRACE("Enter\n");
2500 if (!check_sys_up(wiphy))
2501 return -EIO;
2502
Arend van Spriel40c8e952011-10-12 20:51:20 +02002503 pmkid_len = le32_to_cpu(pmkids->npmkid);
2504 for (i = 0; i < pmkid_len; i++)
Arend van Spriel5b435de2011-10-05 13:19:03 +02002505 if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN))
2506 break;
2507 if (i < WL_NUM_PMKIDS_MAX) {
2508 memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN);
2509 memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
Arend van Spriel40c8e952011-10-12 20:51:20 +02002510 if (i == pmkid_len) {
2511 pmkid_len++;
2512 pmkids->npmkid = cpu_to_le32(pmkid_len);
2513 }
Arend van Spriel5b435de2011-10-05 13:19:03 +02002514 } else
2515 err = -EINVAL;
2516
2517 WL_CONN("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
Arend van Spriel40c8e952011-10-12 20:51:20 +02002518 pmkids->pmkid[pmkid_len].BSSID);
Arend van Spriel5b435de2011-10-05 13:19:03 +02002519 for (i = 0; i < WLAN_PMKID_LEN; i++)
Arend van Spriel40c8e952011-10-12 20:51:20 +02002520 WL_CONN("%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]);
Arend van Spriel5b435de2011-10-05 13:19:03 +02002521
2522 err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
2523
2524 WL_TRACE("Exit\n");
2525 return err;
2526}
2527
2528static s32
2529brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
2530 struct cfg80211_pmksa *pmksa)
2531{
2532 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2533 struct pmkid_list pmkid;
2534 s32 err = 0;
Arend van Spriel40c8e952011-10-12 20:51:20 +02002535 int i, pmkid_len;
Arend van Spriel5b435de2011-10-05 13:19:03 +02002536
2537 WL_TRACE("Enter\n");
2538 if (!check_sys_up(wiphy))
2539 return -EIO;
2540
2541 memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
2542 memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2543
2544 WL_CONN("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
2545 &pmkid.pmkid[0].BSSID);
2546 for (i = 0; i < WLAN_PMKID_LEN; i++)
2547 WL_CONN("%02x\n", pmkid.pmkid[0].PMKID[i]);
2548
Arend van Spriel40c8e952011-10-12 20:51:20 +02002549 pmkid_len = le32_to_cpu(cfg_priv->pmk_list->pmkids.npmkid);
2550 for (i = 0; i < pmkid_len; i++)
Arend van Spriel5b435de2011-10-05 13:19:03 +02002551 if (!memcmp
2552 (pmksa->bssid, &cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
2553 ETH_ALEN))
2554 break;
2555
Arend van Spriel40c8e952011-10-12 20:51:20 +02002556 if ((pmkid_len > 0)
2557 && (i < pmkid_len)) {
Arend van Spriel5b435de2011-10-05 13:19:03 +02002558 memset(&cfg_priv->pmk_list->pmkids.pmkid[i], 0,
2559 sizeof(struct pmkid));
Arend van Spriel40c8e952011-10-12 20:51:20 +02002560 for (; i < (pmkid_len - 1); i++) {
Arend van Spriel5b435de2011-10-05 13:19:03 +02002561 memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
2562 &cfg_priv->pmk_list->pmkids.pmkid[i + 1].BSSID,
2563 ETH_ALEN);
2564 memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].PMKID,
2565 &cfg_priv->pmk_list->pmkids.pmkid[i + 1].PMKID,
2566 WLAN_PMKID_LEN);
2567 }
Arend van Spriel40c8e952011-10-12 20:51:20 +02002568 cfg_priv->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1);
Arend van Spriel5b435de2011-10-05 13:19:03 +02002569 } else
2570 err = -EINVAL;
2571
2572 err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
2573
2574 WL_TRACE("Exit\n");
2575 return err;
2576
2577}
2578
2579static s32
2580brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
2581{
2582 struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2583 s32 err = 0;
2584
2585 WL_TRACE("Enter\n");
2586 if (!check_sys_up(wiphy))
2587 return -EIO;
2588
2589 memset(cfg_priv->pmk_list, 0, sizeof(*cfg_priv->pmk_list));
2590 err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
2591
2592 WL_TRACE("Exit\n");
2593 return err;
2594
2595}
2596
2597static struct cfg80211_ops wl_cfg80211_ops = {
2598 .change_virtual_intf = brcmf_cfg80211_change_iface,
2599 .scan = brcmf_cfg80211_scan,
2600 .set_wiphy_params = brcmf_cfg80211_set_wiphy_params,
2601 .join_ibss = brcmf_cfg80211_join_ibss,
2602 .leave_ibss = brcmf_cfg80211_leave_ibss,
2603 .get_station = brcmf_cfg80211_get_station,
2604 .set_tx_power = brcmf_cfg80211_set_tx_power,
2605 .get_tx_power = brcmf_cfg80211_get_tx_power,
2606 .add_key = brcmf_cfg80211_add_key,
2607 .del_key = brcmf_cfg80211_del_key,
2608 .get_key = brcmf_cfg80211_get_key,
2609 .set_default_key = brcmf_cfg80211_config_default_key,
2610 .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key,
2611 .set_power_mgmt = brcmf_cfg80211_set_power_mgmt,
2612 .set_bitrate_mask = brcmf_cfg80211_set_bitrate_mask,
2613 .connect = brcmf_cfg80211_connect,
2614 .disconnect = brcmf_cfg80211_disconnect,
2615 .suspend = brcmf_cfg80211_suspend,
2616 .resume = brcmf_cfg80211_resume,
2617 .set_pmksa = brcmf_cfg80211_set_pmksa,
2618 .del_pmksa = brcmf_cfg80211_del_pmksa,
2619 .flush_pmksa = brcmf_cfg80211_flush_pmksa
2620};
2621
2622static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
2623{
2624 s32 err = 0;
2625
2626 switch (mode) {
2627 case WL_MODE_BSS:
2628 return NL80211_IFTYPE_STATION;
2629 case WL_MODE_IBSS:
2630 return NL80211_IFTYPE_ADHOC;
2631 default:
2632 return NL80211_IFTYPE_UNSPECIFIED;
2633 }
2634
2635 return err;
2636}
2637
2638static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface,
2639 struct device *ndev)
2640{
2641 struct wireless_dev *wdev;
2642 s32 err = 0;
2643
2644 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
2645 if (!wdev)
2646 return ERR_PTR(-ENOMEM);
2647
2648 wdev->wiphy =
2649 wiphy_new(&wl_cfg80211_ops,
2650 sizeof(struct brcmf_cfg80211_priv) + sizeof_iface);
2651 if (!wdev->wiphy) {
2652 WL_ERR("Couldn not allocate wiphy device\n");
2653 err = -ENOMEM;
2654 goto wiphy_new_out;
2655 }
2656 set_wiphy_dev(wdev->wiphy, ndev);
2657 wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
2658 wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
2659 wdev->wiphy->interface_modes =
2660 BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
2661 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
2662 wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set
2663 * it as 11a by default.
2664 * This will be updated with
2665 * 11n phy tables in
2666 * "ifconfig up"
2667 * if phy has 11n capability
2668 */
2669 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
2670 wdev->wiphy->cipher_suites = __wl_cipher_suites;
2671 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
2672 wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power
2673 * save mode
2674 * by default
2675 */
2676 err = wiphy_register(wdev->wiphy);
2677 if (err < 0) {
2678 WL_ERR("Couldn not register wiphy device (%d)\n", err);
2679 goto wiphy_register_out;
2680 }
2681 return wdev;
2682
2683wiphy_register_out:
2684 wiphy_free(wdev->wiphy);
2685
2686wiphy_new_out:
2687 kfree(wdev);
2688
2689 return ERR_PTR(err);
2690}
2691
2692static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv)
2693{
2694 struct wireless_dev *wdev = cfg_priv->wdev;
2695
2696 if (!wdev) {
2697 WL_ERR("wdev is invalid\n");
2698 return;
2699 }
2700 wiphy_unregister(wdev->wiphy);
2701 wiphy_free(wdev->wiphy);
2702 kfree(wdev);
2703 cfg_priv->wdev = NULL;
2704}
2705
2706static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv,
2707 const struct brcmf_event_msg *e)
2708{
2709 u32 event = be32_to_cpu(e->event_type);
2710 u32 status = be32_to_cpu(e->status);
2711
2712 if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
2713 WL_CONN("Processing set ssid\n");
2714 cfg_priv->link_up = true;
2715 return true;
2716 }
2717
2718 return false;
2719}
2720
2721static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv,
2722 const struct brcmf_event_msg *e)
2723{
2724 u32 event = be32_to_cpu(e->event_type);
2725 u16 flags = be16_to_cpu(e->flags);
2726
2727 if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) {
2728 WL_CONN("Processing link down\n");
2729 return true;
2730 }
2731 return false;
2732}
2733
2734static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv,
2735 const struct brcmf_event_msg *e)
2736{
2737 u32 event = be32_to_cpu(e->event_type);
2738 u32 status = be32_to_cpu(e->status);
2739
2740 if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) {
2741 WL_CONN("Processing Link %s & no network found\n",
2742 be16_to_cpu(e->flags) & BRCMF_EVENT_MSG_LINK ?
2743 "up" : "down");
2744 return true;
2745 }
2746
2747 if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) {
2748 WL_CONN("Processing connecting & no network found\n");
2749 return true;
2750 }
2751
2752 return false;
2753}
2754
2755static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
2756{
2757 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2758
2759 kfree(conn_info->req_ie);
2760 conn_info->req_ie = NULL;
2761 conn_info->req_ie_len = 0;
2762 kfree(conn_info->resp_ie);
2763 conn_info->resp_ie = NULL;
2764 conn_info->resp_ie_len = 0;
2765}
2766
2767static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
2768{
2769 struct net_device *ndev = cfg_to_ndev(cfg_priv);
2770 struct brcmf_cfg80211_assoc_ielen *assoc_info;
2771 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2772 u32 req_len;
2773 u32 resp_len;
2774 s32 err = 0;
2775
2776 brcmf_clear_assoc_ies(cfg_priv);
2777
2778 err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg_priv->extra_buf,
2779 WL_ASSOC_INFO_MAX);
2780 if (err) {
2781 WL_ERR("could not get assoc info (%d)\n", err);
2782 return err;
2783 }
2784 assoc_info = (struct brcmf_cfg80211_assoc_ielen *)cfg_priv->extra_buf;
2785 req_len = assoc_info->req_len;
2786 resp_len = assoc_info->resp_len;
2787 if (req_len) {
2788 err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies",
2789 cfg_priv->extra_buf,
2790 WL_ASSOC_INFO_MAX);
2791 if (err) {
2792 WL_ERR("could not get assoc req (%d)\n", err);
2793 return err;
2794 }
2795 conn_info->req_ie_len = req_len;
2796 conn_info->req_ie =
2797 kmemdup(cfg_priv->extra_buf, conn_info->req_ie_len,
2798 GFP_KERNEL);
2799 } else {
2800 conn_info->req_ie_len = 0;
2801 conn_info->req_ie = NULL;
2802 }
2803 if (resp_len) {
2804 err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies",
2805 cfg_priv->extra_buf,
2806 WL_ASSOC_INFO_MAX);
2807 if (err) {
2808 WL_ERR("could not get assoc resp (%d)\n", err);
2809 return err;
2810 }
2811 conn_info->resp_ie_len = resp_len;
2812 conn_info->resp_ie =
2813 kmemdup(cfg_priv->extra_buf, conn_info->resp_ie_len,
2814 GFP_KERNEL);
2815 } else {
2816 conn_info->resp_ie_len = 0;
2817 conn_info->resp_ie = NULL;
2818 }
2819 WL_CONN("req len (%d) resp len (%d)\n",
2820 conn_info->req_ie_len, conn_info->resp_ie_len);
2821
2822 return err;
2823}
2824
2825static s32
2826brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
2827 struct net_device *ndev,
2828 const struct brcmf_event_msg *e)
2829{
2830 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2831 struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
2832 struct brcmf_channel_info_le channel_le;
2833 struct ieee80211_channel *notify_channel;
2834 struct ieee80211_supported_band *band;
2835 u32 freq;
2836 s32 err = 0;
2837 u32 target_channel;
2838
2839 WL_TRACE("Enter\n");
2840
2841 brcmf_get_assoc_ies(cfg_priv);
2842 brcmf_update_prof(cfg_priv, NULL, &e->addr, WL_PROF_BSSID);
2843 brcmf_update_bss_info(cfg_priv);
2844
2845 brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le,
2846 sizeof(channel_le));
2847
2848 target_channel = le32_to_cpu(channel_le.target_channel);
2849 WL_CONN("Roamed to channel %d\n", target_channel);
2850
2851 if (target_channel <= CH_MAX_2G_CHANNEL)
2852 band = wiphy->bands[IEEE80211_BAND_2GHZ];
2853 else
2854 band = wiphy->bands[IEEE80211_BAND_5GHZ];
2855
2856 freq = ieee80211_channel_to_frequency(target_channel, band->band);
2857 notify_channel = ieee80211_get_channel(wiphy, freq);
2858
2859 cfg80211_roamed(ndev, notify_channel,
2860 (u8 *)brcmf_read_prof(cfg_priv, WL_PROF_BSSID),
2861 conn_info->req_ie, conn_info->req_ie_len,
2862 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
2863 WL_CONN("Report roaming result\n");
2864
2865 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
2866 WL_TRACE("Exit\n");
2867 return err;
2868}
2869
2870static s32
2871brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
2872 struct net_device *ndev, const struct brcmf_event_msg *e,
2873 bool completed)
2874{
2875 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2876 s32 err = 0;
2877
2878 WL_TRACE("Enter\n");
2879
2880 if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
2881 if (completed) {
2882 brcmf_get_assoc_ies(cfg_priv);
2883 brcmf_update_prof(cfg_priv, NULL, &e->addr,
2884 WL_PROF_BSSID);
2885 brcmf_update_bss_info(cfg_priv);
2886 }
2887 cfg80211_connect_result(ndev,
2888 (u8 *)brcmf_read_prof(cfg_priv,
2889 WL_PROF_BSSID),
2890 conn_info->req_ie,
2891 conn_info->req_ie_len,
2892 conn_info->resp_ie,
2893 conn_info->resp_ie_len,
2894 completed ? WLAN_STATUS_SUCCESS :
2895 WLAN_STATUS_AUTH_TIMEOUT,
2896 GFP_KERNEL);
2897 if (completed)
2898 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
2899 WL_CONN("Report connect result - connection %s\n",
2900 completed ? "succeeded" : "failed");
2901 }
2902 WL_TRACE("Exit\n");
2903 return err;
2904}
2905
2906static s32
2907brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv,
2908 struct net_device *ndev,
2909 const struct brcmf_event_msg *e, void *data)
2910{
2911 s32 err = 0;
2912
2913 if (brcmf_is_linkup(cfg_priv, e)) {
2914 WL_CONN("Linkup\n");
2915 if (brcmf_is_ibssmode(cfg_priv)) {
2916 brcmf_update_prof(cfg_priv, NULL, (void *)e->addr,
2917 WL_PROF_BSSID);
2918 wl_inform_ibss(cfg_priv, ndev, e->addr);
2919 cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
2920 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
2921 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
2922 } else
2923 brcmf_bss_connect_done(cfg_priv, ndev, e, true);
2924 } else if (brcmf_is_linkdown(cfg_priv, e)) {
2925 WL_CONN("Linkdown\n");
2926 if (brcmf_is_ibssmode(cfg_priv)) {
2927 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
2928 if (test_and_clear_bit(WL_STATUS_CONNECTED,
2929 &cfg_priv->status))
2930 brcmf_link_down(cfg_priv);
2931 } else {
2932 brcmf_bss_connect_done(cfg_priv, ndev, e, false);
2933 if (test_and_clear_bit(WL_STATUS_CONNECTED,
2934 &cfg_priv->status)) {
2935 cfg80211_disconnected(ndev, 0, NULL, 0,
2936 GFP_KERNEL);
2937 brcmf_link_down(cfg_priv);
2938 }
2939 }
2940 brcmf_init_prof(cfg_priv->profile);
2941 } else if (brcmf_is_nonetwork(cfg_priv, e)) {
2942 if (brcmf_is_ibssmode(cfg_priv))
2943 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
2944 else
2945 brcmf_bss_connect_done(cfg_priv, ndev, e, false);
2946 }
2947
2948 return err;
2949}
2950
2951static s32
2952brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv,
2953 struct net_device *ndev,
2954 const struct brcmf_event_msg *e, void *data)
2955{
2956 s32 err = 0;
2957 u32 event = be32_to_cpu(e->event_type);
2958 u32 status = be32_to_cpu(e->status);
2959
2960 if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
2961 if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status))
2962 brcmf_bss_roaming_done(cfg_priv, ndev, e);
2963 else
2964 brcmf_bss_connect_done(cfg_priv, ndev, e, true);
2965 }
2966
2967 return err;
2968}
2969
2970static s32
2971brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
2972 struct net_device *ndev,
2973 const struct brcmf_event_msg *e, void *data)
2974{
2975 u16 flags = be16_to_cpu(e->flags);
2976 enum nl80211_key_type key_type;
2977
2978 if (flags & BRCMF_EVENT_MSG_GROUP)
2979 key_type = NL80211_KEYTYPE_GROUP;
2980 else
2981 key_type = NL80211_KEYTYPE_PAIRWISE;
2982
2983 cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
2984 NULL, GFP_KERNEL);
2985
2986 return 0;
2987}
2988
2989static s32
2990brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
2991 struct net_device *ndev,
2992 const struct brcmf_event_msg *e, void *data)
2993{
2994 struct brcmf_channel_info_le channel_inform_le;
2995 struct brcmf_scan_results_le *bss_list_le;
2996 u32 len = WL_SCAN_BUF_MAX;
2997 s32 err = 0;
2998 bool scan_abort = false;
2999 u32 scan_channel;
3000
3001 WL_TRACE("Enter\n");
3002
3003 if (cfg_priv->iscan_on && cfg_priv->iscan_kickstart) {
3004 WL_TRACE("Exit\n");
3005 return brcmf_wakeup_iscan(cfg_to_iscan(cfg_priv));
3006 }
3007
3008 if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
3009 WL_ERR("Scan complete while device not scanning\n");
3010 scan_abort = true;
3011 err = -EINVAL;
3012 goto scan_done_out;
3013 }
3014
3015 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_inform_le,
3016 sizeof(channel_inform_le));
3017 if (err) {
3018 WL_ERR("scan busy (%d)\n", err);
3019 scan_abort = true;
3020 goto scan_done_out;
3021 }
3022 scan_channel = le32_to_cpu(channel_inform_le.scan_channel);
3023 if (scan_channel)
3024 WL_CONN("channel_inform.scan_channel (%d)\n", scan_channel);
3025 cfg_priv->bss_list = cfg_priv->scan_results;
3026 bss_list_le = (struct brcmf_scan_results_le *) cfg_priv->bss_list;
3027
3028 memset(cfg_priv->scan_results, 0, len);
3029 bss_list_le->buflen = cpu_to_le32(len);
3030 err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS,
3031 cfg_priv->scan_results, len);
3032 if (err) {
3033 WL_ERR("%s Scan_results error (%d)\n", ndev->name, err);
3034 err = -EINVAL;
3035 scan_abort = true;
3036 goto scan_done_out;
3037 }
3038 cfg_priv->scan_results->buflen = le32_to_cpu(bss_list_le->buflen);
3039 cfg_priv->scan_results->version = le32_to_cpu(bss_list_le->version);
3040 cfg_priv->scan_results->count = le32_to_cpu(bss_list_le->count);
3041
3042 err = brcmf_inform_bss(cfg_priv);
3043 if (err) {
3044 scan_abort = true;
3045 goto scan_done_out;
3046 }
3047
3048scan_done_out:
3049 if (cfg_priv->scan_request) {
3050 WL_SCAN("calling cfg80211_scan_done\n");
3051 cfg80211_scan_done(cfg_priv->scan_request, scan_abort);
3052 brcmf_set_mpc(ndev, 1);
3053 cfg_priv->scan_request = NULL;
3054 }
3055
3056 WL_TRACE("Exit\n");
3057
3058 return err;
3059}
3060
3061static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
3062{
3063 conf->mode = (u32)-1;
3064 conf->frag_threshold = (u32)-1;
3065 conf->rts_threshold = (u32)-1;
3066 conf->retry_short = (u32)-1;
3067 conf->retry_long = (u32)-1;
3068 conf->tx_power = -1;
3069}
3070
3071static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el)
3072{
3073 memset(el, 0, sizeof(*el));
3074 el->handler[BRCMF_E_SCAN_COMPLETE] = brcmf_notify_scan_status;
3075 el->handler[BRCMF_E_LINK] = brcmf_notify_connect_status;
3076 el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status;
3077 el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status;
3078 el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status;
3079}
3080
3081static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
3082{
3083 kfree(cfg_priv->scan_results);
3084 cfg_priv->scan_results = NULL;
3085 kfree(cfg_priv->bss_info);
3086 cfg_priv->bss_info = NULL;
3087 kfree(cfg_priv->conf);
3088 cfg_priv->conf = NULL;
3089 kfree(cfg_priv->profile);
3090 cfg_priv->profile = NULL;
3091 kfree(cfg_priv->scan_req_int);
3092 cfg_priv->scan_req_int = NULL;
3093 kfree(cfg_priv->dcmd_buf);
3094 cfg_priv->dcmd_buf = NULL;
3095 kfree(cfg_priv->extra_buf);
3096 cfg_priv->extra_buf = NULL;
3097 kfree(cfg_priv->iscan);
3098 cfg_priv->iscan = NULL;
3099 kfree(cfg_priv->pmk_list);
3100 cfg_priv->pmk_list = NULL;
3101}
3102
3103static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
3104{
3105 cfg_priv->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
3106 if (!cfg_priv->scan_results)
3107 goto init_priv_mem_out;
3108 cfg_priv->conf = kzalloc(sizeof(*cfg_priv->conf), GFP_KERNEL);
3109 if (!cfg_priv->conf)
3110 goto init_priv_mem_out;
3111 cfg_priv->profile = kzalloc(sizeof(*cfg_priv->profile), GFP_KERNEL);
3112 if (!cfg_priv->profile)
3113 goto init_priv_mem_out;
3114 cfg_priv->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
3115 if (!cfg_priv->bss_info)
3116 goto init_priv_mem_out;
3117 cfg_priv->scan_req_int = kzalloc(sizeof(*cfg_priv->scan_req_int),
3118 GFP_KERNEL);
3119 if (!cfg_priv->scan_req_int)
3120 goto init_priv_mem_out;
3121 cfg_priv->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL);
3122 if (!cfg_priv->dcmd_buf)
3123 goto init_priv_mem_out;
3124 cfg_priv->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
3125 if (!cfg_priv->extra_buf)
3126 goto init_priv_mem_out;
3127 cfg_priv->iscan = kzalloc(sizeof(*cfg_priv->iscan), GFP_KERNEL);
3128 if (!cfg_priv->iscan)
3129 goto init_priv_mem_out;
3130 cfg_priv->pmk_list = kzalloc(sizeof(*cfg_priv->pmk_list), GFP_KERNEL);
3131 if (!cfg_priv->pmk_list)
3132 goto init_priv_mem_out;
3133
3134 return 0;
3135
3136init_priv_mem_out:
3137 brcmf_deinit_priv_mem(cfg_priv);
3138
3139 return -ENOMEM;
3140}
3141
3142/*
3143* retrieve first queued event from head
3144*/
3145
3146static struct brcmf_cfg80211_event_q *brcmf_deq_event(
3147 struct brcmf_cfg80211_priv *cfg_priv)
3148{
3149 struct brcmf_cfg80211_event_q *e = NULL;
3150
3151 spin_lock_irq(&cfg_priv->evt_q_lock);
3152 if (!list_empty(&cfg_priv->evt_q_list)) {
3153 e = list_first_entry(&cfg_priv->evt_q_list,
3154 struct brcmf_cfg80211_event_q, evt_q_list);
3155 list_del(&e->evt_q_list);
3156 }
3157 spin_unlock_irq(&cfg_priv->evt_q_lock);
3158
3159 return e;
3160}
3161
3162/*
3163** push event to tail of the queue
3164*/
3165
3166static s32
3167brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event,
3168 const struct brcmf_event_msg *msg)
3169{
3170 struct brcmf_cfg80211_event_q *e;
3171 s32 err = 0;
3172
3173 e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_KERNEL);
3174 if (!e)
3175 return -ENOMEM;
3176
3177 e->etype = event;
3178 memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
3179
3180 spin_lock_irq(&cfg_priv->evt_q_lock);
3181 list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list);
3182 spin_unlock_irq(&cfg_priv->evt_q_lock);
3183
3184 return err;
3185}
3186
3187static void brcmf_put_event(struct brcmf_cfg80211_event_q *e)
3188{
3189 kfree(e);
3190}
3191
3192static void brcmf_cfg80211_event_handler(struct work_struct *work)
3193{
3194 struct brcmf_cfg80211_priv *cfg_priv =
3195 container_of(work, struct brcmf_cfg80211_priv,
3196 event_work);
3197 struct brcmf_cfg80211_event_q *e;
3198
3199 e = brcmf_deq_event(cfg_priv);
3200 if (unlikely(!e)) {
3201 WL_ERR("event queue empty...\n");
3202 return;
3203 }
3204
3205 do {
3206 WL_INFO("event type (%d)\n", e->etype);
3207 if (cfg_priv->el.handler[e->etype])
3208 cfg_priv->el.handler[e->etype](cfg_priv,
3209 cfg_to_ndev(cfg_priv),
3210 &e->emsg, e->edata);
3211 else
3212 WL_INFO("Unknown Event (%d): ignoring\n", e->etype);
3213 brcmf_put_event(e);
3214 } while ((e = brcmf_deq_event(cfg_priv)));
3215
3216}
3217
3218static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv)
3219{
3220 spin_lock_init(&cfg_priv->evt_q_lock);
3221 INIT_LIST_HEAD(&cfg_priv->evt_q_list);
3222}
3223
3224static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv)
3225{
3226 struct brcmf_cfg80211_event_q *e;
3227
3228 spin_lock_irq(&cfg_priv->evt_q_lock);
3229 while (!list_empty(&cfg_priv->evt_q_list)) {
3230 e = list_first_entry(&cfg_priv->evt_q_list,
3231 struct brcmf_cfg80211_event_q, evt_q_list);
3232 list_del(&e->evt_q_list);
3233 kfree(e);
3234 }
3235 spin_unlock_irq(&cfg_priv->evt_q_lock);
3236}
3237
3238static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv)
3239{
3240 s32 err = 0;
3241
3242 cfg_priv->scan_request = NULL;
3243 cfg_priv->pwr_save = true;
3244 cfg_priv->iscan_on = true; /* iscan on & off switch.
3245 we enable iscan per default */
3246 cfg_priv->roam_on = true; /* roam on & off switch.
3247 we enable roam per default */
3248
3249 cfg_priv->iscan_kickstart = false;
3250 cfg_priv->active_scan = true; /* we do active scan for
3251 specific scan per default */
3252 cfg_priv->dongle_up = false; /* dongle is not up yet */
3253 brcmf_init_eq(cfg_priv);
3254 err = brcmf_init_priv_mem(cfg_priv);
3255 if (err)
3256 return err;
3257 INIT_WORK(&cfg_priv->event_work, brcmf_cfg80211_event_handler);
3258 brcmf_init_eloop_handler(&cfg_priv->el);
3259 mutex_init(&cfg_priv->usr_sync);
3260 err = brcmf_init_iscan(cfg_priv);
3261 if (err)
3262 return err;
3263 brcmf_init_conf(cfg_priv->conf);
3264 brcmf_init_prof(cfg_priv->profile);
3265 brcmf_link_down(cfg_priv);
3266
3267 return err;
3268}
3269
3270static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv)
3271{
3272 cancel_work_sync(&cfg_priv->event_work);
3273 cfg_priv->dongle_up = false; /* dongle down */
3274 brcmf_flush_eq(cfg_priv);
3275 brcmf_link_down(cfg_priv);
3276 brcmf_term_iscan(cfg_priv);
3277 brcmf_deinit_priv_mem(cfg_priv);
3278}
3279
3280struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev,
3281 struct device *busdev,
3282 void *data)
3283{
3284 struct wireless_dev *wdev;
3285 struct brcmf_cfg80211_priv *cfg_priv;
3286 struct brcmf_cfg80211_iface *ci;
3287 struct brcmf_cfg80211_dev *cfg_dev;
3288 s32 err = 0;
3289
3290 if (!ndev) {
3291 WL_ERR("ndev is invalid\n");
3292 return NULL;
3293 }
3294 cfg_dev = kzalloc(sizeof(struct brcmf_cfg80211_dev), GFP_KERNEL);
3295 if (!cfg_dev)
3296 return NULL;
3297
3298 wdev = brcmf_alloc_wdev(sizeof(struct brcmf_cfg80211_iface), busdev);
3299 if (IS_ERR(wdev)) {
3300 kfree(cfg_dev);
3301 return NULL;
3302 }
3303
3304 wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS);
3305 cfg_priv = wdev_to_cfg(wdev);
3306 cfg_priv->wdev = wdev;
3307 cfg_priv->pub = data;
3308 ci = (struct brcmf_cfg80211_iface *)&cfg_priv->ci;
3309 ci->cfg_priv = cfg_priv;
3310 ndev->ieee80211_ptr = wdev;
3311 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
3312 wdev->netdev = ndev;
3313 err = wl_init_priv(cfg_priv);
3314 if (err) {
3315 WL_ERR("Failed to init iwm_priv (%d)\n", err);
3316 goto cfg80211_attach_out;
3317 }
3318 brcmf_set_drvdata(cfg_dev, ci);
3319
3320 return cfg_dev;
3321
3322cfg80211_attach_out:
3323 brcmf_free_wdev(cfg_priv);
3324 kfree(cfg_dev);
3325 return NULL;
3326}
3327
3328void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg_dev)
3329{
3330 struct brcmf_cfg80211_priv *cfg_priv;
3331
3332 cfg_priv = brcmf_priv_get(cfg_dev);
3333
3334 wl_deinit_priv(cfg_priv);
3335 brcmf_free_wdev(cfg_priv);
3336 brcmf_set_drvdata(cfg_dev, NULL);
3337 kfree(cfg_dev);
3338}
3339
3340void
3341brcmf_cfg80211_event(struct net_device *ndev,
3342 const struct brcmf_event_msg *e, void *data)
3343{
3344 u32 event_type = be32_to_cpu(e->event_type);
3345 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
3346
3347 if (!brcmf_enq_event(cfg_priv, event_type, e))
3348 schedule_work(&cfg_priv->event_work);
3349}
3350
3351static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
3352{
3353 s32 infra = 0;
3354 s32 err = 0;
3355
3356 switch (iftype) {
3357 case NL80211_IFTYPE_MONITOR:
3358 case NL80211_IFTYPE_WDS:
3359 WL_ERR("type (%d) : currently we do not support this mode\n",
3360 iftype);
3361 err = -EINVAL;
3362 return err;
3363 case NL80211_IFTYPE_ADHOC:
3364 infra = 0;
3365 break;
3366 case NL80211_IFTYPE_STATION:
3367 infra = 1;
3368 break;
3369 default:
3370 err = -EINVAL;
3371 WL_ERR("invalid type (%d)\n", iftype);
3372 return err;
3373 }
3374 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
3375 if (err) {
3376 WL_ERR("WLC_SET_INFRA error (%d)\n", err);
3377 return err;
3378 }
3379
3380 return 0;
3381}
3382
3383static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
3384{
3385 /* Room for "event_msgs" + '\0' + bitvec */
3386 s8 iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
3387 s8 eventmask[BRCMF_EVENTING_MASK_LEN];
3388 s32 err = 0;
3389
3390 WL_TRACE("Enter\n");
3391
3392 /* Setup event_msgs */
3393 brcmu_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, iovbuf,
3394 sizeof(iovbuf));
3395 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf));
3396 if (err) {
3397 WL_ERR("Get event_msgs error (%d)\n", err);
3398 goto dongle_eventmsg_out;
3399 }
3400 memcpy(eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN);
3401
3402 setbit(eventmask, BRCMF_E_SET_SSID);
3403 setbit(eventmask, BRCMF_E_ROAM);
3404 setbit(eventmask, BRCMF_E_PRUNE);
3405 setbit(eventmask, BRCMF_E_AUTH);
3406 setbit(eventmask, BRCMF_E_REASSOC);
3407 setbit(eventmask, BRCMF_E_REASSOC_IND);
3408 setbit(eventmask, BRCMF_E_DEAUTH_IND);
3409 setbit(eventmask, BRCMF_E_DISASSOC_IND);
3410 setbit(eventmask, BRCMF_E_DISASSOC);
3411 setbit(eventmask, BRCMF_E_JOIN);
3412 setbit(eventmask, BRCMF_E_ASSOC_IND);
3413 setbit(eventmask, BRCMF_E_PSK_SUP);
3414 setbit(eventmask, BRCMF_E_LINK);
3415 setbit(eventmask, BRCMF_E_NDIS_LINK);
3416 setbit(eventmask, BRCMF_E_MIC_ERROR);
3417 setbit(eventmask, BRCMF_E_PMKID_CACHE);
3418 setbit(eventmask, BRCMF_E_TXFAIL);
3419 setbit(eventmask, BRCMF_E_JOIN_START);
3420 setbit(eventmask, BRCMF_E_SCAN_COMPLETE);
3421
3422 brcmu_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, iovbuf,
3423 sizeof(iovbuf));
3424 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
3425 if (err) {
3426 WL_ERR("Set event_msgs error (%d)\n", err);
3427 goto dongle_eventmsg_out;
3428 }
3429
3430dongle_eventmsg_out:
3431 WL_TRACE("Exit\n");
3432 return err;
3433}
3434
3435static s32
3436brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
3437{
3438 s8 iovbuf[32];
3439 s32 roamtrigger[2];
3440 s32 roam_delta[2];
3441 s32 err = 0;
3442
3443 /*
3444 * Setup timeout if Beacons are lost and roam is
3445 * off to report link down
3446 */
3447 if (roamvar) {
3448 brcmu_mkiovar("bcn_timeout", (char *)&bcn_timeout,
3449 sizeof(bcn_timeout), iovbuf, sizeof(iovbuf));
3450 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR,
3451 iovbuf, sizeof(iovbuf));
3452 if (err) {
3453 WL_ERR("bcn_timeout error (%d)\n", err);
3454 goto dongle_rom_out;
3455 }
3456 }
3457
3458 /*
3459 * Enable/Disable built-in roaming to allow supplicant
3460 * to take care of roaming
3461 */
3462 WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On");
3463 brcmu_mkiovar("roam_off", (char *)&roamvar,
3464 sizeof(roamvar), iovbuf, sizeof(iovbuf));
3465 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
3466 if (err) {
3467 WL_ERR("roam_off error (%d)\n", err);
3468 goto dongle_rom_out;
3469 }
3470
3471 roamtrigger[0] = WL_ROAM_TRIGGER_LEVEL;
3472 roamtrigger[1] = BRCM_BAND_ALL;
3473 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_TRIGGER,
3474 (void *)roamtrigger, sizeof(roamtrigger));
3475 if (err) {
3476 WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
3477 goto dongle_rom_out;
3478 }
3479
3480 roam_delta[0] = WL_ROAM_DELTA;
3481 roam_delta[1] = BRCM_BAND_ALL;
3482 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_DELTA,
3483 (void *)roam_delta, sizeof(roam_delta));
3484 if (err) {
3485 WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err);
3486 goto dongle_rom_out;
3487 }
3488
3489dongle_rom_out:
3490 return err;
3491}
3492
3493static s32
3494brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
3495 s32 scan_unassoc_time, s32 scan_passive_time)
3496{
3497 s32 err = 0;
3498
3499 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME,
3500 &scan_assoc_time, sizeof(scan_assoc_time));
3501 if (err) {
3502 if (err == -EOPNOTSUPP)
3503 WL_INFO("Scan assoc time is not supported\n");
3504 else
3505 WL_ERR("Scan assoc time error (%d)\n", err);
3506 goto dongle_scantime_out;
3507 }
3508 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME,
3509 &scan_unassoc_time, sizeof(scan_unassoc_time));
3510 if (err) {
3511 if (err == -EOPNOTSUPP)
3512 WL_INFO("Scan unassoc time is not supported\n");
3513 else
3514 WL_ERR("Scan unassoc time error (%d)\n", err);
3515 goto dongle_scantime_out;
3516 }
3517
3518 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME,
3519 &scan_passive_time, sizeof(scan_passive_time));
3520 if (err) {
3521 if (err == -EOPNOTSUPP)
3522 WL_INFO("Scan passive time is not supported\n");
3523 else
3524 WL_ERR("Scan passive time error (%d)\n", err);
3525 goto dongle_scantime_out;
3526 }
3527
3528dongle_scantime_out:
3529 return err;
3530}
3531
3532static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv)
3533{
3534 struct wiphy *wiphy;
3535 s32 phy_list;
3536 s8 phy;
3537 s32 err = 0;
3538
3539 err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST,
3540 &phy_list, sizeof(phy_list));
3541 if (err) {
3542 WL_ERR("error (%d)\n", err);
3543 return err;
3544 }
3545
3546 phy = ((char *)&phy_list)[1];
3547 WL_INFO("%c phy\n", phy);
3548 if (phy == 'n' || phy == 'a') {
3549 wiphy = cfg_to_wiphy(cfg_priv);
3550 wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
3551 }
3552
3553 return err;
3554}
3555
3556static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv)
3557{
3558 return wl_update_wiphybands(cfg_priv);
3559}
3560
3561static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv)
3562{
3563 struct net_device *ndev;
3564 struct wireless_dev *wdev;
3565 s32 power_mode;
3566 s32 err = 0;
3567
3568 if (cfg_priv->dongle_up)
3569 return err;
3570
3571 ndev = cfg_to_ndev(cfg_priv);
3572 wdev = ndev->ieee80211_ptr;
3573
3574 brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
3575 WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
3576
3577 err = brcmf_dongle_eventmsg(ndev);
3578 if (err)
3579 goto default_conf_out;
3580
3581 power_mode = cfg_priv->pwr_save ? PM_FAST : PM_OFF;
3582 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &power_mode);
3583 if (err)
3584 goto default_conf_out;
3585 WL_INFO("power save set to %s\n",
3586 (power_mode ? "enabled" : "disabled"));
3587
3588 err = brcmf_dongle_roam(ndev, (cfg_priv->roam_on ? 0 : 1),
3589 WL_BEACON_TIMEOUT);
3590 if (err)
3591 goto default_conf_out;
3592 err = brcmf_dongle_mode(ndev, wdev->iftype);
3593 if (err && err != -EINPROGRESS)
3594 goto default_conf_out;
3595 err = brcmf_dongle_probecap(cfg_priv);
3596 if (err)
3597 goto default_conf_out;
3598
3599 /* -EINPROGRESS: Call commit handler */
3600
3601default_conf_out:
3602
3603 cfg_priv->dongle_up = true;
3604
3605 return err;
3606
3607}
3608
3609static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv)
3610{
3611 char buf[10+IFNAMSIZ];
3612 struct dentry *fd;
3613 s32 err = 0;
3614
3615 sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name);
3616 cfg_priv->debugfsdir = debugfs_create_dir(buf,
3617 cfg_to_wiphy(cfg_priv)->debugfsdir);
3618
3619 fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir,
3620 (u16 *)&cfg_priv->profile->beacon_interval);
3621 if (!fd) {
3622 err = -ENOMEM;
3623 goto err_out;
3624 }
3625
3626 fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir,
3627 (u8 *)&cfg_priv->profile->dtim_period);
3628 if (!fd) {
3629 err = -ENOMEM;
3630 goto err_out;
3631 }
3632
3633err_out:
3634 return err;
3635}
3636
3637static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv)
3638{
3639 debugfs_remove_recursive(cfg_priv->debugfsdir);
3640 cfg_priv->debugfsdir = NULL;
3641}
3642
3643static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv)
3644{
3645 s32 err = 0;
3646
3647 set_bit(WL_STATUS_READY, &cfg_priv->status);
3648
3649 brcmf_debugfs_add_netdev_params(cfg_priv);
3650
3651 err = brcmf_config_dongle(cfg_priv);
3652 if (err)
3653 return err;
3654
3655 brcmf_invoke_iscan(cfg_priv);
3656
3657 return err;
3658}
3659
3660static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv)
3661{
3662 /*
3663 * While going down, if associated with AP disassociate
3664 * from AP to save power
3665 */
3666 if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
3667 test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
3668 test_bit(WL_STATUS_READY, &cfg_priv->status)) {
3669 WL_INFO("Disassociating from AP");
3670 brcmf_link_down(cfg_priv);
3671
3672 /* Make sure WPA_Supplicant receives all the event
3673 generated due to DISASSOC call to the fw to keep
3674 the state fw and WPA_Supplicant state consistent
3675 */
3676 brcmf_delay(500);
3677 }
3678
3679 set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
3680 brcmf_term_iscan(cfg_priv);
3681 if (cfg_priv->scan_request) {
3682 cfg80211_scan_done(cfg_priv->scan_request, true);
3683 /* May need to perform this to cover rmmod */
3684 /* wl_set_mpc(cfg_to_ndev(wl), 1); */
3685 cfg_priv->scan_request = NULL;
3686 }
3687 clear_bit(WL_STATUS_READY, &cfg_priv->status);
3688 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
3689 clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
3690
3691 brcmf_debugfs_remove_netdev(cfg_priv);
3692
3693 return 0;
3694}
3695
3696s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev)
3697{
3698 struct brcmf_cfg80211_priv *cfg_priv;
3699 s32 err = 0;
3700
3701 cfg_priv = brcmf_priv_get(cfg_dev);
3702 mutex_lock(&cfg_priv->usr_sync);
3703 err = __brcmf_cfg80211_up(cfg_priv);
3704 mutex_unlock(&cfg_priv->usr_sync);
3705
3706 return err;
3707}
3708
3709s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev)
3710{
3711 struct brcmf_cfg80211_priv *cfg_priv;
3712 s32 err = 0;
3713
3714 cfg_priv = brcmf_priv_get(cfg_dev);
3715 mutex_lock(&cfg_priv->usr_sync);
3716 err = __brcmf_cfg80211_down(cfg_priv);
3717 mutex_unlock(&cfg_priv->usr_sync);
3718
3719 return err;
3720}
3721
3722static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv,
3723 u8 t, u8 l, u8 *v)
3724{
3725 struct brcmf_cfg80211_ie *ie = &cfg_priv->ie;
3726 s32 err = 0;
3727
3728 if (ie->offset + l + 2 > WL_TLV_INFO_MAX) {
3729 WL_ERR("ei crosses buffer boundary\n");
3730 return -ENOSPC;
3731 }
3732 ie->buf[ie->offset] = t;
3733 ie->buf[ie->offset + 1] = l;
3734 memcpy(&ie->buf[ie->offset + 2], v, l);
3735 ie->offset += l + 2;
3736
3737 return err;
3738}