brcmfmac: use memset when setting a broadcast mac address
[deliverable/linux.git] / drivers / net / wireless / brcm80211 / brcmfmac / wl_cfg80211.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 2010 Broadcom Corporation
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17/* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */
18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include <linux/kernel.h>
22#include <linux/if_arp.h>
23#include <linux/sched.h>
24#include <linux/kthread.h>
25#include <linux/netdevice.h>
26#include <linux/bitops.h>
27#include <linux/etherdevice.h>
28#include <linux/ieee80211.h>
29#include <linux/uaccess.h>
30#include <net/cfg80211.h>
31#include <net/netlink.h>
32
33#include <brcmu_utils.h>
34#include <defs.h>
35#include <brcmu_wifi.h>
36#include "dhd.h"
37#include "wl_cfg80211.h"
38#include "fwil.h"
39
40#define BRCMF_SCAN_IE_LEN_MAX 2048
41#define BRCMF_PNO_VERSION 2
42#define BRCMF_PNO_TIME 30
43#define BRCMF_PNO_REPEAT 4
44#define BRCMF_PNO_FREQ_EXPO_MAX 3
45#define BRCMF_PNO_MAX_PFN_COUNT 16
46#define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6
47#define BRCMF_PNO_HIDDEN_BIT 2
48#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF
49#define BRCMF_PNO_SCAN_COMPLETE 1
50#define BRCMF_PNO_SCAN_INCOMPLETE 0
51
52#define BRCMF_IFACE_MAX_CNT 2
53
54#define TLV_LEN_OFF 1 /* length offset */
55#define TLV_HDR_LEN 2 /* header length */
56#define TLV_BODY_OFF 2 /* body offset */
57#define TLV_OUI_LEN 3 /* oui id length */
58#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */
59#define WPA_OUI_TYPE 1
60#define RSN_OUI "\x00\x0F\xAC" /* RSN OUI */
61#define WME_OUI_TYPE 2
62
63#define VS_IE_FIXED_HDR_LEN 6
64#define WPA_IE_VERSION_LEN 2
65#define WPA_IE_MIN_OUI_LEN 4
66#define WPA_IE_SUITE_COUNT_LEN 2
67
68#define WPA_CIPHER_NONE 0 /* None */
69#define WPA_CIPHER_WEP_40 1 /* WEP (40-bit) */
70#define WPA_CIPHER_TKIP 2 /* TKIP: default for WPA */
71#define WPA_CIPHER_AES_CCM 4 /* AES (CCM) */
72#define WPA_CIPHER_WEP_104 5 /* WEP (104-bit) */
73
74#define RSN_AKM_NONE 0 /* None (IBSS) */
75#define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */
76#define RSN_AKM_PSK 2 /* Pre-shared Key */
77#define RSN_CAP_LEN 2 /* Length of RSN capabilities */
78#define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C
79
80#define VNDR_IE_CMD_LEN 4 /* length of the set command
81 * string :"add", "del" (+ NUL)
82 */
83#define VNDR_IE_COUNT_OFFSET 4
84#define VNDR_IE_PKTFLAG_OFFSET 8
85#define VNDR_IE_VSIE_OFFSET 12
86#define VNDR_IE_HDR_SIZE 12
87#define VNDR_IE_BEACON_FLAG 0x1
88#define VNDR_IE_PRBRSP_FLAG 0x2
89#define MAX_VNDR_IE_NUMBER 5
90
91#define DOT11_MGMT_HDR_LEN 24 /* d11 management header len */
92#define DOT11_BCN_PRB_FIXED_LEN 12 /* beacon/probe fixed length */
93
94#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
95 (sizeof(struct brcmf_assoc_params_le) - sizeof(u16))
96
97static u32 brcmf_dbg_level = WL_DBG_ERR;
98
99static bool check_vif_up(struct brcmf_cfg80211_vif *vif)
100{
101 if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state)) {
102 WL_INFO("device is not ready : status (%lu)\n",
103 vif->sme_state);
104 return false;
105 }
106 return true;
107}
108
109#define CHAN2G(_channel, _freq, _flags) { \
110 .band = IEEE80211_BAND_2GHZ, \
111 .center_freq = (_freq), \
112 .hw_value = (_channel), \
113 .flags = (_flags), \
114 .max_antenna_gain = 0, \
115 .max_power = 30, \
116}
117
118#define CHAN5G(_channel, _flags) { \
119 .band = IEEE80211_BAND_5GHZ, \
120 .center_freq = 5000 + (5 * (_channel)), \
121 .hw_value = (_channel), \
122 .flags = (_flags), \
123 .max_antenna_gain = 0, \
124 .max_power = 30, \
125}
126
127#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
128#define RATETAB_ENT(_rateid, _flags) \
129 { \
130 .bitrate = RATE_TO_BASE100KBPS(_rateid), \
131 .hw_value = (_rateid), \
132 .flags = (_flags), \
133 }
134
135static struct ieee80211_rate __wl_rates[] = {
136 RATETAB_ENT(BRCM_RATE_1M, 0),
137 RATETAB_ENT(BRCM_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
138 RATETAB_ENT(BRCM_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
139 RATETAB_ENT(BRCM_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
140 RATETAB_ENT(BRCM_RATE_6M, 0),
141 RATETAB_ENT(BRCM_RATE_9M, 0),
142 RATETAB_ENT(BRCM_RATE_12M, 0),
143 RATETAB_ENT(BRCM_RATE_18M, 0),
144 RATETAB_ENT(BRCM_RATE_24M, 0),
145 RATETAB_ENT(BRCM_RATE_36M, 0),
146 RATETAB_ENT(BRCM_RATE_48M, 0),
147 RATETAB_ENT(BRCM_RATE_54M, 0),
148};
149
150#define wl_a_rates (__wl_rates + 4)
151#define wl_a_rates_size 8
152#define wl_g_rates (__wl_rates + 0)
153#define wl_g_rates_size 12
154
155static struct ieee80211_channel __wl_2ghz_channels[] = {
156 CHAN2G(1, 2412, 0),
157 CHAN2G(2, 2417, 0),
158 CHAN2G(3, 2422, 0),
159 CHAN2G(4, 2427, 0),
160 CHAN2G(5, 2432, 0),
161 CHAN2G(6, 2437, 0),
162 CHAN2G(7, 2442, 0),
163 CHAN2G(8, 2447, 0),
164 CHAN2G(9, 2452, 0),
165 CHAN2G(10, 2457, 0),
166 CHAN2G(11, 2462, 0),
167 CHAN2G(12, 2467, 0),
168 CHAN2G(13, 2472, 0),
169 CHAN2G(14, 2484, 0),
170};
171
172static struct ieee80211_channel __wl_5ghz_a_channels[] = {
173 CHAN5G(34, 0), CHAN5G(36, 0),
174 CHAN5G(38, 0), CHAN5G(40, 0),
175 CHAN5G(42, 0), CHAN5G(44, 0),
176 CHAN5G(46, 0), CHAN5G(48, 0),
177 CHAN5G(52, 0), CHAN5G(56, 0),
178 CHAN5G(60, 0), CHAN5G(64, 0),
179 CHAN5G(100, 0), CHAN5G(104, 0),
180 CHAN5G(108, 0), CHAN5G(112, 0),
181 CHAN5G(116, 0), CHAN5G(120, 0),
182 CHAN5G(124, 0), CHAN5G(128, 0),
183 CHAN5G(132, 0), CHAN5G(136, 0),
184 CHAN5G(140, 0), CHAN5G(149, 0),
185 CHAN5G(153, 0), CHAN5G(157, 0),
186 CHAN5G(161, 0), CHAN5G(165, 0),
187 CHAN5G(184, 0), CHAN5G(188, 0),
188 CHAN5G(192, 0), CHAN5G(196, 0),
189 CHAN5G(200, 0), CHAN5G(204, 0),
190 CHAN5G(208, 0), CHAN5G(212, 0),
191 CHAN5G(216, 0),
192};
193
194static struct ieee80211_channel __wl_5ghz_n_channels[] = {
195 CHAN5G(32, 0), CHAN5G(34, 0),
196 CHAN5G(36, 0), CHAN5G(38, 0),
197 CHAN5G(40, 0), CHAN5G(42, 0),
198 CHAN5G(44, 0), CHAN5G(46, 0),
199 CHAN5G(48, 0), CHAN5G(50, 0),
200 CHAN5G(52, 0), CHAN5G(54, 0),
201 CHAN5G(56, 0), CHAN5G(58, 0),
202 CHAN5G(60, 0), CHAN5G(62, 0),
203 CHAN5G(64, 0), CHAN5G(66, 0),
204 CHAN5G(68, 0), CHAN5G(70, 0),
205 CHAN5G(72, 0), CHAN5G(74, 0),
206 CHAN5G(76, 0), CHAN5G(78, 0),
207 CHAN5G(80, 0), CHAN5G(82, 0),
208 CHAN5G(84, 0), CHAN5G(86, 0),
209 CHAN5G(88, 0), CHAN5G(90, 0),
210 CHAN5G(92, 0), CHAN5G(94, 0),
211 CHAN5G(96, 0), CHAN5G(98, 0),
212 CHAN5G(100, 0), CHAN5G(102, 0),
213 CHAN5G(104, 0), CHAN5G(106, 0),
214 CHAN5G(108, 0), CHAN5G(110, 0),
215 CHAN5G(112, 0), CHAN5G(114, 0),
216 CHAN5G(116, 0), CHAN5G(118, 0),
217 CHAN5G(120, 0), CHAN5G(122, 0),
218 CHAN5G(124, 0), CHAN5G(126, 0),
219 CHAN5G(128, 0), CHAN5G(130, 0),
220 CHAN5G(132, 0), CHAN5G(134, 0),
221 CHAN5G(136, 0), CHAN5G(138, 0),
222 CHAN5G(140, 0), CHAN5G(142, 0),
223 CHAN5G(144, 0), CHAN5G(145, 0),
224 CHAN5G(146, 0), CHAN5G(147, 0),
225 CHAN5G(148, 0), CHAN5G(149, 0),
226 CHAN5G(150, 0), CHAN5G(151, 0),
227 CHAN5G(152, 0), CHAN5G(153, 0),
228 CHAN5G(154, 0), CHAN5G(155, 0),
229 CHAN5G(156, 0), CHAN5G(157, 0),
230 CHAN5G(158, 0), CHAN5G(159, 0),
231 CHAN5G(160, 0), CHAN5G(161, 0),
232 CHAN5G(162, 0), CHAN5G(163, 0),
233 CHAN5G(164, 0), CHAN5G(165, 0),
234 CHAN5G(166, 0), CHAN5G(168, 0),
235 CHAN5G(170, 0), CHAN5G(172, 0),
236 CHAN5G(174, 0), CHAN5G(176, 0),
237 CHAN5G(178, 0), CHAN5G(180, 0),
238 CHAN5G(182, 0), CHAN5G(184, 0),
239 CHAN5G(186, 0), CHAN5G(188, 0),
240 CHAN5G(190, 0), CHAN5G(192, 0),
241 CHAN5G(194, 0), CHAN5G(196, 0),
242 CHAN5G(198, 0), CHAN5G(200, 0),
243 CHAN5G(202, 0), CHAN5G(204, 0),
244 CHAN5G(206, 0), CHAN5G(208, 0),
245 CHAN5G(210, 0), CHAN5G(212, 0),
246 CHAN5G(214, 0), CHAN5G(216, 0),
247 CHAN5G(218, 0), CHAN5G(220, 0),
248 CHAN5G(222, 0), CHAN5G(224, 0),
249 CHAN5G(226, 0), CHAN5G(228, 0),
250};
251
252static struct ieee80211_supported_band __wl_band_2ghz = {
253 .band = IEEE80211_BAND_2GHZ,
254 .channels = __wl_2ghz_channels,
255 .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
256 .bitrates = wl_g_rates,
257 .n_bitrates = wl_g_rates_size,
258};
259
260static struct ieee80211_supported_band __wl_band_5ghz_a = {
261 .band = IEEE80211_BAND_5GHZ,
262 .channels = __wl_5ghz_a_channels,
263 .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
264 .bitrates = wl_a_rates,
265 .n_bitrates = wl_a_rates_size,
266};
267
268static struct ieee80211_supported_band __wl_band_5ghz_n = {
269 .band = IEEE80211_BAND_5GHZ,
270 .channels = __wl_5ghz_n_channels,
271 .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
272 .bitrates = wl_a_rates,
273 .n_bitrates = wl_a_rates_size,
274};
275
276static const u32 __wl_cipher_suites[] = {
277 WLAN_CIPHER_SUITE_WEP40,
278 WLAN_CIPHER_SUITE_WEP104,
279 WLAN_CIPHER_SUITE_TKIP,
280 WLAN_CIPHER_SUITE_CCMP,
281 WLAN_CIPHER_SUITE_AES_CMAC,
282};
283
284/* tag_ID/length/value_buffer tuple */
285struct brcmf_tlv {
286 u8 id;
287 u8 len;
288 u8 data[1];
289};
290
291/* Vendor specific ie. id = 221, oui and type defines exact ie */
292struct brcmf_vs_tlv {
293 u8 id;
294 u8 len;
295 u8 oui[3];
296 u8 oui_type;
297};
298
299struct parsed_vndr_ie_info {
300 u8 *ie_ptr;
301 u32 ie_len; /* total length including id & length field */
302 struct brcmf_vs_tlv vndrie;
303};
304
305struct parsed_vndr_ies {
306 u32 count;
307 struct parsed_vndr_ie_info ie_info[MAX_VNDR_IE_NUMBER];
308};
309
310/* Quarter dBm units to mW
311 * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
312 * Table is offset so the last entry is largest mW value that fits in
313 * a u16.
314 */
315
316#define QDBM_OFFSET 153 /* Offset for first entry */
317#define QDBM_TABLE_LEN 40 /* Table size */
318
319/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
320 * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
321 */
322#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */
323
324/* Largest mW value that will round down to the last table entry,
325 * QDBM_OFFSET + QDBM_TABLE_LEN-1.
326 * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) +
327 * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
328 */
329#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */
330
331static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
332/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */
333/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
334/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
335/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
336/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
337/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
338};
339
340static u16 brcmf_qdbm_to_mw(u8 qdbm)
341{
342 uint factor = 1;
343 int idx = qdbm - QDBM_OFFSET;
344
345 if (idx >= QDBM_TABLE_LEN)
346 /* clamp to max u16 mW value */
347 return 0xFFFF;
348
349 /* scale the qdBm index up to the range of the table 0-40
350 * where an offset of 40 qdBm equals a factor of 10 mW.
351 */
352 while (idx < 0) {
353 idx += 40;
354 factor *= 10;
355 }
356
357 /* return the mW value scaled down to the correct factor of 10,
358 * adding in factor/2 to get proper rounding.
359 */
360 return (nqdBm_to_mW_map[idx] + factor / 2) / factor;
361}
362
363static u8 brcmf_mw_to_qdbm(u16 mw)
364{
365 u8 qdbm;
366 int offset;
367 uint mw_uint = mw;
368 uint boundary;
369
370 /* handle boundary case */
371 if (mw_uint <= 1)
372 return 0;
373
374 offset = QDBM_OFFSET;
375
376 /* move mw into the range of the table */
377 while (mw_uint < QDBM_TABLE_LOW_BOUND) {
378 mw_uint *= 10;
379 offset -= 40;
380 }
381
382 for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) {
383 boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] -
384 nqdBm_to_mW_map[qdbm]) / 2;
385 if (mw_uint < boundary)
386 break;
387 }
388
389 qdbm += (u8) offset;
390
391 return qdbm;
392}
393
394static u16 channel_to_chanspec(struct ieee80211_channel *ch)
395{
396 u16 chanspec;
397
398 chanspec = ieee80211_frequency_to_channel(ch->center_freq);
399 chanspec &= WL_CHANSPEC_CHAN_MASK;
400
401 if (ch->band == IEEE80211_BAND_2GHZ)
402 chanspec |= WL_CHANSPEC_BAND_2G;
403 else
404 chanspec |= WL_CHANSPEC_BAND_5G;
405
406 if (ch->flags & IEEE80211_CHAN_NO_HT40) {
407 chanspec |= WL_CHANSPEC_BW_20;
408 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
409 } else {
410 chanspec |= WL_CHANSPEC_BW_40;
411 if (ch->flags & IEEE80211_CHAN_NO_HT40PLUS)
412 chanspec |= WL_CHANSPEC_CTL_SB_LOWER;
413 else
414 chanspec |= WL_CHANSPEC_CTL_SB_UPPER;
415 }
416 return chanspec;
417}
418
419static void convert_key_from_CPU(struct brcmf_wsec_key *key,
420 struct brcmf_wsec_key_le *key_le)
421{
422 key_le->index = cpu_to_le32(key->index);
423 key_le->len = cpu_to_le32(key->len);
424 key_le->algo = cpu_to_le32(key->algo);
425 key_le->flags = cpu_to_le32(key->flags);
426 key_le->rxiv.hi = cpu_to_le32(key->rxiv.hi);
427 key_le->rxiv.lo = cpu_to_le16(key->rxiv.lo);
428 key_le->iv_initialized = cpu_to_le32(key->iv_initialized);
429 memcpy(key_le->data, key->data, sizeof(key->data));
430 memcpy(key_le->ea, key->ea, sizeof(key->ea));
431}
432
433static int
434send_key_to_dongle(struct net_device *ndev, struct brcmf_wsec_key *key)
435{
436 int err;
437 struct brcmf_wsec_key_le key_le;
438
439 convert_key_from_CPU(key, &key_le);
440
441 brcmf_netdev_wait_pend8021x(ndev);
442
443 err = brcmf_fil_bsscfg_data_set(netdev_priv(ndev), "wsec_key", &key_le,
444 sizeof(key_le));
445
446 if (err)
447 WL_ERR("wsec_key error (%d)\n", err);
448 return err;
449}
450
451static s32
452brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
453 enum nl80211_iftype type, u32 *flags,
454 struct vif_params *params)
455{
456 struct brcmf_if *ifp = netdev_priv(ndev);
457 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
458 s32 infra = 0;
459 s32 ap = 0;
460 s32 err = 0;
461
462 WL_TRACE("Enter, ndev=%p, type=%d\n", ndev, type);
463
464 switch (type) {
465 case NL80211_IFTYPE_MONITOR:
466 case NL80211_IFTYPE_WDS:
467 WL_ERR("type (%d) : currently we do not support this type\n",
468 type);
469 return -EOPNOTSUPP;
470 case NL80211_IFTYPE_ADHOC:
471 cfg->conf->mode = WL_MODE_IBSS;
472 infra = 0;
473 break;
474 case NL80211_IFTYPE_STATION:
475 cfg->conf->mode = WL_MODE_BSS;
476 infra = 1;
477 break;
478 case NL80211_IFTYPE_AP:
479 cfg->conf->mode = WL_MODE_AP;
480 ap = 1;
481 break;
482 default:
483 err = -EINVAL;
484 goto done;
485 }
486
487 if (ap) {
488 set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
489 if (!cfg->ap_info)
490 cfg->ap_info = kzalloc(sizeof(*cfg->ap_info),
491 GFP_KERNEL);
492 if (!cfg->ap_info) {
493 err = -ENOMEM;
494 goto done;
495 }
496 WL_INFO("IF Type = AP\n");
497 } else {
498 err = brcmf_fil_cmd_int_set(netdev_priv(ndev),
499 BRCMF_C_SET_INFRA, infra);
500 if (err) {
501 WL_ERR("WLC_SET_INFRA error (%d)\n", err);
502 err = -EAGAIN;
503 goto done;
504 }
505 WL_INFO("IF Type = %s\n",
506 (cfg->conf->mode == WL_MODE_IBSS) ?
507 "Adhoc" : "Infra");
508 }
509 ndev->ieee80211_ptr->iftype = type;
510
511done:
512 WL_TRACE("Exit\n");
513
514 return err;
515}
516
517static void brcmf_set_mpc(struct net_device *ndev, int mpc)
518{
519 struct brcmf_if *ifp = netdev_priv(ndev);
520 s32 err = 0;
521
522 if (check_vif_up(ifp->vif)) {
523 err = brcmf_fil_iovar_int_set(ifp, "mpc", mpc);
524 if (err) {
525 WL_ERR("fail to set mpc\n");
526 return;
527 }
528 WL_INFO("MPC : %d\n", mpc);
529 }
530}
531
532static void brcmf_iscan_prep(struct brcmf_scan_params_le *params_le,
533 struct brcmf_ssid *ssid)
534{
535 memset(params_le->bssid, 0xFF, ETH_ALEN);
536 params_le->bss_type = DOT11_BSSTYPE_ANY;
537 params_le->scan_type = 0;
538 params_le->channel_num = 0;
539 params_le->nprobes = cpu_to_le32(-1);
540 params_le->active_time = cpu_to_le32(-1);
541 params_le->passive_time = cpu_to_le32(-1);
542 params_le->home_time = cpu_to_le32(-1);
543 if (ssid && ssid->SSID_len) {
544 params_le->ssid_le.SSID_len = cpu_to_le32(ssid->SSID_len);
545 memcpy(&params_le->ssid_le.SSID, ssid->SSID, ssid->SSID_len);
546 }
547}
548
549static s32
550brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan,
551 struct brcmf_ssid *ssid, u16 action)
552{
553 s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
554 offsetof(struct brcmf_iscan_params_le, params_le);
555 struct brcmf_iscan_params_le *params;
556 s32 err = 0;
557
558 if (ssid && ssid->SSID_len)
559 params_size += sizeof(struct brcmf_ssid);
560 params = kzalloc(params_size, GFP_KERNEL);
561 if (!params)
562 return -ENOMEM;
563 BUG_ON(params_size >= BRCMF_DCMD_SMLEN);
564
565 brcmf_iscan_prep(&params->params_le, ssid);
566
567 params->version = cpu_to_le32(BRCMF_ISCAN_REQ_VERSION);
568 params->action = cpu_to_le16(action);
569 params->scan_duration = cpu_to_le16(0);
570
571 err = brcmf_fil_iovar_data_set(netdev_priv(iscan->ndev), "iscan",
572 params, params_size);
573 if (err) {
574 if (err == -EBUSY)
575 WL_INFO("system busy : iscan canceled\n");
576 else
577 WL_ERR("error (%d)\n", err);
578 }
579
580 kfree(params);
581 return err;
582}
583
584static s32 brcmf_do_iscan(struct brcmf_cfg80211_info *cfg)
585{
586 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg);
587 struct net_device *ndev = cfg_to_ndev(cfg);
588 struct brcmf_ssid ssid;
589 u32 passive_scan;
590 s32 err = 0;
591
592 /* Broadcast scan by default */
593 memset(&ssid, 0, sizeof(ssid));
594
595 iscan->state = WL_ISCAN_STATE_SCANING;
596
597 passive_scan = cfg->active_scan ? 0 : 1;
598 err = brcmf_fil_cmd_int_set(netdev_priv(ndev),
599 BRCMF_C_SET_PASSIVE_SCAN, passive_scan);
600 if (err) {
601 WL_ERR("error (%d)\n", err);
602 return err;
603 }
604 brcmf_set_mpc(ndev, 0);
605 cfg->iscan_kickstart = true;
606 err = brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START);
607 if (err) {
608 brcmf_set_mpc(ndev, 1);
609 cfg->iscan_kickstart = false;
610 return err;
611 }
612 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
613 iscan->timer_on = 1;
614 return err;
615}
616
617static s32
618brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev,
619 struct cfg80211_scan_request *request,
620 struct cfg80211_ssid *this_ssid)
621{
622 struct brcmf_if *ifp = netdev_priv(ndev);
623 struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
624 struct cfg80211_ssid *ssids;
625 struct brcmf_cfg80211_scan_req *sr = cfg->scan_req_int;
626 u32 passive_scan;
627 bool iscan_req;
628 bool spec_scan;
629 s32 err = 0;
630 u32 SSID_len;
631
632 if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
633 WL_ERR("Scanning already: status (%lu)\n", cfg->scan_status);
634 return -EAGAIN;
635 }
636 if (test_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status)) {
637 WL_ERR("Scanning being aborted: status (%lu)\n",
638 cfg->scan_status);
639 return -EAGAIN;
640 }
641 if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) {
642 WL_ERR("Connecting: status (%lu)\n", ifp->vif->sme_state);
643 return -EAGAIN;
644 }
645
646 iscan_req = false;
647 spec_scan = false;
648 if (request) {
649 /* scan bss */
650 ssids = request->ssids;
651 if (cfg->iscan_on && (!ssids || !ssids->ssid_len))
652 iscan_req = true;
653 } else {
654 /* scan in ibss */
655 /* we don't do iscan in ibss */
656 ssids = this_ssid;
657 }
658
659 cfg->scan_request = request;
660 set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
661 if (iscan_req) {
662 err = brcmf_do_iscan(cfg);
663 if (!err)
664 return err;
665 else
666 goto scan_out;
667 } else {
668 WL_SCAN("ssid \"%s\", ssid_len (%d)\n",
669 ssids->ssid, ssids->ssid_len);
670 memset(&sr->ssid_le, 0, sizeof(sr->ssid_le));
671 SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len);
672 sr->ssid_le.SSID_len = cpu_to_le32(0);
673 if (SSID_len) {
674 memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len);
675 sr->ssid_le.SSID_len = cpu_to_le32(SSID_len);
676 spec_scan = true;
677 } else {
678 WL_SCAN("Broadcast scan\n");
679 }
680
681 passive_scan = cfg->active_scan ? 0 : 1;
682 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN,
683 passive_scan);
684 if (err) {
685 WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
686 goto scan_out;
687 }
688 brcmf_set_mpc(ndev, 0);
689 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
690 &sr->ssid_le, sizeof(sr->ssid_le));
691 if (err) {
692 if (err == -EBUSY)
693 WL_INFO("system busy : scan for \"%s\" "
694 "canceled\n", sr->ssid_le.SSID);
695 else
696 WL_ERR("WLC_SCAN error (%d)\n", err);
697
698 brcmf_set_mpc(ndev, 1);
699 goto scan_out;
700 }
701 }
702
703 return 0;
704
705scan_out:
706 clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
707 cfg->scan_request = NULL;
708 return err;
709}
710
711static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
712 struct cfg80211_scan_request *request)
713{
714 u32 n_ssids;
715 u32 n_channels;
716 s32 i;
717 s32 offset;
718 u16 chanspec;
719 char *ptr;
720 struct brcmf_ssid_le ssid_le;
721
722 memset(params_le->bssid, 0xFF, ETH_ALEN);
723 params_le->bss_type = DOT11_BSSTYPE_ANY;
724 params_le->scan_type = 0;
725 params_le->channel_num = 0;
726 params_le->nprobes = cpu_to_le32(-1);
727 params_le->active_time = cpu_to_le32(-1);
728 params_le->passive_time = cpu_to_le32(-1);
729 params_le->home_time = cpu_to_le32(-1);
730 memset(&params_le->ssid_le, 0, sizeof(params_le->ssid_le));
731
732 /* if request is null exit so it will be all channel broadcast scan */
733 if (!request)
734 return;
735
736 n_ssids = request->n_ssids;
737 n_channels = request->n_channels;
738 /* Copy channel array if applicable */
739 WL_SCAN("### List of channelspecs to scan ### %d\n", n_channels);
740 if (n_channels > 0) {
741 for (i = 0; i < n_channels; i++) {
742 chanspec = channel_to_chanspec(request->channels[i]);
743 WL_SCAN("Chan : %d, Channel spec: %x\n",
744 request->channels[i]->hw_value, chanspec);
745 params_le->channel_list[i] = cpu_to_le16(chanspec);
746 }
747 } else {
748 WL_SCAN("Scanning all channels\n");
749 }
750 /* Copy ssid array if applicable */
751 WL_SCAN("### List of SSIDs to scan ### %d\n", n_ssids);
752 if (n_ssids > 0) {
753 offset = offsetof(struct brcmf_scan_params_le, channel_list) +
754 n_channels * sizeof(u16);
755 offset = roundup(offset, sizeof(u32));
756 ptr = (char *)params_le + offset;
757 for (i = 0; i < n_ssids; i++) {
758 memset(&ssid_le, 0, sizeof(ssid_le));
759 ssid_le.SSID_len =
760 cpu_to_le32(request->ssids[i].ssid_len);
761 memcpy(ssid_le.SSID, request->ssids[i].ssid,
762 request->ssids[i].ssid_len);
763 if (!ssid_le.SSID_len)
764 WL_SCAN("%d: Broadcast scan\n", i);
765 else
766 WL_SCAN("%d: scan for %s size =%d\n", i,
767 ssid_le.SSID, ssid_le.SSID_len);
768 memcpy(ptr, &ssid_le, sizeof(ssid_le));
769 ptr += sizeof(ssid_le);
770 }
771 } else {
772 WL_SCAN("Broadcast scan %p\n", request->ssids);
773 if ((request->ssids) && request->ssids->ssid_len) {
774 WL_SCAN("SSID %s len=%d\n", params_le->ssid_le.SSID,
775 request->ssids->ssid_len);
776 params_le->ssid_le.SSID_len =
777 cpu_to_le32(request->ssids->ssid_len);
778 memcpy(&params_le->ssid_le.SSID, request->ssids->ssid,
779 request->ssids->ssid_len);
780 }
781 }
782 /* Adding mask to channel numbers */
783 params_le->channel_num =
784 cpu_to_le32((n_ssids << BRCMF_SCAN_PARAMS_NSSID_SHIFT) |
785 (n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK));
786}
787
788static s32
789brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
790 struct net_device *ndev,
791 bool aborted, bool fw_abort)
792{
793 struct brcmf_scan_params_le params_le;
794 struct cfg80211_scan_request *scan_request;
795 s32 err = 0;
796
797 WL_SCAN("Enter\n");
798
799 /* clear scan request, because the FW abort can cause a second call */
800 /* to this functon and might cause a double cfg80211_scan_done */
801 scan_request = cfg->scan_request;
802 cfg->scan_request = NULL;
803
804 if (timer_pending(&cfg->escan_timeout))
805 del_timer_sync(&cfg->escan_timeout);
806
807 if (fw_abort) {
808 /* Do a scan abort to stop the driver's scan engine */
809 WL_SCAN("ABORT scan in firmware\n");
810 memset(&params_le, 0, sizeof(params_le));
811 memset(params_le.bssid, 0xFF, ETH_ALEN);
812 params_le.bss_type = DOT11_BSSTYPE_ANY;
813 params_le.scan_type = 0;
814 params_le.channel_num = cpu_to_le32(1);
815 params_le.nprobes = cpu_to_le32(1);
816 params_le.active_time = cpu_to_le32(-1);
817 params_le.passive_time = cpu_to_le32(-1);
818 params_le.home_time = cpu_to_le32(-1);
819 /* Scan is aborted by setting channel_list[0] to -1 */
820 params_le.channel_list[0] = cpu_to_le16(-1);
821 /* E-Scan (or anyother type) can be aborted by SCAN */
822 err = brcmf_fil_cmd_data_set(netdev_priv(ndev), BRCMF_C_SCAN,
823 &params_le, sizeof(params_le));
824 if (err)
825 WL_ERR("Scan abort failed\n");
826 }
827 /*
828 * e-scan can be initiated by scheduled scan
829 * which takes precedence.
830 */
831 if (cfg->sched_escan) {
832 WL_SCAN("scheduled scan completed\n");
833 cfg->sched_escan = false;
834 if (!aborted)
835 cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
836 brcmf_set_mpc(ndev, 1);
837 } else if (scan_request) {
838 WL_SCAN("ESCAN Completed scan: %s\n",
839 aborted ? "Aborted" : "Done");
840 cfg80211_scan_done(scan_request, aborted);
841 brcmf_set_mpc(ndev, 1);
842 }
843 if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
844 WL_ERR("Scan complete while device not scanning\n");
845 return -EPERM;
846 }
847
848 return err;
849}
850
851static s32
852brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev,
853 struct cfg80211_scan_request *request, u16 action)
854{
855 s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
856 offsetof(struct brcmf_escan_params_le, params_le);
857 struct brcmf_escan_params_le *params;
858 s32 err = 0;
859
860 WL_SCAN("E-SCAN START\n");
861
862 if (request != NULL) {
863 /* Allocate space for populating ssids in struct */
864 params_size += sizeof(u32) * ((request->n_channels + 1) / 2);
865
866 /* Allocate space for populating ssids in struct */
867 params_size += sizeof(struct brcmf_ssid) * request->n_ssids;
868 }
869
870 params = kzalloc(params_size, GFP_KERNEL);
871 if (!params) {
872 err = -ENOMEM;
873 goto exit;
874 }
875 BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN);
876 brcmf_escan_prep(&params->params_le, request);
877 params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
878 params->action = cpu_to_le16(action);
879 params->sync_id = cpu_to_le16(0x1234);
880
881 err = brcmf_fil_iovar_data_set(netdev_priv(ndev), "escan",
882 params, params_size);
883 if (err) {
884 if (err == -EBUSY)
885 WL_INFO("system busy : escan canceled\n");
886 else
887 WL_ERR("error (%d)\n", err);
888 }
889
890 kfree(params);
891exit:
892 return err;
893}
894
895static s32
896brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy,
897 struct net_device *ndev, struct cfg80211_scan_request *request)
898{
899 s32 err;
900 u32 passive_scan;
901 struct brcmf_scan_results *results;
902
903 WL_SCAN("Enter\n");
904 cfg->escan_info.ndev = ndev;
905 cfg->escan_info.wiphy = wiphy;
906 cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANNING;
907 passive_scan = cfg->active_scan ? 0 : 1;
908 err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PASSIVE_SCAN,
909 passive_scan);
910 if (err) {
911 WL_ERR("error (%d)\n", err);
912 return err;
913 }
914 brcmf_set_mpc(ndev, 0);
915 results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf;
916 results->version = 0;
917 results->count = 0;
918 results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE;
919
920 err = brcmf_run_escan(cfg, ndev, request, WL_ESCAN_ACTION_START);
921 if (err)
922 brcmf_set_mpc(ndev, 1);
923 return err;
924}
925
926static s32
927brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
928 struct cfg80211_scan_request *request,
929 struct cfg80211_ssid *this_ssid)
930{
931 struct brcmf_if *ifp = netdev_priv(ndev);
932 struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
933 struct cfg80211_ssid *ssids;
934 struct brcmf_cfg80211_scan_req *sr = cfg->scan_req_int;
935 u32 passive_scan;
936 bool escan_req;
937 bool spec_scan;
938 s32 err;
939 u32 SSID_len;
940
941 WL_SCAN("START ESCAN\n");
942
943 if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
944 WL_ERR("Scanning already: status (%lu)\n", cfg->scan_status);
945 return -EAGAIN;
946 }
947 if (test_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status)) {
948 WL_ERR("Scanning being aborted: status (%lu)\n",
949 cfg->scan_status);
950 return -EAGAIN;
951 }
952 if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) {
953 WL_ERR("Connecting: status (%lu)\n", ifp->vif->sme_state);
954 return -EAGAIN;
955 }
956
957 /* Arm scan timeout timer */
958 mod_timer(&cfg->escan_timeout, jiffies +
959 WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000);
960
961 escan_req = false;
962 if (request) {
963 /* scan bss */
964 ssids = request->ssids;
965 escan_req = true;
966 } else {
967 /* scan in ibss */
968 /* we don't do escan in ibss */
969 ssids = this_ssid;
970 }
971
972 cfg->scan_request = request;
973 set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
974 if (escan_req) {
975 err = brcmf_do_escan(cfg, wiphy, ndev, request);
976 if (!err)
977 return err;
978 else
979 goto scan_out;
980 } else {
981 WL_SCAN("ssid \"%s\", ssid_len (%d)\n",
982 ssids->ssid, ssids->ssid_len);
983 memset(&sr->ssid_le, 0, sizeof(sr->ssid_le));
984 SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len);
985 sr->ssid_le.SSID_len = cpu_to_le32(0);
986 spec_scan = false;
987 if (SSID_len) {
988 memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len);
989 sr->ssid_le.SSID_len = cpu_to_le32(SSID_len);
990 spec_scan = true;
991 } else
992 WL_SCAN("Broadcast scan\n");
993
994 passive_scan = cfg->active_scan ? 0 : 1;
995 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN,
996 passive_scan);
997 if (err) {
998 WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
999 goto scan_out;
1000 }
1001 brcmf_set_mpc(ndev, 0);
1002 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
1003 &sr->ssid_le, sizeof(sr->ssid_le));
1004 if (err) {
1005 if (err == -EBUSY)
1006 WL_INFO("BUSY: scan for \"%s\" canceled\n",
1007 sr->ssid_le.SSID);
1008 else
1009 WL_ERR("WLC_SCAN error (%d)\n", err);
1010
1011 brcmf_set_mpc(ndev, 1);
1012 goto scan_out;
1013 }
1014 }
1015
1016 return 0;
1017
1018scan_out:
1019 clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
1020 if (timer_pending(&cfg->escan_timeout))
1021 del_timer_sync(&cfg->escan_timeout);
1022 cfg->scan_request = NULL;
1023 return err;
1024}
1025
1026static s32
1027brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
1028{
1029 struct net_device *ndev = request->wdev->netdev;
1030 struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
1031 s32 err = 0;
1032
1033 WL_TRACE("Enter\n");
1034
1035 if (!check_vif_up(container_of(request->wdev,
1036 struct brcmf_cfg80211_vif, wdev)))
1037 return -EIO;
1038
1039 if (cfg->iscan_on)
1040 err = brcmf_cfg80211_iscan(wiphy, ndev, request, NULL);
1041 else if (cfg->escan_on)
1042 err = brcmf_cfg80211_escan(wiphy, ndev, request, NULL);
1043
1044 if (err)
1045 WL_ERR("scan error (%d)\n", err);
1046
1047 WL_TRACE("Exit\n");
1048 return err;
1049}
1050
1051static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold)
1052{
1053 s32 err = 0;
1054
1055 err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "rtsthresh",
1056 rts_threshold);
1057 if (err)
1058 WL_ERR("Error (%d)\n", err);
1059
1060 return err;
1061}
1062
1063static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold)
1064{
1065 s32 err = 0;
1066
1067 err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "fragthresh",
1068 frag_threshold);
1069 if (err)
1070 WL_ERR("Error (%d)\n", err);
1071
1072 return err;
1073}
1074
1075static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l)
1076{
1077 s32 err = 0;
1078 u32 cmd = (l ? BRCM_SET_LRL : BRCM_SET_SRL);
1079
1080 err = brcmf_fil_cmd_int_set(netdev_priv(ndev), cmd, retry);
1081 if (err) {
1082 WL_ERR("cmd (%d) , error (%d)\n", cmd, err);
1083 return err;
1084 }
1085 return err;
1086}
1087
1088static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1089{
1090 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
1091 struct net_device *ndev = cfg_to_ndev(cfg);
1092 struct brcmf_if *ifp = netdev_priv(ndev);
1093 s32 err = 0;
1094
1095 WL_TRACE("Enter\n");
1096 if (!check_vif_up(ifp->vif))
1097 return -EIO;
1098
1099 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
1100 (cfg->conf->rts_threshold != wiphy->rts_threshold)) {
1101 cfg->conf->rts_threshold = wiphy->rts_threshold;
1102 err = brcmf_set_rts(ndev, cfg->conf->rts_threshold);
1103 if (!err)
1104 goto done;
1105 }
1106 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
1107 (cfg->conf->frag_threshold != wiphy->frag_threshold)) {
1108 cfg->conf->frag_threshold = wiphy->frag_threshold;
1109 err = brcmf_set_frag(ndev, cfg->conf->frag_threshold);
1110 if (!err)
1111 goto done;
1112 }
1113 if (changed & WIPHY_PARAM_RETRY_LONG
1114 && (cfg->conf->retry_long != wiphy->retry_long)) {
1115 cfg->conf->retry_long = wiphy->retry_long;
1116 err = brcmf_set_retry(ndev, cfg->conf->retry_long, true);
1117 if (!err)
1118 goto done;
1119 }
1120 if (changed & WIPHY_PARAM_RETRY_SHORT
1121 && (cfg->conf->retry_short != wiphy->retry_short)) {
1122 cfg->conf->retry_short = wiphy->retry_short;
1123 err = brcmf_set_retry(ndev, cfg->conf->retry_short, false);
1124 if (!err)
1125 goto done;
1126 }
1127
1128done:
1129 WL_TRACE("Exit\n");
1130 return err;
1131}
1132
1133static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
1134{
1135 memset(prof, 0, sizeof(*prof));
1136}
1137
1138static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params,
1139 size_t *join_params_size)
1140{
1141 u16 chanspec = 0;
1142
1143 if (ch != 0) {
1144 if (ch <= CH_MAX_2G_CHANNEL)
1145 chanspec |= WL_CHANSPEC_BAND_2G;
1146 else
1147 chanspec |= WL_CHANSPEC_BAND_5G;
1148
1149 chanspec |= WL_CHANSPEC_BW_20;
1150 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
1151
1152 *join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE +
1153 sizeof(u16);
1154
1155 chanspec |= (ch & WL_CHANSPEC_CHAN_MASK);
1156 join_params->params_le.chanspec_list[0] = cpu_to_le16(chanspec);
1157 join_params->params_le.chanspec_num = cpu_to_le32(1);
1158
1159 WL_CONN("join_params->params.chanspec_list[0]= %#X,"
1160 "channel %d, chanspec %#X\n",
1161 chanspec, ch, chanspec);
1162 }
1163}
1164
1165static void brcmf_link_down(struct brcmf_cfg80211_info *cfg)
1166{
1167 struct net_device *ndev = NULL;
1168 s32 err = 0;
1169
1170 WL_TRACE("Enter\n");
1171
1172 if (cfg->link_up) {
1173 ndev = cfg_to_ndev(cfg);
1174 WL_INFO("Call WLC_DISASSOC to stop excess roaming\n ");
1175 err = brcmf_fil_cmd_data_set(netdev_priv(ndev),
1176 BRCMF_C_DISASSOC, NULL, 0);
1177 if (err)
1178 WL_ERR("WLC_DISASSOC failed (%d)\n", err);
1179 cfg->link_up = false;
1180 }
1181 WL_TRACE("Exit\n");
1182}
1183
1184static s32
1185brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
1186 struct cfg80211_ibss_params *params)
1187{
1188 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
1189 struct brcmf_if *ifp = netdev_priv(ndev);
1190 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
1191 struct brcmf_join_params join_params;
1192 size_t join_params_size = 0;
1193 s32 err = 0;
1194 s32 wsec = 0;
1195 s32 bcnprd;
1196
1197 WL_TRACE("Enter\n");
1198 if (!check_vif_up(ifp->vif))
1199 return -EIO;
1200
1201 if (params->ssid)
1202 WL_CONN("SSID: %s\n", params->ssid);
1203 else {
1204 WL_CONN("SSID: NULL, Not supported\n");
1205 return -EOPNOTSUPP;
1206 }
1207
1208 set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
1209
1210 if (params->bssid)
1211 WL_CONN("BSSID: %pM\n", params->bssid);
1212 else
1213 WL_CONN("No BSSID specified\n");
1214
1215 if (params->channel)
1216 WL_CONN("channel: %d\n", params->channel->center_freq);
1217 else
1218 WL_CONN("no channel specified\n");
1219
1220 if (params->channel_fixed)
1221 WL_CONN("fixed channel required\n");
1222 else
1223 WL_CONN("no fixed channel required\n");
1224
1225 if (params->ie && params->ie_len)
1226 WL_CONN("ie len: %d\n", params->ie_len);
1227 else
1228 WL_CONN("no ie specified\n");
1229
1230 if (params->beacon_interval)
1231 WL_CONN("beacon interval: %d\n", params->beacon_interval);
1232 else
1233 WL_CONN("no beacon interval specified\n");
1234
1235 if (params->basic_rates)
1236 WL_CONN("basic rates: %08X\n", params->basic_rates);
1237 else
1238 WL_CONN("no basic rates specified\n");
1239
1240 if (params->privacy)
1241 WL_CONN("privacy required\n");
1242 else
1243 WL_CONN("no privacy required\n");
1244
1245 /* Configure Privacy for starter */
1246 if (params->privacy)
1247 wsec |= WEP_ENABLED;
1248
1249 err = brcmf_fil_iovar_int_set(ifp, "wsec", wsec);
1250 if (err) {
1251 WL_ERR("wsec failed (%d)\n", err);
1252 goto done;
1253 }
1254
1255 /* Configure Beacon Interval for starter */
1256 if (params->beacon_interval)
1257 bcnprd = params->beacon_interval;
1258 else
1259 bcnprd = 100;
1260
1261 err = brcmf_fil_cmd_int_set(ifp, BRCM_SET_BCNPRD, bcnprd);
1262 if (err) {
1263 WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err);
1264 goto done;
1265 }
1266
1267 /* Configure required join parameter */
1268 memset(&join_params, 0, sizeof(struct brcmf_join_params));
1269
1270 /* SSID */
1271 profile->ssid.SSID_len = min_t(u32, params->ssid_len, 32);
1272 memcpy(profile->ssid.SSID, params->ssid, profile->ssid.SSID_len);
1273 memcpy(join_params.ssid_le.SSID, params->ssid, profile->ssid.SSID_len);
1274 join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len);
1275 join_params_size = sizeof(join_params.ssid_le);
1276
1277 /* BSSID */
1278 if (params->bssid) {
1279 memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN);
1280 join_params_size = sizeof(join_params.ssid_le) +
1281 BRCMF_ASSOC_PARAMS_FIXED_SIZE;
1282 memcpy(profile->bssid, params->bssid, ETH_ALEN);
1283 } else {
1284 memset(join_params.params_le.bssid, 0xFF, ETH_ALEN);
1285 memset(profile->bssid, 0, ETH_ALEN);
1286 }
1287
1288 /* Channel */
1289 if (params->channel) {
1290 u32 target_channel;
1291
1292 cfg->channel =
1293 ieee80211_frequency_to_channel(
1294 params->channel->center_freq);
1295 if (params->channel_fixed) {
1296 /* adding chanspec */
1297 brcmf_ch_to_chanspec(cfg->channel,
1298 &join_params, &join_params_size);
1299 }
1300
1301 /* set channel for starter */
1302 target_channel = cfg->channel;
1303 err = brcmf_fil_cmd_int_set(ifp, BRCM_SET_CHANNEL,
1304 target_channel);
1305 if (err) {
1306 WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err);
1307 goto done;
1308 }
1309 } else
1310 cfg->channel = 0;
1311
1312 cfg->ibss_starter = false;
1313
1314
1315 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
1316 &join_params, join_params_size);
1317 if (err) {
1318 WL_ERR("WLC_SET_SSID failed (%d)\n", err);
1319 goto done;
1320 }
1321
1322done:
1323 if (err)
1324 clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
1325 WL_TRACE("Exit\n");
1326 return err;
1327}
1328
1329static s32
1330brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
1331{
1332 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
1333 struct brcmf_if *ifp = netdev_priv(ndev);
1334 s32 err = 0;
1335
1336 WL_TRACE("Enter\n");
1337 if (!check_vif_up(ifp->vif))
1338 return -EIO;
1339
1340 brcmf_link_down(cfg);
1341
1342 WL_TRACE("Exit\n");
1343
1344 return err;
1345}
1346
1347static s32 brcmf_set_wpa_version(struct net_device *ndev,
1348 struct cfg80211_connect_params *sme)
1349{
1350 struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
1351 struct brcmf_cfg80211_security *sec;
1352 s32 val = 0;
1353 s32 err = 0;
1354
1355 if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1356 val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
1357 else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1358 val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
1359 else
1360 val = WPA_AUTH_DISABLED;
1361 WL_CONN("setting wpa_auth to 0x%0x\n", val);
1362 err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "wpa_auth", val);
1363 if (err) {
1364 WL_ERR("set wpa_auth failed (%d)\n", err);
1365 return err;
1366 }
1367 sec = &profile->sec;
1368 sec->wpa_versions = sme->crypto.wpa_versions;
1369 return err;
1370}
1371
1372static s32 brcmf_set_auth_type(struct net_device *ndev,
1373 struct cfg80211_connect_params *sme)
1374{
1375 struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
1376 struct brcmf_cfg80211_security *sec;
1377 s32 val = 0;
1378 s32 err = 0;
1379
1380 switch (sme->auth_type) {
1381 case NL80211_AUTHTYPE_OPEN_SYSTEM:
1382 val = 0;
1383 WL_CONN("open system\n");
1384 break;
1385 case NL80211_AUTHTYPE_SHARED_KEY:
1386 val = 1;
1387 WL_CONN("shared key\n");
1388 break;
1389 case NL80211_AUTHTYPE_AUTOMATIC:
1390 val = 2;
1391 WL_CONN("automatic\n");
1392 break;
1393 case NL80211_AUTHTYPE_NETWORK_EAP:
1394 WL_CONN("network eap\n");
1395 default:
1396 val = 2;
1397 WL_ERR("invalid auth type (%d)\n", sme->auth_type);
1398 break;
1399 }
1400
1401 err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "auth", val);
1402 if (err) {
1403 WL_ERR("set auth failed (%d)\n", err);
1404 return err;
1405 }
1406 sec = &profile->sec;
1407 sec->auth_type = sme->auth_type;
1408 return err;
1409}
1410
1411static s32
1412brcmf_set_set_cipher(struct net_device *ndev,
1413 struct cfg80211_connect_params *sme)
1414{
1415 struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
1416 struct brcmf_cfg80211_security *sec;
1417 s32 pval = 0;
1418 s32 gval = 0;
1419 s32 err = 0;
1420
1421 if (sme->crypto.n_ciphers_pairwise) {
1422 switch (sme->crypto.ciphers_pairwise[0]) {
1423 case WLAN_CIPHER_SUITE_WEP40:
1424 case WLAN_CIPHER_SUITE_WEP104:
1425 pval = WEP_ENABLED;
1426 break;
1427 case WLAN_CIPHER_SUITE_TKIP:
1428 pval = TKIP_ENABLED;
1429 break;
1430 case WLAN_CIPHER_SUITE_CCMP:
1431 pval = AES_ENABLED;
1432 break;
1433 case WLAN_CIPHER_SUITE_AES_CMAC:
1434 pval = AES_ENABLED;
1435 break;
1436 default:
1437 WL_ERR("invalid cipher pairwise (%d)\n",
1438 sme->crypto.ciphers_pairwise[0]);
1439 return -EINVAL;
1440 }
1441 }
1442 if (sme->crypto.cipher_group) {
1443 switch (sme->crypto.cipher_group) {
1444 case WLAN_CIPHER_SUITE_WEP40:
1445 case WLAN_CIPHER_SUITE_WEP104:
1446 gval = WEP_ENABLED;
1447 break;
1448 case WLAN_CIPHER_SUITE_TKIP:
1449 gval = TKIP_ENABLED;
1450 break;
1451 case WLAN_CIPHER_SUITE_CCMP:
1452 gval = AES_ENABLED;
1453 break;
1454 case WLAN_CIPHER_SUITE_AES_CMAC:
1455 gval = AES_ENABLED;
1456 break;
1457 default:
1458 WL_ERR("invalid cipher group (%d)\n",
1459 sme->crypto.cipher_group);
1460 return -EINVAL;
1461 }
1462 }
1463
1464 WL_CONN("pval (%d) gval (%d)\n", pval, gval);
1465 err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "wsec", pval | gval);
1466 if (err) {
1467 WL_ERR("error (%d)\n", err);
1468 return err;
1469 }
1470
1471 sec = &profile->sec;
1472 sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
1473 sec->cipher_group = sme->crypto.cipher_group;
1474
1475 return err;
1476}
1477
1478static s32
1479brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
1480{
1481 struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
1482 struct brcmf_cfg80211_security *sec;
1483 s32 val = 0;
1484 s32 err = 0;
1485
1486 if (sme->crypto.n_akm_suites) {
1487 err = brcmf_fil_iovar_int_get(netdev_priv(ndev),
1488 "wpa_auth", &val);
1489 if (err) {
1490 WL_ERR("could not get wpa_auth (%d)\n", err);
1491 return err;
1492 }
1493 if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
1494 switch (sme->crypto.akm_suites[0]) {
1495 case WLAN_AKM_SUITE_8021X:
1496 val = WPA_AUTH_UNSPECIFIED;
1497 break;
1498 case WLAN_AKM_SUITE_PSK:
1499 val = WPA_AUTH_PSK;
1500 break;
1501 default:
1502 WL_ERR("invalid cipher group (%d)\n",
1503 sme->crypto.cipher_group);
1504 return -EINVAL;
1505 }
1506 } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
1507 switch (sme->crypto.akm_suites[0]) {
1508 case WLAN_AKM_SUITE_8021X:
1509 val = WPA2_AUTH_UNSPECIFIED;
1510 break;
1511 case WLAN_AKM_SUITE_PSK:
1512 val = WPA2_AUTH_PSK;
1513 break;
1514 default:
1515 WL_ERR("invalid cipher group (%d)\n",
1516 sme->crypto.cipher_group);
1517 return -EINVAL;
1518 }
1519 }
1520
1521 WL_CONN("setting wpa_auth to %d\n", val);
1522 err = brcmf_fil_iovar_int_set(netdev_priv(ndev),
1523 "wpa_auth", val);
1524 if (err) {
1525 WL_ERR("could not set wpa_auth (%d)\n", err);
1526 return err;
1527 }
1528 }
1529 sec = &profile->sec;
1530 sec->wpa_auth = sme->crypto.akm_suites[0];
1531
1532 return err;
1533}
1534
1535static s32
1536brcmf_set_sharedkey(struct net_device *ndev,
1537 struct cfg80211_connect_params *sme)
1538{
1539 struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
1540 struct brcmf_cfg80211_security *sec;
1541 struct brcmf_wsec_key key;
1542 s32 val;
1543 s32 err = 0;
1544
1545 WL_CONN("key len (%d)\n", sme->key_len);
1546
1547 if (sme->key_len == 0)
1548 return 0;
1549
1550 sec = &profile->sec;
1551 WL_CONN("wpa_versions 0x%x cipher_pairwise 0x%x\n",
1552 sec->wpa_versions, sec->cipher_pairwise);
1553
1554 if (sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))
1555 return 0;
1556
1557 if (!(sec->cipher_pairwise &
1558 (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104)))
1559 return 0;
1560
1561 memset(&key, 0, sizeof(key));
1562 key.len = (u32) sme->key_len;
1563 key.index = (u32) sme->key_idx;
1564 if (key.len > sizeof(key.data)) {
1565 WL_ERR("Too long key length (%u)\n", key.len);
1566 return -EINVAL;
1567 }
1568 memcpy(key.data, sme->key, key.len);
1569 key.flags = BRCMF_PRIMARY_KEY;
1570 switch (sec->cipher_pairwise) {
1571 case WLAN_CIPHER_SUITE_WEP40:
1572 key.algo = CRYPTO_ALGO_WEP1;
1573 break;
1574 case WLAN_CIPHER_SUITE_WEP104:
1575 key.algo = CRYPTO_ALGO_WEP128;
1576 break;
1577 default:
1578 WL_ERR("Invalid algorithm (%d)\n",
1579 sme->crypto.ciphers_pairwise[0]);
1580 return -EINVAL;
1581 }
1582 /* Set the new key/index */
1583 WL_CONN("key length (%d) key index (%d) algo (%d)\n",
1584 key.len, key.index, key.algo);
1585 WL_CONN("key \"%s\"\n", key.data);
1586 err = send_key_to_dongle(ndev, &key);
1587 if (err)
1588 return err;
1589
1590 if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
1591 WL_CONN("set auth_type to shared key\n");
1592 val = WL_AUTH_SHARED_KEY; /* shared key */
1593 err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "auth", val);
1594 if (err)
1595 WL_ERR("set auth failed (%d)\n", err);
1596 }
1597 return err;
1598}
1599
1600static s32
1601brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
1602 struct cfg80211_connect_params *sme)
1603{
1604 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
1605 struct brcmf_if *ifp = netdev_priv(ndev);
1606 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
1607 struct ieee80211_channel *chan = sme->channel;
1608 struct brcmf_join_params join_params;
1609 size_t join_params_size;
1610 struct brcmf_ssid ssid;
1611
1612 s32 err = 0;
1613
1614 WL_TRACE("Enter\n");
1615 if (!check_vif_up(ifp->vif))
1616 return -EIO;
1617
1618 if (!sme->ssid) {
1619 WL_ERR("Invalid ssid\n");
1620 return -EOPNOTSUPP;
1621 }
1622
1623 set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
1624
1625 if (chan) {
1626 cfg->channel =
1627 ieee80211_frequency_to_channel(chan->center_freq);
1628 WL_CONN("channel (%d), center_req (%d)\n",
1629 cfg->channel, chan->center_freq);
1630 } else
1631 cfg->channel = 0;
1632
1633 WL_INFO("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);
1634
1635 err = brcmf_set_wpa_version(ndev, sme);
1636 if (err) {
1637 WL_ERR("wl_set_wpa_version failed (%d)\n", err);
1638 goto done;
1639 }
1640
1641 err = brcmf_set_auth_type(ndev, sme);
1642 if (err) {
1643 WL_ERR("wl_set_auth_type failed (%d)\n", err);
1644 goto done;
1645 }
1646
1647 err = brcmf_set_set_cipher(ndev, sme);
1648 if (err) {
1649 WL_ERR("wl_set_set_cipher failed (%d)\n", err);
1650 goto done;
1651 }
1652
1653 err = brcmf_set_key_mgmt(ndev, sme);
1654 if (err) {
1655 WL_ERR("wl_set_key_mgmt failed (%d)\n", err);
1656 goto done;
1657 }
1658
1659 err = brcmf_set_sharedkey(ndev, sme);
1660 if (err) {
1661 WL_ERR("brcmf_set_sharedkey failed (%d)\n", err);
1662 goto done;
1663 }
1664
1665 memset(&join_params, 0, sizeof(join_params));
1666 join_params_size = sizeof(join_params.ssid_le);
1667
1668 profile->ssid.SSID_len = min_t(u32,
1669 sizeof(ssid.SSID), (u32)sme->ssid_len);
1670 memcpy(&join_params.ssid_le.SSID, sme->ssid, profile->ssid.SSID_len);
1671 memcpy(&profile->ssid.SSID, sme->ssid, profile->ssid.SSID_len);
1672 join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len);
1673
1674 memset(join_params.params_le.bssid, 0xFF, ETH_ALEN);
1675
1676 if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN)
1677 WL_CONN("ssid \"%s\", len (%d)\n",
1678 ssid.SSID, ssid.SSID_len);
1679
1680 brcmf_ch_to_chanspec(cfg->channel,
1681 &join_params, &join_params_size);
1682 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
1683 &join_params, join_params_size);
1684 if (err)
1685 WL_ERR("WLC_SET_SSID failed (%d)\n", err);
1686
1687done:
1688 if (err)
1689 clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
1690 WL_TRACE("Exit\n");
1691 return err;
1692}
1693
1694static s32
1695brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,
1696 u16 reason_code)
1697{
1698 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
1699 struct brcmf_if *ifp = netdev_priv(ndev);
1700 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
1701 struct brcmf_scb_val_le scbval;
1702 s32 err = 0;
1703
1704 WL_TRACE("Enter. Reason code = %d\n", reason_code);
1705 if (!check_vif_up(ifp->vif))
1706 return -EIO;
1707
1708 clear_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
1709
1710 memcpy(&scbval.ea, &profile->bssid, ETH_ALEN);
1711 scbval.val = cpu_to_le32(reason_code);
1712 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_DISASSOC,
1713 &scbval, sizeof(scbval));
1714 if (err)
1715 WL_ERR("error (%d)\n", err);
1716
1717 cfg->link_up = false;
1718
1719 WL_TRACE("Exit\n");
1720 return err;
1721}
1722
1723static s32
1724brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
1725 enum nl80211_tx_power_setting type, s32 mbm)
1726{
1727
1728 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
1729 struct net_device *ndev = cfg_to_ndev(cfg);
1730 struct brcmf_if *ifp = netdev_priv(ndev);
1731 u16 txpwrmw;
1732 s32 err = 0;
1733 s32 disable = 0;
1734 s32 dbm = MBM_TO_DBM(mbm);
1735
1736 WL_TRACE("Enter\n");
1737 if (!check_vif_up(ifp->vif))
1738 return -EIO;
1739
1740 switch (type) {
1741 case NL80211_TX_POWER_AUTOMATIC:
1742 break;
1743 case NL80211_TX_POWER_LIMITED:
1744 case NL80211_TX_POWER_FIXED:
1745 if (dbm < 0) {
1746 WL_ERR("TX_POWER_FIXED - dbm is negative\n");
1747 err = -EINVAL;
1748 goto done;
1749 }
1750 break;
1751 }
1752 /* Make sure radio is off or on as far as software is concerned */
1753 disable = WL_RADIO_SW_DISABLE << 16;
1754 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_RADIO, disable);
1755 if (err)
1756 WL_ERR("WLC_SET_RADIO error (%d)\n", err);
1757
1758 if (dbm > 0xffff)
1759 txpwrmw = 0xffff;
1760 else
1761 txpwrmw = (u16) dbm;
1762 err = brcmf_fil_iovar_int_set(ifp, "qtxpower",
1763 (s32)brcmf_mw_to_qdbm(txpwrmw));
1764 if (err)
1765 WL_ERR("qtxpower error (%d)\n", err);
1766 cfg->conf->tx_power = dbm;
1767
1768done:
1769 WL_TRACE("Exit\n");
1770 return err;
1771}
1772
1773static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
1774{
1775 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
1776 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
1777 s32 txpwrdbm;
1778 u8 result;
1779 s32 err = 0;
1780
1781 WL_TRACE("Enter\n");
1782 if (!check_vif_up(ifp->vif))
1783 return -EIO;
1784
1785 err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &txpwrdbm);
1786 if (err) {
1787 WL_ERR("error (%d)\n", err);
1788 goto done;
1789 }
1790
1791 result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
1792 *dbm = (s32) brcmf_qdbm_to_mw(result);
1793
1794done:
1795 WL_TRACE("Exit\n");
1796 return err;
1797}
1798
1799static s32
1800brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
1801 u8 key_idx, bool unicast, bool multicast)
1802{
1803 struct brcmf_if *ifp = netdev_priv(ndev);
1804 u32 index;
1805 u32 wsec;
1806 s32 err = 0;
1807
1808 WL_TRACE("Enter\n");
1809 WL_CONN("key index (%d)\n", key_idx);
1810 if (!check_vif_up(ifp->vif))
1811 return -EIO;
1812
1813 err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
1814 if (err) {
1815 WL_ERR("WLC_GET_WSEC error (%d)\n", err);
1816 goto done;
1817 }
1818
1819 if (wsec & WEP_ENABLED) {
1820 /* Just select a new current key */
1821 index = key_idx;
1822 err = brcmf_fil_cmd_int_set(ifp,
1823 BRCMF_C_SET_KEY_PRIMARY, index);
1824 if (err)
1825 WL_ERR("error (%d)\n", err);
1826 }
1827done:
1828 WL_TRACE("Exit\n");
1829 return err;
1830}
1831
1832static s32
1833brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
1834 u8 key_idx, const u8 *mac_addr, struct key_params *params)
1835{
1836 struct brcmf_wsec_key key;
1837 s32 err = 0;
1838
1839 memset(&key, 0, sizeof(key));
1840 key.index = (u32) key_idx;
1841 /* Instead of bcast for ea address for default wep keys,
1842 driver needs it to be Null */
1843 if (!is_multicast_ether_addr(mac_addr))
1844 memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN);
1845 key.len = (u32) params->key_len;
1846 /* check for key index change */
1847 if (key.len == 0) {
1848 /* key delete */
1849 err = send_key_to_dongle(ndev, &key);
1850 if (err)
1851 WL_ERR("key delete error (%d)\n", err);
1852 } else {
1853 if (key.len > sizeof(key.data)) {
1854 WL_ERR("Invalid key length (%d)\n", key.len);
1855 return -EINVAL;
1856 }
1857
1858 WL_CONN("Setting the key index %d\n", key.index);
1859 memcpy(key.data, params->key, key.len);
1860
1861 if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
1862 u8 keybuf[8];
1863 memcpy(keybuf, &key.data[24], sizeof(keybuf));
1864 memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
1865 memcpy(&key.data[16], keybuf, sizeof(keybuf));
1866 }
1867
1868 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
1869 if (params->seq && params->seq_len == 6) {
1870 /* rx iv */
1871 u8 *ivptr;
1872 ivptr = (u8 *) params->seq;
1873 key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
1874 (ivptr[3] << 8) | ivptr[2];
1875 key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
1876 key.iv_initialized = true;
1877 }
1878
1879 switch (params->cipher) {
1880 case WLAN_CIPHER_SUITE_WEP40:
1881 key.algo = CRYPTO_ALGO_WEP1;
1882 WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
1883 break;
1884 case WLAN_CIPHER_SUITE_WEP104:
1885 key.algo = CRYPTO_ALGO_WEP128;
1886 WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
1887 break;
1888 case WLAN_CIPHER_SUITE_TKIP:
1889 key.algo = CRYPTO_ALGO_TKIP;
1890 WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
1891 break;
1892 case WLAN_CIPHER_SUITE_AES_CMAC:
1893 key.algo = CRYPTO_ALGO_AES_CCM;
1894 WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
1895 break;
1896 case WLAN_CIPHER_SUITE_CCMP:
1897 key.algo = CRYPTO_ALGO_AES_CCM;
1898 WL_CONN("WLAN_CIPHER_SUITE_CCMP\n");
1899 break;
1900 default:
1901 WL_ERR("Invalid cipher (0x%x)\n", params->cipher);
1902 return -EINVAL;
1903 }
1904 err = send_key_to_dongle(ndev, &key);
1905 if (err)
1906 WL_ERR("wsec_key error (%d)\n", err);
1907 }
1908 return err;
1909}
1910
1911static s32
1912brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
1913 u8 key_idx, bool pairwise, const u8 *mac_addr,
1914 struct key_params *params)
1915{
1916 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
1917 struct brcmf_if *ifp = netdev_priv(ndev);
1918 struct brcmf_wsec_key key;
1919 s32 val;
1920 s32 wsec;
1921 s32 err = 0;
1922 u8 keybuf[8];
1923
1924 WL_TRACE("Enter\n");
1925 WL_CONN("key index (%d)\n", key_idx);
1926 if (!check_vif_up(ifp->vif))
1927 return -EIO;
1928
1929 if (mac_addr) {
1930 WL_TRACE("Exit");
1931 return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params);
1932 }
1933 memset(&key, 0, sizeof(key));
1934
1935 key.len = (u32) params->key_len;
1936 key.index = (u32) key_idx;
1937
1938 if (key.len > sizeof(key.data)) {
1939 WL_ERR("Too long key length (%u)\n", key.len);
1940 err = -EINVAL;
1941 goto done;
1942 }
1943 memcpy(key.data, params->key, key.len);
1944
1945 key.flags = BRCMF_PRIMARY_KEY;
1946 switch (params->cipher) {
1947 case WLAN_CIPHER_SUITE_WEP40:
1948 key.algo = CRYPTO_ALGO_WEP1;
1949 val = WEP_ENABLED;
1950 WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
1951 break;
1952 case WLAN_CIPHER_SUITE_WEP104:
1953 key.algo = CRYPTO_ALGO_WEP128;
1954 val = WEP_ENABLED;
1955 WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
1956 break;
1957 case WLAN_CIPHER_SUITE_TKIP:
1958 if (cfg->conf->mode != WL_MODE_AP) {
1959 WL_CONN("Swapping key\n");
1960 memcpy(keybuf, &key.data[24], sizeof(keybuf));
1961 memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
1962 memcpy(&key.data[16], keybuf, sizeof(keybuf));
1963 }
1964 key.algo = CRYPTO_ALGO_TKIP;
1965 val = TKIP_ENABLED;
1966 WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
1967 break;
1968 case WLAN_CIPHER_SUITE_AES_CMAC:
1969 key.algo = CRYPTO_ALGO_AES_CCM;
1970 val = AES_ENABLED;
1971 WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
1972 break;
1973 case WLAN_CIPHER_SUITE_CCMP:
1974 key.algo = CRYPTO_ALGO_AES_CCM;
1975 val = AES_ENABLED;
1976 WL_CONN("WLAN_CIPHER_SUITE_CCMP\n");
1977 break;
1978 default:
1979 WL_ERR("Invalid cipher (0x%x)\n", params->cipher);
1980 err = -EINVAL;
1981 goto done;
1982 }
1983
1984 err = send_key_to_dongle(ndev, &key);
1985 if (err)
1986 goto done;
1987
1988 err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
1989 if (err) {
1990 WL_ERR("get wsec error (%d)\n", err);
1991 goto done;
1992 }
1993 wsec |= val;
1994 err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
1995 if (err) {
1996 WL_ERR("set wsec error (%d)\n", err);
1997 goto done;
1998 }
1999
2000done:
2001 WL_TRACE("Exit\n");
2002 return err;
2003}
2004
2005static s32
2006brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
2007 u8 key_idx, bool pairwise, const u8 *mac_addr)
2008{
2009 struct brcmf_if *ifp = netdev_priv(ndev);
2010 struct brcmf_wsec_key key;
2011 s32 err = 0;
2012
2013 WL_TRACE("Enter\n");
2014 if (!check_vif_up(ifp->vif))
2015 return -EIO;
2016
2017 memset(&key, 0, sizeof(key));
2018
2019 key.index = (u32) key_idx;
2020 key.flags = BRCMF_PRIMARY_KEY;
2021 key.algo = CRYPTO_ALGO_OFF;
2022
2023 WL_CONN("key index (%d)\n", key_idx);
2024
2025 /* Set the new key/index */
2026 err = send_key_to_dongle(ndev, &key);
2027 if (err) {
2028 if (err == -EINVAL) {
2029 if (key.index >= DOT11_MAX_DEFAULT_KEYS)
2030 /* we ignore this key index in this case */
2031 WL_ERR("invalid key index (%d)\n", key_idx);
2032 }
2033 /* Ignore this error, may happen during DISASSOC */
2034 err = -EAGAIN;
2035 }
2036
2037 WL_TRACE("Exit\n");
2038 return err;
2039}
2040
2041static s32
2042brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
2043 u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
2044 void (*callback) (void *cookie, struct key_params * params))
2045{
2046 struct key_params params;
2047 struct brcmf_if *ifp = netdev_priv(ndev);
2048 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
2049 struct brcmf_cfg80211_security *sec;
2050 s32 wsec;
2051 s32 err = 0;
2052
2053 WL_TRACE("Enter\n");
2054 WL_CONN("key index (%d)\n", key_idx);
2055 if (!check_vif_up(ifp->vif))
2056 return -EIO;
2057
2058 memset(&params, 0, sizeof(params));
2059
2060 err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
2061 if (err) {
2062 WL_ERR("WLC_GET_WSEC error (%d)\n", err);
2063 /* Ignore this error, may happen during DISASSOC */
2064 err = -EAGAIN;
2065 goto done;
2066 }
2067 switch (wsec & ~SES_OW_ENABLED) {
2068 case WEP_ENABLED:
2069 sec = &profile->sec;
2070 if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
2071 params.cipher = WLAN_CIPHER_SUITE_WEP40;
2072 WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
2073 } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
2074 params.cipher = WLAN_CIPHER_SUITE_WEP104;
2075 WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
2076 }
2077 break;
2078 case TKIP_ENABLED:
2079 params.cipher = WLAN_CIPHER_SUITE_TKIP;
2080 WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
2081 break;
2082 case AES_ENABLED:
2083 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
2084 WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
2085 break;
2086 default:
2087 WL_ERR("Invalid algo (0x%x)\n", wsec);
2088 err = -EINVAL;
2089 goto done;
2090 }
2091 callback(cookie, &params);
2092
2093done:
2094 WL_TRACE("Exit\n");
2095 return err;
2096}
2097
2098static s32
2099brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
2100 struct net_device *ndev, u8 key_idx)
2101{
2102 WL_INFO("Not supported\n");
2103
2104 return -EOPNOTSUPP;
2105}
2106
2107static s32
2108brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
2109 u8 *mac, struct station_info *sinfo)
2110{
2111 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
2112 struct brcmf_if *ifp = netdev_priv(ndev);
2113 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
2114 struct brcmf_scb_val_le scb_val;
2115 int rssi;
2116 s32 rate;
2117 s32 err = 0;
2118 u8 *bssid = profile->bssid;
2119 struct brcmf_sta_info_le sta_info_le;
2120
2121 WL_TRACE("Enter, MAC %pM\n", mac);
2122 if (!check_vif_up(ifp->vif))
2123 return -EIO;
2124
2125 if (cfg->conf->mode == WL_MODE_AP) {
2126 memcpy(&sta_info_le, mac, ETH_ALEN);
2127 err = brcmf_fil_iovar_data_get(ifp, "sta_info",
2128 &sta_info_le,
2129 sizeof(sta_info_le));
2130 if (err < 0) {
2131 WL_ERR("GET STA INFO failed, %d\n", err);
2132 goto done;
2133 }
2134 sinfo->filled = STATION_INFO_INACTIVE_TIME;
2135 sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
2136 if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) {
2137 sinfo->filled |= STATION_INFO_CONNECTED_TIME;
2138 sinfo->connected_time = le32_to_cpu(sta_info_le.in);
2139 }
2140 WL_TRACE("STA idle time : %d ms, connected time :%d sec\n",
2141 sinfo->inactive_time, sinfo->connected_time);
2142 } else if (cfg->conf->mode == WL_MODE_BSS) {
2143 if (memcmp(mac, bssid, ETH_ALEN)) {
2144 WL_ERR("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n",
2145 mac, bssid);
2146 err = -ENOENT;
2147 goto done;
2148 }
2149 /* Report the current tx rate */
2150 err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate);
2151 if (err) {
2152 WL_ERR("Could not get rate (%d)\n", err);
2153 goto done;
2154 } else {
2155 sinfo->filled |= STATION_INFO_TX_BITRATE;
2156 sinfo->txrate.legacy = rate * 5;
2157 WL_CONN("Rate %d Mbps\n", rate / 2);
2158 }
2159
2160 if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
2161 &ifp->vif->sme_state)) {
2162 memset(&scb_val, 0, sizeof(scb_val));
2163 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI,
2164 &scb_val, sizeof(scb_val));
2165 if (err) {
2166 WL_ERR("Could not get rssi (%d)\n", err);
2167 goto done;
2168 } else {
2169 rssi = le32_to_cpu(scb_val.val);
2170 sinfo->filled |= STATION_INFO_SIGNAL;
2171 sinfo->signal = rssi;
2172 WL_CONN("RSSI %d dBm\n", rssi);
2173 }
2174 }
2175 } else
2176 err = -EPERM;
2177done:
2178 WL_TRACE("Exit\n");
2179 return err;
2180}
2181
2182static s32
2183brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
2184 bool enabled, s32 timeout)
2185{
2186 s32 pm;
2187 s32 err = 0;
2188 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
2189 struct brcmf_if *ifp = netdev_priv(ndev);
2190
2191 WL_TRACE("Enter\n");
2192
2193 /*
2194 * Powersave enable/disable request is coming from the
2195 * cfg80211 even before the interface is up. In that
2196 * scenario, driver will be storing the power save
2197 * preference in cfg struct to apply this to
2198 * FW later while initializing the dongle
2199 */
2200 cfg->pwr_save = enabled;
2201 if (!check_vif_up(ifp->vif)) {
2202
2203 WL_INFO("Device is not ready, storing the value in cfg_info struct\n");
2204 goto done;
2205 }
2206
2207 pm = enabled ? PM_FAST : PM_OFF;
2208 WL_INFO("power save %s\n", (pm ? "enabled" : "disabled"));
2209
2210 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, pm);
2211 if (err) {
2212 if (err == -ENODEV)
2213 WL_ERR("net_device is not ready yet\n");
2214 else
2215 WL_ERR("error (%d)\n", err);
2216 }
2217done:
2218 WL_TRACE("Exit\n");
2219 return err;
2220}
2221
2222static s32
2223brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev,
2224 const u8 *addr,
2225 const struct cfg80211_bitrate_mask *mask)
2226{
2227 struct brcmf_if *ifp = netdev_priv(ndev);
2228 struct brcm_rateset_le rateset_le;
2229 s32 rate;
2230 s32 val;
2231 s32 err_bg;
2232 s32 err_a;
2233 u32 legacy;
2234 s32 err = 0;
2235
2236 WL_TRACE("Enter\n");
2237 if (!check_vif_up(ifp->vif))
2238 return -EIO;
2239
2240 /* addr param is always NULL. ignore it */
2241 /* Get current rateset */
2242 err = brcmf_fil_cmd_data_get(ifp, BRCM_GET_CURR_RATESET,
2243 &rateset_le, sizeof(rateset_le));
2244 if (err) {
2245 WL_ERR("could not get current rateset (%d)\n", err);
2246 goto done;
2247 }
2248
2249 legacy = ffs(mask->control[IEEE80211_BAND_2GHZ].legacy & 0xFFFF);
2250 if (!legacy)
2251 legacy = ffs(mask->control[IEEE80211_BAND_5GHZ].legacy &
2252 0xFFFF);
2253
2254 val = wl_g_rates[legacy - 1].bitrate * 100000;
2255
2256 if (val < le32_to_cpu(rateset_le.count))
2257 /* Select rate by rateset index */
2258 rate = rateset_le.rates[val] & 0x7f;
2259 else
2260 /* Specified rate in bps */
2261 rate = val / 500000;
2262
2263 WL_CONN("rate %d mbps\n", rate / 2);
2264
2265 /*
2266 *
2267 * Set rate override,
2268 * Since the is a/b/g-blind, both a/bg_rate are enforced.
2269 */
2270 err_bg = brcmf_fil_iovar_int_set(ifp, "bg_rate", rate);
2271 err_a = brcmf_fil_iovar_int_set(ifp, "a_rate", rate);
2272 if (err_bg && err_a) {
2273 WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a);
2274 err = err_bg | err_a;
2275 }
2276
2277done:
2278 WL_TRACE("Exit\n");
2279 return err;
2280}
2281
2282static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
2283 struct brcmf_bss_info_le *bi)
2284{
2285 struct wiphy *wiphy = cfg_to_wiphy(cfg);
2286 struct ieee80211_channel *notify_channel;
2287 struct cfg80211_bss *bss;
2288 struct ieee80211_supported_band *band;
2289 s32 err = 0;
2290 u16 channel;
2291 u32 freq;
2292 u16 notify_capability;
2293 u16 notify_interval;
2294 u8 *notify_ie;
2295 size_t notify_ielen;
2296 s32 notify_signal;
2297
2298 if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) {
2299 WL_ERR("Bss info is larger than buffer. Discarding\n");
2300 return 0;
2301 }
2302
2303 channel = bi->ctl_ch ? bi->ctl_ch :
2304 CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
2305
2306 if (channel <= CH_MAX_2G_CHANNEL)
2307 band = wiphy->bands[IEEE80211_BAND_2GHZ];
2308 else
2309 band = wiphy->bands[IEEE80211_BAND_5GHZ];
2310
2311 freq = ieee80211_channel_to_frequency(channel, band->band);
2312 notify_channel = ieee80211_get_channel(wiphy, freq);
2313
2314 notify_capability = le16_to_cpu(bi->capability);
2315 notify_interval = le16_to_cpu(bi->beacon_period);
2316 notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
2317 notify_ielen = le32_to_cpu(bi->ie_length);
2318 notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
2319
2320 WL_CONN("bssid: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
2321 bi->BSSID[0], bi->BSSID[1], bi->BSSID[2],
2322 bi->BSSID[3], bi->BSSID[4], bi->BSSID[5]);
2323 WL_CONN("Channel: %d(%d)\n", channel, freq);
2324 WL_CONN("Capability: %X\n", notify_capability);
2325 WL_CONN("Beacon interval: %d\n", notify_interval);
2326 WL_CONN("Signal: %d\n", notify_signal);
2327
2328 bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID,
2329 0, notify_capability, notify_interval, notify_ie,
2330 notify_ielen, notify_signal, GFP_KERNEL);
2331
2332 if (!bss)
2333 return -ENOMEM;
2334
2335 cfg80211_put_bss(bss);
2336
2337 return err;
2338}
2339
2340static struct brcmf_bss_info_le *
2341next_bss_le(struct brcmf_scan_results *list, struct brcmf_bss_info_le *bss)
2342{
2343 if (bss == NULL)
2344 return list->bss_info_le;
2345 return (struct brcmf_bss_info_le *)((unsigned long)bss +
2346 le32_to_cpu(bss->length));
2347}
2348
2349static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg)
2350{
2351 struct brcmf_scan_results *bss_list;
2352 struct brcmf_bss_info_le *bi = NULL; /* must be initialized */
2353 s32 err = 0;
2354 int i;
2355
2356 bss_list = cfg->bss_list;
2357 if (bss_list->version != BRCMF_BSS_INFO_VERSION) {
2358 WL_ERR("Version %d != WL_BSS_INFO_VERSION\n",
2359 bss_list->version);
2360 return -EOPNOTSUPP;
2361 }
2362 WL_SCAN("scanned AP count (%d)\n", bss_list->count);
2363 for (i = 0; i < bss_list->count && i < WL_AP_MAX; i++) {
2364 bi = next_bss_le(bss_list, bi);
2365 err = brcmf_inform_single_bss(cfg, bi);
2366 if (err)
2367 break;
2368 }
2369 return err;
2370}
2371
2372static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
2373 struct net_device *ndev, const u8 *bssid)
2374{
2375 struct wiphy *wiphy = cfg_to_wiphy(cfg);
2376 struct ieee80211_channel *notify_channel;
2377 struct brcmf_bss_info_le *bi = NULL;
2378 struct ieee80211_supported_band *band;
2379 struct cfg80211_bss *bss;
2380 u8 *buf = NULL;
2381 s32 err = 0;
2382 u16 channel;
2383 u32 freq;
2384 u16 notify_capability;
2385 u16 notify_interval;
2386 u8 *notify_ie;
2387 size_t notify_ielen;
2388 s32 notify_signal;
2389
2390 WL_TRACE("Enter\n");
2391
2392 buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
2393 if (buf == NULL) {
2394 err = -ENOMEM;
2395 goto CleanUp;
2396 }
2397
2398 *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
2399
2400 err = brcmf_fil_cmd_data_get(netdev_priv(ndev), BRCMF_C_GET_BSS_INFO,
2401 buf, WL_BSS_INFO_MAX);
2402 if (err) {
2403 WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err);
2404 goto CleanUp;
2405 }
2406
2407 bi = (struct brcmf_bss_info_le *)(buf + 4);
2408
2409 channel = bi->ctl_ch ? bi->ctl_ch :
2410 CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
2411
2412 if (channel <= CH_MAX_2G_CHANNEL)
2413 band = wiphy->bands[IEEE80211_BAND_2GHZ];
2414 else
2415 band = wiphy->bands[IEEE80211_BAND_5GHZ];
2416
2417 freq = ieee80211_channel_to_frequency(channel, band->band);
2418 notify_channel = ieee80211_get_channel(wiphy, freq);
2419
2420 notify_capability = le16_to_cpu(bi->capability);
2421 notify_interval = le16_to_cpu(bi->beacon_period);
2422 notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
2423 notify_ielen = le32_to_cpu(bi->ie_length);
2424 notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
2425
2426 WL_CONN("channel: %d(%d)\n", channel, freq);
2427 WL_CONN("capability: %X\n", notify_capability);
2428 WL_CONN("beacon interval: %d\n", notify_interval);
2429 WL_CONN("signal: %d\n", notify_signal);
2430
2431 bss = cfg80211_inform_bss(wiphy, notify_channel, bssid,
2432 0, notify_capability, notify_interval,
2433 notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
2434
2435 if (!bss) {
2436 err = -ENOMEM;
2437 goto CleanUp;
2438 }
2439
2440 cfg80211_put_bss(bss);
2441
2442CleanUp:
2443
2444 kfree(buf);
2445
2446 WL_TRACE("Exit\n");
2447
2448 return err;
2449}
2450
2451static bool brcmf_is_ibssmode(struct brcmf_cfg80211_info *cfg)
2452{
2453 return cfg->conf->mode == WL_MODE_IBSS;
2454}
2455
2456/*
2457 * Traverse a string of 1-byte tag/1-byte length/variable-length value
2458 * triples, returning a pointer to the substring whose first element
2459 * matches tag
2460 */
2461static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key)
2462{
2463 struct brcmf_tlv *elt;
2464 int totlen;
2465
2466 elt = (struct brcmf_tlv *) buf;
2467 totlen = buflen;
2468
2469 /* find tagged parameter */
2470 while (totlen >= TLV_HDR_LEN) {
2471 int len = elt->len;
2472
2473 /* validate remaining totlen */
2474 if ((elt->id == key) && (totlen >= (len + TLV_HDR_LEN)))
2475 return elt;
2476
2477 elt = (struct brcmf_tlv *) ((u8 *) elt + (len + TLV_HDR_LEN));
2478 totlen -= (len + TLV_HDR_LEN);
2479 }
2480
2481 return NULL;
2482}
2483
2484/* Is any of the tlvs the expected entry? If
2485 * not update the tlvs buffer pointer/length.
2486 */
2487static bool
2488brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len,
2489 u8 *oui, u32 oui_len, u8 type)
2490{
2491 /* If the contents match the OUI and the type */
2492 if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
2493 !memcmp(&ie[TLV_BODY_OFF], oui, oui_len) &&
2494 type == ie[TLV_BODY_OFF + oui_len]) {
2495 return true;
2496 }
2497
2498 if (tlvs == NULL)
2499 return false;
2500 /* point to the next ie */
2501 ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
2502 /* calculate the length of the rest of the buffer */
2503 *tlvs_len -= (int)(ie - *tlvs);
2504 /* update the pointer to the start of the buffer */
2505 *tlvs = ie;
2506
2507 return false;
2508}
2509
2510static struct brcmf_vs_tlv *
2511brcmf_find_wpaie(u8 *parse, u32 len)
2512{
2513 struct brcmf_tlv *ie;
2514
2515 while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {
2516 if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len,
2517 WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE))
2518 return (struct brcmf_vs_tlv *)ie;
2519 }
2520 return NULL;
2521}
2522
2523static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg)
2524{
2525 struct net_device *ndev = cfg_to_ndev(cfg);
2526 struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
2527 struct brcmf_if *ifp = netdev_priv(ndev);
2528 struct brcmf_bss_info_le *bi;
2529 struct brcmf_ssid *ssid;
2530 struct brcmf_tlv *tim;
2531 u16 beacon_interval;
2532 u8 dtim_period;
2533 size_t ie_len;
2534 u8 *ie;
2535 s32 err = 0;
2536
2537 WL_TRACE("Enter\n");
2538 if (brcmf_is_ibssmode(cfg))
2539 return err;
2540
2541 ssid = &profile->ssid;
2542
2543 *(__le32 *)cfg->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
2544 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
2545 cfg->extra_buf, WL_EXTRA_BUF_MAX);
2546 if (err) {
2547 WL_ERR("Could not get bss info %d\n", err);
2548 goto update_bss_info_out;
2549 }
2550
2551 bi = (struct brcmf_bss_info_le *)(cfg->extra_buf + 4);
2552 err = brcmf_inform_single_bss(cfg, bi);
2553 if (err)
2554 goto update_bss_info_out;
2555
2556 ie = ((u8 *)bi) + le16_to_cpu(bi->ie_offset);
2557 ie_len = le32_to_cpu(bi->ie_length);
2558 beacon_interval = le16_to_cpu(bi->beacon_period);
2559
2560 tim = brcmf_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
2561 if (tim)
2562 dtim_period = tim->data[1];
2563 else {
2564 /*
2565 * active scan was done so we could not get dtim
2566 * information out of probe response.
2567 * so we speficially query dtim information to dongle.
2568 */
2569 u32 var;
2570 err = brcmf_fil_iovar_int_get(ifp, "dtim_assoc", &var);
2571 if (err) {
2572 WL_ERR("wl dtim_assoc failed (%d)\n", err);
2573 goto update_bss_info_out;
2574 }
2575 dtim_period = (u8)var;
2576 }
2577
2578update_bss_info_out:
2579 WL_TRACE("Exit");
2580 return err;
2581}
2582
2583static void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg)
2584{
2585 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg);
2586 struct escan_info *escan = &cfg->escan_info;
2587 struct brcmf_ssid ssid;
2588
2589 set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
2590 if (cfg->iscan_on) {
2591 iscan->state = WL_ISCAN_STATE_IDLE;
2592
2593 if (iscan->timer_on) {
2594 del_timer_sync(&iscan->timer);
2595 iscan->timer_on = 0;
2596 }
2597
2598 cancel_work_sync(&iscan->work);
2599
2600 /* Abort iscan running in FW */
2601 memset(&ssid, 0, sizeof(ssid));
2602 brcmf_run_iscan(iscan, &ssid, WL_SCAN_ACTION_ABORT);
2603
2604 if (cfg->scan_request) {
2605 /* Indidate scan abort to cfg80211 layer */
2606 WL_INFO("Terminating scan in progress\n");
2607 cfg80211_scan_done(cfg->scan_request, true);
2608 cfg->scan_request = NULL;
2609 }
2610 }
2611 if (cfg->escan_on && cfg->scan_request) {
2612 escan->escan_state = WL_ESCAN_STATE_IDLE;
2613 brcmf_notify_escan_complete(cfg, escan->ndev, true, true);
2614 }
2615 clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
2616 clear_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
2617}
2618
2619static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
2620 bool aborted)
2621{
2622 struct brcmf_cfg80211_info *cfg = iscan_to_cfg(iscan);
2623 struct net_device *ndev = cfg_to_ndev(cfg);
2624
2625 if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
2626 WL_ERR("Scan complete while device not scanning\n");
2627 return;
2628 }
2629 if (cfg->scan_request) {
2630 WL_SCAN("ISCAN Completed scan: %s\n",
2631 aborted ? "Aborted" : "Done");
2632 cfg80211_scan_done(cfg->scan_request, aborted);
2633 brcmf_set_mpc(ndev, 1);
2634 cfg->scan_request = NULL;
2635 }
2636 cfg->iscan_kickstart = false;
2637}
2638
2639static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan)
2640{
2641 if (iscan->state != WL_ISCAN_STATE_IDLE) {
2642 WL_SCAN("wake up iscan\n");
2643 schedule_work(&iscan->work);
2644 return 0;
2645 }
2646
2647 return -EIO;
2648}
2649
2650static s32
2651brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status,
2652 struct brcmf_scan_results **bss_list)
2653{
2654 struct brcmf_scan_results *results;
2655 struct brcmf_scan_results_le *results_le;
2656 struct brcmf_iscan_results *list_buf;
2657 s32 err = 0;
2658
2659 memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
2660 list_buf = (struct brcmf_iscan_results *)iscan->scan_buf;
2661 results = &list_buf->results;
2662 results_le = &list_buf->results_le;
2663 results_le->buflen = cpu_to_le32(sizeof(iscan->scan_buf));
2664 results_le->version = 0;
2665 results_le->count = 0;
2666
2667 err = brcmf_fil_iovar_data_get(netdev_priv(iscan->ndev), "iscanresults",
2668 iscan->scan_buf,
2669 sizeof(iscan->scan_buf));
2670 if (err) {
2671 WL_ERR("error (%d)\n", err);
2672 return err;
2673 }
2674 results->buflen = le32_to_cpu(results_le->buflen);
2675 results->version = le32_to_cpu(results_le->version);
2676 results->count = le32_to_cpu(results_le->count);
2677 WL_SCAN("results->count = %d\n", results_le->count);
2678 WL_SCAN("results->buflen = %d\n", results_le->buflen);
2679 *status = le32_to_cpu(list_buf->status_le);
2680 WL_SCAN("status = %d\n", *status);
2681 *bss_list = results;
2682
2683 return err;
2684}
2685
2686static s32 brcmf_iscan_done(struct brcmf_cfg80211_info *cfg)
2687{
2688 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan;
2689 s32 err = 0;
2690
2691 iscan->state = WL_ISCAN_STATE_IDLE;
2692 brcmf_inform_bss(cfg);
2693 brcmf_notify_iscan_complete(iscan, false);
2694
2695 return err;
2696}
2697
2698static s32 brcmf_iscan_pending(struct brcmf_cfg80211_info *cfg)
2699{
2700 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan;
2701 s32 err = 0;
2702
2703 /* Reschedule the timer */
2704 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
2705 iscan->timer_on = 1;
2706
2707 return err;
2708}
2709
2710static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_info *cfg)
2711{
2712 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan;
2713 s32 err = 0;
2714
2715 brcmf_inform_bss(cfg);
2716 brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE);
2717 /* Reschedule the timer */
2718 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
2719 iscan->timer_on = 1;
2720
2721 return err;
2722}
2723
2724static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_info *cfg)
2725{
2726 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan;
2727 s32 err = 0;
2728
2729 iscan->state = WL_ISCAN_STATE_IDLE;
2730 brcmf_notify_iscan_complete(iscan, true);
2731
2732 return err;
2733}
2734
2735static void brcmf_cfg80211_iscan_handler(struct work_struct *work)
2736{
2737 struct brcmf_cfg80211_iscan_ctrl *iscan =
2738 container_of(work, struct brcmf_cfg80211_iscan_ctrl,
2739 work);
2740 struct brcmf_cfg80211_info *cfg = iscan_to_cfg(iscan);
2741 struct brcmf_cfg80211_iscan_eloop *el = &iscan->el;
2742 u32 status = BRCMF_SCAN_RESULTS_PARTIAL;
2743
2744 if (iscan->timer_on) {
2745 del_timer_sync(&iscan->timer);
2746 iscan->timer_on = 0;
2747 }
2748
2749 if (brcmf_get_iscan_results(iscan, &status, &cfg->bss_list)) {
2750 status = BRCMF_SCAN_RESULTS_ABORTED;
2751 WL_ERR("Abort iscan\n");
2752 }
2753
2754 el->handler[status](cfg);
2755}
2756
2757static void brcmf_iscan_timer(unsigned long data)
2758{
2759 struct brcmf_cfg80211_iscan_ctrl *iscan =
2760 (struct brcmf_cfg80211_iscan_ctrl *)data;
2761
2762 if (iscan) {
2763 iscan->timer_on = 0;
2764 WL_SCAN("timer expired\n");
2765 brcmf_wakeup_iscan(iscan);
2766 }
2767}
2768
2769static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_info *cfg)
2770{
2771 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg);
2772
2773 if (cfg->iscan_on) {
2774 iscan->state = WL_ISCAN_STATE_IDLE;
2775 INIT_WORK(&iscan->work, brcmf_cfg80211_iscan_handler);
2776 }
2777
2778 return 0;
2779}
2780
2781static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el)
2782{
2783 memset(el, 0, sizeof(*el));
2784 el->handler[BRCMF_SCAN_RESULTS_SUCCESS] = brcmf_iscan_done;
2785 el->handler[BRCMF_SCAN_RESULTS_PARTIAL] = brcmf_iscan_inprogress;
2786 el->handler[BRCMF_SCAN_RESULTS_PENDING] = brcmf_iscan_pending;
2787 el->handler[BRCMF_SCAN_RESULTS_ABORTED] = brcmf_iscan_aborted;
2788 el->handler[BRCMF_SCAN_RESULTS_NO_MEM] = brcmf_iscan_aborted;
2789}
2790
2791static s32 brcmf_init_iscan(struct brcmf_cfg80211_info *cfg)
2792{
2793 struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg);
2794 int err = 0;
2795
2796 if (cfg->iscan_on) {
2797 iscan->ndev = cfg_to_ndev(cfg);
2798 brcmf_init_iscan_eloop(&iscan->el);
2799 iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
2800 init_timer(&iscan->timer);
2801 iscan->timer.data = (unsigned long) iscan;
2802 iscan->timer.function = brcmf_iscan_timer;
2803 err = brcmf_invoke_iscan(cfg);
2804 if (!err)
2805 iscan->data = cfg;
2806 }
2807
2808 return err;
2809}
2810
2811static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work)
2812{
2813 struct brcmf_cfg80211_info *cfg =
2814 container_of(work, struct brcmf_cfg80211_info,
2815 escan_timeout_work);
2816
2817 brcmf_notify_escan_complete(cfg,
2818 cfg->escan_info.ndev, true, true);
2819}
2820
2821static void brcmf_escan_timeout(unsigned long data)
2822{
2823 struct brcmf_cfg80211_info *cfg =
2824 (struct brcmf_cfg80211_info *)data;
2825
2826 if (cfg->scan_request) {
2827 WL_ERR("timer expired\n");
2828 if (cfg->escan_on)
2829 schedule_work(&cfg->escan_timeout_work);
2830 }
2831}
2832
2833static s32
2834brcmf_compare_update_same_bss(struct brcmf_bss_info_le *bss,
2835 struct brcmf_bss_info_le *bss_info_le)
2836{
2837 if (!memcmp(&bss_info_le->BSSID, &bss->BSSID, ETH_ALEN) &&
2838 (CHSPEC_BAND(le16_to_cpu(bss_info_le->chanspec)) ==
2839 CHSPEC_BAND(le16_to_cpu(bss->chanspec))) &&
2840 bss_info_le->SSID_len == bss->SSID_len &&
2841 !memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) {
2842 if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) ==
2843 (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL)) {
2844 s16 bss_rssi = le16_to_cpu(bss->RSSI);
2845 s16 bss_info_rssi = le16_to_cpu(bss_info_le->RSSI);
2846
2847 /* preserve max RSSI if the measurements are
2848 * both on-channel or both off-channel
2849 */
2850 if (bss_info_rssi > bss_rssi)
2851 bss->RSSI = bss_info_le->RSSI;
2852 } else if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) &&
2853 (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL) == 0) {
2854 /* preserve the on-channel rssi measurement
2855 * if the new measurement is off channel
2856 */
2857 bss->RSSI = bss_info_le->RSSI;
2858 bss->flags |= WLC_BSS_RSSI_ON_CHANNEL;
2859 }
2860 return 1;
2861 }
2862 return 0;
2863}
2864
2865static s32
2866brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg,
2867 struct net_device *ndev,
2868 const struct brcmf_event_msg *e, void *data)
2869{
2870 s32 status;
2871 s32 err = 0;
2872 struct brcmf_escan_result_le *escan_result_le;
2873 struct brcmf_bss_info_le *bss_info_le;
2874 struct brcmf_bss_info_le *bss = NULL;
2875 u32 bi_length;
2876 struct brcmf_scan_results *list;
2877 u32 i;
2878 bool aborted;
2879
2880 status = be32_to_cpu(e->status);
2881
2882 if (!ndev || !cfg->escan_on ||
2883 !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
2884 WL_ERR("scan not ready ndev %p wl->escan_on %d drv_status %x\n",
2885 ndev, cfg->escan_on,
2886 !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status));
2887 return -EPERM;
2888 }
2889
2890 if (status == BRCMF_E_STATUS_PARTIAL) {
2891 WL_SCAN("ESCAN Partial result\n");
2892 escan_result_le = (struct brcmf_escan_result_le *) data;
2893 if (!escan_result_le) {
2894 WL_ERR("Invalid escan result (NULL pointer)\n");
2895 goto exit;
2896 }
2897 if (!cfg->scan_request) {
2898 WL_SCAN("result without cfg80211 request\n");
2899 goto exit;
2900 }
2901
2902 if (le16_to_cpu(escan_result_le->bss_count) != 1) {
2903 WL_ERR("Invalid bss_count %d: ignoring\n",
2904 escan_result_le->bss_count);
2905 goto exit;
2906 }
2907 bss_info_le = &escan_result_le->bss_info_le;
2908
2909 bi_length = le32_to_cpu(bss_info_le->length);
2910 if (bi_length != (le32_to_cpu(escan_result_le->buflen) -
2911 WL_ESCAN_RESULTS_FIXED_SIZE)) {
2912 WL_ERR("Invalid bss_info length %d: ignoring\n",
2913 bi_length);
2914 goto exit;
2915 }
2916
2917 if (!(cfg_to_wiphy(cfg)->interface_modes &
2918 BIT(NL80211_IFTYPE_ADHOC))) {
2919 if (le16_to_cpu(bss_info_le->capability) &
2920 WLAN_CAPABILITY_IBSS) {
2921 WL_ERR("Ignoring IBSS result\n");
2922 goto exit;
2923 }
2924 }
2925
2926 list = (struct brcmf_scan_results *)
2927 cfg->escan_info.escan_buf;
2928 if (bi_length > WL_ESCAN_BUF_SIZE - list->buflen) {
2929 WL_ERR("Buffer is too small: ignoring\n");
2930 goto exit;
2931 }
2932
2933 for (i = 0; i < list->count; i++) {
2934 bss = bss ? (struct brcmf_bss_info_le *)
2935 ((unsigned char *)bss +
2936 le32_to_cpu(bss->length)) : list->bss_info_le;
2937 if (brcmf_compare_update_same_bss(bss, bss_info_le))
2938 goto exit;
2939 }
2940 memcpy(&(cfg->escan_info.escan_buf[list->buflen]),
2941 bss_info_le, bi_length);
2942 list->version = le32_to_cpu(bss_info_le->version);
2943 list->buflen += bi_length;
2944 list->count++;
2945 } else {
2946 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
2947 if (cfg->scan_request) {
2948 cfg->bss_list = (struct brcmf_scan_results *)
2949 cfg->escan_info.escan_buf;
2950 brcmf_inform_bss(cfg);
2951 aborted = status != BRCMF_E_STATUS_SUCCESS;
2952 brcmf_notify_escan_complete(cfg, ndev, aborted,
2953 false);
2954 } else
2955 WL_ERR("Unexpected scan result 0x%x\n", status);
2956 }
2957exit:
2958 return err;
2959}
2960
2961static void brcmf_init_escan(struct brcmf_cfg80211_info *cfg)
2962{
2963
2964 if (cfg->escan_on) {
2965 cfg->el.handler[BRCMF_E_ESCAN_RESULT] =
2966 brcmf_cfg80211_escan_handler;
2967 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
2968 /* Init scan_timeout timer */
2969 init_timer(&cfg->escan_timeout);
2970 cfg->escan_timeout.data = (unsigned long) cfg;
2971 cfg->escan_timeout.function = brcmf_escan_timeout;
2972 INIT_WORK(&cfg->escan_timeout_work,
2973 brcmf_cfg80211_escan_timeout_worker);
2974 }
2975}
2976
2977static __always_inline void brcmf_delay(u32 ms)
2978{
2979 if (ms < 1000 / HZ) {
2980 cond_resched();
2981 mdelay(ms);
2982 } else {
2983 msleep(ms);
2984 }
2985}
2986
2987static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
2988{
2989 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
2990 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
2991
2992 /*
2993 * Check for BRCMF_VIF_STATUS_READY before any function call which
2994 * could result is bus access. Don't block the resume for
2995 * any driver error conditions
2996 */
2997 WL_TRACE("Enter\n");
2998
2999 if (check_vif_up(ifp->vif))
3000 brcmf_invoke_iscan(wiphy_to_cfg(wiphy));
3001
3002 WL_TRACE("Exit\n");
3003 return 0;
3004}
3005
3006static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
3007 struct cfg80211_wowlan *wow)
3008{
3009 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
3010 struct net_device *ndev = cfg_to_ndev(cfg);
3011 struct brcmf_if *ifp = netdev_priv(ndev);
3012
3013 WL_TRACE("Enter\n");
3014
3015 /*
3016 * Check for BRCMF_VIF_STATUS_READY before any function call which
3017 * could result is bus access. Don't block the suspend for
3018 * any driver error conditions
3019 */
3020
3021 /*
3022 * While going to suspend if associated with AP disassociate
3023 * from AP to save power while system is in suspended state
3024 */
3025 if ((test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state) ||
3026 test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) &&
3027 check_vif_up(ifp->vif)) {
3028 WL_INFO("Disassociating from AP"
3029 " while entering suspend state\n");
3030 brcmf_link_down(cfg);
3031
3032 /*
3033 * Make sure WPA_Supplicant receives all the event
3034 * generated due to DISASSOC call to the fw to keep
3035 * the state fw and WPA_Supplicant state consistent
3036 */
3037 brcmf_delay(500);
3038 }
3039
3040 if (test_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state))
3041 brcmf_abort_scanning(cfg);
3042 else
3043 clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
3044
3045 /* Turn off watchdog timer */
3046 if (test_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state))
3047 brcmf_set_mpc(ndev, 1);
3048
3049 WL_TRACE("Exit\n");
3050
3051 return 0;
3052}
3053
3054static __used s32
3055brcmf_update_pmklist(struct net_device *ndev,
3056 struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
3057{
3058 int i, j;
3059 int pmkid_len;
3060
3061 pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid);
3062
3063 WL_CONN("No of elements %d\n", pmkid_len);
3064 for (i = 0; i < pmkid_len; i++) {
3065 WL_CONN("PMKID[%d]: %pM =\n", i,
3066 &pmk_list->pmkids.pmkid[i].BSSID);
3067 for (j = 0; j < WLAN_PMKID_LEN; j++)
3068 WL_CONN("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]);
3069 }
3070
3071 if (!err)
3072 brcmf_fil_iovar_data_set(netdev_priv(ndev), "pmkid_info",
3073 (char *)pmk_list, sizeof(*pmk_list));
3074
3075 return err;
3076}
3077
3078static s32
3079brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
3080 struct cfg80211_pmksa *pmksa)
3081{
3082 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
3083 struct brcmf_if *ifp = netdev_priv(ndev);
3084 struct pmkid_list *pmkids = &cfg->pmk_list->pmkids;
3085 s32 err = 0;
3086 int i;
3087 int pmkid_len;
3088
3089 WL_TRACE("Enter\n");
3090 if (!check_vif_up(ifp->vif))
3091 return -EIO;
3092
3093 pmkid_len = le32_to_cpu(pmkids->npmkid);
3094 for (i = 0; i < pmkid_len; i++)
3095 if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN))
3096 break;
3097 if (i < WL_NUM_PMKIDS_MAX) {
3098 memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN);
3099 memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
3100 if (i == pmkid_len) {
3101 pmkid_len++;
3102 pmkids->npmkid = cpu_to_le32(pmkid_len);
3103 }
3104 } else
3105 err = -EINVAL;
3106
3107 WL_CONN("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
3108 pmkids->pmkid[pmkid_len].BSSID);
3109 for (i = 0; i < WLAN_PMKID_LEN; i++)
3110 WL_CONN("%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]);
3111
3112 err = brcmf_update_pmklist(ndev, cfg->pmk_list, err);
3113
3114 WL_TRACE("Exit\n");
3115 return err;
3116}
3117
3118static s32
3119brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
3120 struct cfg80211_pmksa *pmksa)
3121{
3122 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
3123 struct brcmf_if *ifp = netdev_priv(ndev);
3124 struct pmkid_list pmkid;
3125 s32 err = 0;
3126 int i, pmkid_len;
3127
3128 WL_TRACE("Enter\n");
3129 if (!check_vif_up(ifp->vif))
3130 return -EIO;
3131
3132 memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
3133 memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
3134
3135 WL_CONN("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
3136 &pmkid.pmkid[0].BSSID);
3137 for (i = 0; i < WLAN_PMKID_LEN; i++)
3138 WL_CONN("%02x\n", pmkid.pmkid[0].PMKID[i]);
3139
3140 pmkid_len = le32_to_cpu(cfg->pmk_list->pmkids.npmkid);
3141 for (i = 0; i < pmkid_len; i++)
3142 if (!memcmp
3143 (pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
3144 ETH_ALEN))
3145 break;
3146
3147 if ((pmkid_len > 0)
3148 && (i < pmkid_len)) {
3149 memset(&cfg->pmk_list->pmkids.pmkid[i], 0,
3150 sizeof(struct pmkid));
3151 for (; i < (pmkid_len - 1); i++) {
3152 memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID,
3153 &cfg->pmk_list->pmkids.pmkid[i + 1].BSSID,
3154 ETH_ALEN);
3155 memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID,
3156 &cfg->pmk_list->pmkids.pmkid[i + 1].PMKID,
3157 WLAN_PMKID_LEN);
3158 }
3159 cfg->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1);
3160 } else
3161 err = -EINVAL;
3162
3163 err = brcmf_update_pmklist(ndev, cfg->pmk_list, err);
3164
3165 WL_TRACE("Exit\n");
3166 return err;
3167
3168}
3169
3170static s32
3171brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
3172{
3173 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
3174 struct brcmf_if *ifp = netdev_priv(ndev);
3175 s32 err = 0;
3176
3177 WL_TRACE("Enter\n");
3178 if (!check_vif_up(ifp->vif))
3179 return -EIO;
3180
3181 memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list));
3182 err = brcmf_update_pmklist(ndev, cfg->pmk_list, err);
3183
3184 WL_TRACE("Exit\n");
3185 return err;
3186
3187}
3188
3189/*
3190 * PFN result doesn't have all the info which are
3191 * required by the supplicant
3192 * (For e.g IEs) Do a target Escan so that sched scan results are reported
3193 * via wl_inform_single_bss in the required format. Escan does require the
3194 * scan request in the form of cfg80211_scan_request. For timebeing, create
3195 * cfg80211_scan_request one out of the received PNO event.
3196 */
3197static s32
3198brcmf_notify_sched_scan_results(struct brcmf_cfg80211_info *cfg,
3199 struct net_device *ndev,
3200 const struct brcmf_event_msg *e, void *data)
3201{
3202 struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
3203 struct cfg80211_scan_request *request = NULL;
3204 struct cfg80211_ssid *ssid = NULL;
3205 struct ieee80211_channel *channel = NULL;
3206 struct wiphy *wiphy = cfg_to_wiphy(cfg);
3207 int err = 0;
3208 int channel_req = 0;
3209 int band = 0;
3210 struct brcmf_pno_scanresults_le *pfn_result;
3211 u32 result_count;
3212 u32 status;
3213
3214 WL_SCAN("Enter\n");
3215
3216 if (e->event_type == cpu_to_be32(BRCMF_E_PFN_NET_LOST)) {
3217 WL_SCAN("PFN NET LOST event. Do Nothing\n");
3218 return 0;
3219 }
3220
3221 pfn_result = (struct brcmf_pno_scanresults_le *)data;
3222 result_count = le32_to_cpu(pfn_result->count);
3223 status = le32_to_cpu(pfn_result->status);
3224
3225 /*
3226 * PFN event is limited to fit 512 bytes so we may get
3227 * multiple NET_FOUND events. For now place a warning here.
3228 */
3229 WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE);
3230 WL_SCAN("PFN NET FOUND event. count: %d\n", result_count);
3231 if (result_count > 0) {
3232 int i;
3233
3234 request = kzalloc(sizeof(*request), GFP_KERNEL);
3235 ssid = kcalloc(result_count, sizeof(*ssid), GFP_KERNEL);
3236 channel = kcalloc(result_count, sizeof(*channel), GFP_KERNEL);
3237 if (!request || !ssid || !channel) {
3238 err = -ENOMEM;
3239 goto out_err;
3240 }
3241
3242 request->wiphy = wiphy;
3243 data += sizeof(struct brcmf_pno_scanresults_le);
3244 netinfo_start = (struct brcmf_pno_net_info_le *)data;
3245
3246 for (i = 0; i < result_count; i++) {
3247 netinfo = &netinfo_start[i];
3248 if (!netinfo) {
3249 WL_ERR("Invalid netinfo ptr. index: %d\n", i);
3250 err = -EINVAL;
3251 goto out_err;
3252 }
3253
3254 WL_SCAN("SSID:%s Channel:%d\n",
3255 netinfo->SSID, netinfo->channel);
3256 memcpy(ssid[i].ssid, netinfo->SSID, netinfo->SSID_len);
3257 ssid[i].ssid_len = netinfo->SSID_len;
3258 request->n_ssids++;
3259
3260 channel_req = netinfo->channel;
3261 if (channel_req <= CH_MAX_2G_CHANNEL)
3262 band = NL80211_BAND_2GHZ;
3263 else
3264 band = NL80211_BAND_5GHZ;
3265 channel[i].center_freq =
3266 ieee80211_channel_to_frequency(channel_req,
3267 band);
3268 channel[i].band = band;
3269 channel[i].flags |= IEEE80211_CHAN_NO_HT40;
3270 request->channels[i] = &channel[i];
3271 request->n_channels++;
3272 }
3273
3274 /* assign parsed ssid array */
3275 if (request->n_ssids)
3276 request->ssids = &ssid[0];
3277
3278 if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
3279 /* Abort any on-going scan */
3280 brcmf_abort_scanning(cfg);
3281 }
3282
3283 set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
3284 err = brcmf_do_escan(cfg, wiphy, ndev, request);
3285 if (err) {
3286 clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
3287 goto out_err;
3288 }
3289 cfg->sched_escan = true;
3290 cfg->scan_request = request;
3291 } else {
3292 WL_ERR("FALSE PNO Event. (pfn_count == 0)\n");
3293 goto out_err;
3294 }
3295
3296 kfree(ssid);
3297 kfree(channel);
3298 kfree(request);
3299 return 0;
3300
3301out_err:
3302 kfree(ssid);
3303 kfree(channel);
3304 kfree(request);
3305 cfg80211_sched_scan_stopped(wiphy);
3306 return err;
3307}
3308
3309#ifndef CONFIG_BRCMISCAN
3310static int brcmf_dev_pno_clean(struct net_device *ndev)
3311{
3312 int ret;
3313
3314 /* Disable pfn */
3315 ret = brcmf_fil_iovar_int_set(netdev_priv(ndev), "pfn", 0);
3316 if (ret == 0) {
3317 /* clear pfn */
3318 ret = brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfnclear",
3319 NULL, 0);
3320 }
3321 if (ret < 0)
3322 WL_ERR("failed code %d\n", ret);
3323
3324 return ret;
3325}
3326
3327static int brcmf_dev_pno_config(struct net_device *ndev)
3328{
3329 struct brcmf_pno_param_le pfn_param;
3330
3331 memset(&pfn_param, 0, sizeof(pfn_param));
3332 pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION);
3333
3334 /* set extra pno params */
3335 pfn_param.flags = cpu_to_le16(1 << BRCMF_PNO_ENABLE_ADAPTSCAN_BIT);
3336 pfn_param.repeat = BRCMF_PNO_REPEAT;
3337 pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX;
3338
3339 /* set up pno scan fr */
3340 pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME);
3341
3342 return brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfn_set",
3343 &pfn_param, sizeof(pfn_param));
3344}
3345
3346static int
3347brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
3348 struct net_device *ndev,
3349 struct cfg80211_sched_scan_request *request)
3350{
3351 struct brcmf_if *ifp = netdev_priv(ndev);
3352 struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
3353 struct brcmf_pno_net_param_le pfn;
3354 int i;
3355 int ret = 0;
3356
3357 WL_SCAN("Enter n_match_sets:%d n_ssids:%d\n",
3358 request->n_match_sets, request->n_ssids);
3359 if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
3360 WL_ERR("Scanning already: status (%lu)\n", cfg->scan_status);
3361 return -EAGAIN;
3362 }
3363
3364 if (!request || !request->n_ssids || !request->n_match_sets) {
3365 WL_ERR("Invalid sched scan req!! n_ssids:%d\n",
3366 request->n_ssids);
3367 return -EINVAL;
3368 }
3369
3370 if (request->n_ssids > 0) {
3371 for (i = 0; i < request->n_ssids; i++) {
3372 /* Active scan req for ssids */
3373 WL_SCAN(">>> Active scan req for ssid (%s)\n",
3374 request->ssids[i].ssid);
3375
3376 /*
3377 * match_set ssids is a supert set of n_ssid list,
3378 * so we need not add these set seperately.
3379 */
3380 }
3381 }
3382
3383 if (request->n_match_sets > 0) {
3384 /* clean up everything */
3385 ret = brcmf_dev_pno_clean(ndev);
3386 if (ret < 0) {
3387 WL_ERR("failed error=%d\n", ret);
3388 return ret;
3389 }
3390
3391 /* configure pno */
3392 ret = brcmf_dev_pno_config(ndev);
3393 if (ret < 0) {
3394 WL_ERR("PNO setup failed!! ret=%d\n", ret);
3395 return -EINVAL;
3396 }
3397
3398 /* configure each match set */
3399 for (i = 0; i < request->n_match_sets; i++) {
3400 struct cfg80211_ssid *ssid;
3401 u32 ssid_len;
3402
3403 ssid = &request->match_sets[i].ssid;
3404 ssid_len = ssid->ssid_len;
3405
3406 if (!ssid_len) {
3407 WL_ERR("skip broadcast ssid\n");
3408 continue;
3409 }
3410 pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN);
3411 pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY);
3412 pfn.wsec = cpu_to_le32(0);
3413 pfn.infra = cpu_to_le32(1);
3414 pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
3415 pfn.ssid.SSID_len = cpu_to_le32(ssid_len);
3416 memcpy(pfn.ssid.SSID, ssid->ssid, ssid_len);
3417 ret = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn,
3418 sizeof(pfn));
3419 WL_SCAN(">>> PNO filter %s for ssid (%s)\n",
3420 ret == 0 ? "set" : "failed",
3421 ssid->ssid);
3422 }
3423 /* Enable the PNO */
3424 if (brcmf_fil_iovar_int_set(ifp, "pfn", 1) < 0) {
3425 WL_ERR("PNO enable failed!! ret=%d\n", ret);
3426 return -EINVAL;
3427 }
3428 } else {
3429 return -EINVAL;
3430 }
3431
3432 return 0;
3433}
3434
3435static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
3436 struct net_device *ndev)
3437{
3438 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
3439
3440 WL_SCAN("enter\n");
3441 brcmf_dev_pno_clean(ndev);
3442 if (cfg->sched_escan)
3443 brcmf_notify_escan_complete(cfg, ndev, true, true);
3444 return 0;
3445}
3446#endif /* CONFIG_BRCMISCAN */
3447
3448#ifdef CONFIG_NL80211_TESTMODE
3449static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
3450{
3451 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
3452 struct net_device *ndev = cfg_to_ndev(cfg);
3453 struct brcmf_dcmd *dcmd = data;
3454 struct sk_buff *reply;
3455 int ret;
3456
3457 WL_TRACE("cmd %x set %d buf %p len %d\n", dcmd->cmd, dcmd->set,
3458 dcmd->buf, dcmd->len);
3459
3460 if (dcmd->set)
3461 ret = brcmf_fil_cmd_data_set(netdev_priv(ndev), dcmd->cmd,
3462 dcmd->buf, dcmd->len);
3463 else
3464 ret = brcmf_fil_cmd_data_get(netdev_priv(ndev), dcmd->cmd,
3465 dcmd->buf, dcmd->len);
3466 if (ret == 0) {
3467 reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*dcmd));
3468 nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*dcmd), dcmd);
3469 ret = cfg80211_testmode_reply(reply);
3470 }
3471 return ret;
3472}
3473#endif
3474
3475static s32 brcmf_configure_opensecurity(struct net_device *ndev, s32 bssidx)
3476{
3477 struct brcmf_if *ifp = netdev_priv(ndev);
3478 s32 err;
3479
3480 /* set auth */
3481 err = brcmf_fil_bsscfg_int_set(ifp, "auth", 0);
3482 if (err < 0) {
3483 WL_ERR("auth error %d\n", err);
3484 return err;
3485 }
3486 /* set wsec */
3487 err = brcmf_fil_bsscfg_int_set(ifp, "wsec", 0);
3488 if (err < 0) {
3489 WL_ERR("wsec error %d\n", err);
3490 return err;
3491 }
3492 /* set upper-layer auth */
3493 err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", WPA_AUTH_NONE);
3494 if (err < 0) {
3495 WL_ERR("wpa_auth error %d\n", err);
3496 return err;
3497 }
3498
3499 return 0;
3500}
3501
3502static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie)
3503{
3504 if (is_rsn_ie)
3505 return (memcmp(oui, RSN_OUI, TLV_OUI_LEN) == 0);
3506
3507 return (memcmp(oui, WPA_OUI, TLV_OUI_LEN) == 0);
3508}
3509
3510static s32
3511brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
3512 bool is_rsn_ie, s32 bssidx)
3513{
3514 struct brcmf_if *ifp = netdev_priv(ndev);
3515 u32 auth = 0; /* d11 open authentication */
3516 u16 count;
3517 s32 err = 0;
3518 s32 len = 0;
3519 u32 i;
3520 u32 wsec;
3521 u32 pval = 0;
3522 u32 gval = 0;
3523 u32 wpa_auth = 0;
3524 u32 offset;
3525 u8 *data;
3526 u16 rsn_cap;
3527 u32 wme_bss_disable;
3528
3529 WL_TRACE("Enter\n");
3530 if (wpa_ie == NULL)
3531 goto exit;
3532
3533 len = wpa_ie->len + TLV_HDR_LEN;
3534 data = (u8 *)wpa_ie;
3535 offset = 0;
3536 if (!is_rsn_ie)
3537 offset += VS_IE_FIXED_HDR_LEN;
3538 offset += WPA_IE_VERSION_LEN;
3539
3540 /* check for multicast cipher suite */
3541 if (offset + WPA_IE_MIN_OUI_LEN > len) {
3542 err = -EINVAL;
3543 WL_ERR("no multicast cipher suite\n");
3544 goto exit;
3545 }
3546
3547 if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
3548 err = -EINVAL;
3549 WL_ERR("ivalid OUI\n");
3550 goto exit;
3551 }
3552 offset += TLV_OUI_LEN;
3553
3554 /* pick up multicast cipher */
3555 switch (data[offset]) {
3556 case WPA_CIPHER_NONE:
3557 gval = 0;
3558 break;
3559 case WPA_CIPHER_WEP_40:
3560 case WPA_CIPHER_WEP_104:
3561 gval = WEP_ENABLED;
3562 break;
3563 case WPA_CIPHER_TKIP:
3564 gval = TKIP_ENABLED;
3565 break;
3566 case WPA_CIPHER_AES_CCM:
3567 gval = AES_ENABLED;
3568 break;
3569 default:
3570 err = -EINVAL;
3571 WL_ERR("Invalid multi cast cipher info\n");
3572 goto exit;
3573 }
3574
3575 offset++;
3576 /* walk thru unicast cipher list and pick up what we recognize */
3577 count = data[offset] + (data[offset + 1] << 8);
3578 offset += WPA_IE_SUITE_COUNT_LEN;
3579 /* Check for unicast suite(s) */
3580 if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) {
3581 err = -EINVAL;
3582 WL_ERR("no unicast cipher suite\n");
3583 goto exit;
3584 }
3585 for (i = 0; i < count; i++) {
3586 if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
3587 err = -EINVAL;
3588 WL_ERR("ivalid OUI\n");
3589 goto exit;
3590 }
3591 offset += TLV_OUI_LEN;
3592 switch (data[offset]) {
3593 case WPA_CIPHER_NONE:
3594 break;
3595 case WPA_CIPHER_WEP_40:
3596 case WPA_CIPHER_WEP_104:
3597 pval |= WEP_ENABLED;
3598 break;
3599 case WPA_CIPHER_TKIP:
3600 pval |= TKIP_ENABLED;
3601 break;
3602 case WPA_CIPHER_AES_CCM:
3603 pval |= AES_ENABLED;
3604 break;
3605 default:
3606 WL_ERR("Ivalid unicast security info\n");
3607 }
3608 offset++;
3609 }
3610 /* walk thru auth management suite list and pick up what we recognize */
3611 count = data[offset] + (data[offset + 1] << 8);
3612 offset += WPA_IE_SUITE_COUNT_LEN;
3613 /* Check for auth key management suite(s) */
3614 if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) {
3615 err = -EINVAL;
3616 WL_ERR("no auth key mgmt suite\n");
3617 goto exit;
3618 }
3619 for (i = 0; i < count; i++) {
3620 if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
3621 err = -EINVAL;
3622 WL_ERR("ivalid OUI\n");
3623 goto exit;
3624 }
3625 offset += TLV_OUI_LEN;
3626 switch (data[offset]) {
3627 case RSN_AKM_NONE:
3628 WL_TRACE("RSN_AKM_NONE\n");
3629 wpa_auth |= WPA_AUTH_NONE;
3630 break;
3631 case RSN_AKM_UNSPECIFIED:
3632 WL_TRACE("RSN_AKM_UNSPECIFIED\n");
3633 is_rsn_ie ? (wpa_auth |= WPA2_AUTH_UNSPECIFIED) :
3634 (wpa_auth |= WPA_AUTH_UNSPECIFIED);
3635 break;
3636 case RSN_AKM_PSK:
3637 WL_TRACE("RSN_AKM_PSK\n");
3638 is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) :
3639 (wpa_auth |= WPA_AUTH_PSK);
3640 break;
3641 default:
3642 WL_ERR("Ivalid key mgmt info\n");
3643 }
3644 offset++;
3645 }
3646
3647 if (is_rsn_ie) {
3648 wme_bss_disable = 1;
3649 if ((offset + RSN_CAP_LEN) <= len) {
3650 rsn_cap = data[offset] + (data[offset + 1] << 8);
3651 if (rsn_cap & RSN_CAP_PTK_REPLAY_CNTR_MASK)
3652 wme_bss_disable = 0;
3653 }
3654 /* set wme_bss_disable to sync RSN Capabilities */
3655 err = brcmf_fil_bsscfg_int_set(ifp, "wme_bss_disable",
3656 wme_bss_disable);
3657 if (err < 0) {
3658 WL_ERR("wme_bss_disable error %d\n", err);
3659 goto exit;
3660 }
3661 }
3662 /* FOR WPS , set SES_OW_ENABLED */
3663 wsec = (pval | gval | SES_OW_ENABLED);
3664
3665 /* set auth */
3666 err = brcmf_fil_bsscfg_int_set(ifp, "auth", auth);
3667 if (err < 0) {
3668 WL_ERR("auth error %d\n", err);
3669 goto exit;
3670 }
3671 /* set wsec */
3672 err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
3673 if (err < 0) {
3674 WL_ERR("wsec error %d\n", err);
3675 goto exit;
3676 }
3677 /* set upper-layer auth */
3678 err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_auth);
3679 if (err < 0) {
3680 WL_ERR("wpa_auth error %d\n", err);
3681 goto exit;
3682 }
3683
3684exit:
3685 return err;
3686}
3687
3688static s32
3689brcmf_parse_vndr_ies(u8 *vndr_ie_buf, u32 vndr_ie_len,
3690 struct parsed_vndr_ies *vndr_ies)
3691{
3692 s32 err = 0;
3693 struct brcmf_vs_tlv *vndrie;
3694 struct brcmf_tlv *ie;
3695 struct parsed_vndr_ie_info *parsed_info;
3696 s32 remaining_len;
3697
3698 remaining_len = (s32)vndr_ie_len;
3699 memset(vndr_ies, 0, sizeof(*vndr_ies));
3700
3701 ie = (struct brcmf_tlv *)vndr_ie_buf;
3702 while (ie) {
3703 if (ie->id != WLAN_EID_VENDOR_SPECIFIC)
3704 goto next;
3705 vndrie = (struct brcmf_vs_tlv *)ie;
3706 /* len should be bigger than OUI length + one */
3707 if (vndrie->len < (VS_IE_FIXED_HDR_LEN - TLV_HDR_LEN + 1)) {
3708 WL_ERR("invalid vndr ie. length is too small %d\n",
3709 vndrie->len);
3710 goto next;
3711 }
3712 /* if wpa or wme ie, do not add ie */
3713 if (!memcmp(vndrie->oui, (u8 *)WPA_OUI, TLV_OUI_LEN) &&
3714 ((vndrie->oui_type == WPA_OUI_TYPE) ||
3715 (vndrie->oui_type == WME_OUI_TYPE))) {
3716 WL_TRACE("Found WPA/WME oui. Do not add it\n");
3717 goto next;
3718 }
3719
3720 parsed_info = &vndr_ies->ie_info[vndr_ies->count];
3721
3722 /* save vndr ie information */
3723 parsed_info->ie_ptr = (char *)vndrie;
3724 parsed_info->ie_len = vndrie->len + TLV_HDR_LEN;
3725 memcpy(&parsed_info->vndrie, vndrie, sizeof(*vndrie));
3726
3727 vndr_ies->count++;
3728
3729 WL_TRACE("** OUI %02x %02x %02x, type 0x%02x\n",
3730 parsed_info->vndrie.oui[0],
3731 parsed_info->vndrie.oui[1],
3732 parsed_info->vndrie.oui[2],
3733 parsed_info->vndrie.oui_type);
3734
3735 if (vndr_ies->count >= MAX_VNDR_IE_NUMBER)
3736 break;
3737next:
3738 remaining_len -= ie->len;
3739 if (remaining_len <= 2)
3740 ie = NULL;
3741 else
3742 ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len);
3743 }
3744 return err;
3745}
3746
3747static u32
3748brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd)
3749{
3750
3751 __le32 iecount_le;
3752 __le32 pktflag_le;
3753
3754 strncpy(iebuf, add_del_cmd, VNDR_IE_CMD_LEN - 1);
3755 iebuf[VNDR_IE_CMD_LEN - 1] = '\0';
3756
3757 iecount_le = cpu_to_le32(1);
3758 memcpy(&iebuf[VNDR_IE_COUNT_OFFSET], &iecount_le, sizeof(iecount_le));
3759
3760 pktflag_le = cpu_to_le32(pktflag);
3761 memcpy(&iebuf[VNDR_IE_PKTFLAG_OFFSET], &pktflag_le, sizeof(pktflag_le));
3762
3763 memcpy(&iebuf[VNDR_IE_VSIE_OFFSET], ie_ptr, ie_len);
3764
3765 return ie_len + VNDR_IE_HDR_SIZE;
3766}
3767
3768static s32
3769brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
3770 struct net_device *ndev, s32 pktflag,
3771 u8 *vndr_ie_buf, u32 vndr_ie_len)
3772{
3773 struct brcmf_if *ifp = netdev_priv(ndev);
3774 s32 err = 0;
3775 u8 *iovar_ie_buf;
3776 u8 *curr_ie_buf;
3777 u8 *mgmt_ie_buf = NULL;
3778 int mgmt_ie_buf_len;
3779 u32 *mgmt_ie_len;
3780 u32 del_add_ie_buf_len = 0;
3781 u32 total_ie_buf_len = 0;
3782 u32 parsed_ie_buf_len = 0;
3783 struct parsed_vndr_ies old_vndr_ies;
3784 struct parsed_vndr_ies new_vndr_ies;
3785 struct parsed_vndr_ie_info *vndrie_info;
3786 s32 i;
3787 u8 *ptr;
3788 int remained_buf_len;
3789
3790 WL_TRACE("bssidx %d, pktflag : 0x%02X\n",
3791 brcmf_ndev_bssidx(ndev), pktflag);
3792 iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
3793 if (!iovar_ie_buf)
3794 return -ENOMEM;
3795 curr_ie_buf = iovar_ie_buf;
3796 if (test_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state) ||
3797 test_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state)) {
3798 switch (pktflag) {
3799 case VNDR_IE_PRBRSP_FLAG:
3800 mgmt_ie_buf = cfg->ap_info->probe_res_ie;
3801 mgmt_ie_len = &cfg->ap_info->probe_res_ie_len;
3802 mgmt_ie_buf_len = sizeof(cfg->ap_info->probe_res_ie);
3803 break;
3804 case VNDR_IE_BEACON_FLAG:
3805 mgmt_ie_buf = cfg->ap_info->beacon_ie;
3806 mgmt_ie_len = &cfg->ap_info->beacon_ie_len;
3807 mgmt_ie_buf_len = sizeof(cfg->ap_info->beacon_ie);
3808 break;
3809 default:
3810 err = -EPERM;
3811 WL_ERR("not suitable type\n");
3812 goto exit;
3813 }
3814 } else {
3815 err = -EPERM;
3816 WL_ERR("not suitable type\n");
3817 goto exit;
3818 }
3819
3820 if (vndr_ie_len > mgmt_ie_buf_len) {
3821 err = -ENOMEM;
3822 WL_ERR("extra IE size too big\n");
3823 goto exit;
3824 }
3825
3826 /* parse and save new vndr_ie in curr_ie_buff before comparing it */
3827 if (vndr_ie_buf && vndr_ie_len && curr_ie_buf) {
3828 ptr = curr_ie_buf;
3829 brcmf_parse_vndr_ies(vndr_ie_buf, vndr_ie_len, &new_vndr_ies);
3830 for (i = 0; i < new_vndr_ies.count; i++) {
3831 vndrie_info = &new_vndr_ies.ie_info[i];
3832 memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr,
3833 vndrie_info->ie_len);
3834 parsed_ie_buf_len += vndrie_info->ie_len;
3835 }
3836 }
3837
3838 if (mgmt_ie_buf != NULL) {
3839 if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) &&
3840 (memcmp(mgmt_ie_buf, curr_ie_buf,
3841 parsed_ie_buf_len) == 0)) {
3842 WL_TRACE("Previous mgmt IE is equals to current IE");
3843 goto exit;
3844 }
3845
3846 /* parse old vndr_ie */
3847 brcmf_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len, &old_vndr_ies);
3848
3849 /* make a command to delete old ie */
3850 for (i = 0; i < old_vndr_ies.count; i++) {
3851 vndrie_info = &old_vndr_ies.ie_info[i];
3852
3853 WL_TRACE("DEL ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
3854 vndrie_info->vndrie.id,
3855 vndrie_info->vndrie.len,
3856 vndrie_info->vndrie.oui[0],
3857 vndrie_info->vndrie.oui[1],
3858 vndrie_info->vndrie.oui[2]);
3859
3860 del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag,
3861 vndrie_info->ie_ptr,
3862 vndrie_info->ie_len,
3863 "del");
3864 curr_ie_buf += del_add_ie_buf_len;
3865 total_ie_buf_len += del_add_ie_buf_len;
3866 }
3867 }
3868
3869 *mgmt_ie_len = 0;
3870 /* Add if there is any extra IE */
3871 if (mgmt_ie_buf && parsed_ie_buf_len) {
3872 ptr = mgmt_ie_buf;
3873
3874 remained_buf_len = mgmt_ie_buf_len;
3875
3876 /* make a command to add new ie */
3877 for (i = 0; i < new_vndr_ies.count; i++) {
3878 vndrie_info = &new_vndr_ies.ie_info[i];
3879
3880 WL_TRACE("ADDED ID : %d, Len: %d, OUI:%02x:%02x:%02x\n",
3881 vndrie_info->vndrie.id,
3882 vndrie_info->vndrie.len,
3883 vndrie_info->vndrie.oui[0],
3884 vndrie_info->vndrie.oui[1],
3885 vndrie_info->vndrie.oui[2]);
3886
3887 del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag,
3888 vndrie_info->ie_ptr,
3889 vndrie_info->ie_len,
3890 "add");
3891 /* verify remained buf size before copy data */
3892 remained_buf_len -= vndrie_info->ie_len;
3893 if (remained_buf_len < 0) {
3894 WL_ERR("no space in mgmt_ie_buf: len left %d",
3895 remained_buf_len);
3896 break;
3897 }
3898
3899 /* save the parsed IE in wl struct */
3900 memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr,
3901 vndrie_info->ie_len);
3902 *mgmt_ie_len += vndrie_info->ie_len;
3903
3904 curr_ie_buf += del_add_ie_buf_len;
3905 total_ie_buf_len += del_add_ie_buf_len;
3906 }
3907 }
3908 if (total_ie_buf_len) {
3909 err = brcmf_fil_bsscfg_data_set(ifp, "vndr_ie", iovar_ie_buf,
3910 total_ie_buf_len);
3911 if (err)
3912 WL_ERR("vndr ie set error : %d\n", err);
3913 }
3914
3915exit:
3916 kfree(iovar_ie_buf);
3917 return err;
3918}
3919
3920static s32
3921brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
3922 struct cfg80211_ap_settings *settings)
3923{
3924 s32 ie_offset;
3925 struct brcmf_if *ifp = netdev_priv(ndev);
3926 struct brcmf_tlv *ssid_ie;
3927 struct brcmf_ssid_le ssid_le;
3928 s32 err = -EPERM;
3929 struct brcmf_tlv *rsn_ie;
3930 struct brcmf_vs_tlv *wpa_ie;
3931 struct brcmf_join_params join_params;
3932 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
3933 s32 bssidx = 0;
3934
3935 WL_TRACE("channel_type=%d, beacon_interval=%d, dtim_period=%d,\n",
3936 settings->channel_type, settings->beacon_interval,
3937 settings->dtim_period);
3938 WL_TRACE("ssid=%s(%d), auth_type=%d, inactivity_timeout=%d\n",
3939 settings->ssid, settings->ssid_len, settings->auth_type,
3940 settings->inactivity_timeout);
3941
3942 if (!test_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state)) {
3943 WL_ERR("Not in AP creation mode\n");
3944 return -EPERM;
3945 }
3946
3947 memset(&ssid_le, 0, sizeof(ssid_le));
3948 if (settings->ssid == NULL || settings->ssid_len == 0) {
3949 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
3950 ssid_ie = brcmf_parse_tlvs(
3951 (u8 *)&settings->beacon.head[ie_offset],
3952 settings->beacon.head_len - ie_offset,
3953 WLAN_EID_SSID);
3954 if (!ssid_ie)
3955 return -EINVAL;
3956
3957 memcpy(ssid_le.SSID, ssid_ie->data, ssid_ie->len);
3958 ssid_le.SSID_len = cpu_to_le32(ssid_ie->len);
3959 WL_TRACE("SSID is (%s) in Head\n", ssid_le.SSID);
3960 } else {
3961 memcpy(ssid_le.SSID, settings->ssid, settings->ssid_len);
3962 ssid_le.SSID_len = cpu_to_le32((u32)settings->ssid_len);
3963 }
3964
3965 brcmf_set_mpc(ndev, 0);
3966 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
3967 if (err < 0) {
3968 WL_ERR("BRCMF_C_DOWN error %d\n", err);
3969 goto exit;
3970 }
3971 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1);
3972 if (err < 0) {
3973 WL_ERR("SET INFRA error %d\n", err);
3974 goto exit;
3975 }
3976 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1);
3977 if (err < 0) {
3978 WL_ERR("setting AP mode failed %d\n", err);
3979 goto exit;
3980 }
3981
3982 /* find the RSN_IE */
3983 rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
3984 settings->beacon.tail_len, WLAN_EID_RSN);
3985
3986 /* find the WPA_IE */
3987 wpa_ie = brcmf_find_wpaie((u8 *)settings->beacon.tail,
3988 settings->beacon.tail_len);
3989
3990 kfree(cfg->ap_info->rsn_ie);
3991 cfg->ap_info->rsn_ie = NULL;
3992 kfree(cfg->ap_info->wpa_ie);
3993 cfg->ap_info->wpa_ie = NULL;
3994
3995 if ((wpa_ie != NULL || rsn_ie != NULL)) {
3996 WL_TRACE("WPA(2) IE is found\n");
3997 if (wpa_ie != NULL) {
3998 /* WPA IE */
3999 err = brcmf_configure_wpaie(ndev, wpa_ie, false,
4000 bssidx);
4001 if (err < 0)
4002 goto exit;
4003 cfg->ap_info->wpa_ie = kmemdup(wpa_ie,
4004 wpa_ie->len +
4005 TLV_HDR_LEN,
4006 GFP_KERNEL);
4007 } else {
4008 /* RSN IE */
4009 err = brcmf_configure_wpaie(ndev,
4010 (struct brcmf_vs_tlv *)rsn_ie, true, bssidx);
4011 if (err < 0)
4012 goto exit;
4013 cfg->ap_info->rsn_ie = kmemdup(rsn_ie,
4014 rsn_ie->len +
4015 TLV_HDR_LEN,
4016 GFP_KERNEL);
4017 }
4018 cfg->ap_info->security_mode = true;
4019 } else {
4020 WL_TRACE("No WPA(2) IEs found\n");
4021 brcmf_configure_opensecurity(ndev, bssidx);
4022 cfg->ap_info->security_mode = false;
4023 }
4024 /* Set Beacon IEs to FW */
4025 err = brcmf_set_management_ie(cfg, ndev,
4026 VNDR_IE_BEACON_FLAG,
4027 (u8 *)settings->beacon.tail,
4028 settings->beacon.tail_len);
4029 if (err)
4030 WL_ERR("Set Beacon IE Failed\n");
4031 else
4032 WL_TRACE("Applied Vndr IEs for Beacon\n");
4033
4034 /* Set Probe Response IEs to FW */
4035 err = brcmf_set_management_ie(cfg, ndev,
4036 VNDR_IE_PRBRSP_FLAG,
4037 (u8 *)settings->beacon.proberesp_ies,
4038 settings->beacon.proberesp_ies_len);
4039 if (err)
4040 WL_ERR("Set Probe Resp IE Failed\n");
4041 else
4042 WL_TRACE("Applied Vndr IEs for Probe Resp\n");
4043
4044 if (settings->beacon_interval) {
4045 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,
4046 settings->beacon_interval);
4047 if (err < 0) {
4048 WL_ERR("Beacon Interval Set Error, %d\n", err);
4049 goto exit;
4050 }
4051 }
4052 if (settings->dtim_period) {
4053 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_DTIMPRD,
4054 settings->dtim_period);
4055 if (err < 0) {
4056 WL_ERR("DTIM Interval Set Error, %d\n", err);
4057 goto exit;
4058 }
4059 }
4060 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
4061 if (err < 0) {
4062 WL_ERR("BRCMF_C_UP error (%d)\n", err);
4063 goto exit;
4064 }
4065
4066 memset(&join_params, 0, sizeof(join_params));
4067 /* join parameters starts with ssid */
4068 memcpy(&join_params.ssid_le, &ssid_le, sizeof(ssid_le));
4069 /* create softap */
4070 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
4071 &join_params, sizeof(join_params));
4072 if (err < 0) {
4073 WL_ERR("SET SSID error (%d)\n", err);
4074 goto exit;
4075 }
4076 clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
4077 set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
4078
4079exit:
4080 if (err)
4081 brcmf_set_mpc(ndev, 1);
4082 return err;
4083}
4084
4085static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
4086{
4087 struct brcmf_if *ifp = netdev_priv(ndev);
4088 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
4089 s32 err = -EPERM;
4090
4091 WL_TRACE("Enter\n");
4092
4093 if (cfg->conf->mode == WL_MODE_AP) {
4094 /* Due to most likely deauths outstanding we sleep */
4095 /* first to make sure they get processed by fw. */
4096 msleep(400);
4097 err = brcmf_fil_cmd_int_set(netdev_priv(ndev),
4098 BRCMF_C_SET_AP, 0);
4099 if (err < 0) {
4100 WL_ERR("setting AP mode failed %d\n", err);
4101 goto exit;
4102 }
4103 err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_UP, 0);
4104 if (err < 0) {
4105 WL_ERR("BRCMF_C_UP error %d\n", err);
4106 goto exit;
4107 }
4108 brcmf_set_mpc(ndev, 1);
4109 clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
4110 clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
4111 }
4112exit:
4113 return err;
4114}
4115
4116static int
4117brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
4118 u8 *mac)
4119{
4120 struct brcmf_scb_val_le scbval;
4121 struct brcmf_if *ifp = netdev_priv(ndev);
4122 s32 err;
4123
4124 if (!mac)
4125 return -EFAULT;
4126
4127 WL_TRACE("Enter %pM\n", mac);
4128
4129 if (!check_vif_up(ifp->vif))
4130 return -EIO;
4131
4132 memcpy(&scbval.ea, mac, ETH_ALEN);
4133 scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING);
4134 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON,
4135 &scbval, sizeof(scbval));
4136 if (err)
4137 WL_ERR("SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err);
4138
4139 WL_TRACE("Exit\n");
4140 return err;
4141}
4142
4143static struct cfg80211_ops wl_cfg80211_ops = {
4144 .change_virtual_intf = brcmf_cfg80211_change_iface,
4145 .scan = brcmf_cfg80211_scan,
4146 .set_wiphy_params = brcmf_cfg80211_set_wiphy_params,
4147 .join_ibss = brcmf_cfg80211_join_ibss,
4148 .leave_ibss = brcmf_cfg80211_leave_ibss,
4149 .get_station = brcmf_cfg80211_get_station,
4150 .set_tx_power = brcmf_cfg80211_set_tx_power,
4151 .get_tx_power = brcmf_cfg80211_get_tx_power,
4152 .add_key = brcmf_cfg80211_add_key,
4153 .del_key = brcmf_cfg80211_del_key,
4154 .get_key = brcmf_cfg80211_get_key,
4155 .set_default_key = brcmf_cfg80211_config_default_key,
4156 .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key,
4157 .set_power_mgmt = brcmf_cfg80211_set_power_mgmt,
4158 .set_bitrate_mask = brcmf_cfg80211_set_bitrate_mask,
4159 .connect = brcmf_cfg80211_connect,
4160 .disconnect = brcmf_cfg80211_disconnect,
4161 .suspend = brcmf_cfg80211_suspend,
4162 .resume = brcmf_cfg80211_resume,
4163 .set_pmksa = brcmf_cfg80211_set_pmksa,
4164 .del_pmksa = brcmf_cfg80211_del_pmksa,
4165 .flush_pmksa = brcmf_cfg80211_flush_pmksa,
4166 .start_ap = brcmf_cfg80211_start_ap,
4167 .stop_ap = brcmf_cfg80211_stop_ap,
4168 .del_station = brcmf_cfg80211_del_station,
4169#ifndef CONFIG_BRCMISCAN
4170 /* scheduled scan need e-scan, which is mutual exclusive with i-scan */
4171 .sched_scan_start = brcmf_cfg80211_sched_scan_start,
4172 .sched_scan_stop = brcmf_cfg80211_sched_scan_stop,
4173#endif
4174#ifdef CONFIG_NL80211_TESTMODE
4175 .testmode_cmd = brcmf_cfg80211_testmode
4176#endif
4177};
4178
4179static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
4180{
4181 s32 err = 0;
4182
4183 switch (mode) {
4184 case WL_MODE_BSS:
4185 return NL80211_IFTYPE_STATION;
4186 case WL_MODE_IBSS:
4187 return NL80211_IFTYPE_ADHOC;
4188 default:
4189 return NL80211_IFTYPE_UNSPECIFIED;
4190 }
4191
4192 return err;
4193}
4194
4195static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
4196{
4197#ifndef CONFIG_BRCMFISCAN
4198 /* scheduled scan settings */
4199 wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
4200 wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
4201 wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
4202 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
4203#endif
4204}
4205
4206static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
4207{
4208 struct wiphy *wiphy;
4209 s32 err = 0;
4210
4211 wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
4212 if (!wiphy) {
4213 WL_ERR("Could not allocate wiphy device\n");
4214 return ERR_PTR(-ENOMEM);
4215 }
4216 set_wiphy_dev(wiphy, phydev);
4217 wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
4218 wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
4219 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
4220 BIT(NL80211_IFTYPE_ADHOC) |
4221 BIT(NL80211_IFTYPE_AP);
4222 wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
4223 wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set
4224 * it as 11a by default.
4225 * This will be updated with
4226 * 11n phy tables in
4227 * "ifconfig up"
4228 * if phy has 11n capability
4229 */
4230 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
4231 wiphy->cipher_suites = __wl_cipher_suites;
4232 wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
4233 wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power
4234 * save mode
4235 * by default
4236 */
4237 brcmf_wiphy_pno_params(wiphy);
4238 err = wiphy_register(wiphy);
4239 if (err < 0) {
4240 WL_ERR("Could not register wiphy device (%d)\n", err);
4241 wiphy_free(wiphy);
4242 return ERR_PTR(err);
4243 }
4244 return wiphy;
4245}
4246
4247static
4248struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
4249 struct net_device *netdev,
4250 s32 mode, bool pm_block)
4251{
4252 struct brcmf_cfg80211_vif *vif;
4253
4254 if (cfg->vif_cnt == BRCMF_IFACE_MAX_CNT)
4255 return ERR_PTR(-ENOSPC);
4256
4257 vif = kzalloc(sizeof(*vif), GFP_KERNEL);
4258 if (!vif)
4259 return ERR_PTR(-ENOMEM);
4260
4261 vif->wdev.wiphy = cfg->wiphy;
4262 vif->wdev.netdev = netdev;
4263 vif->wdev.iftype = brcmf_mode_to_nl80211_iftype(mode);
4264
4265 if (netdev) {
4266 vif->ifp = netdev_priv(netdev);
4267 netdev->ieee80211_ptr = &vif->wdev;
4268 SET_NETDEV_DEV(netdev, wiphy_dev(cfg->wiphy));
4269 }
4270
4271 vif->mode = mode;
4272 vif->pm_block = pm_block;
4273 vif->roam_off = -1;
4274
4275 brcmf_init_prof(&vif->profile);
4276
4277 list_add_tail(&vif->list, &cfg->vif_list);
4278 cfg->vif_cnt++;
4279 return vif;
4280}
4281
4282static void brcmf_free_vif(struct brcmf_cfg80211_vif *vif)
4283{
4284 struct brcmf_cfg80211_info *cfg;
4285 struct wiphy *wiphy;
4286
4287 wiphy = vif->wdev.wiphy;
4288 cfg = wiphy_priv(wiphy);
4289 list_del(&vif->list);
4290 cfg->vif_cnt--;
4291
4292 kfree(vif);
4293 if (!cfg->vif_cnt) {
4294 wiphy_unregister(wiphy);
4295 wiphy_free(wiphy);
4296 }
4297}
4298
4299static bool brcmf_is_linkup(struct brcmf_cfg80211_info *cfg,
4300 const struct brcmf_event_msg *e)
4301{
4302 u32 event = be32_to_cpu(e->event_type);
4303 u32 status = be32_to_cpu(e->status);
4304
4305 if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
4306 WL_CONN("Processing set ssid\n");
4307 cfg->link_up = true;
4308 return true;
4309 }
4310
4311 return false;
4312}
4313
4314static bool brcmf_is_linkdown(struct brcmf_cfg80211_info *cfg,
4315 const struct brcmf_event_msg *e)
4316{
4317 u32 event = be32_to_cpu(e->event_type);
4318 u16 flags = be16_to_cpu(e->flags);
4319
4320 if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) {
4321 WL_CONN("Processing link down\n");
4322 return true;
4323 }
4324 return false;
4325}
4326
4327static bool brcmf_is_nonetwork(struct brcmf_cfg80211_info *cfg,
4328 const struct brcmf_event_msg *e)
4329{
4330 u32 event = be32_to_cpu(e->event_type);
4331 u32 status = be32_to_cpu(e->status);
4332
4333 if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) {
4334 WL_CONN("Processing Link %s & no network found\n",
4335 be16_to_cpu(e->flags) & BRCMF_EVENT_MSG_LINK ?
4336 "up" : "down");
4337 return true;
4338 }
4339
4340 if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) {
4341 WL_CONN("Processing connecting & no network found\n");
4342 return true;
4343 }
4344
4345 return false;
4346}
4347
4348static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg)
4349{
4350 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
4351
4352 kfree(conn_info->req_ie);
4353 conn_info->req_ie = NULL;
4354 conn_info->req_ie_len = 0;
4355 kfree(conn_info->resp_ie);
4356 conn_info->resp_ie = NULL;
4357 conn_info->resp_ie_len = 0;
4358}
4359
4360static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg)
4361{
4362 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
4363 struct brcmf_cfg80211_assoc_ielen_le *assoc_info;
4364 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
4365 u32 req_len;
4366 u32 resp_len;
4367 s32 err = 0;
4368
4369 brcmf_clear_assoc_ies(cfg);
4370
4371 err = brcmf_fil_iovar_data_get(ifp, "assoc_info",
4372 cfg->extra_buf, WL_ASSOC_INFO_MAX);
4373 if (err) {
4374 WL_ERR("could not get assoc info (%d)\n", err);
4375 return err;
4376 }
4377 assoc_info =
4378 (struct brcmf_cfg80211_assoc_ielen_le *)cfg->extra_buf;
4379 req_len = le32_to_cpu(assoc_info->req_len);
4380 resp_len = le32_to_cpu(assoc_info->resp_len);
4381 if (req_len) {
4382 err = brcmf_fil_iovar_data_get(ifp, "assoc_req_ies",
4383 cfg->extra_buf,
4384 WL_ASSOC_INFO_MAX);
4385 if (err) {
4386 WL_ERR("could not get assoc req (%d)\n", err);
4387 return err;
4388 }
4389 conn_info->req_ie_len = req_len;
4390 conn_info->req_ie =
4391 kmemdup(cfg->extra_buf, conn_info->req_ie_len,
4392 GFP_KERNEL);
4393 } else {
4394 conn_info->req_ie_len = 0;
4395 conn_info->req_ie = NULL;
4396 }
4397 if (resp_len) {
4398 err = brcmf_fil_iovar_data_get(ifp, "assoc_resp_ies",
4399 cfg->extra_buf,
4400 WL_ASSOC_INFO_MAX);
4401 if (err) {
4402 WL_ERR("could not get assoc resp (%d)\n", err);
4403 return err;
4404 }
4405 conn_info->resp_ie_len = resp_len;
4406 conn_info->resp_ie =
4407 kmemdup(cfg->extra_buf, conn_info->resp_ie_len,
4408 GFP_KERNEL);
4409 } else {
4410 conn_info->resp_ie_len = 0;
4411 conn_info->resp_ie = NULL;
4412 }
4413 WL_CONN("req len (%d) resp len (%d)\n",
4414 conn_info->req_ie_len, conn_info->resp_ie_len);
4415
4416 return err;
4417}
4418
4419static s32
4420brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
4421 struct net_device *ndev,
4422 const struct brcmf_event_msg *e)
4423{
4424 struct brcmf_if *ifp = netdev_priv(ndev);
4425 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
4426 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
4427 struct wiphy *wiphy = cfg_to_wiphy(cfg);
4428 struct ieee80211_channel *notify_channel = NULL;
4429 struct ieee80211_supported_band *band;
4430 struct brcmf_bss_info_le *bi;
4431 u32 freq;
4432 s32 err = 0;
4433 u32 target_channel;
4434 u8 *buf;
4435
4436 WL_TRACE("Enter\n");
4437
4438 brcmf_get_assoc_ies(cfg);
4439 memcpy(profile->bssid, e->addr, ETH_ALEN);
4440 brcmf_update_bss_info(cfg);
4441
4442 buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
4443 if (buf == NULL) {
4444 err = -ENOMEM;
4445 goto done;
4446 }
4447
4448 /* data sent to dongle has to be little endian */
4449 *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
4450 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
4451 buf, WL_BSS_INFO_MAX);
4452
4453 if (err)
4454 goto done;
4455
4456 bi = (struct brcmf_bss_info_le *)(buf + 4);
4457 target_channel = bi->ctl_ch ? bi->ctl_ch :
4458 CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
4459
4460 if (target_channel <= CH_MAX_2G_CHANNEL)
4461 band = wiphy->bands[IEEE80211_BAND_2GHZ];
4462 else
4463 band = wiphy->bands[IEEE80211_BAND_5GHZ];
4464
4465 freq = ieee80211_channel_to_frequency(target_channel, band->band);
4466 notify_channel = ieee80211_get_channel(wiphy, freq);
4467
4468done:
4469 kfree(buf);
4470 cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid,
4471 conn_info->req_ie, conn_info->req_ie_len,
4472 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
4473 WL_CONN("Report roaming result\n");
4474
4475 set_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
4476 WL_TRACE("Exit\n");
4477 return err;
4478}
4479
4480static s32
4481brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg,
4482 struct net_device *ndev, const struct brcmf_event_msg *e,
4483 bool completed)
4484{
4485 struct brcmf_if *ifp = netdev_priv(ndev);
4486 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
4487 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
4488 s32 err = 0;
4489
4490 WL_TRACE("Enter\n");
4491
4492 if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTING,
4493 &ifp->vif->sme_state)) {
4494 if (completed) {
4495 brcmf_get_assoc_ies(cfg);
4496 memcpy(profile->bssid, e->addr, ETH_ALEN);
4497 brcmf_update_bss_info(cfg);
4498 }
4499 cfg80211_connect_result(ndev,
4500 (u8 *)profile->bssid,
4501 conn_info->req_ie,
4502 conn_info->req_ie_len,
4503 conn_info->resp_ie,
4504 conn_info->resp_ie_len,
4505 completed ? WLAN_STATUS_SUCCESS :
4506 WLAN_STATUS_AUTH_TIMEOUT,
4507 GFP_KERNEL);
4508 if (completed)
4509 set_bit(BRCMF_VIF_STATUS_CONNECTED,
4510 &ifp->vif->sme_state);
4511 WL_CONN("Report connect result - connection %s\n",
4512 completed ? "succeeded" : "failed");
4513 }
4514 WL_TRACE("Exit\n");
4515 return err;
4516}
4517
4518static s32
4519brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,
4520 struct net_device *ndev,
4521 const struct brcmf_event_msg *e, void *data)
4522{
4523 s32 err = 0;
4524 u32 event = be32_to_cpu(e->event_type);
4525 u32 reason = be32_to_cpu(e->reason);
4526 u32 len = be32_to_cpu(e->datalen);
4527 static int generation;
4528
4529 struct station_info sinfo;
4530
4531 WL_CONN("event %d, reason %d\n", event, reason);
4532 memset(&sinfo, 0, sizeof(sinfo));
4533
4534 sinfo.filled = 0;
4535 if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) &&
4536 reason == BRCMF_E_STATUS_SUCCESS) {
4537 sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
4538 if (!data) {
4539 WL_ERR("No IEs present in ASSOC/REASSOC_IND");
4540 return -EINVAL;
4541 }
4542 sinfo.assoc_req_ies = data;
4543 sinfo.assoc_req_ies_len = len;
4544 generation++;
4545 sinfo.generation = generation;
4546 cfg80211_new_sta(ndev, e->addr, &sinfo, GFP_ATOMIC);
4547 } else if ((event == BRCMF_E_DISASSOC_IND) ||
4548 (event == BRCMF_E_DEAUTH_IND) ||
4549 (event == BRCMF_E_DEAUTH)) {
4550 generation++;
4551 sinfo.generation = generation;
4552 cfg80211_del_sta(ndev, e->addr, GFP_ATOMIC);
4553 }
4554 return err;
4555}
4556
4557static s32
4558brcmf_notify_connect_status(struct brcmf_cfg80211_info *cfg,
4559 struct net_device *ndev,
4560 const struct brcmf_event_msg *e, void *data)
4561{
4562 struct brcmf_if *ifp = netdev_priv(ndev);
4563 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
4564 s32 err = 0;
4565
4566 if (cfg->conf->mode == WL_MODE_AP) {
4567 err = brcmf_notify_connect_status_ap(cfg, ndev, e, data);
4568 } else if (brcmf_is_linkup(cfg, e)) {
4569 WL_CONN("Linkup\n");
4570 if (brcmf_is_ibssmode(cfg)) {
4571 memcpy(profile->bssid, e->addr, ETH_ALEN);
4572 wl_inform_ibss(cfg, ndev, e->addr);
4573 cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
4574 clear_bit(BRCMF_VIF_STATUS_CONNECTING,
4575 &ifp->vif->sme_state);
4576 set_bit(BRCMF_VIF_STATUS_CONNECTED,
4577 &ifp->vif->sme_state);
4578 } else
4579 brcmf_bss_connect_done(cfg, ndev, e, true);
4580 } else if (brcmf_is_linkdown(cfg, e)) {
4581 WL_CONN("Linkdown\n");
4582 if (brcmf_is_ibssmode(cfg)) {
4583 clear_bit(BRCMF_VIF_STATUS_CONNECTING,
4584 &ifp->vif->sme_state);
4585 if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED,
4586 &ifp->vif->sme_state))
4587 brcmf_link_down(cfg);
4588 } else {
4589 brcmf_bss_connect_done(cfg, ndev, e, false);
4590 if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED,
4591 &ifp->vif->sme_state)) {
4592 cfg80211_disconnected(ndev, 0, NULL, 0,
4593 GFP_KERNEL);
4594 brcmf_link_down(cfg);
4595 }
4596 }
4597 brcmf_init_prof(ndev_to_prof(ndev));
4598 } else if (brcmf_is_nonetwork(cfg, e)) {
4599 if (brcmf_is_ibssmode(cfg))
4600 clear_bit(BRCMF_VIF_STATUS_CONNECTING,
4601 &ifp->vif->sme_state);
4602 else
4603 brcmf_bss_connect_done(cfg, ndev, e, false);
4604 }
4605
4606 return err;
4607}
4608
4609static s32
4610brcmf_notify_roaming_status(struct brcmf_cfg80211_info *cfg,
4611 struct net_device *ndev,
4612 const struct brcmf_event_msg *e, void *data)
4613{
4614 struct brcmf_if *ifp = netdev_priv(ndev);
4615 s32 err = 0;
4616 u32 event = be32_to_cpu(e->event_type);
4617 u32 status = be32_to_cpu(e->status);
4618
4619 if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
4620 if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state))
4621 brcmf_bss_roaming_done(cfg, ndev, e);
4622 else
4623 brcmf_bss_connect_done(cfg, ndev, e, true);
4624 }
4625
4626 return err;
4627}
4628
4629static s32
4630brcmf_notify_mic_status(struct brcmf_cfg80211_info *cfg,
4631 struct net_device *ndev,
4632 const struct brcmf_event_msg *e, void *data)
4633{
4634 u16 flags = be16_to_cpu(e->flags);
4635 enum nl80211_key_type key_type;
4636
4637 if (flags & BRCMF_EVENT_MSG_GROUP)
4638 key_type = NL80211_KEYTYPE_GROUP;
4639 else
4640 key_type = NL80211_KEYTYPE_PAIRWISE;
4641
4642 cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
4643 NULL, GFP_KERNEL);
4644
4645 return 0;
4646}
4647
4648static s32
4649brcmf_notify_scan_status(struct brcmf_cfg80211_info *cfg,
4650 struct net_device *ndev,
4651 const struct brcmf_event_msg *e, void *data)
4652{
4653 struct brcmf_if *ifp = netdev_priv(ndev);
4654 struct brcmf_channel_info_le channel_inform_le;
4655 struct brcmf_scan_results_le *bss_list_le;
4656 u32 len = WL_SCAN_BUF_MAX;
4657 s32 err = 0;
4658 bool scan_abort = false;
4659 u32 scan_channel;
4660
4661 WL_TRACE("Enter\n");
4662
4663 if (cfg->iscan_on && cfg->iscan_kickstart) {
4664 WL_TRACE("Exit\n");
4665 return brcmf_wakeup_iscan(cfg_to_iscan(cfg));
4666 }
4667
4668 if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
4669 WL_ERR("Scan complete while device not scanning\n");
4670 scan_abort = true;
4671 err = -EINVAL;
4672 goto scan_done_out;
4673 }
4674
4675 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CHANNEL,
4676 &channel_inform_le,
4677 sizeof(channel_inform_le));
4678 if (err) {
4679 WL_ERR("scan busy (%d)\n", err);
4680 scan_abort = true;
4681 goto scan_done_out;
4682 }
4683 scan_channel = le32_to_cpu(channel_inform_le.scan_channel);
4684 if (scan_channel)
4685 WL_CONN("channel_inform.scan_channel (%d)\n", scan_channel);
4686 cfg->bss_list = cfg->scan_results;
4687 bss_list_le = (struct brcmf_scan_results_le *) cfg->bss_list;
4688
4689 memset(cfg->scan_results, 0, len);
4690 bss_list_le->buflen = cpu_to_le32(len);
4691 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_SCAN_RESULTS,
4692 cfg->scan_results, len);
4693 if (err) {
4694 WL_ERR("%s Scan_results error (%d)\n", ndev->name, err);
4695 err = -EINVAL;
4696 scan_abort = true;
4697 goto scan_done_out;
4698 }
4699 cfg->scan_results->buflen = le32_to_cpu(bss_list_le->buflen);
4700 cfg->scan_results->version = le32_to_cpu(bss_list_le->version);
4701 cfg->scan_results->count = le32_to_cpu(bss_list_le->count);
4702
4703 err = brcmf_inform_bss(cfg);
4704 if (err)
4705 scan_abort = true;
4706
4707scan_done_out:
4708 if (cfg->scan_request) {
4709 WL_SCAN("calling cfg80211_scan_done\n");
4710 cfg80211_scan_done(cfg->scan_request, scan_abort);
4711 brcmf_set_mpc(ndev, 1);
4712 cfg->scan_request = NULL;
4713 }
4714
4715 WL_TRACE("Exit\n");
4716
4717 return err;
4718}
4719
4720static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
4721{
4722 conf->mode = (u32)-1;
4723 conf->frag_threshold = (u32)-1;
4724 conf->rts_threshold = (u32)-1;
4725 conf->retry_short = (u32)-1;
4726 conf->retry_long = (u32)-1;
4727 conf->tx_power = -1;
4728}
4729
4730static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el)
4731{
4732 memset(el, 0, sizeof(*el));
4733 el->handler[BRCMF_E_SCAN_COMPLETE] = brcmf_notify_scan_status;
4734 el->handler[BRCMF_E_LINK] = brcmf_notify_connect_status;
4735 el->handler[BRCMF_E_DEAUTH_IND] = brcmf_notify_connect_status;
4736 el->handler[BRCMF_E_DEAUTH] = brcmf_notify_connect_status;
4737 el->handler[BRCMF_E_DISASSOC_IND] = brcmf_notify_connect_status;
4738 el->handler[BRCMF_E_ASSOC_IND] = brcmf_notify_connect_status;
4739 el->handler[BRCMF_E_REASSOC_IND] = brcmf_notify_connect_status;
4740 el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status;
4741 el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status;
4742 el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status;
4743 el->handler[BRCMF_E_PFN_NET_FOUND] = brcmf_notify_sched_scan_results;
4744}
4745
4746static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg)
4747{
4748 kfree(cfg->scan_results);
4749 cfg->scan_results = NULL;
4750 kfree(cfg->bss_info);
4751 cfg->bss_info = NULL;
4752 kfree(cfg->conf);
4753 cfg->conf = NULL;
4754 kfree(cfg->scan_req_int);
4755 cfg->scan_req_int = NULL;
4756 kfree(cfg->escan_ioctl_buf);
4757 cfg->escan_ioctl_buf = NULL;
4758 kfree(cfg->dcmd_buf);
4759 cfg->dcmd_buf = NULL;
4760 kfree(cfg->extra_buf);
4761 cfg->extra_buf = NULL;
4762 kfree(cfg->iscan);
4763 cfg->iscan = NULL;
4764 kfree(cfg->pmk_list);
4765 cfg->pmk_list = NULL;
4766 if (cfg->ap_info) {
4767 kfree(cfg->ap_info->wpa_ie);
4768 kfree(cfg->ap_info->rsn_ie);
4769 kfree(cfg->ap_info);
4770 cfg->ap_info = NULL;
4771 }
4772}
4773
4774static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg)
4775{
4776 cfg->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
4777 if (!cfg->scan_results)
4778 goto init_priv_mem_out;
4779 cfg->conf = kzalloc(sizeof(*cfg->conf), GFP_KERNEL);
4780 if (!cfg->conf)
4781 goto init_priv_mem_out;
4782 cfg->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
4783 if (!cfg->bss_info)
4784 goto init_priv_mem_out;
4785 cfg->scan_req_int = kzalloc(sizeof(*cfg->scan_req_int),
4786 GFP_KERNEL);
4787 if (!cfg->scan_req_int)
4788 goto init_priv_mem_out;
4789 cfg->escan_ioctl_buf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
4790 if (!cfg->escan_ioctl_buf)
4791 goto init_priv_mem_out;
4792 cfg->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL);
4793 if (!cfg->dcmd_buf)
4794 goto init_priv_mem_out;
4795 cfg->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
4796 if (!cfg->extra_buf)
4797 goto init_priv_mem_out;
4798 cfg->iscan = kzalloc(sizeof(*cfg->iscan), GFP_KERNEL);
4799 if (!cfg->iscan)
4800 goto init_priv_mem_out;
4801 cfg->pmk_list = kzalloc(sizeof(*cfg->pmk_list), GFP_KERNEL);
4802 if (!cfg->pmk_list)
4803 goto init_priv_mem_out;
4804
4805 return 0;
4806
4807init_priv_mem_out:
4808 brcmf_deinit_priv_mem(cfg);
4809
4810 return -ENOMEM;
4811}
4812
4813/*
4814* retrieve first queued event from head
4815*/
4816
4817static struct brcmf_cfg80211_event_q *brcmf_deq_event(
4818 struct brcmf_cfg80211_info *cfg)
4819{
4820 struct brcmf_cfg80211_event_q *e = NULL;
4821
4822 spin_lock_irq(&cfg->evt_q_lock);
4823 if (!list_empty(&cfg->evt_q_list)) {
4824 e = list_first_entry(&cfg->evt_q_list,
4825 struct brcmf_cfg80211_event_q, evt_q_list);
4826 list_del(&e->evt_q_list);
4827 }
4828 spin_unlock_irq(&cfg->evt_q_lock);
4829
4830 return e;
4831}
4832
4833/*
4834* push event to tail of the queue
4835*
4836* remark: this function may not sleep as it is called in atomic context.
4837*/
4838
4839static s32
4840brcmf_enq_event(struct brcmf_cfg80211_info *cfg, u32 event,
4841 const struct brcmf_event_msg *msg, void *data)
4842{
4843 struct brcmf_cfg80211_event_q *e;
4844 s32 err = 0;
4845 ulong flags;
4846 u32 data_len;
4847 u32 total_len;
4848
4849 total_len = sizeof(struct brcmf_cfg80211_event_q);
4850 if (data)
4851 data_len = be32_to_cpu(msg->datalen);
4852 else
4853 data_len = 0;
4854 total_len += data_len;
4855 e = kzalloc(total_len, GFP_ATOMIC);
4856 if (!e)
4857 return -ENOMEM;
4858
4859 e->etype = event;
4860 memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
4861 if (data)
4862 memcpy(&e->edata, data, data_len);
4863
4864 spin_lock_irqsave(&cfg->evt_q_lock, flags);
4865 list_add_tail(&e->evt_q_list, &cfg->evt_q_list);
4866 spin_unlock_irqrestore(&cfg->evt_q_lock, flags);
4867
4868 return err;
4869}
4870
4871static void brcmf_put_event(struct brcmf_cfg80211_event_q *e)
4872{
4873 kfree(e);
4874}
4875
4876static void brcmf_cfg80211_event_handler(struct work_struct *work)
4877{
4878 struct brcmf_cfg80211_info *cfg =
4879 container_of(work, struct brcmf_cfg80211_info,
4880 event_work);
4881 struct brcmf_cfg80211_event_q *e;
4882
4883 e = brcmf_deq_event(cfg);
4884 if (unlikely(!e)) {
4885 WL_ERR("event queue empty...\n");
4886 return;
4887 }
4888
4889 do {
4890 WL_INFO("event type (%d)\n", e->etype);
4891 if (cfg->el.handler[e->etype])
4892 cfg->el.handler[e->etype](cfg,
4893 cfg_to_ndev(cfg),
4894 &e->emsg, e->edata);
4895 else
4896 WL_INFO("Unknown Event (%d): ignoring\n", e->etype);
4897 brcmf_put_event(e);
4898 } while ((e = brcmf_deq_event(cfg)));
4899
4900}
4901
4902static void brcmf_init_eq(struct brcmf_cfg80211_info *cfg)
4903{
4904 spin_lock_init(&cfg->evt_q_lock);
4905 INIT_LIST_HEAD(&cfg->evt_q_list);
4906}
4907
4908static void brcmf_flush_eq(struct brcmf_cfg80211_info *cfg)
4909{
4910 struct brcmf_cfg80211_event_q *e;
4911
4912 spin_lock_irq(&cfg->evt_q_lock);
4913 while (!list_empty(&cfg->evt_q_list)) {
4914 e = list_first_entry(&cfg->evt_q_list,
4915 struct brcmf_cfg80211_event_q, evt_q_list);
4916 list_del(&e->evt_q_list);
4917 kfree(e);
4918 }
4919 spin_unlock_irq(&cfg->evt_q_lock);
4920}
4921
4922static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg)
4923{
4924 s32 err = 0;
4925
4926 cfg->scan_request = NULL;
4927 cfg->pwr_save = true;
4928#ifdef CONFIG_BRCMISCAN
4929 cfg->iscan_on = true; /* iscan on & off switch.
4930 we enable iscan per default */
4931 cfg->escan_on = false; /* escan on & off switch.
4932 we disable escan per default */
4933#else
4934 cfg->iscan_on = false; /* iscan on & off switch.
4935 we disable iscan per default */
4936 cfg->escan_on = true; /* escan on & off switch.
4937 we enable escan per default */
4938#endif
4939 cfg->roam_on = true; /* roam on & off switch.
4940 we enable roam per default */
4941
4942 cfg->iscan_kickstart = false;
4943 cfg->active_scan = true; /* we do active scan for
4944 specific scan per default */
4945 cfg->dongle_up = false; /* dongle is not up yet */
4946 brcmf_init_eq(cfg);
4947 err = brcmf_init_priv_mem(cfg);
4948 if (err)
4949 return err;
4950 INIT_WORK(&cfg->event_work, brcmf_cfg80211_event_handler);
4951 brcmf_init_eloop_handler(&cfg->el);
4952 mutex_init(&cfg->usr_sync);
4953 err = brcmf_init_iscan(cfg);
4954 if (err)
4955 return err;
4956 brcmf_init_escan(cfg);
4957 brcmf_init_conf(cfg->conf);
4958 brcmf_link_down(cfg);
4959
4960 return err;
4961}
4962
4963static void wl_deinit_priv(struct brcmf_cfg80211_info *cfg)
4964{
4965 cancel_work_sync(&cfg->event_work);
4966 cfg->dongle_up = false; /* dongle down */
4967 brcmf_flush_eq(cfg);
4968 brcmf_link_down(cfg);
4969 brcmf_abort_scanning(cfg);
4970 brcmf_deinit_priv_mem(cfg);
4971}
4972
4973struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr)
4974{
4975 struct net_device *ndev = drvr->iflist[0]->ndev;
4976 struct device *busdev = drvr->dev;
4977 struct brcmf_cfg80211_info *cfg;
4978 struct wiphy *wiphy;
4979 struct brcmf_cfg80211_vif *vif;
4980 struct brcmf_if *ifp;
4981 s32 err = 0;
4982
4983 if (!ndev) {
4984 WL_ERR("ndev is invalid\n");
4985 return NULL;
4986 }
4987
4988 ifp = netdev_priv(ndev);
4989 wiphy = brcmf_setup_wiphy(busdev);
4990 if (IS_ERR(wiphy))
4991 return NULL;
4992
4993 cfg = wiphy_priv(wiphy);
4994 cfg->wiphy = wiphy;
4995 cfg->pub = drvr;
4996 INIT_LIST_HEAD(&cfg->vif_list);
4997
4998 vif = brcmf_alloc_vif(cfg, ndev, WL_MODE_BSS, false);
4999 if (IS_ERR(vif)) {
5000 wiphy_free(wiphy);
5001 return NULL;
5002 }
5003
5004 err = wl_init_priv(cfg);
5005 if (err) {
5006 WL_ERR("Failed to init iwm_priv (%d)\n", err);
5007 goto cfg80211_attach_out;
5008 }
5009
5010 ifp->vif = vif;
5011 return cfg;
5012
5013cfg80211_attach_out:
5014 brcmf_free_vif(vif);
5015 return NULL;
5016}
5017
5018void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
5019{
5020 struct brcmf_cfg80211_vif *vif;
5021 struct brcmf_cfg80211_vif *tmp;
5022
5023 wl_deinit_priv(cfg);
5024 list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) {
5025 brcmf_free_vif(vif);
5026 }
5027}
5028
5029void
5030brcmf_cfg80211_event(struct net_device *ndev,
5031 const struct brcmf_event_msg *e, void *data)
5032{
5033 u32 event_type = be32_to_cpu(e->event_type);
5034 struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
5035
5036 if (!brcmf_enq_event(cfg, event_type, e, data))
5037 schedule_work(&cfg->event_work);
5038}
5039
5040static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
5041{
5042 s8 eventmask[BRCMF_EVENTING_MASK_LEN];
5043 s32 err = 0;
5044
5045 WL_TRACE("Enter\n");
5046
5047 /* Setup event_msgs */
5048 err = brcmf_fil_iovar_data_get(netdev_priv(ndev), "event_msgs",
5049 eventmask, BRCMF_EVENTING_MASK_LEN);
5050 if (err) {
5051 WL_ERR("Get event_msgs error (%d)\n", err);
5052 goto dongle_eventmsg_out;
5053 }
5054
5055 setbit(eventmask, BRCMF_E_SET_SSID);
5056 setbit(eventmask, BRCMF_E_ROAM);
5057 setbit(eventmask, BRCMF_E_PRUNE);
5058 setbit(eventmask, BRCMF_E_AUTH);
5059 setbit(eventmask, BRCMF_E_REASSOC);
5060 setbit(eventmask, BRCMF_E_REASSOC_IND);
5061 setbit(eventmask, BRCMF_E_DEAUTH_IND);
5062 setbit(eventmask, BRCMF_E_DISASSOC_IND);
5063 setbit(eventmask, BRCMF_E_DISASSOC);
5064 setbit(eventmask, BRCMF_E_JOIN);
5065 setbit(eventmask, BRCMF_E_ASSOC_IND);
5066 setbit(eventmask, BRCMF_E_PSK_SUP);
5067 setbit(eventmask, BRCMF_E_LINK);
5068 setbit(eventmask, BRCMF_E_NDIS_LINK);
5069 setbit(eventmask, BRCMF_E_MIC_ERROR);
5070 setbit(eventmask, BRCMF_E_PMKID_CACHE);
5071 setbit(eventmask, BRCMF_E_TXFAIL);
5072 setbit(eventmask, BRCMF_E_JOIN_START);
5073 setbit(eventmask, BRCMF_E_SCAN_COMPLETE);
5074 setbit(eventmask, BRCMF_E_ESCAN_RESULT);
5075 setbit(eventmask, BRCMF_E_PFN_NET_FOUND);
5076
5077 err = brcmf_fil_iovar_data_set(netdev_priv(ndev), "event_msgs",
5078 eventmask, BRCMF_EVENTING_MASK_LEN);
5079 if (err) {
5080 WL_ERR("Set event_msgs error (%d)\n", err);
5081 goto dongle_eventmsg_out;
5082 }
5083
5084dongle_eventmsg_out:
5085 WL_TRACE("Exit\n");
5086 return err;
5087}
5088
5089static s32
5090brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
5091{
5092 struct brcmf_if *ifp = netdev_priv(ndev);
5093 s32 err = 0;
5094 __le32 roamtrigger[2];
5095 __le32 roam_delta[2];
5096
5097 /*
5098 * Setup timeout if Beacons are lost and roam is
5099 * off to report link down
5100 */
5101 if (roamvar) {
5102 err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout);
5103 if (err) {
5104 WL_ERR("bcn_timeout error (%d)\n", err);
5105 goto dongle_rom_out;
5106 }
5107 }
5108
5109 /*
5110 * Enable/Disable built-in roaming to allow supplicant
5111 * to take care of roaming
5112 */
5113 WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On");
5114 err = brcmf_fil_iovar_int_set(ifp, "roam_off", roamvar);
5115 if (err) {
5116 WL_ERR("roam_off error (%d)\n", err);
5117 goto dongle_rom_out;
5118 }
5119
5120 roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL);
5121 roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL);
5122 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_TRIGGER,
5123 (void *)roamtrigger, sizeof(roamtrigger));
5124 if (err) {
5125 WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
5126 goto dongle_rom_out;
5127 }
5128
5129 roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA);
5130 roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL);
5131 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_DELTA,
5132 (void *)roam_delta, sizeof(roam_delta));
5133 if (err) {
5134 WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err);
5135 goto dongle_rom_out;
5136 }
5137
5138dongle_rom_out:
5139 return err;
5140}
5141
5142static s32
5143brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
5144 s32 scan_unassoc_time, s32 scan_passive_time)
5145{
5146 struct brcmf_if *ifp = netdev_priv(ndev);
5147 s32 err = 0;
5148
5149 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
5150 scan_assoc_time);
5151 if (err) {
5152 if (err == -EOPNOTSUPP)
5153 WL_INFO("Scan assoc time is not supported\n");
5154 else
5155 WL_ERR("Scan assoc time error (%d)\n", err);
5156 goto dongle_scantime_out;
5157 }
5158 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
5159 scan_unassoc_time);
5160 if (err) {
5161 if (err == -EOPNOTSUPP)
5162 WL_INFO("Scan unassoc time is not supported\n");
5163 else
5164 WL_ERR("Scan unassoc time error (%d)\n", err);
5165 goto dongle_scantime_out;
5166 }
5167
5168 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_PASSIVE_TIME,
5169 scan_passive_time);
5170 if (err) {
5171 if (err == -EOPNOTSUPP)
5172 WL_INFO("Scan passive time is not supported\n");
5173 else
5174 WL_ERR("Scan passive time error (%d)\n", err);
5175 goto dongle_scantime_out;
5176 }
5177
5178dongle_scantime_out:
5179 return err;
5180}
5181
5182static s32 wl_update_wiphybands(struct brcmf_cfg80211_info *cfg)
5183{
5184 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
5185 struct wiphy *wiphy;
5186 s32 phy_list;
5187 s8 phy;
5188 s32 err = 0;
5189
5190 err = brcmf_fil_cmd_data_get(ifp, BRCM_GET_PHYLIST,
5191 &phy_list, sizeof(phy_list));
5192 if (err) {
5193 WL_ERR("error (%d)\n", err);
5194 return err;
5195 }
5196
5197 phy = ((char *)&phy_list)[0];
5198 WL_INFO("%c phy\n", phy);
5199 if (phy == 'n' || phy == 'a') {
5200 wiphy = cfg_to_wiphy(cfg);
5201 wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
5202 }
5203
5204 return err;
5205}
5206
5207static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg)
5208{
5209 return wl_update_wiphybands(cfg);
5210}
5211
5212static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
5213{
5214 struct net_device *ndev;
5215 struct wireless_dev *wdev;
5216 s32 power_mode;
5217 s32 err = 0;
5218
5219 if (cfg->dongle_up)
5220 return err;
5221
5222 ndev = cfg_to_ndev(cfg);
5223 wdev = ndev->ieee80211_ptr;
5224
5225 brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
5226 WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
5227
5228 err = brcmf_dongle_eventmsg(ndev);
5229 if (err)
5230 goto default_conf_out;
5231
5232 power_mode = cfg->pwr_save ? PM_FAST : PM_OFF;
5233 err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PM,
5234 power_mode);
5235 if (err)
5236 goto default_conf_out;
5237 WL_INFO("power save set to %s\n",
5238 (power_mode ? "enabled" : "disabled"));
5239
5240 err = brcmf_dongle_roam(ndev, (cfg->roam_on ? 0 : 1),
5241 WL_BEACON_TIMEOUT);
5242 if (err)
5243 goto default_conf_out;
5244 err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype,
5245 NULL, NULL);
5246 if (err && err != -EINPROGRESS)
5247 goto default_conf_out;
5248 err = brcmf_dongle_probecap(cfg);
5249 if (err)
5250 goto default_conf_out;
5251
5252 /* -EINPROGRESS: Call commit handler */
5253
5254default_conf_out:
5255
5256 cfg->dongle_up = true;
5257
5258 return err;
5259
5260}
5261
5262static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg)
5263{
5264 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
5265 s32 err = 0;
5266
5267 set_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);
5268
5269 err = brcmf_config_dongle(cfg);
5270 if (err)
5271 return err;
5272
5273 brcmf_invoke_iscan(cfg);
5274
5275 return err;
5276}
5277
5278static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg)
5279{
5280 struct net_device *ndev = cfg_to_ndev(cfg);
5281 struct brcmf_if *ifp = netdev_priv(ndev);
5282
5283 /*
5284 * While going down, if associated with AP disassociate
5285 * from AP to save power
5286 */
5287 if ((test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state) ||
5288 test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) &&
5289 check_vif_up(ifp->vif)) {
5290 WL_INFO("Disassociating from AP");
5291 brcmf_link_down(cfg);
5292
5293 /* Make sure WPA_Supplicant receives all the event
5294 generated due to DISASSOC call to the fw to keep
5295 the state fw and WPA_Supplicant state consistent
5296 */
5297 brcmf_delay(500);
5298 }
5299
5300 brcmf_abort_scanning(cfg);
5301 clear_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);
5302
5303 return 0;
5304}
5305
5306s32 brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg)
5307{
5308 s32 err = 0;
5309
5310 mutex_lock(&cfg->usr_sync);
5311 err = __brcmf_cfg80211_up(cfg);
5312 mutex_unlock(&cfg->usr_sync);
5313
5314 return err;
5315}
5316
5317s32 brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg)
5318{
5319 s32 err = 0;
5320
5321 mutex_lock(&cfg->usr_sync);
5322 err = __brcmf_cfg80211_down(cfg);
5323 mutex_unlock(&cfg->usr_sync);
5324
5325 return err;
5326}
5327
This page took 0.061135 seconds and 5 git commands to generate.