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