blob: 8fc81739e6b7dfd819ee6d0937365504b4908489 [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);
Arend van Sprielc4e382d2011-10-12 20:51:21 +02002770 struct brcmf_cfg80211_assoc_ielen_le *assoc_info;
Arend van Spriel5b435de2011-10-05 13:19:03 +02002771 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 }
Arend van Sprielc4e382d2011-10-12 20:51:21 +02002784 assoc_info =
2785 (struct brcmf_cfg80211_assoc_ielen_le *)cfg_priv->extra_buf;
2786 req_len = le32_to_cpu(assoc_info->req_len);
2787 resp_len = le32_to_cpu(assoc_info->resp_len);
Arend van Spriel5b435de2011-10-05 13:19:03 +02002788 if (req_len) {
2789 err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies",
2790 cfg_priv->extra_buf,
2791 WL_ASSOC_INFO_MAX);
2792 if (err) {
2793 WL_ERR("could not get assoc req (%d)\n", err);
2794 return err;
2795 }
2796 conn_info->req_ie_len = req_len;
2797 conn_info->req_ie =
2798 kmemdup(cfg_priv->extra_buf, conn_info->req_ie_len,
2799 GFP_KERNEL);
2800 } else {
2801 conn_info->req_ie_len = 0;
2802 conn_info->req_ie = NULL;
2803 }
2804 if (resp_len) {
2805 err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies",
2806 cfg_priv->extra_buf,
2807 WL_ASSOC_INFO_MAX);
2808 if (err) {
2809 WL_ERR("could not get assoc resp (%d)\n", err);
2810 return err;
2811 }
2812 conn_info->resp_ie_len = resp_len;
2813 conn_info->resp_ie =
2814 kmemdup(cfg_priv->extra_buf, conn_info->resp_ie_len,
2815 GFP_KERNEL);
2816 } else {
2817 conn_info->resp_ie_len = 0;
2818 conn_info->resp_ie = NULL;
2819 }
2820 WL_CONN("req len (%d) resp len (%d)\n",
2821 conn_info->req_ie_len, conn_info->resp_ie_len);
2822
2823 return err;
2824}
2825
2826static s32
2827brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
2828 struct net_device *ndev,
2829 const struct brcmf_event_msg *e)
2830{
2831 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2832 struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
2833 struct brcmf_channel_info_le channel_le;
2834 struct ieee80211_channel *notify_channel;
2835 struct ieee80211_supported_band *band;
2836 u32 freq;
2837 s32 err = 0;
2838 u32 target_channel;
2839
2840 WL_TRACE("Enter\n");
2841
2842 brcmf_get_assoc_ies(cfg_priv);
2843 brcmf_update_prof(cfg_priv, NULL, &e->addr, WL_PROF_BSSID);
2844 brcmf_update_bss_info(cfg_priv);
2845
2846 brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le,
2847 sizeof(channel_le));
2848
2849 target_channel = le32_to_cpu(channel_le.target_channel);
2850 WL_CONN("Roamed to channel %d\n", target_channel);
2851
2852 if (target_channel <= CH_MAX_2G_CHANNEL)
2853 band = wiphy->bands[IEEE80211_BAND_2GHZ];
2854 else
2855 band = wiphy->bands[IEEE80211_BAND_5GHZ];
2856
2857 freq = ieee80211_channel_to_frequency(target_channel, band->band);
2858 notify_channel = ieee80211_get_channel(wiphy, freq);
2859
2860 cfg80211_roamed(ndev, notify_channel,
2861 (u8 *)brcmf_read_prof(cfg_priv, WL_PROF_BSSID),
2862 conn_info->req_ie, conn_info->req_ie_len,
2863 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
2864 WL_CONN("Report roaming result\n");
2865
2866 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
2867 WL_TRACE("Exit\n");
2868 return err;
2869}
2870
2871static s32
2872brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
2873 struct net_device *ndev, const struct brcmf_event_msg *e,
2874 bool completed)
2875{
2876 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2877 s32 err = 0;
2878
2879 WL_TRACE("Enter\n");
2880
2881 if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
2882 if (completed) {
2883 brcmf_get_assoc_ies(cfg_priv);
2884 brcmf_update_prof(cfg_priv, NULL, &e->addr,
2885 WL_PROF_BSSID);
2886 brcmf_update_bss_info(cfg_priv);
2887 }
2888 cfg80211_connect_result(ndev,
2889 (u8 *)brcmf_read_prof(cfg_priv,
2890 WL_PROF_BSSID),
2891 conn_info->req_ie,
2892 conn_info->req_ie_len,
2893 conn_info->resp_ie,
2894 conn_info->resp_ie_len,
2895 completed ? WLAN_STATUS_SUCCESS :
2896 WLAN_STATUS_AUTH_TIMEOUT,
2897 GFP_KERNEL);
2898 if (completed)
2899 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
2900 WL_CONN("Report connect result - connection %s\n",
2901 completed ? "succeeded" : "failed");
2902 }
2903 WL_TRACE("Exit\n");
2904 return err;
2905}
2906
2907static s32
2908brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv,
2909 struct net_device *ndev,
2910 const struct brcmf_event_msg *e, void *data)
2911{
2912 s32 err = 0;
2913
2914 if (brcmf_is_linkup(cfg_priv, e)) {
2915 WL_CONN("Linkup\n");
2916 if (brcmf_is_ibssmode(cfg_priv)) {
2917 brcmf_update_prof(cfg_priv, NULL, (void *)e->addr,
2918 WL_PROF_BSSID);
2919 wl_inform_ibss(cfg_priv, ndev, e->addr);
2920 cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
2921 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
2922 set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
2923 } else
2924 brcmf_bss_connect_done(cfg_priv, ndev, e, true);
2925 } else if (brcmf_is_linkdown(cfg_priv, e)) {
2926 WL_CONN("Linkdown\n");
2927 if (brcmf_is_ibssmode(cfg_priv)) {
2928 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
2929 if (test_and_clear_bit(WL_STATUS_CONNECTED,
2930 &cfg_priv->status))
2931 brcmf_link_down(cfg_priv);
2932 } else {
2933 brcmf_bss_connect_done(cfg_priv, ndev, e, false);
2934 if (test_and_clear_bit(WL_STATUS_CONNECTED,
2935 &cfg_priv->status)) {
2936 cfg80211_disconnected(ndev, 0, NULL, 0,
2937 GFP_KERNEL);
2938 brcmf_link_down(cfg_priv);
2939 }
2940 }
2941 brcmf_init_prof(cfg_priv->profile);
2942 } else if (brcmf_is_nonetwork(cfg_priv, e)) {
2943 if (brcmf_is_ibssmode(cfg_priv))
2944 clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
2945 else
2946 brcmf_bss_connect_done(cfg_priv, ndev, e, false);
2947 }
2948
2949 return err;
2950}
2951
2952static s32
2953brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv,
2954 struct net_device *ndev,
2955 const struct brcmf_event_msg *e, void *data)
2956{
2957 s32 err = 0;
2958 u32 event = be32_to_cpu(e->event_type);
2959 u32 status = be32_to_cpu(e->status);
2960
2961 if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
2962 if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status))
2963 brcmf_bss_roaming_done(cfg_priv, ndev, e);
2964 else
2965 brcmf_bss_connect_done(cfg_priv, ndev, e, true);
2966 }
2967
2968 return err;
2969}
2970
2971static s32
2972brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
2973 struct net_device *ndev,
2974 const struct brcmf_event_msg *e, void *data)
2975{
2976 u16 flags = be16_to_cpu(e->flags);
2977 enum nl80211_key_type key_type;
2978
2979 if (flags & BRCMF_EVENT_MSG_GROUP)
2980 key_type = NL80211_KEYTYPE_GROUP;
2981 else
2982 key_type = NL80211_KEYTYPE_PAIRWISE;
2983
2984 cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
2985 NULL, GFP_KERNEL);
2986
2987 return 0;
2988}
2989
2990static s32
2991brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
2992 struct net_device *ndev,
2993 const struct brcmf_event_msg *e, void *data)
2994{
2995 struct brcmf_channel_info_le channel_inform_le;
2996 struct brcmf_scan_results_le *bss_list_le;
2997 u32 len = WL_SCAN_BUF_MAX;
2998 s32 err = 0;
2999 bool scan_abort = false;
3000 u32 scan_channel;
3001
3002 WL_TRACE("Enter\n");
3003
3004 if (cfg_priv->iscan_on && cfg_priv->iscan_kickstart) {
3005 WL_TRACE("Exit\n");
3006 return brcmf_wakeup_iscan(cfg_to_iscan(cfg_priv));
3007 }
3008
3009 if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
3010 WL_ERR("Scan complete while device not scanning\n");
3011 scan_abort = true;
3012 err = -EINVAL;
3013 goto scan_done_out;
3014 }
3015
3016 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_inform_le,
3017 sizeof(channel_inform_le));
3018 if (err) {
3019 WL_ERR("scan busy (%d)\n", err);
3020 scan_abort = true;
3021 goto scan_done_out;
3022 }
3023 scan_channel = le32_to_cpu(channel_inform_le.scan_channel);
3024 if (scan_channel)
3025 WL_CONN("channel_inform.scan_channel (%d)\n", scan_channel);
3026 cfg_priv->bss_list = cfg_priv->scan_results;
3027 bss_list_le = (struct brcmf_scan_results_le *) cfg_priv->bss_list;
3028
3029 memset(cfg_priv->scan_results, 0, len);
3030 bss_list_le->buflen = cpu_to_le32(len);
3031 err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS,
3032 cfg_priv->scan_results, len);
3033 if (err) {
3034 WL_ERR("%s Scan_results error (%d)\n", ndev->name, err);
3035 err = -EINVAL;
3036 scan_abort = true;
3037 goto scan_done_out;
3038 }
3039 cfg_priv->scan_results->buflen = le32_to_cpu(bss_list_le->buflen);
3040 cfg_priv->scan_results->version = le32_to_cpu(bss_list_le->version);
3041 cfg_priv->scan_results->count = le32_to_cpu(bss_list_le->count);
3042
3043 err = brcmf_inform_bss(cfg_priv);
3044 if (err) {
3045 scan_abort = true;
3046 goto scan_done_out;
3047 }
3048
3049scan_done_out:
3050 if (cfg_priv->scan_request) {
3051 WL_SCAN("calling cfg80211_scan_done\n");
3052 cfg80211_scan_done(cfg_priv->scan_request, scan_abort);
3053 brcmf_set_mpc(ndev, 1);
3054 cfg_priv->scan_request = NULL;
3055 }
3056
3057 WL_TRACE("Exit\n");
3058
3059 return err;
3060}
3061
3062static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
3063{
3064 conf->mode = (u32)-1;
3065 conf->frag_threshold = (u32)-1;
3066 conf->rts_threshold = (u32)-1;
3067 conf->retry_short = (u32)-1;
3068 conf->retry_long = (u32)-1;
3069 conf->tx_power = -1;
3070}
3071
3072static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el)
3073{
3074 memset(el, 0, sizeof(*el));
3075 el->handler[BRCMF_E_SCAN_COMPLETE] = brcmf_notify_scan_status;
3076 el->handler[BRCMF_E_LINK] = brcmf_notify_connect_status;
3077 el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status;
3078 el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status;
3079 el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status;
3080}
3081
3082static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
3083{
3084 kfree(cfg_priv->scan_results);
3085 cfg_priv->scan_results = NULL;
3086 kfree(cfg_priv->bss_info);
3087 cfg_priv->bss_info = NULL;
3088 kfree(cfg_priv->conf);
3089 cfg_priv->conf = NULL;
3090 kfree(cfg_priv->profile);
3091 cfg_priv->profile = NULL;
3092 kfree(cfg_priv->scan_req_int);
3093 cfg_priv->scan_req_int = NULL;
3094 kfree(cfg_priv->dcmd_buf);
3095 cfg_priv->dcmd_buf = NULL;
3096 kfree(cfg_priv->extra_buf);
3097 cfg_priv->extra_buf = NULL;
3098 kfree(cfg_priv->iscan);
3099 cfg_priv->iscan = NULL;
3100 kfree(cfg_priv->pmk_list);
3101 cfg_priv->pmk_list = NULL;
3102}
3103
3104static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
3105{
3106 cfg_priv->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
3107 if (!cfg_priv->scan_results)
3108 goto init_priv_mem_out;
3109 cfg_priv->conf = kzalloc(sizeof(*cfg_priv->conf), GFP_KERNEL);
3110 if (!cfg_priv->conf)
3111 goto init_priv_mem_out;
3112 cfg_priv->profile = kzalloc(sizeof(*cfg_priv->profile), GFP_KERNEL);
3113 if (!cfg_priv->profile)
3114 goto init_priv_mem_out;
3115 cfg_priv->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
3116 if (!cfg_priv->bss_info)
3117 goto init_priv_mem_out;
3118 cfg_priv->scan_req_int = kzalloc(sizeof(*cfg_priv->scan_req_int),
3119 GFP_KERNEL);
3120 if (!cfg_priv->scan_req_int)
3121 goto init_priv_mem_out;
3122 cfg_priv->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL);
3123 if (!cfg_priv->dcmd_buf)
3124 goto init_priv_mem_out;
3125 cfg_priv->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
3126 if (!cfg_priv->extra_buf)
3127 goto init_priv_mem_out;
3128 cfg_priv->iscan = kzalloc(sizeof(*cfg_priv->iscan), GFP_KERNEL);
3129 if (!cfg_priv->iscan)
3130 goto init_priv_mem_out;
3131 cfg_priv->pmk_list = kzalloc(sizeof(*cfg_priv->pmk_list), GFP_KERNEL);
3132 if (!cfg_priv->pmk_list)
3133 goto init_priv_mem_out;
3134
3135 return 0;
3136
3137init_priv_mem_out:
3138 brcmf_deinit_priv_mem(cfg_priv);
3139
3140 return -ENOMEM;
3141}
3142
3143/*
3144* retrieve first queued event from head
3145*/
3146
3147static struct brcmf_cfg80211_event_q *brcmf_deq_event(
3148 struct brcmf_cfg80211_priv *cfg_priv)
3149{
3150 struct brcmf_cfg80211_event_q *e = NULL;
3151
3152 spin_lock_irq(&cfg_priv->evt_q_lock);
3153 if (!list_empty(&cfg_priv->evt_q_list)) {
3154 e = list_first_entry(&cfg_priv->evt_q_list,
3155 struct brcmf_cfg80211_event_q, evt_q_list);
3156 list_del(&e->evt_q_list);
3157 }
3158 spin_unlock_irq(&cfg_priv->evt_q_lock);
3159
3160 return e;
3161}
3162
3163/*
3164** push event to tail of the queue
3165*/
3166
3167static s32
3168brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event,
3169 const struct brcmf_event_msg *msg)
3170{
3171 struct brcmf_cfg80211_event_q *e;
3172 s32 err = 0;
3173
3174 e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_KERNEL);
3175 if (!e)
3176 return -ENOMEM;
3177
3178 e->etype = event;
3179 memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
3180
3181 spin_lock_irq(&cfg_priv->evt_q_lock);
3182 list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list);
3183 spin_unlock_irq(&cfg_priv->evt_q_lock);
3184
3185 return err;
3186}
3187
3188static void brcmf_put_event(struct brcmf_cfg80211_event_q *e)
3189{
3190 kfree(e);
3191}
3192
3193static void brcmf_cfg80211_event_handler(struct work_struct *work)
3194{
3195 struct brcmf_cfg80211_priv *cfg_priv =
3196 container_of(work, struct brcmf_cfg80211_priv,
3197 event_work);
3198 struct brcmf_cfg80211_event_q *e;
3199
3200 e = brcmf_deq_event(cfg_priv);
3201 if (unlikely(!e)) {
3202 WL_ERR("event queue empty...\n");
3203 return;
3204 }
3205
3206 do {
3207 WL_INFO("event type (%d)\n", e->etype);
3208 if (cfg_priv->el.handler[e->etype])
3209 cfg_priv->el.handler[e->etype](cfg_priv,
3210 cfg_to_ndev(cfg_priv),
3211 &e->emsg, e->edata);
3212 else
3213 WL_INFO("Unknown Event (%d): ignoring\n", e->etype);
3214 brcmf_put_event(e);
3215 } while ((e = brcmf_deq_event(cfg_priv)));
3216
3217}
3218
3219static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv)
3220{
3221 spin_lock_init(&cfg_priv->evt_q_lock);
3222 INIT_LIST_HEAD(&cfg_priv->evt_q_list);
3223}
3224
3225static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv)
3226{
3227 struct brcmf_cfg80211_event_q *e;
3228
3229 spin_lock_irq(&cfg_priv->evt_q_lock);
3230 while (!list_empty(&cfg_priv->evt_q_list)) {
3231 e = list_first_entry(&cfg_priv->evt_q_list,
3232 struct brcmf_cfg80211_event_q, evt_q_list);
3233 list_del(&e->evt_q_list);
3234 kfree(e);
3235 }
3236 spin_unlock_irq(&cfg_priv->evt_q_lock);
3237}
3238
3239static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv)
3240{
3241 s32 err = 0;
3242
3243 cfg_priv->scan_request = NULL;
3244 cfg_priv->pwr_save = true;
3245 cfg_priv->iscan_on = true; /* iscan on & off switch.
3246 we enable iscan per default */
3247 cfg_priv->roam_on = true; /* roam on & off switch.
3248 we enable roam per default */
3249
3250 cfg_priv->iscan_kickstart = false;
3251 cfg_priv->active_scan = true; /* we do active scan for
3252 specific scan per default */
3253 cfg_priv->dongle_up = false; /* dongle is not up yet */
3254 brcmf_init_eq(cfg_priv);
3255 err = brcmf_init_priv_mem(cfg_priv);
3256 if (err)
3257 return err;
3258 INIT_WORK(&cfg_priv->event_work, brcmf_cfg80211_event_handler);
3259 brcmf_init_eloop_handler(&cfg_priv->el);
3260 mutex_init(&cfg_priv->usr_sync);
3261 err = brcmf_init_iscan(cfg_priv);
3262 if (err)
3263 return err;
3264 brcmf_init_conf(cfg_priv->conf);
3265 brcmf_init_prof(cfg_priv->profile);
3266 brcmf_link_down(cfg_priv);
3267
3268 return err;
3269}
3270
3271static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv)
3272{
3273 cancel_work_sync(&cfg_priv->event_work);
3274 cfg_priv->dongle_up = false; /* dongle down */
3275 brcmf_flush_eq(cfg_priv);
3276 brcmf_link_down(cfg_priv);
3277 brcmf_term_iscan(cfg_priv);
3278 brcmf_deinit_priv_mem(cfg_priv);
3279}
3280
3281struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev,
3282 struct device *busdev,
3283 void *data)
3284{
3285 struct wireless_dev *wdev;
3286 struct brcmf_cfg80211_priv *cfg_priv;
3287 struct brcmf_cfg80211_iface *ci;
3288 struct brcmf_cfg80211_dev *cfg_dev;
3289 s32 err = 0;
3290
3291 if (!ndev) {
3292 WL_ERR("ndev is invalid\n");
3293 return NULL;
3294 }
3295 cfg_dev = kzalloc(sizeof(struct brcmf_cfg80211_dev), GFP_KERNEL);
3296 if (!cfg_dev)
3297 return NULL;
3298
3299 wdev = brcmf_alloc_wdev(sizeof(struct brcmf_cfg80211_iface), busdev);
3300 if (IS_ERR(wdev)) {
3301 kfree(cfg_dev);
3302 return NULL;
3303 }
3304
3305 wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS);
3306 cfg_priv = wdev_to_cfg(wdev);
3307 cfg_priv->wdev = wdev;
3308 cfg_priv->pub = data;
3309 ci = (struct brcmf_cfg80211_iface *)&cfg_priv->ci;
3310 ci->cfg_priv = cfg_priv;
3311 ndev->ieee80211_ptr = wdev;
3312 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
3313 wdev->netdev = ndev;
3314 err = wl_init_priv(cfg_priv);
3315 if (err) {
3316 WL_ERR("Failed to init iwm_priv (%d)\n", err);
3317 goto cfg80211_attach_out;
3318 }
3319 brcmf_set_drvdata(cfg_dev, ci);
3320
3321 return cfg_dev;
3322
3323cfg80211_attach_out:
3324 brcmf_free_wdev(cfg_priv);
3325 kfree(cfg_dev);
3326 return NULL;
3327}
3328
3329void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg_dev)
3330{
3331 struct brcmf_cfg80211_priv *cfg_priv;
3332
3333 cfg_priv = brcmf_priv_get(cfg_dev);
3334
3335 wl_deinit_priv(cfg_priv);
3336 brcmf_free_wdev(cfg_priv);
3337 brcmf_set_drvdata(cfg_dev, NULL);
3338 kfree(cfg_dev);
3339}
3340
3341void
3342brcmf_cfg80211_event(struct net_device *ndev,
3343 const struct brcmf_event_msg *e, void *data)
3344{
3345 u32 event_type = be32_to_cpu(e->event_type);
3346 struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
3347
3348 if (!brcmf_enq_event(cfg_priv, event_type, e))
3349 schedule_work(&cfg_priv->event_work);
3350}
3351
3352static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
3353{
3354 s32 infra = 0;
3355 s32 err = 0;
3356
3357 switch (iftype) {
3358 case NL80211_IFTYPE_MONITOR:
3359 case NL80211_IFTYPE_WDS:
3360 WL_ERR("type (%d) : currently we do not support this mode\n",
3361 iftype);
3362 err = -EINVAL;
3363 return err;
3364 case NL80211_IFTYPE_ADHOC:
3365 infra = 0;
3366 break;
3367 case NL80211_IFTYPE_STATION:
3368 infra = 1;
3369 break;
3370 default:
3371 err = -EINVAL;
3372 WL_ERR("invalid type (%d)\n", iftype);
3373 return err;
3374 }
3375 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
3376 if (err) {
3377 WL_ERR("WLC_SET_INFRA error (%d)\n", err);
3378 return err;
3379 }
3380
3381 return 0;
3382}
3383
3384static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
3385{
3386 /* Room for "event_msgs" + '\0' + bitvec */
3387 s8 iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
3388 s8 eventmask[BRCMF_EVENTING_MASK_LEN];
3389 s32 err = 0;
3390
3391 WL_TRACE("Enter\n");
3392
3393 /* Setup event_msgs */
3394 brcmu_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, iovbuf,
3395 sizeof(iovbuf));
3396 err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf));
3397 if (err) {
3398 WL_ERR("Get event_msgs error (%d)\n", err);
3399 goto dongle_eventmsg_out;
3400 }
3401 memcpy(eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN);
3402
3403 setbit(eventmask, BRCMF_E_SET_SSID);
3404 setbit(eventmask, BRCMF_E_ROAM);
3405 setbit(eventmask, BRCMF_E_PRUNE);
3406 setbit(eventmask, BRCMF_E_AUTH);
3407 setbit(eventmask, BRCMF_E_REASSOC);
3408 setbit(eventmask, BRCMF_E_REASSOC_IND);
3409 setbit(eventmask, BRCMF_E_DEAUTH_IND);
3410 setbit(eventmask, BRCMF_E_DISASSOC_IND);
3411 setbit(eventmask, BRCMF_E_DISASSOC);
3412 setbit(eventmask, BRCMF_E_JOIN);
3413 setbit(eventmask, BRCMF_E_ASSOC_IND);
3414 setbit(eventmask, BRCMF_E_PSK_SUP);
3415 setbit(eventmask, BRCMF_E_LINK);
3416 setbit(eventmask, BRCMF_E_NDIS_LINK);
3417 setbit(eventmask, BRCMF_E_MIC_ERROR);
3418 setbit(eventmask, BRCMF_E_PMKID_CACHE);
3419 setbit(eventmask, BRCMF_E_TXFAIL);
3420 setbit(eventmask, BRCMF_E_JOIN_START);
3421 setbit(eventmask, BRCMF_E_SCAN_COMPLETE);
3422
3423 brcmu_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, iovbuf,
3424 sizeof(iovbuf));
3425 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
3426 if (err) {
3427 WL_ERR("Set event_msgs error (%d)\n", err);
3428 goto dongle_eventmsg_out;
3429 }
3430
3431dongle_eventmsg_out:
3432 WL_TRACE("Exit\n");
3433 return err;
3434}
3435
3436static s32
3437brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
3438{
3439 s8 iovbuf[32];
Arend van Spriel5b435de2011-10-05 13:19:03 +02003440 s32 err = 0;
Arend van Sprielf588bc02011-10-12 20:51:22 +02003441 __le32 roamtrigger[2];
3442 __le32 roam_delta[2];
3443 __le32 bcn_to_le;
3444 __le32 roamvar_le;
Arend van Spriel5b435de2011-10-05 13:19:03 +02003445
3446 /*
3447 * Setup timeout if Beacons are lost and roam is
3448 * off to report link down
3449 */
3450 if (roamvar) {
Arend van Sprielf588bc02011-10-12 20:51:22 +02003451 bcn_to_le = cpu_to_le32(bcn_timeout);
3452 brcmu_mkiovar("bcn_timeout", (char *)&bcn_to_le,
3453 sizeof(bcn_to_le), iovbuf, sizeof(iovbuf));
Arend van Spriel5b435de2011-10-05 13:19:03 +02003454 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR,
3455 iovbuf, sizeof(iovbuf));
3456 if (err) {
3457 WL_ERR("bcn_timeout error (%d)\n", err);
3458 goto dongle_rom_out;
3459 }
3460 }
3461
3462 /*
3463 * Enable/Disable built-in roaming to allow supplicant
3464 * to take care of roaming
3465 */
3466 WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On");
Arend van Sprielf588bc02011-10-12 20:51:22 +02003467 roamvar_le = cpu_to_le32(roamvar);
3468 brcmu_mkiovar("roam_off", (char *)&roamvar_le,
3469 sizeof(roamvar_le), iovbuf, sizeof(iovbuf));
Arend van Spriel5b435de2011-10-05 13:19:03 +02003470 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
3471 if (err) {
3472 WL_ERR("roam_off error (%d)\n", err);
3473 goto dongle_rom_out;
3474 }
3475
Arend van Sprielf588bc02011-10-12 20:51:22 +02003476 roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL);
3477 roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL);
Arend van Spriel5b435de2011-10-05 13:19:03 +02003478 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_TRIGGER,
3479 (void *)roamtrigger, sizeof(roamtrigger));
3480 if (err) {
3481 WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
3482 goto dongle_rom_out;
3483 }
3484
Arend van Sprielf588bc02011-10-12 20:51:22 +02003485 roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA);
3486 roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL);
Arend van Spriel5b435de2011-10-05 13:19:03 +02003487 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_DELTA,
3488 (void *)roam_delta, sizeof(roam_delta));
3489 if (err) {
3490 WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err);
3491 goto dongle_rom_out;
3492 }
3493
3494dongle_rom_out:
3495 return err;
3496}
3497
3498static s32
3499brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
3500 s32 scan_unassoc_time, s32 scan_passive_time)
3501{
3502 s32 err = 0;
3503
3504 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME,
3505 &scan_assoc_time, sizeof(scan_assoc_time));
3506 if (err) {
3507 if (err == -EOPNOTSUPP)
3508 WL_INFO("Scan assoc time is not supported\n");
3509 else
3510 WL_ERR("Scan assoc time error (%d)\n", err);
3511 goto dongle_scantime_out;
3512 }
3513 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME,
3514 &scan_unassoc_time, sizeof(scan_unassoc_time));
3515 if (err) {
3516 if (err == -EOPNOTSUPP)
3517 WL_INFO("Scan unassoc time is not supported\n");
3518 else
3519 WL_ERR("Scan unassoc time error (%d)\n", err);
3520 goto dongle_scantime_out;
3521 }
3522
3523 err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME,
3524 &scan_passive_time, sizeof(scan_passive_time));
3525 if (err) {
3526 if (err == -EOPNOTSUPP)
3527 WL_INFO("Scan passive time is not supported\n");
3528 else
3529 WL_ERR("Scan passive time error (%d)\n", err);
3530 goto dongle_scantime_out;
3531 }
3532
3533dongle_scantime_out:
3534 return err;
3535}
3536
3537static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv)
3538{
3539 struct wiphy *wiphy;
3540 s32 phy_list;
3541 s8 phy;
3542 s32 err = 0;
3543
3544 err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST,
3545 &phy_list, sizeof(phy_list));
3546 if (err) {
3547 WL_ERR("error (%d)\n", err);
3548 return err;
3549 }
3550
3551 phy = ((char *)&phy_list)[1];
3552 WL_INFO("%c phy\n", phy);
3553 if (phy == 'n' || phy == 'a') {
3554 wiphy = cfg_to_wiphy(cfg_priv);
3555 wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
3556 }
3557
3558 return err;
3559}
3560
3561static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv)
3562{
3563 return wl_update_wiphybands(cfg_priv);
3564}
3565
3566static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv)
3567{
3568 struct net_device *ndev;
3569 struct wireless_dev *wdev;
3570 s32 power_mode;
3571 s32 err = 0;
3572
3573 if (cfg_priv->dongle_up)
3574 return err;
3575
3576 ndev = cfg_to_ndev(cfg_priv);
3577 wdev = ndev->ieee80211_ptr;
3578
3579 brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
3580 WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
3581
3582 err = brcmf_dongle_eventmsg(ndev);
3583 if (err)
3584 goto default_conf_out;
3585
3586 power_mode = cfg_priv->pwr_save ? PM_FAST : PM_OFF;
3587 err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &power_mode);
3588 if (err)
3589 goto default_conf_out;
3590 WL_INFO("power save set to %s\n",
3591 (power_mode ? "enabled" : "disabled"));
3592
3593 err = brcmf_dongle_roam(ndev, (cfg_priv->roam_on ? 0 : 1),
3594 WL_BEACON_TIMEOUT);
3595 if (err)
3596 goto default_conf_out;
3597 err = brcmf_dongle_mode(ndev, wdev->iftype);
3598 if (err && err != -EINPROGRESS)
3599 goto default_conf_out;
3600 err = brcmf_dongle_probecap(cfg_priv);
3601 if (err)
3602 goto default_conf_out;
3603
3604 /* -EINPROGRESS: Call commit handler */
3605
3606default_conf_out:
3607
3608 cfg_priv->dongle_up = true;
3609
3610 return err;
3611
3612}
3613
3614static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv)
3615{
3616 char buf[10+IFNAMSIZ];
3617 struct dentry *fd;
3618 s32 err = 0;
3619
3620 sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name);
3621 cfg_priv->debugfsdir = debugfs_create_dir(buf,
3622 cfg_to_wiphy(cfg_priv)->debugfsdir);
3623
3624 fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir,
3625 (u16 *)&cfg_priv->profile->beacon_interval);
3626 if (!fd) {
3627 err = -ENOMEM;
3628 goto err_out;
3629 }
3630
3631 fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir,
3632 (u8 *)&cfg_priv->profile->dtim_period);
3633 if (!fd) {
3634 err = -ENOMEM;
3635 goto err_out;
3636 }
3637
3638err_out:
3639 return err;
3640}
3641
3642static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv)
3643{
3644 debugfs_remove_recursive(cfg_priv->debugfsdir);
3645 cfg_priv->debugfsdir = NULL;
3646}
3647
3648static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv)
3649{
3650 s32 err = 0;
3651
3652 set_bit(WL_STATUS_READY, &cfg_priv->status);
3653
3654 brcmf_debugfs_add_netdev_params(cfg_priv);
3655
3656 err = brcmf_config_dongle(cfg_priv);
3657 if (err)
3658 return err;
3659
3660 brcmf_invoke_iscan(cfg_priv);
3661
3662 return err;
3663}
3664
3665static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv)
3666{
3667 /*
3668 * While going down, if associated with AP disassociate
3669 * from AP to save power
3670 */
3671 if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
3672 test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
3673 test_bit(WL_STATUS_READY, &cfg_priv->status)) {
3674 WL_INFO("Disassociating from AP");
3675 brcmf_link_down(cfg_priv);
3676
3677 /* Make sure WPA_Supplicant receives all the event
3678 generated due to DISASSOC call to the fw to keep
3679 the state fw and WPA_Supplicant state consistent
3680 */
3681 brcmf_delay(500);
3682 }
3683
3684 set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
3685 brcmf_term_iscan(cfg_priv);
3686 if (cfg_priv->scan_request) {
3687 cfg80211_scan_done(cfg_priv->scan_request, true);
3688 /* May need to perform this to cover rmmod */
3689 /* wl_set_mpc(cfg_to_ndev(wl), 1); */
3690 cfg_priv->scan_request = NULL;
3691 }
3692 clear_bit(WL_STATUS_READY, &cfg_priv->status);
3693 clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
3694 clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
3695
3696 brcmf_debugfs_remove_netdev(cfg_priv);
3697
3698 return 0;
3699}
3700
3701s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev)
3702{
3703 struct brcmf_cfg80211_priv *cfg_priv;
3704 s32 err = 0;
3705
3706 cfg_priv = brcmf_priv_get(cfg_dev);
3707 mutex_lock(&cfg_priv->usr_sync);
3708 err = __brcmf_cfg80211_up(cfg_priv);
3709 mutex_unlock(&cfg_priv->usr_sync);
3710
3711 return err;
3712}
3713
3714s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev)
3715{
3716 struct brcmf_cfg80211_priv *cfg_priv;
3717 s32 err = 0;
3718
3719 cfg_priv = brcmf_priv_get(cfg_dev);
3720 mutex_lock(&cfg_priv->usr_sync);
3721 err = __brcmf_cfg80211_down(cfg_priv);
3722 mutex_unlock(&cfg_priv->usr_sync);
3723
3724 return err;
3725}
3726
3727static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv,
3728 u8 t, u8 l, u8 *v)
3729{
3730 struct brcmf_cfg80211_ie *ie = &cfg_priv->ie;
3731 s32 err = 0;
3732
3733 if (ie->offset + l + 2 > WL_TLV_INFO_MAX) {
3734 WL_ERR("ei crosses buffer boundary\n");
3735 return -ENOSPC;
3736 }
3737 ie->buf[ie->offset] = t;
3738 ie->buf[ie->offset + 1] = l;
3739 memcpy(&ie->buf[ie->offset + 2], v, l);
3740 ie->offset += l + 2;
3741
3742 return err;
3743}