brcmfmac: remove use of unconditional access of struct wireless_dev::netdev
[linux-2.6/btrfs-unstable.git] / drivers / net / wireless / brcm80211 / brcmfmac / wl_cfg80211.c
blob56359e3e7eb697715e7b4e0653c0b588b8213a89
1 /*
2 * Copyright (c) 2010 Broadcom Corporation
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 /* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */
19 #include <linux/kernel.h>
20 #include <linux/etherdevice.h>
21 #include <net/cfg80211.h>
22 #include <net/netlink.h>
24 #include <brcmu_utils.h>
25 #include <defs.h>
26 #include <brcmu_wifi.h>
27 #include "dhd.h"
28 #include "dhd_dbg.h"
29 #include "tracepoint.h"
30 #include "fwil_types.h"
31 #include "p2p.h"
32 #include "wl_cfg80211.h"
33 #include "fwil.h"
35 #define BRCMF_SCAN_IE_LEN_MAX 2048
36 #define BRCMF_PNO_VERSION 2
37 #define BRCMF_PNO_TIME 30
38 #define BRCMF_PNO_REPEAT 4
39 #define BRCMF_PNO_FREQ_EXPO_MAX 3
40 #define BRCMF_PNO_MAX_PFN_COUNT 16
41 #define BRCMF_PNO_ENABLE_ADAPTSCAN_BIT 6
42 #define BRCMF_PNO_HIDDEN_BIT 2
43 #define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF
44 #define BRCMF_PNO_SCAN_COMPLETE 1
45 #define BRCMF_PNO_SCAN_INCOMPLETE 0
47 #define BRCMF_IFACE_MAX_CNT 3
49 #define WPA_OUI "\x00\x50\xF2" /* WPA OUI */
50 #define WPA_OUI_TYPE 1
51 #define RSN_OUI "\x00\x0F\xAC" /* RSN OUI */
52 #define WME_OUI_TYPE 2
53 #define WPS_OUI_TYPE 4
55 #define VS_IE_FIXED_HDR_LEN 6
56 #define WPA_IE_VERSION_LEN 2
57 #define WPA_IE_MIN_OUI_LEN 4
58 #define WPA_IE_SUITE_COUNT_LEN 2
60 #define WPA_CIPHER_NONE 0 /* None */
61 #define WPA_CIPHER_WEP_40 1 /* WEP (40-bit) */
62 #define WPA_CIPHER_TKIP 2 /* TKIP: default for WPA */
63 #define WPA_CIPHER_AES_CCM 4 /* AES (CCM) */
64 #define WPA_CIPHER_WEP_104 5 /* WEP (104-bit) */
66 #define RSN_AKM_NONE 0 /* None (IBSS) */
67 #define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */
68 #define RSN_AKM_PSK 2 /* Pre-shared Key */
69 #define RSN_CAP_LEN 2 /* Length of RSN capabilities */
70 #define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C
72 #define VNDR_IE_CMD_LEN 4 /* length of the set command
73 * string :"add", "del" (+ NUL)
75 #define VNDR_IE_COUNT_OFFSET 4
76 #define VNDR_IE_PKTFLAG_OFFSET 8
77 #define VNDR_IE_VSIE_OFFSET 12
78 #define VNDR_IE_HDR_SIZE 12
79 #define VNDR_IE_PARSE_LIMIT 5
81 #define DOT11_MGMT_HDR_LEN 24 /* d11 management header len */
82 #define DOT11_BCN_PRB_FIXED_LEN 12 /* beacon/probe fixed length */
84 #define BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS 320
85 #define BRCMF_SCAN_JOIN_PASSIVE_DWELL_TIME_MS 400
86 #define BRCMF_SCAN_JOIN_PROBE_INTERVAL_MS 20
88 #define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
89 (sizeof(struct brcmf_assoc_params_le) - sizeof(u16))
91 static bool check_vif_up(struct brcmf_cfg80211_vif *vif)
93 if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state)) {
94 brcmf_dbg(INFO, "device is not ready : status (%lu)\n",
95 vif->sme_state);
96 return false;
98 return true;
101 #define CHAN2G(_channel, _freq, _flags) { \
102 .band = IEEE80211_BAND_2GHZ, \
103 .center_freq = (_freq), \
104 .hw_value = (_channel), \
105 .flags = (_flags), \
106 .max_antenna_gain = 0, \
107 .max_power = 30, \
110 #define CHAN5G(_channel, _flags) { \
111 .band = IEEE80211_BAND_5GHZ, \
112 .center_freq = 5000 + (5 * (_channel)), \
113 .hw_value = (_channel), \
114 .flags = (_flags), \
115 .max_antenna_gain = 0, \
116 .max_power = 30, \
119 #define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
120 #define RATETAB_ENT(_rateid, _flags) \
122 .bitrate = RATE_TO_BASE100KBPS(_rateid), \
123 .hw_value = (_rateid), \
124 .flags = (_flags), \
127 static struct ieee80211_rate __wl_rates[] = {
128 RATETAB_ENT(BRCM_RATE_1M, 0),
129 RATETAB_ENT(BRCM_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
130 RATETAB_ENT(BRCM_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
131 RATETAB_ENT(BRCM_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
132 RATETAB_ENT(BRCM_RATE_6M, 0),
133 RATETAB_ENT(BRCM_RATE_9M, 0),
134 RATETAB_ENT(BRCM_RATE_12M, 0),
135 RATETAB_ENT(BRCM_RATE_18M, 0),
136 RATETAB_ENT(BRCM_RATE_24M, 0),
137 RATETAB_ENT(BRCM_RATE_36M, 0),
138 RATETAB_ENT(BRCM_RATE_48M, 0),
139 RATETAB_ENT(BRCM_RATE_54M, 0),
142 #define wl_a_rates (__wl_rates + 4)
143 #define wl_a_rates_size 8
144 #define wl_g_rates (__wl_rates + 0)
145 #define wl_g_rates_size 12
147 static struct ieee80211_channel __wl_2ghz_channels[] = {
148 CHAN2G(1, 2412, 0),
149 CHAN2G(2, 2417, 0),
150 CHAN2G(3, 2422, 0),
151 CHAN2G(4, 2427, 0),
152 CHAN2G(5, 2432, 0),
153 CHAN2G(6, 2437, 0),
154 CHAN2G(7, 2442, 0),
155 CHAN2G(8, 2447, 0),
156 CHAN2G(9, 2452, 0),
157 CHAN2G(10, 2457, 0),
158 CHAN2G(11, 2462, 0),
159 CHAN2G(12, 2467, 0),
160 CHAN2G(13, 2472, 0),
161 CHAN2G(14, 2484, 0),
164 static struct ieee80211_channel __wl_5ghz_a_channels[] = {
165 CHAN5G(34, 0), CHAN5G(36, 0),
166 CHAN5G(38, 0), CHAN5G(40, 0),
167 CHAN5G(42, 0), CHAN5G(44, 0),
168 CHAN5G(46, 0), CHAN5G(48, 0),
169 CHAN5G(52, 0), CHAN5G(56, 0),
170 CHAN5G(60, 0), CHAN5G(64, 0),
171 CHAN5G(100, 0), CHAN5G(104, 0),
172 CHAN5G(108, 0), CHAN5G(112, 0),
173 CHAN5G(116, 0), CHAN5G(120, 0),
174 CHAN5G(124, 0), CHAN5G(128, 0),
175 CHAN5G(132, 0), CHAN5G(136, 0),
176 CHAN5G(140, 0), CHAN5G(149, 0),
177 CHAN5G(153, 0), CHAN5G(157, 0),
178 CHAN5G(161, 0), CHAN5G(165, 0),
179 CHAN5G(184, 0), CHAN5G(188, 0),
180 CHAN5G(192, 0), CHAN5G(196, 0),
181 CHAN5G(200, 0), CHAN5G(204, 0),
182 CHAN5G(208, 0), CHAN5G(212, 0),
183 CHAN5G(216, 0),
186 static struct ieee80211_supported_band __wl_band_2ghz = {
187 .band = IEEE80211_BAND_2GHZ,
188 .channels = __wl_2ghz_channels,
189 .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
190 .bitrates = wl_g_rates,
191 .n_bitrates = wl_g_rates_size,
194 static struct ieee80211_supported_band __wl_band_5ghz_a = {
195 .band = IEEE80211_BAND_5GHZ,
196 .channels = __wl_5ghz_a_channels,
197 .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
198 .bitrates = wl_a_rates,
199 .n_bitrates = wl_a_rates_size,
202 /* This is to override regulatory domains defined in cfg80211 module (reg.c)
203 * By default world regulatory domain defined in reg.c puts the flags
204 * NL80211_RRF_PASSIVE_SCAN and NL80211_RRF_NO_IBSS for 5GHz channels (for
205 * 36..48 and 149..165). With respect to these flags, wpa_supplicant doesn't
206 * start p2p operations on 5GHz channels. All the changes in world regulatory
207 * domain are to be done here.
209 static const struct ieee80211_regdomain brcmf_regdom = {
210 .n_reg_rules = 4,
211 .alpha2 = "99",
212 .reg_rules = {
213 /* IEEE 802.11b/g, channels 1..11 */
214 REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
215 /* If any */
216 /* IEEE 802.11 channel 14 - Only JP enables
217 * this and for 802.11b only
219 REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
220 /* IEEE 802.11a, channel 36..64 */
221 REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
222 /* IEEE 802.11a, channel 100..165 */
223 REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
226 static const u32 __wl_cipher_suites[] = {
227 WLAN_CIPHER_SUITE_WEP40,
228 WLAN_CIPHER_SUITE_WEP104,
229 WLAN_CIPHER_SUITE_TKIP,
230 WLAN_CIPHER_SUITE_CCMP,
231 WLAN_CIPHER_SUITE_AES_CMAC,
234 /* Vendor specific ie. id = 221, oui and type defines exact ie */
235 struct brcmf_vs_tlv {
236 u8 id;
237 u8 len;
238 u8 oui[3];
239 u8 oui_type;
242 struct parsed_vndr_ie_info {
243 u8 *ie_ptr;
244 u32 ie_len; /* total length including id & length field */
245 struct brcmf_vs_tlv vndrie;
248 struct parsed_vndr_ies {
249 u32 count;
250 struct parsed_vndr_ie_info ie_info[VNDR_IE_PARSE_LIMIT];
253 /* Quarter dBm units to mW
254 * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
255 * Table is offset so the last entry is largest mW value that fits in
256 * a u16.
259 #define QDBM_OFFSET 153 /* Offset for first entry */
260 #define QDBM_TABLE_LEN 40 /* Table size */
262 /* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
263 * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
265 #define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */
267 /* Largest mW value that will round down to the last table entry,
268 * QDBM_OFFSET + QDBM_TABLE_LEN-1.
269 * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) +
270 * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
272 #define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */
274 static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
275 /* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */
276 /* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
277 /* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
278 /* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
279 /* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
280 /* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
283 static u16 brcmf_qdbm_to_mw(u8 qdbm)
285 uint factor = 1;
286 int idx = qdbm - QDBM_OFFSET;
288 if (idx >= QDBM_TABLE_LEN)
289 /* clamp to max u16 mW value */
290 return 0xFFFF;
292 /* scale the qdBm index up to the range of the table 0-40
293 * where an offset of 40 qdBm equals a factor of 10 mW.
295 while (idx < 0) {
296 idx += 40;
297 factor *= 10;
300 /* return the mW value scaled down to the correct factor of 10,
301 * adding in factor/2 to get proper rounding.
303 return (nqdBm_to_mW_map[idx] + factor / 2) / factor;
306 static u8 brcmf_mw_to_qdbm(u16 mw)
308 u8 qdbm;
309 int offset;
310 uint mw_uint = mw;
311 uint boundary;
313 /* handle boundary case */
314 if (mw_uint <= 1)
315 return 0;
317 offset = QDBM_OFFSET;
319 /* move mw into the range of the table */
320 while (mw_uint < QDBM_TABLE_LOW_BOUND) {
321 mw_uint *= 10;
322 offset -= 40;
325 for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) {
326 boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] -
327 nqdBm_to_mW_map[qdbm]) / 2;
328 if (mw_uint < boundary)
329 break;
332 qdbm += (u8) offset;
334 return qdbm;
337 u16 channel_to_chanspec(struct ieee80211_channel *ch)
339 u16 chanspec;
341 chanspec = ieee80211_frequency_to_channel(ch->center_freq);
342 chanspec &= WL_CHANSPEC_CHAN_MASK;
344 if (ch->band == IEEE80211_BAND_2GHZ)
345 chanspec |= WL_CHANSPEC_BAND_2G;
346 else
347 chanspec |= WL_CHANSPEC_BAND_5G;
349 chanspec |= WL_CHANSPEC_BW_20;
350 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
352 return chanspec;
355 /* Traverse a string of 1-byte tag/1-byte length/variable-length value
356 * triples, returning a pointer to the substring whose first element
357 * matches tag
359 struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key)
361 struct brcmf_tlv *elt;
362 int totlen;
364 elt = (struct brcmf_tlv *)buf;
365 totlen = buflen;
367 /* find tagged parameter */
368 while (totlen >= TLV_HDR_LEN) {
369 int len = elt->len;
371 /* validate remaining totlen */
372 if ((elt->id == key) && (totlen >= (len + TLV_HDR_LEN)))
373 return elt;
375 elt = (struct brcmf_tlv *)((u8 *)elt + (len + TLV_HDR_LEN));
376 totlen -= (len + TLV_HDR_LEN);
379 return NULL;
382 /* Is any of the tlvs the expected entry? If
383 * not update the tlvs buffer pointer/length.
385 static bool
386 brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len,
387 u8 *oui, u32 oui_len, u8 type)
389 /* If the contents match the OUI and the type */
390 if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
391 !memcmp(&ie[TLV_BODY_OFF], oui, oui_len) &&
392 type == ie[TLV_BODY_OFF + oui_len]) {
393 return true;
396 if (tlvs == NULL)
397 return false;
398 /* point to the next ie */
399 ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
400 /* calculate the length of the rest of the buffer */
401 *tlvs_len -= (int)(ie - *tlvs);
402 /* update the pointer to the start of the buffer */
403 *tlvs = ie;
405 return false;
408 static struct brcmf_vs_tlv *
409 brcmf_find_wpaie(u8 *parse, u32 len)
411 struct brcmf_tlv *ie;
413 while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {
414 if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len,
415 WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE))
416 return (struct brcmf_vs_tlv *)ie;
418 return NULL;
421 static struct brcmf_vs_tlv *
422 brcmf_find_wpsie(u8 *parse, u32 len)
424 struct brcmf_tlv *ie;
426 while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {
427 if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len,
428 WPA_OUI, TLV_OUI_LEN, WPS_OUI_TYPE))
429 return (struct brcmf_vs_tlv *)ie;
431 return NULL;
435 static void convert_key_from_CPU(struct brcmf_wsec_key *key,
436 struct brcmf_wsec_key_le *key_le)
438 key_le->index = cpu_to_le32(key->index);
439 key_le->len = cpu_to_le32(key->len);
440 key_le->algo = cpu_to_le32(key->algo);
441 key_le->flags = cpu_to_le32(key->flags);
442 key_le->rxiv.hi = cpu_to_le32(key->rxiv.hi);
443 key_le->rxiv.lo = cpu_to_le16(key->rxiv.lo);
444 key_le->iv_initialized = cpu_to_le32(key->iv_initialized);
445 memcpy(key_le->data, key->data, sizeof(key->data));
446 memcpy(key_le->ea, key->ea, sizeof(key->ea));
449 static int
450 send_key_to_dongle(struct net_device *ndev, struct brcmf_wsec_key *key)
452 int err;
453 struct brcmf_wsec_key_le key_le;
455 convert_key_from_CPU(key, &key_le);
457 brcmf_netdev_wait_pend8021x(ndev);
459 err = brcmf_fil_bsscfg_data_set(netdev_priv(ndev), "wsec_key", &key_le,
460 sizeof(key_le));
462 if (err)
463 brcmf_err("wsec_key error (%d)\n", err);
464 return err;
467 static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy,
468 const char *name,
469 enum nl80211_iftype type,
470 u32 *flags,
471 struct vif_params *params)
473 brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);
474 switch (type) {
475 case NL80211_IFTYPE_ADHOC:
476 case NL80211_IFTYPE_STATION:
477 case NL80211_IFTYPE_AP:
478 case NL80211_IFTYPE_AP_VLAN:
479 case NL80211_IFTYPE_WDS:
480 case NL80211_IFTYPE_MONITOR:
481 case NL80211_IFTYPE_MESH_POINT:
482 return ERR_PTR(-EOPNOTSUPP);
483 case NL80211_IFTYPE_P2P_CLIENT:
484 case NL80211_IFTYPE_P2P_GO:
485 return brcmf_p2p_add_vif(wiphy, name, type, flags, params);
486 case NL80211_IFTYPE_UNSPECIFIED:
487 case NL80211_IFTYPE_P2P_DEVICE:
488 default:
489 return ERR_PTR(-EINVAL);
493 void brcmf_set_mpc(struct net_device *ndev, int mpc)
495 struct brcmf_if *ifp = netdev_priv(ndev);
496 s32 err = 0;
498 if (check_vif_up(ifp->vif)) {
499 err = brcmf_fil_iovar_int_set(ifp, "mpc", mpc);
500 if (err) {
501 brcmf_err("fail to set mpc\n");
502 return;
504 brcmf_dbg(INFO, "MPC : %d\n", mpc);
509 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
510 struct net_device *ndev,
511 bool aborted, bool fw_abort)
513 struct brcmf_scan_params_le params_le;
514 struct cfg80211_scan_request *scan_request;
515 s32 err = 0;
517 brcmf_dbg(SCAN, "Enter\n");
519 /* clear scan request, because the FW abort can cause a second call */
520 /* to this functon and might cause a double cfg80211_scan_done */
521 scan_request = cfg->scan_request;
522 cfg->scan_request = NULL;
524 if (timer_pending(&cfg->escan_timeout))
525 del_timer_sync(&cfg->escan_timeout);
527 if (fw_abort) {
528 /* Do a scan abort to stop the driver's scan engine */
529 brcmf_dbg(SCAN, "ABORT scan in firmware\n");
530 memset(&params_le, 0, sizeof(params_le));
531 memset(params_le.bssid, 0xFF, ETH_ALEN);
532 params_le.bss_type = DOT11_BSSTYPE_ANY;
533 params_le.scan_type = 0;
534 params_le.channel_num = cpu_to_le32(1);
535 params_le.nprobes = cpu_to_le32(1);
536 params_le.active_time = cpu_to_le32(-1);
537 params_le.passive_time = cpu_to_le32(-1);
538 params_le.home_time = cpu_to_le32(-1);
539 /* Scan is aborted by setting channel_list[0] to -1 */
540 params_le.channel_list[0] = cpu_to_le16(-1);
541 /* E-Scan (or anyother type) can be aborted by SCAN */
542 err = brcmf_fil_cmd_data_set(netdev_priv(ndev), BRCMF_C_SCAN,
543 &params_le, sizeof(params_le));
544 if (err)
545 brcmf_err("Scan abort failed\n");
548 * e-scan can be initiated by scheduled scan
549 * which takes precedence.
551 if (cfg->sched_escan) {
552 brcmf_dbg(SCAN, "scheduled scan completed\n");
553 cfg->sched_escan = false;
554 if (!aborted)
555 cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
556 brcmf_set_mpc(ndev, 1);
557 } else if (scan_request) {
558 brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n",
559 aborted ? "Aborted" : "Done");
560 cfg80211_scan_done(scan_request, aborted);
561 brcmf_set_mpc(ndev, 1);
563 if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status))
564 brcmf_dbg(SCAN, "Scan complete, probably P2P scan\n");
566 return err;
569 static
570 int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
572 struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
573 struct net_device *ndev = wdev->netdev;
575 /* vif event pending in firmware */
576 if (brcmf_cfg80211_vif_event_armed(cfg))
577 return -EBUSY;
579 if (ndev) {
580 if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status) &&
581 cfg->escan_info.ndev == ndev)
582 brcmf_notify_escan_complete(cfg, ndev, true,
583 true);
585 brcmf_fil_iovar_int_set(netdev_priv(ndev), "mpc", 1);
588 switch (wdev->iftype) {
589 case NL80211_IFTYPE_ADHOC:
590 case NL80211_IFTYPE_STATION:
591 case NL80211_IFTYPE_AP:
592 case NL80211_IFTYPE_AP_VLAN:
593 case NL80211_IFTYPE_WDS:
594 case NL80211_IFTYPE_MONITOR:
595 case NL80211_IFTYPE_MESH_POINT:
596 return -EOPNOTSUPP;
597 case NL80211_IFTYPE_P2P_CLIENT:
598 case NL80211_IFTYPE_P2P_GO:
599 return brcmf_p2p_del_vif(wiphy, wdev);
600 case NL80211_IFTYPE_UNSPECIFIED:
601 case NL80211_IFTYPE_P2P_DEVICE:
602 default:
603 return -EINVAL;
605 return -EOPNOTSUPP;
608 static s32
609 brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
610 enum nl80211_iftype type, u32 *flags,
611 struct vif_params *params)
613 struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
614 struct brcmf_if *ifp = netdev_priv(ndev);
615 struct brcmf_cfg80211_vif *vif = ifp->vif;
616 s32 infra = 0;
617 s32 ap = 0;
618 s32 err = 0;
620 brcmf_dbg(TRACE, "Enter, ndev=%p, type=%d\n", ndev, type);
622 switch (type) {
623 case NL80211_IFTYPE_MONITOR:
624 case NL80211_IFTYPE_WDS:
625 brcmf_err("type (%d) : currently we do not support this type\n",
626 type);
627 return -EOPNOTSUPP;
628 case NL80211_IFTYPE_ADHOC:
629 vif->mode = WL_MODE_IBSS;
630 infra = 0;
631 break;
632 case NL80211_IFTYPE_STATION:
633 /* Ignore change for p2p IF. Unclear why supplicant does this */
634 if ((vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ||
635 (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) {
636 brcmf_dbg(TRACE, "Ignoring cmd for p2p if\n");
637 /* WAR: It is unexpected to get a change of VIF for P2P
638 * IF, but it happens. The request can not be handled
639 * but returning EPERM causes a crash. Returning 0
640 * without setting ieee80211_ptr->iftype causes trace
641 * (WARN_ON) but it works with wpa_supplicant
643 return 0;
645 vif->mode = WL_MODE_BSS;
646 infra = 1;
647 break;
648 case NL80211_IFTYPE_AP:
649 case NL80211_IFTYPE_P2P_GO:
650 vif->mode = WL_MODE_AP;
651 ap = 1;
652 break;
653 default:
654 err = -EINVAL;
655 goto done;
658 if (ap) {
659 if (type == NL80211_IFTYPE_P2P_GO) {
660 brcmf_dbg(INFO, "IF Type = P2P GO\n");
661 err = brcmf_p2p_ifchange(cfg, BRCMF_FIL_P2P_IF_GO);
663 if (!err) {
664 set_bit(BRCMF_VIF_STATUS_AP_CREATING, &vif->sme_state);
665 brcmf_dbg(INFO, "IF Type = AP\n");
667 } else {
668 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, infra);
669 if (err) {
670 brcmf_err("WLC_SET_INFRA error (%d)\n", err);
671 err = -EAGAIN;
672 goto done;
674 brcmf_dbg(INFO, "IF Type = %s\n", (vif->mode == WL_MODE_IBSS) ?
675 "Adhoc" : "Infra");
677 ndev->ieee80211_ptr->iftype = type;
679 done:
680 brcmf_dbg(TRACE, "Exit\n");
682 return err;
685 static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
686 struct cfg80211_scan_request *request)
688 u32 n_ssids;
689 u32 n_channels;
690 s32 i;
691 s32 offset;
692 u16 chanspec;
693 char *ptr;
694 struct brcmf_ssid_le ssid_le;
696 memset(params_le->bssid, 0xFF, ETH_ALEN);
697 params_le->bss_type = DOT11_BSSTYPE_ANY;
698 params_le->scan_type = 0;
699 params_le->channel_num = 0;
700 params_le->nprobes = cpu_to_le32(-1);
701 params_le->active_time = cpu_to_le32(-1);
702 params_le->passive_time = cpu_to_le32(-1);
703 params_le->home_time = cpu_to_le32(-1);
704 memset(&params_le->ssid_le, 0, sizeof(params_le->ssid_le));
706 /* if request is null exit so it will be all channel broadcast scan */
707 if (!request)
708 return;
710 n_ssids = request->n_ssids;
711 n_channels = request->n_channels;
712 /* Copy channel array if applicable */
713 brcmf_dbg(SCAN, "### List of channelspecs to scan ### %d\n",
714 n_channels);
715 if (n_channels > 0) {
716 for (i = 0; i < n_channels; i++) {
717 chanspec = channel_to_chanspec(request->channels[i]);
718 brcmf_dbg(SCAN, "Chan : %d, Channel spec: %x\n",
719 request->channels[i]->hw_value, chanspec);
720 params_le->channel_list[i] = cpu_to_le16(chanspec);
722 } else {
723 brcmf_dbg(SCAN, "Scanning all channels\n");
725 /* Copy ssid array if applicable */
726 brcmf_dbg(SCAN, "### List of SSIDs to scan ### %d\n", n_ssids);
727 if (n_ssids > 0) {
728 offset = offsetof(struct brcmf_scan_params_le, channel_list) +
729 n_channels * sizeof(u16);
730 offset = roundup(offset, sizeof(u32));
731 ptr = (char *)params_le + offset;
732 for (i = 0; i < n_ssids; i++) {
733 memset(&ssid_le, 0, sizeof(ssid_le));
734 ssid_le.SSID_len =
735 cpu_to_le32(request->ssids[i].ssid_len);
736 memcpy(ssid_le.SSID, request->ssids[i].ssid,
737 request->ssids[i].ssid_len);
738 if (!ssid_le.SSID_len)
739 brcmf_dbg(SCAN, "%d: Broadcast scan\n", i);
740 else
741 brcmf_dbg(SCAN, "%d: scan for %s size =%d\n",
742 i, ssid_le.SSID, ssid_le.SSID_len);
743 memcpy(ptr, &ssid_le, sizeof(ssid_le));
744 ptr += sizeof(ssid_le);
746 } else {
747 brcmf_dbg(SCAN, "Broadcast scan %p\n", request->ssids);
748 if ((request->ssids) && request->ssids->ssid_len) {
749 brcmf_dbg(SCAN, "SSID %s len=%d\n",
750 params_le->ssid_le.SSID,
751 request->ssids->ssid_len);
752 params_le->ssid_le.SSID_len =
753 cpu_to_le32(request->ssids->ssid_len);
754 memcpy(&params_le->ssid_le.SSID, request->ssids->ssid,
755 request->ssids->ssid_len);
758 /* Adding mask to channel numbers */
759 params_le->channel_num =
760 cpu_to_le32((n_ssids << BRCMF_SCAN_PARAMS_NSSID_SHIFT) |
761 (n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK));
764 static s32
765 brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev,
766 struct cfg80211_scan_request *request, u16 action)
768 s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
769 offsetof(struct brcmf_escan_params_le, params_le);
770 struct brcmf_escan_params_le *params;
771 s32 err = 0;
773 brcmf_dbg(SCAN, "E-SCAN START\n");
775 if (request != NULL) {
776 /* Allocate space for populating ssids in struct */
777 params_size += sizeof(u32) * ((request->n_channels + 1) / 2);
779 /* Allocate space for populating ssids in struct */
780 params_size += sizeof(struct brcmf_ssid) * request->n_ssids;
783 params = kzalloc(params_size, GFP_KERNEL);
784 if (!params) {
785 err = -ENOMEM;
786 goto exit;
788 BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN);
789 brcmf_escan_prep(&params->params_le, request);
790 params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
791 params->action = cpu_to_le16(action);
792 params->sync_id = cpu_to_le16(0x1234);
794 err = brcmf_fil_iovar_data_set(netdev_priv(ndev), "escan",
795 params, params_size);
796 if (err) {
797 if (err == -EBUSY)
798 brcmf_dbg(INFO, "system busy : escan canceled\n");
799 else
800 brcmf_err("error (%d)\n", err);
803 kfree(params);
804 exit:
805 return err;
808 static s32
809 brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy,
810 struct net_device *ndev, struct cfg80211_scan_request *request)
812 s32 err;
813 u32 passive_scan;
814 struct brcmf_scan_results *results;
815 struct escan_info *escan = &cfg->escan_info;
817 brcmf_dbg(SCAN, "Enter\n");
818 escan->ndev = ndev;
819 escan->wiphy = wiphy;
820 escan->escan_state = WL_ESCAN_STATE_SCANNING;
821 passive_scan = cfg->active_scan ? 0 : 1;
822 err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PASSIVE_SCAN,
823 passive_scan);
824 if (err) {
825 brcmf_err("error (%d)\n", err);
826 return err;
828 brcmf_set_mpc(ndev, 0);
829 results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf;
830 results->version = 0;
831 results->count = 0;
832 results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE;
834 err = escan->run(cfg, ndev, request, WL_ESCAN_ACTION_START);
835 if (err)
836 brcmf_set_mpc(ndev, 1);
837 return err;
840 static s32
841 brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev,
842 struct cfg80211_scan_request *request,
843 struct cfg80211_ssid *this_ssid)
845 struct brcmf_if *ifp = netdev_priv(ndev);
846 struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev);
847 struct cfg80211_ssid *ssids;
848 struct brcmf_cfg80211_scan_req *sr = &cfg->scan_req_int;
849 u32 passive_scan;
850 bool escan_req;
851 bool spec_scan;
852 s32 err;
853 u32 SSID_len;
855 brcmf_dbg(SCAN, "START ESCAN\n");
857 if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
858 brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
859 return -EAGAIN;
861 if (test_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status)) {
862 brcmf_err("Scanning being aborted: status (%lu)\n",
863 cfg->scan_status);
864 return -EAGAIN;
866 if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) {
867 brcmf_err("Connecting: status (%lu)\n", ifp->vif->sme_state);
868 return -EAGAIN;
871 /* If scan req comes for p2p0, send it over primary I/F */
872 if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) {
873 ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
874 ndev = ifp->ndev;
877 /* Arm scan timeout timer */
878 mod_timer(&cfg->escan_timeout, jiffies +
879 WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000);
881 escan_req = false;
882 if (request) {
883 /* scan bss */
884 ssids = request->ssids;
885 escan_req = true;
886 } else {
887 /* scan in ibss */
888 /* we don't do escan in ibss */
889 ssids = this_ssid;
892 cfg->scan_request = request;
893 set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
894 if (escan_req) {
895 cfg->escan_info.run = brcmf_run_escan;
896 err = brcmf_p2p_scan_prep(wiphy, request, ifp->vif);
897 if (err)
898 goto scan_out;
900 err = brcmf_do_escan(cfg, wiphy, ndev, request);
901 if (err)
902 goto scan_out;
903 } else {
904 brcmf_dbg(SCAN, "ssid \"%s\", ssid_len (%d)\n",
905 ssids->ssid, ssids->ssid_len);
906 memset(&sr->ssid_le, 0, sizeof(sr->ssid_le));
907 SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len);
908 sr->ssid_le.SSID_len = cpu_to_le32(0);
909 spec_scan = false;
910 if (SSID_len) {
911 memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len);
912 sr->ssid_le.SSID_len = cpu_to_le32(SSID_len);
913 spec_scan = true;
914 } else
915 brcmf_dbg(SCAN, "Broadcast scan\n");
917 passive_scan = cfg->active_scan ? 0 : 1;
918 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN,
919 passive_scan);
920 if (err) {
921 brcmf_err("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
922 goto scan_out;
924 brcmf_set_mpc(ndev, 0);
925 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
926 &sr->ssid_le, sizeof(sr->ssid_le));
927 if (err) {
928 if (err == -EBUSY)
929 brcmf_dbg(INFO, "BUSY: scan for \"%s\" canceled\n",
930 sr->ssid_le.SSID);
931 else
932 brcmf_err("WLC_SCAN error (%d)\n", err);
934 brcmf_set_mpc(ndev, 1);
935 goto scan_out;
939 return 0;
941 scan_out:
942 clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
943 if (timer_pending(&cfg->escan_timeout))
944 del_timer_sync(&cfg->escan_timeout);
945 cfg->scan_request = NULL;
946 return err;
949 static s32
950 brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
952 struct net_device *ndev = request->wdev->netdev;
953 s32 err = 0;
955 brcmf_dbg(TRACE, "Enter\n");
957 if (!check_vif_up(container_of(request->wdev,
958 struct brcmf_cfg80211_vif, wdev)))
959 return -EIO;
961 err = brcmf_cfg80211_escan(wiphy, ndev, request, NULL);
963 if (err)
964 brcmf_err("scan error (%d)\n", err);
966 brcmf_dbg(TRACE, "Exit\n");
967 return err;
970 static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold)
972 s32 err = 0;
974 err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "rtsthresh",
975 rts_threshold);
976 if (err)
977 brcmf_err("Error (%d)\n", err);
979 return err;
982 static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold)
984 s32 err = 0;
986 err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "fragthresh",
987 frag_threshold);
988 if (err)
989 brcmf_err("Error (%d)\n", err);
991 return err;
994 static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l)
996 s32 err = 0;
997 u32 cmd = (l ? BRCMF_C_SET_LRL : BRCMF_C_SET_SRL);
999 err = brcmf_fil_cmd_int_set(netdev_priv(ndev), cmd, retry);
1000 if (err) {
1001 brcmf_err("cmd (%d) , error (%d)\n", cmd, err);
1002 return err;
1004 return err;
1007 static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1009 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
1010 struct net_device *ndev = cfg_to_ndev(cfg);
1011 struct brcmf_if *ifp = netdev_priv(ndev);
1012 s32 err = 0;
1014 brcmf_dbg(TRACE, "Enter\n");
1015 if (!check_vif_up(ifp->vif))
1016 return -EIO;
1018 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
1019 (cfg->conf->rts_threshold != wiphy->rts_threshold)) {
1020 cfg->conf->rts_threshold = wiphy->rts_threshold;
1021 err = brcmf_set_rts(ndev, cfg->conf->rts_threshold);
1022 if (!err)
1023 goto done;
1025 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
1026 (cfg->conf->frag_threshold != wiphy->frag_threshold)) {
1027 cfg->conf->frag_threshold = wiphy->frag_threshold;
1028 err = brcmf_set_frag(ndev, cfg->conf->frag_threshold);
1029 if (!err)
1030 goto done;
1032 if (changed & WIPHY_PARAM_RETRY_LONG
1033 && (cfg->conf->retry_long != wiphy->retry_long)) {
1034 cfg->conf->retry_long = wiphy->retry_long;
1035 err = brcmf_set_retry(ndev, cfg->conf->retry_long, true);
1036 if (!err)
1037 goto done;
1039 if (changed & WIPHY_PARAM_RETRY_SHORT
1040 && (cfg->conf->retry_short != wiphy->retry_short)) {
1041 cfg->conf->retry_short = wiphy->retry_short;
1042 err = brcmf_set_retry(ndev, cfg->conf->retry_short, false);
1043 if (!err)
1044 goto done;
1047 done:
1048 brcmf_dbg(TRACE, "Exit\n");
1049 return err;
1052 static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
1054 memset(prof, 0, sizeof(*prof));
1057 static void brcmf_link_down(struct brcmf_cfg80211_vif *vif)
1059 s32 err = 0;
1061 brcmf_dbg(TRACE, "Enter\n");
1063 if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state)) {
1064 brcmf_dbg(INFO, "Call WLC_DISASSOC to stop excess roaming\n ");
1065 err = brcmf_fil_cmd_data_set(vif->ifp,
1066 BRCMF_C_DISASSOC, NULL, 0);
1067 if (err)
1068 brcmf_err("WLC_DISASSOC failed (%d)\n", err);
1069 clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state);
1071 clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state);
1072 brcmf_dbg(TRACE, "Exit\n");
1075 static s32
1076 brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
1077 struct cfg80211_ibss_params *params)
1079 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
1080 struct brcmf_if *ifp = netdev_priv(ndev);
1081 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
1082 struct brcmf_join_params join_params;
1083 size_t join_params_size = 0;
1084 s32 err = 0;
1085 s32 wsec = 0;
1086 s32 bcnprd;
1087 u16 chanspec;
1089 brcmf_dbg(TRACE, "Enter\n");
1090 if (!check_vif_up(ifp->vif))
1091 return -EIO;
1093 if (params->ssid)
1094 brcmf_dbg(CONN, "SSID: %s\n", params->ssid);
1095 else {
1096 brcmf_dbg(CONN, "SSID: NULL, Not supported\n");
1097 return -EOPNOTSUPP;
1100 set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
1102 if (params->bssid)
1103 brcmf_dbg(CONN, "BSSID: %pM\n", params->bssid);
1104 else
1105 brcmf_dbg(CONN, "No BSSID specified\n");
1107 if (params->chandef.chan)
1108 brcmf_dbg(CONN, "channel: %d\n",
1109 params->chandef.chan->center_freq);
1110 else
1111 brcmf_dbg(CONN, "no channel specified\n");
1113 if (params->channel_fixed)
1114 brcmf_dbg(CONN, "fixed channel required\n");
1115 else
1116 brcmf_dbg(CONN, "no fixed channel required\n");
1118 if (params->ie && params->ie_len)
1119 brcmf_dbg(CONN, "ie len: %d\n", params->ie_len);
1120 else
1121 brcmf_dbg(CONN, "no ie specified\n");
1123 if (params->beacon_interval)
1124 brcmf_dbg(CONN, "beacon interval: %d\n",
1125 params->beacon_interval);
1126 else
1127 brcmf_dbg(CONN, "no beacon interval specified\n");
1129 if (params->basic_rates)
1130 brcmf_dbg(CONN, "basic rates: %08X\n", params->basic_rates);
1131 else
1132 brcmf_dbg(CONN, "no basic rates specified\n");
1134 if (params->privacy)
1135 brcmf_dbg(CONN, "privacy required\n");
1136 else
1137 brcmf_dbg(CONN, "no privacy required\n");
1139 /* Configure Privacy for starter */
1140 if (params->privacy)
1141 wsec |= WEP_ENABLED;
1143 err = brcmf_fil_iovar_int_set(ifp, "wsec", wsec);
1144 if (err) {
1145 brcmf_err("wsec failed (%d)\n", err);
1146 goto done;
1149 /* Configure Beacon Interval for starter */
1150 if (params->beacon_interval)
1151 bcnprd = params->beacon_interval;
1152 else
1153 bcnprd = 100;
1155 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD, bcnprd);
1156 if (err) {
1157 brcmf_err("WLC_SET_BCNPRD failed (%d)\n", err);
1158 goto done;
1161 /* Configure required join parameter */
1162 memset(&join_params, 0, sizeof(struct brcmf_join_params));
1164 /* SSID */
1165 profile->ssid.SSID_len = min_t(u32, params->ssid_len, 32);
1166 memcpy(profile->ssid.SSID, params->ssid, profile->ssid.SSID_len);
1167 memcpy(join_params.ssid_le.SSID, params->ssid, profile->ssid.SSID_len);
1168 join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len);
1169 join_params_size = sizeof(join_params.ssid_le);
1171 /* BSSID */
1172 if (params->bssid) {
1173 memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN);
1174 join_params_size = sizeof(join_params.ssid_le) +
1175 BRCMF_ASSOC_PARAMS_FIXED_SIZE;
1176 memcpy(profile->bssid, params->bssid, ETH_ALEN);
1177 } else {
1178 memset(join_params.params_le.bssid, 0xFF, ETH_ALEN);
1179 memset(profile->bssid, 0, ETH_ALEN);
1182 /* Channel */
1183 if (params->chandef.chan) {
1184 u32 target_channel;
1186 cfg->channel =
1187 ieee80211_frequency_to_channel(
1188 params->chandef.chan->center_freq);
1189 if (params->channel_fixed) {
1190 /* adding chanspec */
1191 chanspec = channel_to_chanspec(params->chandef.chan);
1192 join_params.params_le.chanspec_list[0] =
1193 cpu_to_le16(chanspec);
1194 join_params.params_le.chanspec_num = cpu_to_le32(1);
1195 join_params_size += sizeof(join_params.params_le);
1198 /* set channel for starter */
1199 target_channel = cfg->channel;
1200 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_CHANNEL,
1201 target_channel);
1202 if (err) {
1203 brcmf_err("WLC_SET_CHANNEL failed (%d)\n", err);
1204 goto done;
1206 } else
1207 cfg->channel = 0;
1209 cfg->ibss_starter = false;
1212 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
1213 &join_params, join_params_size);
1214 if (err) {
1215 brcmf_err("WLC_SET_SSID failed (%d)\n", err);
1216 goto done;
1219 done:
1220 if (err)
1221 clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
1222 brcmf_dbg(TRACE, "Exit\n");
1223 return err;
1226 static s32
1227 brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
1229 struct brcmf_if *ifp = netdev_priv(ndev);
1230 s32 err = 0;
1232 brcmf_dbg(TRACE, "Enter\n");
1233 if (!check_vif_up(ifp->vif))
1234 return -EIO;
1236 brcmf_link_down(ifp->vif);
1238 brcmf_dbg(TRACE, "Exit\n");
1240 return err;
1243 static s32 brcmf_set_wpa_version(struct net_device *ndev,
1244 struct cfg80211_connect_params *sme)
1246 struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
1247 struct brcmf_cfg80211_security *sec;
1248 s32 val = 0;
1249 s32 err = 0;
1251 if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1252 val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
1253 else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1254 val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
1255 else
1256 val = WPA_AUTH_DISABLED;
1257 brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
1258 err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val);
1259 if (err) {
1260 brcmf_err("set wpa_auth failed (%d)\n", err);
1261 return err;
1263 sec = &profile->sec;
1264 sec->wpa_versions = sme->crypto.wpa_versions;
1265 return err;
1268 static s32 brcmf_set_auth_type(struct net_device *ndev,
1269 struct cfg80211_connect_params *sme)
1271 struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
1272 struct brcmf_cfg80211_security *sec;
1273 s32 val = 0;
1274 s32 err = 0;
1276 switch (sme->auth_type) {
1277 case NL80211_AUTHTYPE_OPEN_SYSTEM:
1278 val = 0;
1279 brcmf_dbg(CONN, "open system\n");
1280 break;
1281 case NL80211_AUTHTYPE_SHARED_KEY:
1282 val = 1;
1283 brcmf_dbg(CONN, "shared key\n");
1284 break;
1285 case NL80211_AUTHTYPE_AUTOMATIC:
1286 val = 2;
1287 brcmf_dbg(CONN, "automatic\n");
1288 break;
1289 case NL80211_AUTHTYPE_NETWORK_EAP:
1290 brcmf_dbg(CONN, "network eap\n");
1291 default:
1292 val = 2;
1293 brcmf_err("invalid auth type (%d)\n", sme->auth_type);
1294 break;
1297 err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "auth", val);
1298 if (err) {
1299 brcmf_err("set auth failed (%d)\n", err);
1300 return err;
1302 sec = &profile->sec;
1303 sec->auth_type = sme->auth_type;
1304 return err;
1307 static s32
1308 brcmf_set_set_cipher(struct net_device *ndev,
1309 struct cfg80211_connect_params *sme)
1311 struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
1312 struct brcmf_cfg80211_security *sec;
1313 s32 pval = 0;
1314 s32 gval = 0;
1315 s32 err = 0;
1317 if (sme->crypto.n_ciphers_pairwise) {
1318 switch (sme->crypto.ciphers_pairwise[0]) {
1319 case WLAN_CIPHER_SUITE_WEP40:
1320 case WLAN_CIPHER_SUITE_WEP104:
1321 pval = WEP_ENABLED;
1322 break;
1323 case WLAN_CIPHER_SUITE_TKIP:
1324 pval = TKIP_ENABLED;
1325 break;
1326 case WLAN_CIPHER_SUITE_CCMP:
1327 pval = AES_ENABLED;
1328 break;
1329 case WLAN_CIPHER_SUITE_AES_CMAC:
1330 pval = AES_ENABLED;
1331 break;
1332 default:
1333 brcmf_err("invalid cipher pairwise (%d)\n",
1334 sme->crypto.ciphers_pairwise[0]);
1335 return -EINVAL;
1338 if (sme->crypto.cipher_group) {
1339 switch (sme->crypto.cipher_group) {
1340 case WLAN_CIPHER_SUITE_WEP40:
1341 case WLAN_CIPHER_SUITE_WEP104:
1342 gval = WEP_ENABLED;
1343 break;
1344 case WLAN_CIPHER_SUITE_TKIP:
1345 gval = TKIP_ENABLED;
1346 break;
1347 case WLAN_CIPHER_SUITE_CCMP:
1348 gval = AES_ENABLED;
1349 break;
1350 case WLAN_CIPHER_SUITE_AES_CMAC:
1351 gval = AES_ENABLED;
1352 break;
1353 default:
1354 brcmf_err("invalid cipher group (%d)\n",
1355 sme->crypto.cipher_group);
1356 return -EINVAL;
1360 brcmf_dbg(CONN, "pval (%d) gval (%d)\n", pval, gval);
1361 /* In case of privacy, but no security and WPS then simulate */
1362 /* setting AES. WPS-2.0 allows no security */
1363 if (brcmf_find_wpsie(sme->ie, sme->ie_len) && !pval && !gval &&
1364 sme->privacy)
1365 pval = AES_ENABLED;
1366 err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wsec", pval | gval);
1367 if (err) {
1368 brcmf_err("error (%d)\n", err);
1369 return err;
1372 sec = &profile->sec;
1373 sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
1374 sec->cipher_group = sme->crypto.cipher_group;
1376 return err;
1379 static s32
1380 brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
1382 struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
1383 struct brcmf_cfg80211_security *sec;
1384 s32 val = 0;
1385 s32 err = 0;
1387 if (sme->crypto.n_akm_suites) {
1388 err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev),
1389 "wpa_auth", &val);
1390 if (err) {
1391 brcmf_err("could not get wpa_auth (%d)\n", err);
1392 return err;
1394 if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
1395 switch (sme->crypto.akm_suites[0]) {
1396 case WLAN_AKM_SUITE_8021X:
1397 val = WPA_AUTH_UNSPECIFIED;
1398 break;
1399 case WLAN_AKM_SUITE_PSK:
1400 val = WPA_AUTH_PSK;
1401 break;
1402 default:
1403 brcmf_err("invalid cipher group (%d)\n",
1404 sme->crypto.cipher_group);
1405 return -EINVAL;
1407 } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
1408 switch (sme->crypto.akm_suites[0]) {
1409 case WLAN_AKM_SUITE_8021X:
1410 val = WPA2_AUTH_UNSPECIFIED;
1411 break;
1412 case WLAN_AKM_SUITE_PSK:
1413 val = WPA2_AUTH_PSK;
1414 break;
1415 default:
1416 brcmf_err("invalid cipher group (%d)\n",
1417 sme->crypto.cipher_group);
1418 return -EINVAL;
1422 brcmf_dbg(CONN, "setting wpa_auth to %d\n", val);
1423 err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev),
1424 "wpa_auth", val);
1425 if (err) {
1426 brcmf_err("could not set wpa_auth (%d)\n", err);
1427 return err;
1430 sec = &profile->sec;
1431 sec->wpa_auth = sme->crypto.akm_suites[0];
1433 return err;
1436 static s32
1437 brcmf_set_sharedkey(struct net_device *ndev,
1438 struct cfg80211_connect_params *sme)
1440 struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);
1441 struct brcmf_cfg80211_security *sec;
1442 struct brcmf_wsec_key key;
1443 s32 val;
1444 s32 err = 0;
1446 brcmf_dbg(CONN, "key len (%d)\n", sme->key_len);
1448 if (sme->key_len == 0)
1449 return 0;
1451 sec = &profile->sec;
1452 brcmf_dbg(CONN, "wpa_versions 0x%x cipher_pairwise 0x%x\n",
1453 sec->wpa_versions, sec->cipher_pairwise);
1455 if (sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))
1456 return 0;
1458 if (!(sec->cipher_pairwise &
1459 (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104)))
1460 return 0;
1462 memset(&key, 0, sizeof(key));
1463 key.len = (u32) sme->key_len;
1464 key.index = (u32) sme->key_idx;
1465 if (key.len > sizeof(key.data)) {
1466 brcmf_err("Too long key length (%u)\n", key.len);
1467 return -EINVAL;
1469 memcpy(key.data, sme->key, key.len);
1470 key.flags = BRCMF_PRIMARY_KEY;
1471 switch (sec->cipher_pairwise) {
1472 case WLAN_CIPHER_SUITE_WEP40:
1473 key.algo = CRYPTO_ALGO_WEP1;
1474 break;
1475 case WLAN_CIPHER_SUITE_WEP104:
1476 key.algo = CRYPTO_ALGO_WEP128;
1477 break;
1478 default:
1479 brcmf_err("Invalid algorithm (%d)\n",
1480 sme->crypto.ciphers_pairwise[0]);
1481 return -EINVAL;
1483 /* Set the new key/index */
1484 brcmf_dbg(CONN, "key length (%d) key index (%d) algo (%d)\n",
1485 key.len, key.index, key.algo);
1486 brcmf_dbg(CONN, "key \"%s\"\n", key.data);
1487 err = send_key_to_dongle(ndev, &key);
1488 if (err)
1489 return err;
1491 if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
1492 brcmf_dbg(CONN, "set auth_type to shared key\n");
1493 val = WL_AUTH_SHARED_KEY; /* shared key */
1494 err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "auth", val);
1495 if (err)
1496 brcmf_err("set auth failed (%d)\n", err);
1498 return err;
1501 static
1502 enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp,
1503 enum nl80211_auth_type type)
1505 u32 ci;
1506 if (type == NL80211_AUTHTYPE_AUTOMATIC) {
1507 /* shift to ignore chip revision */
1508 ci = brcmf_get_chip_info(ifp) >> 4;
1509 switch (ci) {
1510 case 43236:
1511 brcmf_dbg(CONN, "43236 WAR: use OPEN instead of AUTO\n");
1512 return NL80211_AUTHTYPE_OPEN_SYSTEM;
1513 default:
1514 break;
1517 return type;
1520 static s32
1521 brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
1522 struct cfg80211_connect_params *sme)
1524 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
1525 struct brcmf_if *ifp = netdev_priv(ndev);
1526 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
1527 struct ieee80211_channel *chan = sme->channel;
1528 struct brcmf_join_params join_params;
1529 size_t join_params_size;
1530 struct brcmf_tlv *rsn_ie;
1531 struct brcmf_vs_tlv *wpa_ie;
1532 void *ie;
1533 u32 ie_len;
1534 struct brcmf_ext_join_params_le *ext_join_params;
1535 u16 chanspec;
1537 s32 err = 0;
1539 brcmf_dbg(TRACE, "Enter\n");
1540 if (!check_vif_up(ifp->vif))
1541 return -EIO;
1543 if (!sme->ssid) {
1544 brcmf_err("Invalid ssid\n");
1545 return -EOPNOTSUPP;
1548 if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif) {
1549 /* A normal (non P2P) connection request setup. */
1550 ie = NULL;
1551 ie_len = 0;
1552 /* find the WPA_IE */
1553 wpa_ie = brcmf_find_wpaie((u8 *)sme->ie, sme->ie_len);
1554 if (wpa_ie) {
1555 ie = wpa_ie;
1556 ie_len = wpa_ie->len + TLV_HDR_LEN;
1557 } else {
1558 /* find the RSN_IE */
1559 rsn_ie = brcmf_parse_tlvs((u8 *)sme->ie, sme->ie_len,
1560 WLAN_EID_RSN);
1561 if (rsn_ie) {
1562 ie = rsn_ie;
1563 ie_len = rsn_ie->len + TLV_HDR_LEN;
1566 brcmf_fil_iovar_data_set(ifp, "wpaie", ie, ie_len);
1569 err = brcmf_vif_set_mgmt_ie(ifp->vif, BRCMF_VNDR_IE_ASSOCREQ_FLAG,
1570 sme->ie, sme->ie_len);
1571 if (err)
1572 brcmf_err("Set Assoc REQ IE Failed\n");
1573 else
1574 brcmf_dbg(TRACE, "Applied Vndr IEs for Assoc request\n");
1576 set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
1578 if (chan) {
1579 cfg->channel =
1580 ieee80211_frequency_to_channel(chan->center_freq);
1581 chanspec = channel_to_chanspec(chan);
1582 brcmf_dbg(CONN, "channel=%d, center_req=%d, chanspec=0x%04x\n",
1583 cfg->channel, chan->center_freq, chanspec);
1584 } else {
1585 cfg->channel = 0;
1586 chanspec = 0;
1589 brcmf_dbg(INFO, "ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);
1591 err = brcmf_set_wpa_version(ndev, sme);
1592 if (err) {
1593 brcmf_err("wl_set_wpa_version failed (%d)\n", err);
1594 goto done;
1597 sme->auth_type = brcmf_war_auth_type(ifp, sme->auth_type);
1598 err = brcmf_set_auth_type(ndev, sme);
1599 if (err) {
1600 brcmf_err("wl_set_auth_type failed (%d)\n", err);
1601 goto done;
1604 err = brcmf_set_set_cipher(ndev, sme);
1605 if (err) {
1606 brcmf_err("wl_set_set_cipher failed (%d)\n", err);
1607 goto done;
1610 err = brcmf_set_key_mgmt(ndev, sme);
1611 if (err) {
1612 brcmf_err("wl_set_key_mgmt failed (%d)\n", err);
1613 goto done;
1616 err = brcmf_set_sharedkey(ndev, sme);
1617 if (err) {
1618 brcmf_err("brcmf_set_sharedkey failed (%d)\n", err);
1619 goto done;
1622 profile->ssid.SSID_len = min_t(u32, (u32)sizeof(profile->ssid.SSID),
1623 (u32)sme->ssid_len);
1624 memcpy(&profile->ssid.SSID, sme->ssid, profile->ssid.SSID_len);
1625 if (profile->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
1626 profile->ssid.SSID[profile->ssid.SSID_len] = 0;
1627 brcmf_dbg(CONN, "SSID \"%s\", len (%d)\n", profile->ssid.SSID,
1628 profile->ssid.SSID_len);
1631 /* Join with specific BSSID and cached SSID
1632 * If SSID is zero join based on BSSID only
1634 join_params_size = offsetof(struct brcmf_ext_join_params_le, assoc_le) +
1635 offsetof(struct brcmf_assoc_params_le, chanspec_list);
1636 if (cfg->channel)
1637 join_params_size += sizeof(u16);
1638 ext_join_params = kzalloc(join_params_size, GFP_KERNEL);
1639 if (ext_join_params == NULL) {
1640 err = -ENOMEM;
1641 goto done;
1643 ext_join_params->ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len);
1644 memcpy(&ext_join_params->ssid_le.SSID, sme->ssid,
1645 profile->ssid.SSID_len);
1646 /*increase dwell time to receive probe response or detect Beacon
1647 * from target AP at a noisy air only during connect command
1649 ext_join_params->scan_le.active_time =
1650 cpu_to_le32(BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS);
1651 ext_join_params->scan_le.passive_time =
1652 cpu_to_le32(BRCMF_SCAN_JOIN_PASSIVE_DWELL_TIME_MS);
1653 /* Set up join scan parameters */
1654 ext_join_params->scan_le.scan_type = -1;
1655 /* to sync with presence period of VSDB GO.
1656 * Send probe request more frequently. Probe request will be stopped
1657 * when it gets probe response from target AP/GO.
1659 ext_join_params->scan_le.nprobes =
1660 cpu_to_le32(BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS /
1661 BRCMF_SCAN_JOIN_PROBE_INTERVAL_MS);
1662 ext_join_params->scan_le.home_time = cpu_to_le32(-1);
1664 if (sme->bssid)
1665 memcpy(&ext_join_params->assoc_le.bssid, sme->bssid, ETH_ALEN);
1666 else
1667 memset(&ext_join_params->assoc_le.bssid, 0xFF, ETH_ALEN);
1669 if (cfg->channel) {
1670 ext_join_params->assoc_le.chanspec_num = cpu_to_le32(1);
1672 ext_join_params->assoc_le.chanspec_list[0] =
1673 cpu_to_le16(chanspec);
1676 err = brcmf_fil_bsscfg_data_set(ifp, "join", ext_join_params,
1677 join_params_size);
1678 kfree(ext_join_params);
1679 if (!err)
1680 /* This is it. join command worked, we are done */
1681 goto done;
1683 /* join command failed, fallback to set ssid */
1684 memset(&join_params, 0, sizeof(join_params));
1685 join_params_size = sizeof(join_params.ssid_le);
1687 memcpy(&join_params.ssid_le.SSID, sme->ssid, profile->ssid.SSID_len);
1688 join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len);
1690 if (sme->bssid)
1691 memcpy(join_params.params_le.bssid, sme->bssid, ETH_ALEN);
1692 else
1693 memset(join_params.params_le.bssid, 0xFF, ETH_ALEN);
1695 if (cfg->channel) {
1696 join_params.params_le.chanspec_list[0] = cpu_to_le16(chanspec);
1697 join_params.params_le.chanspec_num = cpu_to_le32(1);
1698 join_params_size += sizeof(join_params.params_le);
1700 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
1701 &join_params, join_params_size);
1702 if (err)
1703 brcmf_err("BRCMF_C_SET_SSID failed (%d)\n", err);
1705 done:
1706 if (err)
1707 clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
1708 brcmf_dbg(TRACE, "Exit\n");
1709 return err;
1712 static s32
1713 brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,
1714 u16 reason_code)
1716 struct brcmf_if *ifp = netdev_priv(ndev);
1717 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
1718 struct brcmf_scb_val_le scbval;
1719 s32 err = 0;
1721 brcmf_dbg(TRACE, "Enter. Reason code = %d\n", reason_code);
1722 if (!check_vif_up(ifp->vif))
1723 return -EIO;
1725 clear_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
1727 memcpy(&scbval.ea, &profile->bssid, ETH_ALEN);
1728 scbval.val = cpu_to_le32(reason_code);
1729 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_DISASSOC,
1730 &scbval, sizeof(scbval));
1731 if (err)
1732 brcmf_err("error (%d)\n", err);
1734 brcmf_dbg(TRACE, "Exit\n");
1735 return err;
1738 static s32
1739 brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
1740 enum nl80211_tx_power_setting type, s32 mbm)
1743 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
1744 struct net_device *ndev = cfg_to_ndev(cfg);
1745 struct brcmf_if *ifp = netdev_priv(ndev);
1746 u16 txpwrmw;
1747 s32 err = 0;
1748 s32 disable = 0;
1749 s32 dbm = MBM_TO_DBM(mbm);
1751 brcmf_dbg(TRACE, "Enter\n");
1752 if (!check_vif_up(ifp->vif))
1753 return -EIO;
1755 switch (type) {
1756 case NL80211_TX_POWER_AUTOMATIC:
1757 break;
1758 case NL80211_TX_POWER_LIMITED:
1759 case NL80211_TX_POWER_FIXED:
1760 if (dbm < 0) {
1761 brcmf_err("TX_POWER_FIXED - dbm is negative\n");
1762 err = -EINVAL;
1763 goto done;
1765 break;
1767 /* Make sure radio is off or on as far as software is concerned */
1768 disable = WL_RADIO_SW_DISABLE << 16;
1769 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_RADIO, disable);
1770 if (err)
1771 brcmf_err("WLC_SET_RADIO error (%d)\n", err);
1773 if (dbm > 0xffff)
1774 txpwrmw = 0xffff;
1775 else
1776 txpwrmw = (u16) dbm;
1777 err = brcmf_fil_iovar_int_set(ifp, "qtxpower",
1778 (s32)brcmf_mw_to_qdbm(txpwrmw));
1779 if (err)
1780 brcmf_err("qtxpower error (%d)\n", err);
1781 cfg->conf->tx_power = dbm;
1783 done:
1784 brcmf_dbg(TRACE, "Exit\n");
1785 return err;
1788 static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy,
1789 struct wireless_dev *wdev,
1790 s32 *dbm)
1792 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
1793 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
1794 s32 txpwrdbm;
1795 u8 result;
1796 s32 err = 0;
1798 brcmf_dbg(TRACE, "Enter\n");
1799 if (!check_vif_up(ifp->vif))
1800 return -EIO;
1802 err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &txpwrdbm);
1803 if (err) {
1804 brcmf_err("error (%d)\n", err);
1805 goto done;
1808 result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
1809 *dbm = (s32) brcmf_qdbm_to_mw(result);
1811 done:
1812 brcmf_dbg(TRACE, "Exit\n");
1813 return err;
1816 static s32
1817 brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
1818 u8 key_idx, bool unicast, bool multicast)
1820 struct brcmf_if *ifp = netdev_priv(ndev);
1821 u32 index;
1822 u32 wsec;
1823 s32 err = 0;
1825 brcmf_dbg(TRACE, "Enter\n");
1826 brcmf_dbg(CONN, "key index (%d)\n", key_idx);
1827 if (!check_vif_up(ifp->vif))
1828 return -EIO;
1830 err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
1831 if (err) {
1832 brcmf_err("WLC_GET_WSEC error (%d)\n", err);
1833 goto done;
1836 if (wsec & WEP_ENABLED) {
1837 /* Just select a new current key */
1838 index = key_idx;
1839 err = brcmf_fil_cmd_int_set(ifp,
1840 BRCMF_C_SET_KEY_PRIMARY, index);
1841 if (err)
1842 brcmf_err("error (%d)\n", err);
1844 done:
1845 brcmf_dbg(TRACE, "Exit\n");
1846 return err;
1849 static s32
1850 brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
1851 u8 key_idx, const u8 *mac_addr, struct key_params *params)
1853 struct brcmf_wsec_key key;
1854 s32 err = 0;
1856 memset(&key, 0, sizeof(key));
1857 key.index = (u32) key_idx;
1858 /* Instead of bcast for ea address for default wep keys,
1859 driver needs it to be Null */
1860 if (!is_multicast_ether_addr(mac_addr))
1861 memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN);
1862 key.len = (u32) params->key_len;
1863 /* check for key index change */
1864 if (key.len == 0) {
1865 /* key delete */
1866 err = send_key_to_dongle(ndev, &key);
1867 if (err)
1868 brcmf_err("key delete error (%d)\n", err);
1869 } else {
1870 if (key.len > sizeof(key.data)) {
1871 brcmf_err("Invalid key length (%d)\n", key.len);
1872 return -EINVAL;
1875 brcmf_dbg(CONN, "Setting the key index %d\n", key.index);
1876 memcpy(key.data, params->key, key.len);
1878 if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
1879 u8 keybuf[8];
1880 memcpy(keybuf, &key.data[24], sizeof(keybuf));
1881 memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
1882 memcpy(&key.data[16], keybuf, sizeof(keybuf));
1885 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
1886 if (params->seq && params->seq_len == 6) {
1887 /* rx iv */
1888 u8 *ivptr;
1889 ivptr = (u8 *) params->seq;
1890 key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
1891 (ivptr[3] << 8) | ivptr[2];
1892 key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
1893 key.iv_initialized = true;
1896 switch (params->cipher) {
1897 case WLAN_CIPHER_SUITE_WEP40:
1898 key.algo = CRYPTO_ALGO_WEP1;
1899 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n");
1900 break;
1901 case WLAN_CIPHER_SUITE_WEP104:
1902 key.algo = CRYPTO_ALGO_WEP128;
1903 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
1904 break;
1905 case WLAN_CIPHER_SUITE_TKIP:
1906 key.algo = CRYPTO_ALGO_TKIP;
1907 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
1908 break;
1909 case WLAN_CIPHER_SUITE_AES_CMAC:
1910 key.algo = CRYPTO_ALGO_AES_CCM;
1911 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
1912 break;
1913 case WLAN_CIPHER_SUITE_CCMP:
1914 key.algo = CRYPTO_ALGO_AES_CCM;
1915 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_CCMP\n");
1916 break;
1917 default:
1918 brcmf_err("Invalid cipher (0x%x)\n", params->cipher);
1919 return -EINVAL;
1921 err = send_key_to_dongle(ndev, &key);
1922 if (err)
1923 brcmf_err("wsec_key error (%d)\n", err);
1925 return err;
1928 static s32
1929 brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
1930 u8 key_idx, bool pairwise, const u8 *mac_addr,
1931 struct key_params *params)
1933 struct brcmf_if *ifp = netdev_priv(ndev);
1934 struct brcmf_wsec_key key;
1935 s32 val;
1936 s32 wsec;
1937 s32 err = 0;
1938 u8 keybuf[8];
1940 brcmf_dbg(TRACE, "Enter\n");
1941 brcmf_dbg(CONN, "key index (%d)\n", key_idx);
1942 if (!check_vif_up(ifp->vif))
1943 return -EIO;
1945 if (mac_addr) {
1946 brcmf_dbg(TRACE, "Exit");
1947 return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params);
1949 memset(&key, 0, sizeof(key));
1951 key.len = (u32) params->key_len;
1952 key.index = (u32) key_idx;
1954 if (key.len > sizeof(key.data)) {
1955 brcmf_err("Too long key length (%u)\n", key.len);
1956 err = -EINVAL;
1957 goto done;
1959 memcpy(key.data, params->key, key.len);
1961 key.flags = BRCMF_PRIMARY_KEY;
1962 switch (params->cipher) {
1963 case WLAN_CIPHER_SUITE_WEP40:
1964 key.algo = CRYPTO_ALGO_WEP1;
1965 val = WEP_ENABLED;
1966 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n");
1967 break;
1968 case WLAN_CIPHER_SUITE_WEP104:
1969 key.algo = CRYPTO_ALGO_WEP128;
1970 val = WEP_ENABLED;
1971 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
1972 break;
1973 case WLAN_CIPHER_SUITE_TKIP:
1974 if (ifp->vif->mode != WL_MODE_AP) {
1975 brcmf_dbg(CONN, "Swapping key\n");
1976 memcpy(keybuf, &key.data[24], sizeof(keybuf));
1977 memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
1978 memcpy(&key.data[16], keybuf, sizeof(keybuf));
1980 key.algo = CRYPTO_ALGO_TKIP;
1981 val = TKIP_ENABLED;
1982 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
1983 break;
1984 case WLAN_CIPHER_SUITE_AES_CMAC:
1985 key.algo = CRYPTO_ALGO_AES_CCM;
1986 val = AES_ENABLED;
1987 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
1988 break;
1989 case WLAN_CIPHER_SUITE_CCMP:
1990 key.algo = CRYPTO_ALGO_AES_CCM;
1991 val = AES_ENABLED;
1992 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_CCMP\n");
1993 break;
1994 default:
1995 brcmf_err("Invalid cipher (0x%x)\n", params->cipher);
1996 err = -EINVAL;
1997 goto done;
2000 err = send_key_to_dongle(ndev, &key);
2001 if (err)
2002 goto done;
2004 err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
2005 if (err) {
2006 brcmf_err("get wsec error (%d)\n", err);
2007 goto done;
2009 wsec |= val;
2010 err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
2011 if (err) {
2012 brcmf_err("set wsec error (%d)\n", err);
2013 goto done;
2016 done:
2017 brcmf_dbg(TRACE, "Exit\n");
2018 return err;
2021 static s32
2022 brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
2023 u8 key_idx, bool pairwise, const u8 *mac_addr)
2025 struct brcmf_if *ifp = netdev_priv(ndev);
2026 struct brcmf_wsec_key key;
2027 s32 err = 0;
2029 brcmf_dbg(TRACE, "Enter\n");
2030 if (!check_vif_up(ifp->vif))
2031 return -EIO;
2033 if (key_idx >= DOT11_MAX_DEFAULT_KEYS) {
2034 /* we ignore this key index in this case */
2035 brcmf_err("invalid key index (%d)\n", key_idx);
2036 return -EINVAL;
2039 memset(&key, 0, sizeof(key));
2041 key.index = (u32) key_idx;
2042 key.flags = BRCMF_PRIMARY_KEY;
2043 key.algo = CRYPTO_ALGO_OFF;
2045 brcmf_dbg(CONN, "key index (%d)\n", key_idx);
2047 /* Set the new key/index */
2048 err = send_key_to_dongle(ndev, &key);
2050 brcmf_dbg(TRACE, "Exit\n");
2051 return err;
2054 static s32
2055 brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
2056 u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
2057 void (*callback) (void *cookie, struct key_params * params))
2059 struct key_params params;
2060 struct brcmf_if *ifp = netdev_priv(ndev);
2061 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
2062 struct brcmf_cfg80211_security *sec;
2063 s32 wsec;
2064 s32 err = 0;
2066 brcmf_dbg(TRACE, "Enter\n");
2067 brcmf_dbg(CONN, "key index (%d)\n", key_idx);
2068 if (!check_vif_up(ifp->vif))
2069 return -EIO;
2071 memset(&params, 0, sizeof(params));
2073 err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
2074 if (err) {
2075 brcmf_err("WLC_GET_WSEC error (%d)\n", err);
2076 /* Ignore this error, may happen during DISASSOC */
2077 err = -EAGAIN;
2078 goto done;
2080 switch (wsec & ~SES_OW_ENABLED) {
2081 case WEP_ENABLED:
2082 sec = &profile->sec;
2083 if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
2084 params.cipher = WLAN_CIPHER_SUITE_WEP40;
2085 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n");
2086 } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
2087 params.cipher = WLAN_CIPHER_SUITE_WEP104;
2088 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
2090 break;
2091 case TKIP_ENABLED:
2092 params.cipher = WLAN_CIPHER_SUITE_TKIP;
2093 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
2094 break;
2095 case AES_ENABLED:
2096 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
2097 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
2098 break;
2099 default:
2100 brcmf_err("Invalid algo (0x%x)\n", wsec);
2101 err = -EINVAL;
2102 goto done;
2104 callback(cookie, &params);
2106 done:
2107 brcmf_dbg(TRACE, "Exit\n");
2108 return err;
2111 static s32
2112 brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
2113 struct net_device *ndev, u8 key_idx)
2115 brcmf_dbg(INFO, "Not supported\n");
2117 return -EOPNOTSUPP;
2120 static s32
2121 brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
2122 u8 *mac, struct station_info *sinfo)
2124 struct brcmf_if *ifp = netdev_priv(ndev);
2125 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
2126 struct brcmf_scb_val_le scb_val;
2127 int rssi;
2128 s32 rate;
2129 s32 err = 0;
2130 u8 *bssid = profile->bssid;
2131 struct brcmf_sta_info_le sta_info_le;
2133 brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
2134 if (!check_vif_up(ifp->vif))
2135 return -EIO;
2137 if (ifp->vif->mode == WL_MODE_AP) {
2138 memcpy(&sta_info_le, mac, ETH_ALEN);
2139 err = brcmf_fil_iovar_data_get(ifp, "sta_info",
2140 &sta_info_le,
2141 sizeof(sta_info_le));
2142 if (err < 0) {
2143 brcmf_err("GET STA INFO failed, %d\n", err);
2144 goto done;
2146 sinfo->filled = STATION_INFO_INACTIVE_TIME;
2147 sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
2148 if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) {
2149 sinfo->filled |= STATION_INFO_CONNECTED_TIME;
2150 sinfo->connected_time = le32_to_cpu(sta_info_le.in);
2152 brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n",
2153 sinfo->inactive_time, sinfo->connected_time);
2154 } else if (ifp->vif->mode == WL_MODE_BSS) {
2155 if (memcmp(mac, bssid, ETH_ALEN)) {
2156 brcmf_err("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n",
2157 mac, bssid);
2158 err = -ENOENT;
2159 goto done;
2161 /* Report the current tx rate */
2162 err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate);
2163 if (err) {
2164 brcmf_err("Could not get rate (%d)\n", err);
2165 goto done;
2166 } else {
2167 sinfo->filled |= STATION_INFO_TX_BITRATE;
2168 sinfo->txrate.legacy = rate * 5;
2169 brcmf_dbg(CONN, "Rate %d Mbps\n", rate / 2);
2172 if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
2173 &ifp->vif->sme_state)) {
2174 memset(&scb_val, 0, sizeof(scb_val));
2175 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI,
2176 &scb_val, sizeof(scb_val));
2177 if (err) {
2178 brcmf_err("Could not get rssi (%d)\n", err);
2179 goto done;
2180 } else {
2181 rssi = le32_to_cpu(scb_val.val);
2182 sinfo->filled |= STATION_INFO_SIGNAL;
2183 sinfo->signal = rssi;
2184 brcmf_dbg(CONN, "RSSI %d dBm\n", rssi);
2187 } else
2188 err = -EPERM;
2189 done:
2190 brcmf_dbg(TRACE, "Exit\n");
2191 return err;
2194 static s32
2195 brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
2196 bool enabled, s32 timeout)
2198 s32 pm;
2199 s32 err = 0;
2200 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
2201 struct brcmf_if *ifp = netdev_priv(ndev);
2203 brcmf_dbg(TRACE, "Enter\n");
2206 * Powersave enable/disable request is coming from the
2207 * cfg80211 even before the interface is up. In that
2208 * scenario, driver will be storing the power save
2209 * preference in cfg struct to apply this to
2210 * FW later while initializing the dongle
2212 cfg->pwr_save = enabled;
2213 if (!check_vif_up(ifp->vif)) {
2215 brcmf_dbg(INFO, "Device is not ready, storing the value in cfg_info struct\n");
2216 goto done;
2219 pm = enabled ? PM_FAST : PM_OFF;
2220 brcmf_dbg(INFO, "power save %s\n", (pm ? "enabled" : "disabled"));
2222 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, pm);
2223 if (err) {
2224 if (err == -ENODEV)
2225 brcmf_err("net_device is not ready yet\n");
2226 else
2227 brcmf_err("error (%d)\n", err);
2229 done:
2230 brcmf_dbg(TRACE, "Exit\n");
2231 return err;
2234 static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
2235 struct brcmf_bss_info_le *bi)
2237 struct wiphy *wiphy = cfg_to_wiphy(cfg);
2238 struct ieee80211_channel *notify_channel;
2239 struct cfg80211_bss *bss;
2240 struct ieee80211_supported_band *band;
2241 s32 err = 0;
2242 u16 channel;
2243 u32 freq;
2244 u16 notify_capability;
2245 u16 notify_interval;
2246 u8 *notify_ie;
2247 size_t notify_ielen;
2248 s32 notify_signal;
2250 if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) {
2251 brcmf_err("Bss info is larger than buffer. Discarding\n");
2252 return 0;
2255 channel = bi->ctl_ch ? bi->ctl_ch :
2256 CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
2258 if (channel <= CH_MAX_2G_CHANNEL)
2259 band = wiphy->bands[IEEE80211_BAND_2GHZ];
2260 else
2261 band = wiphy->bands[IEEE80211_BAND_5GHZ];
2263 freq = ieee80211_channel_to_frequency(channel, band->band);
2264 notify_channel = ieee80211_get_channel(wiphy, freq);
2266 notify_capability = le16_to_cpu(bi->capability);
2267 notify_interval = le16_to_cpu(bi->beacon_period);
2268 notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
2269 notify_ielen = le32_to_cpu(bi->ie_length);
2270 notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
2272 brcmf_dbg(CONN, "bssid: %pM\n", bi->BSSID);
2273 brcmf_dbg(CONN, "Channel: %d(%d)\n", channel, freq);
2274 brcmf_dbg(CONN, "Capability: %X\n", notify_capability);
2275 brcmf_dbg(CONN, "Beacon interval: %d\n", notify_interval);
2276 brcmf_dbg(CONN, "Signal: %d\n", notify_signal);
2278 bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID,
2279 0, notify_capability, notify_interval, notify_ie,
2280 notify_ielen, notify_signal, GFP_KERNEL);
2282 if (!bss)
2283 return -ENOMEM;
2285 cfg80211_put_bss(wiphy, bss);
2287 return err;
2290 static struct brcmf_bss_info_le *
2291 next_bss_le(struct brcmf_scan_results *list, struct brcmf_bss_info_le *bss)
2293 if (bss == NULL)
2294 return list->bss_info_le;
2295 return (struct brcmf_bss_info_le *)((unsigned long)bss +
2296 le32_to_cpu(bss->length));
2299 static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg)
2301 struct brcmf_scan_results *bss_list;
2302 struct brcmf_bss_info_le *bi = NULL; /* must be initialized */
2303 s32 err = 0;
2304 int i;
2306 bss_list = cfg->bss_list;
2307 if (bss_list->count != 0 &&
2308 bss_list->version != BRCMF_BSS_INFO_VERSION) {
2309 brcmf_err("Version %d != WL_BSS_INFO_VERSION\n",
2310 bss_list->version);
2311 return -EOPNOTSUPP;
2313 brcmf_dbg(SCAN, "scanned AP count (%d)\n", bss_list->count);
2314 for (i = 0; i < bss_list->count; i++) {
2315 bi = next_bss_le(bss_list, bi);
2316 err = brcmf_inform_single_bss(cfg, bi);
2317 if (err)
2318 break;
2320 return err;
2323 static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
2324 struct net_device *ndev, const u8 *bssid)
2326 struct wiphy *wiphy = cfg_to_wiphy(cfg);
2327 struct ieee80211_channel *notify_channel;
2328 struct brcmf_bss_info_le *bi = NULL;
2329 struct ieee80211_supported_band *band;
2330 struct cfg80211_bss *bss;
2331 u8 *buf = NULL;
2332 s32 err = 0;
2333 u16 channel;
2334 u32 freq;
2335 u16 notify_capability;
2336 u16 notify_interval;
2337 u8 *notify_ie;
2338 size_t notify_ielen;
2339 s32 notify_signal;
2341 brcmf_dbg(TRACE, "Enter\n");
2343 buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
2344 if (buf == NULL) {
2345 err = -ENOMEM;
2346 goto CleanUp;
2349 *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
2351 err = brcmf_fil_cmd_data_get(netdev_priv(ndev), BRCMF_C_GET_BSS_INFO,
2352 buf, WL_BSS_INFO_MAX);
2353 if (err) {
2354 brcmf_err("WLC_GET_BSS_INFO failed: %d\n", err);
2355 goto CleanUp;
2358 bi = (struct brcmf_bss_info_le *)(buf + 4);
2360 channel = bi->ctl_ch ? bi->ctl_ch :
2361 CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
2363 if (channel <= CH_MAX_2G_CHANNEL)
2364 band = wiphy->bands[IEEE80211_BAND_2GHZ];
2365 else
2366 band = wiphy->bands[IEEE80211_BAND_5GHZ];
2368 freq = ieee80211_channel_to_frequency(channel, band->band);
2369 notify_channel = ieee80211_get_channel(wiphy, freq);
2371 notify_capability = le16_to_cpu(bi->capability);
2372 notify_interval = le16_to_cpu(bi->beacon_period);
2373 notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
2374 notify_ielen = le32_to_cpu(bi->ie_length);
2375 notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
2377 brcmf_dbg(CONN, "channel: %d(%d)\n", channel, freq);
2378 brcmf_dbg(CONN, "capability: %X\n", notify_capability);
2379 brcmf_dbg(CONN, "beacon interval: %d\n", notify_interval);
2380 brcmf_dbg(CONN, "signal: %d\n", notify_signal);
2382 bss = cfg80211_inform_bss(wiphy, notify_channel, bssid,
2383 0, notify_capability, notify_interval,
2384 notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
2386 if (!bss) {
2387 err = -ENOMEM;
2388 goto CleanUp;
2391 cfg80211_put_bss(wiphy, bss);
2393 CleanUp:
2395 kfree(buf);
2397 brcmf_dbg(TRACE, "Exit\n");
2399 return err;
2402 static bool brcmf_is_ibssmode(struct brcmf_cfg80211_vif *vif)
2404 return vif->mode == WL_MODE_IBSS;
2407 static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg,
2408 struct brcmf_if *ifp)
2410 struct brcmf_cfg80211_profile *profile = ndev_to_prof(ifp->ndev);
2411 struct brcmf_bss_info_le *bi;
2412 struct brcmf_ssid *ssid;
2413 struct brcmf_tlv *tim;
2414 u16 beacon_interval;
2415 u8 dtim_period;
2416 size_t ie_len;
2417 u8 *ie;
2418 s32 err = 0;
2420 brcmf_dbg(TRACE, "Enter\n");
2421 if (brcmf_is_ibssmode(ifp->vif))
2422 return err;
2424 ssid = &profile->ssid;
2426 *(__le32 *)cfg->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
2427 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
2428 cfg->extra_buf, WL_EXTRA_BUF_MAX);
2429 if (err) {
2430 brcmf_err("Could not get bss info %d\n", err);
2431 goto update_bss_info_out;
2434 bi = (struct brcmf_bss_info_le *)(cfg->extra_buf + 4);
2435 err = brcmf_inform_single_bss(cfg, bi);
2436 if (err)
2437 goto update_bss_info_out;
2439 ie = ((u8 *)bi) + le16_to_cpu(bi->ie_offset);
2440 ie_len = le32_to_cpu(bi->ie_length);
2441 beacon_interval = le16_to_cpu(bi->beacon_period);
2443 tim = brcmf_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
2444 if (tim)
2445 dtim_period = tim->data[1];
2446 else {
2448 * active scan was done so we could not get dtim
2449 * information out of probe response.
2450 * so we speficially query dtim information to dongle.
2452 u32 var;
2453 err = brcmf_fil_iovar_int_get(ifp, "dtim_assoc", &var);
2454 if (err) {
2455 brcmf_err("wl dtim_assoc failed (%d)\n", err);
2456 goto update_bss_info_out;
2458 dtim_period = (u8)var;
2461 update_bss_info_out:
2462 brcmf_dbg(TRACE, "Exit");
2463 return err;
2466 void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg)
2468 struct escan_info *escan = &cfg->escan_info;
2470 set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
2471 if (cfg->scan_request) {
2472 escan->escan_state = WL_ESCAN_STATE_IDLE;
2473 brcmf_notify_escan_complete(cfg, escan->ndev, true, true);
2475 clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
2476 clear_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
2479 static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work)
2481 struct brcmf_cfg80211_info *cfg =
2482 container_of(work, struct brcmf_cfg80211_info,
2483 escan_timeout_work);
2485 brcmf_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
2488 static void brcmf_escan_timeout(unsigned long data)
2490 struct brcmf_cfg80211_info *cfg =
2491 (struct brcmf_cfg80211_info *)data;
2493 if (cfg->scan_request) {
2494 brcmf_err("timer expired\n");
2495 schedule_work(&cfg->escan_timeout_work);
2499 static s32
2500 brcmf_compare_update_same_bss(struct brcmf_bss_info_le *bss,
2501 struct brcmf_bss_info_le *bss_info_le)
2503 if (!memcmp(&bss_info_le->BSSID, &bss->BSSID, ETH_ALEN) &&
2504 (CHSPEC_BAND(le16_to_cpu(bss_info_le->chanspec)) ==
2505 CHSPEC_BAND(le16_to_cpu(bss->chanspec))) &&
2506 bss_info_le->SSID_len == bss->SSID_len &&
2507 !memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) {
2508 if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) ==
2509 (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL)) {
2510 s16 bss_rssi = le16_to_cpu(bss->RSSI);
2511 s16 bss_info_rssi = le16_to_cpu(bss_info_le->RSSI);
2513 /* preserve max RSSI if the measurements are
2514 * both on-channel or both off-channel
2516 if (bss_info_rssi > bss_rssi)
2517 bss->RSSI = bss_info_le->RSSI;
2518 } else if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) &&
2519 (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL) == 0) {
2520 /* preserve the on-channel rssi measurement
2521 * if the new measurement is off channel
2523 bss->RSSI = bss_info_le->RSSI;
2524 bss->flags |= WLC_BSS_RSSI_ON_CHANNEL;
2526 return 1;
2528 return 0;
2531 static s32
2532 brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
2533 const struct brcmf_event_msg *e, void *data)
2535 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
2536 struct net_device *ndev = ifp->ndev;
2537 s32 status;
2538 s32 err = 0;
2539 struct brcmf_escan_result_le *escan_result_le;
2540 struct brcmf_bss_info_le *bss_info_le;
2541 struct brcmf_bss_info_le *bss = NULL;
2542 u32 bi_length;
2543 struct brcmf_scan_results *list;
2544 u32 i;
2545 bool aborted;
2547 status = e->status;
2549 if (!ndev || !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
2550 brcmf_err("scan not ready ndev %p drv_status %x\n", ndev,
2551 !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status));
2552 return -EPERM;
2555 if (status == BRCMF_E_STATUS_PARTIAL) {
2556 brcmf_dbg(SCAN, "ESCAN Partial result\n");
2557 escan_result_le = (struct brcmf_escan_result_le *) data;
2558 if (!escan_result_le) {
2559 brcmf_err("Invalid escan result (NULL pointer)\n");
2560 goto exit;
2562 if (le16_to_cpu(escan_result_le->bss_count) != 1) {
2563 brcmf_err("Invalid bss_count %d: ignoring\n",
2564 escan_result_le->bss_count);
2565 goto exit;
2567 bss_info_le = &escan_result_le->bss_info_le;
2569 if (brcmf_p2p_scan_finding_common_channel(cfg, bss_info_le))
2570 goto exit;
2572 if (!cfg->scan_request) {
2573 brcmf_dbg(SCAN, "result without cfg80211 request\n");
2574 goto exit;
2577 bi_length = le32_to_cpu(bss_info_le->length);
2578 if (bi_length != (le32_to_cpu(escan_result_le->buflen) -
2579 WL_ESCAN_RESULTS_FIXED_SIZE)) {
2580 brcmf_err("Invalid bss_info length %d: ignoring\n",
2581 bi_length);
2582 goto exit;
2585 if (!(cfg_to_wiphy(cfg)->interface_modes &
2586 BIT(NL80211_IFTYPE_ADHOC))) {
2587 if (le16_to_cpu(bss_info_le->capability) &
2588 WLAN_CAPABILITY_IBSS) {
2589 brcmf_err("Ignoring IBSS result\n");
2590 goto exit;
2594 list = (struct brcmf_scan_results *)
2595 cfg->escan_info.escan_buf;
2596 if (bi_length > WL_ESCAN_BUF_SIZE - list->buflen) {
2597 brcmf_err("Buffer is too small: ignoring\n");
2598 goto exit;
2601 for (i = 0; i < list->count; i++) {
2602 bss = bss ? (struct brcmf_bss_info_le *)
2603 ((unsigned char *)bss +
2604 le32_to_cpu(bss->length)) : list->bss_info_le;
2605 if (brcmf_compare_update_same_bss(bss, bss_info_le))
2606 goto exit;
2608 memcpy(&(cfg->escan_info.escan_buf[list->buflen]),
2609 bss_info_le, bi_length);
2610 list->version = le32_to_cpu(bss_info_le->version);
2611 list->buflen += bi_length;
2612 list->count++;
2613 } else {
2614 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
2615 if (brcmf_p2p_scan_finding_common_channel(cfg, NULL))
2616 goto exit;
2617 if (cfg->scan_request) {
2618 cfg->bss_list = (struct brcmf_scan_results *)
2619 cfg->escan_info.escan_buf;
2620 brcmf_inform_bss(cfg);
2621 aborted = status != BRCMF_E_STATUS_SUCCESS;
2622 brcmf_notify_escan_complete(cfg, ndev, aborted,
2623 false);
2624 } else
2625 brcmf_dbg(SCAN, "Ignored scan complete result 0x%x\n",
2626 status);
2628 exit:
2629 return err;
2632 static void brcmf_init_escan(struct brcmf_cfg80211_info *cfg)
2634 brcmf_fweh_register(cfg->pub, BRCMF_E_ESCAN_RESULT,
2635 brcmf_cfg80211_escan_handler);
2636 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
2637 /* Init scan_timeout timer */
2638 init_timer(&cfg->escan_timeout);
2639 cfg->escan_timeout.data = (unsigned long) cfg;
2640 cfg->escan_timeout.function = brcmf_escan_timeout;
2641 INIT_WORK(&cfg->escan_timeout_work,
2642 brcmf_cfg80211_escan_timeout_worker);
2645 static __always_inline void brcmf_delay(u32 ms)
2647 if (ms < 1000 / HZ) {
2648 cond_resched();
2649 mdelay(ms);
2650 } else {
2651 msleep(ms);
2655 static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
2657 brcmf_dbg(TRACE, "Enter\n");
2659 return 0;
2662 static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
2663 struct cfg80211_wowlan *wow)
2665 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
2666 struct net_device *ndev = cfg_to_ndev(cfg);
2667 struct brcmf_cfg80211_vif *vif;
2669 brcmf_dbg(TRACE, "Enter\n");
2672 * if the primary net_device is not READY there is nothing
2673 * we can do but pray resume goes smoothly.
2675 vif = ((struct brcmf_if *)netdev_priv(ndev))->vif;
2676 if (!check_vif_up(vif))
2677 goto exit;
2679 list_for_each_entry(vif, &cfg->vif_list, list) {
2680 if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state))
2681 continue;
2683 * While going to suspend if associated with AP disassociate
2684 * from AP to save power while system is in suspended state
2686 brcmf_link_down(vif);
2688 /* Make sure WPA_Supplicant receives all the event
2689 * generated due to DISASSOC call to the fw to keep
2690 * the state fw and WPA_Supplicant state consistent
2692 brcmf_delay(500);
2695 /* end any scanning */
2696 if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status))
2697 brcmf_abort_scanning(cfg);
2699 /* Turn off watchdog timer */
2700 brcmf_set_mpc(ndev, 1);
2702 exit:
2703 brcmf_dbg(TRACE, "Exit\n");
2704 /* clear any scanning activity */
2705 cfg->scan_status = 0;
2706 return 0;
2709 static __used s32
2710 brcmf_update_pmklist(struct net_device *ndev,
2711 struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
2713 int i, j;
2714 int pmkid_len;
2716 pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid);
2718 brcmf_dbg(CONN, "No of elements %d\n", pmkid_len);
2719 for (i = 0; i < pmkid_len; i++) {
2720 brcmf_dbg(CONN, "PMKID[%d]: %pM =\n", i,
2721 &pmk_list->pmkids.pmkid[i].BSSID);
2722 for (j = 0; j < WLAN_PMKID_LEN; j++)
2723 brcmf_dbg(CONN, "%02x\n",
2724 pmk_list->pmkids.pmkid[i].PMKID[j]);
2727 if (!err)
2728 brcmf_fil_iovar_data_set(netdev_priv(ndev), "pmkid_info",
2729 (char *)pmk_list, sizeof(*pmk_list));
2731 return err;
2734 static s32
2735 brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
2736 struct cfg80211_pmksa *pmksa)
2738 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
2739 struct brcmf_if *ifp = netdev_priv(ndev);
2740 struct pmkid_list *pmkids = &cfg->pmk_list->pmkids;
2741 s32 err = 0;
2742 int i;
2743 int pmkid_len;
2745 brcmf_dbg(TRACE, "Enter\n");
2746 if (!check_vif_up(ifp->vif))
2747 return -EIO;
2749 pmkid_len = le32_to_cpu(pmkids->npmkid);
2750 for (i = 0; i < pmkid_len; i++)
2751 if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN))
2752 break;
2753 if (i < WL_NUM_PMKIDS_MAX) {
2754 memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN);
2755 memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2756 if (i == pmkid_len) {
2757 pmkid_len++;
2758 pmkids->npmkid = cpu_to_le32(pmkid_len);
2760 } else
2761 err = -EINVAL;
2763 brcmf_dbg(CONN, "set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
2764 pmkids->pmkid[pmkid_len].BSSID);
2765 for (i = 0; i < WLAN_PMKID_LEN; i++)
2766 brcmf_dbg(CONN, "%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]);
2768 err = brcmf_update_pmklist(ndev, cfg->pmk_list, err);
2770 brcmf_dbg(TRACE, "Exit\n");
2771 return err;
2774 static s32
2775 brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
2776 struct cfg80211_pmksa *pmksa)
2778 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
2779 struct brcmf_if *ifp = netdev_priv(ndev);
2780 struct pmkid_list pmkid;
2781 s32 err = 0;
2782 int i, pmkid_len;
2784 brcmf_dbg(TRACE, "Enter\n");
2785 if (!check_vif_up(ifp->vif))
2786 return -EIO;
2788 memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
2789 memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2791 brcmf_dbg(CONN, "del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
2792 &pmkid.pmkid[0].BSSID);
2793 for (i = 0; i < WLAN_PMKID_LEN; i++)
2794 brcmf_dbg(CONN, "%02x\n", pmkid.pmkid[0].PMKID[i]);
2796 pmkid_len = le32_to_cpu(cfg->pmk_list->pmkids.npmkid);
2797 for (i = 0; i < pmkid_len; i++)
2798 if (!memcmp
2799 (pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
2800 ETH_ALEN))
2801 break;
2803 if ((pmkid_len > 0)
2804 && (i < pmkid_len)) {
2805 memset(&cfg->pmk_list->pmkids.pmkid[i], 0,
2806 sizeof(struct pmkid));
2807 for (; i < (pmkid_len - 1); i++) {
2808 memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID,
2809 &cfg->pmk_list->pmkids.pmkid[i + 1].BSSID,
2810 ETH_ALEN);
2811 memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID,
2812 &cfg->pmk_list->pmkids.pmkid[i + 1].PMKID,
2813 WLAN_PMKID_LEN);
2815 cfg->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1);
2816 } else
2817 err = -EINVAL;
2819 err = brcmf_update_pmklist(ndev, cfg->pmk_list, err);
2821 brcmf_dbg(TRACE, "Exit\n");
2822 return err;
2826 static s32
2827 brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
2829 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
2830 struct brcmf_if *ifp = netdev_priv(ndev);
2831 s32 err = 0;
2833 brcmf_dbg(TRACE, "Enter\n");
2834 if (!check_vif_up(ifp->vif))
2835 return -EIO;
2837 memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list));
2838 err = brcmf_update_pmklist(ndev, cfg->pmk_list, err);
2840 brcmf_dbg(TRACE, "Exit\n");
2841 return err;
2846 * PFN result doesn't have all the info which are
2847 * required by the supplicant
2848 * (For e.g IEs) Do a target Escan so that sched scan results are reported
2849 * via wl_inform_single_bss in the required format. Escan does require the
2850 * scan request in the form of cfg80211_scan_request. For timebeing, create
2851 * cfg80211_scan_request one out of the received PNO event.
2853 static s32
2854 brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
2855 const struct brcmf_event_msg *e, void *data)
2857 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
2858 struct net_device *ndev = ifp->ndev;
2859 struct brcmf_pno_net_info_le *netinfo, *netinfo_start;
2860 struct cfg80211_scan_request *request = NULL;
2861 struct cfg80211_ssid *ssid = NULL;
2862 struct ieee80211_channel *channel = NULL;
2863 struct wiphy *wiphy = cfg_to_wiphy(cfg);
2864 int err = 0;
2865 int channel_req = 0;
2866 int band = 0;
2867 struct brcmf_pno_scanresults_le *pfn_result;
2868 u32 result_count;
2869 u32 status;
2871 brcmf_dbg(SCAN, "Enter\n");
2873 if (e->event_code == BRCMF_E_PFN_NET_LOST) {
2874 brcmf_dbg(SCAN, "PFN NET LOST event. Do Nothing\n");
2875 return 0;
2878 pfn_result = (struct brcmf_pno_scanresults_le *)data;
2879 result_count = le32_to_cpu(pfn_result->count);
2880 status = le32_to_cpu(pfn_result->status);
2883 * PFN event is limited to fit 512 bytes so we may get
2884 * multiple NET_FOUND events. For now place a warning here.
2886 WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE);
2887 brcmf_dbg(SCAN, "PFN NET FOUND event. count: %d\n", result_count);
2888 if (result_count > 0) {
2889 int i;
2891 request = kzalloc(sizeof(*request), GFP_KERNEL);
2892 ssid = kcalloc(result_count, sizeof(*ssid), GFP_KERNEL);
2893 channel = kcalloc(result_count, sizeof(*channel), GFP_KERNEL);
2894 if (!request || !ssid || !channel) {
2895 err = -ENOMEM;
2896 goto out_err;
2899 request->wiphy = wiphy;
2900 data += sizeof(struct brcmf_pno_scanresults_le);
2901 netinfo_start = (struct brcmf_pno_net_info_le *)data;
2903 for (i = 0; i < result_count; i++) {
2904 netinfo = &netinfo_start[i];
2905 if (!netinfo) {
2906 brcmf_err("Invalid netinfo ptr. index: %d\n",
2908 err = -EINVAL;
2909 goto out_err;
2912 brcmf_dbg(SCAN, "SSID:%s Channel:%d\n",
2913 netinfo->SSID, netinfo->channel);
2914 memcpy(ssid[i].ssid, netinfo->SSID, netinfo->SSID_len);
2915 ssid[i].ssid_len = netinfo->SSID_len;
2916 request->n_ssids++;
2918 channel_req = netinfo->channel;
2919 if (channel_req <= CH_MAX_2G_CHANNEL)
2920 band = NL80211_BAND_2GHZ;
2921 else
2922 band = NL80211_BAND_5GHZ;
2923 channel[i].center_freq =
2924 ieee80211_channel_to_frequency(channel_req,
2925 band);
2926 channel[i].band = band;
2927 channel[i].flags |= IEEE80211_CHAN_NO_HT40;
2928 request->channels[i] = &channel[i];
2929 request->n_channels++;
2932 /* assign parsed ssid array */
2933 if (request->n_ssids)
2934 request->ssids = &ssid[0];
2936 if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
2937 /* Abort any on-going scan */
2938 brcmf_abort_scanning(cfg);
2941 set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
2942 err = brcmf_do_escan(cfg, wiphy, ndev, request);
2943 if (err) {
2944 clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
2945 goto out_err;
2947 cfg->sched_escan = true;
2948 cfg->scan_request = request;
2949 } else {
2950 brcmf_err("FALSE PNO Event. (pfn_count == 0)\n");
2951 goto out_err;
2954 kfree(ssid);
2955 kfree(channel);
2956 kfree(request);
2957 return 0;
2959 out_err:
2960 kfree(ssid);
2961 kfree(channel);
2962 kfree(request);
2963 cfg80211_sched_scan_stopped(wiphy);
2964 return err;
2967 static int brcmf_dev_pno_clean(struct net_device *ndev)
2969 int ret;
2971 /* Disable pfn */
2972 ret = brcmf_fil_iovar_int_set(netdev_priv(ndev), "pfn", 0);
2973 if (ret == 0) {
2974 /* clear pfn */
2975 ret = brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfnclear",
2976 NULL, 0);
2978 if (ret < 0)
2979 brcmf_err("failed code %d\n", ret);
2981 return ret;
2984 static int brcmf_dev_pno_config(struct net_device *ndev)
2986 struct brcmf_pno_param_le pfn_param;
2988 memset(&pfn_param, 0, sizeof(pfn_param));
2989 pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION);
2991 /* set extra pno params */
2992 pfn_param.flags = cpu_to_le16(1 << BRCMF_PNO_ENABLE_ADAPTSCAN_BIT);
2993 pfn_param.repeat = BRCMF_PNO_REPEAT;
2994 pfn_param.exp = BRCMF_PNO_FREQ_EXPO_MAX;
2996 /* set up pno scan fr */
2997 pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME);
2999 return brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfn_set",
3000 &pfn_param, sizeof(pfn_param));
3003 static int
3004 brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
3005 struct net_device *ndev,
3006 struct cfg80211_sched_scan_request *request)
3008 struct brcmf_if *ifp = netdev_priv(ndev);
3009 struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
3010 struct brcmf_pno_net_param_le pfn;
3011 int i;
3012 int ret = 0;
3014 brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n",
3015 request->n_match_sets, request->n_ssids);
3016 if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
3017 brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
3018 return -EAGAIN;
3021 if (!request->n_ssids || !request->n_match_sets) {
3022 brcmf_err("Invalid sched scan req!! n_ssids:%d\n",
3023 request->n_ssids);
3024 return -EINVAL;
3027 if (request->n_ssids > 0) {
3028 for (i = 0; i < request->n_ssids; i++) {
3029 /* Active scan req for ssids */
3030 brcmf_dbg(SCAN, ">>> Active scan req for ssid (%s)\n",
3031 request->ssids[i].ssid);
3034 * match_set ssids is a supert set of n_ssid list,
3035 * so we need not add these set seperately.
3040 if (request->n_match_sets > 0) {
3041 /* clean up everything */
3042 ret = brcmf_dev_pno_clean(ndev);
3043 if (ret < 0) {
3044 brcmf_err("failed error=%d\n", ret);
3045 return ret;
3048 /* configure pno */
3049 ret = brcmf_dev_pno_config(ndev);
3050 if (ret < 0) {
3051 brcmf_err("PNO setup failed!! ret=%d\n", ret);
3052 return -EINVAL;
3055 /* configure each match set */
3056 for (i = 0; i < request->n_match_sets; i++) {
3057 struct cfg80211_ssid *ssid;
3058 u32 ssid_len;
3060 ssid = &request->match_sets[i].ssid;
3061 ssid_len = ssid->ssid_len;
3063 if (!ssid_len) {
3064 brcmf_err("skip broadcast ssid\n");
3065 continue;
3067 pfn.auth = cpu_to_le32(WLAN_AUTH_OPEN);
3068 pfn.wpa_auth = cpu_to_le32(BRCMF_PNO_WPA_AUTH_ANY);
3069 pfn.wsec = cpu_to_le32(0);
3070 pfn.infra = cpu_to_le32(1);
3071 pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT);
3072 pfn.ssid.SSID_len = cpu_to_le32(ssid_len);
3073 memcpy(pfn.ssid.SSID, ssid->ssid, ssid_len);
3074 ret = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn,
3075 sizeof(pfn));
3076 brcmf_dbg(SCAN, ">>> PNO filter %s for ssid (%s)\n",
3077 ret == 0 ? "set" : "failed", ssid->ssid);
3079 /* Enable the PNO */
3080 if (brcmf_fil_iovar_int_set(ifp, "pfn", 1) < 0) {
3081 brcmf_err("PNO enable failed!! ret=%d\n", ret);
3082 return -EINVAL;
3084 } else {
3085 return -EINVAL;
3088 return 0;
3091 static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
3092 struct net_device *ndev)
3094 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
3096 brcmf_dbg(SCAN, "enter\n");
3097 brcmf_dev_pno_clean(ndev);
3098 if (cfg->sched_escan)
3099 brcmf_notify_escan_complete(cfg, ndev, true, true);
3100 return 0;
3103 #ifdef CONFIG_NL80211_TESTMODE
3104 static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
3106 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
3107 struct net_device *ndev = cfg_to_ndev(cfg);
3108 struct brcmf_dcmd *dcmd = data;
3109 struct sk_buff *reply;
3110 int ret;
3112 brcmf_dbg(TRACE, "cmd %x set %d buf %p len %d\n", dcmd->cmd, dcmd->set,
3113 dcmd->buf, dcmd->len);
3115 if (dcmd->set)
3116 ret = brcmf_fil_cmd_data_set(netdev_priv(ndev), dcmd->cmd,
3117 dcmd->buf, dcmd->len);
3118 else
3119 ret = brcmf_fil_cmd_data_get(netdev_priv(ndev), dcmd->cmd,
3120 dcmd->buf, dcmd->len);
3121 if (ret == 0) {
3122 reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*dcmd));
3123 nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*dcmd), dcmd);
3124 ret = cfg80211_testmode_reply(reply);
3126 return ret;
3128 #endif
3130 static s32 brcmf_configure_opensecurity(struct brcmf_if *ifp)
3132 s32 err;
3134 /* set auth */
3135 err = brcmf_fil_bsscfg_int_set(ifp, "auth", 0);
3136 if (err < 0) {
3137 brcmf_err("auth error %d\n", err);
3138 return err;
3140 /* set wsec */
3141 err = brcmf_fil_bsscfg_int_set(ifp, "wsec", 0);
3142 if (err < 0) {
3143 brcmf_err("wsec error %d\n", err);
3144 return err;
3146 /* set upper-layer auth */
3147 err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", WPA_AUTH_NONE);
3148 if (err < 0) {
3149 brcmf_err("wpa_auth error %d\n", err);
3150 return err;
3153 return 0;
3156 static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie)
3158 if (is_rsn_ie)
3159 return (memcmp(oui, RSN_OUI, TLV_OUI_LEN) == 0);
3161 return (memcmp(oui, WPA_OUI, TLV_OUI_LEN) == 0);
3164 static s32
3165 brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie,
3166 bool is_rsn_ie)
3168 struct brcmf_if *ifp = netdev_priv(ndev);
3169 u32 auth = 0; /* d11 open authentication */
3170 u16 count;
3171 s32 err = 0;
3172 s32 len = 0;
3173 u32 i;
3174 u32 wsec;
3175 u32 pval = 0;
3176 u32 gval = 0;
3177 u32 wpa_auth = 0;
3178 u32 offset;
3179 u8 *data;
3180 u16 rsn_cap;
3181 u32 wme_bss_disable;
3183 brcmf_dbg(TRACE, "Enter\n");
3184 if (wpa_ie == NULL)
3185 goto exit;
3187 len = wpa_ie->len + TLV_HDR_LEN;
3188 data = (u8 *)wpa_ie;
3189 offset = TLV_HDR_LEN;
3190 if (!is_rsn_ie)
3191 offset += VS_IE_FIXED_HDR_LEN;
3192 else
3193 offset += WPA_IE_VERSION_LEN;
3195 /* check for multicast cipher suite */
3196 if (offset + WPA_IE_MIN_OUI_LEN > len) {
3197 err = -EINVAL;
3198 brcmf_err("no multicast cipher suite\n");
3199 goto exit;
3202 if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
3203 err = -EINVAL;
3204 brcmf_err("ivalid OUI\n");
3205 goto exit;
3207 offset += TLV_OUI_LEN;
3209 /* pick up multicast cipher */
3210 switch (data[offset]) {
3211 case WPA_CIPHER_NONE:
3212 gval = 0;
3213 break;
3214 case WPA_CIPHER_WEP_40:
3215 case WPA_CIPHER_WEP_104:
3216 gval = WEP_ENABLED;
3217 break;
3218 case WPA_CIPHER_TKIP:
3219 gval = TKIP_ENABLED;
3220 break;
3221 case WPA_CIPHER_AES_CCM:
3222 gval = AES_ENABLED;
3223 break;
3224 default:
3225 err = -EINVAL;
3226 brcmf_err("Invalid multi cast cipher info\n");
3227 goto exit;
3230 offset++;
3231 /* walk thru unicast cipher list and pick up what we recognize */
3232 count = data[offset] + (data[offset + 1] << 8);
3233 offset += WPA_IE_SUITE_COUNT_LEN;
3234 /* Check for unicast suite(s) */
3235 if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) {
3236 err = -EINVAL;
3237 brcmf_err("no unicast cipher suite\n");
3238 goto exit;
3240 for (i = 0; i < count; i++) {
3241 if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
3242 err = -EINVAL;
3243 brcmf_err("ivalid OUI\n");
3244 goto exit;
3246 offset += TLV_OUI_LEN;
3247 switch (data[offset]) {
3248 case WPA_CIPHER_NONE:
3249 break;
3250 case WPA_CIPHER_WEP_40:
3251 case WPA_CIPHER_WEP_104:
3252 pval |= WEP_ENABLED;
3253 break;
3254 case WPA_CIPHER_TKIP:
3255 pval |= TKIP_ENABLED;
3256 break;
3257 case WPA_CIPHER_AES_CCM:
3258 pval |= AES_ENABLED;
3259 break;
3260 default:
3261 brcmf_err("Ivalid unicast security info\n");
3263 offset++;
3265 /* walk thru auth management suite list and pick up what we recognize */
3266 count = data[offset] + (data[offset + 1] << 8);
3267 offset += WPA_IE_SUITE_COUNT_LEN;
3268 /* Check for auth key management suite(s) */
3269 if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) {
3270 err = -EINVAL;
3271 brcmf_err("no auth key mgmt suite\n");
3272 goto exit;
3274 for (i = 0; i < count; i++) {
3275 if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {
3276 err = -EINVAL;
3277 brcmf_err("ivalid OUI\n");
3278 goto exit;
3280 offset += TLV_OUI_LEN;
3281 switch (data[offset]) {
3282 case RSN_AKM_NONE:
3283 brcmf_dbg(TRACE, "RSN_AKM_NONE\n");
3284 wpa_auth |= WPA_AUTH_NONE;
3285 break;
3286 case RSN_AKM_UNSPECIFIED:
3287 brcmf_dbg(TRACE, "RSN_AKM_UNSPECIFIED\n");
3288 is_rsn_ie ? (wpa_auth |= WPA2_AUTH_UNSPECIFIED) :
3289 (wpa_auth |= WPA_AUTH_UNSPECIFIED);
3290 break;
3291 case RSN_AKM_PSK:
3292 brcmf_dbg(TRACE, "RSN_AKM_PSK\n");
3293 is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) :
3294 (wpa_auth |= WPA_AUTH_PSK);
3295 break;
3296 default:
3297 brcmf_err("Ivalid key mgmt info\n");
3299 offset++;
3302 if (is_rsn_ie) {
3303 wme_bss_disable = 1;
3304 if ((offset + RSN_CAP_LEN) <= len) {
3305 rsn_cap = data[offset] + (data[offset + 1] << 8);
3306 if (rsn_cap & RSN_CAP_PTK_REPLAY_CNTR_MASK)
3307 wme_bss_disable = 0;
3309 /* set wme_bss_disable to sync RSN Capabilities */
3310 err = brcmf_fil_bsscfg_int_set(ifp, "wme_bss_disable",
3311 wme_bss_disable);
3312 if (err < 0) {
3313 brcmf_err("wme_bss_disable error %d\n", err);
3314 goto exit;
3317 /* FOR WPS , set SES_OW_ENABLED */
3318 wsec = (pval | gval | SES_OW_ENABLED);
3320 /* set auth */
3321 err = brcmf_fil_bsscfg_int_set(ifp, "auth", auth);
3322 if (err < 0) {
3323 brcmf_err("auth error %d\n", err);
3324 goto exit;
3326 /* set wsec */
3327 err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
3328 if (err < 0) {
3329 brcmf_err("wsec error %d\n", err);
3330 goto exit;
3332 /* set upper-layer auth */
3333 err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_auth);
3334 if (err < 0) {
3335 brcmf_err("wpa_auth error %d\n", err);
3336 goto exit;
3339 exit:
3340 return err;
3343 static s32
3344 brcmf_parse_vndr_ies(const u8 *vndr_ie_buf, u32 vndr_ie_len,
3345 struct parsed_vndr_ies *vndr_ies)
3347 s32 err = 0;
3348 struct brcmf_vs_tlv *vndrie;
3349 struct brcmf_tlv *ie;
3350 struct parsed_vndr_ie_info *parsed_info;
3351 s32 remaining_len;
3353 remaining_len = (s32)vndr_ie_len;
3354 memset(vndr_ies, 0, sizeof(*vndr_ies));
3356 ie = (struct brcmf_tlv *)vndr_ie_buf;
3357 while (ie) {
3358 if (ie->id != WLAN_EID_VENDOR_SPECIFIC)
3359 goto next;
3360 vndrie = (struct brcmf_vs_tlv *)ie;
3361 /* len should be bigger than OUI length + one */
3362 if (vndrie->len < (VS_IE_FIXED_HDR_LEN - TLV_HDR_LEN + 1)) {
3363 brcmf_err("invalid vndr ie. length is too small %d\n",
3364 vndrie->len);
3365 goto next;
3367 /* if wpa or wme ie, do not add ie */
3368 if (!memcmp(vndrie->oui, (u8 *)WPA_OUI, TLV_OUI_LEN) &&
3369 ((vndrie->oui_type == WPA_OUI_TYPE) ||
3370 (vndrie->oui_type == WME_OUI_TYPE))) {
3371 brcmf_dbg(TRACE, "Found WPA/WME oui. Do not add it\n");
3372 goto next;
3375 parsed_info = &vndr_ies->ie_info[vndr_ies->count];
3377 /* save vndr ie information */
3378 parsed_info->ie_ptr = (char *)vndrie;
3379 parsed_info->ie_len = vndrie->len + TLV_HDR_LEN;
3380 memcpy(&parsed_info->vndrie, vndrie, sizeof(*vndrie));
3382 vndr_ies->count++;
3384 brcmf_dbg(TRACE, "** OUI %02x %02x %02x, type 0x%02x\n",
3385 parsed_info->vndrie.oui[0],
3386 parsed_info->vndrie.oui[1],
3387 parsed_info->vndrie.oui[2],
3388 parsed_info->vndrie.oui_type);
3390 if (vndr_ies->count >= VNDR_IE_PARSE_LIMIT)
3391 break;
3392 next:
3393 remaining_len -= (ie->len + TLV_HDR_LEN);
3394 if (remaining_len <= TLV_HDR_LEN)
3395 ie = NULL;
3396 else
3397 ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len +
3398 TLV_HDR_LEN);
3400 return err;
3403 static u32
3404 brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd)
3407 __le32 iecount_le;
3408 __le32 pktflag_le;
3410 strncpy(iebuf, add_del_cmd, VNDR_IE_CMD_LEN - 1);
3411 iebuf[VNDR_IE_CMD_LEN - 1] = '\0';
3413 iecount_le = cpu_to_le32(1);
3414 memcpy(&iebuf[VNDR_IE_COUNT_OFFSET], &iecount_le, sizeof(iecount_le));
3416 pktflag_le = cpu_to_le32(pktflag);
3417 memcpy(&iebuf[VNDR_IE_PKTFLAG_OFFSET], &pktflag_le, sizeof(pktflag_le));
3419 memcpy(&iebuf[VNDR_IE_VSIE_OFFSET], ie_ptr, ie_len);
3421 return ie_len + VNDR_IE_HDR_SIZE;
3424 s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
3425 const u8 *vndr_ie_buf, u32 vndr_ie_len)
3427 struct brcmf_if *ifp;
3428 struct vif_saved_ie *saved_ie;
3429 s32 err = 0;
3430 u8 *iovar_ie_buf;
3431 u8 *curr_ie_buf;
3432 u8 *mgmt_ie_buf = NULL;
3433 int mgmt_ie_buf_len;
3434 u32 *mgmt_ie_len;
3435 u32 del_add_ie_buf_len = 0;
3436 u32 total_ie_buf_len = 0;
3437 u32 parsed_ie_buf_len = 0;
3438 struct parsed_vndr_ies old_vndr_ies;
3439 struct parsed_vndr_ies new_vndr_ies;
3440 struct parsed_vndr_ie_info *vndrie_info;
3441 s32 i;
3442 u8 *ptr;
3443 int remained_buf_len;
3445 if (!vif)
3446 return -ENODEV;
3447 ifp = vif->ifp;
3448 saved_ie = &vif->saved_ie;
3450 brcmf_dbg(TRACE, "bssidx %d, pktflag : 0x%02X\n", ifp->bssidx, pktflag);
3451 iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
3452 if (!iovar_ie_buf)
3453 return -ENOMEM;
3454 curr_ie_buf = iovar_ie_buf;
3455 switch (pktflag) {
3456 case BRCMF_VNDR_IE_PRBREQ_FLAG:
3457 mgmt_ie_buf = saved_ie->probe_req_ie;
3458 mgmt_ie_len = &saved_ie->probe_req_ie_len;
3459 mgmt_ie_buf_len = sizeof(saved_ie->probe_req_ie);
3460 break;
3461 case BRCMF_VNDR_IE_PRBRSP_FLAG:
3462 mgmt_ie_buf = saved_ie->probe_res_ie;
3463 mgmt_ie_len = &saved_ie->probe_res_ie_len;
3464 mgmt_ie_buf_len = sizeof(saved_ie->probe_res_ie);
3465 break;
3466 case BRCMF_VNDR_IE_BEACON_FLAG:
3467 mgmt_ie_buf = saved_ie->beacon_ie;
3468 mgmt_ie_len = &saved_ie->beacon_ie_len;
3469 mgmt_ie_buf_len = sizeof(saved_ie->beacon_ie);
3470 break;
3471 case BRCMF_VNDR_IE_ASSOCREQ_FLAG:
3472 mgmt_ie_buf = saved_ie->assoc_req_ie;
3473 mgmt_ie_len = &saved_ie->assoc_req_ie_len;
3474 mgmt_ie_buf_len = sizeof(saved_ie->assoc_req_ie);
3475 break;
3476 default:
3477 err = -EPERM;
3478 brcmf_err("not suitable type\n");
3479 goto exit;
3482 if (vndr_ie_len > mgmt_ie_buf_len) {
3483 err = -ENOMEM;
3484 brcmf_err("extra IE size too big\n");
3485 goto exit;
3488 /* parse and save new vndr_ie in curr_ie_buff before comparing it */
3489 if (vndr_ie_buf && vndr_ie_len && curr_ie_buf) {
3490 ptr = curr_ie_buf;
3491 brcmf_parse_vndr_ies(vndr_ie_buf, vndr_ie_len, &new_vndr_ies);
3492 for (i = 0; i < new_vndr_ies.count; i++) {
3493 vndrie_info = &new_vndr_ies.ie_info[i];
3494 memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr,
3495 vndrie_info->ie_len);
3496 parsed_ie_buf_len += vndrie_info->ie_len;
3500 if (mgmt_ie_buf && *mgmt_ie_len) {
3501 if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) &&
3502 (memcmp(mgmt_ie_buf, curr_ie_buf,
3503 parsed_ie_buf_len) == 0)) {
3504 brcmf_dbg(TRACE, "Previous mgmt IE equals to current IE\n");
3505 goto exit;
3508 /* parse old vndr_ie */
3509 brcmf_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len, &old_vndr_ies);
3511 /* make a command to delete old ie */
3512 for (i = 0; i < old_vndr_ies.count; i++) {
3513 vndrie_info = &old_vndr_ies.ie_info[i];
3515 brcmf_dbg(TRACE, "DEL ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
3516 vndrie_info->vndrie.id,
3517 vndrie_info->vndrie.len,
3518 vndrie_info->vndrie.oui[0],
3519 vndrie_info->vndrie.oui[1],
3520 vndrie_info->vndrie.oui[2]);
3522 del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag,
3523 vndrie_info->ie_ptr,
3524 vndrie_info->ie_len,
3525 "del");
3526 curr_ie_buf += del_add_ie_buf_len;
3527 total_ie_buf_len += del_add_ie_buf_len;
3531 *mgmt_ie_len = 0;
3532 /* Add if there is any extra IE */
3533 if (mgmt_ie_buf && parsed_ie_buf_len) {
3534 ptr = mgmt_ie_buf;
3536 remained_buf_len = mgmt_ie_buf_len;
3538 /* make a command to add new ie */
3539 for (i = 0; i < new_vndr_ies.count; i++) {
3540 vndrie_info = &new_vndr_ies.ie_info[i];
3542 /* verify remained buf size before copy data */
3543 if (remained_buf_len < (vndrie_info->vndrie.len +
3544 VNDR_IE_VSIE_OFFSET)) {
3545 brcmf_err("no space in mgmt_ie_buf: len left %d",
3546 remained_buf_len);
3547 break;
3549 remained_buf_len -= (vndrie_info->ie_len +
3550 VNDR_IE_VSIE_OFFSET);
3552 brcmf_dbg(TRACE, "ADDED ID : %d, Len: %d, OUI:%02x:%02x:%02x\n",
3553 vndrie_info->vndrie.id,
3554 vndrie_info->vndrie.len,
3555 vndrie_info->vndrie.oui[0],
3556 vndrie_info->vndrie.oui[1],
3557 vndrie_info->vndrie.oui[2]);
3559 del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag,
3560 vndrie_info->ie_ptr,
3561 vndrie_info->ie_len,
3562 "add");
3564 /* save the parsed IE in wl struct */
3565 memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr,
3566 vndrie_info->ie_len);
3567 *mgmt_ie_len += vndrie_info->ie_len;
3569 curr_ie_buf += del_add_ie_buf_len;
3570 total_ie_buf_len += del_add_ie_buf_len;
3573 if (total_ie_buf_len) {
3574 err = brcmf_fil_bsscfg_data_set(ifp, "vndr_ie", iovar_ie_buf,
3575 total_ie_buf_len);
3576 if (err)
3577 brcmf_err("vndr ie set error : %d\n", err);
3580 exit:
3581 kfree(iovar_ie_buf);
3582 return err;
3585 s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif)
3587 s32 pktflags[] = {
3588 BRCMF_VNDR_IE_PRBREQ_FLAG,
3589 BRCMF_VNDR_IE_PRBRSP_FLAG,
3590 BRCMF_VNDR_IE_BEACON_FLAG
3592 int i;
3594 for (i = 0; i < ARRAY_SIZE(pktflags); i++)
3595 brcmf_vif_set_mgmt_ie(vif, pktflags[i], NULL, 0);
3597 memset(&vif->saved_ie, 0, sizeof(vif->saved_ie));
3598 return 0;
3601 static s32
3602 brcmf_config_ap_mgmt_ie(struct brcmf_cfg80211_vif *vif,
3603 struct cfg80211_beacon_data *beacon)
3605 s32 err;
3607 /* Set Beacon IEs to FW */
3608 err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_BEACON_FLAG,
3609 beacon->tail, beacon->tail_len);
3610 if (err) {
3611 brcmf_err("Set Beacon IE Failed\n");
3612 return err;
3614 brcmf_dbg(TRACE, "Applied Vndr IEs for Beacon\n");
3616 /* Set Probe Response IEs to FW */
3617 err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBRSP_FLAG,
3618 beacon->proberesp_ies,
3619 beacon->proberesp_ies_len);
3620 if (err)
3621 brcmf_err("Set Probe Resp IE Failed\n");
3622 else
3623 brcmf_dbg(TRACE, "Applied Vndr IEs for Probe Resp\n");
3625 return err;
3628 static s32
3629 brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
3630 struct cfg80211_ap_settings *settings)
3632 s32 ie_offset;
3633 struct brcmf_if *ifp = netdev_priv(ndev);
3634 struct brcmf_tlv *ssid_ie;
3635 struct brcmf_ssid_le ssid_le;
3636 s32 err = -EPERM;
3637 struct brcmf_tlv *rsn_ie;
3638 struct brcmf_vs_tlv *wpa_ie;
3639 struct brcmf_join_params join_params;
3640 enum nl80211_iftype dev_role;
3641 struct brcmf_fil_bss_enable_le bss_enable;
3643 brcmf_dbg(TRACE, "channel_type=%d, beacon_interval=%d, dtim_period=%d,\n",
3644 cfg80211_get_chandef_type(&settings->chandef),
3645 settings->beacon_interval,
3646 settings->dtim_period);
3647 brcmf_dbg(TRACE, "ssid=%s(%zu), auth_type=%d, inactivity_timeout=%d\n",
3648 settings->ssid, settings->ssid_len, settings->auth_type,
3649 settings->inactivity_timeout);
3651 dev_role = ifp->vif->wdev.iftype;
3653 memset(&ssid_le, 0, sizeof(ssid_le));
3654 if (settings->ssid == NULL || settings->ssid_len == 0) {
3655 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
3656 ssid_ie = brcmf_parse_tlvs(
3657 (u8 *)&settings->beacon.head[ie_offset],
3658 settings->beacon.head_len - ie_offset,
3659 WLAN_EID_SSID);
3660 if (!ssid_ie)
3661 return -EINVAL;
3663 memcpy(ssid_le.SSID, ssid_ie->data, ssid_ie->len);
3664 ssid_le.SSID_len = cpu_to_le32(ssid_ie->len);
3665 brcmf_dbg(TRACE, "SSID is (%s) in Head\n", ssid_le.SSID);
3666 } else {
3667 memcpy(ssid_le.SSID, settings->ssid, settings->ssid_len);
3668 ssid_le.SSID_len = cpu_to_le32((u32)settings->ssid_len);
3671 brcmf_set_mpc(ndev, 0);
3673 /* find the RSN_IE */
3674 rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
3675 settings->beacon.tail_len, WLAN_EID_RSN);
3677 /* find the WPA_IE */
3678 wpa_ie = brcmf_find_wpaie((u8 *)settings->beacon.tail,
3679 settings->beacon.tail_len);
3681 if ((wpa_ie != NULL || rsn_ie != NULL)) {
3682 brcmf_dbg(TRACE, "WPA(2) IE is found\n");
3683 if (wpa_ie != NULL) {
3684 /* WPA IE */
3685 err = brcmf_configure_wpaie(ndev, wpa_ie, false);
3686 if (err < 0)
3687 goto exit;
3688 } else {
3689 /* RSN IE */
3690 err = brcmf_configure_wpaie(ndev,
3691 (struct brcmf_vs_tlv *)rsn_ie, true);
3692 if (err < 0)
3693 goto exit;
3695 } else {
3696 brcmf_dbg(TRACE, "No WPA(2) IEs found\n");
3697 brcmf_configure_opensecurity(ifp);
3700 brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon);
3702 if (settings->beacon_interval) {
3703 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,
3704 settings->beacon_interval);
3705 if (err < 0) {
3706 brcmf_err("Beacon Interval Set Error, %d\n", err);
3707 goto exit;
3710 if (settings->dtim_period) {
3711 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_DTIMPRD,
3712 settings->dtim_period);
3713 if (err < 0) {
3714 brcmf_err("DTIM Interval Set Error, %d\n", err);
3715 goto exit;
3719 if (dev_role == NL80211_IFTYPE_AP) {
3720 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
3721 if (err < 0) {
3722 brcmf_err("BRCMF_C_DOWN error %d\n", err);
3723 goto exit;
3725 brcmf_fil_iovar_int_set(ifp, "apsta", 0);
3728 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1);
3729 if (err < 0) {
3730 brcmf_err("SET INFRA error %d\n", err);
3731 goto exit;
3733 if (dev_role == NL80211_IFTYPE_AP) {
3734 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1);
3735 if (err < 0) {
3736 brcmf_err("setting AP mode failed %d\n", err);
3737 goto exit;
3739 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
3740 if (err < 0) {
3741 brcmf_err("BRCMF_C_UP error (%d)\n", err);
3742 goto exit;
3745 memset(&join_params, 0, sizeof(join_params));
3746 /* join parameters starts with ssid */
3747 memcpy(&join_params.ssid_le, &ssid_le, sizeof(ssid_le));
3748 /* create softap */
3749 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
3750 &join_params, sizeof(join_params));
3751 if (err < 0) {
3752 brcmf_err("SET SSID error (%d)\n", err);
3753 goto exit;
3755 brcmf_dbg(TRACE, "AP mode configuration complete\n");
3756 } else {
3757 err = brcmf_fil_bsscfg_data_set(ifp, "ssid", &ssid_le,
3758 sizeof(ssid_le));
3759 if (err < 0) {
3760 brcmf_err("setting ssid failed %d\n", err);
3761 goto exit;
3763 bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx);
3764 bss_enable.enable = cpu_to_le32(1);
3765 err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable,
3766 sizeof(bss_enable));
3767 if (err < 0) {
3768 brcmf_err("bss_enable config failed %d\n", err);
3769 goto exit;
3772 brcmf_dbg(TRACE, "GO mode configuration complete\n");
3774 clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
3775 set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
3777 exit:
3778 if (err)
3779 brcmf_set_mpc(ndev, 1);
3780 return err;
3783 static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
3785 struct brcmf_if *ifp = netdev_priv(ndev);
3786 s32 err = -EPERM;
3787 struct brcmf_fil_bss_enable_le bss_enable;
3789 brcmf_dbg(TRACE, "Enter\n");
3791 if (ifp->vif->wdev.iftype == NL80211_IFTYPE_AP) {
3792 /* Due to most likely deauths outstanding we sleep */
3793 /* first to make sure they get processed by fw. */
3794 msleep(400);
3795 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
3796 if (err < 0) {
3797 brcmf_err("setting AP mode failed %d\n", err);
3798 goto exit;
3800 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
3801 if (err < 0) {
3802 brcmf_err("BRCMF_C_UP error %d\n", err);
3803 goto exit;
3805 } else {
3806 bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx);
3807 bss_enable.enable = cpu_to_le32(0);
3808 err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable,
3809 sizeof(bss_enable));
3810 if (err < 0)
3811 brcmf_err("bss_enable config failed %d\n", err);
3813 brcmf_set_mpc(ndev, 1);
3814 set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
3815 clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
3817 exit:
3818 return err;
3821 static s32
3822 brcmf_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *ndev,
3823 struct cfg80211_beacon_data *info)
3825 struct brcmf_if *ifp = netdev_priv(ndev);
3826 s32 err;
3828 brcmf_dbg(TRACE, "Enter\n");
3830 err = brcmf_config_ap_mgmt_ie(ifp->vif, info);
3832 return err;
3835 static int
3836 brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
3837 u8 *mac)
3839 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
3840 struct brcmf_scb_val_le scbval;
3841 struct brcmf_if *ifp = netdev_priv(ndev);
3842 s32 err;
3844 if (!mac)
3845 return -EFAULT;
3847 brcmf_dbg(TRACE, "Enter %pM\n", mac);
3849 if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
3850 ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
3851 if (!check_vif_up(ifp->vif))
3852 return -EIO;
3854 memcpy(&scbval.ea, mac, ETH_ALEN);
3855 scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING);
3856 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON,
3857 &scbval, sizeof(scbval));
3858 if (err)
3859 brcmf_err("SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err);
3861 brcmf_dbg(TRACE, "Exit\n");
3862 return err;
3866 static void
3867 brcmf_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
3868 struct wireless_dev *wdev,
3869 u16 frame_type, bool reg)
3871 struct brcmf_cfg80211_vif *vif;
3872 u16 mgmt_type;
3874 brcmf_dbg(TRACE, "Enter, frame_type %04x, reg=%d\n", frame_type, reg);
3876 mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4;
3877 vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
3878 if (reg)
3879 vif->mgmt_rx_reg |= BIT(mgmt_type);
3880 else
3881 vif->mgmt_rx_reg &= ~BIT(mgmt_type);
3885 static int
3886 brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
3887 struct ieee80211_channel *chan, bool offchan,
3888 unsigned int wait, const u8 *buf, size_t len,
3889 bool no_cck, bool dont_wait_for_ack, u64 *cookie)
3891 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
3892 const struct ieee80211_mgmt *mgmt;
3893 struct brcmf_cfg80211_vif *vif;
3894 s32 err = 0;
3895 s32 ie_offset;
3896 s32 ie_len;
3897 struct brcmf_fil_action_frame_le *action_frame;
3898 struct brcmf_fil_af_params_le *af_params;
3899 bool ack;
3900 s32 chan_nr;
3902 brcmf_dbg(TRACE, "Enter\n");
3904 *cookie = 0;
3906 mgmt = (const struct ieee80211_mgmt *)buf;
3908 if (!ieee80211_is_mgmt(mgmt->frame_control)) {
3909 brcmf_err("Driver only allows MGMT packet type\n");
3910 return -EPERM;
3913 if (ieee80211_is_probe_resp(mgmt->frame_control)) {
3914 /* Right now the only reason to get a probe response */
3915 /* is for p2p listen response or for p2p GO from */
3916 /* wpa_supplicant. Unfortunately the probe is send */
3917 /* on primary ndev, while dongle wants it on the p2p */
3918 /* vif. Since this is only reason for a probe */
3919 /* response to be sent, the vif is taken from cfg. */
3920 /* If ever desired to send proberesp for non p2p */
3921 /* response then data should be checked for */
3922 /* "DIRECT-". Note in future supplicant will take */
3923 /* dedicated p2p wdev to do this and then this 'hack'*/
3924 /* is not needed anymore. */
3925 ie_offset = DOT11_MGMT_HDR_LEN +
3926 DOT11_BCN_PRB_FIXED_LEN;
3927 ie_len = len - ie_offset;
3928 vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
3929 if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif)
3930 vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
3931 err = brcmf_vif_set_mgmt_ie(vif,
3932 BRCMF_VNDR_IE_PRBRSP_FLAG,
3933 &buf[ie_offset],
3934 ie_len);
3935 cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,
3936 GFP_KERNEL);
3937 } else if (ieee80211_is_action(mgmt->frame_control)) {
3938 af_params = kzalloc(sizeof(*af_params), GFP_KERNEL);
3939 if (af_params == NULL) {
3940 brcmf_err("unable to allocate frame\n");
3941 err = -ENOMEM;
3942 goto exit;
3944 action_frame = &af_params->action_frame;
3945 /* Add the packet Id */
3946 action_frame->packet_id = cpu_to_le32(*cookie);
3947 /* Add BSSID */
3948 memcpy(&action_frame->da[0], &mgmt->da[0], ETH_ALEN);
3949 memcpy(&af_params->bssid[0], &mgmt->bssid[0], ETH_ALEN);
3950 /* Add the length exepted for 802.11 header */
3951 action_frame->len = cpu_to_le16(len - DOT11_MGMT_HDR_LEN);
3952 /* Add the channel */
3953 chan_nr = ieee80211_frequency_to_channel(chan->center_freq);
3954 af_params->channel = cpu_to_le32(chan_nr);
3956 memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN],
3957 le16_to_cpu(action_frame->len));
3959 brcmf_dbg(TRACE, "Action frame, cookie=%lld, len=%d, freq=%d\n",
3960 *cookie, le16_to_cpu(action_frame->len),
3961 chan->center_freq);
3963 ack = brcmf_p2p_send_action_frame(cfg, cfg_to_ndev(cfg),
3964 af_params);
3966 cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack,
3967 GFP_KERNEL);
3968 kfree(af_params);
3969 } else {
3970 brcmf_dbg(TRACE, "Unhandled, fc=%04x!!\n", mgmt->frame_control);
3971 brcmf_dbg_hex_dump(true, buf, len, "payload, len=%Zu\n", len);
3974 exit:
3975 return err;
3979 static int
3980 brcmf_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
3981 struct wireless_dev *wdev,
3982 u64 cookie)
3984 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
3985 struct brcmf_cfg80211_vif *vif;
3986 int err = 0;
3988 brcmf_dbg(TRACE, "Enter p2p listen cancel\n");
3990 vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
3991 if (vif == NULL) {
3992 brcmf_err("No p2p device available for probe response\n");
3993 err = -ENODEV;
3994 goto exit;
3996 brcmf_p2p_cancel_remain_on_channel(vif->ifp);
3997 exit:
3998 return err;
4001 static struct cfg80211_ops wl_cfg80211_ops = {
4002 .add_virtual_intf = brcmf_cfg80211_add_iface,
4003 .del_virtual_intf = brcmf_cfg80211_del_iface,
4004 .change_virtual_intf = brcmf_cfg80211_change_iface,
4005 .scan = brcmf_cfg80211_scan,
4006 .set_wiphy_params = brcmf_cfg80211_set_wiphy_params,
4007 .join_ibss = brcmf_cfg80211_join_ibss,
4008 .leave_ibss = brcmf_cfg80211_leave_ibss,
4009 .get_station = brcmf_cfg80211_get_station,
4010 .set_tx_power = brcmf_cfg80211_set_tx_power,
4011 .get_tx_power = brcmf_cfg80211_get_tx_power,
4012 .add_key = brcmf_cfg80211_add_key,
4013 .del_key = brcmf_cfg80211_del_key,
4014 .get_key = brcmf_cfg80211_get_key,
4015 .set_default_key = brcmf_cfg80211_config_default_key,
4016 .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key,
4017 .set_power_mgmt = brcmf_cfg80211_set_power_mgmt,
4018 .connect = brcmf_cfg80211_connect,
4019 .disconnect = brcmf_cfg80211_disconnect,
4020 .suspend = brcmf_cfg80211_suspend,
4021 .resume = brcmf_cfg80211_resume,
4022 .set_pmksa = brcmf_cfg80211_set_pmksa,
4023 .del_pmksa = brcmf_cfg80211_del_pmksa,
4024 .flush_pmksa = brcmf_cfg80211_flush_pmksa,
4025 .start_ap = brcmf_cfg80211_start_ap,
4026 .stop_ap = brcmf_cfg80211_stop_ap,
4027 .change_beacon = brcmf_cfg80211_change_beacon,
4028 .del_station = brcmf_cfg80211_del_station,
4029 .sched_scan_start = brcmf_cfg80211_sched_scan_start,
4030 .sched_scan_stop = brcmf_cfg80211_sched_scan_stop,
4031 .mgmt_frame_register = brcmf_cfg80211_mgmt_frame_register,
4032 .mgmt_tx = brcmf_cfg80211_mgmt_tx,
4033 .remain_on_channel = brcmf_p2p_remain_on_channel,
4034 .cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel,
4035 #ifdef CONFIG_NL80211_TESTMODE
4036 .testmode_cmd = brcmf_cfg80211_testmode
4037 #endif
4040 static s32 brcmf_nl80211_iftype_to_mode(enum nl80211_iftype type)
4042 switch (type) {
4043 case NL80211_IFTYPE_AP_VLAN:
4044 case NL80211_IFTYPE_WDS:
4045 case NL80211_IFTYPE_MONITOR:
4046 case NL80211_IFTYPE_MESH_POINT:
4047 return -ENOTSUPP;
4048 case NL80211_IFTYPE_ADHOC:
4049 return WL_MODE_IBSS;
4050 case NL80211_IFTYPE_STATION:
4051 case NL80211_IFTYPE_P2P_CLIENT:
4052 return WL_MODE_BSS;
4053 case NL80211_IFTYPE_AP:
4054 case NL80211_IFTYPE_P2P_GO:
4055 return WL_MODE_AP;
4056 case NL80211_IFTYPE_P2P_DEVICE:
4057 return WL_MODE_P2P;
4058 case NL80211_IFTYPE_UNSPECIFIED:
4059 default:
4060 break;
4063 return -EINVAL;
4066 static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
4068 /* scheduled scan settings */
4069 wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
4070 wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
4071 wiphy->max_sched_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
4072 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
4075 static const struct ieee80211_iface_limit brcmf_iface_limits[] = {
4077 .max = 2,
4078 .types = BIT(NL80211_IFTYPE_STATION) |
4079 BIT(NL80211_IFTYPE_ADHOC) |
4080 BIT(NL80211_IFTYPE_AP)
4083 .max = 1,
4084 .types = BIT(NL80211_IFTYPE_P2P_DEVICE)
4087 .max = 1,
4088 .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
4089 BIT(NL80211_IFTYPE_P2P_GO)
4092 static const struct ieee80211_iface_combination brcmf_iface_combos[] = {
4094 .max_interfaces = BRCMF_IFACE_MAX_CNT,
4095 .num_different_channels = 1, /* no multi-channel for now */
4096 .n_limits = ARRAY_SIZE(brcmf_iface_limits),
4097 .limits = brcmf_iface_limits
4101 static const struct ieee80211_txrx_stypes
4102 brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
4103 [NL80211_IFTYPE_STATION] = {
4104 .tx = 0xffff,
4105 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
4106 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
4108 [NL80211_IFTYPE_P2P_CLIENT] = {
4109 .tx = 0xffff,
4110 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
4111 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
4113 [NL80211_IFTYPE_P2P_GO] = {
4114 .tx = 0xffff,
4115 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
4116 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
4117 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
4118 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
4119 BIT(IEEE80211_STYPE_AUTH >> 4) |
4120 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
4121 BIT(IEEE80211_STYPE_ACTION >> 4)
4125 static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
4127 struct wiphy *wiphy;
4128 s32 err = 0;
4130 wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info));
4131 if (!wiphy) {
4132 brcmf_err("Could not allocate wiphy device\n");
4133 return ERR_PTR(-ENOMEM);
4135 set_wiphy_dev(wiphy, phydev);
4136 wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
4137 wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
4138 wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
4139 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
4140 BIT(NL80211_IFTYPE_ADHOC) |
4141 BIT(NL80211_IFTYPE_AP) |
4142 BIT(NL80211_IFTYPE_P2P_CLIENT) |
4143 BIT(NL80211_IFTYPE_P2P_GO) |
4144 BIT(NL80211_IFTYPE_P2P_DEVICE);
4145 wiphy->iface_combinations = brcmf_iface_combos;
4146 wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
4147 wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
4148 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
4149 wiphy->cipher_suites = __wl_cipher_suites;
4150 wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
4151 wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT |
4152 WIPHY_FLAG_OFFCHAN_TX |
4153 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
4154 wiphy->mgmt_stypes = brcmf_txrx_stypes;
4155 wiphy->max_remain_on_channel_duration = 5000;
4156 brcmf_wiphy_pno_params(wiphy);
4157 brcmf_dbg(INFO, "Registering custom regulatory\n");
4158 wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
4159 wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
4160 err = wiphy_register(wiphy);
4161 if (err < 0) {
4162 brcmf_err("Could not register wiphy device (%d)\n", err);
4163 wiphy_free(wiphy);
4164 return ERR_PTR(err);
4166 return wiphy;
4169 struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
4170 enum nl80211_iftype type,
4171 bool pm_block)
4173 struct brcmf_cfg80211_vif *vif;
4175 if (cfg->vif_cnt == BRCMF_IFACE_MAX_CNT)
4176 return ERR_PTR(-ENOSPC);
4178 brcmf_dbg(TRACE, "allocating virtual interface (size=%zu)\n",
4179 sizeof(*vif));
4180 vif = kzalloc(sizeof(*vif), GFP_KERNEL);
4181 if (!vif)
4182 return ERR_PTR(-ENOMEM);
4184 vif->wdev.wiphy = cfg->wiphy;
4185 vif->wdev.iftype = type;
4187 vif->mode = brcmf_nl80211_iftype_to_mode(type);
4188 vif->pm_block = pm_block;
4189 vif->roam_off = -1;
4191 brcmf_init_prof(&vif->profile);
4193 list_add_tail(&vif->list, &cfg->vif_list);
4194 cfg->vif_cnt++;
4195 return vif;
4198 void brcmf_free_vif(struct brcmf_cfg80211_vif *vif)
4200 struct brcmf_cfg80211_info *cfg;
4201 struct wiphy *wiphy;
4203 wiphy = vif->wdev.wiphy;
4204 cfg = wiphy_priv(wiphy);
4205 list_del(&vif->list);
4206 cfg->vif_cnt--;
4208 kfree(vif);
4209 if (!cfg->vif_cnt) {
4210 wiphy_unregister(wiphy);
4211 wiphy_free(wiphy);
4215 static bool brcmf_is_linkup(const struct brcmf_event_msg *e)
4217 u32 event = e->event_code;
4218 u32 status = e->status;
4220 if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
4221 brcmf_dbg(CONN, "Processing set ssid\n");
4222 return true;
4225 return false;
4228 static bool brcmf_is_linkdown(const struct brcmf_event_msg *e)
4230 u32 event = e->event_code;
4231 u16 flags = e->flags;
4233 if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) {
4234 brcmf_dbg(CONN, "Processing link down\n");
4235 return true;
4237 return false;
4240 static bool brcmf_is_nonetwork(struct brcmf_cfg80211_info *cfg,
4241 const struct brcmf_event_msg *e)
4243 u32 event = e->event_code;
4244 u32 status = e->status;
4246 if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) {
4247 brcmf_dbg(CONN, "Processing Link %s & no network found\n",
4248 e->flags & BRCMF_EVENT_MSG_LINK ? "up" : "down");
4249 return true;
4252 if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) {
4253 brcmf_dbg(CONN, "Processing connecting & no network found\n");
4254 return true;
4257 return false;
4260 static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg)
4262 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
4264 kfree(conn_info->req_ie);
4265 conn_info->req_ie = NULL;
4266 conn_info->req_ie_len = 0;
4267 kfree(conn_info->resp_ie);
4268 conn_info->resp_ie = NULL;
4269 conn_info->resp_ie_len = 0;
4272 static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
4273 struct brcmf_if *ifp)
4275 struct brcmf_cfg80211_assoc_ielen_le *assoc_info;
4276 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
4277 u32 req_len;
4278 u32 resp_len;
4279 s32 err = 0;
4281 brcmf_clear_assoc_ies(cfg);
4283 err = brcmf_fil_iovar_data_get(ifp, "assoc_info",
4284 cfg->extra_buf, WL_ASSOC_INFO_MAX);
4285 if (err) {
4286 brcmf_err("could not get assoc info (%d)\n", err);
4287 return err;
4289 assoc_info =
4290 (struct brcmf_cfg80211_assoc_ielen_le *)cfg->extra_buf;
4291 req_len = le32_to_cpu(assoc_info->req_len);
4292 resp_len = le32_to_cpu(assoc_info->resp_len);
4293 if (req_len) {
4294 err = brcmf_fil_iovar_data_get(ifp, "assoc_req_ies",
4295 cfg->extra_buf,
4296 WL_ASSOC_INFO_MAX);
4297 if (err) {
4298 brcmf_err("could not get assoc req (%d)\n", err);
4299 return err;
4301 conn_info->req_ie_len = req_len;
4302 conn_info->req_ie =
4303 kmemdup(cfg->extra_buf, conn_info->req_ie_len,
4304 GFP_KERNEL);
4305 } else {
4306 conn_info->req_ie_len = 0;
4307 conn_info->req_ie = NULL;
4309 if (resp_len) {
4310 err = brcmf_fil_iovar_data_get(ifp, "assoc_resp_ies",
4311 cfg->extra_buf,
4312 WL_ASSOC_INFO_MAX);
4313 if (err) {
4314 brcmf_err("could not get assoc resp (%d)\n", err);
4315 return err;
4317 conn_info->resp_ie_len = resp_len;
4318 conn_info->resp_ie =
4319 kmemdup(cfg->extra_buf, conn_info->resp_ie_len,
4320 GFP_KERNEL);
4321 } else {
4322 conn_info->resp_ie_len = 0;
4323 conn_info->resp_ie = NULL;
4325 brcmf_dbg(CONN, "req len (%d) resp len (%d)\n",
4326 conn_info->req_ie_len, conn_info->resp_ie_len);
4328 return err;
4331 static s32
4332 brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
4333 struct net_device *ndev,
4334 const struct brcmf_event_msg *e)
4336 struct brcmf_if *ifp = netdev_priv(ndev);
4337 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
4338 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
4339 struct wiphy *wiphy = cfg_to_wiphy(cfg);
4340 struct ieee80211_channel *notify_channel = NULL;
4341 struct ieee80211_supported_band *band;
4342 struct brcmf_bss_info_le *bi;
4343 u32 freq;
4344 s32 err = 0;
4345 u32 target_channel;
4346 u8 *buf;
4348 brcmf_dbg(TRACE, "Enter\n");
4350 brcmf_get_assoc_ies(cfg, ifp);
4351 memcpy(profile->bssid, e->addr, ETH_ALEN);
4352 brcmf_update_bss_info(cfg, ifp);
4354 buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
4355 if (buf == NULL) {
4356 err = -ENOMEM;
4357 goto done;
4360 /* data sent to dongle has to be little endian */
4361 *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
4362 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
4363 buf, WL_BSS_INFO_MAX);
4365 if (err)
4366 goto done;
4368 bi = (struct brcmf_bss_info_le *)(buf + 4);
4369 target_channel = bi->ctl_ch ? bi->ctl_ch :
4370 CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
4372 if (target_channel <= CH_MAX_2G_CHANNEL)
4373 band = wiphy->bands[IEEE80211_BAND_2GHZ];
4374 else
4375 band = wiphy->bands[IEEE80211_BAND_5GHZ];
4377 freq = ieee80211_channel_to_frequency(target_channel, band->band);
4378 notify_channel = ieee80211_get_channel(wiphy, freq);
4380 done:
4381 kfree(buf);
4382 cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid,
4383 conn_info->req_ie, conn_info->req_ie_len,
4384 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
4385 brcmf_dbg(CONN, "Report roaming result\n");
4387 set_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
4388 brcmf_dbg(TRACE, "Exit\n");
4389 return err;
4392 static s32
4393 brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg,
4394 struct net_device *ndev, const struct brcmf_event_msg *e,
4395 bool completed)
4397 struct brcmf_if *ifp = netdev_priv(ndev);
4398 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
4399 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
4400 s32 err = 0;
4402 brcmf_dbg(TRACE, "Enter\n");
4404 if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTING,
4405 &ifp->vif->sme_state)) {
4406 if (completed) {
4407 brcmf_get_assoc_ies(cfg, ifp);
4408 memcpy(profile->bssid, e->addr, ETH_ALEN);
4409 brcmf_update_bss_info(cfg, ifp);
4410 set_bit(BRCMF_VIF_STATUS_CONNECTED,
4411 &ifp->vif->sme_state);
4413 cfg80211_connect_result(ndev,
4414 (u8 *)profile->bssid,
4415 conn_info->req_ie,
4416 conn_info->req_ie_len,
4417 conn_info->resp_ie,
4418 conn_info->resp_ie_len,
4419 completed ? WLAN_STATUS_SUCCESS :
4420 WLAN_STATUS_AUTH_TIMEOUT,
4421 GFP_KERNEL);
4422 brcmf_dbg(CONN, "Report connect result - connection %s\n",
4423 completed ? "succeeded" : "failed");
4425 brcmf_dbg(TRACE, "Exit\n");
4426 return err;
4429 static s32
4430 brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,
4431 struct net_device *ndev,
4432 const struct brcmf_event_msg *e, void *data)
4434 static int generation;
4435 u32 event = e->event_code;
4436 u32 reason = e->reason;
4437 struct station_info sinfo;
4439 brcmf_dbg(CONN, "event %d, reason %d\n", event, reason);
4440 if (event == BRCMF_E_LINK && reason == BRCMF_E_REASON_LINK_BSSCFG_DIS &&
4441 ndev != cfg_to_ndev(cfg)) {
4442 brcmf_dbg(CONN, "AP mode link down\n");
4443 complete(&cfg->vif_disabled);
4444 return 0;
4447 if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) &&
4448 (reason == BRCMF_E_STATUS_SUCCESS)) {
4449 memset(&sinfo, 0, sizeof(sinfo));
4450 sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
4451 if (!data) {
4452 brcmf_err("No IEs present in ASSOC/REASSOC_IND");
4453 return -EINVAL;
4455 sinfo.assoc_req_ies = data;
4456 sinfo.assoc_req_ies_len = e->datalen;
4457 generation++;
4458 sinfo.generation = generation;
4459 cfg80211_new_sta(ndev, e->addr, &sinfo, GFP_KERNEL);
4460 } else if ((event == BRCMF_E_DISASSOC_IND) ||
4461 (event == BRCMF_E_DEAUTH_IND) ||
4462 (event == BRCMF_E_DEAUTH)) {
4463 cfg80211_del_sta(ndev, e->addr, GFP_KERNEL);
4465 return 0;
4468 static s32
4469 brcmf_notify_connect_status(struct brcmf_if *ifp,
4470 const struct brcmf_event_msg *e, void *data)
4472 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
4473 struct net_device *ndev = ifp->ndev;
4474 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
4475 s32 err = 0;
4477 if (ifp->vif->mode == WL_MODE_AP) {
4478 err = brcmf_notify_connect_status_ap(cfg, ndev, e, data);
4479 } else if (brcmf_is_linkup(e)) {
4480 brcmf_dbg(CONN, "Linkup\n");
4481 if (brcmf_is_ibssmode(ifp->vif)) {
4482 memcpy(profile->bssid, e->addr, ETH_ALEN);
4483 wl_inform_ibss(cfg, ndev, e->addr);
4484 cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
4485 clear_bit(BRCMF_VIF_STATUS_CONNECTING,
4486 &ifp->vif->sme_state);
4487 set_bit(BRCMF_VIF_STATUS_CONNECTED,
4488 &ifp->vif->sme_state);
4489 } else
4490 brcmf_bss_connect_done(cfg, ndev, e, true);
4491 } else if (brcmf_is_linkdown(e)) {
4492 brcmf_dbg(CONN, "Linkdown\n");
4493 if (!brcmf_is_ibssmode(ifp->vif)) {
4494 brcmf_bss_connect_done(cfg, ndev, e, false);
4495 if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED,
4496 &ifp->vif->sme_state))
4497 cfg80211_disconnected(ndev, 0, NULL, 0,
4498 GFP_KERNEL);
4500 brcmf_link_down(ifp->vif);
4501 brcmf_init_prof(ndev_to_prof(ndev));
4502 if (ndev != cfg_to_ndev(cfg))
4503 complete(&cfg->vif_disabled);
4504 } else if (brcmf_is_nonetwork(cfg, e)) {
4505 if (brcmf_is_ibssmode(ifp->vif))
4506 clear_bit(BRCMF_VIF_STATUS_CONNECTING,
4507 &ifp->vif->sme_state);
4508 else
4509 brcmf_bss_connect_done(cfg, ndev, e, false);
4512 return err;
4515 static s32
4516 brcmf_notify_roaming_status(struct brcmf_if *ifp,
4517 const struct brcmf_event_msg *e, void *data)
4519 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
4520 s32 err = 0;
4521 u32 event = e->event_code;
4522 u32 status = e->status;
4524 if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
4525 if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state))
4526 brcmf_bss_roaming_done(cfg, ifp->ndev, e);
4527 else
4528 brcmf_bss_connect_done(cfg, ifp->ndev, e, true);
4531 return err;
4534 static s32
4535 brcmf_notify_mic_status(struct brcmf_if *ifp,
4536 const struct brcmf_event_msg *e, void *data)
4538 u16 flags = e->flags;
4539 enum nl80211_key_type key_type;
4541 if (flags & BRCMF_EVENT_MSG_GROUP)
4542 key_type = NL80211_KEYTYPE_GROUP;
4543 else
4544 key_type = NL80211_KEYTYPE_PAIRWISE;
4546 cfg80211_michael_mic_failure(ifp->ndev, (u8 *)&e->addr, key_type, -1,
4547 NULL, GFP_KERNEL);
4549 return 0;
4552 static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,
4553 const struct brcmf_event_msg *e, void *data)
4555 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
4556 struct brcmf_if_event *ifevent = (struct brcmf_if_event *)data;
4557 struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;
4558 struct brcmf_cfg80211_vif *vif;
4560 brcmf_dbg(TRACE, "Enter: action %u flags %u ifidx %u bsscfg %u\n",
4561 ifevent->action, ifevent->flags, ifevent->ifidx,
4562 ifevent->bssidx);
4564 mutex_lock(&event->vif_event_lock);
4565 event->action = ifevent->action;
4566 vif = event->vif;
4568 switch (ifevent->action) {
4569 case BRCMF_E_IF_ADD:
4570 /* waiting process may have timed out */
4571 if (!cfg->vif_event.vif) {
4572 mutex_unlock(&event->vif_event_lock);
4573 return -EBADF;
4576 ifp->vif = vif;
4577 vif->ifp = ifp;
4578 vif->wdev.netdev = ifp->ndev;
4579 ifp->ndev->ieee80211_ptr = &vif->wdev;
4580 SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy));
4581 mutex_unlock(&event->vif_event_lock);
4582 wake_up(&event->vif_wq);
4583 return 0;
4585 case BRCMF_E_IF_DEL:
4586 ifp->vif = NULL;
4587 mutex_unlock(&event->vif_event_lock);
4588 /* event may not be upon user request */
4589 if (brcmf_cfg80211_vif_event_armed(cfg))
4590 wake_up(&event->vif_wq);
4591 return 0;
4593 case BRCMF_E_IF_CHANGE:
4594 mutex_unlock(&event->vif_event_lock);
4595 wake_up(&event->vif_wq);
4596 return 0;
4598 default:
4599 mutex_unlock(&event->vif_event_lock);
4600 break;
4602 return -EINVAL;
4605 static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
4607 conf->frag_threshold = (u32)-1;
4608 conf->rts_threshold = (u32)-1;
4609 conf->retry_short = (u32)-1;
4610 conf->retry_long = (u32)-1;
4611 conf->tx_power = -1;
4614 static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)
4616 brcmf_fweh_register(cfg->pub, BRCMF_E_LINK,
4617 brcmf_notify_connect_status);
4618 brcmf_fweh_register(cfg->pub, BRCMF_E_DEAUTH_IND,
4619 brcmf_notify_connect_status);
4620 brcmf_fweh_register(cfg->pub, BRCMF_E_DEAUTH,
4621 brcmf_notify_connect_status);
4622 brcmf_fweh_register(cfg->pub, BRCMF_E_DISASSOC_IND,
4623 brcmf_notify_connect_status);
4624 brcmf_fweh_register(cfg->pub, BRCMF_E_ASSOC_IND,
4625 brcmf_notify_connect_status);
4626 brcmf_fweh_register(cfg->pub, BRCMF_E_REASSOC_IND,
4627 brcmf_notify_connect_status);
4628 brcmf_fweh_register(cfg->pub, BRCMF_E_ROAM,
4629 brcmf_notify_roaming_status);
4630 brcmf_fweh_register(cfg->pub, BRCMF_E_MIC_ERROR,
4631 brcmf_notify_mic_status);
4632 brcmf_fweh_register(cfg->pub, BRCMF_E_SET_SSID,
4633 brcmf_notify_connect_status);
4634 brcmf_fweh_register(cfg->pub, BRCMF_E_PFN_NET_FOUND,
4635 brcmf_notify_sched_scan_results);
4636 brcmf_fweh_register(cfg->pub, BRCMF_E_IF,
4637 brcmf_notify_vif_event);
4638 brcmf_fweh_register(cfg->pub, BRCMF_E_P2P_PROBEREQ_MSG,
4639 brcmf_p2p_notify_rx_mgmt_p2p_probereq);
4640 brcmf_fweh_register(cfg->pub, BRCMF_E_P2P_DISC_LISTEN_COMPLETE,
4641 brcmf_p2p_notify_listen_complete);
4642 brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_RX,
4643 brcmf_p2p_notify_action_frame_rx);
4644 brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_COMPLETE,
4645 brcmf_p2p_notify_action_tx_complete);
4646 brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE,
4647 brcmf_p2p_notify_action_tx_complete);
4650 static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg)
4652 kfree(cfg->conf);
4653 cfg->conf = NULL;
4654 kfree(cfg->escan_ioctl_buf);
4655 cfg->escan_ioctl_buf = NULL;
4656 kfree(cfg->extra_buf);
4657 cfg->extra_buf = NULL;
4658 kfree(cfg->pmk_list);
4659 cfg->pmk_list = NULL;
4662 static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg)
4664 cfg->conf = kzalloc(sizeof(*cfg->conf), GFP_KERNEL);
4665 if (!cfg->conf)
4666 goto init_priv_mem_out;
4667 cfg->escan_ioctl_buf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
4668 if (!cfg->escan_ioctl_buf)
4669 goto init_priv_mem_out;
4670 cfg->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
4671 if (!cfg->extra_buf)
4672 goto init_priv_mem_out;
4673 cfg->pmk_list = kzalloc(sizeof(*cfg->pmk_list), GFP_KERNEL);
4674 if (!cfg->pmk_list)
4675 goto init_priv_mem_out;
4677 return 0;
4679 init_priv_mem_out:
4680 brcmf_deinit_priv_mem(cfg);
4682 return -ENOMEM;
4685 static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg)
4687 s32 err = 0;
4689 cfg->scan_request = NULL;
4690 cfg->pwr_save = true;
4691 cfg->roam_on = true; /* roam on & off switch.
4692 we enable roam per default */
4693 cfg->active_scan = true; /* we do active scan for
4694 specific scan per default */
4695 cfg->dongle_up = false; /* dongle is not up yet */
4696 err = brcmf_init_priv_mem(cfg);
4697 if (err)
4698 return err;
4699 brcmf_register_event_handlers(cfg);
4700 mutex_init(&cfg->usr_sync);
4701 brcmf_init_escan(cfg);
4702 brcmf_init_conf(cfg->conf);
4703 init_completion(&cfg->vif_disabled);
4704 return err;
4707 static void wl_deinit_priv(struct brcmf_cfg80211_info *cfg)
4709 cfg->dongle_up = false; /* dongle down */
4710 brcmf_abort_scanning(cfg);
4711 brcmf_deinit_priv_mem(cfg);
4714 static void init_vif_event(struct brcmf_cfg80211_vif_event *event)
4716 init_waitqueue_head(&event->vif_wq);
4717 mutex_init(&event->vif_event_lock);
4720 struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
4721 struct device *busdev)
4723 struct net_device *ndev = drvr->iflist[0]->ndev;
4724 struct brcmf_cfg80211_info *cfg;
4725 struct wiphy *wiphy;
4726 struct brcmf_cfg80211_vif *vif;
4727 struct brcmf_if *ifp;
4728 s32 err = 0;
4730 if (!ndev) {
4731 brcmf_err("ndev is invalid\n");
4732 return NULL;
4735 ifp = netdev_priv(ndev);
4736 wiphy = brcmf_setup_wiphy(busdev);
4737 if (IS_ERR(wiphy))
4738 return NULL;
4740 cfg = wiphy_priv(wiphy);
4741 cfg->wiphy = wiphy;
4742 cfg->pub = drvr;
4743 init_vif_event(&cfg->vif_event);
4744 INIT_LIST_HEAD(&cfg->vif_list);
4746 vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION, false);
4747 if (IS_ERR(vif)) {
4748 wiphy_free(wiphy);
4749 return NULL;
4752 vif->ifp = ifp;
4753 vif->wdev.netdev = ndev;
4754 ndev->ieee80211_ptr = &vif->wdev;
4755 SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy));
4757 err = wl_init_priv(cfg);
4758 if (err) {
4759 brcmf_err("Failed to init iwm_priv (%d)\n", err);
4760 goto cfg80211_attach_out;
4762 ifp->vif = vif;
4764 err = brcmf_p2p_attach(cfg);
4765 if (err) {
4766 brcmf_err("P2P initilisation failed (%d)\n", err);
4767 goto cfg80211_p2p_attach_out;
4770 return cfg;
4772 cfg80211_p2p_attach_out:
4773 wl_deinit_priv(cfg);
4775 cfg80211_attach_out:
4776 brcmf_free_vif(vif);
4777 wiphy_free(wiphy);
4778 return NULL;
4781 void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
4783 struct brcmf_cfg80211_vif *vif;
4784 struct brcmf_cfg80211_vif *tmp;
4786 wl_deinit_priv(cfg);
4787 list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) {
4788 brcmf_free_vif(vif);
4792 static s32
4793 brcmf_dongle_roam(struct brcmf_if *ifp, u32 roamvar, u32 bcn_timeout)
4795 s32 err = 0;
4796 __le32 roamtrigger[2];
4797 __le32 roam_delta[2];
4800 * Setup timeout if Beacons are lost and roam is
4801 * off to report link down
4803 if (roamvar) {
4804 err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout);
4805 if (err) {
4806 brcmf_err("bcn_timeout error (%d)\n", err);
4807 goto dongle_rom_out;
4812 * Enable/Disable built-in roaming to allow supplicant
4813 * to take care of roaming
4815 brcmf_dbg(INFO, "Internal Roaming = %s\n", roamvar ? "Off" : "On");
4816 err = brcmf_fil_iovar_int_set(ifp, "roam_off", roamvar);
4817 if (err) {
4818 brcmf_err("roam_off error (%d)\n", err);
4819 goto dongle_rom_out;
4822 roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL);
4823 roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL);
4824 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_TRIGGER,
4825 (void *)roamtrigger, sizeof(roamtrigger));
4826 if (err) {
4827 brcmf_err("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
4828 goto dongle_rom_out;
4831 roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA);
4832 roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL);
4833 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_DELTA,
4834 (void *)roam_delta, sizeof(roam_delta));
4835 if (err) {
4836 brcmf_err("WLC_SET_ROAM_DELTA error (%d)\n", err);
4837 goto dongle_rom_out;
4840 dongle_rom_out:
4841 return err;
4844 static s32
4845 brcmf_dongle_scantime(struct brcmf_if *ifp, s32 scan_assoc_time,
4846 s32 scan_unassoc_time, s32 scan_passive_time)
4848 s32 err = 0;
4850 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
4851 scan_assoc_time);
4852 if (err) {
4853 if (err == -EOPNOTSUPP)
4854 brcmf_dbg(INFO, "Scan assoc time is not supported\n");
4855 else
4856 brcmf_err("Scan assoc time error (%d)\n", err);
4857 goto dongle_scantime_out;
4859 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
4860 scan_unassoc_time);
4861 if (err) {
4862 if (err == -EOPNOTSUPP)
4863 brcmf_dbg(INFO, "Scan unassoc time is not supported\n");
4864 else
4865 brcmf_err("Scan unassoc time error (%d)\n", err);
4866 goto dongle_scantime_out;
4869 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_PASSIVE_TIME,
4870 scan_passive_time);
4871 if (err) {
4872 if (err == -EOPNOTSUPP)
4873 brcmf_dbg(INFO, "Scan passive time is not supported\n");
4874 else
4875 brcmf_err("Scan passive time error (%d)\n", err);
4876 goto dongle_scantime_out;
4879 dongle_scantime_out:
4880 return err;
4884 static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap)
4886 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
4887 struct ieee80211_channel *band_chan_arr;
4888 struct brcmf_chanspec_list *list;
4889 s32 err;
4890 u8 *pbuf;
4891 u32 i, j;
4892 u32 total;
4893 u16 chanspec;
4894 enum ieee80211_band band;
4895 u32 channel;
4896 u32 *n_cnt;
4897 bool ht40_allowed;
4898 u32 index;
4899 u32 ht40_flag;
4900 bool update;
4901 u32 array_size;
4903 pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
4905 if (pbuf == NULL)
4906 return -ENOMEM;
4908 list = (struct brcmf_chanspec_list *)pbuf;
4910 err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf,
4911 BRCMF_DCMD_MEDLEN);
4912 if (err) {
4913 brcmf_err("get chanspecs error (%d)\n", err);
4914 goto exit;
4917 __wl_band_2ghz.n_channels = 0;
4918 __wl_band_5ghz_a.n_channels = 0;
4920 total = le32_to_cpu(list->count);
4921 for (i = 0; i < total; i++) {
4922 chanspec = (u16)le32_to_cpu(list->element[i]);
4923 channel = CHSPEC_CHANNEL(chanspec);
4925 if (CHSPEC_IS40(chanspec)) {
4926 if (CHSPEC_SB_UPPER(chanspec))
4927 channel += CH_10MHZ_APART;
4928 else
4929 channel -= CH_10MHZ_APART;
4930 } else if (CHSPEC_IS80(chanspec)) {
4931 brcmf_dbg(INFO, "HT80 center channel : %d\n",
4932 channel);
4933 continue;
4935 if (CHSPEC_IS2G(chanspec) && (channel >= CH_MIN_2G_CHANNEL) &&
4936 (channel <= CH_MAX_2G_CHANNEL)) {
4937 band_chan_arr = __wl_2ghz_channels;
4938 array_size = ARRAY_SIZE(__wl_2ghz_channels);
4939 n_cnt = &__wl_band_2ghz.n_channels;
4940 band = IEEE80211_BAND_2GHZ;
4941 ht40_allowed = (bw_cap == WLC_N_BW_40ALL);
4942 } else if (CHSPEC_IS5G(chanspec) &&
4943 channel >= CH_MIN_5G_CHANNEL) {
4944 band_chan_arr = __wl_5ghz_a_channels;
4945 array_size = ARRAY_SIZE(__wl_5ghz_a_channels);
4946 n_cnt = &__wl_band_5ghz_a.n_channels;
4947 band = IEEE80211_BAND_5GHZ;
4948 ht40_allowed = !(bw_cap == WLC_N_BW_20ALL);
4949 } else {
4950 brcmf_err("Invalid channel Sepc. 0x%x.\n", chanspec);
4951 continue;
4953 if (!ht40_allowed && CHSPEC_IS40(chanspec))
4954 continue;
4955 update = false;
4956 for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
4957 if (band_chan_arr[j].hw_value == channel) {
4958 update = true;
4959 break;
4962 if (update)
4963 index = j;
4964 else
4965 index = *n_cnt;
4966 if (index < array_size) {
4967 band_chan_arr[index].center_freq =
4968 ieee80211_channel_to_frequency(channel, band);
4969 band_chan_arr[index].hw_value = channel;
4971 if (CHSPEC_IS40(chanspec) && ht40_allowed) {
4972 /* assuming the order is HT20, HT40 Upper,
4973 * HT40 lower from chanspecs
4975 ht40_flag = band_chan_arr[index].flags &
4976 IEEE80211_CHAN_NO_HT40;
4977 if (CHSPEC_SB_UPPER(chanspec)) {
4978 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
4979 band_chan_arr[index].flags &=
4980 ~IEEE80211_CHAN_NO_HT40;
4981 band_chan_arr[index].flags |=
4982 IEEE80211_CHAN_NO_HT40PLUS;
4983 } else {
4984 /* It should be one of
4985 * IEEE80211_CHAN_NO_HT40 or
4986 * IEEE80211_CHAN_NO_HT40PLUS
4988 band_chan_arr[index].flags &=
4989 ~IEEE80211_CHAN_NO_HT40;
4990 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
4991 band_chan_arr[index].flags |=
4992 IEEE80211_CHAN_NO_HT40MINUS;
4994 } else {
4995 band_chan_arr[index].flags =
4996 IEEE80211_CHAN_NO_HT40;
4997 if (band == IEEE80211_BAND_2GHZ)
4998 channel |= WL_CHANSPEC_BAND_2G;
4999 else
5000 channel |= WL_CHANSPEC_BAND_5G;
5001 channel |= WL_CHANSPEC_BW_20;
5002 err = brcmf_fil_bsscfg_int_get(ifp,
5003 "per_chan_info",
5004 &channel);
5005 if (!err) {
5006 if (channel & WL_CHAN_RADAR)
5007 band_chan_arr[index].flags |=
5008 (IEEE80211_CHAN_RADAR |
5009 IEEE80211_CHAN_NO_IBSS);
5010 if (channel & WL_CHAN_PASSIVE)
5011 band_chan_arr[index].flags |=
5012 IEEE80211_CHAN_PASSIVE_SCAN;
5015 if (!update)
5016 (*n_cnt)++;
5019 exit:
5020 kfree(pbuf);
5021 return err;
5025 static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
5027 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
5028 struct wiphy *wiphy;
5029 s32 phy_list;
5030 u32 band_list[3];
5031 u32 nmode;
5032 u32 bw_cap = 0;
5033 s8 phy;
5034 s32 err;
5035 u32 nband;
5036 s32 i;
5037 struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS];
5038 s32 index;
5040 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_PHYLIST,
5041 &phy_list, sizeof(phy_list));
5042 if (err) {
5043 brcmf_err("BRCMF_C_GET_PHYLIST error (%d)\n", err);
5044 return err;
5047 phy = ((char *)&phy_list)[0];
5048 brcmf_dbg(INFO, "BRCMF_C_GET_PHYLIST reported: %c phy\n", phy);
5051 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST,
5052 &band_list, sizeof(band_list));
5053 if (err) {
5054 brcmf_err("BRCMF_C_GET_BANDLIST error (%d)\n", err);
5055 return err;
5057 brcmf_dbg(INFO, "BRCMF_C_GET_BANDLIST reported: 0x%08x 0x%08x 0x%08x phy\n",
5058 band_list[0], band_list[1], band_list[2]);
5060 err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode);
5061 if (err) {
5062 brcmf_err("nmode error (%d)\n", err);
5063 } else {
5064 err = brcmf_fil_iovar_int_get(ifp, "mimo_bw_cap", &bw_cap);
5065 if (err)
5066 brcmf_err("mimo_bw_cap error (%d)\n", err);
5068 brcmf_dbg(INFO, "nmode=%d, mimo_bw_cap=%d\n", nmode, bw_cap);
5070 err = brcmf_construct_reginfo(cfg, bw_cap);
5071 if (err) {
5072 brcmf_err("brcmf_construct_reginfo failed (%d)\n", err);
5073 return err;
5076 nband = band_list[0];
5077 memset(bands, 0, sizeof(bands));
5079 for (i = 1; i <= nband && i < ARRAY_SIZE(band_list); i++) {
5080 index = -1;
5081 if ((band_list[i] == WLC_BAND_5G) &&
5082 (__wl_band_5ghz_a.n_channels > 0)) {
5083 index = IEEE80211_BAND_5GHZ;
5084 bands[index] = &__wl_band_5ghz_a;
5085 if ((bw_cap == WLC_N_BW_40ALL) ||
5086 (bw_cap == WLC_N_BW_20IN2G_40IN5G))
5087 bands[index]->ht_cap.cap |=
5088 IEEE80211_HT_CAP_SGI_40;
5089 } else if ((band_list[i] == WLC_BAND_2G) &&
5090 (__wl_band_2ghz.n_channels > 0)) {
5091 index = IEEE80211_BAND_2GHZ;
5092 bands[index] = &__wl_band_2ghz;
5093 if (bw_cap == WLC_N_BW_40ALL)
5094 bands[index]->ht_cap.cap |=
5095 IEEE80211_HT_CAP_SGI_40;
5098 if ((index >= 0) && nmode) {
5099 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
5100 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
5101 bands[index]->ht_cap.ht_supported = true;
5102 bands[index]->ht_cap.ampdu_factor =
5103 IEEE80211_HT_MAX_AMPDU_64K;
5104 bands[index]->ht_cap.ampdu_density =
5105 IEEE80211_HT_MPDU_DENSITY_16;
5106 /* An HT shall support all EQM rates for one spatial
5107 * stream
5109 bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
5113 wiphy = cfg_to_wiphy(cfg);
5114 wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
5115 wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
5116 wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
5118 return err;
5122 static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg)
5124 return brcmf_update_wiphybands(cfg);
5127 static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
5129 struct net_device *ndev;
5130 struct wireless_dev *wdev;
5131 struct brcmf_if *ifp;
5132 s32 power_mode;
5133 s32 err = 0;
5135 if (cfg->dongle_up)
5136 return err;
5138 ndev = cfg_to_ndev(cfg);
5139 wdev = ndev->ieee80211_ptr;
5140 ifp = netdev_priv(ndev);
5142 /* make sure RF is ready for work */
5143 brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
5145 brcmf_dongle_scantime(ifp, WL_SCAN_CHANNEL_TIME,
5146 WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
5148 power_mode = cfg->pwr_save ? PM_FAST : PM_OFF;
5149 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, power_mode);
5150 if (err)
5151 goto default_conf_out;
5152 brcmf_dbg(INFO, "power save set to %s\n",
5153 (power_mode ? "enabled" : "disabled"));
5155 err = brcmf_dongle_roam(ifp, (cfg->roam_on ? 0 : 1), WL_BEACON_TIMEOUT);
5156 if (err)
5157 goto default_conf_out;
5158 err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype,
5159 NULL, NULL);
5160 if (err)
5161 goto default_conf_out;
5162 err = brcmf_dongle_probecap(cfg);
5163 if (err)
5164 goto default_conf_out;
5166 cfg->dongle_up = true;
5167 default_conf_out:
5169 return err;
5173 static s32 __brcmf_cfg80211_up(struct brcmf_if *ifp)
5175 set_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);
5177 return brcmf_config_dongle(ifp->drvr->config);
5180 static s32 __brcmf_cfg80211_down(struct brcmf_if *ifp)
5182 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
5185 * While going down, if associated with AP disassociate
5186 * from AP to save power
5188 if (check_vif_up(ifp->vif)) {
5189 brcmf_link_down(ifp->vif);
5191 /* Make sure WPA_Supplicant receives all the event
5192 generated due to DISASSOC call to the fw to keep
5193 the state fw and WPA_Supplicant state consistent
5195 brcmf_delay(500);
5198 brcmf_abort_scanning(cfg);
5199 clear_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);
5201 return 0;
5204 s32 brcmf_cfg80211_up(struct net_device *ndev)
5206 struct brcmf_if *ifp = netdev_priv(ndev);
5207 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
5208 s32 err = 0;
5210 mutex_lock(&cfg->usr_sync);
5211 err = __brcmf_cfg80211_up(ifp);
5212 mutex_unlock(&cfg->usr_sync);
5214 return err;
5217 s32 brcmf_cfg80211_down(struct net_device *ndev)
5219 struct brcmf_if *ifp = netdev_priv(ndev);
5220 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
5221 s32 err = 0;
5223 mutex_lock(&cfg->usr_sync);
5224 err = __brcmf_cfg80211_down(ifp);
5225 mutex_unlock(&cfg->usr_sync);
5227 return err;
5230 u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state)
5232 struct brcmf_cfg80211_vif *vif;
5233 bool result = 0;
5235 list_for_each_entry(vif, &cfg->vif_list, list) {
5236 if (test_bit(state, &vif->sme_state))
5237 result++;
5239 return result;
5242 static inline bool vif_event_equals(struct brcmf_cfg80211_vif_event *event,
5243 u8 action)
5245 u8 evt_action;
5247 mutex_lock(&event->vif_event_lock);
5248 evt_action = event->action;
5249 mutex_unlock(&event->vif_event_lock);
5250 return evt_action == action;
5253 void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg,
5254 struct brcmf_cfg80211_vif *vif)
5256 struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;
5258 mutex_lock(&event->vif_event_lock);
5259 event->vif = vif;
5260 event->action = 0;
5261 mutex_unlock(&event->vif_event_lock);
5264 bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg)
5266 struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;
5267 bool armed;
5269 mutex_lock(&event->vif_event_lock);
5270 armed = event->vif != NULL;
5271 mutex_unlock(&event->vif_event_lock);
5273 return armed;
5275 int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg,
5276 u8 action, ulong timeout)
5278 struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;
5280 return wait_event_timeout(event->vif_wq,
5281 vif_event_equals(event, action), timeout);