5fe24615578d20c6bd528d046a145073125eb956
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rkwifi / bcmdhd / wl_cfg80211.c
1 /*
2  * Linux cfg80211 driver
3  *
4  * Copyright (C) 1999-2016, Broadcom Corporation
5  * 
6  *      Unless you and Broadcom execute a separate written software license
7  * agreement governing use of this software, this software is licensed to you
8  * under the terms of the GNU General Public License version 2 (the "GPL"),
9  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10  * following added to such license:
11  * 
12  *      As a special exception, the copyright holders of this software give you
13  * permission to link this software with independent modules, and to copy and
14  * distribute the resulting executable under terms of your choice, provided that
15  * you also meet, for each linked independent module, the terms and conditions of
16  * the license of that module.  An independent module is a module which is not
17  * derived from this software.  The special exception does not apply to any
18  * modifications of the software.
19  * 
20  *      Notwithstanding the above, under no circumstances may you combine this
21  * software in any way with any other Broadcom software provided under a license
22  * other than the GPL, without Broadcom's express prior written consent.
23  *
24  *
25  * <<Broadcom-WL-IPTag/Open:>>
26  *
27  * $Id: wl_cfg80211.c 610196 2016-01-06 11:20:45Z $
28  */
29 /* */
30 #include <typedefs.h>
31 #include <linuxver.h>
32 #include <osl.h>
33 #include <linux/kernel.h>
34
35 #include <bcmutils.h>
36 #include <bcmwifi_channels.h>
37 #include <bcmendian.h>
38 #include <proto/ethernet.h>
39 #include <proto/802.11.h>
40 #include <linux/if_arp.h>
41 #include <asm/uaccess.h>
42
43 #include <proto/ethernet.h>
44 #include <linux/kernel.h>
45 #include <linux/kthread.h>
46 #include <linux/netdevice.h>
47 #include <linux/sched.h>
48 #include <linux/etherdevice.h>
49 #include <linux/wireless.h>
50 #include <linux/ieee80211.h>
51 #include <linux/wait.h>
52 #include <net/cfg80211.h>
53 #include <net/rtnetlink.h>
54
55 #include <wlioctl.h>
56 #include <wldev_common.h>
57 #include <wl_cfg80211.h>
58 #include <wl_cfgp2p.h>
59 #include <wl_android.h>
60 #include <dngl_stats.h>
61 #include <dhd.h>
62 #include <dhd_linux.h>
63 #include <dhdioctl.h>
64 #include <wlioctl.h>
65 #include <dhd_cfg80211.h>
66 #include <dhd_bus.h>
67 #ifdef PNO_SUPPORT
68 #include <dhd_pno.h>
69 #endif /* PNO_SUPPORT */
70
71 #if defined(WL_VENDOR_EXT_SUPPORT)
72 #include <wl_cfgvendor.h>
73 #endif /* defined(WL_VENDOR_EXT_SUPPORT) */
74
75 #ifdef WL_NAN
76 #include <wl_cfgnan.h>
77 #endif /* WL_NAN */
78 #include <dhd_config.h>
79
80 #ifdef PROP_TXSTATUS
81 #include <dhd_wlfc.h>
82 #endif
83
84 #ifdef BCMPCIE
85 #include <dhd_flowring.h>
86 #endif
87
88 #ifdef WL11U
89 #if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
90 #error You should enable 'WL_ENABLE_P2P_IF' or 'WL_CFG80211_P2P_DEV_IF' \
91         according to Kernel version and is supported only in Android-JB
92 #endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
93 #endif /* WL11U */
94
95
96 #define IW_WSEC_ENABLED(wsec)   ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
97
98 static struct device *cfg80211_parent_dev = NULL;
99 /* g_bcm_cfg should be static. Do not change */
100 static struct bcm_cfg80211 *g_bcm_cfg = NULL;
101 #ifdef CUSTOMER_HW4_DEBUG
102 u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_P2P_ACTION;
103 #else
104 u32 wl_dbg_level = WL_DBG_ERR;
105 #endif /* CUSTOMER_HW4_DEBUG */
106
107 #define MAX_WAIT_TIME 1500
108 #ifdef WLAIBSS_MCHAN
109 #define IBSS_IF_NAME "ibss%d"
110 #endif /* WLAIBSS_MCHAN */
111
112 #ifdef VSDB
113 /* sleep time to keep STA's connecting or connection for continuous af tx or finding a peer */
114 #define DEFAULT_SLEEP_TIME_VSDB         120
115 #define OFF_CHAN_TIME_THRESHOLD_MS      200
116 #define AF_RETRY_DELAY_TIME                     40
117
118 /* if sta is connected or connecting, sleep for a while before retry af tx or finding a peer */
119 #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg)  \
120         do {    \
121                 if (wl_get_drv_status(cfg, CONNECTED, bcmcfg_to_prmry_ndev(cfg)) ||     \
122                         wl_get_drv_status(cfg, CONNECTING, bcmcfg_to_prmry_ndev(cfg))) {        \
123                         OSL_SLEEP(DEFAULT_SLEEP_TIME_VSDB);                     \
124                 }       \
125         } while (0)
126 #else /* VSDB */
127 /* if not VSDB, do nothing */
128 #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg)
129 #endif /* VSDB */
130
131 #ifdef WL_CFG80211_SYNC_GON
132 #define WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg) \
133         (wl_get_drv_status_all(cfg, SENDING_ACT_FRM) || \
134                 wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN))
135 #else
136 #define WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg) wl_get_drv_status_all(cfg, SENDING_ACT_FRM)
137 #endif /* WL_CFG80211_SYNC_GON */
138
139 #define DNGL_FUNC(func, parameters) func parameters
140 #define COEX_DHCP
141
142 #define WLAN_EID_SSID   0
143 #define CH_MIN_5G_CHANNEL 34
144 #define CH_MIN_2G_CHANNEL 1
145 #define ACTIVE_SCAN 1
146 #define PASSIVE_SCAN 0
147
148 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
149         4 && __GNUC_MINOR__ >= 6))
150 #define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \
151 _Pragma("GCC diagnostic push") \
152 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \
153 (entry) = list_first_entry((ptr), type, member); \
154 _Pragma("GCC diagnostic pop") \
155
156 #define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
157 _Pragma("GCC diagnostic push") \
158 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \
159 entry = container_of((ptr), type, member); \
160 _Pragma("GCC diagnostic pop") \
161
162 #else
163 #define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \
164 (entry) = list_first_entry((ptr), type, member); \
165
166 #define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
167 entry = container_of((ptr), type, member); \
168
169 #endif /* STRICT_GCC_WARNINGS */
170
171 enum rmc_event_type {
172         RMC_EVENT_NONE,
173         RMC_EVENT_LEADER_CHECK_FAIL
174 };
175
176 /* This is to override regulatory domains defined in cfg80211 module (reg.c)
177  * By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN
178  * and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165).
179  * With respect to these flags, wpa_supplicant doesn't start p2p operations on 5GHz channels.
180  * All the chnages in world regulatory domain are to be done here.
181  *
182  * this definition reuires disabling missing-field-initializer warning
183  * as the ieee80211_regdomain definition differs in plain linux and in Android
184  */
185 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
186         4 && __GNUC_MINOR__ >= 6))
187 _Pragma("GCC diagnostic push")
188 _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"")
189 #endif
190 static const struct ieee80211_regdomain brcm_regdom = {
191         .n_reg_rules = 4,
192         .alpha2 =  "99",
193         .reg_rules = {
194                 /* IEEE 802.11b/g, channels 1..11 */
195                 REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
196                 /* If any */
197                 /* IEEE 802.11 channel 14 - Only JP enables
198                  * this and for 802.11b only
199                  */
200                 REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
201                 /* IEEE 802.11a, channel 36..64 */
202                 REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
203                 /* IEEE 802.11a, channel 100..165 */
204                 REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
205 };
206 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
207         4 && __GNUC_MINOR__ >= 6))
208 _Pragma("GCC diagnostic pop")
209 #endif
210
211
212 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
213         (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
214 static const struct ieee80211_iface_limit common_if_limits[] = {
215         {
216         /*
217          * Driver can support up to 2 AP's
218          */
219         .max = 2,
220         .types = BIT(NL80211_IFTYPE_AP),
221         },
222         {
223         /*
224          * During P2P-GO removal, P2P-GO is first changed to STA and later only
225          * removed. So setting maximum possible number of STA interfaces according
226          * to kernel version.
227          *
228          * less than linux-3.8 - max:3 (wlan0 + p2p0 + group removal of p2p-p2p0-x)
229          * linux-3.8 and above - max:2 (wlan0 + group removal of p2p-wlan0-x)
230          */
231 #ifdef WL_ENABLE_P2P_IF
232         .max = 3,
233 #else
234         .max = 2,
235 #endif /* WL_ENABLE_P2P_IF */
236         .types = BIT(NL80211_IFTYPE_STATION),
237         },
238         {
239         .max = 2,
240         .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
241         },
242 #if defined(WL_CFG80211_P2P_DEV_IF)
243         {
244         .max = 1,
245         .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
246         },
247 #endif /* WL_CFG80211_P2P_DEV_IF */
248         {
249         .max = 1,
250         .types = BIT(NL80211_IFTYPE_ADHOC),
251         },
252 };
253 #ifdef BCM4330_CHIP
254 #define NUM_DIFF_CHANNELS 1
255 #else
256 #define NUM_DIFF_CHANNELS 2
257 #endif
258 static const struct ieee80211_iface_combination
259 common_iface_combinations[] = {
260         {
261         .num_different_channels = NUM_DIFF_CHANNELS,
262         /*
263          * max_interfaces = 4
264          * The max no of interfaces will be used in dual p2p case.
265          * {STA, P2P Device, P2P Group 1, P2P Group 2}. Though we
266          * will not be using the STA functionality in this case, it
267          * will remain registered as it is the primary interface.
268          */
269         .max_interfaces = 4,
270         .limits = common_if_limits,
271         .n_limits = ARRAY_SIZE(common_if_limits),
272         },
273 };
274 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
275
276 /* Data Element Definitions */
277 #define WPS_ID_CONFIG_METHODS     0x1008
278 #define WPS_ID_REQ_TYPE           0x103A
279 #define WPS_ID_DEVICE_NAME        0x1011
280 #define WPS_ID_VERSION            0x104A
281 #define WPS_ID_DEVICE_PWD_ID      0x1012
282 #define WPS_ID_REQ_DEV_TYPE       0x106A
283 #define WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS 0x1053
284 #define WPS_ID_PRIM_DEV_TYPE      0x1054
285
286 /* Device Password ID */
287 #define DEV_PW_DEFAULT 0x0000
288 #define DEV_PW_USER_SPECIFIED 0x0001,
289 #define DEV_PW_MACHINE_SPECIFIED 0x0002
290 #define DEV_PW_REKEY 0x0003
291 #define DEV_PW_PUSHBUTTON 0x0004
292 #define DEV_PW_REGISTRAR_SPECIFIED 0x0005
293
294 /* Config Methods */
295 #define WPS_CONFIG_USBA 0x0001
296 #define WPS_CONFIG_ETHERNET 0x0002
297 #define WPS_CONFIG_LABEL 0x0004
298 #define WPS_CONFIG_DISPLAY 0x0008
299 #define WPS_CONFIG_EXT_NFC_TOKEN 0x0010
300 #define WPS_CONFIG_INT_NFC_TOKEN 0x0020
301 #define WPS_CONFIG_NFC_INTERFACE 0x0040
302 #define WPS_CONFIG_PUSHBUTTON 0x0080
303 #define WPS_CONFIG_KEYPAD 0x0100
304 #define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280
305 #define WPS_CONFIG_PHY_PUSHBUTTON 0x0480
306 #define WPS_CONFIG_VIRT_DISPLAY 0x2008
307 #define WPS_CONFIG_PHY_DISPLAY 0x4008
308
309 #define PM_BLOCK 1
310 #define PM_ENABLE 0
311
312
313 #define WL_AKM_SUITE_SHA256_1X  0x000FAC05
314 #define WL_AKM_SUITE_SHA256_PSK 0x000FAC06
315
316 #ifndef IBSS_COALESCE_ALLOWED
317 #define IBSS_COALESCE_ALLOWED 0
318 #endif
319
320 #ifndef IBSS_INITIAL_SCAN_ALLOWED
321 #define IBSS_INITIAL_SCAN_ALLOWED 0
322 #endif
323
324 #define CUSTOM_RETRY_MASK 0xff000000 /* Mask for retry counter of custom dwell time */
325 #define LONG_LISTEN_TIME 2000
326
327 #define MAX_SCAN_ABORT_WAIT_CNT 20
328 #define WAIT_SCAN_ABORT_OSL_SLEEP_TIME 10
329
330 #define IDSUP_4WAY_HANDSHAKE_TIMEOUT    10000
331 enum idsup_event_type {
332         IDSUP_EVENT_SUCCESS = 0,
333         IDSUP_EVENT_4WAY_HANDSHAKE_TIMEOUT
334 };
335 /*
336  * cfg80211_ops api/callback list
337  */
338 static s32 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
339         const struct ether_addr *sa, const struct ether_addr *bssid,
340         u8 **pheader, u32 *body_len, u8 *pbody);
341 static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
342         struct cfg80211_scan_request *request,
343         struct cfg80211_ssid *this_ssid);
344 #if defined(WL_CFG80211_P2P_DEV_IF)
345 static s32
346 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request);
347 #else
348 static s32
349 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
350         struct cfg80211_scan_request *request);
351 #endif /* WL_CFG80211_P2P_DEV_IF */
352 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
353 #ifdef WLAIBSS_MCHAN
354 static bcm_struct_cfgdev* bcm_cfg80211_add_ibss_if(struct wiphy *wiphy, char *name);
355 static s32 bcm_cfg80211_del_ibss_if(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev);
356 #endif /* WLAIBSS_MCHAN */
357 static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
358         struct cfg80211_ibss_params *params);
359 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy,
360         struct net_device *dev);
361 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
362 static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
363         struct net_device *dev, const u8 *mac,
364         struct station_info *sinfo);
365 #else
366 static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
367         struct net_device *dev, u8 *mac,
368         struct station_info *sinfo);
369 #endif
370 static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
371         struct net_device *dev, bool enabled,
372         s32 timeout);
373 static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
374         struct cfg80211_connect_params *sme);
375 static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
376         u16 reason_code);
377 #if defined(WL_CFG80211_P2P_DEV_IF)
378 static s32
379 wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
380         enum nl80211_tx_power_setting type, s32 mbm);
381 #else
382 static s32
383 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
384         enum nl80211_tx_power_setting type, s32 dbm);
385 #endif /* WL_CFG80211_P2P_DEV_IF */
386 #if defined(WL_CFG80211_P2P_DEV_IF)
387 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
388         struct wireless_dev *wdev, s32 *dbm);
389 #else
390 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
391 #endif /* WL_CFG80211_P2P_DEV_IF */
392 static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
393         struct net_device *dev,
394         u8 key_idx, bool unicast, bool multicast);
395 static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
396         u8 key_idx, bool pairwise, const u8 *mac_addr,
397         struct key_params *params);
398 static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
399         u8 key_idx, bool pairwise, const u8 *mac_addr);
400 static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
401         u8 key_idx, bool pairwise, const u8 *mac_addr,
402         void *cookie, void (*callback) (void *cookie,
403         struct key_params *params));
404 static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
405         struct net_device *dev, u8 key_idx);
406 static s32 wl_cfg80211_resume(struct wiphy *wiphy);
407 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
408         2, 0))
409 static s32 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
410         bcm_struct_cfgdev *cfgdev, u64 cookie);
411 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
412 static s32 wl_cfg80211_del_station(
413                 struct wiphy *wiphy, struct net_device *ndev,
414                 struct station_del_parameters *params);
415 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
416 static s32 wl_cfg80211_del_station(struct wiphy *wiphy,
417         struct net_device *ndev, const u8* mac_addr);
418 #else
419 static s32 wl_cfg80211_del_station(struct wiphy *wiphy,
420         struct net_device *ndev, u8* mac_addr);
421 #endif
422 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
423 static s32 wl_cfg80211_change_station(struct wiphy *wiphy,
424         struct net_device *dev, const u8 *mac, struct station_parameters *params);
425 #else
426 static s32 wl_cfg80211_change_station(struct wiphy *wiphy,
427         struct net_device *dev, u8 *mac, struct station_parameters *params);
428 #endif
429 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
430 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
431 static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
432 #else
433 static s32 wl_cfg80211_suspend(struct wiphy *wiphy);
434 #endif /* KERNEL_VERSION(2, 6, 39) || WL_COMPAT_WIRELES */
435 static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
436         struct cfg80211_pmksa *pmksa);
437 static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
438         struct cfg80211_pmksa *pmksa);
439 static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
440         struct net_device *dev);
441 static void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg);
442 static void wl_cfg80211_cancel_scan(struct bcm_cfg80211 *cfg);
443 static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
444         struct net_device *ndev, bool aborted, bool fw_abort);
445 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
446 #if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \
447         KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
448 static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
449         u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
450         u32 peer_capability, const u8 *data, size_t len);
451 #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) && \
452                 (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
453 static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
454         const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
455         u32 peer_capability, const u8 *data, size_t len);
456 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
457 static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
458         const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
459         u32 peer_capability, bool initiator, const u8 *data, size_t len);
460 #else
461 static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
462         u8 *peer, u8 action_code, u8 dialog_token, u16 status_code, const u8 *data,
463         size_t len);
464 #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
465 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
466 static s32 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
467         const u8 *peer, enum nl80211_tdls_operation oper);
468 #else
469 static s32 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
470         u8 *peer, enum nl80211_tdls_operation oper);
471 #endif
472 #endif 
473 #ifdef WL_SCHED_SCAN
474 static int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev);
475 #endif
476 #if defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF)
477 bcm_struct_cfgdev*
478 wl_cfg80211_create_iface(struct wiphy *wiphy, enum nl80211_iftype
479                  iface_type, u8 *mac_addr, const char *name);
480 s32
481 wl_cfg80211_del_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev);
482 #endif /* defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF) */
483
484 s32 wl_cfg80211_interface_ops(struct bcm_cfg80211 *cfg,
485         struct net_device *ndev, s32 bsscfg_idx,
486         enum nl80211_iftype iface_type, s32 del, u8 *addr);
487 s32 wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg,
488         struct net_device *ndev, s32 bsscfg_idx,
489         enum nl80211_iftype iface_type, s32 del, u8 *addr);
490 chanspec_t wl_chspec_driver_to_host(chanspec_t chanspec);
491 chanspec_t wl_chspec_host_to_driver(chanspec_t chanspec);
492 #ifdef WL11ULB
493 static s32 wl_cfg80211_get_ulb_bw(struct wireless_dev *wdev);
494 static chanspec_t wl_cfg80211_ulb_get_min_bw_chspec(struct wireless_dev *wdev, s32 bssidx);
495 static s32 wl_cfg80211_ulbbw_to_ulbchspec(u32 ulb_bw);
496 #else
497 static inline chanspec_t wl_cfg80211_ulb_get_min_bw_chspec(
498                 struct wireless_dev *wdev, s32 bssidx)
499 {
500         return WL_CHANSPEC_BW_20;
501 }
502 #endif /* WL11ULB */
503
504 /*
505  * event & event Q handlers for cfg80211 interfaces
506  */
507 static s32 wl_create_event_handler(struct bcm_cfg80211 *cfg);
508 static void wl_destroy_event_handler(struct bcm_cfg80211 *cfg);
509 static s32 wl_event_handler(void *data);
510 static void wl_init_eq(struct bcm_cfg80211 *cfg);
511 static void wl_flush_eq(struct bcm_cfg80211 *cfg);
512 static unsigned long wl_lock_eq(struct bcm_cfg80211 *cfg);
513 static void wl_unlock_eq(struct bcm_cfg80211 *cfg, unsigned long flags);
514 static void wl_init_eq_lock(struct bcm_cfg80211 *cfg);
515 static void wl_init_event_handler(struct bcm_cfg80211 *cfg);
516 static struct wl_event_q *wl_deq_event(struct bcm_cfg80211 *cfg);
517 static s32 wl_enq_event(struct bcm_cfg80211 *cfg, struct net_device *ndev, u32 type,
518         const wl_event_msg_t *msg, void *data);
519 static void wl_put_event(struct wl_event_q *e);
520 static void wl_wakeup_event(struct bcm_cfg80211 *cfg);
521 static s32 wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
522         const wl_event_msg_t *e, void *data);
523 static s32 wl_notify_connect_status(struct bcm_cfg80211 *cfg,
524         bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
525 static s32 wl_notify_roaming_status(struct bcm_cfg80211 *cfg,
526         bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
527 static s32 wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
528         const wl_event_msg_t *e, void *data);
529 static s32 wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
530         const wl_event_msg_t *e, void *data, bool completed);
531 static s32 wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
532         const wl_event_msg_t *e, void *data);
533 static s32 wl_notify_mic_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
534         const wl_event_msg_t *e, void *data);
535 #ifdef BT_WIFI_HANDOVER
536 static s32 wl_notify_bt_wifi_handover_req(struct bcm_cfg80211 *cfg,
537         bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
538 #endif /* BT_WIFI_HANDOVER */
539 #ifdef WL_SCHED_SCAN
540 static s32
541 wl_notify_sched_scan_results(struct bcm_cfg80211 *cfg, struct net_device *ndev,
542         const wl_event_msg_t *e, void *data);
543 #endif /* WL_SCHED_SCAN */
544 #ifdef PNO_SUPPORT
545 static s32 wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
546         const wl_event_msg_t *e, void *data);
547 #endif /* PNO_SUPPORT */
548 #ifdef GSCAN_SUPPORT
549 static s32 wl_notify_gscan_event(struct bcm_cfg80211 *wl, bcm_struct_cfgdev *cfgdev,
550         const wl_event_msg_t *e, void *data);
551 #endif /* GSCAN_SUPPORT */
552 static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_net_info,
553         enum wl_status state, bool set);
554 #ifdef DHD_LOSSLESS_ROAMING
555 static s32 wl_notify_roam_prep_status(struct bcm_cfg80211 *cfg,
556         bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
557 static void wl_del_roam_timeout(struct bcm_cfg80211 *cfg);
558 #endif /* DHD_LOSSLESS_ROAMING */
559 #ifdef CUSTOM_EVENT_PM_WAKE
560 static s32 wl_check_pmstatus(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
561         const wl_event_msg_t *e, void *data);
562 #endif /* CUSTOM_EVENT_PM_WAKE */
563
564 #ifdef WLTDLS
565 static s32 wl_tdls_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
566         const wl_event_msg_t *e, void *data);
567 #endif /* WLTDLS */
568 /*
569  * register/deregister parent device
570  */
571 static void wl_cfg80211_clear_parent_dev(void);
572 /*
573  * ioctl utilites
574  */
575
576 /*
577  * cfg80211 set_wiphy_params utilities
578  */
579 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold);
580 static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold);
581 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
582
583 /*
584  * cfg profile utilities
585  */
586 static s32 wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
587         const wl_event_msg_t *e, const void *data, s32 item);
588 static void *wl_read_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 item);
589 static void wl_init_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev);
590
591 /*
592  * cfg80211 connect utilites
593  */
594 static s32 wl_set_wpa_version(struct net_device *dev,
595         struct cfg80211_connect_params *sme);
596 static s32 wl_set_auth_type(struct net_device *dev,
597         struct cfg80211_connect_params *sme);
598 static s32 wl_set_set_cipher(struct net_device *dev,
599         struct cfg80211_connect_params *sme);
600 static s32 wl_set_key_mgmt(struct net_device *dev,
601         struct cfg80211_connect_params *sme);
602 static s32 wl_set_set_sharedkey(struct net_device *dev,
603         struct cfg80211_connect_params *sme);
604 static s32 wl_get_assoc_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev);
605 static s32 wl_ch_to_chanspec(struct net_device *dev, int ch,
606         struct wl_join_params *join_params, size_t *join_params_size);
607 void wl_cfg80211_clear_security(struct bcm_cfg80211 *cfg);
608
609 /*
610  * information element utilities
611  */
612 static void wl_rst_ie(struct bcm_cfg80211 *cfg);
613 static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v);
614 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, const u8 *ie_stream, u32 *ie_size,
615         bool roam);
616 static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size);
617 static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size);
618 static u32 wl_get_ielen(struct bcm_cfg80211 *cfg);
619
620 #ifdef WL11U
621 bcm_tlv_t *
622 wl_cfg80211_find_interworking_ie(u8 *parse, u32 len);
623 static s32
624 wl_cfg80211_add_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx, s32 pktflag,
625             uint8 ie_id, uint8 *data, uint8 data_len);
626 #endif /* WL11U */
627
628 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev, void *data);
629 static void wl_free_wdev(struct bcm_cfg80211 *cfg);
630 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
631 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
632 static int
633 #else
634 static void
635 #endif /* kernel version < 3.10.11 */
636 wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
637 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
638
639 static s32 wl_inform_bss(struct bcm_cfg80211 *cfg);
640 static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi, bool roam);
641 static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool roam);
642 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy);
643 s32 wl_cfg80211_channel_to_freq(u32 channel);
644
645
646 static void wl_cfg80211_work_handler(struct work_struct *work);
647 static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
648         u8 key_idx, const u8 *mac_addr,
649         struct key_params *params);
650 /*
651  * key indianess swap utilities
652  */
653 static void swap_key_from_BE(struct wl_wsec_key *key);
654 static void swap_key_to_BE(struct wl_wsec_key *key);
655
656 /*
657  * bcm_cfg80211 memory init/deinit utilities
658  */
659 static s32 wl_init_priv_mem(struct bcm_cfg80211 *cfg);
660 static void wl_deinit_priv_mem(struct bcm_cfg80211 *cfg);
661
662 static void wl_delay(u32 ms);
663
664 /*
665  * ibss mode utilities
666  */
667 static bool wl_is_ibssmode(struct bcm_cfg80211 *cfg, struct net_device *ndev);
668 static __used bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg);
669
670 /*
671  * link up/down , default configuration utilities
672  */
673 static s32 __wl_cfg80211_up(struct bcm_cfg80211 *cfg);
674 static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg);
675 static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e);
676 static bool wl_is_linkup(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e,
677         struct net_device *ndev);
678 static bool wl_is_nonetwork(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e);
679 static void wl_link_up(struct bcm_cfg80211 *cfg);
680 static void wl_link_down(struct bcm_cfg80211 *cfg);
681 static s32 wl_config_ifmode(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 iftype);
682 static void wl_init_conf(struct wl_conf *conf);
683 static s32 wl_cfg80211_handle_ifdel(struct bcm_cfg80211 *cfg, wl_if_event_info *if_event_info,
684         struct net_device* ndev);
685
686 int wl_cfg80211_get_ioctl_version(void);
687
688 /*
689  * find most significant bit set
690  */
691 static __used u32 wl_find_msb(u16 bit16);
692
693 /*
694  * rfkill support
695  */
696 static int wl_setup_rfkill(struct bcm_cfg80211 *cfg, bool setup);
697 static int wl_rfkill_set(void *data, bool blocked);
698 #ifdef DEBUGFS_CFG80211
699 static s32 wl_setup_debugfs(struct bcm_cfg80211 *cfg);
700 static s32 wl_free_debugfs(struct bcm_cfg80211 *cfg);
701 #endif
702
703 static wl_scan_params_t *wl_cfg80211_scan_alloc_params(int channel,
704         int nprobes, int *out_params_size);
705 static bool check_dev_role_integrity(struct bcm_cfg80211 *cfg, u32 dev_role);
706
707 #ifdef WL_CFG80211_ACL
708 /* ACL */
709 static int wl_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *cfgdev,
710         const struct cfg80211_acl_data *acl);
711 #endif /* WL_CFG80211_ACL */
712
713 /*
714  * Some external functions, TODO: move them to dhd_linux.h
715  */
716 int dhd_add_monitor(char *name, struct net_device **new_ndev);
717 int dhd_del_monitor(struct net_device *ndev);
718 int dhd_monitor_init(void *dhd_pub);
719 int dhd_monitor_uninit(void);
720 int dhd_start_xmit(struct sk_buff *skb, struct net_device *net);
721
722
723 #ifdef DHD_IFDEBUG
724 void wl_dump_ifinfo(struct bcm_cfg80211 *cfg);
725 #endif
726
727 #ifdef P2P_LISTEN_OFFLOADING
728 s32 wl_cfg80211_p2plo_deinit(struct bcm_cfg80211 *cfg);
729 #endif /* P2P_LISTEN_OFFLOADING */
730
731 static int wl_cfg80211_delayed_roam(struct bcm_cfg80211 *cfg, struct net_device *ndev,
732         const struct ether_addr *bssid);
733
734 static int bw2cap[] = { 0, 0, WLC_BW_CAP_20MHZ, WLC_BW_CAP_40MHZ, WLC_BW_CAP_80MHZ,
735         WLC_BW_CAP_160MHZ, WLC_BW_CAP_160MHZ };
736
737 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0))
738 #define CFG80211_DISCONNECTED(dev, reason, ie, len, loc_gen, gfp) \
739         cfg80211_disconnected(dev, reason, ie, len, gfp);
740 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0))
741 #define CFG80211_DISCONNECTED(dev, reason, ie, len, loc_gen, gfp) \
742         cfg80211_disconnected(dev, reason, ie, len, loc_gen, gfp);
743 #endif
744
745 #define IS_WPA_AKM(akm) ((akm) == RSN_AKM_NONE ||                       \
746                                  (akm) == RSN_AKM_UNSPECIFIED ||        \
747                                  (akm) == RSN_AKM_PSK)
748
749
750 extern int dhd_wait_pend8021x(struct net_device *dev);
751 #ifdef PROP_TXSTATUS_VSDB
752 extern int disable_proptx;
753 #endif /* PROP_TXSTATUS_VSDB */
754
755
756 extern int passive_channel_skip;
757
758 static s32
759 wl_ap_start_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
760         const wl_event_msg_t *e, void *data);
761 static s32
762 wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
763         const wl_event_msg_t *e, void *data);
764 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0)) && (LINUX_VERSION_CODE <= (3, 7, \
765         0)))
766 struct chan_info {
767         int freq;
768         int chan_type;
769 };
770 #endif
771
772
773 #if (WL_DBG_LEVEL > 0)
774 #define WL_DBG_ESTR_MAX 50
775 static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = {
776         "SET_SSID", "JOIN", "START", "AUTH", "AUTH_IND",
777         "DEAUTH", "DEAUTH_IND", "ASSOC", "ASSOC_IND", "REASSOC",
778         "REASSOC_IND", "DISASSOC", "DISASSOC_IND", "QUIET_START", "QUIET_END",
779         "BEACON_RX", "LINK", "MIC_ERROR", "NDIS_LINK", "ROAM",
780         "TXFAIL", "PMKID_CACHE", "RETROGRADE_TSF", "PRUNE", "AUTOAUTH",
781         "EAPOL_MSG", "SCAN_COMPLETE", "ADDTS_IND", "DELTS_IND", "BCNSENT_IND",
782         "BCNRX_MSG", "BCNLOST_MSG", "ROAM_PREP", "PFN_NET_FOUND",
783         "PFN_NET_LOST",
784         "RESET_COMPLETE", "JOIN_START", "ROAM_START", "ASSOC_START",
785         "IBSS_ASSOC",
786         "RADIO", "PSM_WATCHDOG",
787         "WLC_E_XXX_ASSOC_START", "WLC_E_XXX_ASSOC_ABORT",
788         "PROBREQ_MSG",
789         "SCAN_CONFIRM_IND", "PSK_SUP", "COUNTRY_CODE_CHANGED",
790         "EXCEEDED_MEDIUM_TIME", "ICV_ERROR",
791         "UNICAST_DECODE_ERROR", "MULTICAST_DECODE_ERROR", "TRACE",
792         "WLC_E_BTA_HCI_EVENT", "IF", "WLC_E_P2P_DISC_LISTEN_COMPLETE",
793         "RSSI", "PFN_SCAN_COMPLETE", "WLC_E_EXTLOG_MSG",
794         "ACTION_FRAME", "ACTION_FRAME_COMPLETE", "WLC_E_PRE_ASSOC_IND",
795         "WLC_E_PRE_REASSOC_IND", "WLC_E_CHANNEL_ADOPTED", "WLC_E_AP_STARTED",
796         "WLC_E_DFS_AP_STOP", "WLC_E_DFS_AP_RESUME", "WLC_E_WAI_STA_EVENT",
797         "WLC_E_WAI_MSG", "WLC_E_ESCAN_RESULT", "WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE",
798         "WLC_E_PROBRESP_MSG", "WLC_E_P2P_PROBREQ_MSG", "WLC_E_DCS_REQUEST", "WLC_E_FIFO_CREDIT_MAP",
799         "WLC_E_ACTION_FRAME_RX", "WLC_E_WAKE_EVENT", "WLC_E_RM_COMPLETE"
800 };
801 #endif                          /* WL_DBG_LEVEL */
802
803 #define CHAN2G(_channel, _freq, _flags) {                       \
804         .band                   = IEEE80211_BAND_2GHZ,          \
805         .center_freq            = (_freq),                      \
806         .hw_value               = (_channel),                   \
807         .flags                  = (_flags),                     \
808         .max_antenna_gain       = 0,                            \
809         .max_power              = 30,                           \
810 }
811
812 #define CHAN5G(_channel, _flags) {                              \
813         .band                   = IEEE80211_BAND_5GHZ,          \
814         .center_freq            = 5000 + (5 * (_channel)),      \
815         .hw_value               = (_channel),                   \
816         .flags                  = (_flags),                     \
817         .max_antenna_gain       = 0,                            \
818         .max_power              = 30,                           \
819 }
820
821 #define RATE_TO_BASE100KBPS(rate)   (((rate) * 10) / 2)
822 #define RATETAB_ENT(_rateid, _flags) \
823         {                                                               \
824                 .bitrate        = RATE_TO_BASE100KBPS(_rateid),     \
825                 .hw_value       = (_rateid),                        \
826                 .flags    = (_flags),                        \
827         }
828
829 static struct ieee80211_rate __wl_rates[] = {
830         RATETAB_ENT(DOT11_RATE_1M, 0),
831         RATETAB_ENT(DOT11_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
832         RATETAB_ENT(DOT11_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
833         RATETAB_ENT(DOT11_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
834         RATETAB_ENT(DOT11_RATE_6M, 0),
835         RATETAB_ENT(DOT11_RATE_9M, 0),
836         RATETAB_ENT(DOT11_RATE_12M, 0),
837         RATETAB_ENT(DOT11_RATE_18M, 0),
838         RATETAB_ENT(DOT11_RATE_24M, 0),
839         RATETAB_ENT(DOT11_RATE_36M, 0),
840         RATETAB_ENT(DOT11_RATE_48M, 0),
841         RATETAB_ENT(DOT11_RATE_54M, 0)
842 };
843
844 #define wl_a_rates              (__wl_rates + 4)
845 #define wl_a_rates_size 8
846 #define wl_g_rates              (__wl_rates + 0)
847 #define wl_g_rates_size 12
848
849 static struct ieee80211_channel __wl_2ghz_channels[] = {
850         CHAN2G(1, 2412, 0),
851         CHAN2G(2, 2417, 0),
852         CHAN2G(3, 2422, 0),
853         CHAN2G(4, 2427, 0),
854         CHAN2G(5, 2432, 0),
855         CHAN2G(6, 2437, 0),
856         CHAN2G(7, 2442, 0),
857         CHAN2G(8, 2447, 0),
858         CHAN2G(9, 2452, 0),
859         CHAN2G(10, 2457, 0),
860         CHAN2G(11, 2462, 0),
861         CHAN2G(12, 2467, 0),
862         CHAN2G(13, 2472, 0),
863         CHAN2G(14, 2484, 0)
864 };
865
866 static struct ieee80211_channel __wl_5ghz_a_channels[] = {
867         CHAN5G(34, 0), CHAN5G(36, 0),
868         CHAN5G(38, 0), CHAN5G(40, 0),
869         CHAN5G(42, 0), CHAN5G(44, 0),
870         CHAN5G(46, 0), CHAN5G(48, 0),
871         CHAN5G(52, 0), CHAN5G(56, 0),
872         CHAN5G(60, 0), CHAN5G(64, 0),
873         CHAN5G(100, 0), CHAN5G(104, 0),
874         CHAN5G(108, 0), CHAN5G(112, 0),
875         CHAN5G(116, 0), CHAN5G(120, 0),
876         CHAN5G(124, 0), CHAN5G(128, 0),
877         CHAN5G(132, 0), CHAN5G(136, 0),
878         CHAN5G(140, 0), CHAN5G(144, 0),
879         CHAN5G(149, 0), CHAN5G(153, 0),
880         CHAN5G(157, 0), CHAN5G(161, 0),
881         CHAN5G(165, 0)
882 };
883
884 static struct ieee80211_supported_band __wl_band_2ghz = {
885         .band = IEEE80211_BAND_2GHZ,
886         .channels = __wl_2ghz_channels,
887         .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
888         .bitrates = wl_g_rates,
889         .n_bitrates = wl_g_rates_size
890 };
891
892 static struct ieee80211_supported_band __wl_band_5ghz_a = {
893         .band = IEEE80211_BAND_5GHZ,
894         .channels = __wl_5ghz_a_channels,
895         .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
896         .bitrates = wl_a_rates,
897         .n_bitrates = wl_a_rates_size
898 };
899
900 static const u32 __wl_cipher_suites[] = {
901         WLAN_CIPHER_SUITE_WEP40,
902         WLAN_CIPHER_SUITE_WEP104,
903         WLAN_CIPHER_SUITE_TKIP,
904         WLAN_CIPHER_SUITE_CCMP,
905         WLAN_CIPHER_SUITE_AES_CMAC,
906 };
907
908 #ifdef WL_SUPPORT_ACS
909 /*
910  * The firmware code required for this feature to work is currently under
911  * BCMINTERNAL flag. In future if this is to enabled we need to bring the
912  * required firmware code out of the BCMINTERNAL flag.
913  */
914 struct wl_dump_survey {
915         u32 obss;
916         u32 ibss;
917         u32 no_ctg;
918         u32 no_pckt;
919         u32 tx;
920         u32 idle;
921 };
922 #endif /* WL_SUPPORT_ACS */
923
924
925 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
926 static int maxrxpktglom = 0;
927 #endif
928
929 /* IOCtl version read from targeted driver */
930 static int ioctl_version;
931 #ifdef DEBUGFS_CFG80211
932 #define S_SUBLOGLEVEL 20
933 static const struct {
934         u32 log_level;
935         char *sublogname;
936 } sublogname_map[] = {
937         {WL_DBG_ERR, "ERR"},
938         {WL_DBG_INFO, "INFO"},
939         {WL_DBG_DBG, "DBG"},
940         {WL_DBG_SCAN, "SCAN"},
941         {WL_DBG_TRACE, "TRACE"},
942         {WL_DBG_P2P_ACTION, "P2PACTION"}
943 };
944 #endif
945
946 #ifdef CUSTOMER_HW4_DEBUG
947 uint prev_dhd_console_ms = 0;
948 u32 prev_wl_dbg_level = 0;
949 bool wl_scan_timeout_dbg_enabled = 0;
950 static void wl_scan_timeout_dbg_set(void);
951 static void wl_scan_timeout_dbg_clear(void);
952
953 static void wl_scan_timeout_dbg_set(void)
954 {
955         WL_ERR(("Enter \n"));
956         prev_dhd_console_ms = dhd_console_ms;
957         prev_wl_dbg_level = wl_dbg_level;
958
959         dhd_console_ms = 1;
960         wl_dbg_level |= (WL_DBG_ERR | WL_DBG_P2P_ACTION | WL_DBG_SCAN);
961
962         wl_scan_timeout_dbg_enabled = 1;
963 }
964 static void wl_scan_timeout_dbg_clear(void)
965 {
966         WL_ERR(("Enter \n"));
967         dhd_console_ms = prev_dhd_console_ms;
968         wl_dbg_level = prev_wl_dbg_level;
969
970         wl_scan_timeout_dbg_enabled = 0;
971 }
972 #endif /* CUSTOMER_HW4_DEBUG */
973
974 /* watchdog timer for disconnecting when fw is not associated for FW_ASSOC_WATCHDOG_TIME ms */
975 uint32 fw_assoc_watchdog_ms = 0;
976 bool fw_assoc_watchdog_started = 0;
977 #define FW_ASSOC_WATCHDOG_TIME 10 * 1000 /* msec */
978
979 #ifdef DHD_IFDEBUG
980
981 void wl_dump_ifinfo(struct bcm_cfg80211 *cfg)
982 {
983         WL_ERR(("cfg=%p\n", cfg));
984         if (cfg) {
985                 WL_ERR(("cfg->wdev=%p\n", bcmcfg_to_prmry_wdev(cfg)));
986                 if (bcmcfg_to_prmry_wdev(cfg)) {
987                         WL_ERR(("cfg->wdev->wiphy=%p\n", bcmcfg_to_wiphy(cfg)));
988                         WL_ERR(("cfg->wdev->netdev=%p\n", bcmcfg_to_prmry_ndev(cfg)));
989                 }
990         }
991 }
992 #endif
993
994 static void wl_add_remove_pm_enable_work(struct bcm_cfg80211 *cfg,
995         enum wl_pm_workq_act_type type)
996 {
997         u16 wq_duration = 0;
998
999         if (cfg == NULL)
1000                 return;
1001
1002         mutex_lock(&cfg->pm_sync);
1003         /*
1004          * Make cancel and schedule work part mutually exclusive
1005          * so that while cancelling, we are sure that there is no
1006          * work getting scheduled.
1007          */
1008         if (delayed_work_pending(&cfg->pm_enable_work)) {
1009                 cancel_delayed_work_sync(&cfg->pm_enable_work);
1010                 DHD_OS_WAKE_UNLOCK(cfg->pub);
1011         }
1012
1013         if (type == WL_PM_WORKQ_SHORT) {
1014                 wq_duration = WL_PM_ENABLE_TIMEOUT;
1015         } else if (type == WL_PM_WORKQ_LONG) {
1016                 wq_duration = (WL_PM_ENABLE_TIMEOUT*2);
1017         }
1018         if (wq_duration) {
1019                 DHD_OS_WAKE_LOCK(cfg->pub);
1020                 schedule_delayed_work(&cfg->pm_enable_work,
1021                                 msecs_to_jiffies((const unsigned int)wq_duration));
1022         }
1023         mutex_unlock(&cfg->pm_sync);
1024 }
1025
1026 /* Return a new chanspec given a legacy chanspec
1027  * Returns INVCHANSPEC on error
1028  */
1029 static chanspec_t
1030 wl_chspec_from_legacy(chanspec_t legacy_chspec)
1031 {
1032         chanspec_t chspec;
1033
1034         /* get the channel number */
1035         chspec = LCHSPEC_CHANNEL(legacy_chspec);
1036
1037         /* convert the band */
1038         if (LCHSPEC_IS2G(legacy_chspec)) {
1039                 chspec |= WL_CHANSPEC_BAND_2G;
1040         } else {
1041                 chspec |= WL_CHANSPEC_BAND_5G;
1042         }
1043
1044         /* convert the bw and sideband */
1045         if (LCHSPEC_IS20(legacy_chspec)) {
1046                 chspec |= WL_CHANSPEC_BW_20;
1047         } else {
1048                 chspec |= WL_CHANSPEC_BW_40;
1049                 if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
1050                         chspec |= WL_CHANSPEC_CTL_SB_L;
1051                 } else {
1052                         chspec |= WL_CHANSPEC_CTL_SB_U;
1053                 }
1054         }
1055
1056         if (wf_chspec_malformed(chspec)) {
1057                 WL_ERR(("wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
1058                         chspec));
1059                 return INVCHANSPEC;
1060         }
1061
1062         return chspec;
1063 }
1064
1065 /* Return a legacy chanspec given a new chanspec
1066  * Returns INVCHANSPEC on error
1067  */
1068 static chanspec_t
1069 wl_chspec_to_legacy(chanspec_t chspec)
1070 {
1071         chanspec_t lchspec;
1072
1073         if (wf_chspec_malformed(chspec)) {
1074                 WL_ERR(("wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n",
1075                         chspec));
1076                 return INVCHANSPEC;
1077         }
1078
1079         /* get the channel number */
1080         lchspec = CHSPEC_CHANNEL(chspec);
1081
1082         /* convert the band */
1083         if (CHSPEC_IS2G(chspec)) {
1084                 lchspec |= WL_LCHANSPEC_BAND_2G;
1085         } else {
1086                 lchspec |= WL_LCHANSPEC_BAND_5G;
1087         }
1088
1089         /* convert the bw and sideband */
1090         if (CHSPEC_IS20(chspec)) {
1091                 lchspec |= WL_LCHANSPEC_BW_20;
1092                 lchspec |= WL_LCHANSPEC_CTL_SB_NONE;
1093         } else if (CHSPEC_IS40(chspec)) {
1094                 lchspec |= WL_LCHANSPEC_BW_40;
1095                 if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_L) {
1096                         lchspec |= WL_LCHANSPEC_CTL_SB_LOWER;
1097                 } else {
1098                         lchspec |= WL_LCHANSPEC_CTL_SB_UPPER;
1099                 }
1100         } else {
1101                 /* cannot express the bandwidth */
1102                 char chanbuf[CHANSPEC_STR_LEN];
1103                 WL_ERR((
1104                         "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) "
1105                         "to pre-11ac format\n",
1106                         wf_chspec_ntoa(chspec, chanbuf), chspec));
1107                 return INVCHANSPEC;
1108         }
1109
1110         return lchspec;
1111 }
1112
1113 /* given a chanspec value, do the endian and chanspec version conversion to
1114  * a chanspec_t value
1115  * Returns INVCHANSPEC on error
1116  */
1117 chanspec_t
1118 wl_chspec_host_to_driver(chanspec_t chanspec)
1119 {
1120         if (ioctl_version == 1) {
1121                 chanspec = wl_chspec_to_legacy(chanspec);
1122                 if (chanspec == INVCHANSPEC) {
1123                         return chanspec;
1124                 }
1125         }
1126         chanspec = htodchanspec(chanspec);
1127
1128         return chanspec;
1129 }
1130
1131 /* given a channel value, do the endian and chanspec version conversion to
1132  * a chanspec_t value
1133  * Returns INVCHANSPEC on error
1134  */
1135 chanspec_t
1136 wl_ch_host_to_driver(s32 bssidx, u16 channel)
1137 {
1138         chanspec_t chanspec;
1139
1140         chanspec = channel & WL_CHANSPEC_CHAN_MASK;
1141
1142         if (channel <= CH_MAX_2G_CHANNEL)
1143                 chanspec |= WL_CHANSPEC_BAND_2G;
1144         else
1145                 chanspec |= WL_CHANSPEC_BAND_5G;
1146
1147         chanspec |= wl_cfg80211_ulb_get_min_bw_chspec(NULL, bssidx);
1148
1149         chanspec |= WL_CHANSPEC_CTL_SB_NONE;
1150
1151         return wl_chspec_host_to_driver(chanspec);
1152 }
1153
1154 /* given a chanspec value from the driver, do the endian and chanspec version conversion to
1155  * a chanspec_t value
1156  * Returns INVCHANSPEC on error
1157  */
1158 chanspec_t
1159 wl_chspec_driver_to_host(chanspec_t chanspec)
1160 {
1161         chanspec = dtohchanspec(chanspec);
1162         if (ioctl_version == 1) {
1163                 chanspec = wl_chspec_from_legacy(chanspec);
1164         }
1165
1166         return chanspec;
1167 }
1168
1169 /*
1170  * convert ASCII string to MAC address (colon-delimited format)
1171  * eg: 00:11:22:33:44:55
1172  */
1173 int
1174 wl_cfg80211_ether_atoe(const char *a, struct ether_addr *n)
1175 {
1176         char *c = NULL;
1177         int count = 0;
1178
1179         memset(n, 0, ETHER_ADDR_LEN);
1180         for (;;) {
1181                 n->octet[count++] = (uint8)simple_strtoul(a, &c, 16);
1182                 if (!*c++ || count == ETHER_ADDR_LEN)
1183                         break;
1184                 a = c;
1185         }
1186         return (count == ETHER_ADDR_LEN);
1187 }
1188
1189 /* There isn't a lot of sense in it, but you can transmit anything you like */
1190 static const struct ieee80211_txrx_stypes
1191 wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
1192         [NL80211_IFTYPE_ADHOC] = {
1193                 .tx = 0xffff,
1194                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
1195         },
1196         [NL80211_IFTYPE_STATION] = {
1197                 .tx = 0xffff,
1198                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1199                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
1200         },
1201         [NL80211_IFTYPE_AP] = {
1202                 .tx = 0xffff,
1203                 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
1204                 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
1205                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
1206                 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
1207                 BIT(IEEE80211_STYPE_AUTH >> 4) |
1208                 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
1209                 BIT(IEEE80211_STYPE_ACTION >> 4)
1210         },
1211         [NL80211_IFTYPE_AP_VLAN] = {
1212                 /* copy AP */
1213                 .tx = 0xffff,
1214                 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
1215                 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
1216                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
1217                 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
1218                 BIT(IEEE80211_STYPE_AUTH >> 4) |
1219                 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
1220                 BIT(IEEE80211_STYPE_ACTION >> 4)
1221         },
1222         [NL80211_IFTYPE_P2P_CLIENT] = {
1223                 .tx = 0xffff,
1224                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1225                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
1226         },
1227         [NL80211_IFTYPE_P2P_GO] = {
1228                 .tx = 0xffff,
1229                 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
1230                 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
1231                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
1232                 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
1233                 BIT(IEEE80211_STYPE_AUTH >> 4) |
1234                 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
1235                 BIT(IEEE80211_STYPE_ACTION >> 4)
1236         },
1237 #if defined(WL_CFG80211_P2P_DEV_IF)
1238         [NL80211_IFTYPE_P2P_DEVICE] = {
1239                 .tx = 0xffff,
1240                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1241                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
1242         },
1243 #endif /* WL_CFG80211_P2P_DEV_IF */
1244 };
1245
1246 static void swap_key_from_BE(struct wl_wsec_key *key)
1247 {
1248         key->index = htod32(key->index);
1249         key->len = htod32(key->len);
1250         key->algo = htod32(key->algo);
1251         key->flags = htod32(key->flags);
1252         key->rxiv.hi = htod32(key->rxiv.hi);
1253         key->rxiv.lo = htod16(key->rxiv.lo);
1254         key->iv_initialized = htod32(key->iv_initialized);
1255 }
1256
1257 static void swap_key_to_BE(struct wl_wsec_key *key)
1258 {
1259         key->index = dtoh32(key->index);
1260         key->len = dtoh32(key->len);
1261         key->algo = dtoh32(key->algo);
1262         key->flags = dtoh32(key->flags);
1263         key->rxiv.hi = dtoh32(key->rxiv.hi);
1264         key->rxiv.lo = dtoh16(key->rxiv.lo);
1265         key->iv_initialized = dtoh32(key->iv_initialized);
1266 }
1267
1268 /* Dump the contents of the encoded wps ie buffer and get pbc value */
1269 static void
1270 wl_validate_wps_ie(char *wps_ie, s32 wps_ie_len, bool *pbc)
1271 {
1272         #define WPS_IE_FIXED_LEN 6
1273         u16 len;
1274         u8 *subel = NULL;
1275         u16 subelt_id;
1276         u16 subelt_len;
1277         u16 val;
1278         u8 *valptr = (uint8*) &val;
1279         if (wps_ie == NULL || wps_ie_len < WPS_IE_FIXED_LEN) {
1280                 WL_ERR(("invalid argument : NULL\n"));
1281                 return;
1282         }
1283         len = (u16)wps_ie[TLV_LEN_OFF];
1284
1285         if (len > wps_ie_len) {
1286                 WL_ERR(("invalid length len %d, wps ie len %d\n", len, wps_ie_len));
1287                 return;
1288         }
1289         WL_DBG(("wps_ie len=%d\n", len));
1290         len -= 4;       /* for the WPS IE's OUI, oui_type fields */
1291         subel = wps_ie + WPS_IE_FIXED_LEN;
1292         while (len >= 4) {              /* must have attr id, attr len fields */
1293                 valptr[0] = *subel++;
1294                 valptr[1] = *subel++;
1295                 subelt_id = HTON16(val);
1296
1297                 valptr[0] = *subel++;
1298                 valptr[1] = *subel++;
1299                 subelt_len = HTON16(val);
1300
1301                 len -= 4;                       /* for the attr id, attr len fields */
1302                 len -= subelt_len;      /* for the remaining fields in this attribute */
1303                 WL_DBG((" subel=%p, subelt_id=0x%x subelt_len=%u\n",
1304                         subel, subelt_id, subelt_len));
1305
1306                 if (subelt_id == WPS_ID_VERSION) {
1307                         WL_DBG(("  attr WPS_ID_VERSION: %u\n", *subel));
1308                 } else if (subelt_id == WPS_ID_REQ_TYPE) {
1309                         WL_DBG(("  attr WPS_ID_REQ_TYPE: %u\n", *subel));
1310                 } else if (subelt_id == WPS_ID_CONFIG_METHODS) {
1311                         valptr[0] = *subel;
1312                         valptr[1] = *(subel + 1);
1313                         WL_DBG(("  attr WPS_ID_CONFIG_METHODS: %x\n", HTON16(val)));
1314                 } else if (subelt_id == WPS_ID_DEVICE_NAME) {
1315                         char devname[100];
1316                         memcpy(devname, subel, subelt_len);
1317                         devname[subelt_len] = '\0';
1318                         WL_DBG(("  attr WPS_ID_DEVICE_NAME: %s (len %u)\n",
1319                                 devname, subelt_len));
1320                 } else if (subelt_id == WPS_ID_DEVICE_PWD_ID) {
1321                         valptr[0] = *subel;
1322                         valptr[1] = *(subel + 1);
1323                         WL_DBG(("  attr WPS_ID_DEVICE_PWD_ID: %u\n", HTON16(val)));
1324                         *pbc = (HTON16(val) == DEV_PW_PUSHBUTTON) ? true : false;
1325                 } else if (subelt_id == WPS_ID_PRIM_DEV_TYPE) {
1326                         valptr[0] = *subel;
1327                         valptr[1] = *(subel + 1);
1328                         WL_DBG(("  attr WPS_ID_PRIM_DEV_TYPE: cat=%u \n", HTON16(val)));
1329                         valptr[0] = *(subel + 6);
1330                         valptr[1] = *(subel + 7);
1331                         WL_DBG(("  attr WPS_ID_PRIM_DEV_TYPE: subcat=%u\n", HTON16(val)));
1332                 } else if (subelt_id == WPS_ID_REQ_DEV_TYPE) {
1333                         valptr[0] = *subel;
1334                         valptr[1] = *(subel + 1);
1335                         WL_DBG(("  attr WPS_ID_REQ_DEV_TYPE: cat=%u\n", HTON16(val)));
1336                         valptr[0] = *(subel + 6);
1337                         valptr[1] = *(subel + 7);
1338                         WL_DBG(("  attr WPS_ID_REQ_DEV_TYPE: subcat=%u\n", HTON16(val)));
1339                 } else if (subelt_id == WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS) {
1340                         valptr[0] = *subel;
1341                         valptr[1] = *(subel + 1);
1342                         WL_DBG(("  attr WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS"
1343                                 ": cat=%u\n", HTON16(val)));
1344                 } else {
1345                         WL_DBG(("  unknown attr 0x%x\n", subelt_id));
1346                 }
1347
1348                 subel += subelt_len;
1349         }
1350 }
1351
1352 s32 wl_set_tx_power(struct net_device *dev,
1353         enum nl80211_tx_power_setting type, s32 dbm)
1354 {
1355         s32 err = 0;
1356         s32 disable = 0;
1357         s32 txpwrqdbm;
1358         struct bcm_cfg80211 *cfg = g_bcm_cfg;
1359
1360         /* Make sure radio is off or on as far as software is concerned */
1361         disable = WL_RADIO_SW_DISABLE << 16;
1362         disable = htod32(disable);
1363         err = wldev_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable), true);
1364         if (unlikely(err)) {
1365                 WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
1366                 return err;
1367         }
1368
1369         if (dbm > 0xffff)
1370                 dbm = 0xffff;
1371         txpwrqdbm = dbm * 4;
1372         err = wldev_iovar_setbuf_bsscfg(dev, "qtxpower", (void *)&txpwrqdbm,
1373                 sizeof(txpwrqdbm), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
1374                 &cfg->ioctl_buf_sync);
1375         if (unlikely(err))
1376                 WL_ERR(("qtxpower error (%d)\n", err));
1377         else
1378                 WL_ERR(("dBm=%d, txpwrqdbm=0x%x\n", dbm, txpwrqdbm));
1379
1380         return err;
1381 }
1382
1383 s32 wl_get_tx_power(struct net_device *dev, s32 *dbm)
1384 {
1385         s32 err = 0;
1386         s32 txpwrdbm;
1387         struct bcm_cfg80211 *cfg = g_bcm_cfg;
1388
1389         err = wldev_iovar_getbuf_bsscfg(dev, "qtxpower",
1390                 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
1391         if (unlikely(err)) {
1392                 WL_ERR(("error (%d)\n", err));
1393                 return err;
1394         }
1395
1396         memcpy(&txpwrdbm, cfg->ioctl_buf, sizeof(txpwrdbm));
1397         txpwrdbm = dtoh32(txpwrdbm);
1398         *dbm = (txpwrdbm & ~WL_TXPWR_OVERRIDE) / 4;
1399
1400         WL_INFORM(("dBm=%d, txpwrdbm=0x%x\n", *dbm, txpwrdbm));
1401
1402         return err;
1403 }
1404
1405 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
1406 {
1407         chanspec_t chspec;
1408         int err = 0;
1409         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1410         struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
1411         struct ether_addr bssid;
1412         struct wl_bss_info *bss = NULL;
1413         s32 bssidx = 0; /* Explicitly set to primary bssidx */
1414
1415         if ((err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), false))) {
1416                 /* STA interface is not associated. So start the new interface on a temp
1417                  * channel . Later proper channel will be applied by the above framework
1418                  * via set_channel (cfg80211 API).
1419                  */
1420                 WL_DBG(("Not associated. Return a temp channel. \n"));
1421                 return wl_ch_host_to_driver(bssidx, WL_P2P_TEMP_CHAN);
1422         }
1423
1424
1425         *(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
1426         if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, cfg->extra_buf,
1427                 WL_EXTRA_BUF_MAX, false))) {
1428                         WL_ERR(("Failed to get associated bss info, use temp channel \n"));
1429                         chspec = wl_ch_host_to_driver(bssidx, WL_P2P_TEMP_CHAN);
1430         }
1431         else {
1432                         bss = (struct wl_bss_info *) (cfg->extra_buf + 4);
1433                         chspec =  bss->chanspec;
1434
1435                         WL_DBG(("Valid BSS Found. chanspec:%d \n", chspec));
1436         }
1437         return chspec;
1438 }
1439
1440 static bcm_struct_cfgdev *
1441 wl_cfg80211_add_monitor_if(char *name)
1442 {
1443 #if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)
1444         WL_INFORM(("wl_cfg80211_add_monitor_if: No more support monitor interface\n"));
1445         return ERR_PTR(-EOPNOTSUPP);
1446 #else
1447         struct net_device* ndev = NULL;
1448
1449         dhd_add_monitor(name, &ndev);
1450         WL_INFORM(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev));
1451         return ndev_to_cfgdev(ndev);
1452 #endif /* WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF */
1453 }
1454
1455 static bcm_struct_cfgdev *
1456 wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
1457 #if defined(WL_CFG80211_P2P_DEV_IF)
1458         const char *name,
1459 #else
1460         char *name,
1461 #endif /* WL_CFG80211_P2P_DEV_IF */
1462 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
1463         unsigned char name_assign_type,
1464 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) */
1465         enum nl80211_iftype type, u32 *flags,
1466         struct vif_params *params)
1467 {
1468         s32 err = -ENODEV;
1469         s32 timeout = -1;
1470         s32 wlif_type = -1;
1471         s32 mode = 0;
1472         s32 val = 0;
1473         s32 cfg_type;
1474         s32 dhd_mode = 0;
1475         chanspec_t chspec;
1476         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1477         struct net_device *primary_ndev;
1478         struct net_device *new_ndev;
1479         struct ether_addr primary_mac;
1480 #ifdef WL_VIRTUAL_APSTA
1481         bcm_struct_cfgdev *new_cfgdev;
1482 #endif /* WL_VIRTUAL_APSTA */
1483 #ifdef PROP_TXSTATUS_VSDB
1484 #if defined(BCMSDIO)
1485         s32 up = 1;
1486         dhd_pub_t *dhd;
1487         bool enabled;
1488 #endif 
1489 #endif /* PROP_TXSTATUS_VSDB */
1490 #if defined(SUPPORT_AP_POWERSAVE)
1491         dhd_pub_t *dhd;
1492 #endif /* SUPPORT_AP_POWERSAVE */
1493         bool hang_required = false;
1494
1495         if (!cfg)
1496                 return ERR_PTR(-EINVAL);
1497
1498 #ifdef PROP_TXSTATUS_VSDB
1499 #if defined(BCMSDIO)
1500         dhd = (dhd_pub_t *)(cfg->pub);
1501 #endif 
1502 #endif /* PROP_TXSTATUS_VSDB */
1503 #if defined(SUPPORT_AP_POWERSAVE)
1504         dhd = (dhd_pub_t *)(cfg->pub);
1505 #endif /* SUPPORT_AP_POWERSAVE */
1506
1507         /* Use primary I/F for sending cmds down to firmware */
1508         primary_ndev = bcmcfg_to_prmry_ndev(cfg);
1509
1510         if (unlikely(!wl_get_drv_status(cfg, READY, primary_ndev))) {
1511                 WL_ERR(("device is not ready\n"));
1512                 return ERR_PTR(-ENODEV);
1513         }
1514
1515         WL_DBG(("if name: %s, type: %d\n", name, type));
1516         switch (type) {
1517         case NL80211_IFTYPE_ADHOC:
1518 #ifdef WLAIBSS_MCHAN
1519                 return bcm_cfg80211_add_ibss_if(wiphy, (char *)name);
1520 #endif /* WLAIBSS_MCHAN */
1521         case NL80211_IFTYPE_AP_VLAN:
1522         case NL80211_IFTYPE_WDS:
1523         case NL80211_IFTYPE_MESH_POINT:
1524                 WL_ERR(("Unsupported interface type\n"));
1525                 mode = WL_MODE_IBSS;
1526                 return NULL;
1527         case NL80211_IFTYPE_MONITOR:
1528                 return wl_cfg80211_add_monitor_if((char *)name);
1529 #if defined(WL_CFG80211_P2P_DEV_IF)
1530         case NL80211_IFTYPE_P2P_DEVICE:
1531                 cfg->down_disc_if = FALSE;
1532                 return wl_cfgp2p_add_p2p_disc_if(cfg);
1533 #endif /* WL_CFG80211_P2P_DEV_IF */
1534         case NL80211_IFTYPE_STATION:
1535 #ifdef WL_VIRTUAL_APSTA
1536 #ifdef WLAIBSS_MCHAN
1537                 if (cfg->ibss_cfgdev) {
1538                         WL_ERR(("AIBSS is already operational. "
1539                                         " AIBSS & DUALSTA can't be used together \n"));
1540                         return ERR_PTR(-ENOMEM);
1541                 }
1542 #endif /* WLAIBSS_MCHAN */
1543                 if (!name) {
1544                         WL_ERR(("Interface name not provided \n"));
1545                         return ERR_PTR(-ENODEV);
1546                 }
1547
1548                 if (wl_cfgp2p_vif_created(cfg)) {
1549                         WL_ERR(("Could not create new iface."
1550                                 "Already one p2p interface is running"));
1551                         return ERR_PTR(-ENODEV);
1552                 }
1553                 new_cfgdev = wl_cfg80211_create_iface(cfg->wdev->wiphy,
1554                         NL80211_IFTYPE_STATION, NULL, name);
1555                 if (!new_cfgdev)
1556                         return ERR_PTR(-ENOMEM);
1557                 else
1558                         return new_cfgdev;
1559 #endif /* WL_VIRTUAL_APSTA */
1560         case NL80211_IFTYPE_P2P_CLIENT:
1561                 wlif_type = WL_P2P_IF_CLIENT;
1562                 mode = WL_MODE_BSS;
1563                 break;
1564         case NL80211_IFTYPE_P2P_GO:
1565         case NL80211_IFTYPE_AP:
1566                 wlif_type = WL_P2P_IF_GO;
1567                 mode = WL_MODE_AP;
1568                 break;
1569         default:
1570                 WL_ERR(("Unsupported interface type\n"));
1571                 return ERR_PTR(-ENODEV);
1572                 break;
1573         }
1574
1575         if (!name) {
1576                 WL_ERR(("name is NULL\n"));
1577                 return ERR_PTR(-ENODEV);
1578         }
1579         if (cfg->p2p_supported && (wlif_type != -1)) {
1580                 ASSERT(cfg->p2p); /* ensure expectation of p2p initialization */
1581
1582 #ifdef PROP_TXSTATUS_VSDB
1583 #if defined(BCMSDIO)
1584                 if (!dhd)
1585                         return ERR_PTR(-ENODEV);
1586 #endif 
1587 #endif /* PROP_TXSTATUS_VSDB */
1588                 if (!cfg->p2p)
1589                         return ERR_PTR(-ENODEV);
1590
1591                 if (cfg->cfgdev_bssidx != -1) {
1592                         WL_ERR(("Failed to start p2p, Maximum no of interface reached"));
1593                         return ERR_PTR(-ENODEV);
1594                 }
1595
1596                 if (cfg->p2p && !cfg->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
1597                         p2p_on(cfg) = true;
1598                         wl_cfgp2p_set_firm_p2p(cfg);
1599                         wl_cfgp2p_init_discovery(cfg);
1600                         get_primary_mac(cfg, &primary_mac);
1601                         wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
1602                 }
1603
1604                 strncpy(cfg->p2p->vir_ifname, name, IFNAMSIZ - 1);
1605                 cfg->p2p->vir_ifname[IFNAMSIZ - 1] = '\0';
1606
1607                 wl_cfg80211_scan_abort(cfg);
1608 #ifdef PROP_TXSTATUS_VSDB
1609 #if defined(BCMSDIO)
1610                 if (!cfg->wlfc_on && !disable_proptx) {
1611                         dhd_wlfc_get_enable(dhd, &enabled);
1612                         if (!enabled && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
1613                                 dhd->op_mode != DHD_FLAG_IBSS_MODE) {
1614                                 dhd_wlfc_init(dhd);
1615                                 err = wldev_ioctl(primary_ndev, WLC_UP, &up, sizeof(s32), true);
1616                                 if (err < 0)
1617                                         WL_ERR(("WLC_UP return err:%d\n", err));
1618                         }
1619                         cfg->wlfc_on = true;
1620                 }
1621 #endif 
1622 #endif /* PROP_TXSTATUS_VSDB */
1623
1624                 /* Dual p2p doesn't support multiple P2PGO interfaces,
1625                  * p2p_go_count is the counter for GO creation
1626                  * requests.
1627                  */
1628                 if ((cfg->p2p->p2p_go_count > 0) && (type == NL80211_IFTYPE_P2P_GO)) {
1629                         WL_ERR(("Fw doesnot support  multiple Go"));
1630                         return ERR_PTR(-ENOMEM);
1631                 }
1632                 /* In concurrency case, STA may be already associated in a particular channel.
1633                  * so retrieve the current channel of primary interface and then start the virtual
1634                  * interface on that.
1635                  */
1636                  chspec = wl_cfg80211_get_shared_freq(wiphy);
1637
1638                 /* For P2P mode, use P2P-specific driver features to create the
1639                  * bss: "cfg p2p_ifadd"
1640                  */
1641                 if (wl_check_dongle_idle(wiphy) != TRUE) {
1642                         WL_ERR(("FW is busy to add interface"));
1643                         return ERR_PTR(-ENOMEM);
1644                 }
1645                 wl_set_p2p_status(cfg, IF_ADDING);
1646                 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
1647                 if (wlif_type == WL_P2P_IF_GO)
1648                         wldev_iovar_setint(primary_ndev, "mpc", 0);
1649                 cfg_type = wl_cfgp2p_get_conn_idx(cfg);
1650                 if (cfg_type == BCME_ERROR) {
1651                         wl_clr_p2p_status(cfg, IF_ADDING);
1652                         WL_ERR(("Failed to get connection idx for p2p interface"));
1653                         goto fail;
1654                 }
1655                 err = wl_cfgp2p_ifadd(cfg, wl_to_p2p_bss_macaddr(cfg, cfg_type),
1656                         htod32(wlif_type), chspec);
1657                 if (unlikely(err)) {
1658                         wl_clr_p2p_status(cfg, IF_ADDING);
1659                         WL_ERR((" virtual iface add failed (%d) \n", err));
1660                         return ERR_PTR(-ENOMEM);
1661                 }
1662
1663                 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
1664                         ((wl_get_p2p_status(cfg, IF_ADDING) == false) &&
1665                         (cfg->if_event_info.valid)),
1666                         msecs_to_jiffies(MAX_WAIT_TIME));
1667
1668                 if (timeout > 0 && !wl_get_p2p_status(cfg, IF_ADDING) && cfg->if_event_info.valid) {
1669                         struct wireless_dev *vwdev;
1670                         int pm_mode = PM_ENABLE;
1671                         wl_if_event_info *event = &cfg->if_event_info;
1672                         /* IF_ADD event has come back, we can proceed to to register
1673                          * the new interface now, use the interface name provided by caller (thus
1674                          * ignore the one from wlc)
1675                          */
1676                         new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx, cfg->p2p->vir_ifname,
1677                                 event->mac, event->bssidx, event->name);
1678                         if (new_ndev == NULL)
1679                                 goto fail;
1680
1681                         wl_to_p2p_bss_ndev(cfg, cfg_type) = new_ndev;
1682                         wl_to_p2p_bss_bssidx(cfg, cfg_type) = event->bssidx;
1683                         vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL);
1684                         if (unlikely(!vwdev)) {
1685                                 WL_ERR(("Could not allocate wireless device\n"));
1686                                 err = -ENOMEM;
1687                                 goto fail;
1688                         }
1689                         vwdev->wiphy = cfg->wdev->wiphy;
1690                         WL_INFORM(("virtual interface(%s) is created\n", cfg->p2p->vir_ifname));
1691                         if (type == NL80211_IFTYPE_P2P_GO) {
1692                                 cfg->p2p->p2p_go_count++;
1693                         }
1694                         vwdev->iftype = type;
1695 #ifdef DHD_IFDEBUG
1696                         WL_ERR(("new_ndev: %p\n", new_ndev));
1697 #endif
1698                         vwdev->netdev = new_ndev;
1699                         new_ndev->ieee80211_ptr = vwdev;
1700                         SET_NETDEV_DEV(new_ndev, wiphy_dev(vwdev->wiphy));
1701                         wl_set_drv_status(cfg, READY, new_ndev);
1702                         wl_set_mode_by_netdev(cfg, new_ndev, mode);
1703
1704                         if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev) != BCME_OK) {
1705                                 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev);
1706                                 err = -ENODEV;
1707                                 goto fail;
1708                         }
1709                         err = wl_alloc_netinfo(cfg, new_ndev, vwdev, mode, pm_mode, event->bssidx);
1710                         if (unlikely(err != 0)) {
1711                                 WL_ERR(("Allocation of netinfo failed (%d) \n", err));
1712                                 goto fail;
1713                         }
1714                         val = 1;
1715                         /* Disable firmware roaming for P2P interface  */
1716                         wldev_iovar_setint(new_ndev, "roam_off", val);
1717 #ifdef WL11ULB
1718                         if (cfg->p2p_wdev && is_p2p_group_iface(new_ndev->ieee80211_ptr)) {
1719                                 u32 ulb_bw = wl_cfg80211_get_ulb_bw(cfg->p2p_wdev);
1720                                 if (ulb_bw) {
1721                                         /* Apply ULB BW settings on the newly spawned interface */
1722                                         WL_DBG(("[ULB] Applying ULB BW for the newly"
1723                                                 "created P2P interface \n"));
1724                                         if (wl_cfg80211_set_ulb_bw(new_ndev,
1725                                                 ulb_bw, new_ndev->name) < 0) {
1726                                                 /*
1727                                                  * If ulb_bw set failed, fail the iface creation.
1728                                                  * wl_dealloc_netinfo_by_wdev will be called by the
1729                                                  * unregister notifier.
1730                                                  */
1731                                                 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev);
1732                                                 err = -EINVAL;
1733                                                 goto fail;
1734                                         }
1735                                 }
1736                         }
1737 #endif /* WL11ULB */
1738
1739                         if (mode != WL_MODE_AP)
1740                                 wldev_iovar_setint(new_ndev, "buf_key_b4_m4", 1);
1741
1742                         WL_ERR((" virtual interface(%s) is "
1743                                 "created net attach done\n", cfg->p2p->vir_ifname));
1744                         if (mode == WL_MODE_AP)
1745                                 wl_set_drv_status(cfg, CONNECTED, new_ndev);
1746 #ifdef SUPPORT_AP_POWERSAVE
1747                         if (mode == WL_MODE_AP) {
1748                                 dhd_set_ap_powersave(dhd, 0, TRUE);
1749                         }
1750 #endif /* SUPPORT_AP_POWERSAVE */
1751                         if (type == NL80211_IFTYPE_P2P_CLIENT)
1752                                 dhd_mode = DHD_FLAG_P2P_GC_MODE;
1753                         else if (type == NL80211_IFTYPE_P2P_GO)
1754                                 dhd_mode = DHD_FLAG_P2P_GO_MODE;
1755                         DNGL_FUNC(dhd_cfg80211_set_p2p_info, (cfg, dhd_mode));
1756                         /* reinitialize completion to clear previous count */
1757 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
1758                         INIT_COMPLETION(cfg->iface_disable);
1759 #else
1760                         init_completion(&cfg->iface_disable);
1761 #endif
1762                         return ndev_to_cfgdev(new_ndev);
1763                 } else {
1764                         wl_clr_p2p_status(cfg, IF_ADDING);
1765                         WL_ERR((" virtual interface(%s) is not created \n", cfg->p2p->vir_ifname));
1766
1767                         WL_ERR(("left timeout : %d\n", timeout));
1768                         WL_ERR(("IF_ADDING status : %d\n", wl_get_p2p_status(cfg, IF_ADDING)));
1769                         WL_ERR(("event valid : %d\n", cfg->if_event_info.valid));
1770
1771                         wl_clr_p2p_status(cfg, GO_NEG_PHASE);
1772                         wl_set_p2p_status(cfg, IF_DELETING);
1773
1774                         err = wl_cfgp2p_ifdel(cfg, wl_to_p2p_bss_macaddr(cfg, cfg_type));
1775                         if (err == BCME_OK) {
1776                                 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
1777                                         ((wl_get_p2p_status(cfg, IF_DELETING) == false) &&
1778                                         (cfg->if_event_info.valid)),
1779                                         msecs_to_jiffies(MAX_WAIT_TIME));
1780                                 if (timeout > 0 && !wl_get_p2p_status(cfg, IF_DELETING) &&
1781                                         cfg->if_event_info.valid) {
1782                                          /*
1783                                           * Should indicate upper layer this failure case of p2p
1784                                           * interface creation
1785                                           */
1786                                         WL_ERR(("IFDEL operation done\n"));
1787                                 } else {
1788                                         WL_ERR(("IFDEL didn't complete properly\n"));
1789                                         hang_required = true;
1790                                 }
1791                         } else {
1792                                 hang_required = true;
1793                         }
1794
1795                         if (hang_required) {
1796                                 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
1797                                 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
1798
1799                                 WL_ERR(("p2p_ifdel failed, error %d, sent HANG event to %s\n",
1800                                         err, ndev->name));
1801                                 dhd->hang_reason = HANG_REASON_P2P_IFACE_DEL_FAILURE;
1802                                 net_os_send_hang_message(ndev);
1803                         }
1804
1805                         memset(cfg->p2p->vir_ifname, '\0', IFNAMSIZ);
1806                         wl_to_p2p_bss_bssidx(cfg, cfg_type) = -1;
1807 #ifdef PROP_TXSTATUS_VSDB
1808 #if defined(BCMSDIO)
1809                         dhd_wlfc_get_enable(dhd, &enabled);
1810                         if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
1811                                 dhd->op_mode != DHD_FLAG_IBSS_MODE) {
1812                                 dhd_wlfc_deinit(dhd);
1813                                 cfg->wlfc_on = false;
1814                         }
1815 #endif 
1816 #endif /* PROP_TXSTATUS_VSDB */
1817                         /*
1818                         * Returns -ENODEV to upperlayer to indicate that DHD
1819                         * failed to create p2p interface
1820                         */
1821                         err = -ENODEV;
1822                 }
1823         }
1824 fail:
1825         if (wlif_type == WL_P2P_IF_GO)
1826                 wldev_iovar_setint(primary_ndev, "mpc", 1);
1827         return ERR_PTR(err);
1828 }
1829
1830 static s32
1831 wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
1832 {
1833         struct net_device *dev = NULL;
1834         struct ether_addr p2p_mac;
1835         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1836         s32 timeout = -1;
1837         s32 ret = 0;
1838         s32 index = -1;
1839         s32 type = -1;
1840 #ifdef CUSTOM_SET_CPUCORE
1841         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
1842 #endif /* CUSTOM_SET_CPUCORE */
1843         WL_DBG(("Enter\n"));
1844
1845 #ifdef CUSTOM_SET_CPUCORE
1846         dhd->chan_isvht80 &= ~DHD_FLAG_P2P_MODE;
1847         if (!(dhd->chan_isvht80))
1848                 dhd_set_cpucore(dhd, FALSE);
1849 #endif /* CUSTOM_SET_CPUCORE */
1850 #ifdef WL_CFG80211_P2P_DEV_IF
1851         if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
1852                 if (dhd_download_fw_on_driverload) {
1853                         return wl_cfgp2p_del_p2p_disc_if(cfgdev, cfg);
1854                 } else {
1855                         cfg->down_disc_if = TRUE;
1856                         return 0;
1857                 }
1858         }
1859 #endif /* WL_CFG80211_P2P_DEV_IF */
1860         dev = cfgdev_to_wlc_ndev(cfgdev, cfg);
1861
1862 #ifdef WLAIBSS_MCHAN
1863         if (cfgdev == cfg->ibss_cfgdev)
1864                 return bcm_cfg80211_del_ibss_if(wiphy, cfgdev);
1865 #endif /* WLAIBSS_MCHAN */
1866
1867 #ifdef WL_VIRTUAL_APSTA
1868         if (cfgdev == cfg->bss_cfgdev)
1869                 return wl_cfg80211_del_iface(wiphy, cfgdev);
1870 #endif /* WL_VIRTUAL_APSTA */
1871         if ((index = wl_get_bssidx_by_wdev(cfg, cfgdev_to_wdev(cfgdev))) < 0) {
1872                 WL_ERR(("Find p2p index from wdev failed\n"));
1873                 return BCME_ERROR;
1874         }
1875         if (wl_check_dongle_idle(wiphy) != TRUE) {
1876                 WL_ERR(("FW is busy to add interface"));
1877                 return BCME_ERROR;
1878         }
1879         if (cfg->p2p_supported) {
1880                 if (wl_cfgp2p_find_type(cfg, index, &type) != BCME_OK)
1881                         return BCME_ERROR;
1882                 memcpy(p2p_mac.octet, wl_to_p2p_bss_macaddr(cfg, type).octet, ETHER_ADDR_LEN);
1883
1884                 /* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases
1885                  */
1886                 WL_DBG(("P2P: GO_NEG_PHASE status cleared "));
1887                 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
1888                 if (wl_cfgp2p_vif_created(cfg)) {
1889                         if (wl_get_drv_status(cfg, SCANNING, dev)) {
1890                                 wl_notify_escan_complete(cfg, dev, true, true);
1891                         }
1892                         wldev_iovar_setint(dev, "mpc", 1);
1893                         /* Delete pm_enable_work */
1894                         wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
1895
1896                         /* for GC */
1897                         if (wl_get_drv_status(cfg, DISCONNECTING, dev) &&
1898                                 (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_AP)) {
1899                                 WL_ERR(("Wait for Link Down event for GC !\n"));
1900                                 wait_for_completion_timeout
1901                                         (&cfg->iface_disable, msecs_to_jiffies(500));
1902                         }
1903
1904                         memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
1905                         wl_set_p2p_status(cfg, IF_DELETING);
1906                         DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (cfg));
1907
1908                         /* for GO */
1909                         if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
1910                                 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
1911                                 cfg->p2p->p2p_go_count--;
1912                                 /* disable interface before bsscfg free */
1913                                 ret = wl_cfgp2p_ifdisable(cfg, &p2p_mac);
1914                                 /* if fw doesn't support "ifdis",
1915                                    do not wait for link down of ap mode
1916                                  */
1917                                 if (ret == 0) {
1918                                         WL_ERR(("Wait for Link Down event for GO !!!\n"));
1919                                         wait_for_completion_timeout(&cfg->iface_disable,
1920                                                 msecs_to_jiffies(500));
1921                                 } else if (ret != BCME_UNSUPPORTED) {
1922                                         msleep(300);
1923                                 }
1924                         }
1925                         wl_cfg80211_clear_per_bss_ies(cfg, index);
1926
1927                         if (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_AP)
1928                                 wldev_iovar_setint(dev, "buf_key_b4_m4", 0);
1929                         memcpy(p2p_mac.octet, wl_to_p2p_bss_macaddr(cfg, type).octet,
1930                         ETHER_ADDR_LEN);
1931                         CFGP2P_INFO(("primary idx %d : cfg p2p_ifdis "MACDBG"\n",
1932                                dev->ifindex, MAC2STRDBG(p2p_mac.octet)));
1933
1934                         /* delete interface after link down */
1935                         ret = wl_cfgp2p_ifdel(cfg, &p2p_mac);
1936                         if (ret != BCME_OK) {
1937                                 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
1938                                 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
1939
1940                                 WL_ERR(("p2p_ifdel failed, error %d, sent HANG event to %s\n",
1941                                         ret, ndev->name));
1942                                 dhd->hang_reason = HANG_REASON_P2P_IFACE_DEL_FAILURE;
1943                                 net_os_send_hang_message(ndev);
1944                         } else {
1945                                 /* Wait for IF_DEL operation to be finished */
1946                                 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
1947                                         ((wl_get_p2p_status(cfg, IF_DELETING) == false) &&
1948                                         (cfg->if_event_info.valid)),
1949                                         msecs_to_jiffies(MAX_WAIT_TIME));
1950                                 if (timeout > 0 && !wl_get_p2p_status(cfg, IF_DELETING) &&
1951                                         cfg->if_event_info.valid) {
1952
1953                                         WL_DBG(("IFDEL operation done\n"));
1954                                         wl_cfg80211_handle_ifdel(cfg, &cfg->if_event_info, dev);
1955                                 } else {
1956                                         WL_ERR(("IFDEL didn't complete properly\n"));
1957                                 }
1958                         }
1959
1960                         ret = dhd_del_monitor(dev);
1961                         if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
1962                                 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_CANCEL((dhd_pub_t *)(cfg->pub));
1963                         }
1964                 }
1965         }
1966         return ret;
1967 }
1968
1969 static s32
1970 wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
1971         enum nl80211_iftype type, u32 *flags,
1972         struct vif_params *params)
1973 {
1974         s32 ap = 0;
1975         s32 infra = 0;
1976         s32 ibss = 0;
1977         s32 wlif_type;
1978         s32 mode = 0;
1979         s32 err = BCME_OK;
1980         s32 index;
1981         s32 conn_idx = -1;
1982         chanspec_t chspec;
1983         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1984         struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg);
1985         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
1986
1987         WL_DBG(("Enter type %d\n", type));
1988         switch (type) {
1989         case NL80211_IFTYPE_MONITOR:
1990         case NL80211_IFTYPE_WDS:
1991         case NL80211_IFTYPE_MESH_POINT:
1992                 ap = 1;
1993                 WL_ERR(("type (%d) : currently we do not support this type\n",
1994                         type));
1995                 break;
1996         case NL80211_IFTYPE_ADHOC:
1997                 mode = WL_MODE_IBSS;
1998                 ibss = 1;
1999                 break;
2000         case NL80211_IFTYPE_STATION:
2001         case NL80211_IFTYPE_P2P_CLIENT:
2002                 mode = WL_MODE_BSS;
2003                 infra = 1;
2004                 break;
2005         case NL80211_IFTYPE_AP:
2006                 dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
2007                 /* intentional fall through */
2008         case NL80211_IFTYPE_AP_VLAN:
2009         case NL80211_IFTYPE_P2P_GO:
2010                 mode = WL_MODE_AP;
2011                 ap = 1;
2012                 break;
2013         default:
2014                 return -EINVAL;
2015         }
2016         if (!dhd)
2017                 return -EINVAL;
2018
2019         /* If any scan is going on, abort it */
2020         if (wl_get_drv_status_all(cfg, SCANNING)) {
2021                 int wait_cnt = MAX_SCAN_ABORT_WAIT_CNT;
2022                 WL_ERR(("Scan in progress. Aborting the scan!\n"));
2023                 wl_cfg80211_scan_abort(cfg);
2024                 while (wl_get_drv_status_all(cfg, SCANNING) && wait_cnt) {
2025                         WL_DBG(("Waiting for SCANNING terminated, wait_cnt: %d\n", wait_cnt));
2026                         wait_cnt--;
2027                         OSL_SLEEP(WAIT_SCAN_ABORT_OSL_SLEEP_TIME);
2028                 }
2029                 if (wl_get_drv_status_all(cfg, SCANNING)) {
2030                         wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
2031                 }
2032         }
2033
2034         if (wl_check_dongle_idle(wiphy) != TRUE) {
2035                 WL_ERR(("FW is busy to add interface"));
2036                 return -EINVAL;
2037         }
2038         if (ap) {
2039                 wl_set_mode_by_netdev(cfg, ndev, mode);
2040                 if (is_p2p_group_iface(ndev->ieee80211_ptr) &&
2041                         cfg->p2p && wl_cfgp2p_vif_created(cfg)) {
2042                         WL_DBG(("p2p_vif_created p2p_on (%d)\n", p2p_on(cfg)));
2043                         wldev_iovar_setint(ndev, "mpc", 0);
2044                         wl_notify_escan_complete(cfg, ndev, true, true);
2045
2046                         /* Dual p2p doesn't support multiple P2PGO interfaces,
2047                          * p2p_go_count is the counter for GO creation
2048                          * requests.
2049                          */
2050                         if ((cfg->p2p->p2p_go_count > 0) && (type == NL80211_IFTYPE_P2P_GO)) {
2051                                 wl_set_mode_by_netdev(cfg, ndev, WL_MODE_BSS);
2052                                 WL_ERR(("Fw doesnot support  multiple GO "));
2053                                 return BCME_ERROR;
2054                         }
2055                         /* In concurrency case, STA may be already associated in a particular
2056                          * channel. so retrieve the current channel of primary interface and
2057                          * then start the virtual interface on that.
2058                          */
2059                         chspec = wl_cfg80211_get_shared_freq(wiphy);
2060                         index = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
2061                         if (index < 0) {
2062                                 WL_ERR(("Find p2p index from ndev(%p) failed\n", ndev));
2063                                 return BCME_ERROR;
2064                         }
2065                         if (wl_cfgp2p_find_type(cfg, index, &conn_idx) != BCME_OK)
2066                                 return BCME_ERROR;
2067
2068                         wlif_type = WL_P2P_IF_GO;
2069                         printf("%s : ap (%d), infra (%d), iftype (%d) conn_idx (%d)\n",
2070                                 ndev->name, ap, infra, type, conn_idx);
2071                         wl_set_p2p_status(cfg, IF_CHANGING);
2072                         wl_clr_p2p_status(cfg, IF_CHANGED);
2073                         wl_cfgp2p_ifchange(cfg, wl_to_p2p_bss_macaddr(cfg, conn_idx),
2074                                 htod32(wlif_type), chspec, conn_idx);
2075                         wait_event_interruptible_timeout(cfg->netif_change_event,
2076                                 (wl_get_p2p_status(cfg, IF_CHANGED) == true),
2077                                 msecs_to_jiffies(MAX_WAIT_TIME));
2078                         wl_set_mode_by_netdev(cfg, ndev, mode);
2079                         dhd->op_mode &= ~DHD_FLAG_P2P_GC_MODE;
2080                         dhd->op_mode |= DHD_FLAG_P2P_GO_MODE;
2081                         wl_clr_p2p_status(cfg, IF_CHANGING);
2082                         wl_clr_p2p_status(cfg, IF_CHANGED);
2083                         if (mode == WL_MODE_AP)
2084                                 wl_set_drv_status(cfg, CONNECTED, ndev);
2085 #ifdef SUPPORT_AP_POWERSAVE
2086                         dhd_set_ap_powersave(dhd, 0, TRUE);
2087 #endif /* SUPPORT_AP_POWERSAVE */
2088                 } else if (((ndev == primary_ndev) ||
2089                         (ndev == ((struct net_device *)cfgdev_to_ndev(cfg->bss_cfgdev)))) &&
2090                         !wl_get_drv_status(cfg, AP_CREATED, ndev)) {
2091                         wl_set_drv_status(cfg, AP_CREATING, ndev);
2092                 } else {
2093                         WL_ERR(("Cannot change the interface for GO or SOFTAP\n"));
2094                         return -EINVAL;
2095                 }
2096         } else {
2097                 /* P2P GO interface deletion is handled on the basis of role type (AP).
2098                  * So avoid changing role for p2p type.
2099                  */
2100                 if (ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
2101                         wl_set_mode_by_netdev(cfg, ndev, mode);
2102                 WL_DBG(("Change_virtual_iface for transition from GO/AP to client/STA"));
2103 #ifdef SUPPORT_AP_POWERSAVE
2104                 dhd_set_ap_powersave(dhd, 0, FALSE);
2105 #endif /* SUPPORT_AP_POWERSAVE */
2106         }
2107
2108         if (ibss) {
2109                 infra = 0;
2110                 wl_set_mode_by_netdev(cfg, ndev, mode);
2111                 err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(s32), true);
2112                 if (err < 0) {
2113                         WL_ERR(("SET Adhoc error %d\n", err));
2114                         return -EINVAL;
2115                 }
2116         }
2117
2118         ndev->ieee80211_ptr->iftype = type;
2119         return 0;
2120 }
2121
2122 s32
2123 wl_cfg80211_notify_ifadd(int ifidx, char *name, uint8 *mac, uint8 bssidx)
2124 {
2125         bool ifadd_expected = FALSE;
2126         struct bcm_cfg80211 *cfg = g_bcm_cfg;
2127
2128         /* P2P may send WLC_E_IF_ADD and/or WLC_E_IF_CHANGE during IF updating ("p2p_ifupd")
2129          * redirect the IF_ADD event to ifchange as it is not a real "new" interface
2130          */
2131         if (wl_get_p2p_status(cfg, IF_CHANGING))
2132                 return wl_cfg80211_notify_ifchange(ifidx, name, mac, bssidx);
2133
2134         /* Okay, we are expecting IF_ADD (as IF_ADDING is true) */
2135         if (wl_get_p2p_status(cfg, IF_ADDING)) {
2136                 ifadd_expected = TRUE;
2137                 wl_clr_p2p_status(cfg, IF_ADDING);
2138         } else if (cfg->bss_pending_op) {
2139                 ifadd_expected = TRUE;
2140                 cfg->bss_pending_op = FALSE;
2141         }
2142
2143         if (ifadd_expected) {
2144                 wl_if_event_info *if_event_info = &cfg->if_event_info;
2145
2146                 if_event_info->valid = TRUE;
2147                 if_event_info->ifidx = ifidx;
2148                 if_event_info->bssidx = bssidx;
2149                 strncpy(if_event_info->name, name, IFNAMSIZ);
2150                 if_event_info->name[IFNAMSIZ] = '\0';
2151                 if (mac)
2152                         memcpy(if_event_info->mac, mac, ETHER_ADDR_LEN);
2153                 wake_up_interruptible(&cfg->netif_change_event);
2154                 return BCME_OK;
2155         }
2156
2157         return BCME_ERROR;
2158 }
2159
2160 s32
2161 wl_cfg80211_notify_ifdel(int ifidx, char *name, uint8 *mac, uint8 bssidx)
2162 {
2163         bool ifdel_expected = FALSE;
2164         struct bcm_cfg80211 *cfg = g_bcm_cfg;
2165         wl_if_event_info *if_event_info = &cfg->if_event_info;
2166
2167         if (wl_get_p2p_status(cfg, IF_DELETING)) {
2168                 ifdel_expected = TRUE;
2169                 wl_clr_p2p_status(cfg, IF_DELETING);
2170         } else if (cfg->bss_pending_op) {
2171                 ifdel_expected = TRUE;
2172                 cfg->bss_pending_op = FALSE;
2173         }
2174
2175         if (ifdel_expected) {
2176                 if_event_info->valid = TRUE;
2177                 if_event_info->ifidx = ifidx;
2178                 if_event_info->bssidx = bssidx;
2179                 wake_up_interruptible(&cfg->netif_change_event);
2180                 return BCME_OK;
2181         }
2182
2183         return BCME_ERROR;
2184 }
2185
2186 s32
2187 wl_cfg80211_notify_ifchange(int ifidx, char *name, uint8 *mac, uint8 bssidx)
2188 {
2189         struct bcm_cfg80211 *cfg = g_bcm_cfg;
2190
2191         if (wl_get_p2p_status(cfg, IF_CHANGING)) {
2192                 wl_set_p2p_status(cfg, IF_CHANGED);
2193                 wake_up_interruptible(&cfg->netif_change_event);
2194                 return BCME_OK;
2195         }
2196
2197         return BCME_ERROR;
2198 }
2199
2200 static s32 wl_cfg80211_handle_ifdel(struct bcm_cfg80211 *cfg, wl_if_event_info *if_event_info,
2201         struct net_device* ndev)
2202 {
2203         s32 type = -1;
2204         s32 bssidx = -1;
2205 #ifdef PROP_TXSTATUS_VSDB
2206 #if defined(BCMSDIO)
2207         dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
2208         bool enabled;
2209 #endif 
2210 #endif /* PROP_TXSTATUS_VSDB */
2211
2212         bssidx = if_event_info->bssidx;
2213         if (bssidx != wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION1) &&
2214                 bssidx != wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION2)) {
2215                 WL_ERR(("got IF_DEL for if %d, not owned by cfg driver\n", bssidx));
2216                 return BCME_ERROR;
2217         }
2218
2219         if (p2p_is_on(cfg) && wl_cfgp2p_vif_created(cfg)) {
2220                 if (cfg->scan_request && (cfg->escan_info.ndev == ndev)) {
2221                         /* Abort any pending scan requests */
2222                         cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
2223                         WL_DBG(("ESCAN COMPLETED\n"));
2224                         wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, false);
2225                 }
2226
2227                 memset(cfg->p2p->vir_ifname, '\0', IFNAMSIZ);
2228                 if (wl_cfgp2p_find_type(cfg, bssidx, &type) == BCME_OK) {
2229                         /* Update P2P data */
2230                         wl_clr_drv_status(cfg, CONNECTED, wl_to_p2p_bss_ndev(cfg, type));
2231                         wl_to_p2p_bss_ndev(cfg, type) = NULL;
2232                         wl_to_p2p_bss_bssidx(cfg, type) = -1;
2233                 } else if (wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr) < 0) {
2234                         WL_ERR(("bssidx not known for the given ndev as per net_info data \n"));
2235                         return BCME_ERROR;
2236                 }
2237
2238 #ifdef PROP_TXSTATUS_VSDB
2239 #if defined(BCMSDIO)
2240                 dhd_wlfc_get_enable(dhd, &enabled);
2241                 if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
2242                         dhd->op_mode != DHD_FLAG_IBSS_MODE) {
2243                         dhd_wlfc_deinit(dhd);
2244                         cfg->wlfc_on = false;
2245                 }
2246 #endif 
2247 #endif /* PROP_TXSTATUS_VSDB */
2248         }
2249
2250         dhd_net_if_lock(ndev);
2251         wl_cfg80211_remove_if(cfg, if_event_info->ifidx, ndev);
2252         dhd_net_if_unlock(ndev);
2253
2254         return BCME_OK;
2255 }
2256
2257 /* Find listen channel */
2258 static s32 wl_find_listen_channel(struct bcm_cfg80211 *cfg,
2259         const u8 *ie, u32 ie_len)
2260 {
2261         wifi_p2p_ie_t *p2p_ie;
2262         u8 *end, *pos;
2263         s32 listen_channel;
2264
2265 /* unfortunately const cast required here - function is
2266  * a callback so its signature must not be changed
2267  * and cascade of changing wl_cfgp2p_find_p2pie
2268  * causes need for const cast in other places
2269  */
2270 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
2271         4 && __GNUC_MINOR__ >= 6))
2272 _Pragma("GCC diagnostic push")
2273 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
2274 #endif
2275         pos = (u8 *)ie;
2276 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
2277         4 && __GNUC_MINOR__ >= 6))
2278 _Pragma("GCC diagnostic pop")
2279 #endif
2280         p2p_ie = wl_cfgp2p_find_p2pie(pos, ie_len);
2281
2282         if (p2p_ie == NULL)
2283                 return 0;
2284
2285         pos = p2p_ie->subelts;
2286         end = p2p_ie->subelts + (p2p_ie->len - 4);
2287
2288         CFGP2P_DBG((" found p2p ie ! lenth %d \n",
2289                 p2p_ie->len));
2290
2291         while (pos < end) {
2292                 uint16 attr_len;
2293                 if (pos + 2 >= end) {
2294                         CFGP2P_DBG((" -- Invalid P2P attribute"));
2295                         return 0;
2296                 }
2297                 attr_len = ((uint16) (((pos + 1)[1] << 8) | (pos + 1)[0]));
2298
2299                 if (pos + 3 + attr_len > end) {
2300                         CFGP2P_DBG(("P2P: Attribute underflow "
2301                                    "(len=%u left=%d)",
2302                                    attr_len, (int) (end - pos - 3)));
2303                         return 0;
2304                 }
2305
2306                 /* if Listen Channel att id is 6 and the vailue is valid,
2307                  * return the listen channel
2308                  */
2309                 if (pos[0] == 6) {
2310                         /* listen channel subel length format
2311                          * 1(id) + 2(len) + 3(country) + 1(op. class) + 1(chan num)
2312                          */
2313                         listen_channel = pos[1 + 2 + 3 + 1];
2314
2315                         if (listen_channel == SOCIAL_CHAN_1 ||
2316                                 listen_channel == SOCIAL_CHAN_2 ||
2317                                 listen_channel == SOCIAL_CHAN_3) {
2318                                 CFGP2P_DBG((" Found my Listen Channel %d \n", listen_channel));
2319                                 return listen_channel;
2320                         }
2321                 }
2322                 pos += 3 + attr_len;
2323         }
2324         return 0;
2325 }
2326
2327 static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_request *request)
2328 {
2329         u32 n_ssids;
2330         u32 n_channels;
2331         u16 channel;
2332         chanspec_t chanspec;
2333         s32 i = 0, j = 0, offset;
2334         char *ptr;
2335         wlc_ssid_t ssid;
2336         struct bcm_cfg80211 *cfg = g_bcm_cfg;
2337         struct wireless_dev *wdev;
2338
2339         memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
2340         params->bss_type = DOT11_BSSTYPE_ANY;
2341         params->scan_type = 0;
2342         params->nprobes = -1;
2343         params->active_time = -1;
2344         params->passive_time = -1;
2345         params->home_time = -1;
2346         params->channel_num = 0;
2347         memset(&params->ssid, 0, sizeof(wlc_ssid_t));
2348
2349         WL_SCAN(("Preparing Scan request\n"));
2350         WL_SCAN(("nprobes=%d\n", params->nprobes));
2351         WL_SCAN(("active_time=%d\n", params->active_time));
2352         WL_SCAN(("passive_time=%d\n", params->passive_time));
2353         WL_SCAN(("home_time=%d\n", params->home_time));
2354         WL_SCAN(("scan_type=%d\n", params->scan_type));
2355
2356         params->nprobes = htod32(params->nprobes);
2357         params->active_time = htod32(params->active_time);
2358         params->passive_time = htod32(params->passive_time);
2359         params->home_time = htod32(params->home_time);
2360
2361         /* if request is null just exit so it will be all channel broadcast scan */
2362         if (!request)
2363                 return;
2364
2365         n_ssids = request->n_ssids;
2366         n_channels = request->n_channels;
2367
2368         /* Copy channel array if applicable */
2369         WL_SCAN(("### List of channelspecs to scan ###\n"));
2370         if (n_channels > 0) {
2371                 for (i = 0; i < n_channels; i++) {
2372                         chanspec = 0;
2373                         channel = ieee80211_frequency_to_channel(request->channels[i]->center_freq);
2374                         /* SKIP DFS channels for Secondary interface */
2375                         if ((cfg->escan_info.ndev != bcmcfg_to_prmry_ndev(cfg)) &&
2376                                 (request->channels[i]->flags &
2377 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
2378                                 (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN)))
2379 #else
2380                                 (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR)))
2381 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) */
2382                                 continue;
2383                         if (!dhd_conf_match_channel(cfg->pub, channel))
2384                                 continue;
2385
2386 #if defined(WL_CFG80211_P2P_DEV_IF)
2387                         wdev = request->wdev;
2388 #else
2389                         wdev = request->dev->ieee80211_ptr;
2390 #endif /* WL_CFG80211_P2P_DEV_IF */
2391                         chanspec = wl_cfg80211_ulb_get_min_bw_chspec(wdev, -1);
2392                         if (chanspec == INVCHANSPEC) {
2393                                 WL_ERR(("Invalid chanspec! Skipping channel\n"));
2394                                 continue;
2395                         }
2396
2397                         if (request->channels[i]->band == IEEE80211_BAND_2GHZ) {
2398                                 chanspec |= WL_CHANSPEC_BAND_2G;
2399                         } else {
2400                                 chanspec |= WL_CHANSPEC_BAND_5G;
2401                         }
2402                         params->channel_list[j] = channel;
2403                         params->channel_list[j] &= WL_CHANSPEC_CHAN_MASK;
2404                         params->channel_list[j] |= chanspec;
2405                         WL_SCAN(("Chan : %d, Channel spec: %x \n",
2406                                 channel, params->channel_list[j]));
2407                         params->channel_list[j] = wl_chspec_host_to_driver(params->channel_list[j]);
2408                         j++;
2409                 }
2410         } else {
2411                 WL_SCAN(("Scanning all channels\n"));
2412         }
2413         n_channels = j;
2414         /* Copy ssid array if applicable */
2415         WL_SCAN(("### List of SSIDs to scan ###\n"));
2416         if (n_ssids > 0) {
2417                 offset = offsetof(wl_scan_params_t, channel_list) + n_channels * sizeof(u16);
2418                 offset = roundup(offset, sizeof(u32));
2419                 ptr = (char*)params + offset;
2420                 for (i = 0; i < n_ssids; i++) {
2421                         memset(&ssid, 0, sizeof(wlc_ssid_t));
2422                         ssid.SSID_len = request->ssids[i].ssid_len;
2423                         memcpy(ssid.SSID, request->ssids[i].ssid, ssid.SSID_len);
2424                         if (!ssid.SSID_len)
2425                                 WL_SCAN(("%d: Broadcast scan\n", i));
2426                         else
2427                                 WL_SCAN(("%d: scan  for  %s size =%d\n", i,
2428                                 ssid.SSID, ssid.SSID_len));
2429                         memcpy(ptr, &ssid, sizeof(wlc_ssid_t));
2430                         ptr += sizeof(wlc_ssid_t);
2431                 }
2432         } else {
2433                 WL_SCAN(("Broadcast scan\n"));
2434         }
2435         /* Adding mask to channel numbers */
2436         params->channel_num =
2437                 htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) |
2438                        (n_channels & WL_SCAN_PARAMS_COUNT_MASK));
2439
2440         if (n_channels == 1) {
2441                 params->active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
2442                 params->nprobes = htod32(params->active_time / WL_SCAN_JOIN_PROBE_INTERVAL_MS);
2443         }
2444 }
2445
2446 static s32
2447 wl_get_valid_channels(struct net_device *ndev, u8 *valid_chan_list, s32 size)
2448 {
2449         wl_uint32_list_t *list;
2450         s32 err = BCME_OK;
2451         if (valid_chan_list == NULL || size <= 0)
2452                 return -ENOMEM;
2453
2454         memset(valid_chan_list, 0, size);
2455         list = (wl_uint32_list_t *)(void *) valid_chan_list;
2456         list->count = htod32(WL_NUMCHANNELS);
2457         err = wldev_ioctl(ndev, WLC_GET_VALID_CHANNELS, valid_chan_list, size, false);
2458         if (err != 0) {
2459                 WL_ERR(("get channels failed with %d\n", err));
2460         }
2461
2462         return err;
2463 }
2464
2465 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2466 #define FIRST_SCAN_ACTIVE_DWELL_TIME_MS 40
2467 bool g_first_broadcast_scan = TRUE;
2468 #endif 
2469
2470 static s32
2471 wl_run_escan(struct bcm_cfg80211 *cfg, struct net_device *ndev,
2472         struct cfg80211_scan_request *request, uint16 action)
2473 {
2474         s32 err = BCME_OK;
2475         u32 n_channels;
2476         u32 n_ssids;
2477         s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params));
2478         wl_escan_params_t *params = NULL;
2479         u8 chan_buf[sizeof(u32)*(WL_NUMCHANNELS + 1)];
2480         u32 num_chans = 0;
2481         s32 channel;
2482         u32 n_valid_chan;
2483         s32 search_state = WL_P2P_DISC_ST_SCAN;
2484         u32 i, j, n_nodfs = 0;
2485         u16 *default_chan_list = NULL;
2486         wl_uint32_list_t *list;
2487         s32 bssidx = -1;
2488         struct net_device *dev = NULL;
2489 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2490         bool is_first_init_2g_scan = false;
2491 #endif 
2492         p2p_scan_purpose_t      p2p_scan_purpose = P2P_SCAN_PURPOSE_MIN;
2493         scb_val_t scbval;
2494         static int cnt = 0;
2495
2496         WL_DBG(("Enter \n"));
2497
2498         /* scan request can come with empty request : perform all default scan */
2499         if (!cfg) {
2500                 err = -EINVAL;
2501                 goto exit;
2502         }
2503         if (!cfg->p2p_supported || !p2p_scan(cfg)) {
2504                 /* LEGACY SCAN TRIGGER */
2505                 WL_SCAN((" LEGACY E-SCAN START\n"));
2506
2507 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2508                 if (!request) {
2509                         err = -EINVAL;
2510                         goto exit;
2511                 }
2512                 if (ndev == bcmcfg_to_prmry_ndev(cfg) && g_first_broadcast_scan == true) {
2513                         is_first_init_2g_scan = true;
2514                         g_first_broadcast_scan = false;
2515                 }
2516 #endif 
2517
2518                 /* if scan request is not empty parse scan request paramters */
2519                 if (request != NULL) {
2520                         n_channels = request->n_channels;
2521                         n_ssids = request->n_ssids;
2522                         if (n_channels % 2)
2523                                 /* If n_channels is odd, add a padd of u16 */
2524                                 params_size += sizeof(u16) * (n_channels + 1);
2525                         else
2526                                 params_size += sizeof(u16) * n_channels;
2527
2528                         /* Allocate space for populating ssids in wl_escan_params_t struct */
2529                         params_size += sizeof(struct wlc_ssid) * n_ssids;
2530                 }
2531                 params = (wl_escan_params_t *) kzalloc(params_size, GFP_KERNEL);
2532                 if (params == NULL) {
2533                         err = -ENOMEM;
2534                         goto exit;
2535                 }
2536                 wl_scan_prep(&params->params, request);
2537
2538 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2539                 /* Override active_time to reduce scan time if it's first bradcast scan. */
2540                 if (is_first_init_2g_scan)
2541                         params->params.active_time = FIRST_SCAN_ACTIVE_DWELL_TIME_MS;
2542 #endif 
2543
2544                 params->version = htod32(ESCAN_REQ_VERSION);
2545                 params->action =  htod16(action);
2546                 wl_escan_set_sync_id(params->sync_id, cfg);
2547                 wl_escan_set_type(cfg, WL_SCANTYPE_LEGACY);
2548                 if (params_size + sizeof("escan") >= WLC_IOCTL_MEDLEN) {
2549                         WL_ERR(("ioctl buffer length not sufficient\n"));
2550                         kfree(params);
2551                         err = -ENOMEM;
2552                         goto exit;
2553                 }
2554                 if (cfg->active_scan == PASSIVE_SCAN) {
2555                         params->params.scan_type = DOT11_SCANTYPE_PASSIVE;
2556                         WL_DBG(("Passive scan_type %d \n", params->params.scan_type));
2557                 }
2558
2559                 bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
2560
2561                 err = wldev_iovar_setbuf(ndev, "escan", params, params_size,
2562                         cfg->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
2563                 WL_SCAN(("%s: LEGACY_SCAN sync ID: %d, bssidx: %d\n", __FUNCTION__, params->sync_id, bssidx));
2564                 if (unlikely(err)) {
2565                         if (err == BCME_EPERM)
2566                                 /* Scan Not permitted at this point of time */
2567                                 WL_DBG((" Escan not permitted at this time (%d)\n", err));
2568                         else
2569                                 WL_ERR((" Escan set error (%d)\n", err));
2570                 }
2571                 kfree(params);
2572         }
2573         else if (p2p_is_on(cfg) && p2p_scan(cfg)) {
2574                 /* P2P SCAN TRIGGER */
2575                 s32 _freq = 0;
2576                 n_nodfs = 0;
2577                 if (request && request->n_channels) {
2578                         num_chans = request->n_channels;
2579                         WL_SCAN((" chann number : %d\n", num_chans));
2580                         default_chan_list = kzalloc(num_chans * sizeof(*default_chan_list),
2581                                 GFP_KERNEL);
2582                         if (default_chan_list == NULL) {
2583                                 WL_ERR(("channel list allocation failed \n"));
2584                                 err = -ENOMEM;
2585                                 goto exit;
2586                         }
2587                         if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) {
2588 #ifdef P2P_SKIP_DFS
2589                                 int is_printed = false;
2590 #endif /* P2P_SKIP_DFS */
2591                                 list = (wl_uint32_list_t *) chan_buf;
2592                                 n_valid_chan = dtoh32(list->count);
2593                                 for (i = 0; i < num_chans; i++)
2594                                 {
2595                                         _freq = request->channels[i]->center_freq;
2596                                         channel = ieee80211_frequency_to_channel(_freq);
2597
2598                                         /* ignore DFS channels */
2599                                         if (request->channels[i]->flags &
2600 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2601                                                 (IEEE80211_CHAN_NO_IR
2602                                                 | IEEE80211_CHAN_RADAR))
2603 #else
2604                                                 (IEEE80211_CHAN_RADAR
2605                                                 | IEEE80211_CHAN_PASSIVE_SCAN))
2606 #endif
2607                                                 continue;
2608 #ifdef P2P_SKIP_DFS
2609                                         if (channel >= 52 && channel <= 144) {
2610                                                 if (is_printed == false) {
2611                                                         WL_ERR(("SKIP DFS CHANs(52~144)\n"));
2612                                                         is_printed = true;
2613                                                 }
2614                                                 continue;
2615                                         }
2616 #endif /* P2P_SKIP_DFS */
2617
2618                                         for (j = 0; j < n_valid_chan; j++) {
2619                                                 /* allows only supported channel on
2620                                                 *  current reguatory
2621                                                 */
2622                                                 if (channel == (dtoh32(list->element[j])))
2623                                                         default_chan_list[n_nodfs++] =
2624                                                                 channel;
2625                                         }
2626
2627                                 }
2628                         }
2629                         if (num_chans == SOCIAL_CHAN_CNT && (
2630                                                 (default_chan_list[0] == SOCIAL_CHAN_1) &&
2631                                                 (default_chan_list[1] == SOCIAL_CHAN_2) &&
2632                                                 (default_chan_list[2] == SOCIAL_CHAN_3))) {
2633                                 /* SOCIAL CHANNELS 1, 6, 11 */
2634                                 search_state = WL_P2P_DISC_ST_SEARCH;
2635                                 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2636                                 WL_INFORM(("P2P SEARCH PHASE START \n"));
2637                         } else if (((dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION1)) &&
2638                                 (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP)) ||
2639                                 ((dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION2)) &&
2640                                 (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP))) {
2641                                 /* If you are already a GO, then do SEARCH only */
2642                                 WL_INFORM(("Already a GO. Do SEARCH Only"));
2643                                 search_state = WL_P2P_DISC_ST_SEARCH;
2644                                 num_chans = n_nodfs;
2645                                 p2p_scan_purpose = P2P_SCAN_NORMAL;
2646
2647                         } else if (num_chans == 1) {
2648                                 p2p_scan_purpose = P2P_SCAN_CONNECT_TRY;
2649                         } else if (num_chans == SOCIAL_CHAN_CNT + 1) {
2650                         /* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by
2651                          * the supplicant
2652                          */
2653                                 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2654                         } else {
2655                                 WL_INFORM(("P2P SCAN STATE START \n"));
2656                                 num_chans = n_nodfs;
2657                                 p2p_scan_purpose = P2P_SCAN_NORMAL;
2658                         }
2659                 } else {
2660                         err = -EINVAL;
2661                         goto exit;
2662                 }
2663                 err = wl_cfgp2p_escan(cfg, ndev, ACTIVE_SCAN, num_chans, default_chan_list,
2664                         search_state, action,
2665                         wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE), NULL,
2666                         p2p_scan_purpose);
2667
2668                 if (!err)
2669                         cfg->p2p->search_state = search_state;
2670
2671                 kfree(default_chan_list);
2672         }
2673 exit:
2674         if (unlikely(err)) {
2675                 /* Don't print Error incase of Scan suppress */
2676                 if ((err == BCME_EPERM) && cfg->scan_suppressed)
2677                         WL_DBG(("Escan failed: Scan Suppressed \n"));
2678                 else {
2679                         cnt++;
2680                         WL_ERR(("error (%d), cnt=%d\n", err, cnt));
2681                         // terence 20140111: send disassoc to firmware
2682                         if (cnt >= 4) {
2683                                 dev = bcmcfg_to_prmry_ndev(cfg);
2684                                 memset(&scbval, 0, sizeof(scb_val_t));
2685                                 wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true);
2686                                 WL_ERR(("Send disassoc to break the busy dev=%p\n", dev));
2687                                 cnt = 0;
2688                         }
2689                 }
2690         } else {
2691                 cnt = 0;
2692         }
2693         return err;
2694 }
2695
2696
2697 static s32
2698 wl_do_escan(struct bcm_cfg80211 *cfg, struct wiphy *wiphy, struct net_device *ndev,
2699         struct cfg80211_scan_request *request)
2700 {
2701         s32 err = BCME_OK;
2702         s32 passive_scan;
2703         s32 passive_scan_time;
2704         s32 passive_scan_time_org;
2705         wl_scan_results_t *results;
2706         WL_SCAN(("Enter \n"));
2707
2708         results = wl_escan_get_buf(cfg, FALSE);
2709         results->version = 0;
2710         results->count = 0;
2711         results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
2712
2713         cfg->escan_info.ndev = ndev;
2714         cfg->escan_info.wiphy = wiphy;
2715         cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
2716         passive_scan = cfg->active_scan ? 0 : 1;
2717         err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
2718                 &passive_scan, sizeof(passive_scan), true);
2719         if (unlikely(err)) {
2720                 WL_ERR(("error (%d)\n", err));
2721                 goto exit;
2722         }
2723
2724         if (passive_channel_skip) {
2725
2726                 err = wldev_ioctl(ndev, WLC_GET_SCAN_PASSIVE_TIME,
2727                         &passive_scan_time_org, sizeof(passive_scan_time_org), false);
2728                 if (unlikely(err)) {
2729                         WL_ERR(("== error (%d)\n", err));
2730                         goto exit;
2731                 }
2732
2733                 WL_SCAN(("PASSIVE SCAN time : %d \n", passive_scan_time_org));
2734
2735                 passive_scan_time = 0;
2736                 err = wldev_ioctl(ndev, WLC_SET_SCAN_PASSIVE_TIME,
2737                         &passive_scan_time, sizeof(passive_scan_time), true);
2738                 if (unlikely(err)) {
2739                         WL_ERR(("== error (%d)\n", err));
2740                         goto exit;
2741                 }
2742
2743                 WL_SCAN(("PASSIVE SCAN SKIPED!! (passive_channel_skip:%d) \n",
2744                         passive_channel_skip));
2745         }
2746
2747         err = wl_run_escan(cfg, ndev, request, WL_SCAN_ACTION_START);
2748
2749         if (passive_channel_skip) {
2750                 err = wldev_ioctl(ndev, WLC_SET_SCAN_PASSIVE_TIME,
2751                         &passive_scan_time_org, sizeof(passive_scan_time_org), true);
2752                 if (unlikely(err)) {
2753                         WL_ERR(("== error (%d)\n", err));
2754                         goto exit;
2755                 }
2756
2757                 WL_SCAN(("PASSIVE SCAN RECOVERED!! (passive_scan_time_org:%d) \n",
2758                         passive_scan_time_org));
2759         }
2760
2761 exit:
2762         return err;
2763 }
2764
2765 static s32
2766 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
2767         struct cfg80211_scan_request *request,
2768         struct cfg80211_ssid *this_ssid)
2769 {
2770         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2771         struct cfg80211_ssid *ssids;
2772         struct ether_addr primary_mac;
2773         bool p2p_ssid;
2774 #ifdef WL11U
2775         bcm_tlv_t *interworking_ie;
2776 #endif
2777         s32 err = 0;
2778         s32 bssidx = -1;
2779         s32 i;
2780
2781         unsigned long flags;
2782         static s32 busy_count = 0;
2783 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
2784         struct net_device *remain_on_channel_ndev = NULL;
2785 #endif
2786
2787         /*
2788          * Hostapd triggers scan before starting automatic channel selection
2789          * to collect channel characteristics. However firmware scan engine
2790          * doesn't support any channel characteristics collection along with
2791          * scan. Hence return scan success.
2792          */
2793         if (request && (scan_req_iftype(request) == NL80211_IFTYPE_AP)) {
2794                 WL_INFORM(("Scan Command on SoftAP Interface. Ignoring...\n"));
2795                 return 0;
2796         }
2797
2798         ndev = ndev_to_wlc_ndev(ndev, cfg);
2799
2800         if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg)) {
2801                 WL_ERR(("Sending Action Frames. Try it again.\n"));
2802                 return -EAGAIN;
2803         }
2804
2805         WL_DBG(("Enter wiphy (%p)\n", wiphy));
2806         if (wl_get_drv_status_all(cfg, SCANNING)) {
2807                 if (cfg->scan_request == NULL) {
2808                         wl_clr_drv_status_all(cfg, SCANNING);
2809                         WL_DBG(("<<<<<<<<<<<Force Clear Scanning Status>>>>>>>>>>>\n"));
2810                 } else {
2811                         WL_ERR(("Scanning already\n"));
2812                         return -EAGAIN;
2813                 }
2814         }
2815         if (wl_get_drv_status(cfg, SCAN_ABORTING, ndev)) {
2816                 WL_ERR(("Scanning being aborted\n"));
2817                 return -EAGAIN;
2818         }
2819         if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) {
2820                 WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n"));
2821                 return -EOPNOTSUPP;
2822         }
2823
2824 #ifdef P2P_LISTEN_OFFLOADING
2825         if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
2826                 WL_ERR(("P2P_FIND: Discovery offload is in progress\n"));
2827                 return -EAGAIN;
2828         }
2829 #endif /* P2P_LISTEN_OFFLOADING */
2830
2831 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
2832         remain_on_channel_ndev = wl_cfg80211_get_remain_on_channel_ndev(cfg);
2833         if (remain_on_channel_ndev) {
2834                 WL_DBG(("Remain_on_channel bit is set, somehow it didn't get cleared\n"));
2835                 wl_notify_escan_complete(cfg, remain_on_channel_ndev, true, true);
2836         }
2837 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
2838
2839
2840         /* Arm scan timeout timer */
2841         mod_timer(&cfg->scan_timeout, jiffies + msecs_to_jiffies(WL_SCAN_TIMER_INTERVAL_MS));
2842         if (request) {          /* scan bss */
2843                 ssids = request->ssids;
2844                 p2p_ssid = false;
2845                 for (i = 0; i < request->n_ssids; i++) {
2846                         if (ssids[i].ssid_len &&
2847                                 IS_P2P_SSID(ssids[i].ssid, ssids[i].ssid_len)) {
2848                                 p2p_ssid = true;
2849                                 break;
2850                         }
2851                 }
2852                 if (p2p_ssid) {
2853                         if (cfg->p2p_supported) {
2854                                 /* p2p scan trigger */
2855                                 if (p2p_on(cfg) == false) {
2856                                         /* p2p on at the first time */
2857                                         p2p_on(cfg) = true;
2858                                         wl_cfgp2p_set_firm_p2p(cfg);
2859                                         get_primary_mac(cfg, &primary_mac);
2860                                         wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
2861 #if defined(P2P_IE_MISSING_FIX)
2862                                         cfg->p2p_prb_noti = false;
2863 #endif
2864                                 }
2865                                 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
2866                                 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
2867                                 p2p_scan(cfg) = true;
2868                         }
2869                 } else {
2870                         /* legacy scan trigger
2871                          * So, we have to disable p2p discovery if p2p discovery is on
2872                          */
2873                         if (cfg->p2p_supported) {
2874                                 p2p_scan(cfg) = false;
2875                                 /* If Netdevice is not equals to primary and p2p is on
2876                                 *  , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
2877                                 */
2878
2879                                 if (p2p_scan(cfg) == false) {
2880                                         if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
2881                                                 err = wl_cfgp2p_discover_enable_search(cfg,
2882                                                 false);
2883                                                 if (unlikely(err)) {
2884                                                         goto scan_out;
2885                                                 }
2886
2887                                         }
2888                                 }
2889                         }
2890                         if (!cfg->p2p_supported || !p2p_scan(cfg)) {
2891                                 if ((bssidx = wl_get_bssidx_by_wdev(cfg,
2892                                         ndev->ieee80211_ptr)) < 0) {
2893                                         WL_ERR(("Find p2p index from ndev(%p) failed\n",
2894                                                 ndev));
2895                                         err = BCME_ERROR;
2896                                         goto scan_out;
2897                                 }
2898 #ifdef WL11U
2899                                 if ((interworking_ie = wl_cfg80211_find_interworking_ie(
2900                                         (u8 *)request->ie, request->ie_len)) != NULL) {
2901                                         err = wl_cfg80211_add_iw_ie(cfg, ndev, bssidx,
2902                                                VNDR_IE_CUSTOM_FLAG, interworking_ie->id,
2903                                                interworking_ie->data, interworking_ie->len);
2904
2905                                         if (unlikely(err)) {
2906                                                 WL_ERR(("Failed to add interworking IE"));
2907                                         }
2908                                 } else if (cfg->iw_ie_len != 0) {
2909                                 /* we have to clear IW IE and disable gratuitous APR */
2910                                         wl_cfg80211_add_iw_ie(cfg, ndev, bssidx,
2911                                                 VNDR_IE_CUSTOM_FLAG,
2912                                                 DOT11_MNG_INTERWORKING_ID,
2913                                                 0, 0);
2914
2915                                         (void)wldev_iovar_setint_bsscfg(ndev, "grat_arp", 0,
2916                                                 bssidx);
2917                                         cfg->wl11u = FALSE;
2918                                         cfg->iw_ie_len = 0;
2919                                         memset(cfg->iw_ie, 0, IW_IES_MAX_BUF_LEN);
2920                                         /* we don't care about error */
2921                                 }
2922 #endif /* WL11U */
2923                                 err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(ndev),
2924                                         bssidx, VNDR_IE_PRBREQ_FLAG, request->ie,
2925                                         request->ie_len);
2926
2927                                 if (unlikely(err)) {
2928                                         goto scan_out;
2929                                 }
2930
2931                         }
2932                 }
2933         } else {                /* scan in ibss */
2934                 ssids = this_ssid;
2935         }
2936
2937         if (request && cfg->p2p_supported && !p2p_scan(cfg)) {
2938                 WL_TRACE_HW4(("START SCAN\n"));
2939                 DHD_OS_SCAN_WAKE_LOCK_TIMEOUT((dhd_pub_t *)(cfg->pub),
2940                         SCAN_WAKE_LOCK_TIMEOUT);
2941                 DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
2942         }
2943
2944         if (cfg->p2p_supported) {
2945                 if (p2p_on(cfg) && p2p_scan(cfg)) {
2946
2947                         /* find my listen channel */
2948                         cfg->afx_hdl->my_listen_chan =
2949                                 wl_find_listen_channel(cfg, request->ie,
2950                                 request->ie_len);
2951                         err = wl_cfgp2p_enable_discovery(cfg, ndev,
2952                         request->ie, request->ie_len);
2953
2954                         if (unlikely(err)) {
2955                                 goto scan_out;
2956                         }
2957                 }
2958         }
2959         err = wl_do_escan(cfg, wiphy, ndev, request);
2960         if (likely(!err))
2961                 goto scan_success;
2962         else
2963                 goto scan_out;
2964
2965 scan_success:
2966         busy_count = 0;
2967         cfg->scan_request = request;
2968         wl_set_drv_status(cfg, SCANNING, ndev);
2969
2970         return 0;
2971
2972 scan_out:
2973         if (err == BCME_BUSY || err == BCME_NOTREADY) {
2974                 WL_ERR(("Scan err = (%d), busy?%d", err, -EBUSY));
2975                 err = -EBUSY;
2976         } else if ((err == BCME_EPERM) && cfg->scan_suppressed) {
2977                 WL_ERR(("Scan not permitted due to scan suppress\n"));
2978                 err = -EPERM;
2979         } else {
2980                 /* For all other fw errors, use a generic error code as return
2981                  * value to cfg80211 stack
2982                  */
2983                 err = -EAGAIN;
2984         }
2985
2986 #define SCAN_EBUSY_RETRY_LIMIT 20
2987         if (err == -EBUSY) {
2988                 if (busy_count++ > SCAN_EBUSY_RETRY_LIMIT) {
2989                         struct ether_addr bssid;
2990                         s32 ret = 0;
2991 #if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
2992                         dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
2993 #endif /* DHD_DEBUG && BCMPCIE && DHD_FW_COREDUMP */
2994                         busy_count = 0;
2995                         WL_ERR(("Unusual continuous EBUSY error, %d %d %d %d %d %d %d %d %d\n",
2996                                 wl_get_drv_status(cfg, SCANNING, ndev),
2997                                 wl_get_drv_status(cfg, SCAN_ABORTING, ndev),
2998                                 wl_get_drv_status(cfg, CONNECTING, ndev),
2999                                 wl_get_drv_status(cfg, CONNECTED, ndev),
3000                                 wl_get_drv_status(cfg, DISCONNECTING, ndev),
3001                                 wl_get_drv_status(cfg, AP_CREATING, ndev),
3002                                 wl_get_drv_status(cfg, AP_CREATED, ndev),
3003                                 wl_get_drv_status(cfg, SENDING_ACT_FRM, ndev),
3004                                 wl_get_drv_status(cfg, SENDING_ACT_FRM, ndev)));
3005
3006 #if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
3007                         if (dhdp->memdump_enabled) {
3008                                 dhdp->memdump_type = DUMP_TYPE_SCAN_BUSY;
3009                                 dhd_bus_mem_dump(dhdp);
3010                         }
3011 #endif /* DHD_DEBUG && BCMPCIE && DHD_FW_COREDUMP */
3012
3013                         bzero(&bssid, sizeof(bssid));
3014                         if ((ret = wldev_ioctl(ndev, WLC_GET_BSSID,
3015                                 &bssid, ETHER_ADDR_LEN, false)) == 0)
3016                                 WL_ERR(("FW is connected with " MACDBG "/n",
3017                                         MAC2STRDBG(bssid.octet)));
3018                         else
3019                                 WL_ERR(("GET BSSID failed with %d\n", ret));
3020
3021                         wl_cfg80211_scan_abort(cfg);
3022
3023                 } else {
3024                         /* Hold the context for 400msec, so that 10 subsequent scans
3025                         * can give a buffer of 4sec which is enough to
3026                         * cover any on-going scan in the firmware
3027                         */
3028                         WL_DBG(("Enforcing delay for EBUSY case \n"));
3029                         msleep(500);
3030                 }
3031         } else {
3032                 busy_count = 0;
3033         }
3034
3035         wl_clr_drv_status(cfg, SCANNING, ndev);
3036         if (timer_pending(&cfg->scan_timeout))
3037                 del_timer_sync(&cfg->scan_timeout);
3038         DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
3039         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
3040         cfg->scan_request = NULL;
3041         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
3042
3043         return err;
3044 }
3045
3046 static s32
3047 #if defined(WL_CFG80211_P2P_DEV_IF)
3048 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
3049 #else
3050 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
3051         struct cfg80211_scan_request *request)
3052 #endif /* WL_CFG80211_P2P_DEV_IF */
3053 {
3054         s32 err = 0;
3055         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3056 #if defined(WL_CFG80211_P2P_DEV_IF)
3057         struct net_device *ndev = wdev_to_wlc_ndev(request->wdev, cfg);
3058 #endif /* WL_CFG80211_P2P_DEV_IF */
3059
3060         WL_DBG(("Enter\n"));
3061         RETURN_EIO_IF_NOT_UP(cfg);
3062
3063         if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
3064                 if (wl_cfg_multip2p_operational(cfg)) {
3065                         WL_ERR(("wlan0 scan failed, p2p devices are operational"));
3066                          return -ENODEV;
3067                 }
3068         }
3069
3070         mutex_lock(&cfg->usr_sync);
3071         err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
3072         if (unlikely(err)) {
3073                 WL_ERR(("scan error (%d)\n", err));
3074         }
3075         mutex_unlock(&cfg->usr_sync);
3076
3077         return err;
3078 }
3079
3080 static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
3081 {
3082         s32 err = 0;
3083
3084         err = wldev_iovar_setint(dev, "rtsthresh", rts_threshold);
3085         if (unlikely(err)) {
3086                 WL_ERR(("Error (%d)\n", err));
3087                 return err;
3088         }
3089         return err;
3090 }
3091
3092 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
3093 {
3094         s32 err = 0;
3095
3096         err = wldev_iovar_setint_bsscfg(dev, "fragthresh", frag_threshold, 0);
3097         if (unlikely(err)) {
3098                 WL_ERR(("Error (%d)\n", err));
3099                 return err;
3100         }
3101         return err;
3102 }
3103
3104 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
3105 {
3106         s32 err = 0;
3107         u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
3108
3109         retry = htod32(retry);
3110         err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), true);
3111         if (unlikely(err)) {
3112                 WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
3113                 return err;
3114         }
3115         return err;
3116 }
3117
3118 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
3119 {
3120         struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy);
3121         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
3122         s32 err = 0;
3123
3124         RETURN_EIO_IF_NOT_UP(cfg);
3125         WL_DBG(("Enter\n"));
3126         if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
3127                 (cfg->conf->rts_threshold != wiphy->rts_threshold)) {
3128                 cfg->conf->rts_threshold = wiphy->rts_threshold;
3129                 err = wl_set_rts(ndev, cfg->conf->rts_threshold);
3130                 if (!err)
3131                         return err;
3132         }
3133         if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
3134                 (cfg->conf->frag_threshold != wiphy->frag_threshold)) {
3135                 cfg->conf->frag_threshold = wiphy->frag_threshold;
3136                 err = wl_set_frag(ndev, cfg->conf->frag_threshold);
3137                 if (!err)
3138                         return err;
3139         }
3140         if (changed & WIPHY_PARAM_RETRY_LONG &&
3141                 (cfg->conf->retry_long != wiphy->retry_long)) {
3142                 cfg->conf->retry_long = wiphy->retry_long;
3143                 err = wl_set_retry(ndev, cfg->conf->retry_long, true);
3144                 if (!err)
3145                         return err;
3146         }
3147         if (changed & WIPHY_PARAM_RETRY_SHORT &&
3148                 (cfg->conf->retry_short != wiphy->retry_short)) {
3149                 cfg->conf->retry_short = wiphy->retry_short;
3150                 err = wl_set_retry(ndev, cfg->conf->retry_short, false);
3151                 if (!err) {
3152                         return err;
3153                 }
3154         }
3155
3156         return err;
3157 }
3158 static chanspec_t
3159 channel_to_chanspec(struct wiphy *wiphy, struct net_device *dev, u32 channel, u32 bw_cap)
3160 {
3161         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3162         u8 *buf = NULL;
3163         wl_uint32_list_t *list;
3164         int err = BCME_OK;
3165         chanspec_t c = 0, ret_c = 0;
3166         int bw = 0, tmp_bw = 0;
3167         int i;
3168         u32 tmp_c;
3169         u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
3170 #define LOCAL_BUF_SIZE  1024
3171         buf = (u8 *) kzalloc(LOCAL_BUF_SIZE, kflags);
3172         if (!buf) {
3173                 WL_ERR(("buf memory alloc failed\n"));
3174                 goto exit;
3175         }
3176         list = (wl_uint32_list_t *)(void *)buf;
3177         list->count = htod32(WL_NUMCHANSPECS);
3178         err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
3179                 0, buf, LOCAL_BUF_SIZE, 0, &cfg->ioctl_buf_sync);
3180         if (err != BCME_OK) {
3181                 WL_ERR(("get chanspecs failed with %d\n", err));
3182                 goto exit;
3183         }
3184         for (i = 0; i < dtoh32(list->count); i++) {
3185                 c = dtoh32(list->element[i]);
3186                 if (channel <= CH_MAX_2G_CHANNEL) {
3187                         if (!CHSPEC_IS20(c))
3188                                 continue;
3189                         if (channel == CHSPEC_CHANNEL(c)) {
3190                                 ret_c = c;
3191                                 bw = 20;
3192                                 goto exit;
3193                         }
3194                 }
3195                 tmp_c = wf_chspec_ctlchan(c);
3196                 tmp_bw = bw2cap[CHSPEC_BW(c) >> WL_CHANSPEC_BW_SHIFT];
3197                 if (tmp_c != channel)
3198                         continue;
3199
3200                 if ((tmp_bw > bw) && (tmp_bw <= bw_cap)) {
3201                         bw = tmp_bw;
3202                         ret_c = c;
3203                         if (bw == bw_cap)
3204                                 goto exit;
3205                 }
3206         }
3207 exit:
3208         if (buf)
3209                 kfree(buf);
3210 #undef LOCAL_BUF_SIZE
3211         WL_INFORM(("return chanspec %x %d\n", ret_c, bw));
3212         return ret_c;
3213 }
3214
3215 void
3216 wl_cfg80211_ibss_vsie_set_buffer(vndr_ie_setbuf_t *ibss_vsie, int ibss_vsie_len)
3217 {
3218         struct bcm_cfg80211 *cfg = g_bcm_cfg;
3219
3220         if (cfg != NULL && ibss_vsie != NULL) {
3221                 if (cfg->ibss_vsie != NULL) {
3222                         kfree(cfg->ibss_vsie);
3223                 }
3224                 cfg->ibss_vsie = ibss_vsie;
3225                 cfg->ibss_vsie_len = ibss_vsie_len;
3226         }
3227 }
3228
3229 static void
3230 wl_cfg80211_ibss_vsie_free(struct bcm_cfg80211 *cfg)
3231 {
3232         /* free & initiralize VSIE (Vendor Specific IE) */
3233         if (cfg->ibss_vsie != NULL) {
3234                 kfree(cfg->ibss_vsie);
3235                 cfg->ibss_vsie = NULL;
3236                 cfg->ibss_vsie_len = 0;
3237         }
3238 }
3239
3240 s32
3241 wl_cfg80211_ibss_vsie_delete(struct net_device *dev)
3242 {
3243         struct bcm_cfg80211 *cfg = g_bcm_cfg;
3244         char *ioctl_buf = NULL;
3245         s32 ret = BCME_OK;
3246
3247         if (cfg != NULL && cfg->ibss_vsie != NULL) {
3248                 ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
3249                 if (!ioctl_buf) {
3250                         WL_ERR(("ioctl memory alloc failed\n"));
3251                         return -ENOMEM;
3252                 }
3253
3254                 /* change the command from "add" to "del" */
3255                 strncpy(cfg->ibss_vsie->cmd, "del", VNDR_IE_CMD_LEN - 1);
3256                 cfg->ibss_vsie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
3257
3258                 ret = wldev_iovar_setbuf(dev, "ie",
3259                         cfg->ibss_vsie, cfg->ibss_vsie_len,
3260                         ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
3261                 WL_ERR(("ret=%d\n", ret));
3262
3263                 if (ret == BCME_OK) {
3264                         /* free & initiralize VSIE */
3265                         kfree(cfg->ibss_vsie);
3266                         cfg->ibss_vsie = NULL;
3267                         cfg->ibss_vsie_len = 0;
3268                 }
3269
3270                 if (ioctl_buf) {
3271                         kfree(ioctl_buf);
3272                 }
3273         }
3274
3275         return ret;
3276 }
3277
3278 #ifdef WLAIBSS_MCHAN
3279 static bcm_struct_cfgdev*
3280 bcm_cfg80211_add_ibss_if(struct wiphy *wiphy, char *name)
3281 {
3282         int err = 0;
3283         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3284         struct wireless_dev* wdev = NULL;
3285         struct net_device *new_ndev = NULL;
3286         struct net_device *primary_ndev = NULL;
3287         s32 timeout;
3288         wl_aibss_if_t aibss_if;
3289         wl_if_event_info *event = NULL;
3290
3291         if (cfg->ibss_cfgdev != NULL) {
3292                 WL_ERR(("IBSS interface %s already exists\n", name));
3293                 return NULL;
3294         }
3295
3296         WL_ERR(("Try to create IBSS interface %s\n", name));
3297         primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3298         /* generate a new MAC address for the IBSS interface */
3299         get_primary_mac(cfg, &cfg->ibss_if_addr);
3300         cfg->ibss_if_addr.octet[4] ^= 0x40;
3301         memset(&aibss_if, sizeof(aibss_if), 0);
3302         memcpy(&aibss_if.addr, &cfg->ibss_if_addr, sizeof(aibss_if.addr));
3303         aibss_if.chspec = 0;
3304         aibss_if.len = sizeof(aibss_if);
3305
3306         cfg->bss_pending_op = TRUE;
3307         memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
3308         err = wldev_iovar_setbuf(primary_ndev, "aibss_ifadd", &aibss_if,
3309                 sizeof(aibss_if), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, NULL);
3310         if (err) {
3311                 WL_ERR(("IOVAR aibss_ifadd failed with error %d\n", err));
3312                 goto fail;
3313         }
3314         timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
3315                 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
3316         if (timeout <= 0 || cfg->bss_pending_op)
3317                 goto fail;
3318
3319         event = &cfg->if_event_info;
3320         /* By calling wl_cfg80211_allocate_if (dhd_allocate_if eventually) we give the control
3321          * over this net_device interface to dhd_linux, hence the interface is managed by dhd_liux
3322          * and will be freed by dhd_detach unless it gets unregistered before that. The
3323          * wireless_dev instance new_ndev->ieee80211_ptr associated with this net_device will
3324          * be freed by wl_dealloc_netinfo
3325          */
3326         new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx, event->name,
3327                 event->mac, event->bssidx, event->name);
3328         if (new_ndev == NULL)
3329                 goto fail;
3330         wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
3331         if (wdev == NULL)
3332                 goto fail;
3333         wdev->wiphy = wiphy;
3334         wdev->iftype = NL80211_IFTYPE_ADHOC;
3335         wdev->netdev = new_ndev;
3336         new_ndev->ieee80211_ptr = wdev;
3337         SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy));
3338
3339         /* rtnl lock must have been acquired, if this is not the case, wl_cfg80211_register_if
3340         * needs to be modified to take one parameter (bool need_rtnl_lock)
3341          */
3342         ASSERT_RTNL();
3343         if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev) != BCME_OK)
3344                 goto fail;
3345
3346         wl_alloc_netinfo(cfg, new_ndev, wdev, WL_MODE_IBSS, PM_ENABLE, event->bssidx);
3347         cfg->ibss_cfgdev = ndev_to_cfgdev(new_ndev);
3348         WL_ERR(("IBSS interface %s created\n", new_ndev->name));
3349         return cfg->ibss_cfgdev;
3350
3351 fail:
3352         WL_ERR(("failed to create IBSS interface %s \n", name));
3353         cfg->bss_pending_op = FALSE;
3354         if (new_ndev)
3355                 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev);
3356         if (wdev)
3357                 kfree(wdev);
3358         return NULL;
3359 }
3360
3361 static s32
3362 bcm_cfg80211_del_ibss_if(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
3363 {
3364         int err = 0;
3365         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3366         struct net_device *ndev = NULL;
3367         struct net_device *primary_ndev = NULL;
3368         s32 timeout;
3369
3370         if (!cfgdev || cfg->ibss_cfgdev != cfgdev || ETHER_ISNULLADDR(&cfg->ibss_if_addr.octet))
3371                 return -EINVAL;
3372         ndev = (struct net_device *)cfgdev_to_ndev(cfg->ibss_cfgdev);
3373         primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3374
3375         cfg->bss_pending_op = TRUE;
3376         memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
3377         err = wldev_iovar_setbuf(primary_ndev, "aibss_ifdel", &cfg->ibss_if_addr,
3378                 sizeof(cfg->ibss_if_addr), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, NULL);
3379         if (err) {
3380                 WL_ERR(("IOVAR aibss_ifdel failed with error %d\n", err));
3381                 goto fail;
3382         }
3383         timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
3384                 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
3385         if (timeout <= 0 || cfg->bss_pending_op) {
3386                 WL_ERR(("timeout in waiting IF_DEL event\n"));
3387                 goto fail;
3388         }
3389
3390         wl_cfg80211_remove_if(cfg, cfg->if_event_info.ifidx, ndev);
3391         cfg->ibss_cfgdev = NULL;
3392         return 0;
3393
3394 fail:
3395         cfg->bss_pending_op = FALSE;
3396         return -1;
3397 }
3398 #endif /* WLAIBSS_MCHAN */
3399
3400 s32
3401 wl_cfg80211_interface_ops(struct bcm_cfg80211 *cfg,
3402         struct net_device *ndev, s32 bsscfg_idx,
3403         enum nl80211_iftype iface_type, s32 del, u8 *addr)
3404 {
3405         wl_interface_create_t iface;
3406         s32 ret;
3407         wl_interface_info_t *info;
3408
3409         bzero(&iface, sizeof(wl_interface_create_t));
3410
3411         iface.ver = WL_INTERFACE_CREATE_VER;
3412
3413         if (iface_type == NL80211_IFTYPE_AP)
3414                 iface.flags = WL_INTERFACE_CREATE_AP;
3415         else
3416                 iface.flags = WL_INTERFACE_CREATE_STA;
3417
3418         if (del) {
3419                 ret = wldev_iovar_setbuf(ndev, "interface_remove",
3420                         NULL, 0, cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
3421         } else {
3422                 if (addr) {
3423                         memcpy(&iface.mac_addr.octet, addr, ETH_ALEN);
3424                         iface.flags |= WL_INTERFACE_MAC_USE;
3425                 }
3426                 ret = wldev_iovar_getbuf(ndev, "interface_create",
3427                         &iface, sizeof(wl_interface_create_t),
3428                         cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
3429                 if (ret == 0) {
3430                         /* success */
3431                         info = (wl_interface_info_t *)cfg->ioctl_buf;
3432                         WL_DBG(("wl interface create success!! bssidx:%d \n",
3433                                 info->bsscfgidx));
3434                         ret = info->bsscfgidx;
3435                 }
3436         }
3437
3438         if (ret < 0)
3439                 WL_ERR(("Interface %s failed!! ret %d\n",
3440                         del ? "remove" : "create", ret));
3441
3442         return ret;
3443 }
3444
3445
3446 s32
3447 wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg,
3448         struct net_device *ndev, s32 bsscfg_idx,
3449         enum nl80211_iftype iface_type, s32 del, u8 *addr)
3450 {
3451         s32 ret = BCME_OK;
3452         s32 val = 0;
3453
3454         struct {
3455                 s32 cfg;
3456                 s32 val;
3457                 struct ether_addr ea;
3458         } bss_setbuf;
3459
3460         WL_INFORM(("iface_type:%d del:%d \n", iface_type, del));
3461
3462         bzero(&bss_setbuf, sizeof(bss_setbuf));
3463
3464         /* AP=3, STA=2, up=1, down=0, val=-1 */
3465         if (del) {
3466                 val = -1;
3467         } else if (iface_type == NL80211_IFTYPE_AP) {
3468                 /* AP Interface */
3469                 WL_DBG(("Adding AP Interface \n"));
3470                 val = 3;
3471         } else if (iface_type == NL80211_IFTYPE_STATION) {
3472                 WL_DBG(("Adding STA Interface \n"));
3473                 val = 2;
3474         } else {
3475                 WL_ERR((" add_del_bss NOT supported for IFACE type:0x%x", iface_type));
3476                 return -EINVAL;
3477         }
3478
3479         bss_setbuf.cfg = htod32(bsscfg_idx);
3480         bss_setbuf.val = htod32(val);
3481
3482         if (addr) {
3483                 memcpy(&bss_setbuf.ea.octet, addr, ETH_ALEN);
3484         }
3485
3486         ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
3487                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
3488         if (ret != 0)
3489                 WL_ERR(("'bss %d' failed with %d\n", val, ret));
3490
3491         return ret;
3492 }
3493
3494 #if defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF)
3495 /* Create a Generic Network Interface and initialize it depending up on
3496  * the interface type
3497  */
3498 bcm_struct_cfgdev*
3499 wl_cfg80211_create_iface(struct wiphy *wiphy,
3500         enum nl80211_iftype iface_type,
3501         u8 *mac_addr, const char *name)
3502 {
3503         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3504         struct net_device *new_ndev = NULL;
3505         struct net_device *primary_ndev = NULL;
3506         s32 ret = BCME_OK;
3507         s32 bsscfg_idx = 0;
3508         u32 timeout;
3509         wl_if_event_info *event = NULL;
3510         struct wireless_dev *wdev = NULL;
3511         u8 addr[ETH_ALEN];
3512
3513         WL_DBG(("Enter\n"));
3514
3515         if (!name) {
3516                 WL_ERR(("Interface name not provided\n"));
3517                 return NULL;
3518         }
3519
3520         primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3521
3522 #ifdef DHD_IFDEBUG
3523         WL_ERR(("cfg=%p, primary_ndev=%p, ifname=%s\n", cfg, primary_ndev, name));
3524 #endif
3525
3526         /* If any scan is going on, abort it */
3527         if (wl_get_drv_status_all(cfg, SCANNING)) {
3528                 int wait_cnt = MAX_SCAN_ABORT_WAIT_CNT;
3529                 WL_ERR(("Scan in progress. Aborting the scan!\n"));
3530                 wl_cfg80211_scan_abort(cfg);
3531                 while (wl_get_drv_status_all(cfg, SCANNING) && wait_cnt) {
3532                         WL_DBG(("Waiting for SCANNING terminated, wait_cnt: %d\n", wait_cnt));
3533                         wait_cnt--;
3534                         OSL_SLEEP(WAIT_SCAN_ABORT_OSL_SLEEP_TIME);
3535                 }
3536                 if (!wait_cnt && wl_get_drv_status_all(cfg, SCANNING)) {
3537                         WL_ERR(("Failed to abort scan\n"));
3538                         return NULL;
3539                 }
3540         }
3541
3542         primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3543         if (likely(!mac_addr)) {
3544                 /* Use primary MAC with the locally administered bit for the
3545                  *  Secondary STA I/F
3546                  */
3547                 memcpy(addr, primary_ndev->dev_addr, ETH_ALEN);
3548                 addr[0] |= 0x02;
3549         } else {
3550                 /* Use the application provided mac address (if any) */
3551                 memcpy(addr, mac_addr, ETH_ALEN);
3552         }
3553
3554         if ((iface_type != NL80211_IFTYPE_STATION) && (iface_type != NL80211_IFTYPE_AP)) {
3555                 WL_ERR(("IFACE type:%d not supported. STA "
3556                                         "or AP IFACE is only supported\n", iface_type));
3557                 return NULL;
3558         }
3559
3560         cfg->bss_pending_op = TRUE;
3561         memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
3562
3563         /* De-initialize the p2p discovery interface, if operational */
3564         if (p2p_is_on(cfg)) {
3565                 WL_DBG(("Disabling P2P Discovery Interface \n"));
3566 #ifdef WL_CFG80211_P2P_DEV_IF
3567                 ret = wl_cfg80211_scan_stop(bcmcfg_to_p2p_wdev(cfg));
3568 #else
3569                 ret = wl_cfg80211_scan_stop(cfg->p2p_net);
3570 #endif
3571                 if (unlikely(ret < 0)) {
3572                         CFGP2P_ERR(("P2P scan stop failed, ret=%d\n", ret));
3573                 }
3574
3575 #ifdef DHD_IFDEBUG
3576                 WL_ERR(("call wl_cfgp2p_disable_discovery()\n"));
3577 #endif
3578                 wl_cfgp2p_disable_discovery(cfg);
3579                 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0;
3580                 p2p_on(cfg) = false;
3581         }
3582
3583         /*
3584          * Intialize the firmware I/F.
3585          */
3586         ret = wl_cfg80211_interface_ops(cfg, primary_ndev, bsscfg_idx,
3587                 NL80211_IFTYPE_STATION, 0, addr);
3588         if (ret == BCME_UNSUPPORTED) {
3589                 /* Use bssidx 1 by default */
3590                 bsscfg_idx = 1;
3591                 if ((ret = wl_cfg80211_add_del_bss(cfg, primary_ndev,
3592                         bsscfg_idx, iface_type, 0, addr)) < 0) {
3593                         return NULL;
3594                 }
3595         } else if (ret < 0) {
3596                 WL_ERR(("Interface create failed!! ret:%d \n", ret));
3597                 goto fail;
3598         } else {
3599                 /* Success */
3600                 bsscfg_idx = ret;
3601         }
3602
3603         WL_DBG(("Interface created!! bssidx:%d \n", bsscfg_idx));
3604
3605         /*
3606          * Wait till the firmware send a confirmation event back.
3607          */
3608         WL_DBG(("Wait for the FW I/F Event\n"));
3609         timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
3610                 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
3611         if (timeout <= 0 || cfg->bss_pending_op) {
3612                 WL_ERR(("ADD_IF event, didn't come. Return \n"));
3613                 goto fail;
3614         }
3615
3616         /*
3617          * Since FW operation is successful,we can go ahead with the
3618          * the host interface creation.
3619          */
3620         event = &cfg->if_event_info;
3621         new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx,
3622                 (char*)name, addr, event->bssidx, event->name);
3623         if (!new_ndev) {
3624                 WL_ERR(("I/F allocation failed! \n"));
3625                 goto fail;
3626         } else
3627                 WL_DBG(("I/F allocation succeeded! ifidx:0x%x bssidx:0x%x \n",
3628                  event->ifidx, event->bssidx));
3629
3630         wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
3631         if (!wdev) {
3632                 WL_ERR(("wireless_dev alloc failed! \n"));
3633                 goto fail;
3634         }
3635
3636         wdev->wiphy = wiphy;
3637         wdev->iftype = iface_type;
3638         new_ndev->ieee80211_ptr = wdev;
3639         SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy));
3640
3641 #ifdef DHD_IFDEBUG
3642         WL_ERR(("wdev=%p, new_ndev=%p\n", wdev, new_ndev));
3643 #endif
3644
3645         /* RTNL lock must have been acquired. */
3646         ASSERT_RTNL();
3647
3648         /* Set the locally administed mac addr, if not applied already */
3649         if (memcmp(addr, event->mac, ETH_ALEN) != 0) {
3650                 ret = wldev_iovar_setbuf_bsscfg(primary_ndev, "cur_etheraddr",
3651                         addr, ETH_ALEN, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
3652                         event->bssidx, &cfg->ioctl_buf_sync);
3653                 if (unlikely(ret)) {
3654                                 WL_ERR(("set cur_etheraddr Error (%d)\n", ret));
3655                                 goto fail;
3656                 }
3657                 memcpy(new_ndev->dev_addr, addr, ETH_ALEN);
3658         }
3659
3660         if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev) != BCME_OK) {
3661                 WL_ERR(("IFACE register failed \n"));
3662                 goto fail;
3663         }
3664
3665         /* Initialize with the station mode params */
3666         wl_alloc_netinfo(cfg, new_ndev, wdev,
3667                 (iface_type == NL80211_IFTYPE_STATION) ?
3668                 WL_MODE_BSS : WL_MODE_AP, PM_ENABLE, event->bssidx);
3669         cfg->bss_cfgdev = ndev_to_cfgdev(new_ndev);
3670         cfg->cfgdev_bssidx = event->bssidx;
3671
3672         WL_DBG(("Host Network Interface for Secondary I/F created"));
3673
3674 #ifdef DHD_IFDEBUG
3675         WL_ERR(("cfg->bss_cfgdev=%p\n", cfg->bss_cfgdev));
3676 #endif
3677
3678         return cfg->bss_cfgdev;
3679
3680 fail:
3681         cfg->bss_pending_op = FALSE;
3682         cfg->cfgdev_bssidx = -1;
3683         if (wdev)
3684                 kfree(wdev);
3685         if (new_ndev)
3686                 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev);
3687
3688 #ifdef DHD_IFDEBUG
3689         WL_ERR(("failed!!!\n"));
3690 #endif
3691
3692         return NULL;
3693 }
3694
3695 s32
3696 wl_cfg80211_del_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
3697 {
3698         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3699         struct net_device *ndev = NULL;
3700         struct net_device *primary_ndev = NULL;
3701         s32 ret = BCME_OK;
3702         s32 bsscfg_idx = 1;
3703         u32 timeout;
3704         u32 ifidx;
3705         enum nl80211_iftype iface_type = NL80211_IFTYPE_STATION;
3706
3707         WL_ERR(("Enter\n"));
3708
3709         if (!cfg->bss_cfgdev)
3710                 return 0;
3711
3712         /* If any scan is going on, abort it */
3713         if (wl_get_drv_status_all(cfg, SCANNING)) {
3714                 WL_ERR(("Scan in progress. Aborting the scan!\n"));
3715                 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
3716         }
3717
3718         ndev = (struct net_device *)cfgdev_to_ndev(cfg->bss_cfgdev);
3719         primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3720
3721 #ifdef DHD_IFDEBUG
3722         WL_ERR(("cfg->bss_cfgdev=%p, ndev=%p, primary_ndev=%p\n",
3723                 cfg->bss_cfgdev, ndev, primary_ndev));
3724 #endif
3725
3726         cfg->bss_pending_op = TRUE;
3727         memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
3728
3729         /* Delete the firmware interface. "interface_remove" command
3730          * should go on the interface to be deleted
3731          */
3732         ret = wl_cfg80211_interface_ops(cfg, ndev, cfg->cfgdev_bssidx,
3733                 NL80211_IFTYPE_STATION, 1, NULL);
3734         if (ret == BCME_UNSUPPORTED) {
3735                 if ((ret = wl_cfg80211_add_del_bss(cfg, ndev,
3736                         bsscfg_idx, iface_type, true, NULL)) < 0) {
3737                         WL_ERR(("DEL bss failed ret:%d \n", ret));
3738                         goto exit;
3739                 }
3740         } else if (ret < 0) {
3741                 WL_ERR(("Interface DEL failed ret:%d \n", ret));
3742                 goto exit;
3743         }
3744
3745         timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
3746                 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
3747         if (timeout <= 0 || cfg->bss_pending_op) {
3748                 WL_ERR(("timeout in waiting IF_DEL event\n"));
3749         }
3750
3751 exit:
3752         ifidx = dhd_net2idx(((struct dhd_pub *)(cfg->pub))->info, ndev);
3753         wl_cfg80211_remove_if(cfg, ifidx, ndev);
3754         cfg->bss_cfgdev = NULL;
3755         cfg->cfgdev_bssidx = -1;
3756         cfg->bss_pending_op = FALSE;
3757
3758         WL_ERR(("IF_DEL Done.\n"));
3759
3760         return ret;
3761 }
3762 #endif /* defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF) */
3763
3764 static s32
3765 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
3766         struct cfg80211_ibss_params *params)
3767 {
3768         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3769         struct cfg80211_bss *bss;
3770         struct ieee80211_channel *chan;
3771         struct wl_join_params join_params;
3772         int scan_suppress;
3773         struct cfg80211_ssid ssid;
3774         s32 scan_retry = 0;
3775         s32 err = 0;
3776         size_t join_params_size;
3777         chanspec_t chanspec = 0;
3778         u32 param[2] = {0, 0};
3779         u32 bw_cap = 0;
3780
3781         WL_TRACE(("In\n"));
3782         RETURN_EIO_IF_NOT_UP(cfg);
3783         WL_INFORM(("JOIN BSSID:" MACDBG "\n", MAC2STRDBG(params->bssid)));
3784         if (!params->ssid || params->ssid_len <= 0) {
3785                 WL_ERR(("Invalid parameter\n"));
3786                 return -EINVAL;
3787         }
3788 #if defined(WL_CFG80211_P2P_DEV_IF)
3789         chan = params->chandef.chan;
3790 #else
3791         chan = params->channel;
3792 #endif /* WL_CFG80211_P2P_DEV_IF */
3793         if (chan)
3794                 cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
3795         if (wl_get_drv_status(cfg, CONNECTED, dev)) {
3796                 struct wlc_ssid *lssid = (struct wlc_ssid *)wl_read_prof(cfg, dev, WL_PROF_SSID);
3797                 u8 *bssid = (u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID);
3798                 u32 *channel = (u32 *)wl_read_prof(cfg, dev, WL_PROF_CHAN);
3799                 if (!params->bssid || ((memcmp(params->bssid, bssid, ETHER_ADDR_LEN) == 0) &&
3800                         (memcmp(params->ssid, lssid->SSID, lssid->SSID_len) == 0) &&
3801                         (*channel == cfg->channel))) {
3802                         WL_ERR(("Connection already existed to " MACDBG "\n",
3803                                 MAC2STRDBG((u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID))));
3804                         return -EISCONN;
3805                 }
3806                 WL_ERR(("Ignore Previous connecton to %s (" MACDBG ")\n",
3807                         lssid->SSID, MAC2STRDBG(bssid)));
3808         }
3809
3810         /* remove the VSIE */
3811         wl_cfg80211_ibss_vsie_delete(dev);
3812
3813         bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
3814         if (!bss) {
3815                 if (IBSS_INITIAL_SCAN_ALLOWED == TRUE) {
3816                         memcpy(ssid.ssid, params->ssid, params->ssid_len);
3817                         ssid.ssid_len = params->ssid_len;
3818                         do {
3819                                 if (unlikely
3820                                         (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
3821                                          -EBUSY)) {
3822                                         wl_delay(150);
3823                                 } else {
3824                                         break;
3825                                 }
3826                         } while (++scan_retry < WL_SCAN_RETRY_MAX);
3827
3828                         /* rtnl lock code is removed here. don't see why rtnl lock
3829                          * needs to be released.
3830                          */
3831
3832                         /* wait 4 secons till scan done.... */
3833                         schedule_timeout_interruptible(msecs_to_jiffies(4000));
3834
3835                         bss = cfg80211_get_ibss(wiphy, NULL,
3836                                 params->ssid, params->ssid_len);
3837                 }
3838         }
3839         if (bss && ((IBSS_COALESCE_ALLOWED == TRUE) ||
3840                 ((IBSS_COALESCE_ALLOWED == FALSE) && params->bssid &&
3841                 !memcmp(bss->bssid, params->bssid, ETHER_ADDR_LEN)))) {
3842                 cfg->ibss_starter = false;
3843                 WL_DBG(("Found IBSS\n"));
3844         } else {
3845                 cfg->ibss_starter = true;
3846         }
3847         if (chan) {
3848                 if (chan->band == IEEE80211_BAND_5GHZ)
3849                         param[0] = WLC_BAND_5G;
3850                 else if (chan->band == IEEE80211_BAND_2GHZ)
3851                         param[0] = WLC_BAND_2G;
3852                 err = wldev_iovar_getint(dev, "bw_cap", param);
3853                 if (unlikely(err)) {
3854                         WL_ERR(("Get bw_cap Failed (%d)\n", err));
3855                         return err;
3856                 }
3857                 bw_cap = param[0];
3858                 chanspec = channel_to_chanspec(wiphy, dev, cfg->channel, bw_cap);
3859         }
3860         /*
3861          * Join with specific BSSID and cached SSID
3862          * If SSID is zero join based on BSSID only
3863          */
3864         memset(&join_params, 0, sizeof(join_params));
3865         memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
3866                 params->ssid_len);
3867         join_params.ssid.SSID_len = htod32(params->ssid_len);
3868         if (params->bssid) {
3869                 memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
3870                 err = wldev_ioctl(dev, WLC_SET_DESIRED_BSSID, &join_params.params.bssid,
3871                         ETHER_ADDR_LEN, true);
3872                 if (unlikely(err)) {
3873                         WL_ERR(("Error (%d)\n", err));
3874                         return err;
3875                 }
3876         } else
3877                 memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
3878         wldev_iovar_setint(dev, "ibss_coalesce_allowed", IBSS_COALESCE_ALLOWED);
3879
3880         if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
3881                 scan_suppress = TRUE;
3882                 /* Set the SCAN SUPPRESS Flag in the firmware to skip join scan */
3883                 err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS,
3884                         &scan_suppress, sizeof(int), true);
3885                 if (unlikely(err)) {
3886                         WL_ERR(("Scan Suppress Setting Failed (%d)\n", err));
3887                         return err;
3888                 }
3889         }
3890
3891         join_params.params.chanspec_list[0] = chanspec;
3892         join_params.params.chanspec_num = 1;
3893         wldev_iovar_setint(dev, "chanspec", chanspec);
3894         join_params_size = sizeof(join_params);
3895
3896         /* Disable Authentication, IBSS will add key if it required */
3897         wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
3898         wldev_iovar_setint(dev, "wsec", 0);
3899
3900
3901         err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
3902                 join_params_size, true);
3903         if (unlikely(err)) {
3904                 WL_ERR(("Error (%d)\n", err));
3905                 return err;
3906         }
3907
3908         if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
3909                 scan_suppress = FALSE;
3910                 /* Reset the SCAN SUPPRESS Flag */
3911                 err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS,
3912                         &scan_suppress, sizeof(int), true);
3913                 if (unlikely(err)) {
3914                         WL_ERR(("Reset Scan Suppress Flag Failed (%d)\n", err));
3915                         return err;
3916                 }
3917         }
3918         wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
3919         wl_update_prof(cfg, dev, NULL, &cfg->channel, WL_PROF_CHAN);
3920         cfg->rmc_event_seq = 0; /* initialize rmcfail sequence */
3921         return err;
3922 }
3923
3924 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
3925 {
3926         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3927         s32 err = 0;
3928         scb_val_t scbval;
3929         u8 *curbssid;
3930
3931         RETURN_EIO_IF_NOT_UP(cfg);
3932         wl_link_down(cfg);
3933
3934         WL_ERR(("Leave IBSS\n"));
3935         curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
3936         wl_set_drv_status(cfg, DISCONNECTING, dev);
3937         scbval.val = 0;
3938         memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
3939         err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
3940                 sizeof(scb_val_t), true);
3941         if (unlikely(err)) {
3942                 wl_clr_drv_status(cfg, DISCONNECTING, dev);
3943                 WL_ERR(("error(%d)\n", err));
3944                 return err;
3945         }
3946
3947         /* remove the VSIE */
3948         wl_cfg80211_ibss_vsie_delete(dev);
3949
3950         return err;
3951 }
3952
3953
3954 static s32
3955 wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
3956 {
3957         struct bcm_cfg80211 *cfg = g_bcm_cfg;
3958         struct wl_security *sec;
3959         s32 val = 0;
3960         s32 err = 0;
3961         s32 bssidx;
3962
3963         if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
3964                 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
3965                 return BCME_ERROR;
3966         }
3967
3968         if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
3969                 val = WPA_AUTH_PSK |
3970                         WPA_AUTH_UNSPECIFIED;
3971         else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
3972                 val = WPA2_AUTH_PSK|
3973                         WPA2_AUTH_UNSPECIFIED;
3974         else
3975                 val = WPA_AUTH_DISABLED;
3976
3977         if (is_wps_conn(sme))
3978                 val = WPA_AUTH_DISABLED;
3979
3980         WL_DBG(("setting wpa_auth to 0x%0x\n", val));
3981         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
3982         if (unlikely(err)) {
3983                 WL_ERR(("set wpa_auth failed (%d)\n", err));
3984                 return err;
3985         }
3986         sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
3987         sec->wpa_versions = sme->crypto.wpa_versions;
3988         return err;
3989 }
3990
3991
3992 static s32
3993 wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
3994 {
3995         struct bcm_cfg80211 *cfg = g_bcm_cfg;
3996         struct wl_security *sec;
3997         s32 val = 0;
3998         s32 err = 0;
3999         s32 bssidx;
4000
4001         if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4002                 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4003                 return BCME_ERROR;
4004         }
4005
4006         switch (sme->auth_type) {
4007         case NL80211_AUTHTYPE_OPEN_SYSTEM:
4008                 val = WL_AUTH_OPEN_SYSTEM;
4009                 WL_DBG(("open system\n"));
4010                 break;
4011         case NL80211_AUTHTYPE_SHARED_KEY:
4012                 val = WL_AUTH_SHARED_KEY;
4013                 WL_DBG(("shared key\n"));
4014                 break;
4015         case NL80211_AUTHTYPE_AUTOMATIC:
4016                 val = WL_AUTH_OPEN_SHARED;
4017                 WL_DBG(("automatic\n"));
4018                 break;
4019         default:
4020                 val = 2;
4021                 WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
4022                 break;
4023         }
4024
4025         err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
4026         if (unlikely(err)) {
4027                 WL_ERR(("set auth failed (%d)\n", err));
4028                 return err;
4029         }
4030         sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4031         sec->auth_type = sme->auth_type;
4032         return err;
4033 }
4034
4035 static s32
4036 wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
4037 {
4038         struct bcm_cfg80211 *cfg = g_bcm_cfg;
4039         struct wl_security *sec;
4040         s32 pval = 0;
4041         s32 gval = 0;
4042         s32 err = 0;
4043         s32 wsec_val = 0;
4044
4045         s32 bssidx;
4046
4047         if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4048                 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4049                 return BCME_ERROR;
4050         }
4051
4052         if (sme->crypto.n_ciphers_pairwise) {
4053                 switch (sme->crypto.ciphers_pairwise[0]) {
4054                 case WLAN_CIPHER_SUITE_WEP40:
4055                 case WLAN_CIPHER_SUITE_WEP104:
4056                         pval = WEP_ENABLED;
4057                         break;
4058                 case WLAN_CIPHER_SUITE_TKIP:
4059                         pval = TKIP_ENABLED;
4060                         break;
4061                 case WLAN_CIPHER_SUITE_CCMP:
4062                 case WLAN_CIPHER_SUITE_AES_CMAC:
4063                         pval = AES_ENABLED;
4064                         break;
4065                 default:
4066                         WL_ERR(("invalid cipher pairwise (%d)\n",
4067                                 sme->crypto.ciphers_pairwise[0]));
4068                         return -EINVAL;
4069                 }
4070         }
4071         if (sme->crypto.cipher_group) {
4072                 switch (sme->crypto.cipher_group) {
4073                 case WLAN_CIPHER_SUITE_WEP40:
4074                 case WLAN_CIPHER_SUITE_WEP104:
4075                         gval = WEP_ENABLED;
4076                         break;
4077                 case WLAN_CIPHER_SUITE_TKIP:
4078                         gval = TKIP_ENABLED;
4079                         break;
4080                 case WLAN_CIPHER_SUITE_CCMP:
4081                         gval = AES_ENABLED;
4082                         break;
4083                 case WLAN_CIPHER_SUITE_AES_CMAC:
4084                         gval = AES_ENABLED;
4085                         break;
4086                 default:
4087                         WL_ERR(("invalid cipher group (%d)\n",
4088                                 sme->crypto.cipher_group));
4089                         return -EINVAL;
4090                 }
4091         }
4092
4093         WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
4094
4095         if (is_wps_conn(sme)) {
4096                 if (sme->privacy)
4097                         err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
4098                 else
4099                         /* WPS-2.0 allows no security */
4100                         err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
4101         } else {
4102                         WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC"));
4103                         wsec_val = pval | gval;
4104
4105                         WL_DBG((" Set WSEC to fW 0x%x \n", wsec_val));
4106                         err = wldev_iovar_setint_bsscfg(dev, "wsec",
4107                                 wsec_val, bssidx);
4108         }
4109         if (unlikely(err)) {
4110                 WL_ERR(("error (%d)\n", err));
4111                 return err;
4112         }
4113
4114         sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4115         sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
4116         sec->cipher_group = sme->crypto.cipher_group;
4117
4118         return err;
4119 }
4120
4121 static s32
4122 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
4123 {
4124         struct bcm_cfg80211 *cfg = g_bcm_cfg;
4125         struct wl_security *sec;
4126         s32 val = 0;
4127         s32 err = 0;
4128         s32 bssidx;
4129
4130         if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4131                 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4132                 return BCME_ERROR;
4133         }
4134
4135         if (sme->crypto.n_akm_suites) {
4136                 err = wldev_iovar_getint(dev, "wpa_auth", &val);
4137                 if (unlikely(err)) {
4138                         WL_ERR(("could not get wpa_auth (%d)\n", err));
4139                         return err;
4140                 }
4141                 if (val & (WPA_AUTH_PSK |
4142                         WPA_AUTH_UNSPECIFIED)) {
4143                         switch (sme->crypto.akm_suites[0]) {
4144                         case WLAN_AKM_SUITE_8021X:
4145                                 val = WPA_AUTH_UNSPECIFIED;
4146                                 break;
4147                         case WLAN_AKM_SUITE_PSK:
4148                                 val = WPA_AUTH_PSK;
4149                                 break;
4150                         default:
4151                                 WL_ERR(("invalid akm suite (0x%x)\n",
4152                                         sme->crypto.akm_suites[0]));
4153                                 return -EINVAL;
4154                         }
4155                 } else if (val & (WPA2_AUTH_PSK |
4156                         WPA2_AUTH_UNSPECIFIED)) {
4157                         switch (sme->crypto.akm_suites[0]) {
4158                         case WLAN_AKM_SUITE_8021X:
4159                                 val = WPA2_AUTH_UNSPECIFIED;
4160                                 break;
4161                         case WLAN_AKM_SUITE_PSK:
4162                                 val = WPA2_AUTH_PSK;
4163                                 break;
4164                         default:
4165                                 WL_ERR(("invalid akm suite (0x%x)\n",
4166                                         sme->crypto.akm_suites[0]));
4167                                 return -EINVAL;
4168                         }
4169                 }
4170
4171
4172                 WL_DBG(("setting wpa_auth to 0x%x\n", val));
4173
4174                 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
4175                 if (unlikely(err)) {
4176                         WL_ERR(("could not set wpa_auth (%d)\n", err));
4177                         return err;
4178                 }
4179         }
4180         sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4181         sec->wpa_auth = sme->crypto.akm_suites[0];
4182
4183         return err;
4184 }
4185
4186 static s32
4187 wl_set_set_sharedkey(struct net_device *dev,
4188         struct cfg80211_connect_params *sme)
4189 {
4190         struct bcm_cfg80211 *cfg = g_bcm_cfg;
4191         struct wl_security *sec;
4192         struct wl_wsec_key key;
4193         s32 val;
4194         s32 err = 0;
4195         s32 bssidx;
4196
4197         if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4198                 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4199                 return BCME_ERROR;
4200         }
4201
4202         WL_DBG(("key len (%d)\n", sme->key_len));
4203         if (sme->key_len) {
4204                 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4205                 WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
4206                         sec->wpa_versions, sec->cipher_pairwise));
4207                 if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 |
4208                         NL80211_WPA_VERSION_2)) &&
4209                         (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
4210                 WLAN_CIPHER_SUITE_WEP104)))
4211                 {
4212                         memset(&key, 0, sizeof(key));
4213                         key.len = (u32) sme->key_len;
4214                         key.index = (u32) sme->key_idx;
4215                         if (unlikely(key.len > sizeof(key.data))) {
4216                                 WL_ERR(("Too long key length (%u)\n", key.len));
4217                                 return -EINVAL;
4218                         }
4219                         memcpy(key.data, sme->key, key.len);
4220                         key.flags = WL_PRIMARY_KEY;
4221                         switch (sec->cipher_pairwise) {
4222                         case WLAN_CIPHER_SUITE_WEP40:
4223                                 key.algo = CRYPTO_ALGO_WEP1;
4224                                 break;
4225                         case WLAN_CIPHER_SUITE_WEP104:
4226                                 key.algo = CRYPTO_ALGO_WEP128;
4227                                 break;
4228                         default:
4229                                 WL_ERR(("Invalid algorithm (%d)\n",
4230                                         sme->crypto.ciphers_pairwise[0]));
4231                                 return -EINVAL;
4232                         }
4233                         /* Set the new key/index */
4234                         WL_DBG(("key length (%d) key index (%d) algo (%d)\n",
4235                                 key.len, key.index, key.algo));
4236                         WL_DBG(("key \"%s\"\n", key.data));
4237                         swap_key_from_BE(&key);
4238                         err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
4239                                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4240                         if (unlikely(err)) {
4241                                 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
4242                                 return err;
4243                         }
4244                         if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
4245                                 WL_DBG(("set auth_type to shared key\n"));
4246                                 val = WL_AUTH_SHARED_KEY;       /* shared key */
4247                                 err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
4248                                 if (unlikely(err)) {
4249                                         WL_ERR(("set auth failed (%d)\n", err));
4250                                         return err;
4251                                 }
4252                         }
4253                 }
4254         }
4255         return err;
4256 }
4257
4258 #if defined(ESCAN_RESULT_PATCH)
4259 static u8 connect_req_bssid[6];
4260 static u8 broad_bssid[6];
4261 #endif /* ESCAN_RESULT_PATCH */
4262
4263
4264
4265 #if defined(CUSTOM_SET_CPUCORE) || defined(CONFIG_TCPACK_FASTTX)
4266 static bool wl_get_chan_isvht80(struct net_device *net, dhd_pub_t *dhd)
4267 {
4268         u32 chanspec = 0;
4269         bool isvht80 = 0;
4270
4271         if (wldev_iovar_getint(net, "chanspec", (s32 *)&chanspec) == BCME_OK)
4272                 chanspec = wl_chspec_driver_to_host(chanspec);
4273
4274         isvht80 = chanspec & WL_CHANSPEC_BW_80;
4275         WL_INFO(("%s: chanspec(%x:%d)\n", __FUNCTION__, chanspec, isvht80));
4276
4277         return isvht80;
4278 }
4279 #endif /* CUSTOM_SET_CPUCORE || CONFIG_TCPACK_FASTTX */
4280
4281 static s32
4282 wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
4283         struct cfg80211_connect_params *sme)
4284 {
4285         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4286         struct ieee80211_channel *chan = sme->channel;
4287         wl_extjoin_params_t *ext_join_params;
4288         struct wl_join_params join_params;
4289         size_t join_params_size;
4290         s32 err = 0;
4291         wpa_ie_fixed_t *wpa_ie;
4292         bcm_tlv_t *wpa2_ie;
4293         u8* wpaie  = 0;
4294         u32 wpaie_len = 0;
4295         u32 chan_cnt = 0;
4296         struct ether_addr bssid;
4297         s32 bssidx = -1;
4298         int ret;
4299         int wait_cnt;
4300
4301         WL_DBG(("In\n"));
4302
4303 #if defined(SUPPORT_RANDOM_MAC_SCAN)
4304         wl_cfg80211_set_random_mac(dev, FALSE);
4305 #endif /* SUPPORT_RANDOM_MAC_SCAN */
4306
4307 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
4308         if (sme->channel_hint) {
4309                 chan = sme->channel_hint;
4310                 WL_DBG(("channel_hint (%d), channel_hint center_freq (%d)\n",
4311                         ieee80211_frequency_to_channel(sme->channel_hint->center_freq),
4312                         sme->channel_hint->center_freq));
4313         }
4314         if (sme->bssid_hint) {
4315                 sme->bssid = sme->bssid_hint;
4316                 WL_DBG(("bssid_hint "MACDBG" \n", MAC2STRDBG(sme->bssid_hint)));
4317         }
4318 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
4319
4320         if (unlikely(!sme->ssid)) {
4321                 WL_ERR(("Invalid ssid\n"));
4322                 return -EOPNOTSUPP;
4323         }
4324
4325         if (unlikely(sme->ssid_len > DOT11_MAX_SSID_LEN)) {
4326                 WL_ERR(("Invalid SSID info: SSID=%s, length=%zd\n",
4327                         sme->ssid, sme->ssid_len));
4328                 return -EINVAL;
4329         }
4330
4331         RETURN_EIO_IF_NOT_UP(cfg);
4332
4333         /*
4334          * Cancel ongoing scan to sync up with sme state machine of cfg80211.
4335          */
4336 #if (defined(BCM4359_CHIP) || !defined(ESCAN_RESULT_PATCH))
4337         if (cfg->scan_request) {
4338                 WL_TRACE_HW4(("Aborting the scan! \n"));
4339                 wl_cfg80211_scan_abort(cfg);
4340                 wait_cnt = MAX_SCAN_ABORT_WAIT_CNT;
4341                 while (wl_get_drv_status(cfg, SCANNING, dev) && wait_cnt) {
4342                         WL_DBG(("Waiting for SCANNING terminated, wait_cnt: %d\n", wait_cnt));
4343                         wait_cnt--;
4344                         OSL_SLEEP(WAIT_SCAN_ABORT_OSL_SLEEP_TIME);
4345                 }
4346                 if (wl_get_drv_status(cfg, SCANNING, dev)) {
4347                         wl_notify_escan_complete(cfg, dev, true, true);
4348                 }
4349         }
4350 #endif
4351 #ifdef WL_SCHED_SCAN
4352         if (cfg->sched_scan_req) {
4353                 wl_cfg80211_sched_scan_stop(wiphy, bcmcfg_to_prmry_ndev(cfg));
4354         }
4355 #endif
4356 #if defined(ESCAN_RESULT_PATCH)
4357         if (sme->bssid)
4358                 memcpy(connect_req_bssid, sme->bssid, ETHER_ADDR_LEN);
4359         else
4360                 bzero(connect_req_bssid, ETHER_ADDR_LEN);
4361         bzero(broad_bssid, ETHER_ADDR_LEN);
4362 #endif
4363 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
4364         maxrxpktglom = 0;
4365 #endif
4366         bzero(&bssid, sizeof(bssid));
4367         if (!wl_get_drv_status(cfg, CONNECTED, dev)&&
4368                 (ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false)) == 0) {
4369                 if (!ETHER_ISNULLADDR(&bssid)) {
4370                         scb_val_t scbval;
4371                         wl_set_drv_status(cfg, DISCONNECTING, dev);
4372                         scbval.val = DOT11_RC_DISASSOC_LEAVING;
4373                         memcpy(&scbval.ea, &bssid, ETHER_ADDR_LEN);
4374                         scbval.val = htod32(scbval.val);
4375
4376                         WL_DBG(("drv status CONNECTED is not set, but connected in FW!" MACDBG "/n",
4377                                 MAC2STRDBG(bssid.octet)));
4378                         err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
4379                                 sizeof(scb_val_t), true);
4380                         if (unlikely(err)) {
4381                                 wl_clr_drv_status(cfg, DISCONNECTING, dev);
4382                                 WL_ERR(("error (%d)\n", err));
4383                                 return err;
4384                         }
4385                         wait_cnt = 500/10;
4386                         while (wl_get_drv_status(cfg, DISCONNECTING, dev) && wait_cnt) {
4387                                 WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n",
4388                                         wait_cnt));
4389                                 wait_cnt--;
4390                                 OSL_SLEEP(10);
4391                         }
4392                 } else
4393                         WL_DBG(("Currently not associated!\n"));
4394         } else {
4395                 /* if status is DISCONNECTING, wait for disconnection terminated max 500 ms */
4396                 wait_cnt = 200/10;
4397                 while (wl_get_drv_status(cfg, DISCONNECTING, dev) && wait_cnt) {
4398                         WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n", wait_cnt));
4399                         wait_cnt--;
4400                         OSL_SLEEP(10);
4401                 }
4402                 if (wl_get_drv_status(cfg, DISCONNECTING, dev)) {
4403                         WL_ERR(("Force clear DISCONNECTING status!\n"));
4404                         wl_clr_drv_status(cfg, DISCONNECTING, dev);
4405                 }
4406         }
4407
4408         /* Clean BSSID */
4409         bzero(&bssid, sizeof(bssid));
4410         if (!wl_get_drv_status(cfg, DISCONNECTING, dev))
4411                 wl_update_prof(cfg, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
4412
4413         if (p2p_is_on(cfg) && (dev != bcmcfg_to_prmry_ndev(cfg))) {
4414                 /* we only allow to connect using virtual interface in case of P2P */
4415                         if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4416                                 WL_ERR(("Find p2p index from wdev(%p) failed\n",
4417                                         dev->ieee80211_ptr));
4418                                 return BCME_ERROR;
4419                         }
4420                         wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
4421                                 VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
4422         } else if (dev == bcmcfg_to_prmry_ndev(cfg)) {
4423                 /* find the RSN_IE */
4424                 if ((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
4425                         DOT11_MNG_RSN_ID)) != NULL) {
4426                         WL_DBG((" WPA2 IE is found\n"));
4427                 }
4428                 /* find the WPA_IE */
4429                 if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)sme->ie,
4430                         sme->ie_len)) != NULL) {
4431                         WL_DBG((" WPA IE is found\n"));
4432                 }
4433                 if (wpa_ie != NULL || wpa2_ie != NULL) {
4434                         wpaie = (wpa_ie != NULL) ? (u8 *)wpa_ie : (u8 *)wpa2_ie;
4435                         wpaie_len = (wpa_ie != NULL) ? wpa_ie->length : wpa2_ie->len;
4436                         wpaie_len += WPA_RSN_IE_TAG_FIXED_LEN;
4437                         err = wldev_iovar_setbuf(dev, "wpaie", wpaie, wpaie_len,
4438                                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
4439                         if (unlikely(err)) {
4440                                 WL_ERR(("wpaie set error (%d)\n", err));
4441                                 return err;
4442                         }
4443                 } else {
4444                         err = wldev_iovar_setbuf(dev, "wpaie", NULL, 0,
4445                                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
4446                         if (unlikely(err)) {
4447                                 WL_ERR(("wpaie set error (%d)\n", err));
4448                                 return err;
4449                         }
4450                 }
4451
4452                 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4453                         WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4454                         return BCME_ERROR;
4455                 }
4456                 err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
4457                         VNDR_IE_ASSOCREQ_FLAG, (const u8 *)sme->ie, sme->ie_len);
4458                 if (unlikely(err)) {
4459                         return err;
4460                 }
4461         }
4462         if (chan) {
4463                 /* If RCC is not enabled, use the channel provided by userspace */
4464                 cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
4465                 chan_cnt = 1;
4466                 WL_DBG(("channel (%d), center_req (%d), %d channels\n", cfg->channel,
4467                         chan->center_freq, chan_cnt));
4468         } else {
4469                 /*
4470                  * No channel information from user space. if RCC is enabled, the RCC
4471                  * would prepare the channel list, else no channel would be provided
4472                  * and firmware would need to do a full channel scan.
4473                  */
4474                 WL_DBG(("No channel info from user space\n"));
4475                 cfg->channel = 0;
4476         }
4477         WL_DBG(("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len));
4478         WL_DBG(("3. set wpa version \n"));
4479         err = wl_set_wpa_version(dev, sme);
4480         if (unlikely(err)) {
4481                 WL_ERR(("Invalid wpa_version\n"));
4482                 return err;
4483         }
4484                 err = wl_set_auth_type(dev, sme);
4485                 if (unlikely(err)) {
4486                         WL_ERR(("Invalid auth type\n"));
4487                         return err;
4488                 }
4489
4490         err = wl_set_set_cipher(dev, sme);
4491         if (unlikely(err)) {
4492                 WL_ERR(("Invalid ciper\n"));
4493                 return err;
4494         }
4495
4496         err = wl_set_key_mgmt(dev, sme);
4497         if (unlikely(err)) {
4498                 WL_ERR(("Invalid key mgmt\n"));
4499                 return err;
4500         }
4501
4502         err = wl_set_set_sharedkey(dev, sme);
4503         if (unlikely(err)) {
4504                 WL_ERR(("Invalid shared key\n"));
4505                 return err;
4506         }
4507
4508         /*
4509          *  Join with specific BSSID and cached SSID
4510          *  If SSID is zero join based on BSSID only
4511          */
4512         join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE +
4513                 chan_cnt * sizeof(chanspec_t);
4514         ext_join_params =  (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL);
4515         if (ext_join_params == NULL) {
4516                 err = -ENOMEM;
4517                 wl_clr_drv_status(cfg, CONNECTING, dev);
4518                 goto exit;
4519         }
4520         ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len);
4521         memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len);
4522         wl_update_prof(cfg, dev, NULL, &ext_join_params->ssid, WL_PROF_SSID);
4523         ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
4524         /* increate dwell time to receive probe response or detect Beacon
4525         * from target AP at a noisy air only during connect command
4526         */
4527         ext_join_params->scan.active_time = chan_cnt ? WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS : -1;
4528         ext_join_params->scan.passive_time = chan_cnt ? WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS : -1;
4529         /* Set up join scan parameters */
4530         ext_join_params->scan.scan_type = -1;
4531         ext_join_params->scan.nprobes = chan_cnt ?
4532                 (ext_join_params->scan.active_time/WL_SCAN_JOIN_PROBE_INTERVAL_MS) : -1;
4533         ext_join_params->scan.home_time = -1;
4534
4535         if (sme->bssid)
4536                 memcpy(&ext_join_params->assoc.bssid, sme->bssid, ETH_ALEN);
4537         else
4538                 memcpy(&ext_join_params->assoc.bssid, &ether_bcast, ETH_ALEN);
4539         ext_join_params->assoc.chanspec_num = chan_cnt;
4540         if (chan_cnt) {
4541                 if (cfg->channel) {
4542                         /*
4543                          * Use the channel provided by userspace
4544                          */
4545                         u16 channel, band, bw, ctl_sb;
4546                         chanspec_t chspec;
4547                         channel = cfg->channel;
4548                         band = (channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G
4549                                 : WL_CHANSPEC_BAND_5G;
4550
4551                         /* Get min_bw set for the interface */
4552                         bw = wl_cfg80211_ulb_get_min_bw_chspec(dev->ieee80211_ptr, bssidx);
4553                         if (bw == INVCHANSPEC) {
4554                                 WL_ERR(("Invalid chanspec \n"));
4555                                 kfree(ext_join_params);
4556                                 return BCME_ERROR;
4557                         }
4558
4559                         ctl_sb = WL_CHANSPEC_CTL_SB_NONE;
4560                         chspec = (channel | band | bw | ctl_sb);
4561                         ext_join_params->assoc.chanspec_list[0]  &= WL_CHANSPEC_CHAN_MASK;
4562                         ext_join_params->assoc.chanspec_list[0] |= chspec;
4563                         ext_join_params->assoc.chanspec_list[0] =
4564                                 wl_chspec_host_to_driver(ext_join_params->assoc.chanspec_list[0]);
4565                 }
4566         }
4567         ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num);
4568         if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
4569                 WL_INFORM(("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID,
4570                         ext_join_params->ssid.SSID_len));
4571         }
4572         wl_set_drv_status(cfg, CONNECTING, dev);
4573
4574         if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4575                 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4576                 kfree(ext_join_params);
4577                 return BCME_ERROR;
4578         }
4579         err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size,
4580                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4581
4582         if (cfg->rcc_enabled) {
4583                 printf("Connecting with " MACDBG " ssid \"%s\", len (%d) with rcc channels \n\n",
4584                         MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)),
4585                         ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len);
4586         } else {
4587                 printf("Connecting with " MACDBG " ssid \"%s\", len (%d) channel=%d\n\n",
4588                         MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)),
4589                         ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len, cfg->channel);
4590         }
4591
4592         kfree(ext_join_params);
4593         if (err) {
4594                 wl_clr_drv_status(cfg, CONNECTING, dev);
4595                 if (err == BCME_UNSUPPORTED) {
4596                         WL_DBG(("join iovar is not supported\n"));
4597                         goto set_ssid;
4598                 } else {
4599                         WL_ERR(("error (%d)\n", err));
4600                         goto exit;
4601                 }
4602         } else
4603                 goto exit;
4604
4605 set_ssid:
4606         memset(&join_params, 0, sizeof(join_params));
4607         join_params_size = sizeof(join_params.ssid);
4608
4609         join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
4610         memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
4611         join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
4612         wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
4613         if (sme->bssid)
4614                 memcpy(&join_params.params.bssid, sme->bssid, ETH_ALEN);
4615         else
4616                 memcpy(&join_params.params.bssid, &ether_bcast, ETH_ALEN);
4617
4618         if (wl_ch_to_chanspec(dev, cfg->channel, &join_params, &join_params_size) < 0) {
4619                 WL_ERR(("Invalid chanspec\n"));
4620                 return -EINVAL;
4621         }
4622
4623         WL_DBG(("join_param_size %zu\n", join_params_size));
4624
4625         if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
4626                 WL_INFORM(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
4627                         join_params.ssid.SSID_len));
4628         }
4629         wl_set_drv_status(cfg, CONNECTING, dev);
4630         err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true);
4631         if (err) {
4632                 WL_ERR(("error (%d)\n", err));
4633                 wl_clr_drv_status(cfg, CONNECTING, dev);
4634         }
4635 exit:
4636         return err;
4637 }
4638
4639 static s32
4640 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
4641         u16 reason_code)
4642 {
4643         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4644         scb_val_t scbval;
4645         bool act = false;
4646         s32 err = 0;
4647         u8 *curbssid;
4648 #ifdef CUSTOM_SET_CPUCORE
4649         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
4650 #endif /* CUSTOM_SET_CPUCORE */
4651         WL_ERR(("Reason %d\n", reason_code));
4652         RETURN_EIO_IF_NOT_UP(cfg);
4653         act = *(bool *) wl_read_prof(cfg, dev, WL_PROF_ACT);
4654         curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
4655 #ifdef ESCAN_RESULT_PATCH
4656         if (wl_get_drv_status(cfg, CONNECTING, dev) && curbssid &&
4657                 (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0)) {
4658                 WL_ERR(("Disconnecting from connecting device: " MACDBG "\n",
4659                         MAC2STRDBG(curbssid)));
4660                 act = true;
4661         }
4662 #endif /* ESCAN_RESULT_PATCH */
4663
4664         if (act) {
4665                 /*
4666                 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
4667                 */
4668 #if !defined(ESCAN_RESULT_PATCH)
4669                 /* Let scan aborted by F/W */
4670                 if (cfg->scan_request) {
4671                         WL_TRACE_HW4(("Aborting the scan! \n"));
4672                         wl_notify_escan_complete(cfg, dev, true, true);
4673                 }
4674 #endif /* ESCAN_RESULT_PATCH */
4675                 if (wl_get_drv_status(cfg, CONNECTING, dev) ||
4676                         wl_get_drv_status(cfg, CONNECTED, dev)) {
4677                                 wl_set_drv_status(cfg, DISCONNECTING, dev);
4678                                 scbval.val = reason_code;
4679                                 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
4680                                 scbval.val = htod32(scbval.val);
4681                                 err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
4682                                                 sizeof(scb_val_t), true);
4683                                 if (unlikely(err)) {
4684                                         wl_clr_drv_status(cfg, DISCONNECTING, dev);
4685                                         WL_ERR(("error (%d)\n", err));
4686                                         return err;
4687                                 }
4688 #if defined(BCM4358_CHIP)
4689                                 WL_ERR(("Wait for complete of disconnecting \n"));
4690                                 OSL_SLEEP(200);
4691 #endif /* BCM4358_CHIP */
4692                 }
4693         }
4694 #ifdef CUSTOM_SET_CPUCORE
4695         /* set default cpucore */
4696         if (dev == bcmcfg_to_prmry_ndev(cfg)) {
4697                 dhd->chan_isvht80 &= ~DHD_FLAG_STA_MODE;
4698                 if (!(dhd->chan_isvht80))
4699                         dhd_set_cpucore(dhd, FALSE);
4700         }
4701 #endif /* CUSTOM_SET_CPUCORE */
4702
4703         return err;
4704 }
4705
4706 static s32
4707 #if defined(WL_CFG80211_P2P_DEV_IF)
4708 wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
4709         enum nl80211_tx_power_setting type, s32 mbm)
4710 #else
4711 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
4712         enum nl80211_tx_power_setting type, s32 dbm)
4713 #endif /* WL_CFG80211_P2P_DEV_IF */
4714 {
4715
4716         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4717         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
4718         s32 err = 0;
4719 #if defined(WL_CFG80211_P2P_DEV_IF)
4720         s32 dbm = MBM_TO_DBM(mbm);
4721 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || \
4722         defined(WL_COMPAT_WIRELESS) || defined(WL_SUPPORT_BACKPORTED_KPATCHES)
4723         dbm = MBM_TO_DBM(dbm);
4724 #endif /* WL_CFG80211_P2P_DEV_IF */
4725
4726         RETURN_EIO_IF_NOT_UP(cfg);
4727         switch (type) {
4728         case NL80211_TX_POWER_AUTOMATIC:
4729                 break;
4730         case NL80211_TX_POWER_LIMITED:
4731                 if (dbm < 0) {
4732                         WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
4733                         return -EINVAL;
4734                 }
4735                 break;
4736         case NL80211_TX_POWER_FIXED:
4737                 if (dbm < 0) {
4738                         WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
4739                         return -EINVAL;
4740                 }
4741                 break;
4742         }
4743
4744         err = wl_set_tx_power(ndev, type, dbm);
4745         if (unlikely(err)) {
4746                 WL_ERR(("error (%d)\n", err));
4747                 return err;
4748         }
4749
4750         cfg->conf->tx_power = dbm;
4751
4752         return err;
4753 }
4754
4755 static s32
4756 #if defined(WL_CFG80211_P2P_DEV_IF)
4757 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
4758         struct wireless_dev *wdev, s32 *dbm)
4759 #else
4760 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
4761 #endif /* WL_CFG80211_P2P_DEV_IF */
4762 {
4763         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4764         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
4765         s32 err = 0;
4766
4767         RETURN_EIO_IF_NOT_UP(cfg);
4768         err = wl_get_tx_power(ndev, dbm);
4769         if (unlikely(err))
4770                 WL_ERR(("error (%d)\n", err));
4771
4772         return err;
4773 }
4774
4775 static s32
4776 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
4777         u8 key_idx, bool unicast, bool multicast)
4778 {
4779         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4780         u32 index;
4781         s32 wsec;
4782         s32 err = 0;
4783         s32 bssidx;
4784
4785         if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4786                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev->ieee80211_ptr));
4787                 return BCME_ERROR;
4788         }
4789
4790         WL_DBG(("key index (%d)\n", key_idx));
4791         RETURN_EIO_IF_NOT_UP(cfg);
4792         err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
4793         if (unlikely(err)) {
4794                 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
4795                 return err;
4796         }
4797         if (wsec == WEP_ENABLED) {
4798                 /* Just select a new current key */
4799                 index = (u32) key_idx;
4800                 index = htod32(index);
4801                 err = wldev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
4802                         sizeof(index), true);
4803                 if (unlikely(err)) {
4804                         WL_ERR(("error (%d)\n", err));
4805                 }
4806         }
4807         return err;
4808 }
4809
4810 static s32
4811 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
4812         u8 key_idx, const u8 *mac_addr, struct key_params *params)
4813 {
4814         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4815         struct wl_wsec_key key;
4816         s32 err = 0;
4817         s32 bssidx;
4818         s32 mode = wl_get_mode_by_netdev(cfg, dev);
4819
4820         if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4821                 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4822                 return BCME_ERROR;
4823         }
4824         memset(&key, 0, sizeof(key));
4825         key.index = (u32) key_idx;
4826
4827         if (!ETHER_ISMULTI(mac_addr))
4828                 memcpy((char *)&key.ea, (const void *)mac_addr, ETHER_ADDR_LEN);
4829         key.len = (u32) params->key_len;
4830
4831         /* check for key index change */
4832         if (key.len == 0) {
4833                 /* key delete */
4834                 swap_key_from_BE(&key);
4835                 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
4836                         cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4837                 if (unlikely(err)) {
4838                         WL_ERR(("key delete error (%d)\n", err));
4839                         return err;
4840                 }
4841         } else {
4842                 if (key.len > sizeof(key.data)) {
4843                         WL_ERR(("Invalid key length (%d)\n", key.len));
4844                         return -EINVAL;
4845                 }
4846                 WL_DBG(("Setting the key index %d\n", key.index));
4847                 memcpy(key.data, params->key, key.len);
4848
4849                 if ((mode == WL_MODE_BSS) &&
4850                         (params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
4851                         u8 keybuf[8];
4852                         memcpy(keybuf, &key.data[24], sizeof(keybuf));
4853                         memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
4854                         memcpy(&key.data[16], keybuf, sizeof(keybuf));
4855                 }
4856
4857                 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
4858                 if (params->seq && params->seq_len == 6) {
4859                         /* rx iv */
4860                         u8 *ivptr;
4861                         ivptr = (u8 *) params->seq;
4862                         key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
4863                                 (ivptr[3] << 8) | ivptr[2];
4864                         key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
4865                         key.iv_initialized = true;
4866                 }
4867
4868                 switch (params->cipher) {
4869                 case WLAN_CIPHER_SUITE_WEP40:
4870                         key.algo = CRYPTO_ALGO_WEP1;
4871                         WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
4872                         break;
4873                 case WLAN_CIPHER_SUITE_WEP104:
4874                         key.algo = CRYPTO_ALGO_WEP128;
4875                         WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
4876                         break;
4877                 case WLAN_CIPHER_SUITE_TKIP:
4878                         key.algo = CRYPTO_ALGO_TKIP;
4879                         WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
4880                         break;
4881                 case WLAN_CIPHER_SUITE_AES_CMAC:
4882                         key.algo = CRYPTO_ALGO_AES_CCM;
4883                         WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
4884                         break;
4885                 case WLAN_CIPHER_SUITE_CCMP:
4886                         key.algo = CRYPTO_ALGO_AES_CCM;
4887                         WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
4888                         break;
4889                 default:
4890                         WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
4891                         return -EINVAL;
4892                 }
4893                 swap_key_from_BE(&key);
4894                 /* need to guarantee EAPOL 4/4 send out before set key */
4895                 dhd_wait_pend8021x(dev);
4896                 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
4897                         cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4898                 if (unlikely(err)) {
4899                         WL_ERR(("WLC_SET_KEY error (%d)\n", err));
4900                         return err;
4901                 }
4902         }
4903         return err;
4904 }
4905
4906 int
4907 wl_cfg80211_enable_roam_offload(struct net_device *dev, int enable)
4908 {
4909         int err;
4910         wl_eventmsg_buf_t ev_buf;
4911
4912         if (dev != bcmcfg_to_prmry_ndev(g_bcm_cfg)) {
4913                 /* roam offload is only for the primary device */
4914                 return -1;
4915         }
4916         err = wldev_iovar_setint(dev, "roam_offload", enable);
4917         if (err)
4918                 return err;
4919
4920         if (enable) {
4921                 err = wldev_iovar_setint(dev, "sup_wpa_tmo", IDSUP_4WAY_HANDSHAKE_TIMEOUT);
4922                 if (err) {
4923                         WL_INFORM(("Setting 'sup_wpa_tmo' failed, err=%d\n", err));
4924                 }
4925         }
4926
4927         bzero(&ev_buf, sizeof(wl_eventmsg_buf_t));
4928         wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_REQ_IE, !enable);
4929         wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_RESP_IE, !enable);
4930         wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_REASSOC, !enable);
4931         wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_JOIN, !enable);
4932         wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ROAM, !enable);
4933         err = wl_cfg80211_apply_eventbuffer(dev, g_bcm_cfg, &ev_buf);
4934         if (!err) {
4935                 g_bcm_cfg->roam_offload = enable;
4936         }
4937         return err;
4938 }
4939
4940 #if defined(WL_VIRTUAL_APSTA)
4941 int
4942 wl_cfg80211_interface_create(struct net_device *dev, char *name)
4943 {
4944         struct bcm_cfg80211 *cfg = g_bcm_cfg;
4945         bcm_struct_cfgdev *new_cfgdev;
4946
4947         new_cfgdev = wl_cfg80211_create_iface(cfg->wdev->wiphy,
4948                         NL80211_IFTYPE_STATION, NULL, name);
4949         if (!new_cfgdev) {
4950                 return BCME_ERROR;
4951         }
4952         else {
4953                 WL_DBG(("Iface %s created successfuly\n", name));
4954                 return BCME_OK;
4955         }
4956 }
4957
4958 int
4959 wl_cfg80211_interface_delete(struct net_device *dev, char *name)
4960 {
4961         struct bcm_cfg80211 *cfg = g_bcm_cfg;
4962         struct net_info *iter, *next;
4963         int err = BCME_ERROR;
4964
4965         if (name == NULL) {
4966                 return BCME_ERROR;
4967         }
4968
4969         for_each_ndev(cfg, iter, next) {
4970                 if (iter->ndev) {
4971                         if (strcmp(iter->ndev->name, name) == 0) {
4972                                 err =  wl_cfg80211_del_iface(cfg->wdev->wiphy, cfg->bss_cfgdev);
4973                                 break;
4974                         }
4975                 }
4976         }
4977         if (!err) {
4978                 WL_DBG(("Iface %s deleted successfuly", name));
4979         }
4980         return err;
4981 }
4982 #endif /* defined (WL_VIRTUAL_APSTA) */
4983
4984 static s32
4985 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
4986         u8 key_idx, bool pairwise, const u8 *mac_addr,
4987         struct key_params *params)
4988 {
4989         struct wl_wsec_key key;
4990         s32 val = 0;
4991         s32 wsec = 0;
4992         s32 err = 0;
4993         u8 keybuf[8];
4994         s32 bssidx = 0;
4995         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4996         s32 mode = wl_get_mode_by_netdev(cfg, dev);
4997         WL_DBG(("key index (%d)\n", key_idx));
4998         RETURN_EIO_IF_NOT_UP(cfg);
4999
5000         if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5001                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev->ieee80211_ptr));
5002                 return BCME_ERROR;
5003         }
5004
5005         if (mac_addr &&
5006                 ((params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
5007                 (params->cipher != WLAN_CIPHER_SUITE_WEP104))) {
5008                         wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
5009                         goto exit;
5010         }
5011         memset(&key, 0, sizeof(key));
5012         /* Clear any buffered wep key */
5013         memset(&cfg->wep_key, 0, sizeof(struct wl_wsec_key));
5014
5015         key.len = (u32) params->key_len;
5016         key.index = (u32) key_idx;
5017
5018         if (unlikely(key.len > sizeof(key.data))) {
5019                 WL_ERR(("Too long key length (%u)\n", key.len));
5020                 return -EINVAL;
5021         }
5022         memcpy(key.data, params->key, key.len);
5023
5024         key.flags = WL_PRIMARY_KEY;
5025         switch (params->cipher) {
5026         case WLAN_CIPHER_SUITE_WEP40:
5027                 key.algo = CRYPTO_ALGO_WEP1;
5028                 val = WEP_ENABLED;
5029                 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
5030                 break;
5031         case WLAN_CIPHER_SUITE_WEP104:
5032                 key.algo = CRYPTO_ALGO_WEP128;
5033                 val = WEP_ENABLED;
5034                 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
5035                 break;
5036         case WLAN_CIPHER_SUITE_TKIP:
5037                 key.algo = CRYPTO_ALGO_TKIP;
5038                 val = TKIP_ENABLED;
5039                 /* wpa_supplicant switches the third and fourth quarters of the TKIP key */
5040                 if (mode == WL_MODE_BSS) {
5041                         bcopy(&key.data[24], keybuf, sizeof(keybuf));
5042                         bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
5043                         bcopy(keybuf, &key.data[16], sizeof(keybuf));
5044                 }
5045                 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
5046                 break;
5047         case WLAN_CIPHER_SUITE_AES_CMAC:
5048                 key.algo = CRYPTO_ALGO_AES_CCM;
5049                 val = AES_ENABLED;
5050                 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
5051                 break;
5052         case WLAN_CIPHER_SUITE_CCMP:
5053                 key.algo = CRYPTO_ALGO_AES_CCM;
5054                 val = AES_ENABLED;
5055                 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
5056                 break;
5057         default:
5058                 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
5059                 return -EINVAL;
5060         }
5061
5062         /* Set the new key/index */
5063         if ((mode == WL_MODE_IBSS) && (val & (TKIP_ENABLED | AES_ENABLED))) {
5064                 WL_ERR(("IBSS KEY setted\n"));
5065                 wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_NONE);
5066         }
5067         swap_key_from_BE(&key);
5068         if ((params->cipher == WLAN_CIPHER_SUITE_WEP40) ||
5069                 (params->cipher == WLAN_CIPHER_SUITE_WEP104)) {
5070                 /*
5071                  * For AP role, since we are doing a wl down before bringing up AP,
5072                  * the plumbed keys will be lost. So for AP once we bring up AP, we
5073                  * need to plumb keys again. So buffer the keys for future use. This
5074                  * is more like a WAR. If firmware later has the capability to do
5075                  * interface upgrade without doing a "wl down" and "wl apsta 0", then
5076                  * this will not be required.
5077                  */
5078                 WL_DBG(("Buffering WEP Keys \n"));
5079                 memcpy(&cfg->wep_key, &key, sizeof(struct wl_wsec_key));
5080         }
5081         err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), cfg->ioctl_buf,
5082                 WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
5083         if (unlikely(err)) {
5084                 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
5085                 return err;
5086         }
5087
5088 exit:
5089         err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
5090         if (unlikely(err)) {
5091                 WL_ERR(("get wsec error (%d)\n", err));
5092                 return err;
5093         }
5094
5095         wsec |= val;
5096         err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
5097         if (unlikely(err)) {
5098                 WL_ERR(("set wsec error (%d)\n", err));
5099                 return err;
5100         }
5101
5102         return err;
5103 }
5104
5105 static s32
5106 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
5107         u8 key_idx, bool pairwise, const u8 *mac_addr)
5108 {
5109         struct wl_wsec_key key;
5110         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5111         s32 err = 0;
5112         s32 bssidx;
5113
5114         WL_DBG(("Enter. key_idx: %d\n", key_idx));
5115         if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5116                 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
5117                 return BCME_ERROR;
5118         }
5119
5120         if ((key_idx >= DOT11_MAX_DEFAULT_KEYS) && (key_idx < DOT11_MAX_DEFAULT_KEYS+2))
5121                 return -EINVAL;
5122
5123         RETURN_EIO_IF_NOT_UP(cfg);
5124         memset(&key, 0, sizeof(key));
5125
5126         key.flags = WL_PRIMARY_KEY;
5127         key.algo = CRYPTO_ALGO_OFF;
5128         key.index = (u32) key_idx;
5129
5130         /* Set the new key/index */
5131         swap_key_from_BE(&key);
5132         err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), cfg->ioctl_buf,
5133                 WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
5134         if (unlikely(err)) {
5135                 if (err == -EINVAL) {
5136                         if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
5137                                 /* we ignore this key index in this case */
5138                                 WL_DBG(("invalid key index (%d)\n", key_idx));
5139                         }
5140                 } else {
5141                         WL_ERR(("WLC_SET_KEY error (%d)\n", err));
5142                 }
5143                 return err;
5144         }
5145         return err;
5146 }
5147
5148 static s32
5149 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
5150         u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
5151         void (*callback) (void *cookie, struct key_params * params))
5152 {
5153         struct key_params params;
5154         struct wl_wsec_key key;
5155         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5156         struct wl_security *sec;
5157         s32 wsec;
5158         s32 err = 0;
5159         s32 bssidx;
5160
5161         if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5162                 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
5163                 return BCME_ERROR;
5164         }
5165         WL_DBG(("key index (%d)\n", key_idx));
5166         RETURN_EIO_IF_NOT_UP(cfg);
5167         memset(&key, 0, sizeof(key));
5168         key.index = key_idx;
5169         swap_key_to_BE(&key);
5170         memset(&params, 0, sizeof(params));
5171         params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
5172         memcpy((void *)params.key, key.data, params.key_len);
5173
5174         err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
5175         if (unlikely(err)) {
5176                 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
5177                 return err;
5178         }
5179         switch (WSEC_ENABLED(wsec)) {
5180                 case WEP_ENABLED:
5181                         sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
5182                         if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
5183                                 params.cipher = WLAN_CIPHER_SUITE_WEP40;
5184                                 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
5185                         } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
5186                                 params.cipher = WLAN_CIPHER_SUITE_WEP104;
5187                                 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
5188                         }
5189                         break;
5190                 case TKIP_ENABLED:
5191                         params.cipher = WLAN_CIPHER_SUITE_TKIP;
5192                         WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
5193                         break;
5194                 case AES_ENABLED:
5195                         params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
5196                         WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
5197                         break;
5198                 default:
5199                         WL_ERR(("Invalid algo (0x%x)\n", wsec));
5200                         return -EINVAL;
5201         }
5202
5203         callback(cookie, &params);
5204         return err;
5205 }
5206
5207 static s32
5208 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
5209         struct net_device *dev, u8 key_idx)
5210 {
5211         WL_INFORM(("Not supported\n"));
5212         return -EOPNOTSUPP;
5213 }
5214
5215 #if defined(RSSIAVG)
5216 static wl_rssi_cache_ctrl_t g_rssi_cache_ctrl;
5217 static wl_rssi_cache_ctrl_t g_connected_rssi_cache_ctrl;
5218 #endif
5219 #if defined(BSSCACHE)
5220 static wl_bss_cache_ctrl_t g_bss_cache_ctrl;
5221 #endif
5222
5223 static s32
5224 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
5225 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5226         const u8 *mac, struct station_info *sinfo)
5227 #else
5228 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5229         u8 *mac, struct station_info *sinfo)
5230 #endif
5231 {
5232         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5233         scb_val_t scb_val;
5234         s32 rssi;
5235         s32 rate;
5236         s32 err = 0;
5237         sta_info_t *sta;
5238 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
5239         s8 eabuf[ETHER_ADDR_STR_LEN];
5240 #endif
5241         dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
5242         bool fw_assoc_state = FALSE;
5243         u32 dhd_assoc_state = 0;
5244         static int err_cnt = 0;
5245
5246         RETURN_EIO_IF_NOT_UP(cfg);
5247         if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
5248                 err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac,
5249                         ETHER_ADDR_LEN, cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
5250                 if (err < 0) {
5251                         WL_ERR(("GET STA INFO failed, %d\n", err));
5252                         return err;
5253                 }
5254                 sinfo->filled = STA_INFO_BIT(INFO_INACTIVE_TIME);
5255                 sta = (sta_info_t *)cfg->ioctl_buf;
5256                 sta->len = dtoh16(sta->len);
5257                 sta->cap = dtoh16(sta->cap);
5258                 sta->flags = dtoh32(sta->flags);
5259                 sta->idle = dtoh32(sta->idle);
5260                 sta->in = dtoh32(sta->in);
5261                 sinfo->inactive_time = sta->idle * 1000;
5262 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
5263                 if (sta->flags & WL_STA_ASSOC) {
5264                         sinfo->filled |= STA_INFO_BIT(INFO_CONNECTED_TIME);
5265                         sinfo->connected_time = sta->in;
5266                 }
5267                 WL_INFORM(("STA %s : idle time : %d sec, connected time :%d ms\n",
5268                         bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), sinfo->inactive_time,
5269                         sta->idle * 1000));
5270 #endif
5271         } else if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_BSS ||
5272                 wl_get_mode_by_netdev(cfg, dev) == WL_MODE_IBSS) {
5273                 get_pktcnt_t pktcnt;
5274                 u8 *curmacp;
5275
5276                 if (cfg->roam_offload) {
5277                         struct ether_addr bssid;
5278                         err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
5279                         if (err) {
5280                                 WL_ERR(("Failed to get current BSSID\n"));
5281                         } else {
5282                                 if (!ETHER_ISNULLADDR(&bssid.octet) &&
5283                                                 memcmp(mac, &bssid.octet, ETHER_ADDR_LEN) != 0) {
5284                                         /* roaming is detected */
5285                                         err = wl_cfg80211_delayed_roam(cfg, dev, &bssid);
5286                                         if (err)
5287                                                 WL_ERR(("Failed to handle the delayed roam, "
5288                                                         "err=%d", err));
5289                                         mac = (u8 *)bssid.octet;
5290                                 }
5291                         }
5292                 }
5293                 dhd_assoc_state = wl_get_drv_status(cfg, CONNECTED, dev);
5294                 fw_assoc_state = dhd_is_associated(dhd, 0, &err);
5295                 if (!dhd_assoc_state || !fw_assoc_state) {
5296                         WL_ERR(("NOT assoc\n"));
5297                         if (err == -ERESTARTSYS)
5298                                 return err;
5299                         if (!dhd_assoc_state) {
5300                                 WL_TRACE_HW4(("drv state is not connected \n"));
5301                         }
5302                         if (!fw_assoc_state) {
5303                                 WL_TRACE_HW4(("fw state is not associated \n"));
5304                         }
5305                         /* Disconnect due to fw is not associated for FW_ASSOC_WATCHDOG_TIME ms.
5306                         * 'err == 0' of dhd_is_associated() and '!fw_assoc_state'
5307                         * means that BSSID is null.
5308                         */
5309                         if (dhd_assoc_state && !fw_assoc_state && !err) {
5310                                 if (!fw_assoc_watchdog_started) {
5311                                         fw_assoc_watchdog_ms = OSL_SYSUPTIME();
5312                                         fw_assoc_watchdog_started = TRUE;
5313                                         WL_TRACE_HW4(("fw_assoc_watchdog_started \n"));
5314                                 } else {
5315                                         if (OSL_SYSUPTIME() - fw_assoc_watchdog_ms >
5316                                                 FW_ASSOC_WATCHDOG_TIME) {
5317                                                 fw_assoc_watchdog_started = FALSE;
5318                                                 err = -ENODEV;
5319                                                 WL_TRACE_HW4(("fw is not associated for %d ms \n",
5320                                                         (OSL_SYSUPTIME() - fw_assoc_watchdog_ms)));
5321                                                 goto get_station_err;
5322                                         }
5323                                 }
5324                         }
5325                         err = -ENODEV;
5326                         return err;
5327                 }
5328                 fw_assoc_watchdog_started = FALSE;
5329                 curmacp = wl_read_prof(cfg, dev, WL_PROF_BSSID);
5330                 if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
5331                         WL_ERR(("Wrong Mac address: "MACDBG" != "MACDBG"\n",
5332                                 MAC2STRDBG(mac), MAC2STRDBG(curmacp)));
5333                 }
5334
5335                 /* Report the current tx rate */
5336                 err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
5337                 if (err) {
5338                         WL_ERR(("Could not get rate (%d)\n", err));
5339                 } else {
5340 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
5341                         int rxpktglom;
5342 #endif
5343                         rate = dtoh32(rate);
5344                         sinfo->filled |= STA_INFO_BIT(INFO_TX_BITRATE);
5345                         sinfo->txrate.legacy = rate * 5;
5346                         WL_DBG(("Rate %d Mbps\n", (rate / 2)));
5347 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
5348                         rxpktglom = ((rate/2) > 150) ? 20 : 10;
5349
5350                         if (maxrxpktglom != rxpktglom) {
5351                                 maxrxpktglom = rxpktglom;
5352                                 WL_DBG(("Rate %d Mbps, update bus:maxtxpktglom=%d\n", (rate/2),
5353                                         maxrxpktglom));
5354                                 err = wldev_iovar_setbuf(dev, "bus:maxtxpktglom",
5355                                         (char*)&maxrxpktglom, 4, cfg->ioctl_buf,
5356                                         WLC_IOCTL_MAXLEN, NULL);
5357                                 if (err < 0) {
5358                                         WL_ERR(("set bus:maxtxpktglom failed, %d\n", err));
5359                                 }
5360                         }
5361 #endif
5362                 }
5363
5364                 memset(&scb_val, 0, sizeof(scb_val));
5365                 scb_val.val = 0;
5366                 err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,
5367                         sizeof(scb_val_t), false);
5368                 if (err) {
5369                         WL_ERR(("Could not get rssi (%d)\n", err));
5370                         goto get_station_err;
5371                 }
5372                 rssi = dtoh32(scb_val.val);
5373 #if defined(RSSIAVG)
5374                 err = wl_update_connected_rssi_cache(dev, &g_connected_rssi_cache_ctrl, &rssi);
5375                 if (err) {
5376                         WL_ERR(("Could not get rssi (%d)\n", err));
5377                         goto get_station_err;
5378                 }
5379                 wl_delete_dirty_rssi_cache(&g_connected_rssi_cache_ctrl);
5380                 wl_reset_rssi_cache(&g_connected_rssi_cache_ctrl);
5381 #endif
5382 #if defined(RSSIOFFSET)
5383                 rssi = wl_update_rssi_offset(dev, rssi);
5384 #endif
5385 #if !defined(RSSIAVG) && !defined(RSSIOFFSET)
5386                 // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
5387                 rssi = MIN(rssi, RSSI_MAXVAL);
5388 #endif
5389                 sinfo->filled |= STA_INFO_BIT(INFO_SIGNAL);
5390                 sinfo->signal = rssi;
5391                 WL_DBG(("RSSI %d dBm\n", rssi));
5392                 err = wldev_ioctl(dev, WLC_GET_PKTCNTS, &pktcnt,
5393                         sizeof(pktcnt), false);
5394                 if (!err) {
5395                         sinfo->filled |= (STA_INFO_BIT(INFO_RX_PACKETS) |
5396                                 STA_INFO_BIT(INFO_RX_DROP_MISC) |
5397                                 STA_INFO_BIT(INFO_TX_PACKETS) |
5398                                 STA_INFO_BIT(INFO_TX_FAILED));
5399                         sinfo->rx_packets = pktcnt.rx_good_pkt;
5400                         sinfo->rx_dropped_misc = pktcnt.rx_bad_pkt;
5401                         sinfo->tx_packets = pktcnt.tx_good_pkt;
5402                         sinfo->tx_failed  = pktcnt.tx_bad_pkt;
5403                 }
5404 get_station_err:
5405                 if (err)
5406                         err_cnt++;
5407                 else
5408                         err_cnt = 0;
5409                 if (err_cnt >= 3 && (err != -ERESTARTSYS)) {
5410                         /* Disconnect due to zero BSSID or error to get RSSI */
5411                         WL_ERR(("force cfg80211_disconnected: %d\n", err));
5412                         wl_clr_drv_status(cfg, CONNECTED, dev);
5413                         CFG80211_DISCONNECTED(dev, 0, NULL, 0, false, GFP_KERNEL);
5414                         wl_link_down(cfg);
5415                 }
5416         }
5417         else {
5418                 WL_ERR(("Invalid device mode %d\n", wl_get_mode_by_netdev(cfg, dev)));
5419         }
5420
5421         return err;
5422 }
5423
5424 static s32
5425 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
5426         bool enabled, s32 timeout)
5427 {
5428         s32 pm;
5429         s32 err = 0;
5430         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5431         struct net_info *_net_info = wl_get_netinfo_by_netdev(cfg, dev);
5432         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
5433
5434         RETURN_EIO_IF_NOT_UP(cfg);
5435         WL_DBG(("Enter\n"));
5436         if (cfg->p2p_net == dev || _net_info == NULL ||
5437                 !wl_get_drv_status(cfg, CONNECTED, dev) ||
5438                 (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_BSS &&
5439                 wl_get_mode_by_netdev(cfg, dev) != WL_MODE_IBSS)) {
5440                 return err;
5441         }
5442         /* Enlarge pm_enable_work */
5443         wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_LONG);
5444
5445         pm = enabled ? PM_FAST : PM_OFF;
5446         if (_net_info->pm_block) {
5447                 WL_ERR(("%s:Do not enable the power save for pm_block %d\n",
5448                         dev->name, _net_info->pm_block));
5449                 pm = PM_OFF;
5450         }
5451         if (enabled && dhd_conf_get_pm(dhd) >= 0)
5452                 pm = dhd_conf_get_pm(dhd);
5453         pm = htod32(pm);
5454         WL_DBG(("%s:power save %s\n", dev->name, (pm ? "enabled" : "disabled")));
5455         err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true);
5456         if (unlikely(err)) {
5457                 if (err == -ENODEV)
5458                         WL_DBG(("net_device is not ready yet\n"));
5459                 else
5460                         WL_ERR(("error (%d)\n", err));
5461                 return err;
5462         }
5463         wl_cfg80211_update_power_mode(dev);
5464         return err;
5465 }
5466
5467 void wl_cfg80211_update_power_mode(struct net_device *dev)
5468 {
5469         int err, pm = -1;
5470
5471         err = wldev_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), true);
5472         if (err)
5473                 WL_ERR(("%s:error (%d)\n", __FUNCTION__, err));
5474         else if (pm != -1 && dev->ieee80211_ptr)
5475                 dev->ieee80211_ptr->ps = (pm == PM_OFF) ? false : true;
5476 }
5477
5478 void wl_cfg80211_set_passive_scan(struct net_device *dev, char *command)
5479 {
5480         struct bcm_cfg80211 *cfg = g_bcm_cfg;
5481
5482         if (strcmp(command, "SCAN-ACTIVE") == 0) {
5483                 cfg->active_scan = 1;
5484         } else if (strcmp(command, "SCAN-PASSIVE") == 0) {
5485                 cfg->active_scan = 0;
5486         } else
5487                 WL_ERR(("Unknown command \n"));
5488 }
5489
5490 static __used u32 wl_find_msb(u16 bit16)
5491 {
5492         u32 ret = 0;
5493
5494         if (bit16 & 0xff00) {
5495                 ret += 8;
5496                 bit16 >>= 8;
5497         }
5498
5499         if (bit16 & 0xf0) {
5500                 ret += 4;
5501                 bit16 >>= 4;
5502         }
5503
5504         if (bit16 & 0xc) {
5505                 ret += 2;
5506                 bit16 >>= 2;
5507         }
5508
5509         if (bit16 & 2)
5510                 ret += bit16 & 2;
5511         else if (bit16)
5512                 ret += bit16;
5513
5514         return ret;
5515 }
5516
5517 static s32 wl_cfg80211_resume(struct wiphy *wiphy)
5518 {
5519         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5520         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
5521         s32 err = BCME_OK;
5522
5523         if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
5524                 WL_INFORM(("device is not ready\n"));
5525                 return err;
5526         }
5527
5528         return err;
5529 }
5530
5531 static s32
5532 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
5533 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
5534 #else
5535 wl_cfg80211_suspend(struct wiphy *wiphy)
5536 #endif /* KERNEL_VERSION(2, 6, 39) || WL_COMPAT_WIRELES */
5537 {
5538         s32 err = BCME_OK;
5539 #ifdef DHD_CLEAR_ON_SUSPEND
5540         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5541         struct net_info *iter, *next;
5542         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
5543         unsigned long flags;
5544         if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
5545                 WL_INFORM(("device is not ready : status (%d)\n",
5546                         (int)cfg->status));
5547                 return err;
5548         }
5549         for_each_ndev(cfg, iter, next) {
5550                 /* p2p discovery iface doesn't have a ndev associated with it (for kernel > 3.8) */
5551                 if (iter->ndev)
5552                         wl_set_drv_status(cfg, SCAN_ABORTING, iter->ndev);
5553                 }
5554         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
5555         if (cfg->scan_request) {
5556                 cfg80211_scan_done(cfg->scan_request, true);
5557                 cfg->scan_request = NULL;
5558         }
5559         for_each_ndev(cfg, iter, next) {
5560                 if (iter->ndev) {
5561                         wl_clr_drv_status(cfg, SCANNING, iter->ndev);
5562                         wl_clr_drv_status(cfg, SCAN_ABORTING, iter->ndev);
5563                 }
5564         }
5565         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
5566         for_each_ndev(cfg, iter, next) {
5567                 if (iter->ndev) {
5568                         if (wl_get_drv_status(cfg, CONNECTING, iter->ndev)) {
5569                                 wl_bss_connect_done(cfg, iter->ndev, NULL, NULL, false);
5570                         }
5571                 }
5572         }
5573 #endif /* DHD_CLEAR_ON_SUSPEND */
5574
5575
5576         return err;
5577 }
5578
5579 static s32
5580 wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
5581         s32 err)
5582 {
5583         int i, j;
5584         struct bcm_cfg80211 *cfg = g_bcm_cfg;
5585         struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
5586
5587         if (!pmk_list) {
5588                 printf("pmk_list is NULL\n");
5589                 return -EINVAL;
5590         }
5591         /* pmk list is supported only for STA interface i.e. primary interface
5592          * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
5593          */
5594         if (primary_dev != dev) {
5595                 WL_INFORM(("Not supporting Flushing pmklist on virtual"
5596                         " interfaces than primary interface\n"));
5597                 return err;
5598         }
5599
5600         WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
5601         for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
5602                 WL_DBG(("PMKID[%d]: %pM =\n", i,
5603                         &pmk_list->pmkids.pmkid[i].BSSID));
5604                 for (j = 0; j < WPA2_PMKID_LEN; j++) {
5605                         WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
5606                 }
5607         }
5608         if (likely(!err)) {
5609                 err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmk_list,
5610                         sizeof(*pmk_list), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
5611         }
5612
5613         return err;
5614 }
5615
5616 static s32
5617 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
5618         struct cfg80211_pmksa *pmksa)
5619 {
5620         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5621         s32 err = 0;
5622         int i;
5623
5624         RETURN_EIO_IF_NOT_UP(cfg);
5625         for (i = 0; i < cfg->pmk_list->pmkids.npmkid; i++)
5626                 if (!memcmp(pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
5627                         ETHER_ADDR_LEN))
5628                         break;
5629         if (i < WL_NUM_PMKIDS_MAX) {
5630                 memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
5631                         ETHER_ADDR_LEN);
5632                 memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
5633                         WPA2_PMKID_LEN);
5634                 if (i == cfg->pmk_list->pmkids.npmkid)
5635                         cfg->pmk_list->pmkids.npmkid++;
5636         } else {
5637                 err = -EINVAL;
5638         }
5639         WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
5640                 &cfg->pmk_list->pmkids.pmkid[cfg->pmk_list->pmkids.npmkid - 1].BSSID));
5641         for (i = 0; i < WPA2_PMKID_LEN; i++) {
5642                 WL_DBG(("%02x\n",
5643                         cfg->pmk_list->pmkids.pmkid[cfg->pmk_list->pmkids.npmkid - 1].
5644                         PMKID[i]));
5645         }
5646
5647         err = wl_update_pmklist(dev, cfg->pmk_list, err);
5648
5649         return err;
5650 }
5651
5652 static s32
5653 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
5654         struct cfg80211_pmksa *pmksa)
5655 {
5656         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5657
5658         struct _pmkid_list pmkid = {.npmkid = 0};
5659         s32 err = 0;
5660         int i;
5661
5662         RETURN_EIO_IF_NOT_UP(cfg);
5663         memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
5664         memcpy(pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
5665
5666         WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
5667                 &pmkid.pmkid[0].BSSID));
5668         for (i = 0; i < WPA2_PMKID_LEN; i++) {
5669                 WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
5670         }
5671
5672         for (i = 0; i < cfg->pmk_list->pmkids.npmkid; i++)
5673                 if (!memcmp
5674                     (pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
5675                      ETHER_ADDR_LEN))
5676                         break;
5677
5678         if ((cfg->pmk_list->pmkids.npmkid > 0) &&
5679                 (i < cfg->pmk_list->pmkids.npmkid)) {
5680                 memset(&cfg->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
5681                 for (; i < (cfg->pmk_list->pmkids.npmkid - 1); i++) {
5682                         memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID,
5683                                 &cfg->pmk_list->pmkids.pmkid[i + 1].BSSID,
5684                                 ETHER_ADDR_LEN);
5685                         memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID,
5686                                 &cfg->pmk_list->pmkids.pmkid[i + 1].PMKID,
5687                                 WPA2_PMKID_LEN);
5688                 }
5689                 cfg->pmk_list->pmkids.npmkid--;
5690         } else {
5691                 err = -EINVAL;
5692         }
5693
5694         err = wl_update_pmklist(dev, cfg->pmk_list, err);
5695
5696         return err;
5697
5698 }
5699
5700 static s32
5701 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
5702 {
5703         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5704         s32 err = 0;
5705         RETURN_EIO_IF_NOT_UP(cfg);
5706         memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list));
5707         err = wl_update_pmklist(dev, cfg->pmk_list, err);
5708         return err;
5709
5710 }
5711
5712 static wl_scan_params_t *
5713 wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size)
5714 {
5715         wl_scan_params_t *params;
5716         int params_size;
5717         int num_chans;
5718         int bssidx = 0;
5719
5720         *out_params_size = 0;
5721
5722         /* Our scan params only need space for 1 channel and 0 ssids */
5723         params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16);
5724         params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL);
5725         if (params == NULL) {
5726                 WL_ERR(("mem alloc failed (%d bytes)\n", params_size));
5727                 return params;
5728         }
5729         memset(params, 0, params_size);
5730         params->nprobes = nprobes;
5731
5732         num_chans = (channel == 0) ? 0 : 1;
5733
5734         memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
5735         params->bss_type = DOT11_BSSTYPE_ANY;
5736         params->scan_type = DOT11_SCANTYPE_ACTIVE;
5737         params->nprobes = htod32(1);
5738         params->active_time = htod32(-1);
5739         params->passive_time = htod32(-1);
5740         params->home_time = htod32(10);
5741         if (channel == -1)
5742                 params->channel_list[0] = htodchanspec(channel);
5743         else
5744                 params->channel_list[0] = wl_ch_host_to_driver(bssidx, channel);
5745
5746         /* Our scan params have 1 channel and 0 ssids */
5747         params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
5748                 (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
5749
5750         *out_params_size = params_size; /* rtn size to the caller */
5751         return params;
5752 }
5753
5754 static s32
5755 #if defined(WL_CFG80211_P2P_DEV_IF)
5756 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
5757         struct ieee80211_channel *channel, unsigned int duration, u64 *cookie)
5758 #else
5759 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
5760         struct ieee80211_channel * channel,
5761         enum nl80211_channel_type channel_type,
5762         unsigned int duration, u64 *cookie)
5763 #endif /* WL_CFG80211_P2P_DEV_IF */
5764 {
5765         s32 target_channel;
5766         s32 err = BCME_OK;
5767         struct ether_addr primary_mac;
5768         struct net_device *ndev = NULL;
5769         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5770
5771         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
5772
5773         WL_DBG(("Enter, channel: %d, duration ms (%d) SCANNING ?? %s \n",
5774                 ieee80211_frequency_to_channel(channel->center_freq),
5775                 duration, (wl_get_drv_status(cfg, SCANNING, ndev)) ? "YES":"NO"));
5776
5777         if (!cfg->p2p) {
5778                 WL_ERR(("cfg->p2p is not initialized\n"));
5779                 err = BCME_ERROR;
5780                 goto exit;
5781         }
5782
5783 #ifdef P2P_LISTEN_OFFLOADING
5784         if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
5785                 WL_ERR(("P2P_FIND: Discovery offload is in progress\n"));
5786                 return -EAGAIN;
5787         }
5788 #endif /* P2P_LISTEN_OFFLOADING */
5789
5790 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5791         if (wl_get_drv_status_all(cfg, SCANNING)) {
5792                 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
5793         }
5794 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5795
5796         target_channel = ieee80211_frequency_to_channel(channel->center_freq);
5797         memcpy(&cfg->remain_on_chan, channel, sizeof(struct ieee80211_channel));
5798 #if defined(WL_ENABLE_P2P_IF)
5799         cfg->remain_on_chan_type = channel_type;
5800 #endif /* WL_ENABLE_P2P_IF */
5801         *cookie = wl_cfg80211_get_new_roc_id(cfg);
5802 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5803         if (wl_get_drv_status(cfg, SCANNING, ndev)) {
5804                 struct timer_list *_timer;
5805                 WL_DBG(("scan is running. go to fake listen state\n"));
5806
5807                 if (duration > LONG_LISTEN_TIME) {
5808                         wl_cfg80211_scan_abort(cfg);
5809                 } else {
5810                         wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
5811
5812                         if (timer_pending(&cfg->p2p->listen_timer)) {
5813                                 WL_DBG(("cancel current listen timer \n"));
5814                                 del_timer_sync(&cfg->p2p->listen_timer);
5815                         }
5816
5817                         _timer = &cfg->p2p->listen_timer;
5818                         wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
5819
5820                         INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration, 0);
5821
5822                         err = BCME_OK;
5823                         goto exit;
5824                 }
5825         }
5826 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5827
5828 #ifdef WL_CFG80211_SYNC_GON
5829         if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
5830                 /* do not enter listen mode again if we are in listen mode already for next af.
5831                  * remain on channel completion will be returned by waiting next af completion.
5832                  */
5833 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5834                 wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
5835 #else
5836                 wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
5837 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5838                 goto exit;
5839         }
5840 #endif /* WL_CFG80211_SYNC_GON */
5841         if (cfg->p2p && !cfg->p2p->on) {
5842                 /* In case of p2p_listen command, supplicant send remain_on_channel
5843                  * without turning on P2P
5844                  */
5845                 get_primary_mac(cfg, &primary_mac);
5846                 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
5847                 p2p_on(cfg) = true;
5848         }
5849
5850         if (p2p_is_on(cfg)) {
5851                 err = wl_cfgp2p_enable_discovery(cfg, ndev, NULL, 0);
5852                 if (unlikely(err)) {
5853                         goto exit;
5854                 }
5855 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5856                 wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
5857 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5858                 err = wl_cfgp2p_discover_listen(cfg, target_channel, duration);
5859
5860 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5861                 if (err == BCME_OK) {
5862                         wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
5863                 } else {
5864                         /* if failed, firmware may be internal scanning state.
5865                          * so other scan request shall not abort it
5866                          */
5867                         wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
5868                 }
5869 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5870                 /* WAR: set err = ok to prevent cookie mismatch in wpa_supplicant
5871                  * and expire timer will send a completion to the upper layer
5872                  */
5873                 err = BCME_OK;
5874         }
5875
5876 exit:
5877         if (err == BCME_OK) {
5878                 WL_INFORM(("Success\n"));
5879 #if defined(WL_CFG80211_P2P_DEV_IF)
5880                 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
5881                         duration, GFP_KERNEL);
5882 #else
5883                 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
5884                         channel_type, duration, GFP_KERNEL);
5885 #endif /* WL_CFG80211_P2P_DEV_IF */
5886         } else {
5887                 WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err, *cookie));
5888         }
5889         return err;
5890 }
5891
5892 static s32
5893 wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
5894         bcm_struct_cfgdev *cfgdev, u64 cookie)
5895 {
5896         s32 err = 0;
5897         struct bcm_cfg80211 *cfg = g_bcm_cfg;
5898
5899 #ifdef P2PLISTEN_AP_SAMECHN
5900         struct net_device *dev;
5901 #endif /* P2PLISTEN_AP_SAMECHN */
5902
5903         RETURN_EIO_IF_NOT_UP(cfg);
5904 #if defined(WL_CFG80211_P2P_DEV_IF)
5905         if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
5906                 WL_DBG((" enter ) on P2P dedicated discover interface\n"));
5907         }
5908 #else
5909         WL_DBG((" enter ) netdev_ifidx: %d \n", cfgdev->ifindex));
5910 #endif /* WL_CFG80211_P2P_DEV_IF */
5911
5912 #ifdef P2PLISTEN_AP_SAMECHN
5913         if (cfg && cfg->p2p_resp_apchn_status) {
5914                 dev = bcmcfg_to_prmry_ndev(cfg);
5915                 wl_cfg80211_set_p2p_resp_ap_chn(dev, 0);
5916                 cfg->p2p_resp_apchn_status = false;
5917                 WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
5918         }
5919 #endif /* P2PLISTEN_AP_SAMECHN */
5920
5921         if (cfg->last_roc_id == cookie) {
5922                 wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
5923                         wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
5924         } else {
5925                 WL_ERR(("%s : ignore, request cookie(%llu) is not matched. (cur : %llu)\n",
5926                         __FUNCTION__, cookie, cfg->last_roc_id));
5927         }
5928
5929         return err;
5930 }
5931
5932 static void
5933 wl_cfg80211_afx_handler(struct work_struct *work)
5934 {
5935         struct afx_hdl *afx_instance;
5936         struct bcm_cfg80211 *cfg = g_bcm_cfg;
5937         s32 ret = BCME_OK;
5938
5939         BCM_SET_CONTAINER_OF(afx_instance, work, struct afx_hdl, work);
5940         if (afx_instance != NULL && cfg->afx_hdl->is_active) {
5941                 if (cfg->afx_hdl->is_listen && cfg->afx_hdl->my_listen_chan) {
5942                         ret = wl_cfgp2p_discover_listen(cfg, cfg->afx_hdl->my_listen_chan,
5943                                 (100 * (1 + (RANDOM32() % 3)))); /* 100ms ~ 300ms */
5944                 } else {
5945                         ret = wl_cfgp2p_act_frm_search(cfg, cfg->afx_hdl->dev,
5946                                 cfg->afx_hdl->bssidx, cfg->afx_hdl->peer_listen_chan,
5947                                 NULL);
5948                 }
5949                 if (unlikely(ret != BCME_OK)) {
5950                         WL_ERR(("ERROR occurred! returned value is (%d)\n", ret));
5951                         if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL))
5952                                 complete(&cfg->act_frm_scan);
5953                 }
5954         }
5955 }
5956
5957 static s32
5958 wl_cfg80211_af_searching_channel(struct bcm_cfg80211 *cfg, struct net_device *dev)
5959 {
5960         u32 max_retry = WL_CHANNEL_SYNC_RETRY;
5961         bool is_p2p_gas = false;
5962
5963         if (dev == NULL)
5964                 return -1;
5965
5966         WL_DBG((" enter ) \n"));
5967
5968         wl_set_drv_status(cfg, FINDING_COMMON_CHANNEL, dev);
5969         cfg->afx_hdl->is_active = TRUE;
5970
5971         if (cfg->afx_hdl->pending_tx_act_frm) {
5972                 wl_action_frame_t *action_frame;
5973                 action_frame = &(cfg->afx_hdl->pending_tx_act_frm->action_frame);
5974                 if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len))
5975                         is_p2p_gas = true;
5976         }
5977
5978         /* Loop to wait until we find a peer's channel or the
5979          * pending action frame tx is cancelled.
5980          */
5981         while ((cfg->afx_hdl->retry < max_retry) &&
5982                 (cfg->afx_hdl->peer_chan == WL_INVALID)) {
5983                 cfg->afx_hdl->is_listen = FALSE;
5984                 wl_set_drv_status(cfg, SCANNING, dev);
5985                 WL_DBG(("Scheduling the action frame for sending.. retry %d\n",
5986                         cfg->afx_hdl->retry));
5987                 /* search peer on peer's listen channel */
5988                 schedule_work(&cfg->afx_hdl->work);
5989                 wait_for_completion_timeout(&cfg->act_frm_scan,
5990                         msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
5991
5992                 if ((cfg->afx_hdl->peer_chan != WL_INVALID) ||
5993                         !(wl_get_drv_status(cfg, FINDING_COMMON_CHANNEL, dev)))
5994                         break;
5995
5996                 if (is_p2p_gas)
5997                         break;
5998
5999                 if (cfg->afx_hdl->my_listen_chan) {
6000                         WL_DBG(("Scheduling Listen peer in my listen channel = %d\n",
6001                                 cfg->afx_hdl->my_listen_chan));
6002                         /* listen on my listen channel */
6003                         cfg->afx_hdl->is_listen = TRUE;
6004                         schedule_work(&cfg->afx_hdl->work);
6005                         wait_for_completion_timeout(&cfg->act_frm_scan,
6006                                 msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
6007                 }
6008                 if ((cfg->afx_hdl->peer_chan != WL_INVALID) ||
6009                         !(wl_get_drv_status(cfg, FINDING_COMMON_CHANNEL, dev)))
6010                         break;
6011
6012                 cfg->afx_hdl->retry++;
6013
6014                 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg);
6015         }
6016
6017         cfg->afx_hdl->is_active = FALSE;
6018
6019         wl_clr_drv_status(cfg, SCANNING, dev);
6020         wl_clr_drv_status(cfg, FINDING_COMMON_CHANNEL, dev);
6021
6022         return (cfg->afx_hdl->peer_chan);
6023 }
6024
6025 struct p2p_config_af_params {
6026         s32 max_tx_retry;       /* max tx retry count if tx no ack */
6027         /* To make sure to send successfully action frame, we have to turn off mpc
6028          * 0: off, 1: on,  (-1): do nothing
6029          */
6030         s32 mpc_onoff;
6031 #ifdef WL_CFG80211_SYNC_GON
6032         bool extra_listen;
6033 #endif
6034         bool search_channel;    /* 1: search peer's channel to send af */
6035 };
6036
6037 static s32
6038 wl_cfg80211_config_p2p_pub_af_tx(struct wiphy *wiphy,
6039         wl_action_frame_t *action_frame, wl_af_params_t *af_params,
6040         struct p2p_config_af_params *config_af_params)
6041 {
6042         s32 err = BCME_OK;
6043         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6044         wifi_p2p_pub_act_frame_t *act_frm =
6045                 (wifi_p2p_pub_act_frame_t *) (action_frame->data);
6046
6047         /* initialize default value */
6048 #ifdef WL_CFG80211_SYNC_GON
6049         config_af_params->extra_listen = true;
6050 #endif
6051         config_af_params->search_channel = false;
6052         config_af_params->max_tx_retry = WL_AF_TX_MAX_RETRY;
6053         config_af_params->mpc_onoff = -1;
6054         cfg->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
6055
6056         switch (act_frm->subtype) {
6057         case P2P_PAF_GON_REQ: {
6058                 WL_DBG(("P2P: GO_NEG_PHASE status set \n"));
6059                 wl_set_p2p_status(cfg, GO_NEG_PHASE);
6060
6061                 config_af_params->mpc_onoff = 0;
6062                 config_af_params->search_channel = true;
6063                 cfg->next_af_subtype = act_frm->subtype + 1;
6064
6065                 /* increase dwell time to wait for RESP frame */
6066                 af_params->dwell_time = WL_MED_DWELL_TIME;
6067
6068                 break;
6069         }
6070         case P2P_PAF_GON_RSP: {
6071                 cfg->next_af_subtype = act_frm->subtype + 1;
6072                 /* increase dwell time to wait for CONF frame */
6073                 af_params->dwell_time = WL_MED_DWELL_TIME + 100;
6074                 break;
6075         }
6076         case P2P_PAF_GON_CONF: {
6077                 /* If we reached till GO Neg confirmation reset the filter */
6078                 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
6079                 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
6080
6081                 /* turn on mpc again if go nego is done */
6082                 config_af_params->mpc_onoff = 1;
6083
6084                 /* minimize dwell time */
6085                 af_params->dwell_time = WL_MIN_DWELL_TIME;
6086
6087 #ifdef WL_CFG80211_SYNC_GON
6088                 config_af_params->extra_listen = false;
6089 #endif /* WL_CFG80211_SYNC_GON */
6090                 break;
6091         }
6092         case P2P_PAF_INVITE_REQ: {
6093                 config_af_params->search_channel = true;
6094                 cfg->next_af_subtype = act_frm->subtype + 1;
6095
6096                 /* increase dwell time */
6097                 af_params->dwell_time = WL_MED_DWELL_TIME;
6098                 break;
6099         }
6100         case P2P_PAF_INVITE_RSP:
6101                 /* minimize dwell time */
6102                 af_params->dwell_time = WL_MIN_DWELL_TIME;
6103 #ifdef WL_CFG80211_SYNC_GON
6104                 config_af_params->extra_listen = false;
6105 #endif /* WL_CFG80211_SYNC_GON */
6106                 break;
6107         case P2P_PAF_DEVDIS_REQ: {
6108                 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
6109                         action_frame->len)) {
6110                         config_af_params->search_channel = true;
6111                 }
6112
6113                 cfg->next_af_subtype = act_frm->subtype + 1;
6114                 /* maximize dwell time to wait for RESP frame */
6115                 af_params->dwell_time = WL_LONG_DWELL_TIME;
6116                 break;
6117         }
6118         case P2P_PAF_DEVDIS_RSP:
6119                 /* minimize dwell time */
6120                 af_params->dwell_time = WL_MIN_DWELL_TIME;
6121 #ifdef WL_CFG80211_SYNC_GON
6122                 config_af_params->extra_listen = false;
6123 #endif /* WL_CFG80211_SYNC_GON */
6124                 break;
6125         case P2P_PAF_PROVDIS_REQ: {
6126                 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
6127                         action_frame->len)) {
6128                         config_af_params->search_channel = true;
6129                 }
6130
6131                 config_af_params->mpc_onoff = 0;
6132                 cfg->next_af_subtype = act_frm->subtype + 1;
6133                 /* increase dwell time to wait for RESP frame */
6134                 af_params->dwell_time = WL_MED_DWELL_TIME;
6135                 break;
6136         }
6137         case P2P_PAF_PROVDIS_RSP: {
6138                 cfg->next_af_subtype = P2P_PAF_GON_REQ;
6139                 af_params->dwell_time = WL_MIN_DWELL_TIME;
6140 #ifdef WL_CFG80211_SYNC_GON
6141                 config_af_params->extra_listen = false;
6142 #endif /* WL_CFG80211_SYNC_GON */
6143                 break;
6144         }
6145         default:
6146                 WL_DBG(("Unknown p2p pub act frame subtype: %d\n",
6147                         act_frm->subtype));
6148                 err = BCME_BADARG;
6149         }
6150         return err;
6151 }
6152
6153 #ifdef WL11U
6154 static bool
6155 wl_cfg80211_check_DFS_channel(struct bcm_cfg80211 *cfg, wl_af_params_t *af_params,
6156         void *frame, u16 frame_len)
6157 {
6158         struct wl_scan_results *bss_list;
6159         struct wl_bss_info *bi = NULL;
6160         bool result = false;
6161         s32 i;
6162         chanspec_t chanspec;
6163
6164         /* If DFS channel is 52~148, check to block it or not */
6165         if (af_params &&
6166                 (af_params->channel >= 52 && af_params->channel <= 148)) {
6167                 if (!wl_cfgp2p_is_p2p_action(frame, frame_len)) {
6168                         bss_list = cfg->bss_list;
6169                         bi = next_bss(bss_list, bi);
6170                         for_each_bss(bss_list, bi, i) {
6171                                 chanspec = wl_chspec_driver_to_host(bi->chanspec);
6172                                 if (CHSPEC_IS5G(chanspec) &&
6173                                         ((bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(chanspec))
6174                                         == af_params->channel)) {
6175                                         result = true;  /* do not block the action frame */
6176                                         break;
6177                                 }
6178                         }
6179                 }
6180         }
6181         else {
6182                 result = true;
6183         }
6184
6185         WL_DBG(("result=%s", result?"true":"false"));
6186         return result;
6187 }
6188 #endif /* WL11U */
6189 static bool
6190 wl_cfg80211_check_dwell_overflow(int32 requested_dwell, ulong dwell_jiffies)
6191 {
6192         if ((requested_dwell & CUSTOM_RETRY_MASK) &&
6193                         (jiffies_to_msecs(jiffies - dwell_jiffies) >
6194                          (requested_dwell & ~CUSTOM_RETRY_MASK))) {
6195                 WL_ERR(("Action frame TX retry time over dwell time!\n"));
6196                 return true;
6197         }
6198         return false;
6199 }
6200
6201 static bool
6202 wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev,
6203         bcm_struct_cfgdev *cfgdev, wl_af_params_t *af_params,
6204         wl_action_frame_t *action_frame, u16 action_frame_len, s32 bssidx)
6205 {
6206 #ifdef WL11U
6207         struct net_device *ndev = NULL;
6208 #endif /* WL11U */
6209         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6210         bool ack = false;
6211         u8 category, action;
6212         s32 tx_retry;
6213         struct p2p_config_af_params config_af_params;
6214         struct net_info *netinfo;
6215 #ifdef VSDB
6216         ulong off_chan_started_jiffies = 0;
6217 #endif
6218         ulong dwell_jiffies = 0;
6219         bool dwell_overflow = false;
6220         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
6221
6222         int32 requested_dwell = af_params->dwell_time;
6223
6224         /* Add the default dwell time
6225          * Dwell time to stay off-channel to wait for a response action frame
6226          * after transmitting an GO Negotiation action frame
6227          */
6228         af_params->dwell_time = WL_DWELL_TIME;
6229
6230 #ifdef WL11U
6231 #if defined(WL_CFG80211_P2P_DEV_IF)
6232         ndev = dev;
6233 #else
6234         ndev = ndev_to_cfgdev(cfgdev);
6235 #endif /* WL_CFG80211_P2P_DEV_IF */
6236 #endif /* WL11U */
6237
6238         category = action_frame->data[DOT11_ACTION_CAT_OFF];
6239         action = action_frame->data[DOT11_ACTION_ACT_OFF];
6240
6241         /* initialize variables */
6242         tx_retry = 0;
6243         cfg->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
6244         config_af_params.max_tx_retry = WL_AF_TX_MAX_RETRY;
6245         config_af_params.mpc_onoff = -1;
6246         config_af_params.search_channel = false;
6247 #ifdef WL_CFG80211_SYNC_GON
6248         config_af_params.extra_listen = false;
6249 #endif
6250
6251         /* config parameters */
6252         /* Public Action Frame Process - DOT11_ACTION_CAT_PUBLIC */
6253         if (category == DOT11_ACTION_CAT_PUBLIC) {
6254                 if ((action == P2P_PUB_AF_ACTION) &&
6255                         (action_frame_len >= sizeof(wifi_p2p_pub_act_frame_t))) {
6256                         /* p2p public action frame process */
6257                         if (BCME_OK != wl_cfg80211_config_p2p_pub_af_tx(wiphy,
6258                                 action_frame, af_params, &config_af_params)) {
6259                                 WL_DBG(("Unknown subtype.\n"));
6260                         }
6261
6262                 } else if (action_frame_len >= sizeof(wifi_p2psd_gas_pub_act_frame_t)) {
6263                         /* service discovery process */
6264                         if (action == P2PSD_ACTION_ID_GAS_IREQ ||
6265                                 action == P2PSD_ACTION_ID_GAS_CREQ) {
6266                                 /* configure service discovery query frame */
6267
6268                                 config_af_params.search_channel = true;
6269
6270                                 /* save next af suptype to cancel remained dwell time */
6271                                 cfg->next_af_subtype = action + 1;
6272
6273                                 af_params->dwell_time = WL_MED_DWELL_TIME;
6274                                 if (requested_dwell & CUSTOM_RETRY_MASK) {
6275                                         config_af_params.max_tx_retry =
6276                                                 (requested_dwell & CUSTOM_RETRY_MASK) >> 24;
6277                                         af_params->dwell_time =
6278                                                 (requested_dwell & ~CUSTOM_RETRY_MASK);
6279                                         WL_DBG(("Custom retry(%d) and dwell time(%d) is set.\n",
6280                                                 config_af_params.max_tx_retry,
6281                                                 af_params->dwell_time));
6282                                 }
6283                         } else if (action == P2PSD_ACTION_ID_GAS_IRESP ||
6284                                 action == P2PSD_ACTION_ID_GAS_CRESP) {
6285                                 /* configure service discovery response frame */
6286                                 af_params->dwell_time = WL_MIN_DWELL_TIME;
6287                         } else {
6288                                 WL_DBG(("Unknown action type: %d\n", action));
6289                         }
6290                 } else {
6291                         WL_DBG(("Unknown Frame: category 0x%x, action 0x%x, length %d\n",
6292                                 category, action, action_frame_len));
6293                 }
6294         } else if (category == P2P_AF_CATEGORY) {
6295                 /* do not configure anything. it will be sent with a default configuration */
6296         } else {
6297                 WL_DBG(("Unknown Frame: category 0x%x, action 0x%x\n",
6298                         category, action));
6299                 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
6300                         wl_clr_drv_status(cfg, SENDING_ACT_FRM, dev);
6301                         return false;
6302                 }
6303         }
6304
6305         /* To make sure to send successfully action frame, we have to turn off mpc */
6306         if (config_af_params.mpc_onoff == 0) {
6307                 wldev_iovar_setint(dev, "mpc", 0);
6308         }
6309
6310         netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
6311         /* validate channel and p2p ies */
6312         if (config_af_params.search_channel && IS_P2P_SOCIAL(af_params->channel) &&
6313                 netinfo && netinfo->bss.ies.probe_req_ie_len) {
6314                 config_af_params.search_channel = true;
6315         } else {
6316                 config_af_params.search_channel = false;
6317         }
6318 #ifdef WL11U
6319         if (ndev == bcmcfg_to_prmry_ndev(cfg))
6320                 config_af_params.search_channel = false;
6321 #endif /* WL11U */
6322
6323 #ifdef VSDB
6324         /* if connecting on primary iface, sleep for a while before sending af tx for VSDB */
6325         if (wl_get_drv_status(cfg, CONNECTING, bcmcfg_to_prmry_ndev(cfg))) {
6326                 OSL_SLEEP(50);
6327         }
6328 #endif
6329
6330         /* if scan is ongoing, abort current scan. */
6331         if (wl_get_drv_status_all(cfg, SCANNING)) {
6332                 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
6333         }
6334
6335         /* Abort P2P listen */
6336         if (discover_cfgdev(cfgdev, cfg)) {
6337                 if (cfg->p2p_supported && cfg->p2p) {
6338                         wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
6339                                 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
6340                 }
6341         }
6342
6343 #ifdef WL11U
6344         /* handling DFS channel exceptions */
6345         if (!wl_cfg80211_check_DFS_channel(cfg, af_params, action_frame->data, action_frame->len)) {
6346                 return false;   /* the action frame was blocked */
6347         }
6348 #endif /* WL11U */
6349
6350         /* set status and destination address before sending af */
6351         if (cfg->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
6352                 /* set this status to cancel the remained dwell time in rx process */
6353                 wl_set_drv_status(cfg, WAITING_NEXT_ACT_FRM, dev);
6354         }
6355         wl_set_drv_status(cfg, SENDING_ACT_FRM, dev);
6356         memcpy(cfg->afx_hdl->tx_dst_addr.octet,
6357                 af_params->action_frame.da.octet,
6358                 sizeof(cfg->afx_hdl->tx_dst_addr.octet));
6359
6360         /* save af_params for rx process */
6361         cfg->afx_hdl->pending_tx_act_frm = af_params;
6362
6363         if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len)) {
6364                 WL_DBG(("Set GAS action frame config.\n"));
6365                 config_af_params.search_channel = false;
6366                 config_af_params.max_tx_retry = 1;
6367         }
6368
6369         /* search peer's channel */
6370         if (config_af_params.search_channel) {
6371                 /* initialize afx_hdl */
6372                 if ((cfg->afx_hdl->bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
6373                         WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
6374                         goto exit;
6375                 }
6376                 cfg->afx_hdl->dev = dev;
6377                 cfg->afx_hdl->retry = 0;
6378                 cfg->afx_hdl->peer_chan = WL_INVALID;
6379
6380                 if (wl_cfg80211_af_searching_channel(cfg, dev) == WL_INVALID) {
6381                         WL_ERR(("couldn't find peer's channel.\n"));
6382                         wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len,
6383                                 af_params->channel);
6384                         goto exit;
6385                 }
6386
6387                 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
6388                 /*
6389                  * Abort scan even for VSDB scenarios. Scan gets aborted in firmware
6390                  * but after the check of piggyback algorithm.
6391                  * To take care of current piggback algo, lets abort the scan here itself.
6392                  */
6393                 wl_notify_escan_complete(cfg, dev, true, true);
6394                 /* Suspend P2P discovery's search-listen to prevent it from
6395                  * starting a scan or changing the channel.
6396                  */
6397                 if ((wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
6398                         WL_ERR(("Can not disable discovery mode\n"));
6399                         goto exit;
6400                 }
6401
6402                 /* update channel */
6403                 af_params->channel = cfg->afx_hdl->peer_chan;
6404         }
6405
6406 #ifdef VSDB
6407         off_chan_started_jiffies = jiffies;
6408 #endif /* VSDB */
6409
6410         wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len, af_params->channel);
6411
6412         wl_cfgp2p_need_wait_actfrmae(cfg, action_frame->data, action_frame->len, true);
6413
6414         dwell_jiffies = jiffies;
6415         /* Now send a tx action frame */
6416         ack = wl_cfgp2p_tx_action_frame(cfg, dev, af_params, bssidx) ? false : true;
6417         dwell_overflow = wl_cfg80211_check_dwell_overflow(requested_dwell, dwell_jiffies);
6418
6419         /* if failed, retry it. tx_retry_max value is configure by .... */
6420         while ((ack == false) && (tx_retry++ < config_af_params.max_tx_retry) &&
6421                         !dwell_overflow) {
6422 #ifdef VSDB
6423                 if (af_params->channel) {
6424                         if (jiffies_to_msecs(jiffies - off_chan_started_jiffies) >
6425                                 OFF_CHAN_TIME_THRESHOLD_MS) {
6426                                 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg);
6427                                 off_chan_started_jiffies = jiffies;
6428                         } else
6429                                 OSL_SLEEP(AF_RETRY_DELAY_TIME);
6430                 }
6431 #endif /* VSDB */
6432                 ack = wl_cfgp2p_tx_action_frame(cfg, dev, af_params, bssidx) ?
6433                         false : true;
6434                 dwell_overflow = wl_cfg80211_check_dwell_overflow(requested_dwell, dwell_jiffies);
6435         }
6436
6437         if (ack == false) {
6438                 WL_ERR(("Failed to send Action Frame(retry %d)\n", tx_retry));
6439         }
6440         WL_DBG(("Complete to send action frame\n"));
6441 exit:
6442         /* Clear SENDING_ACT_FRM after all sending af is done */
6443         wl_clr_drv_status(cfg, SENDING_ACT_FRM, dev);
6444
6445 #ifdef WL_CFG80211_SYNC_GON
6446         /* WAR: sometimes dongle does not keep the dwell time of 'actframe'.
6447          * if we coundn't get the next action response frame and dongle does not keep
6448          * the dwell time, go to listen state again to get next action response frame.
6449          */
6450         if (ack && config_af_params.extra_listen &&
6451                 wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM) &&
6452                 cfg->af_sent_channel == cfg->afx_hdl->my_listen_chan) {
6453                 s32 extar_listen_time;
6454
6455                 extar_listen_time = af_params->dwell_time -
6456                         jiffies_to_msecs(jiffies - cfg->af_tx_sent_jiffies);
6457
6458                 if (extar_listen_time > 50) {
6459                         wl_set_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, dev);
6460                         WL_DBG(("Wait more time! actual af time:%d,"
6461                                 "calculated extar listen:%d\n",
6462                                 af_params->dwell_time, extar_listen_time));
6463                         if (wl_cfgp2p_discover_listen(cfg, cfg->af_sent_channel,
6464                                 extar_listen_time + 100) == BCME_OK) {
6465                                 wait_for_completion_timeout(&cfg->wait_next_af,
6466                                         msecs_to_jiffies(extar_listen_time + 100 + 300));
6467                         }
6468                         wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, dev);
6469                 }
6470         }
6471 #endif /* WL_CFG80211_SYNC_GON */
6472         wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, dev);
6473
6474         if (cfg->afx_hdl->pending_tx_act_frm)
6475                 cfg->afx_hdl->pending_tx_act_frm = NULL;
6476
6477         WL_INFORM(("-- sending Action Frame is %s, listen chan: %d\n",
6478                 (ack) ? "Succeeded!!":"Failed!!", cfg->afx_hdl->my_listen_chan));
6479
6480
6481         /* if all done, turn mpc on again */
6482         if (config_af_params.mpc_onoff == 1) {
6483                 wldev_iovar_setint(dev, "mpc", 1);
6484         }
6485
6486         return ack;
6487 }
6488
6489 #define MAX_NUM_OF_ASSOCIATED_DEV       64
6490 static s32
6491 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
6492 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
6493         struct cfg80211_mgmt_tx_params *params, u64 *cookie)
6494 #else
6495 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
6496         struct ieee80211_channel *channel, bool offchan,
6497 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0))
6498         enum nl80211_channel_type channel_type,
6499         bool channel_type_valid,
6500 #endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0) */
6501         unsigned int wait, const u8* buf, size_t len,
6502 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
6503         bool no_cck,
6504 #endif
6505 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
6506         bool dont_wait_for_ack,
6507 #endif
6508         u64 *cookie)
6509 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
6510 {
6511         wl_action_frame_t *action_frame;
6512         wl_af_params_t *af_params;
6513         scb_val_t scb_val;
6514 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
6515         struct ieee80211_channel *channel = params->chan;
6516         const u8 *buf = params->buf;
6517         size_t len = params->len;
6518 #endif
6519         const struct ieee80211_mgmt *mgmt;
6520         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6521         struct net_device *dev = NULL;
6522         s32 err = BCME_OK;
6523         s32 bssidx = 0;
6524         u32 id;
6525         bool ack = false;
6526         s8 eabuf[ETHER_ADDR_STR_LEN];
6527
6528         WL_DBG(("Enter \n"));
6529
6530         dev = cfgdev_to_wlc_ndev(cfgdev, cfg);
6531
6532         if (!dev) {
6533                 WL_ERR(("dev is NULL\n"));
6534                 return -EINVAL;
6535         }
6536
6537         /* set bsscfg idx for iovar (wlan0: P2PAPI_BSSCFG_PRIMARY, p2p: P2PAPI_BSSCFG_DEVICE)   */
6538         if (discover_cfgdev(cfgdev, cfg)) {
6539                 if (!cfg->p2p_supported || !cfg->p2p) {
6540                         WL_ERR(("P2P doesn't setup completed yet\n"));
6541                         return -EINVAL;
6542                 }
6543                 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
6544         }
6545         else {
6546                 if ((bssidx = wl_get_bssidx_by_wdev(cfg, cfgdev_to_wdev(cfgdev))) < 0) {
6547                         WL_ERR(("Find p2p index failed\n"));
6548                         return BCME_ERROR;
6549                 }
6550         }
6551
6552         WL_DBG(("TX target bssidx=%d\n", bssidx));
6553
6554         if (p2p_is_on(cfg)) {
6555                 /* Suspend P2P discovery search-listen to prevent it from changing the
6556                  * channel.
6557                  */
6558                 if ((err = wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
6559                         WL_ERR(("Can not disable discovery mode\n"));
6560                         return -EFAULT;
6561                 }
6562         }
6563         *cookie = 0;
6564         id = cfg->send_action_id++;
6565         if (id == 0)
6566                 id = cfg->send_action_id++;
6567         *cookie = id;
6568         mgmt = (const struct ieee80211_mgmt *)buf;
6569         if (ieee80211_is_mgmt(mgmt->frame_control)) {
6570                 if (ieee80211_is_probe_resp(mgmt->frame_control)) {
6571                         s32 ie_offset =  DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
6572                         s32 ie_len = len - ie_offset;
6573                         if ((dev == bcmcfg_to_prmry_ndev(cfg)) && cfg->p2p) {
6574                                 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
6575                         }
6576                         wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
6577                                 VNDR_IE_PRBRSP_FLAG, (const u8 *)(buf + ie_offset), ie_len);
6578                         cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
6579 #if defined(P2P_IE_MISSING_FIX)
6580                         if (!cfg->p2p_prb_noti) {
6581                                 cfg->p2p_prb_noti = true;
6582                                 WL_DBG(("%s: TX 802_1X Probe Response first time.\n",
6583                                         __FUNCTION__));
6584                         }
6585 #endif
6586                         goto exit;
6587                 } else if (ieee80211_is_disassoc(mgmt->frame_control) ||
6588                         ieee80211_is_deauth(mgmt->frame_control)) {
6589                         char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
6590                                 sizeof(struct ether_addr) + sizeof(uint)] = {0};
6591                         int num_associated = 0;
6592                         struct maclist *assoc_maclist = (struct maclist *)mac_buf;
6593                         if (!bcmp((const uint8 *)BSSID_BROADCAST,
6594                                 (const struct ether_addr *)mgmt->da, ETHER_ADDR_LEN)) {
6595                                 assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
6596                                 err = wldev_ioctl(dev, WLC_GET_ASSOCLIST,
6597                                         assoc_maclist, sizeof(mac_buf), false);
6598                                 if (err < 0)
6599                                         WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
6600                                 else
6601                                         num_associated = assoc_maclist->count;
6602                         }
6603                         memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN);
6604                         scb_val.val = mgmt->u.disassoc.reason_code;
6605                         err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
6606                                 sizeof(scb_val_t), true);
6607                         if (err < 0)
6608                                 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON error %d\n", err));
6609                         WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
6610                                 bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf),
6611                                 scb_val.val));
6612
6613                         if (num_associated > 0 && ETHER_ISBCAST(mgmt->da))
6614                                 wl_delay(400);
6615
6616                         cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
6617                         goto exit;
6618
6619                 } else if (ieee80211_is_action(mgmt->frame_control)) {
6620                         /* Abort the dwell time of any previous off-channel
6621                         * action frame that may be still in effect.  Sending
6622                         * off-channel action frames relies on the driver's
6623                         * scan engine.  If a previous off-channel action frame
6624                         * tx is still in progress (including the dwell time),
6625                         * then this new action frame will not be sent out.
6626                         */
6627 /* Do not abort scan for VSDB. Scan will be aborted in firmware if necessary.
6628  * And previous off-channel action frame must be ended before new af tx.
6629  */
6630 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
6631                         wl_notify_escan_complete(cfg, dev, true, true);
6632 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
6633                 }
6634
6635         } else {
6636                 WL_ERR(("Driver only allows MGMT packet type\n"));
6637                 goto exit;
6638         }
6639
6640         af_params = (wl_af_params_t *) kzalloc(WL_WIFI_AF_PARAMS_SIZE, GFP_KERNEL);
6641
6642         if (af_params == NULL)
6643         {
6644                 WL_ERR(("unable to allocate frame\n"));
6645                 return -ENOMEM;
6646         }
6647
6648         action_frame = &af_params->action_frame;
6649
6650         /* Add the packet Id */
6651         action_frame->packetId = *cookie;
6652         WL_DBG(("action frame %d\n", action_frame->packetId));
6653         /* Add BSSID */
6654         memcpy(&action_frame->da, &mgmt->da[0], ETHER_ADDR_LEN);
6655         memcpy(&af_params->BSSID, &mgmt->bssid[0], ETHER_ADDR_LEN);
6656
6657         /* Add the length exepted for 802.11 header  */
6658         action_frame->len = len - DOT11_MGMT_HDR_LEN;
6659         WL_DBG(("action_frame->len: %d\n", action_frame->len));
6660
6661         /* Add the channel */
6662         af_params->channel =
6663                 ieee80211_frequency_to_channel(channel->center_freq);
6664         /* Save listen_chan for searching common channel */
6665         cfg->afx_hdl->peer_listen_chan = af_params->channel;
6666         WL_DBG(("channel from upper layer %d\n", cfg->afx_hdl->peer_listen_chan));
6667
6668 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
6669         af_params->dwell_time = params->wait;
6670 #else
6671         af_params->dwell_time = wait;
6672 #endif
6673
6674         memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len);
6675
6676         ack = wl_cfg80211_send_action_frame(wiphy, dev, cfgdev, af_params,
6677                 action_frame, action_frame->len, bssidx);
6678         cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, ack, GFP_KERNEL);
6679
6680         kfree(af_params);
6681 exit:
6682         return err;
6683 }
6684
6685
6686 static void
6687 wl_cfg80211_mgmt_frame_register(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
6688         u16 frame_type, bool reg)
6689 {
6690
6691         WL_DBG(("frame_type: %x, reg: %d\n", frame_type, reg));
6692
6693         if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
6694                 return;
6695
6696         return;
6697 }
6698
6699
6700 static s32
6701 wl_cfg80211_change_bss(struct wiphy *wiphy,
6702         struct net_device *dev,
6703         struct bss_parameters *params)
6704 {
6705         s32 err = 0;
6706         s32 ap_isolate = 0;
6707
6708         if (params->use_cts_prot >= 0) {
6709         }
6710
6711         if (params->use_short_preamble >= 0) {
6712         }
6713
6714         if (params->use_short_slot_time >= 0) {
6715         }
6716
6717         if (params->basic_rates) {
6718         }
6719
6720         if (params->ap_isolate >= 0) {
6721                 ap_isolate = params->ap_isolate;
6722                 err = wldev_iovar_setint(dev, "ap_isolate", ap_isolate);
6723                 if (unlikely(err))
6724                 {
6725                         WL_ERR(("set ap_isolate Error (%d)\n", err));
6726                 }
6727         }
6728
6729         if (params->ht_opmode >= 0) {
6730         }
6731
6732
6733         return 0;
6734 }
6735
6736 static s32
6737 wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
6738         struct ieee80211_channel *chan,
6739         enum nl80211_channel_type channel_type)
6740 {
6741         s32 _chan;
6742         chanspec_t chspec = 0;
6743         chanspec_t fw_chspec = 0;
6744         u32 bw = WL_CHANSPEC_BW_20;
6745 #ifdef WL11ULB
6746         u32 ulb_bw = wl_cfg80211_get_ulb_bw(dev->ieee80211_ptr);
6747 #endif /* WL11ULB */
6748
6749         s32 err = BCME_OK;
6750         s32 bw_cap = 0;
6751         struct {
6752                 u32 band;
6753                 u32 bw_cap;
6754         } param = {0, 0};
6755         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6756 #ifdef CUSTOM_SET_CPUCORE
6757         dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
6758 #endif /* CUSTOM_SET_CPUCORE */
6759
6760         dev = ndev_to_wlc_ndev(dev, cfg);
6761         _chan = ieee80211_frequency_to_channel(chan->center_freq);
6762         printf("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
6763                 dev->ifindex, channel_type, _chan);
6764
6765
6766 #ifdef WL11ULB
6767         if (ulb_bw) {
6768                 WL_DBG(("[ULB] setting AP/GO BW to ulb_bw 0x%x \n", ulb_bw));
6769                 bw = wl_cfg80211_ulbbw_to_ulbchspec(ulb_bw);
6770                 goto set_channel;
6771         }
6772 #endif /* WL11ULB */
6773         if (chan->band == IEEE80211_BAND_5GHZ) {
6774                 param.band = WLC_BAND_5G;
6775                 err = wldev_iovar_getbuf(dev, "bw_cap", &param, sizeof(param),
6776                         cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
6777                 if (err) {
6778                         if (err != BCME_UNSUPPORTED) {
6779                                 WL_ERR(("bw_cap failed, %d\n", err));
6780                                 return err;
6781                         } else {
6782                                 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
6783                                 if (err) {
6784                                         WL_ERR(("error get mimo_bw_cap (%d)\n", err));
6785                                 }
6786                                 if (bw_cap != WLC_N_BW_20ALL)
6787                                         bw = WL_CHANSPEC_BW_40;
6788                         }
6789                 } else {
6790                         if (WL_BW_CAP_80MHZ(cfg->ioctl_buf[0]))
6791                                 bw = WL_CHANSPEC_BW_80;
6792                         else if (WL_BW_CAP_40MHZ(cfg->ioctl_buf[0]))
6793                                 bw = WL_CHANSPEC_BW_40;
6794                         else
6795                                 bw = WL_CHANSPEC_BW_20;
6796
6797                 }
6798
6799         } else if (chan->band == IEEE80211_BAND_2GHZ)
6800                 bw = WL_CHANSPEC_BW_20;
6801 set_channel:
6802         chspec = wf_channel2chspec(_chan, bw);
6803         if (wf_chspec_valid(chspec)) {
6804                 fw_chspec = wl_chspec_host_to_driver(chspec);
6805                 if (fw_chspec != INVCHANSPEC) {
6806                         if ((err = wldev_iovar_setint(dev, "chanspec",
6807                                 fw_chspec)) == BCME_BADCHAN) {
6808                                 if (bw == WL_CHANSPEC_BW_80)
6809                                         goto change_bw;
6810                                 err = wldev_ioctl(dev, WLC_SET_CHANNEL,
6811                                         &_chan, sizeof(_chan), true);
6812                                 if (err < 0) {
6813                                         WL_ERR(("WLC_SET_CHANNEL error %d"
6814                                         "chip may not be supporting this channel\n", err));
6815                                 }
6816                         } else if (err) {
6817                                 WL_ERR(("failed to set chanspec error %d\n", err));
6818                         }
6819                 } else {
6820                         WL_ERR(("failed to convert host chanspec to fw chanspec\n"));
6821                         err = BCME_ERROR;
6822                 }
6823         } else {
6824 change_bw:
6825                 if (bw == WL_CHANSPEC_BW_80)
6826                         bw = WL_CHANSPEC_BW_40;
6827                 else if (bw == WL_CHANSPEC_BW_40)
6828                         bw = WL_CHANSPEC_BW_20;
6829                 else
6830                         bw = 0;
6831                 if (bw)
6832                         goto set_channel;
6833                 WL_ERR(("Invalid chanspec 0x%x\n", chspec));
6834                 err = BCME_ERROR;
6835         }
6836 #ifdef CUSTOM_SET_CPUCORE
6837         if (dhd->op_mode == DHD_FLAG_HOSTAP_MODE) {
6838                 WL_DBG(("SoftAP mode do not need to set cpucore\n"));
6839         } else if (chspec & WL_CHANSPEC_BW_80) {
6840                 /* SoftAp only mode do not need to set cpucore */
6841                 if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) &&
6842                         dev != bcmcfg_to_prmry_ndev(cfg)) {
6843                         /* Soft AP on virtual Iface (AP+STA case) */
6844                         dhd->chan_isvht80 |= DHD_FLAG_HOSTAP_MODE;
6845                         dhd_set_cpucore(dhd, TRUE);
6846                 } else if (is_p2p_group_iface(dev->ieee80211_ptr)) {
6847                         /* If P2P IF is vht80 */
6848                         dhd->chan_isvht80 |= DHD_FLAG_P2P_MODE;
6849                         dhd_set_cpucore(dhd, TRUE);
6850                 }
6851         }
6852 #endif /* CUSTOM_SET_CPUCORE */
6853         if (!err && (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP)) {
6854                 /* Update AP/GO operating channel */
6855                 cfg->ap_oper_channel = _chan;
6856         }
6857         return err;
6858 }
6859
6860 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
6861 struct net_device *
6862 wl_cfg80211_get_remain_on_channel_ndev(struct bcm_cfg80211 *cfg)
6863 {
6864         struct net_info *_net_info, *next;
6865         list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
6866                 if (_net_info->ndev &&
6867                         test_bit(WL_STATUS_REMAINING_ON_CHANNEL, &_net_info->sme_state))
6868                         return _net_info->ndev;
6869         }
6870         return NULL;
6871 }
6872 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
6873
6874 static s32
6875 wl_validate_opensecurity(struct net_device *dev, s32 bssidx, bool privacy)
6876 {
6877         s32 err = BCME_OK;
6878         u32 wpa_val;
6879         s32 wsec = 0;
6880
6881         /* set auth */
6882         err = wldev_iovar_setint_bsscfg(dev, "auth", 0, bssidx);
6883         if (err < 0) {
6884                 WL_ERR(("auth error %d\n", err));
6885                 return BCME_ERROR;
6886         }
6887
6888         if (privacy) {
6889                 /* If privacy bit is set in open mode, then WEP would be enabled */
6890                 wsec = WEP_ENABLED;
6891                 WL_DBG(("Setting wsec to %d for WEP \n", wsec));
6892         }
6893
6894         /* set wsec */
6895         err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
6896         if (err < 0) {
6897                 WL_ERR(("wsec error %d\n", err));
6898                 return BCME_ERROR;
6899         }
6900
6901         /* set upper-layer auth */
6902         if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_ADHOC)
6903                 wpa_val = WPA_AUTH_NONE;
6904         else
6905                 wpa_val = WPA_AUTH_DISABLED;
6906         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_val, bssidx);
6907         if (err < 0) {
6908                 WL_ERR(("wpa_auth error %d\n", err));
6909                 return BCME_ERROR;
6910         }
6911
6912         return 0;
6913 }
6914
6915 static s32
6916 wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
6917 {
6918         s32 len = 0;
6919         s32 err = BCME_OK;
6920         u16 auth = 0; /* d11 open authentication */
6921         u32 wsec;
6922         u32 pval = 0;
6923         u32 gval = 0;
6924         u32 wpa_auth = 0;
6925         wpa_suite_mcast_t *mcast;
6926         wpa_suite_ucast_t *ucast;
6927         wpa_suite_auth_key_mgmt_t *mgmt;
6928         wpa_pmkid_list_t *pmkid;
6929         int cnt = 0;
6930
6931         u16 suite_count;
6932         u8 rsn_cap[2];
6933         u32 wme_bss_disable;
6934
6935         if (wpa2ie == NULL)
6936                 goto exit;
6937
6938         WL_DBG(("Enter \n"));
6939         len =  wpa2ie->len - WPA2_VERSION_LEN;
6940         /* check the mcast cipher */
6941         mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
6942         switch (mcast->type) {
6943                 case WPA_CIPHER_NONE:
6944                         gval = 0;
6945                         break;
6946                 case WPA_CIPHER_WEP_40:
6947                 case WPA_CIPHER_WEP_104:
6948                         gval = WEP_ENABLED;
6949                         break;
6950                 case WPA_CIPHER_TKIP:
6951                         gval = TKIP_ENABLED;
6952                         break;
6953                 case WPA_CIPHER_AES_CCM:
6954                         gval = AES_ENABLED;
6955                         break;
6956                 default:
6957                         WL_ERR(("No Security Info\n"));
6958                         break;
6959         }
6960         if ((len -= WPA_SUITE_LEN) <= 0)
6961                 return BCME_BADLEN;
6962
6963         /* check the unicast cipher */
6964         ucast = (wpa_suite_ucast_t *)&mcast[1];
6965         suite_count = ltoh16_ua(&ucast->count);
6966         switch (ucast->list[0].type) {
6967                 case WPA_CIPHER_NONE:
6968                         pval = 0;
6969                         break;
6970                 case WPA_CIPHER_WEP_40:
6971                 case WPA_CIPHER_WEP_104:
6972                         pval = WEP_ENABLED;
6973                         break;
6974                 case WPA_CIPHER_TKIP:
6975                         pval = TKIP_ENABLED;
6976                         break;
6977                 case WPA_CIPHER_AES_CCM:
6978                         pval = AES_ENABLED;
6979                         break;
6980                 default:
6981                         WL_ERR(("No Security Info\n"));
6982         }
6983         if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
6984                 return BCME_BADLEN;
6985
6986         /* FOR WPS , set SEC_OW_ENABLED */
6987         wsec = (pval | gval | SES_OW_ENABLED);
6988         /* check the AKM */
6989         mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
6990         suite_count = cnt = ltoh16_ua(&mgmt->count);
6991         while (cnt--) {
6992                 switch (mgmt->list[cnt].type) {
6993                 case RSN_AKM_NONE:
6994                                 wpa_auth |= WPA_AUTH_NONE;
6995                         break;
6996                 case RSN_AKM_UNSPECIFIED:
6997                                 wpa_auth |= WPA2_AUTH_UNSPECIFIED;
6998                         break;
6999                 case RSN_AKM_PSK:
7000                                 wpa_auth |= WPA2_AUTH_PSK;
7001                                 break;
7002                 default:
7003                         WL_ERR(("No Key Mgmt Info\n"));
7004                 }
7005         }
7006
7007         if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
7008                 rsn_cap[0] = *(u8 *)&mgmt->list[suite_count];
7009                 rsn_cap[1] = *((u8 *)&mgmt->list[suite_count] + 1);
7010
7011                 if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
7012                         wme_bss_disable = 0;
7013                 } else {
7014                         wme_bss_disable = 1;
7015                 }
7016
7017
7018                 /* set wme_bss_disable to sync RSN Capabilities */
7019                 err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
7020                 if (err < 0) {
7021                         WL_ERR(("wme_bss_disable error %d\n", err));
7022                         return BCME_ERROR;
7023                 }
7024         } else {
7025                 WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
7026         }
7027
7028         len -= RSN_CAP_LEN;
7029         if (len >= WPA2_PMKID_COUNT_LEN) {
7030                 pmkid = (wpa_pmkid_list_t *)((u8 *)&mgmt->list[suite_count] + RSN_CAP_LEN);
7031                 cnt = ltoh16_ua(&pmkid->count);
7032                 if (cnt != 0) {
7033                         WL_ERR(("AP has non-zero PMKID count. Wrong!\n"));
7034                         return BCME_ERROR;
7035                 }
7036                 /* since PMKID cnt is known to be 0 for AP, */
7037                 /* so don't bother to send down this info to firmware */
7038         }
7039
7040
7041         /* set auth */
7042         err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
7043         if (err < 0) {
7044                 WL_ERR(("auth error %d\n", err));
7045                 return BCME_ERROR;
7046         }
7047
7048         /* set wsec */
7049         err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
7050         if (err < 0) {
7051                 WL_ERR(("wsec error %d\n", err));
7052                 return BCME_ERROR;
7053         }
7054
7055
7056         /* set upper-layer auth */
7057         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
7058         if (err < 0) {
7059                 WL_ERR(("wpa_auth error %d\n", err));
7060                 return BCME_ERROR;
7061         }
7062 exit:
7063         return 0;
7064 }
7065
7066 static s32
7067 wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx)
7068 {
7069         wpa_suite_mcast_t *mcast;
7070         wpa_suite_ucast_t *ucast;
7071         wpa_suite_auth_key_mgmt_t *mgmt;
7072         u16 auth = 0; /* d11 open authentication */
7073         u16 count;
7074         s32 err = BCME_OK;
7075         s32 len = 0;
7076         u32 i;
7077         u32 wsec;
7078         u32 pval = 0;
7079         u32 gval = 0;
7080         u32 wpa_auth = 0;
7081         u32 tmp = 0;
7082
7083         if (wpaie == NULL)
7084                 goto exit;
7085         WL_DBG(("Enter \n"));
7086         len = wpaie->length;    /* value length */
7087         len -= WPA_IE_TAG_FIXED_LEN;
7088         /* check for multicast cipher suite */
7089         if (len < WPA_SUITE_LEN) {
7090                 WL_INFORM(("no multicast cipher suite\n"));
7091                 goto exit;
7092         }
7093
7094         /* pick up multicast cipher */
7095         mcast = (wpa_suite_mcast_t *)&wpaie[1];
7096         len -= WPA_SUITE_LEN;
7097         if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
7098                 if (IS_WPA_CIPHER(mcast->type)) {
7099                         tmp = 0;
7100                         switch (mcast->type) {
7101                                 case WPA_CIPHER_NONE:
7102                                         tmp = 0;
7103                                         break;
7104                                 case WPA_CIPHER_WEP_40:
7105                                 case WPA_CIPHER_WEP_104:
7106                                         tmp = WEP_ENABLED;
7107                                         break;
7108                                 case WPA_CIPHER_TKIP:
7109                                         tmp = TKIP_ENABLED;
7110                                         break;
7111                                 case WPA_CIPHER_AES_CCM:
7112                                         tmp = AES_ENABLED;
7113                                         break;
7114                                 default:
7115                                         WL_ERR(("No Security Info\n"));
7116                         }
7117                         gval |= tmp;
7118                 }
7119         }
7120         /* Check for unicast suite(s) */
7121         if (len < WPA_IE_SUITE_COUNT_LEN) {
7122                 WL_INFORM(("no unicast suite\n"));
7123                 goto exit;
7124         }
7125         /* walk thru unicast cipher list and pick up what we recognize */
7126         ucast = (wpa_suite_ucast_t *)&mcast[1];
7127         count = ltoh16_ua(&ucast->count);
7128         len -= WPA_IE_SUITE_COUNT_LEN;
7129         for (i = 0; i < count && len >= WPA_SUITE_LEN;
7130                 i++, len -= WPA_SUITE_LEN) {
7131                 if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
7132                         if (IS_WPA_CIPHER(ucast->list[i].type)) {
7133                                 tmp = 0;
7134                                 switch (ucast->list[i].type) {
7135                                         case WPA_CIPHER_NONE:
7136                                                 tmp = 0;
7137                                                 break;
7138                                         case WPA_CIPHER_WEP_40:
7139                                         case WPA_CIPHER_WEP_104:
7140                                                 tmp = WEP_ENABLED;
7141                                                 break;
7142                                         case WPA_CIPHER_TKIP:
7143                                                 tmp = TKIP_ENABLED;
7144                                                 break;
7145                                         case WPA_CIPHER_AES_CCM:
7146                                                 tmp = AES_ENABLED;
7147                                                 break;
7148                                         default:
7149                                                 WL_ERR(("No Security Info\n"));
7150                                 }
7151                                 pval |= tmp;
7152                         }
7153                 }
7154         }
7155         len -= (count - i) * WPA_SUITE_LEN;
7156         /* Check for auth key management suite(s) */
7157         if (len < WPA_IE_SUITE_COUNT_LEN) {
7158                 WL_INFORM((" no auth key mgmt suite\n"));
7159                 goto exit;
7160         }
7161         /* walk thru auth management suite list and pick up what we recognize */
7162         mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
7163         count = ltoh16_ua(&mgmt->count);
7164         len -= WPA_IE_SUITE_COUNT_LEN;
7165         for (i = 0; i < count && len >= WPA_SUITE_LEN;
7166                 i++, len -= WPA_SUITE_LEN) {
7167                 if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
7168                         if (IS_WPA_AKM(mgmt->list[i].type)) {
7169                                 tmp = 0;
7170                                 switch (mgmt->list[i].type) {
7171                                         case RSN_AKM_NONE:
7172                                                 tmp = WPA_AUTH_NONE;
7173                                                 break;
7174                                         case RSN_AKM_UNSPECIFIED:
7175                                                 tmp = WPA_AUTH_UNSPECIFIED;
7176                                                 break;
7177                                         case RSN_AKM_PSK:
7178                                                 tmp = WPA_AUTH_PSK;
7179                                                 break;
7180                                         default:
7181                                                 WL_ERR(("No Key Mgmt Info\n"));
7182                                 }
7183                                 wpa_auth |= tmp;
7184                         }
7185                 }
7186
7187         }
7188         /* FOR WPS , set SEC_OW_ENABLED */
7189         wsec = (pval | gval | SES_OW_ENABLED);
7190         /* set auth */
7191         err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
7192         if (err < 0) {
7193                 WL_ERR(("auth error %d\n", err));
7194                 return BCME_ERROR;
7195         }
7196         /* set wsec */
7197         err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
7198         if (err < 0) {
7199                 WL_ERR(("wsec error %d\n", err));
7200                 return BCME_ERROR;
7201         }
7202         /* set upper-layer auth */
7203         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
7204         if (err < 0) {
7205                 WL_ERR(("wpa_auth error %d\n", err));
7206                 return BCME_ERROR;
7207         }
7208 exit:
7209         return 0;
7210 }
7211
7212
7213 static s32
7214 wl_cfg80211_bcn_validate_sec(
7215         struct net_device *dev,
7216         struct parsed_ies *ies,
7217         u32 dev_role,
7218         s32 bssidx,
7219         bool privacy)
7220 {
7221         struct bcm_cfg80211 *cfg = g_bcm_cfg;
7222         wl_cfgbss_t *bss = wl_get_cfgbss_by_wdev(cfg, dev->ieee80211_ptr);
7223
7224         if (!bss) {
7225                 WL_ERR(("cfgbss is NULL \n"));
7226                 return BCME_ERROR;
7227         }
7228
7229         if (dev_role == NL80211_IFTYPE_P2P_GO && (ies->wpa2_ie)) {
7230                 /* For P2P GO, the sec type is WPA2-PSK */
7231                 WL_DBG(("P2P GO: validating wpa2_ie"));
7232                 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0)
7233                         return BCME_ERROR;
7234
7235         } else if (dev_role == NL80211_IFTYPE_AP) {
7236
7237                 WL_DBG(("SoftAP: validating security"));
7238                 /* If wpa2_ie or wpa_ie is present validate it */
7239
7240                 if ((ies->wpa2_ie || ies->wpa_ie) &&
7241                         ((wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0 ||
7242                         wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0))) {
7243                         bss->security_mode = false;
7244                         return BCME_ERROR;
7245                 }
7246
7247                 bss->security_mode = true;
7248                 if (bss->rsn_ie) {
7249                         kfree(bss->rsn_ie);
7250                         bss->rsn_ie = NULL;
7251                 }
7252                 if (bss->wpa_ie) {
7253                         kfree(bss->wpa_ie);
7254                         bss->wpa_ie = NULL;
7255                 }
7256                 if (bss->wps_ie) {
7257                         kfree(bss->wps_ie);
7258                         bss->wps_ie = NULL;
7259                 }
7260                 if (ies->wpa_ie != NULL) {
7261                         /* WPAIE */
7262                         bss->rsn_ie = NULL;
7263                         bss->wpa_ie = kmemdup(ies->wpa_ie,
7264                                 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
7265                                 GFP_KERNEL);
7266                 } else if (ies->wpa2_ie != NULL) {
7267                         /* RSNIE */
7268                         bss->wpa_ie = NULL;
7269                         bss->rsn_ie = kmemdup(ies->wpa2_ie,
7270                                 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
7271                                 GFP_KERNEL);
7272                 }
7273                 if (!ies->wpa2_ie && !ies->wpa_ie) {
7274                         wl_validate_opensecurity(dev, bssidx, privacy);
7275                         bss->security_mode = false;
7276                 }
7277
7278                 if (ies->wps_ie) {
7279                         bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
7280                 }
7281         }
7282
7283         return 0;
7284
7285 }
7286
7287 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
7288 static s32 wl_cfg80211_bcn_set_params(
7289         struct cfg80211_ap_settings *info,
7290         struct net_device *dev,
7291         u32 dev_role, s32 bssidx)
7292 {
7293         struct bcm_cfg80211 *cfg = g_bcm_cfg;
7294         s32 err = BCME_OK;
7295
7296         WL_DBG(("interval (%d) \ndtim_period (%d) \n",
7297                 info->beacon_interval, info->dtim_period));
7298
7299         if (info->beacon_interval) {
7300                 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
7301                         &info->beacon_interval, sizeof(s32), true)) < 0) {
7302                         WL_ERR(("Beacon Interval Set Error, %d\n", err));
7303                         return err;
7304                 }
7305         }
7306
7307         if (info->dtim_period) {
7308                 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
7309                         &info->dtim_period, sizeof(s32), true)) < 0) {
7310                         WL_ERR(("DTIM Interval Set Error, %d\n", err));
7311                         return err;
7312                 }
7313         }
7314
7315         if ((info->ssid) && (info->ssid_len > 0) &&
7316                 (info->ssid_len <= 32)) {
7317                 WL_DBG(("SSID (%s) len:%zd \n", info->ssid, info->ssid_len));
7318                 if (dev_role == NL80211_IFTYPE_AP) {
7319                         /* Store the hostapd SSID */
7320                         memset(cfg->hostapd_ssid.SSID, 0x00, 32);
7321                         memcpy(cfg->hostapd_ssid.SSID, info->ssid, info->ssid_len);
7322                         cfg->hostapd_ssid.SSID_len = info->ssid_len;
7323                 } else {
7324                                 /* P2P GO */
7325                         memset(cfg->p2p->ssid.SSID, 0x00, 32);
7326                         memcpy(cfg->p2p->ssid.SSID, info->ssid, info->ssid_len);
7327                         cfg->p2p->ssid.SSID_len = info->ssid_len;
7328                 }
7329         }
7330
7331         if (info->hidden_ssid) {
7332                 if ((err = wldev_iovar_setint(dev, "closednet", 1)) < 0)
7333                         WL_ERR(("failed to set hidden : %d\n", err));
7334                 WL_DBG(("hidden_ssid_enum_val: %d \n", info->hidden_ssid));
7335         }
7336
7337         return err;
7338 }
7339 #endif 
7340
7341 static s32
7342 wl_cfg80211_parse_ies(u8 *ptr, u32 len, struct parsed_ies *ies)
7343 {
7344         s32 err = BCME_OK;
7345
7346         memset(ies, 0, sizeof(struct parsed_ies));
7347
7348         /* find the WPSIE */
7349         if ((ies->wps_ie = wl_cfgp2p_find_wpsie(ptr, len)) != NULL) {
7350                 WL_DBG(("WPSIE in beacon \n"));
7351                 ies->wps_ie_len = ies->wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
7352         } else {
7353                 WL_DBG(("No WPSIE in beacon \n"));
7354         }
7355
7356         /* find the RSN_IE */
7357         if ((ies->wpa2_ie = bcm_parse_tlvs(ptr, len,
7358                 DOT11_MNG_RSN_ID)) != NULL) {
7359                 WL_DBG((" WPA2 IE found\n"));
7360                 ies->wpa2_ie_len = ies->wpa2_ie->len;
7361         }
7362
7363         /* find the WPA_IE */
7364         if ((ies->wpa_ie = wl_cfgp2p_find_wpaie(ptr, len)) != NULL) {
7365                 WL_DBG((" WPA found\n"));
7366                 ies->wpa_ie_len = ies->wpa_ie->length;
7367         }
7368
7369         return err;
7370
7371 }
7372
7373 #define MAX_AP_LINK_WAIT_TIME   10000
7374 static s32
7375 wl_cfg80211_bcn_bringup_ap(
7376         struct net_device *dev,
7377         struct parsed_ies *ies,
7378         u32 dev_role, s32 bssidx)
7379 {
7380         struct bcm_cfg80211 *cfg = g_bcm_cfg;
7381         struct wl_join_params join_params;
7382         struct wiphy *wiphy;
7383         bool is_bssup = false;
7384         s32 infra = 1;
7385         s32 join_params_size = 0;
7386         s32 ap = 1;
7387         s32 pm;
7388         s32 wsec;
7389 #ifdef SOFTAP_UAPSD_OFF
7390         uint32 wme_apsd = 0;
7391 #endif /* SOFTAP_UAPSD_OFF */
7392         s32 err = BCME_OK;
7393         s32 is_rsdb_supported = BCME_ERROR;
7394         u32 timeout;
7395 #if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
7396         dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
7397 #endif /* DHD_DEBUG && BCMPCIE && DHD_FW_COREDUMP */
7398
7399         is_rsdb_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_RSDB_MODE);
7400         if (is_rsdb_supported < 0)
7401                 return (-ENODEV);
7402
7403         WL_DBG(("Enter dev_role:%d bssidx:%d\n", dev_role, bssidx));
7404
7405         /* Common code for SoftAP and P2P GO */
7406         wiphy = bcmcfg_to_wiphy(cfg);
7407         if (wl_check_dongle_idle(wiphy) != TRUE) {
7408                 WL_ERR(("FW is busy to add interface"));
7409                 return -EINVAL;
7410         }
7411         wldev_iovar_setint(dev, "mpc", 0);
7412
7413         wl_clr_drv_status(cfg, AP_CREATED, dev);
7414
7415         if (dev_role == NL80211_IFTYPE_P2P_GO) {
7416                 is_bssup = wl_cfgp2p_bss_isup(dev, bssidx);
7417                 if (!is_bssup && (ies->wpa2_ie != NULL)) {
7418
7419                         err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
7420                         if (err < 0) {
7421                                 WL_ERR(("SET INFRA error %d\n", err));
7422                                 goto exit;
7423                         }
7424
7425                         err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &cfg->p2p->ssid,
7426                                 sizeof(cfg->p2p->ssid), cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
7427                                 bssidx, &cfg->ioctl_buf_sync);
7428                         if (err < 0) {
7429                                 WL_ERR(("GO SSID setting error %d\n", err));
7430                                 goto exit;
7431                         }
7432
7433                         /* Do abort scan before creating GO */
7434                         wl_cfg80211_scan_abort(cfg);
7435
7436                         if ((err = wl_cfgp2p_bss(cfg, dev, bssidx, 1)) < 0) {
7437                                 WL_ERR(("GO Bring up error %d\n", err));
7438                                 goto exit;
7439                         }
7440                 } else
7441                         WL_DBG(("Bss is already up\n"));
7442         } else if ((dev_role == NL80211_IFTYPE_AP) &&
7443                 (wl_get_drv_status(cfg, AP_CREATING, dev))) {
7444
7445                 /* Device role SoftAP */
7446                 WL_DBG(("Creating AP bssidx:%d dev_role:%d\n", bssidx, dev_role));
7447
7448                 /* Clear the status bit after use */
7449                 wl_clr_drv_status(cfg, AP_CREATING, dev);
7450
7451                 /* AP on primary Interface */
7452                 if (bssidx == 0) {
7453                         if (is_rsdb_supported) {
7454                                 if ((err = wl_cfg80211_add_del_bss(cfg, dev, bssidx,
7455                                         NL80211_IFTYPE_AP, 0, NULL)) < 0) {
7456                                         WL_ERR(("wl add_del_bss returned error:%d\n", err));
7457                                         goto exit;
7458                                 }
7459                         } else if (is_rsdb_supported == 0) {
7460                         /* AP mode switch not supported. Try setting up AP explicitly */
7461                                 err = wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), true);
7462                                 if (err < 0) {
7463                                         WL_ERR(("WLC_DOWN error %d\n", err));
7464                                         goto exit;
7465                                 }
7466                                 err = wldev_iovar_setint(dev, "apsta", 0);
7467                                 if (err < 0) {
7468                                         WL_ERR(("wl apsta 0 error %d\n", err));
7469                                         goto exit;
7470                                 }
7471
7472                                 if ((err = wldev_ioctl(dev,
7473                                         WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
7474                                         WL_ERR(("setting AP mode failed %d \n", err));
7475                                         goto exit;
7476                                 }
7477
7478                         }
7479
7480                         pm = 0;
7481                         if ((err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true)) != 0) {
7482                                 WL_ERR(("wl PM 0 returned error:%d\n", err));
7483                                 goto exit;
7484                         }
7485
7486                         err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
7487                         if (err < 0) {
7488                                 WL_ERR(("SET INFRA error %d\n", err));
7489                                 goto exit;
7490                         }
7491                 } else if (cfg->cfgdev_bssidx && (bssidx == cfg->cfgdev_bssidx)) {
7492
7493                         WL_DBG(("Bringup SoftAP on virtual Interface bssidx:%d \n", bssidx));
7494
7495                         if ((err = wl_cfg80211_add_del_bss(cfg, dev,
7496                                 bssidx, NL80211_IFTYPE_AP, 0, NULL)) < 0) {
7497                                 WL_ERR(("wl bss ap returned error:%d\n", err));
7498                                 goto exit;
7499                         }
7500
7501                 }
7502
7503 #ifdef SOFTAP_UAPSD_OFF
7504                 err = wldev_iovar_setbuf_bsscfg(dev, "wme_apsd", &wme_apsd, sizeof(wme_apsd),
7505                         cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync);
7506                 if (err < 0) {
7507                         WL_ERR(("failed to disable uapsd, error=%d\n", err));
7508                 }
7509 #endif /* SOFTAP_UAPSD_OFF */
7510
7511                 err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
7512                 if (unlikely(err)) {
7513                         WL_ERR(("WLC_UP error (%d)\n", err));
7514                         goto exit;
7515                 }
7516
7517                 err = wldev_iovar_getint(dev, "wsec", (s32 *)&wsec);
7518                 if (unlikely(err)) {
7519                         WL_ERR(("Could not get wsec %d\n", err));
7520                         goto exit;
7521                 }
7522                 if ((wsec == WEP_ENABLED) && cfg->wep_key.len) {
7523                         WL_DBG(("Applying buffered WEP KEY \n"));
7524                         err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &cfg->wep_key,
7525                                 sizeof(struct wl_wsec_key), cfg->ioctl_buf,
7526                                 WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
7527                         /* clear the key after use */
7528                         memset(&cfg->wep_key, 0, sizeof(struct wl_wsec_key));
7529                         if (unlikely(err)) {
7530                                 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
7531                                 goto exit;
7532                         }
7533                 }
7534
7535                 memset(&join_params, 0, sizeof(join_params));
7536                 /* join parameters starts with ssid */
7537                 join_params_size = sizeof(join_params.ssid);
7538                 memcpy(join_params.ssid.SSID, cfg->hostapd_ssid.SSID,
7539                         cfg->hostapd_ssid.SSID_len);
7540                 join_params.ssid.SSID_len = htod32(cfg->hostapd_ssid.SSID_len);
7541
7542                 /* create softap */
7543                 if ((err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
7544                         join_params_size, true)) != 0) {
7545                         WL_ERR(("SoftAP/GO set ssid failed! \n"));
7546                         goto exit;
7547                 } else {
7548                         WL_DBG((" SoftAP SSID \"%s\" \n", join_params.ssid.SSID));
7549                 }
7550
7551                 if (bssidx != 0) {
7552                         /* AP on Virtual Interface */
7553                         if ((err = wl_cfgp2p_bss(cfg, dev, bssidx, 1)) < 0) {
7554                                 WL_ERR(("GO Bring up error %d\n", err));
7555                                 goto exit;
7556                         }
7557                 }
7558
7559         }
7560         /* Wait for Linkup event to mark successful AP/GO bring up */
7561         timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
7562                 wl_get_drv_status(cfg, AP_CREATED, dev), msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME));
7563         if (timeout <= 0 || !wl_get_drv_status(cfg, AP_CREATED, dev)) {
7564                 WL_ERR(("Link up didn't come for AP interface. AP/GO creation failed! \n"));
7565 #if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
7566                 if (dhdp->memdump_enabled) {
7567                         dhdp->memdump_type = DUMP_TYPE_AP_LINKUP_FAILURE;
7568                         dhd_bus_mem_dump(dhdp);
7569                 }
7570 #endif /* DHD_DEBUG && BCMPCIE && DHD_FW_COREDUMP */
7571                 err = -ENODEV;
7572                 goto exit;
7573         }
7574
7575 exit:
7576         if (cfg->wep_key.len)
7577                 memset(&cfg->wep_key, 0, sizeof(struct wl_wsec_key));
7578         return err;
7579 }
7580
7581 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
7582 s32
7583 wl_cfg80211_parse_ap_ies(
7584         struct net_device *dev,
7585         struct cfg80211_beacon_data *info,
7586         struct parsed_ies *ies)
7587 {
7588         struct parsed_ies prb_ies;
7589         struct bcm_cfg80211 *cfg = g_bcm_cfg;
7590         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
7591         u8 *vndr = NULL;
7592         u32 vndr_ie_len = 0;
7593         s32 err = BCME_OK;
7594
7595         /* Parse Beacon IEs */
7596         if (wl_cfg80211_parse_ies((u8 *)info->tail,
7597                 info->tail_len, ies) < 0) {
7598                 WL_ERR(("Beacon get IEs failed \n"));
7599                 err = -EINVAL;
7600                 goto fail;
7601         }
7602
7603         vndr = (u8 *)info->proberesp_ies;
7604         vndr_ie_len = info->proberesp_ies_len;
7605
7606         if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
7607                 /* SoftAP mode */
7608                 struct ieee80211_mgmt *mgmt;
7609                 mgmt = (struct ieee80211_mgmt *)info->probe_resp;
7610                 if (mgmt != NULL) {
7611                         vndr = (u8 *)&mgmt->u.probe_resp.variable;
7612                         vndr_ie_len = info->probe_resp_len -
7613                                 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
7614                 }
7615         }
7616
7617         /* Parse Probe Response IEs */
7618         if (wl_cfg80211_parse_ies(vndr, vndr_ie_len, &prb_ies) < 0) {
7619                 WL_ERR(("PROBE RESP get IEs failed \n"));
7620                 err = -EINVAL;
7621         }
7622
7623 fail:
7624
7625         return err;
7626 }
7627
7628 s32
7629 wl_cfg80211_set_ies(
7630         struct net_device *dev,
7631         struct cfg80211_beacon_data *info,
7632         s32 bssidx)
7633 {
7634         struct bcm_cfg80211 *cfg = g_bcm_cfg;
7635         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
7636         u8 *vndr = NULL;
7637         u32 vndr_ie_len = 0;
7638         s32 err = BCME_OK;
7639
7640         /* Set Beacon IEs to FW */
7641         if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
7642                 VNDR_IE_BEACON_FLAG, (const u8 *)info->tail,
7643                 info->tail_len)) < 0) {
7644                 WL_ERR(("Set Beacon IE Failed \n"));
7645         } else {
7646                 WL_DBG(("Applied Vndr IEs for Beacon \n"));
7647         }
7648
7649         vndr = (u8 *)info->proberesp_ies;
7650         vndr_ie_len = info->proberesp_ies_len;
7651
7652         if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
7653                 /* SoftAP mode */
7654                 struct ieee80211_mgmt *mgmt;
7655                 mgmt = (struct ieee80211_mgmt *)info->probe_resp;
7656                 if (mgmt != NULL) {
7657                         vndr = (u8 *)&mgmt->u.probe_resp.variable;
7658                         vndr_ie_len = info->probe_resp_len -
7659                                 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
7660                 }
7661         }
7662
7663         /* Set Probe Response IEs to FW */
7664         if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
7665                 VNDR_IE_PRBRSP_FLAG, vndr, vndr_ie_len)) < 0) {
7666                 WL_ERR(("Set Probe Resp IE Failed \n"));
7667         } else {
7668                 WL_DBG(("Applied Vndr IEs for Probe Resp \n"));
7669         }
7670
7671         return err;
7672 }
7673 #endif 
7674
7675 static s32 wl_cfg80211_hostapd_sec(
7676         struct net_device *dev,
7677         struct parsed_ies *ies,
7678         s32 bssidx)
7679 {
7680         bool update_bss = 0;
7681         struct bcm_cfg80211 *cfg = g_bcm_cfg;
7682         wl_cfgbss_t *bss = wl_get_cfgbss_by_wdev(cfg, dev->ieee80211_ptr);
7683
7684         if (!bss) {
7685                 WL_ERR(("cfgbss is NULL \n"));
7686                 return -EINVAL;
7687         }
7688
7689         if (ies->wps_ie) {
7690                 if (bss->wps_ie &&
7691                         memcmp(bss->wps_ie, ies->wps_ie, ies->wps_ie_len)) {
7692                         WL_DBG((" WPS IE is changed\n"));
7693                         kfree(bss->wps_ie);
7694                         bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
7695                 } else if (bss->wps_ie == NULL) {
7696                         WL_DBG((" WPS IE is added\n"));
7697                         bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
7698                 }
7699
7700                 if ((ies->wpa_ie != NULL || ies->wpa2_ie != NULL)) {
7701                         if (!bss->security_mode) {
7702                                 /* change from open mode to security mode */
7703                                 update_bss = true;
7704                                 if (ies->wpa_ie != NULL) {
7705                                         bss->wpa_ie = kmemdup(ies->wpa_ie,
7706                                         ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
7707                                         GFP_KERNEL);
7708                                 } else {
7709                                         bss->rsn_ie = kmemdup(ies->wpa2_ie,
7710                                         ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
7711                                         GFP_KERNEL);
7712                                 }
7713                         } else if (bss->wpa_ie) {
7714                                 /* change from WPA2 mode to WPA mode */
7715                                 if (ies->wpa_ie != NULL) {
7716                                         update_bss = true;
7717                                         kfree(bss->rsn_ie);
7718                                         bss->rsn_ie = NULL;
7719                                         bss->wpa_ie = kmemdup(ies->wpa_ie,
7720                                         ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
7721                                         GFP_KERNEL);
7722                                 } else if (memcmp(bss->rsn_ie,
7723                                         ies->wpa2_ie, ies->wpa2_ie->len
7724                                         + WPA_RSN_IE_TAG_FIXED_LEN)) {
7725                                         update_bss = true;
7726                                         kfree(bss->rsn_ie);
7727                                         bss->rsn_ie = kmemdup(ies->wpa2_ie,
7728                                         ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
7729                                         GFP_KERNEL);
7730                                         bss->wpa_ie = NULL;
7731                                 }
7732                         }
7733                         if (update_bss) {
7734                                 bss->security_mode = true;
7735                                 wl_cfgp2p_bss(cfg, dev, bssidx, 0);
7736                                 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0 ||
7737                                         wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0) {
7738                                         return BCME_ERROR;
7739                                 }
7740                                 wl_cfgp2p_bss(cfg, dev, bssidx, 1);
7741                         }
7742                 }
7743         } else {
7744                 WL_ERR(("No WPSIE in beacon \n"));
7745         }
7746         return 0;
7747 }
7748
7749 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
7750         2, 0))
7751 static s32
7752 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
7753 wl_cfg80211_del_station(
7754                 struct wiphy *wiphy, struct net_device *ndev,
7755                 struct station_del_parameters *params)
7756 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
7757 wl_cfg80211_del_station(
7758         struct wiphy *wiphy,
7759         struct net_device *ndev,
7760         const u8* mac_addr)
7761 #else
7762 wl_cfg80211_del_station(
7763         struct wiphy *wiphy,
7764         struct net_device *ndev,
7765         u8* mac_addr)
7766 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
7767 {
7768         struct net_device *dev;
7769         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7770         scb_val_t scb_val;
7771         s8 eabuf[ETHER_ADDR_STR_LEN];
7772         int err;
7773         char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
7774                 sizeof(struct ether_addr) + sizeof(uint)] = {0};
7775         struct maclist *assoc_maclist = (struct maclist *)mac_buf;
7776         int num_associated = 0;
7777
7778 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
7779         const u8 *mac_addr = params->mac;
7780 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
7781
7782         WL_DBG(("Entry\n"));
7783         if (mac_addr == NULL) {
7784                 WL_DBG(("mac_addr is NULL ignore it\n"));
7785                 return 0;
7786         }
7787
7788         dev = ndev_to_wlc_ndev(ndev, cfg);
7789
7790         if (p2p_is_on(cfg)) {
7791                 /* Suspend P2P discovery search-listen to prevent it from changing the
7792                  * channel.
7793                  */
7794                 if ((wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
7795                         WL_ERR(("Can not disable discovery mode\n"));
7796                         return -EFAULT;
7797                 }
7798         }
7799
7800         assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
7801         err = wldev_ioctl(ndev, WLC_GET_ASSOCLIST,
7802                 assoc_maclist, sizeof(mac_buf), false);
7803         if (err < 0)
7804                 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
7805         else
7806                 num_associated = assoc_maclist->count;
7807
7808         memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN);
7809         scb_val.val = DOT11_RC_DEAUTH_LEAVING;
7810         err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
7811                 sizeof(scb_val_t), true);
7812         if (err < 0)
7813                 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err));
7814         WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
7815                 bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf),
7816                 scb_val.val));
7817
7818         if (num_associated > 0 && ETHER_ISBCAST(mac_addr))
7819                 wl_delay(400);
7820
7821         return 0;
7822 }
7823
7824 static s32
7825 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
7826 wl_cfg80211_change_station(
7827         struct wiphy *wiphy,
7828         struct net_device *dev,
7829         const u8 *mac,
7830         struct station_parameters *params)
7831 #else
7832 wl_cfg80211_change_station(
7833         struct wiphy *wiphy,
7834         struct net_device *dev,
7835         u8 *mac,
7836         struct station_parameters *params)
7837 #endif
7838 {
7839         int err;
7840         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7841         struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg);
7842
7843         WL_DBG(("SCB_AUTHORIZE mac_addr:"MACDBG" sta_flags_mask:0x%x "
7844                                 "sta_flags_set:0x%x iface:%s \n", MAC2STRDBG(mac),
7845                                 params->sta_flags_mask, params->sta_flags_set, dev->name));
7846
7847         /* Processing only authorize/de-authorize flag for now */
7848         if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) {
7849                 WL_ERR(("WLC_SCB_AUTHORIZE sta_flags_mask not set \n"));
7850                 return -ENOTSUPP;
7851         }
7852
7853         if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))) {
7854 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
7855                 err = wldev_ioctl(primary_ndev, WLC_SCB_DEAUTHORIZE, (u8 *)mac, ETH_ALEN, true);
7856 #else
7857                 err = wldev_ioctl(primary_ndev, WLC_SCB_DEAUTHORIZE, mac, ETH_ALEN, true);
7858 #endif
7859                 if (err)
7860                         WL_ERR(("WLC_SCB_DEAUTHORIZE error (%d)\n", err));
7861                 return err;
7862         }
7863
7864 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
7865         err = wldev_ioctl(primary_ndev, WLC_SCB_AUTHORIZE, (u8 *)mac, ETH_ALEN, true);
7866 #else
7867         err = wldev_ioctl(primary_ndev, WLC_SCB_AUTHORIZE, mac, ETH_ALEN, true);
7868 #endif
7869         if (err)
7870                 WL_ERR(("WLC_SCB_AUTHORIZE error (%d)\n", err));
7871 #ifdef DHD_LOSSLESS_ROAMING
7872         wl_del_roam_timeout(cfg);
7873 #endif
7874         return err;
7875 }
7876 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
7877
7878 static s32
7879 wl_cfg80211_set_scb_timings(
7880         struct bcm_cfg80211 *cfg,
7881         struct net_device *dev)
7882 {
7883         int err;
7884         u32 ps_pretend;
7885         wl_scb_probe_t scb_probe;
7886
7887         bzero(&scb_probe, sizeof(wl_scb_probe_t));
7888         scb_probe.scb_timeout = WL_SCB_TIMEOUT;
7889         scb_probe.scb_activity_time = WL_SCB_ACTIVITY_TIME;
7890         scb_probe.scb_max_probe = WL_SCB_MAX_PROBE;
7891         err = wldev_iovar_setbuf(dev, "scb_probe", (void *)&scb_probe,
7892                 sizeof(wl_scb_probe_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
7893                 &cfg->ioctl_buf_sync);
7894         if (unlikely(err)) {
7895                 WL_ERR(("set 'scb_probe' failed, error = %d\n", err));
7896                 return err;
7897         }
7898
7899         ps_pretend = MAX(WL_SCB_MAX_PROBE / 2, WL_MIN_PSPRETEND_THRESHOLD);
7900         err = wldev_iovar_setint(dev, "pspretend_threshold", ps_pretend);
7901         if (unlikely(err)) {
7902                 if (err == BCME_UNSUPPORTED) {
7903                         /* Ignore error if fw doesn't support the iovar */
7904                         WL_DBG(("wl pspretend_threshold %d set error %d\n",
7905                                 ps_pretend, err));
7906                 } else {
7907                         WL_ERR(("wl pspretend_threshold %d set error %d\n",
7908                                 ps_pretend, err));
7909                         return err;
7910                 }
7911         }
7912
7913         return 0;
7914 }
7915
7916 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
7917 static s32
7918 wl_cfg80211_start_ap(
7919         struct wiphy *wiphy,
7920         struct net_device *dev,
7921         struct cfg80211_ap_settings *info)
7922 {
7923         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7924         s32 err = BCME_OK;
7925         struct parsed_ies ies;
7926         s32 bssidx = 0;
7927         u32 dev_role = 0;
7928         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
7929
7930         WL_DBG(("Enter \n"));
7931
7932 #if defined(SUPPORT_RANDOM_MAC_SCAN)
7933         wl_cfg80211_set_random_mac(dev, FALSE);
7934 #endif /* SUPPORT_RANDOM_MAC_SCAN */
7935
7936         if ((dev == bcmcfg_to_prmry_ndev(cfg)) ||
7937                 (dev == ((struct net_device *)cfgdev_to_ndev(cfg->bss_cfgdev)))) {
7938                 WL_DBG(("Start AP req on iface: %s \n", dev->name));
7939                 dev_role = NL80211_IFTYPE_AP;
7940         }
7941 #if defined(WL_ENABLE_P2P_IF)
7942         else if (dev == cfg->p2p_net) {
7943                 /* Group Add request on p2p0 */
7944                 WL_DBG(("Start AP req on P2P iface: GO\n"));
7945                 dev = bcmcfg_to_prmry_ndev(cfg);
7946                 dev_role = NL80211_IFTYPE_P2P_GO;
7947         }
7948 #endif /* WL_ENABLE_P2P_IF */
7949
7950         if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
7951                 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
7952                 return BCME_ERROR;
7953         }
7954
7955         if (p2p_is_on(cfg) && (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO)) {
7956                 dev_role = NL80211_IFTYPE_P2P_GO;
7957         } else if (dev_role == NL80211_IFTYPE_AP) {
7958                 dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
7959                 /*
7960                  * Enabling Softap is causing issues with STA NDO operations
7961                  * as NDO is not interface specific. So disable NDO while
7962                  * Softap is enabled
7963                  */
7964                 err = dhd_ndo_enable(dhd, FALSE);
7965                 WL_DBG(("%s: Disabling NDO on Hostapd mode %d\n", __FUNCTION__, err));
7966                 if (err) {
7967                         /* Non fatal error. */
7968                         WL_ERR(("%s: Disabling NDO Failed %d\n", __FUNCTION__, err));
7969                 } else {
7970                         cfg->revert_ndo_disable = true;
7971                 }
7972
7973 #ifdef PKT_FILTER_SUPPORT
7974                 /* Disable packet filter */
7975                 if (dhd->early_suspended) {
7976                         WL_ERR(("Disable pkt_filter\n"));
7977                         dhd_enable_packet_filter(0, dhd);
7978                 }
7979 #endif /* PKT_FILTER_SUPPORT */
7980 #ifdef ARP_OFFLOAD_SUPPORT
7981                 /* IF SoftAP is enabled, disable arpoe */
7982                 dhd_arp_offload_set(dhd, 0);
7983                 dhd_arp_offload_enable(dhd, FALSE);
7984 #endif /* ARP_OFFLOAD_SUPPORT */
7985                 if ((dhd->op_mode & DHD_FLAG_STA_MODE) && wl_cfg80211_is_roam_offload()) {
7986                         WL_ERR(("Cleare roam_offload_bssid_list at STA-SoftAP MODE.\n"));
7987                         wl_android_set_roam_offload_bssid_list(dev, "0");
7988                 }
7989         } else {
7990                 /* only AP or GO role need to be handled here. */
7991                 err = -EINVAL;
7992                 goto fail;
7993         }
7994
7995         if (!check_dev_role_integrity(cfg, dev_role)) {
7996                 err = -EINVAL;
7997                 goto fail;
7998         }
7999
8000 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
8001         if ((err = wl_cfg80211_set_channel(wiphy, dev,
8002                 dev->ieee80211_ptr->preset_chandef.chan,
8003                 NL80211_CHAN_HT20) < 0)) {
8004                 WL_ERR(("Set channel failed \n"));
8005                 goto fail;
8006         }
8007 #endif 
8008
8009         if ((err = wl_cfg80211_bcn_set_params(info, dev,
8010                 dev_role, bssidx)) < 0) {
8011                 WL_ERR(("Beacon params set failed \n"));
8012                 goto fail;
8013         }
8014
8015         /* Parse IEs */
8016         if ((err = wl_cfg80211_parse_ap_ies(dev, &info->beacon, &ies)) < 0) {
8017                 WL_ERR(("Set IEs failed \n"));
8018                 goto fail;
8019         }
8020
8021         if ((err = wl_cfg80211_bcn_validate_sec(dev, &ies,
8022                 dev_role, bssidx, info->privacy)) < 0)
8023         {
8024                 WL_ERR(("Beacon set security failed \n"));
8025                 goto fail;
8026         }
8027
8028         if ((err = wl_cfg80211_bcn_bringup_ap(dev, &ies,
8029                 dev_role, bssidx)) < 0) {
8030                 WL_ERR(("Beacon bring up AP/GO failed \n"));
8031                 goto fail;
8032         }
8033
8034         /* Set GC/STA SCB expiry timings. */
8035         if ((err = wl_cfg80211_set_scb_timings(cfg, dev))) {
8036                 WL_ERR(("scb setting failed \n"));
8037                 goto fail;
8038         }
8039
8040         WL_DBG(("** AP/GO Created **\n"));
8041
8042 #ifdef WL_CFG80211_ACL
8043         /* Enfoce Admission Control. */
8044         if ((err = wl_cfg80211_set_mac_acl(wiphy, dev, info->acl)) < 0) {
8045                 WL_ERR(("Set ACL failed\n"));
8046         }
8047 #endif /* WL_CFG80211_ACL */
8048
8049         /* Set IEs to FW */
8050         if ((err = wl_cfg80211_set_ies(dev, &info->beacon, bssidx)) < 0)
8051                 WL_ERR(("Set IEs failed \n"));
8052
8053         /* Enable Probe Req filter, WPS-AP certification 4.2.13 */
8054         if ((dev_role == NL80211_IFTYPE_AP) && (ies.wps_ie != NULL)) {
8055                 bool pbc = 0;
8056                 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
8057                 if (pbc) {
8058                         WL_DBG(("set WLC_E_PROBREQ_MSG\n"));
8059                         wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
8060                 }
8061         }
8062
8063 fail:
8064         if (err) {
8065                 WL_ERR(("ADD/SET beacon failed\n"));
8066                 wldev_iovar_setint(dev, "mpc", 1);
8067                 if (dev_role == NL80211_IFTYPE_AP) {
8068                         dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
8069
8070 #ifdef PKT_FILTER_SUPPORT
8071                         /* Enable packet filter */
8072                         if (dhd->early_suspended) {
8073                                 WL_ERR(("Enable pkt_filter\n"));
8074                                 dhd_enable_packet_filter(1, dhd);
8075                         }
8076 #endif /* PKT_FILTER_SUPPORT */
8077                 }
8078         }
8079
8080         return err;
8081 }
8082
8083 static s32
8084 wl_cfg80211_stop_ap(
8085         struct wiphy *wiphy,
8086         struct net_device *dev)
8087 {
8088         int err = 0;
8089         u32 dev_role = 0;
8090         int infra = 0;
8091         int ap = 0;
8092         s32 bssidx = 0;
8093         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8094         s32 is_rsdb_supported = BCME_ERROR;
8095         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
8096
8097         WL_DBG(("Enter \n"));
8098
8099         is_rsdb_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_RSDB_MODE);
8100         if (is_rsdb_supported < 0)
8101                 return (-ENODEV);
8102
8103         wl_clr_drv_status(cfg, AP_CREATING, dev);
8104         wl_clr_drv_status(cfg, AP_CREATED, dev);
8105         cfg->ap_oper_channel = 0;
8106
8107         if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
8108                 dev_role = NL80211_IFTYPE_AP;
8109                 WL_DBG(("stopping AP operation\n"));
8110         } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
8111                 dev_role = NL80211_IFTYPE_P2P_GO;
8112                 WL_DBG(("stopping P2P GO operation\n"));
8113         } else {
8114                 WL_ERR(("no AP/P2P GO interface is operational.\n"));
8115                 return -EINVAL;
8116         }
8117
8118         if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
8119                 WL_ERR(("find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
8120                 return BCME_ERROR;
8121         }
8122
8123         if (!check_dev_role_integrity(cfg, dev_role)) {
8124                 WL_ERR(("role integrity check failed \n"));
8125                 err = -EINVAL;
8126                 goto exit;
8127         }
8128
8129         if ((err = wl_cfgp2p_bss(cfg, dev, bssidx, 0)) < 0) {
8130                 WL_ERR(("bss down error %d\n", err));
8131         }
8132
8133         if (dev_role == NL80211_IFTYPE_AP) {
8134                 if (cfg->revert_ndo_disable == true) {
8135                         err = dhd_ndo_enable(dhd, TRUE);
8136                         WL_DBG(("%s: Enabling back NDO on Softap turn off %d\n",
8137                                 __FUNCTION__, err));
8138                         if (err) {
8139                                 WL_ERR(("%s: Enabling NDO Failed %d\n", __FUNCTION__, err));
8140                         }
8141                         cfg->revert_ndo_disable = false;
8142                 }
8143
8144 #ifdef PKT_FILTER_SUPPORT
8145                 /* Enable packet filter */
8146                 if (dhd->early_suspended) {
8147                         WL_ERR(("Enable pkt_filter\n"));
8148                         dhd_enable_packet_filter(1, dhd);
8149                 }
8150 #endif /* PKT_FILTER_SUPPORT */
8151 #ifdef ARP_OFFLOAD_SUPPORT
8152                 /* IF SoftAP is disabled, enable arpoe back for STA mode. */
8153                 dhd_arp_offload_set(dhd, dhd_arp_mode);
8154                 dhd_arp_offload_enable(dhd, TRUE);
8155 #endif /* ARP_OFFLOAD_SUPPORT */
8156                 /*
8157                  * Bring down the AP interface by changing role to STA.
8158                  * Don't do a down or "WLC_SET_AP 0" since the shared
8159                  * interface may be still running
8160                  */
8161                 if (is_rsdb_supported) {
8162                         if ((err = wl_cfg80211_add_del_bss(cfg, dev,
8163                                 bssidx, NL80211_IFTYPE_STATION, 0, NULL)) < 0) {
8164                                 if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32),
8165                                         true)) < 0) {
8166                                         WL_ERR(("setting AP mode failed %d \n", err));
8167                                         err = -ENOTSUPP;
8168                                         goto exit;
8169                                 }
8170                         }
8171                 } else if (is_rsdb_supported == 0) {
8172                         err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
8173                         if (err < 0) {
8174                                 WL_ERR(("SET INFRA error %d\n", err));
8175                                 err = -ENOTSUPP;
8176                                 goto exit;
8177                         }
8178                         err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
8179                         if (unlikely(err)) {
8180                                 WL_ERR(("WLC_UP error (%d)\n", err));
8181                                 err = -EINVAL;
8182                                 goto exit;
8183                         }
8184                 }
8185
8186                 /* Turn on the MPC */
8187                 wldev_iovar_setint(dev, "mpc", 1);
8188
8189                  wl_cfg80211_clear_per_bss_ies(cfg, bssidx);
8190         } else {
8191                 WL_DBG(("Stopping P2P GO \n"));
8192                 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE((dhd_pub_t *)(cfg->pub),
8193                         DHD_EVENT_TIMEOUT_MS*3);
8194                 DHD_OS_WAKE_LOCK_TIMEOUT((dhd_pub_t *)(cfg->pub));
8195         }
8196
8197 exit:
8198
8199         if (dev_role == NL80211_IFTYPE_AP) {
8200                 /* clear the AP mode */
8201                 dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
8202         }
8203         return err;
8204 }
8205
8206 static s32
8207 wl_cfg80211_change_beacon(
8208         struct wiphy *wiphy,
8209         struct net_device *dev,
8210         struct cfg80211_beacon_data *info)
8211 {
8212         s32 err = BCME_OK;
8213         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8214         struct parsed_ies ies;
8215         u32 dev_role = 0;
8216         s32 bssidx = 0;
8217         bool pbc = 0;
8218
8219         WL_DBG(("Enter \n"));
8220
8221         if (dev == bcmcfg_to_prmry_ndev(cfg)) {
8222                 dev_role = NL80211_IFTYPE_AP;
8223         }
8224 #if defined(WL_ENABLE_P2P_IF)
8225         else if (dev == cfg->p2p_net) {
8226                 /* Group Add request on p2p0 */
8227                 dev = bcmcfg_to_prmry_ndev(cfg);
8228                 dev_role = NL80211_IFTYPE_P2P_GO;
8229         }
8230 #endif /* WL_ENABLE_P2P_IF */
8231
8232         if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
8233                 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
8234                 return BCME_ERROR;
8235         }
8236
8237         if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
8238                 dev_role = NL80211_IFTYPE_P2P_GO;
8239         }
8240
8241         if (!check_dev_role_integrity(cfg, dev_role)) {
8242                 err = -EINVAL;
8243                 goto fail;
8244         }
8245
8246         if ((dev_role == NL80211_IFTYPE_P2P_GO) && (cfg->p2p_wdev == NULL)) {
8247                 WL_ERR(("P2P already down status!\n"));
8248                 err = BCME_ERROR;
8249                 goto fail;
8250         }
8251
8252         /* Parse IEs */
8253         if ((err = wl_cfg80211_parse_ap_ies(dev, info, &ies)) < 0) {
8254                 WL_ERR(("Parse IEs failed \n"));
8255                 goto fail;
8256         }
8257
8258         /* Set IEs to FW */
8259         if ((err = wl_cfg80211_set_ies(dev, info, bssidx)) < 0) {
8260                 WL_ERR(("Set IEs failed \n"));
8261                 goto fail;
8262         }
8263
8264         if (dev_role == NL80211_IFTYPE_AP) {
8265                 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
8266                         WL_ERR(("Hostapd update sec failed \n"));
8267                         err = -EINVAL;
8268                         goto fail;
8269                 }
8270                 /* Enable Probe Req filter, WPS-AP certification 4.2.13 */
8271                 if ((dev_role == NL80211_IFTYPE_AP) && (ies.wps_ie != NULL)) {
8272                         wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
8273                         WL_DBG((" WPS AP, wps_ie is exists pbc=%d\n", pbc));
8274                         if (pbc)
8275                                 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
8276                         else
8277                                 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
8278                 }
8279         }
8280
8281 fail:
8282         return err;
8283 }
8284 #else
8285 static s32
8286 wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
8287         struct beacon_parameters *info)
8288 {
8289         s32 err = BCME_OK;
8290         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8291         s32 ie_offset = 0;
8292         s32 bssidx = 0;
8293         u32 dev_role = NL80211_IFTYPE_AP;
8294         struct parsed_ies ies;
8295         bcm_tlv_t *ssid_ie;
8296         bool pbc = 0;
8297         bool privacy;
8298         bool is_bss_up = 0;
8299         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
8300
8301         WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
8302                 info->interval, info->dtim_period, info->head_len, info->tail_len));
8303
8304         if (dev == bcmcfg_to_prmry_ndev(cfg)) {
8305                 dev_role = NL80211_IFTYPE_AP;
8306         }
8307 #if defined(WL_ENABLE_P2P_IF)
8308         else if (dev == cfg->p2p_net) {
8309                 /* Group Add request on p2p0 */
8310                 dev = bcmcfg_to_prmry_ndev(cfg);
8311                 dev_role = NL80211_IFTYPE_P2P_GO;
8312         }
8313 #endif /* WL_ENABLE_P2P_IF */
8314
8315         if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
8316                 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
8317                 return BCME_ERROR;
8318         }
8319
8320         if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
8321                 dev_role = NL80211_IFTYPE_P2P_GO;
8322         } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
8323                 dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
8324         }
8325
8326         if (!check_dev_role_integrity(cfg, dev_role)) {
8327                 err = -ENODEV;
8328                 goto fail;
8329         }
8330
8331         if ((dev_role == NL80211_IFTYPE_P2P_GO) && (cfg->p2p_wdev == NULL)) {
8332                 WL_ERR(("P2P already down status!\n"));
8333                 err = BCME_ERROR;
8334                 goto fail;
8335         }
8336
8337         ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
8338         /* find the SSID */
8339         if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
8340                 info->head_len - ie_offset,
8341                 DOT11_MNG_SSID_ID)) != NULL) {
8342                 if (dev_role == NL80211_IFTYPE_AP) {
8343                         /* Store the hostapd SSID */
8344                         memset(&cfg->hostapd_ssid.SSID[0], 0x00, 32);
8345                         memcpy(&cfg->hostapd_ssid.SSID[0], ssid_ie->data, ssid_ie->len);
8346                         cfg->hostapd_ssid.SSID_len = ssid_ie->len;
8347                 } else {
8348                                 /* P2P GO */
8349                         memset(&cfg->p2p->ssid.SSID[0], 0x00, 32);
8350                         memcpy(cfg->p2p->ssid.SSID, ssid_ie->data, ssid_ie->len);
8351                         cfg->p2p->ssid.SSID_len = ssid_ie->len;
8352                 }
8353         }
8354
8355         if (wl_cfg80211_parse_ies((u8 *)info->tail,
8356                 info->tail_len, &ies) < 0) {
8357                 WL_ERR(("Beacon get IEs failed \n"));
8358                 err = -EINVAL;
8359                 goto fail;
8360         }
8361
8362         if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
8363                 VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
8364                 info->tail_len)) < 0) {
8365                 WL_ERR(("Beacon set IEs failed \n"));
8366                 goto fail;
8367         } else {
8368                 WL_DBG(("Applied Vndr IEs for Beacon \n"));
8369         }
8370
8371 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
8372         if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
8373                 VNDR_IE_PRBRSP_FLAG, (u8 *)info->proberesp_ies,
8374                 info->proberesp_ies_len)) < 0) {
8375                 WL_ERR(("ProbeRsp set IEs failed \n"));
8376                 goto fail;
8377         } else {
8378                 WL_DBG(("Applied Vndr IEs for ProbeRsp \n"));
8379         }
8380 #endif
8381
8382         is_bss_up = wl_cfgp2p_bss_isup(dev, bssidx);
8383
8384 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
8385         privacy = info->privacy;
8386 #else
8387         privacy = 0;
8388 #endif
8389         if (!is_bss_up &&
8390                 (wl_cfg80211_bcn_validate_sec(dev, &ies, dev_role, bssidx, privacy) < 0))
8391         {
8392                 WL_ERR(("Beacon set security failed \n"));
8393                 err = -EINVAL;
8394                 goto fail;
8395         }
8396
8397         /* Set BI and DTIM period */
8398         if (info->interval) {
8399                 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
8400                         &info->interval, sizeof(s32), true)) < 0) {
8401                         WL_ERR(("Beacon Interval Set Error, %d\n", err));
8402                         return err;
8403                 }
8404         }
8405         if (info->dtim_period) {
8406                 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
8407                         &info->dtim_period, sizeof(s32), true)) < 0) {
8408                         WL_ERR(("DTIM Interval Set Error, %d\n", err));
8409                         return err;
8410                 }
8411         }
8412
8413         /* If bss is already up, skip bring up */
8414         if (!is_bss_up &&
8415                 (err = wl_cfg80211_bcn_bringup_ap(dev, &ies, dev_role, bssidx)) < 0)
8416         {
8417                 WL_ERR(("Beacon bring up AP/GO failed \n"));
8418                 goto fail;
8419         }
8420
8421         /* Set GC/STA SCB expiry timings. */
8422         if ((err = wl_cfg80211_set_scb_timings(cfg, dev))) {
8423                 WL_ERR(("scb setting failed \n"));
8424                 goto fail;
8425         }
8426
8427         if (wl_get_drv_status(cfg, AP_CREATED, dev)) {
8428                 /* Soft AP already running. Update changed params */
8429                 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
8430                         WL_ERR(("Hostapd update sec failed \n"));
8431                         err = -EINVAL;
8432                         goto fail;
8433                 }
8434         }
8435
8436         /* Enable Probe Req filter */
8437         if (((dev_role == NL80211_IFTYPE_P2P_GO) ||
8438                 (dev_role == NL80211_IFTYPE_AP)) && (ies.wps_ie != NULL)) {
8439                 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
8440                 if (pbc)
8441                         wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
8442         }
8443
8444         WL_DBG(("** ADD/SET beacon done **\n"));
8445
8446 fail:
8447         if (err) {
8448                 WL_ERR(("ADD/SET beacon failed\n"));
8449                 wldev_iovar_setint(dev, "mpc", 1);
8450                 if (dev_role == NL80211_IFTYPE_AP) {
8451                         /* clear the AP mode */
8452                         dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
8453                 }
8454         }
8455         return err;
8456
8457 }
8458 #endif 
8459
8460 #ifdef WL_SCHED_SCAN
8461 #define PNO_TIME                30
8462 #define PNO_REPEAT              4
8463 #define PNO_FREQ_EXPO_MAX       2
8464 static bool
8465 is_ssid_in_list(struct cfg80211_ssid *ssid, struct cfg80211_ssid *ssid_list, int count)
8466 {
8467         int i;
8468
8469         if (!ssid || !ssid_list)
8470                 return FALSE;
8471
8472         for (i = 0; i < count; i++) {
8473                 if (ssid->ssid_len == ssid_list[i].ssid_len) {
8474                         if (strncmp(ssid->ssid, ssid_list[i].ssid, ssid->ssid_len) == 0)
8475                                 return TRUE;
8476                 }
8477         }
8478         return FALSE;
8479 }
8480
8481 static int
8482 wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
8483                              struct net_device *dev,
8484                              struct cfg80211_sched_scan_request *request)
8485 {
8486         ushort pno_time = PNO_TIME;
8487         int pno_repeat = PNO_REPEAT;
8488         int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
8489         wlc_ssid_ext_t ssids_local[MAX_PFN_LIST_COUNT];
8490         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8491         struct cfg80211_ssid *ssid = NULL;
8492         struct cfg80211_ssid *hidden_ssid_list = NULL;
8493         int ssid_cnt = 0;
8494         int i;
8495         int ret = 0;
8496
8497         if (!request) {
8498                 WL_ERR(("Sched scan request was NULL\n"));
8499                 return -EINVAL;
8500         }
8501
8502         WL_DBG(("Enter \n"));
8503         WL_PNO((">>> SCHED SCAN START\n"));
8504         WL_PNO(("Enter n_match_sets:%d   n_ssids:%d \n",
8505                 request->n_match_sets, request->n_ssids));
8506         WL_PNO(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
8507                 request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max));
8508
8509
8510         if (!request->n_ssids || !request->n_match_sets) {
8511                 WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids));
8512                 return -EINVAL;
8513         }
8514
8515         memset(&ssids_local, 0, sizeof(ssids_local));
8516
8517         if (request->n_ssids > 0) {
8518                 hidden_ssid_list = request->ssids;
8519         }
8520
8521         for (i = 0; i < request->n_match_sets && ssid_cnt < MAX_PFN_LIST_COUNT; i++) {
8522                 ssid = &request->match_sets[i].ssid;
8523                 /* No need to include null ssid */
8524                 if (ssid->ssid_len) {
8525                         memcpy(ssids_local[ssid_cnt].SSID, ssid->ssid, ssid->ssid_len);
8526                         ssids_local[ssid_cnt].SSID_len = ssid->ssid_len;
8527                         if (is_ssid_in_list(ssid, hidden_ssid_list, request->n_ssids)) {
8528                                 ssids_local[ssid_cnt].hidden = TRUE;
8529                                 WL_PNO((">>> PNO hidden SSID (%s) \n", ssid->ssid));
8530                         } else {
8531                                 ssids_local[ssid_cnt].hidden = FALSE;
8532                                 WL_PNO((">>> PNO non-hidden SSID (%s) \n", ssid->ssid));
8533                         }
8534                         ssid_cnt++;
8535                 }
8536         }
8537
8538         if (ssid_cnt) {
8539                 if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, ssid_cnt,
8540                         pno_time, pno_repeat, pno_freq_expo_max, NULL, 0)) < 0) {
8541                         WL_ERR(("PNO setup failed!! ret=%d \n", ret));
8542                         return -EINVAL;
8543                 }
8544                 cfg->sched_scan_req = request;
8545         } else {
8546                 return -EINVAL;
8547         }
8548
8549         return 0;
8550 }
8551
8552 static int
8553 wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
8554 {
8555         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8556
8557         WL_DBG(("Enter \n"));
8558         WL_PNO((">>> SCHED SCAN STOP\n"));
8559
8560         if (dhd_dev_pno_stop_for_ssid(dev) < 0)
8561                 WL_ERR(("PNO Stop for SSID failed"));
8562
8563         if (cfg->scan_request && cfg->sched_scan_running) {
8564                 WL_PNO((">>> Sched scan running. Aborting it..\n"));
8565                 wl_notify_escan_complete(cfg, dev, true, true);
8566         }
8567
8568          cfg->sched_scan_req = NULL;
8569          cfg->sched_scan_running = FALSE;
8570
8571         return 0;
8572 }
8573 #endif /* WL_SCHED_SCAN */
8574
8575 #ifdef WL_SUPPORT_ACS
8576 /*
8577  * Currently the dump_obss IOVAR is returning string as output so we need to
8578  * parse the output buffer in an unoptimized way. Going forward if we get the
8579  * IOVAR output in binary format this method can be optimized
8580  */
8581 static int wl_parse_dump_obss(char *buf, struct wl_dump_survey *survey)
8582 {
8583         int i;
8584         char *token;
8585         char delim[] = " \n";
8586
8587         token = strsep(&buf, delim);
8588         while (token != NULL) {
8589                 if (!strcmp(token, "OBSS")) {
8590                         for (i = 0; i < OBSS_TOKEN_IDX; i++)
8591                                 token = strsep(&buf, delim);
8592                         survey->obss = simple_strtoul(token, NULL, 10);
8593                 }
8594
8595                 if (!strcmp(token, "IBSS")) {
8596                         for (i = 0; i < IBSS_TOKEN_IDX; i++)
8597                                 token = strsep(&buf, delim);
8598                         survey->ibss = simple_strtoul(token, NULL, 10);
8599                 }
8600
8601                 if (!strcmp(token, "TXDur")) {
8602                         for (i = 0; i < TX_TOKEN_IDX; i++)
8603                                 token = strsep(&buf, delim);
8604                         survey->tx = simple_strtoul(token, NULL, 10);
8605                 }
8606
8607                 if (!strcmp(token, "Category")) {
8608                         for (i = 0; i < CTG_TOKEN_IDX; i++)
8609                                 token = strsep(&buf, delim);
8610                         survey->no_ctg = simple_strtoul(token, NULL, 10);
8611                 }
8612
8613                 if (!strcmp(token, "Packet")) {
8614                         for (i = 0; i < PKT_TOKEN_IDX; i++)
8615                                 token = strsep(&buf, delim);
8616                         survey->no_pckt = simple_strtoul(token, NULL, 10);
8617                 }
8618
8619                 if (!strcmp(token, "Opp(time):")) {
8620                         for (i = 0; i < IDLE_TOKEN_IDX; i++)
8621                                 token = strsep(&buf, delim);
8622                         survey->idle = simple_strtoul(token, NULL, 10);
8623                 }
8624
8625                 token = strsep(&buf, delim);
8626         }
8627
8628         return 0;
8629 }
8630
8631 static int wl_dump_obss(struct net_device *ndev, cca_msrmnt_query req,
8632         struct wl_dump_survey *survey)
8633 {
8634         cca_stats_n_flags *results;
8635         char *buf;
8636         int retry, err;
8637
8638         buf = kzalloc(sizeof(char) * WLC_IOCTL_MAXLEN, GFP_KERNEL);
8639         if (unlikely(!buf)) {
8640                 WL_ERR(("%s: buf alloc failed\n", __func__));
8641                 return -ENOMEM;
8642         }
8643
8644         retry = IOCTL_RETRY_COUNT;
8645         while (retry--) {
8646                 err = wldev_iovar_getbuf(ndev, "dump_obss", &req, sizeof(req),
8647                         buf, WLC_IOCTL_MAXLEN, NULL);
8648                 if (err >=  0) {
8649                         break;
8650                 }
8651                 WL_DBG(("attempt = %d, err = %d, \n",
8652                         (IOCTL_RETRY_COUNT - retry), err));
8653         }
8654
8655         if (retry <= 0) {
8656                 WL_ERR(("failure, dump_obss IOVAR failed\n"));
8657                 err = -EINVAL;
8658                 goto exit;
8659         }
8660
8661         results = (cca_stats_n_flags *)(buf);
8662         wl_parse_dump_obss(results->buf, survey);
8663         kfree(buf);
8664
8665         return 0;
8666 exit:
8667         kfree(buf);
8668         return err;
8669 }
8670
8671 static int wl_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
8672         int idx, struct survey_info *info)
8673 {
8674         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8675         struct wl_dump_survey *survey;
8676         struct ieee80211_supported_band *band;
8677         struct ieee80211_channel*chan;
8678         cca_msrmnt_query req;
8679         int val, err, noise, retry;
8680
8681         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
8682         if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
8683                 return -ENOENT;
8684         }
8685         band = wiphy->bands[IEEE80211_BAND_2GHZ];
8686         if (band && idx >= band->n_channels) {
8687                 idx -= band->n_channels;
8688                 band = NULL;
8689         }
8690
8691         if (!band || idx >= band->n_channels) {
8692                 /* Move to 5G band */
8693                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
8694                 if (idx >= band->n_channels) {
8695                         return -ENOENT;
8696                 }
8697         }
8698
8699         chan = &band->channels[idx];
8700         /* Setting current channel to the requested channel */
8701         if ((err = wl_cfg80211_set_channel(wiphy, ndev, chan,
8702                 NL80211_CHAN_HT20) < 0)) {
8703                 WL_ERR(("Set channel failed \n"));
8704         }
8705
8706         if (!idx) {
8707                 /* Disable mpc */
8708                 val = 0;
8709                 err = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
8710                         sizeof(val), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
8711                         &cfg->ioctl_buf_sync);
8712                 if (err < 0) {
8713                         WL_ERR(("set 'mpc' failed, error = %d\n", err));
8714                 }
8715
8716                 /* Set interface up, explicitly. */
8717                 val = 1;
8718                 err = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
8719                 if (err < 0) {
8720                         WL_ERR(("set interface up failed, error = %d\n", err));
8721                 }
8722         }
8723
8724         /* Get noise value */
8725         retry = IOCTL_RETRY_COUNT;
8726         while (retry--) {
8727                 err = wldev_ioctl(ndev, WLC_GET_PHY_NOISE, &noise,
8728                         sizeof(noise), false);
8729                 if (err >=  0) {
8730                         break;
8731                 }
8732                 WL_DBG(("attempt = %d, err = %d, \n",
8733                         (IOCTL_RETRY_COUNT - retry), err));
8734         }
8735
8736         if (retry <= 0) {
8737                 WL_ERR(("Get Phy Noise failed, error = %d\n", err));
8738                 noise = CHAN_NOISE_DUMMY;
8739         }
8740
8741         survey = (struct wl_dump_survey *) kzalloc(sizeof(struct wl_dump_survey),
8742                 GFP_KERNEL);
8743         if (unlikely(!survey)) {
8744                 WL_ERR(("%s: alloc failed\n", __func__));
8745                 return -ENOMEM;
8746         }
8747
8748         /* Start Measurement for obss stats on current channel */
8749         req.msrmnt_query = 0;
8750         req.time_req = ACS_MSRMNT_DELAY;
8751         if ((err = wl_dump_obss(ndev, req, survey)) < 0) {
8752                 goto exit;
8753         }
8754
8755         /*
8756          * Wait for the meaurement to complete, adding a buffer value of 10 to take
8757          * into consideration any delay in IOVAR completion
8758          */
8759         msleep(ACS_MSRMNT_DELAY + 10);
8760
8761         /* Issue IOVAR to collect measurement results */
8762         req.msrmnt_query = 1;
8763         if ((err = wl_dump_obss(ndev, req, survey)) < 0) {
8764                 goto exit;
8765         }
8766
8767         info->channel = chan;
8768         info->noise = noise;
8769         info->channel_time = ACS_MSRMNT_DELAY;
8770         info->channel_time_busy = ACS_MSRMNT_DELAY - survey->idle;
8771         info->channel_time_rx = survey->obss + survey->ibss + survey->no_ctg +
8772                 survey->no_pckt;
8773         info->channel_time_tx = survey->tx;
8774         info->filled = SURVEY_INFO_NOISE_DBM |SURVEY_INFO_CHANNEL_TIME |
8775                 SURVEY_INFO_CHANNEL_TIME_BUSY | SURVEY_INFO_CHANNEL_TIME_RX |
8776                 SURVEY_INFO_CHANNEL_TIME_TX;
8777         kfree(survey);
8778
8779         return 0;
8780 exit:
8781         kfree(survey);
8782         return err;
8783 }
8784 #endif /* WL_SUPPORT_ACS */
8785
8786 static struct cfg80211_ops wl_cfg80211_ops = {
8787         .add_virtual_intf = wl_cfg80211_add_virtual_iface,
8788         .del_virtual_intf = wl_cfg80211_del_virtual_iface,
8789         .change_virtual_intf = wl_cfg80211_change_virtual_iface,
8790 #if defined(WL_CFG80211_P2P_DEV_IF)
8791         .start_p2p_device = wl_cfgp2p_start_p2p_device,
8792         .stop_p2p_device = wl_cfgp2p_stop_p2p_device,
8793 #endif /* WL_CFG80211_P2P_DEV_IF */
8794         .scan = wl_cfg80211_scan,
8795         .set_wiphy_params = wl_cfg80211_set_wiphy_params,
8796         .join_ibss = wl_cfg80211_join_ibss,
8797         .leave_ibss = wl_cfg80211_leave_ibss,
8798         .get_station = wl_cfg80211_get_station,
8799         .set_tx_power = wl_cfg80211_set_tx_power,
8800         .get_tx_power = wl_cfg80211_get_tx_power,
8801         .add_key = wl_cfg80211_add_key,
8802         .del_key = wl_cfg80211_del_key,
8803         .get_key = wl_cfg80211_get_key,
8804         .set_default_key = wl_cfg80211_config_default_key,
8805         .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
8806         .set_power_mgmt = wl_cfg80211_set_power_mgmt,
8807         .connect = wl_cfg80211_connect,
8808         .disconnect = wl_cfg80211_disconnect,
8809         .suspend = wl_cfg80211_suspend,
8810         .resume = wl_cfg80211_resume,
8811         .set_pmksa = wl_cfg80211_set_pmksa,
8812         .del_pmksa = wl_cfg80211_del_pmksa,
8813         .flush_pmksa = wl_cfg80211_flush_pmksa,
8814         .remain_on_channel = wl_cfg80211_remain_on_channel,
8815         .cancel_remain_on_channel = wl_cfg80211_cancel_remain_on_channel,
8816         .mgmt_tx = wl_cfg80211_mgmt_tx,
8817         .mgmt_frame_register = wl_cfg80211_mgmt_frame_register,
8818         .change_bss = wl_cfg80211_change_bss,
8819 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
8820         .set_channel = wl_cfg80211_set_channel,
8821 #endif 
8822 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
8823         .set_beacon = wl_cfg80211_add_set_beacon,
8824         .add_beacon = wl_cfg80211_add_set_beacon,
8825 #else
8826         .change_beacon = wl_cfg80211_change_beacon,
8827         .start_ap = wl_cfg80211_start_ap,
8828         .stop_ap = wl_cfg80211_stop_ap,
8829 #endif 
8830 #ifdef WL_SCHED_SCAN
8831         .sched_scan_start = wl_cfg80211_sched_scan_start,
8832         .sched_scan_stop = wl_cfg80211_sched_scan_stop,
8833 #endif /* WL_SCHED_SCAN */
8834 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
8835         2, 0))
8836         .del_station = wl_cfg80211_del_station,
8837         .change_station = wl_cfg80211_change_station,
8838         .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait,
8839 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */
8840 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
8841         .tdls_mgmt = wl_cfg80211_tdls_mgmt,
8842         .tdls_oper = wl_cfg80211_tdls_oper,
8843 #endif 
8844 #ifdef WL_SUPPORT_ACS
8845         .dump_survey = wl_cfg80211_dump_survey,
8846 #endif /* WL_SUPPORT_ACS */
8847 #ifdef WL_CFG80211_ACL
8848         .set_mac_acl = wl_cfg80211_set_mac_acl,
8849 #endif /* WL_CFG80211_ACL */
8850 };
8851
8852 s32 wl_mode_to_nl80211_iftype(s32 mode)
8853 {
8854         s32 err = 0;
8855
8856         switch (mode) {
8857         case WL_MODE_BSS:
8858                 return NL80211_IFTYPE_STATION;
8859         case WL_MODE_IBSS:
8860                 return NL80211_IFTYPE_ADHOC;
8861         case WL_MODE_AP:
8862                 return NL80211_IFTYPE_AP;
8863         default:
8864                 return NL80211_IFTYPE_UNSPECIFIED;
8865         }
8866
8867         return err;
8868 }
8869
8870 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
8871 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
8872 #define WL_CFG80211_REG_NOTIFIER() static int wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
8873 #else
8874 #define WL_CFG80211_REG_NOTIFIER() static void wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
8875 #endif /* kernel version < 3.9.0 */
8876 #endif
8877
8878 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
8879 WL_CFG80211_REG_NOTIFIER()
8880 {
8881         struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy);
8882         int ret = 0;
8883         int revinfo = -1;
8884
8885         if (!request || !cfg) {
8886                 WL_ERR(("Invalid arg\n"));
8887 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
8888                 return -EINVAL;
8889 #else
8890                 return;
8891 #endif /* kernel version < 3.9.0 */
8892         }
8893
8894         WL_DBG(("ccode: %c%c Initiator: %d\n",
8895                 request->alpha2[0], request->alpha2[1], request->initiator));
8896
8897         /* We support only REGDOM_SET_BY_USER as of now */
8898         if ((request->initiator != NL80211_REGDOM_SET_BY_USER) &&
8899                 (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
8900                 WL_ERR(("reg_notifier for intiator:%d not supported : set default\n",
8901                         request->initiator));
8902                 /* in case of no supported country by regdb
8903                      lets driver setup platform default Locale
8904                 */
8905         }
8906
8907         WL_ERR(("Set country code %c%c from %s\n",
8908                 request->alpha2[0], request->alpha2[1],
8909                 ((request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) ? " 11d AP" : "User")));
8910
8911         if ((ret = wldev_set_country(bcmcfg_to_prmry_ndev(cfg), request->alpha2,
8912                 false, (request->initiator == NL80211_REGDOM_SET_BY_USER ? true : false),
8913                 revinfo)) < 0) {
8914                 WL_ERR(("set country Failed :%d\n", ret));
8915         }
8916
8917 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
8918         return ret;
8919 #else
8920         return;
8921 #endif /* kernel version < 3.9.0 */
8922 }
8923 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
8924
8925 #ifdef CONFIG_PM
8926 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
8927 static const struct wiphy_wowlan_support brcm_wowlan_support = {
8928         .flags = WIPHY_WOWLAN_ANY,
8929         .n_patterns = WL_WOWLAN_MAX_PATTERNS,
8930         .pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN,
8931         .pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN,
8932 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
8933         .max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN,
8934 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
8935 };
8936 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
8937 #if 0
8938 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8939 static struct cfg80211_wowlan brcm_wowlan_config = {
8940         .disconnect = true,
8941         .gtk_rekey_failure = true,
8942         .eap_identity_req = true,
8943         .four_way_handshake = true,
8944 };
8945 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
8946 #endif
8947 #endif /* CONFIG_PM */
8948
8949 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, void *context)
8950 {
8951         s32 err = 0;
8952 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
8953         dhd_pub_t *dhd = (dhd_pub_t *)context;
8954         BCM_REFERENCE(dhd);
8955
8956         if (!dhd) {
8957                 WL_ERR(("DHD is NULL!!"));
8958                 err = -ENODEV;
8959                 return err;
8960         }
8961 #endif 
8962
8963         wdev->wiphy =
8964             wiphy_new(&wl_cfg80211_ops, sizeof(struct bcm_cfg80211));
8965         if (unlikely(!wdev->wiphy)) {
8966                 WL_ERR(("Couldn not allocate wiphy device\n"));
8967                 err = -ENOMEM;
8968                 return err;
8969         }
8970         set_wiphy_dev(wdev->wiphy, sdiofunc_dev);
8971         wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX;
8972         /* Report  how many SSIDs Driver can support per Scan request */
8973         wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX;
8974         wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
8975 #ifdef WL_SCHED_SCAN
8976         wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT;
8977         wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT;
8978         wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX;
8979         wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8980 #endif /* WL_SCHED_SCAN */
8981         wdev->wiphy->interface_modes =
8982                 BIT(NL80211_IFTYPE_STATION)
8983                 | BIT(NL80211_IFTYPE_ADHOC)
8984 #if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
8985                 | BIT(NL80211_IFTYPE_MONITOR)
8986 #endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
8987 #if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)
8988                 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8989                 | BIT(NL80211_IFTYPE_P2P_GO)
8990 #endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */
8991 #if defined(WL_CFG80211_P2P_DEV_IF)
8992                 | BIT(NL80211_IFTYPE_P2P_DEVICE)
8993 #endif /* WL_CFG80211_P2P_DEV_IF */
8994                 | BIT(NL80211_IFTYPE_AP);
8995
8996 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
8997         (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
8998         WL_DBG(("Setting interface combinations for common mode\n"));
8999         wdev->wiphy->iface_combinations = common_iface_combinations;
9000         wdev->wiphy->n_iface_combinations =
9001                 ARRAY_SIZE(common_iface_combinations);
9002 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
9003
9004         wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
9005
9006         wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
9007         wdev->wiphy->cipher_suites = __wl_cipher_suites;
9008         wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
9009         wdev->wiphy->max_remain_on_channel_duration = 5000;
9010         wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes;
9011 #ifndef WL_POWERSAVE_DISABLED
9012         wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
9013 #else
9014         wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
9015 #endif                          /* !WL_POWERSAVE_DISABLED */
9016         wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK |
9017                 WIPHY_FLAG_4ADDR_AP |
9018 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39))
9019                 WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS |
9020 #endif
9021                 WIPHY_FLAG_4ADDR_STATION;
9022 #if ((defined(ROAM_ENABLE) || defined(BCMFW_ROAM_ENABLE)) && (LINUX_VERSION_CODE >= \
9023         KERNEL_VERSION(3, 2, 0)))
9024         /*
9025          * If FW ROAM flag is advertised, upper layer wouldn't provide
9026          * the bssid & freq in the connect command. This will result a
9027          * delay in initial connection time due to firmware doing a full
9028          * channel scan to figure out the channel & bssid. However kernel
9029          * ver >= 3.15, provides bssid_hint & freq_hint and hence kernel
9030          * ver >= 3.15 won't have any issue. So if this flags need to be
9031          * advertised for kernel < 3.15, suggest to use RCC along with it
9032          * to avoid the initial connection delay.
9033          */
9034         wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
9035 #endif 
9036 #ifdef UNSET_FW_ROAM_WIPHY_FLAG
9037         wdev->wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_FW_ROAM;
9038 #endif /* UNSET_FW_ROAM_WIPHY_FLAG */
9039 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
9040         wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
9041                 WIPHY_FLAG_OFFCHAN_TX;
9042 #endif
9043 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
9044         4, 0))
9045         /* From 3.4 kernel ownards AP_SME flag can be advertised
9046          * to remove the patch from supplicant
9047          */
9048         wdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
9049
9050 #ifdef WL_CFG80211_ACL
9051         /* Configure ACL capabilities. */
9052         wdev->wiphy->max_acl_mac_addrs = MAX_NUM_MAC_FILT;
9053 #endif
9054
9055 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9056         /* Supplicant distinguish between the SoftAP mode and other
9057          * modes (e.g. P2P, WPS, HS2.0) when it builds the probe
9058          * response frame from Supplicant MR1 and Kernel 3.4.0 or
9059          * later version. To add Vendor specific IE into the
9060          * probe response frame in case of SoftAP mode,
9061          * AP_PROBE_RESP_OFFLOAD flag is set to wiphy->flags variable.
9062          */
9063         if (dhd_get_fw_mode(dhd->info) == DHD_FLAG_HOSTAP_MODE) {
9064                 wdev->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
9065                 wdev->wiphy->probe_resp_offload = 0;
9066         }
9067 #endif 
9068 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
9069
9070 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
9071         wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
9072 #endif
9073
9074 #if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
9075         /*
9076          * From linux-3.10 kernel, wowlan packet filter is mandated to avoid the
9077          * disconnection of connected network before suspend. So a dummy wowlan
9078          * filter is configured for kernels linux-3.8 and above.
9079          */
9080
9081 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9082         wdev->wiphy->wowlan = &brcm_wowlan_support;
9083         /* If this is not provided cfg stack will get disconnect
9084          * during suspend.
9085          */
9086         //wdev->wiphy->wowlan_config = &brcm_wowlan_config;
9087 #else
9088         wdev->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
9089         wdev->wiphy->wowlan.n_patterns = WL_WOWLAN_MAX_PATTERNS;
9090         wdev->wiphy->wowlan.pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN;
9091         wdev->wiphy->wowlan.pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN;
9092 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
9093         wdev->wiphy->wowlan.max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN;
9094 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
9095 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
9096 #endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
9097
9098         WL_DBG(("Registering custom regulatory)\n"));
9099 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
9100         wdev->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
9101 #else
9102         wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
9103 #endif
9104         wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom);
9105 #if defined(WL_VENDOR_EXT_SUPPORT)
9106         WL_ERR(("Registering Vendor80211\n"));
9107         err = wl_cfgvendor_attach(wdev->wiphy);
9108         if (unlikely(err < 0)) {
9109                 WL_ERR(("Couldn not attach vendor commands (%d)\n", err));
9110         }
9111 #endif /* defined(WL_VENDOR_EXT_SUPPORT) */
9112         /* Now we can register wiphy with cfg80211 module */
9113         err = wiphy_register(wdev->wiphy);
9114         if (unlikely(err < 0)) {
9115                 WL_ERR(("Couldn not register wiphy device (%d)\n", err));
9116                 wiphy_free(wdev->wiphy);
9117         }
9118
9119 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \
9120         KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS)
9121         wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS;
9122 #endif
9123
9124         return err;
9125 }
9126
9127 static void wl_free_wdev(struct bcm_cfg80211 *cfg)
9128 {
9129         struct wireless_dev *wdev = cfg->wdev;
9130         struct wiphy *wiphy = NULL;
9131         if (!wdev) {
9132                 WL_ERR(("wdev is invalid\n"));
9133                 return;
9134         }
9135         if (wdev->wiphy) {
9136                 wiphy = wdev->wiphy;
9137
9138 #if defined(WL_VENDOR_EXT_SUPPORT)
9139                 wl_cfgvendor_detach(wdev->wiphy);
9140 #endif /* if defined(WL_VENDOR_EXT_SUPPORT) */
9141 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9142                 /* Reset wowlan & wowlan_config before Unregister to avoid  Kernel Panic */
9143                 WL_DBG(("wl_free_wdev Clearing wowlan Config \n"));
9144                 wdev->wiphy->wowlan = NULL;
9145                 wdev->wiphy->wowlan_config = NULL;
9146 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
9147                 wiphy_unregister(wdev->wiphy);
9148                 wdev->wiphy->dev.parent = NULL;
9149                 wdev->wiphy = NULL;
9150         }
9151
9152         wl_delete_all_netinfo(cfg);
9153         if (wiphy)
9154                 wiphy_free(wiphy);
9155
9156         /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "cfg",
9157          * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
9158          */
9159 }
9160
9161 static s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
9162 {
9163         struct wl_scan_results *bss_list;
9164         struct wl_bss_info *bi = NULL;  /* must be initialized */
9165         s32 err = 0;
9166         s32 i;
9167 #if defined(RSSIAVG)
9168         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
9169         int rssi;
9170 #endif
9171 #if defined(BSSCACHE)
9172         wl_bss_cache_t *node;
9173 #endif
9174
9175         bss_list = cfg->bss_list;
9176
9177         /* Free cache in p2p scanning*/
9178         if (p2p_is_on(cfg) && p2p_scan(cfg)) {
9179 #if defined(RSSIAVG)
9180                 wl_free_rssi_cache(&g_rssi_cache_ctrl);
9181 #endif
9182 #if defined(BSSCACHE)
9183                 wl_free_bss_cache(&g_bss_cache_ctrl);
9184 #endif
9185         }
9186
9187         /* Delete disconnected cache */
9188 #if defined(BSSCACHE)
9189         wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
9190 #if defined(RSSIAVG)
9191         wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
9192 #endif
9193         if (cfg->p2p_disconnected == 0)
9194                 memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN);
9195 #endif
9196
9197         /* Update cache */
9198 #if defined(RSSIAVG)
9199         wl_update_rssi_cache(&g_rssi_cache_ctrl, bss_list);
9200         if (!in_atomic())
9201                 wl_update_connected_rssi_cache(ndev, &g_rssi_cache_ctrl, &rssi);
9202 #endif
9203 #if defined(BSSCACHE)
9204         wl_update_bss_cache(&g_bss_cache_ctrl,
9205 #if defined(RSSIAVG)
9206                 &g_rssi_cache_ctrl,
9207 #endif
9208                 bss_list);
9209 #endif
9210
9211         /* delete dirty cache */
9212 #if defined(RSSIAVG)
9213         wl_delete_dirty_rssi_cache(&g_rssi_cache_ctrl);
9214         wl_reset_rssi_cache(&g_rssi_cache_ctrl);
9215 #endif
9216 #if defined(BSSCACHE)
9217         wl_delete_dirty_bss_cache(&g_bss_cache_ctrl);
9218         wl_reset_bss_cache(&g_bss_cache_ctrl);
9219 #endif
9220
9221 #if defined(BSSCACHE)
9222         if (cfg->p2p_disconnected > 0) {
9223                 // terence 20130703: Fix for wrong group_capab (timing issue)
9224                 wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
9225 #if defined(RSSIAVG)
9226                 wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
9227 #endif
9228         }
9229         WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
9230         node = g_bss_cache_ctrl.m_cache_head;
9231         for (i=0; node && i<WL_AP_MAX; i++) {
9232                 bi = node->results.bss_info;
9233                 err = wl_inform_single_bss(cfg, bi, false);
9234                 node = node->next;
9235         }
9236 #else
9237         WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
9238         bi = next_bss(bss_list, bi);
9239         for_each_bss(bss_list, bi, i) {
9240                 if (cfg->p2p_disconnected > 0 && !memcmp(&bi->BSSID, &cfg->disconnected_bssid, ETHER_ADDR_LEN))
9241                         continue;
9242                 err = wl_inform_single_bss(cfg, bi, false);
9243         }
9244 #endif
9245
9246         if (cfg->p2p_disconnected > 0) {
9247                 // terence 20130703: Fix for wrong group_capab (timing issue)
9248                 cfg->p2p_disconnected++;
9249                 if (cfg->p2p_disconnected >= REPEATED_SCAN_RESULT_CNT+1) {
9250                         cfg->p2p_disconnected = 0;
9251                         memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN);
9252                 }
9253         }
9254
9255         return err;
9256 }
9257
9258 static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi, bool roam)
9259 {
9260         struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
9261         struct ieee80211_mgmt *mgmt;
9262         struct ieee80211_channel *channel;
9263         struct ieee80211_supported_band *band;
9264         struct wl_cfg80211_bss_info *notif_bss_info;
9265         struct wl_scan_req *sr = wl_to_sr(cfg);
9266         struct beacon_proberesp *beacon_proberesp;
9267         struct cfg80211_bss *cbss = NULL;
9268         s32 mgmt_type;
9269         s32 signal;
9270         u32 freq;
9271         s32 err = 0;
9272         gfp_t aflags;
9273
9274         if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
9275                 WL_DBG(("Beacon is larger than buffer. Discarding\n"));
9276                 return err;
9277         }
9278         aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
9279         notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt)
9280                 - sizeof(u8) + WL_BSS_INFO_MAX, aflags);
9281         if (unlikely(!notif_bss_info)) {
9282                 WL_ERR(("notif_bss_info alloc failed\n"));
9283                 return -ENOMEM;
9284         }
9285         mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
9286         notif_bss_info->channel =
9287                 wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
9288
9289         if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
9290                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
9291         else
9292                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
9293         if (!band) {
9294                 WL_ERR(("No valid band\n"));
9295                 kfree(notif_bss_info);
9296                 return -EINVAL;
9297         }
9298         notif_bss_info->rssi = dtoh16(bi->RSSI);
9299 #if defined(RSSIAVG)
9300         notif_bss_info->rssi = wl_get_avg_rssi(&g_rssi_cache_ctrl, &bi->BSSID);
9301         if (notif_bss_info->rssi == RSSI_MINVAL)
9302                 notif_bss_info->rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
9303 #endif
9304 #if defined(RSSIOFFSET)
9305         notif_bss_info->rssi = wl_update_rssi_offset(bcmcfg_to_prmry_ndev(cfg), notif_bss_info->rssi);
9306 #endif
9307 #if !defined(RSSIAVG) && !defined(RSSIOFFSET)
9308         // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
9309         notif_bss_info->rssi = MIN(notif_bss_info->rssi, RSSI_MAXVAL);
9310 #endif
9311         memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
9312         mgmt_type = cfg->active_scan ?
9313                 IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
9314         if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
9315             mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
9316         }
9317         beacon_proberesp = cfg->active_scan ?
9318                 (struct beacon_proberesp *)&mgmt->u.probe_resp :
9319                 (struct beacon_proberesp *)&mgmt->u.beacon;
9320         beacon_proberesp->timestamp = 0;
9321         beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
9322         beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
9323         wl_rst_ie(cfg);
9324         wl_update_hidden_ap_ie(bi, ((u8 *) bi) + bi->ie_offset, &bi->ie_length, roam);
9325         wl_mrg_ie(cfg, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
9326         wl_cp_ie(cfg, beacon_proberesp->variable, WL_BSS_INFO_MAX -
9327                 offsetof(struct wl_cfg80211_bss_info, frame_buf));
9328         notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
9329                 u.beacon.variable) + wl_get_ielen(cfg);
9330 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
9331         freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
9332         (void)band->band;
9333 #else
9334         freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band);
9335 #endif
9336         if (freq == 0) {
9337                 WL_ERR(("Invalid channel, fail to change channel to freq\n"));
9338                 kfree(notif_bss_info);
9339                 return -EINVAL;
9340         }
9341         channel = ieee80211_get_channel(wiphy, freq);
9342         WL_SCAN(("BSSID %pM, channel %2d, rssi %3d, capa 0x04%x, mgmt_type %d, "
9343                 "frame_len %d, SSID \"%s\"\n", &bi->BSSID, notif_bss_info->channel,
9344                 notif_bss_info->rssi, mgmt->u.beacon.capab_info, mgmt_type,
9345                 notif_bss_info->frame_len, bi->SSID));
9346         if (unlikely(!channel)) {
9347                 WL_ERR(("ieee80211_get_channel error, freq=%d, channel=%d\n",
9348                         freq, notif_bss_info->channel));
9349                 kfree(notif_bss_info);
9350                 return -EINVAL;
9351         }
9352
9353         signal = notif_bss_info->rssi * 100;
9354         if (!mgmt->u.probe_resp.timestamp) {
9355 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
9356                 struct timespec ts;
9357                 get_monotonic_boottime(&ts);
9358                 mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000)
9359                                 + ts.tv_nsec / 1000;
9360 #else
9361                 struct timeval tv;
9362                 do_gettimeofday(&tv);
9363                 mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec*1000000)
9364                                 + tv.tv_usec;
9365 #endif
9366         }
9367
9368
9369         cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
9370                 le16_to_cpu(notif_bss_info->frame_len), signal, aflags);
9371         if (unlikely(!cbss)) {
9372                 WL_ERR(("cfg80211_inform_bss_frame error\n"));
9373                 kfree(notif_bss_info);
9374                 return -EINVAL;
9375         }
9376
9377
9378 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
9379         cfg80211_put_bss(wiphy, cbss);
9380 #else
9381         cfg80211_put_bss(cbss);
9382 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
9383         kfree(notif_bss_info);
9384         return err;
9385 }
9386
9387 static bool wl_is_linkup(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e, struct net_device *ndev)
9388 {
9389         u32 event = ntoh32(e->event_type);
9390         u32 status =  ntoh32(e->status);
9391         u16 flags = ntoh16(e->flags);
9392
9393         WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
9394         if (event == WLC_E_SET_SSID) {
9395                 if (status == WLC_E_STATUS_SUCCESS) {
9396                         if (!wl_is_ibssmode(cfg, ndev))
9397                                 return true;
9398                 }
9399         } else if (event == WLC_E_LINK) {
9400                 if (flags & WLC_EVENT_MSG_LINK)
9401                         return true;
9402         }
9403
9404         WL_DBG(("wl_is_linkup false\n"));
9405         return false;
9406 }
9407
9408 static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
9409 {
9410         u32 event = ntoh32(e->event_type);
9411         u16 flags = ntoh16(e->flags);
9412
9413         if (event == WLC_E_DEAUTH_IND ||
9414         event == WLC_E_DISASSOC_IND ||
9415         event == WLC_E_DISASSOC ||
9416         event == WLC_E_DEAUTH) {
9417 #if (WL_DBG_LEVEL > 0)
9418         WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
9419 #endif /* (WL_DBG_LEVEL > 0) */
9420                 return true;
9421         } else if (event == WLC_E_LINK) {
9422                 if (!(flags & WLC_EVENT_MSG_LINK)) {
9423 #if (WL_DBG_LEVEL > 0)
9424         WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
9425 #endif /* (WL_DBG_LEVEL > 0) */
9426                         return true;
9427                 }
9428         }
9429
9430         return false;
9431 }
9432
9433 static bool wl_is_nonetwork(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
9434 {
9435         u32 event = ntoh32(e->event_type);
9436         u32 status = ntoh32(e->status);
9437
9438         if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS)
9439                 return true;
9440         if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS)
9441                 return true;
9442
9443         return false;
9444 }
9445
9446 /* The mainline kernel >= 3.2.0 has support for indicating new/del station
9447  * to AP/P2P GO via events. If this change is backported to kernel for which
9448  * this driver is being built, then define WL_CFG80211_STA_EVENT. You
9449  * should use this new/del sta event mechanism for BRCM supplicant >= 22.
9450  */
9451 static s32
9452 wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
9453         const wl_event_msg_t *e, void *data)
9454 {
9455         s32 err = 0;
9456         u32 event = ntoh32(e->event_type);
9457         u32 reason = ntoh32(e->reason);
9458         u32 len = ntoh32(e->datalen);
9459         u32 status = ntoh32(e->status);
9460
9461 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
9462         bool isfree = false;
9463         u8 *mgmt_frame;
9464         u8 bsscfgidx = e->bsscfgidx;
9465         s32 freq;
9466         s32 channel;
9467         u8 *body = NULL;
9468         u16 fc = 0;
9469
9470         struct ieee80211_supported_band *band;
9471         struct ether_addr da;
9472         struct ether_addr bssid;
9473         struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
9474         channel_info_t ci;
9475 #else
9476         struct station_info sinfo;
9477 #endif 
9478
9479         WL_DBG(("event %d status %d reason %d\n", event, ntoh32(e->status), reason));
9480         /* if link down, bsscfg is disabled. */
9481         if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
9482                 wl_get_p2p_status(cfg, IF_DELETING) && (ndev != bcmcfg_to_prmry_ndev(cfg))) {
9483                 wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
9484                 WL_INFORM(("AP mode link down !! \n"));
9485                 complete(&cfg->iface_disable);
9486                 return 0;
9487         }
9488
9489         if ((event == WLC_E_LINK) && (status == WLC_E_STATUS_SUCCESS) &&
9490                 (reason == WLC_E_REASON_INITIAL_ASSOC) &&
9491                 (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP)) {
9492                 if (!wl_get_drv_status(cfg, AP_CREATED, ndev)) {
9493                         /* AP/GO brought up successfull in firmware */
9494                         WL_ERR(("** AP/GO Link up event **\n"));
9495                         wl_set_drv_status(cfg, AP_CREATED, ndev);
9496                         wake_up_interruptible(&cfg->netif_change_event);
9497                         return 0;
9498                 }
9499         }
9500
9501         if (event == WLC_E_DISASSOC_IND || event == WLC_E_DEAUTH_IND || event == WLC_E_DEAUTH) {
9502                 WL_ERR(("event %s(%d) status %d reason %d\n",
9503                 bcmevent_get_name(event), event, ntoh32(e->status), reason));
9504         }
9505
9506 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
9507         WL_DBG(("Enter \n"));
9508         if (!len && (event == WLC_E_DEAUTH)) {
9509                 len = 2; /* reason code field */
9510                 data = &reason;
9511         }
9512         if (len) {
9513                 body = kzalloc(len, GFP_KERNEL);
9514
9515                 if (body == NULL) {
9516                         WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
9517                         return WL_INVALID;
9518                 }
9519         }
9520         memset(&bssid, 0, ETHER_ADDR_LEN);
9521         WL_DBG(("Enter event %d ndev %p\n", event, ndev));
9522         if (wl_get_mode_by_netdev(cfg, ndev) == WL_INVALID) {
9523                 kfree(body);
9524                 return WL_INVALID;
9525         }
9526         if (len)
9527                 memcpy(body, data, len);
9528
9529         wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
9530                 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &cfg->ioctl_buf_sync);
9531         memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
9532         err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
9533         switch (event) {
9534                 case WLC_E_ASSOC_IND:
9535                         fc = FC_ASSOC_REQ;
9536                         break;
9537                 case WLC_E_REASSOC_IND:
9538                         fc = FC_REASSOC_REQ;
9539                         break;
9540                 case WLC_E_DISASSOC_IND:
9541                         fc = FC_DISASSOC;
9542                         break;
9543                 case WLC_E_DEAUTH_IND:
9544                         fc = FC_DISASSOC;
9545                         break;
9546                 case WLC_E_DEAUTH:
9547                         fc = FC_DISASSOC;
9548                         break;
9549                 default:
9550                         fc = 0;
9551                         goto exit;
9552         }
9553         if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) {
9554                 kfree(body);
9555                 return err;
9556         }
9557
9558         channel = dtoh32(ci.hw_channel);
9559         if (channel <= CH_MAX_2G_CHANNEL)
9560                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
9561         else
9562                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
9563         if (!band) {
9564                 WL_ERR(("No valid band\n"));
9565                 if (body)
9566                         kfree(body);
9567                 return -EINVAL;
9568         }
9569 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
9570         freq = ieee80211_channel_to_frequency(channel);
9571         (void)band->band;
9572 #else
9573         freq = ieee80211_channel_to_frequency(channel, band->band);
9574 #endif
9575
9576         err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
9577                 &mgmt_frame, &len, body);
9578         if (err < 0)
9579                 goto exit;
9580         isfree = true;
9581
9582         if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) {
9583 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) && (LINUX_VERSION_CODE < \
9584         KERNEL_VERSION(3, 18, 0)))
9585                 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
9586
9587 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
9588                 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len);
9589 #else
9590                 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
9591 #endif 
9592         } else if (event == WLC_E_DISASSOC_IND) {
9593 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9594                 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
9595 #else
9596                 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
9597 #endif 
9598         } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
9599 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9600                 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
9601 #else
9602                 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
9603 #endif 
9604         }
9605
9606 exit:
9607         if (isfree)
9608                 kfree(mgmt_frame);
9609         if (body)
9610                 kfree(body);
9611 #else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
9612         sinfo.filled = 0;
9613         if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
9614                 reason == DOT11_SC_SUCCESS) {
9615                 /* Linux ver >= 4.0 assoc_req_ies_len is used instead of
9616                  * STATION_INFO_ASSOC_REQ_IES flag
9617                  */
9618 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
9619                 sinfo.filled = STA_INFO_BIT(INFO_ASSOC_REQ_IES);
9620 #endif /*  (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) */
9621                 if (!data) {
9622                         WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
9623                         return -EINVAL;
9624                 }
9625                 sinfo.assoc_req_ies = data;
9626                 sinfo.assoc_req_ies_len = len;
9627                 printf("%s: connected device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
9628                 cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
9629         } else if (event == WLC_E_DISASSOC_IND) {
9630                 printf("%s: disassociated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
9631                 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
9632         } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
9633                 printf("%s: deauthenticated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
9634                 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
9635         }
9636 #endif 
9637         return err;
9638 }
9639
9640 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
9641 #define MAX_ASSOC_REJECT_ERR_STATUS 5
9642 int wl_get_connect_failed_status(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
9643 {
9644         u32 status = ntoh32(e->status);
9645
9646         cfg->assoc_reject_status = 0;
9647
9648         if (status == WLC_E_STATUS_FAIL) {
9649                 WL_ERR(("auth assoc status event=%d e->status %d e->reason %d \n",
9650                         ntoh32(cfg->event_auth_assoc.event_type),
9651                         (int)ntoh32(cfg->event_auth_assoc.status),
9652                         (int)ntoh32(cfg->event_auth_assoc.reason)));
9653
9654                 switch ((int)ntoh32(cfg->event_auth_assoc.status)) {
9655                         case WLC_E_STATUS_NO_ACK:
9656                                 cfg->assoc_reject_status = 1;
9657                                 break;
9658                         case WLC_E_STATUS_FAIL:
9659                                 cfg->assoc_reject_status = 2;
9660                                 break;
9661                         case WLC_E_STATUS_UNSOLICITED:
9662                                 cfg->assoc_reject_status = 3;
9663                                 break;
9664                         case WLC_E_STATUS_TIMEOUT:
9665                                 cfg->assoc_reject_status = 4;
9666                                 break;
9667                         case WLC_E_STATUS_ABORT:
9668                                 cfg->assoc_reject_status = 5;
9669                                 break;
9670                         default:
9671                                 break;
9672                 }
9673                 if (cfg->assoc_reject_status) {
9674                         if (ntoh32(cfg->event_auth_assoc.event_type) == WLC_E_ASSOC) {
9675                                 cfg->assoc_reject_status += MAX_ASSOC_REJECT_ERR_STATUS;
9676                         }
9677                 }
9678         }
9679
9680         WL_ERR(("assoc_reject_status %d \n", cfg->assoc_reject_status));
9681
9682         return 0;
9683 }
9684
9685 s32 wl_cfg80211_get_connect_failed_status(struct net_device *dev, char* cmd, int total_len)
9686 {
9687         struct bcm_cfg80211 *cfg = NULL;
9688         int bytes_written = 0;
9689
9690         cfg = g_bcm_cfg;
9691
9692         if (cfg == NULL) {
9693                 return -1;
9694         }
9695
9696         memset(cmd, 0, total_len);
9697         bytes_written = snprintf(cmd, 30, "assoc_reject.status %d", cfg->assoc_reject_status);
9698
9699         WL_ERR(("cmd: %s \n", cmd));
9700
9701         return bytes_written;
9702 }
9703 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
9704
9705 static s32
9706 wl_get_auth_assoc_status(struct bcm_cfg80211 *cfg, struct net_device *ndev,
9707         const wl_event_msg_t *e)
9708 {
9709         u32 reason = ntoh32(e->reason);
9710         u32 event = ntoh32(e->event_type);
9711         struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
9712         WL_DBG(("event type : %d, reason : %d\n", event, reason));
9713
9714 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
9715         memcpy(&cfg->event_auth_assoc, e, sizeof(wl_event_msg_t));
9716         WL_ERR(("event=%d status %d reason %d \n",
9717                 ntoh32(cfg->event_auth_assoc.event_type),
9718                 ntoh32(cfg->event_auth_assoc.status),
9719                 ntoh32(cfg->event_auth_assoc.reason)));
9720 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
9721         if (sec) {
9722                 switch (event) {
9723                 case WLC_E_ASSOC:
9724                 case WLC_E_AUTH:
9725                                 sec->auth_assoc_res_status = reason;
9726                 default:
9727                         break;
9728                 }
9729         } else
9730                 WL_ERR(("sec is NULL\n"));
9731         return 0;
9732 }
9733
9734 static s32
9735 wl_notify_connect_status_ibss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
9736         const wl_event_msg_t *e, void *data)
9737 {
9738         s32 err = 0;
9739         u32 event = ntoh32(e->event_type);
9740         u16 flags = ntoh16(e->flags);
9741         u32 status =  ntoh32(e->status);
9742         bool active;
9743 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
9744         struct ieee80211_channel *channel = NULL;
9745         struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
9746         u32 chanspec, chan;
9747         u32 freq, band;
9748 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
9749
9750         if (event == WLC_E_JOIN) {
9751                 WL_DBG(("joined in IBSS network\n"));
9752         }
9753         if (event == WLC_E_START) {
9754                 WL_DBG(("started IBSS network\n"));
9755         }
9756         if (event == WLC_E_JOIN || event == WLC_E_START ||
9757                 (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
9758 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
9759                 err = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
9760                 if (unlikely(err)) {
9761                         WL_ERR(("Could not get chanspec %d\n", err));
9762                         return err;
9763                 }
9764                 chan = wf_chspec_ctlchan(wl_chspec_driver_to_host(chanspec));
9765                 band = (chan <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
9766                 freq = ieee80211_channel_to_frequency(chan, band);
9767                 channel = ieee80211_get_channel(wiphy, freq);
9768 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
9769                 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
9770                         /* ROAM or Redundant */
9771                         u8 *cur_bssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
9772                         if (memcmp(cur_bssid, &e->addr, ETHER_ADDR_LEN) == 0) {
9773                                 WL_DBG(("IBSS connected event from same BSSID("
9774                                         MACDBG "), ignore it\n", MAC2STRDBG(cur_bssid)));
9775                                 return err;
9776                         }
9777                         WL_INFORM(("IBSS BSSID is changed from " MACDBG " to " MACDBG "\n",
9778                                 MAC2STRDBG(cur_bssid), MAC2STRDBG((const u8 *)&e->addr)));
9779                         wl_get_assoc_ies(cfg, ndev);
9780                         wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
9781                         wl_update_bss_info(cfg, ndev, false);
9782 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
9783                         cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, channel, GFP_KERNEL);
9784 #else
9785                         cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, GFP_KERNEL);
9786 #endif
9787                 }
9788                 else {
9789                         /* New connection */
9790                         WL_INFORM(("IBSS connected to " MACDBG "\n",
9791                                 MAC2STRDBG((const u8 *)&e->addr)));
9792                         wl_link_up(cfg);
9793                         wl_get_assoc_ies(cfg, ndev);
9794                         wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
9795                         wl_update_bss_info(cfg, ndev, false);
9796 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
9797                         cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, channel, GFP_KERNEL);
9798 #else
9799                         cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, GFP_KERNEL);
9800 #endif
9801                         wl_set_drv_status(cfg, CONNECTED, ndev);
9802                         active = true;
9803                         wl_update_prof(cfg, ndev, NULL, (const void *)&active, WL_PROF_ACT);
9804                 }
9805         } else if ((event == WLC_E_LINK && !(flags & WLC_EVENT_MSG_LINK)) ||
9806                 event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
9807                 wl_clr_drv_status(cfg, CONNECTED, ndev);
9808                 wl_link_down(cfg);
9809                 wl_init_prof(cfg, ndev);
9810         }
9811         else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
9812                 WL_DBG(("no action - join fail (IBSS mode)\n"));
9813         }
9814         else {
9815                 WL_DBG(("no action (IBSS mode)\n"));
9816 }
9817         return err;
9818 }
9819
9820 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
9821 #define WiFiALL_OUI         "\x50\x6F\x9A"  /* Wi-FiAll OUI */
9822 #define WiFiALL_OUI_LEN     3
9823 #define WiFiALL_OUI_TYPE    16
9824
9825 int wl_get_bss_info(struct bcm_cfg80211 *cfg, struct net_device *dev, uint8 *mac)
9826 {
9827         s32 err = 0;
9828         struct wl_bss_info *bi;
9829         uint8 eabuf[ETHER_ADDR_LEN];
9830         u32 rate, channel, freq, supported_rate, nss = 0, mcs_map, mode_80211 = 0;
9831         char rate_str[4];
9832         u8 *ie = NULL;
9833         u32 ie_len;
9834         struct wiphy *wiphy;
9835         struct cfg80211_bss *bss;
9836         bcm_tlv_t *interworking_ie = NULL;
9837         bcm_tlv_t *tlv_ie = NULL;
9838         bcm_tlv_t *vht_ie = NULL;
9839         vndr_ie_t *vndrie;
9840         int16 ie_11u_rel_num = -1, ie_mu_mimo_cap = -1;
9841         u32 i, remained_len, count = 0;
9842         char roam_count_str[4], akm_str[4];
9843         s32 val = 0;
9844
9845         /* get BSS information */
9846
9847         strncpy(cfg->bss_info, "x x x x x x x x x x x x x", GET_BSS_INFO_LEN);
9848
9849         *(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
9850
9851         err = wldev_ioctl(dev, WLC_GET_BSS_INFO, cfg->extra_buf, WL_EXTRA_BUF_MAX, false);
9852         if (unlikely(err)) {
9853                 WL_ERR(("Could not get bss info %d\n", err));
9854                 cfg->roam_count = 0;
9855                 return -1;
9856         }
9857
9858         if (!mac) {
9859                 WL_ERR(("mac is null \n"));
9860                 cfg->roam_count = 0;
9861                 return -1;
9862         }
9863
9864         memcpy(eabuf, mac, ETHER_ADDR_LEN);
9865
9866         bi = (struct wl_bss_info *)(cfg->extra_buf + 4);
9867         channel = wf_chspec_ctlchan(bi->chanspec);
9868
9869 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
9870         freq = ieee80211_channel_to_frequency(channel);
9871 #else
9872         if (channel > 14) {
9873                 freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
9874         } else {
9875                 freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
9876         }
9877 #endif
9878
9879         err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
9880         if (err) {
9881                 WL_ERR(("Could not get rate (%d)\n", err));
9882                 snprintf(rate_str, sizeof(rate_str), "x"); // Unknown
9883
9884         } else {
9885                 rate = dtoh32(rate);
9886                 snprintf(rate_str, sizeof(rate_str), "%d", (rate/2));
9887         }
9888
9889         //supported maximum rate
9890         supported_rate = (bi->rateset.rates[bi->rateset.count - 1] & 0x7f) / 2;
9891
9892         if (supported_rate < 12) {
9893                 mode_80211 = 0; //11b maximum rate is 11Mbps. 11b mode
9894         } else {
9895                 //It's not HT Capable case.
9896                 if (channel > 14) {
9897                         mode_80211 = 3; // 11a mode
9898                 } else {
9899                         mode_80211 = 1; // 11g mode
9900                 }
9901         }
9902
9903         if (bi->n_cap) {
9904                 /* check Rx MCS Map for HT */
9905                 nss = 0;
9906                 mode_80211 = 2;
9907                 for (i = 0; i < MAX_STREAMS_SUPPORTED; i++) {
9908                         int8 bitmap = 0xFF;
9909                         if (i == MAX_STREAMS_SUPPORTED-1) {
9910                                 bitmap = 0x7F;
9911                         }
9912                         if (bi->basic_mcs[i] & bitmap) {
9913                                 nss++;
9914                         }
9915                 }
9916         }
9917
9918         if (bi->vht_cap) {
9919                 nss = 0;
9920                 mode_80211 = 4;
9921                 for (i = 1; i <= VHT_CAP_MCS_MAP_NSS_MAX; i++) {
9922                         mcs_map = VHT_MCS_MAP_GET_MCS_PER_SS(i, dtoh16(bi->vht_rxmcsmap));
9923                         if (mcs_map != VHT_CAP_MCS_MAP_NONE) {
9924                                 nss++;
9925                         }
9926                 }
9927         }
9928
9929         if (nss) {
9930                 nss = nss - 1;
9931         }
9932
9933         wiphy = bcmcfg_to_wiphy(cfg);
9934         bss = cfg80211_get_bss(wiphy, NULL, eabuf,
9935                         bi->SSID, strlen(bi->SSID), WLAN_CAPABILITY_ESS,
9936                         WLAN_CAPABILITY_ESS);
9937
9938         if (!bss) {
9939                 WL_ERR(("Could not find the AP\n"));
9940         } else {
9941 #if defined(WL_CFG80211_P2P_DEV_IF)
9942                 ie = (u8 *)bss->ies->data;
9943                 ie_len = bss->ies->len;
9944 #else
9945                 ie = bss->information_elements;
9946                 ie_len = bss->len_information_elements;
9947 #endif /* WL_CFG80211_P2P_DEV_IF */
9948         }
9949
9950         if (ie) {
9951                 ie_mu_mimo_cap = 0;
9952                 ie_11u_rel_num = 0;
9953
9954                 if (bi->vht_cap) {
9955                         if ((vht_ie = bcm_parse_tlvs(ie, (u32)ie_len,
9956                                         DOT11_MNG_VHT_CAP_ID)) != NULL) {
9957                                 ie_mu_mimo_cap = (vht_ie->data[2] & 0x08) >> 3;
9958                         }
9959                 }
9960
9961                 if ((interworking_ie = bcm_parse_tlvs(ie, (u32)ie_len,
9962                                 DOT11_MNG_INTERWORKING_ID)) != NULL) {
9963                         if ((tlv_ie = bcm_parse_tlvs(ie, (u32)ie_len, DOT11_MNG_VS_ID)) != NULL) {
9964                                 remained_len = ie_len;
9965
9966                                 while (tlv_ie) {
9967                                         if (count > MAX_VNDR_IE_NUMBER)
9968                                                 break;
9969
9970                                         if (tlv_ie->id == DOT11_MNG_VS_ID) {
9971                                                 vndrie = (vndr_ie_t *) tlv_ie;
9972
9973                                                 if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) {
9974                                                         WL_ERR(("%s: invalid vndr ie."
9975                                                                 "length is too small %d\n",
9976                                                                 __FUNCTION__, vndrie->len));
9977                                                         break;
9978                                                 }
9979
9980                                                 if (!bcmp(vndrie->oui,
9981                                                         (u8*)WiFiALL_OUI, WiFiALL_OUI_LEN) &&
9982                                                         (vndrie->data[0] == WiFiALL_OUI_TYPE))
9983                                                 {
9984                                                         WL_ERR(("Found Wi-FiAll OUI oui.\n"));
9985                                                         ie_11u_rel_num = vndrie->data[1];
9986                                                         ie_11u_rel_num = (ie_11u_rel_num & 0xf0)>>4;
9987                                                         ie_11u_rel_num += 1;
9988
9989                                                         break;
9990                                                 }
9991                                         }
9992                                         count++;
9993                                         tlv_ie = bcm_next_tlv(tlv_ie, &remained_len);
9994                                 }
9995                         }
9996                 }
9997         }
9998
9999         for (i = 0; i < bi->SSID_len; i++) {
10000                 if (bi->SSID[i] == ' ') {
10001                         bi->SSID[i] = '_';
10002                 }
10003         }
10004
10005         //0 : None, 1 : OKC, 2 : FT, 3 : CCKM
10006         err = wldev_iovar_getint(dev, "wpa_auth", &val);
10007         if (unlikely(err)) {
10008                 WL_ERR(("could not get wpa_auth (%d)\n", err));
10009                 snprintf(akm_str, sizeof(akm_str), "x"); // Unknown
10010         } else {
10011                 WL_ERR(("wpa_auth val %d \n", val));
10012 #if defined(BCMEXTCCX)
10013                 if (val & (WPA_AUTH_CCKM | WPA2_AUTH_CCKM)) {
10014                         snprintf(akm_str, sizeof(akm_str), "3");
10015                 } else
10016 #endif  
10017                 if (val & WPA2_AUTH_FT) {
10018                         snprintf(akm_str, sizeof(akm_str), "2");
10019                 } else if (val & (WPA_AUTH_UNSPECIFIED | WPA2_AUTH_UNSPECIFIED)) {
10020                         snprintf(akm_str, sizeof(akm_str), "1");
10021                 } else {
10022                         snprintf(akm_str, sizeof(akm_str), "0");
10023                 }
10024         }
10025
10026         if (cfg->roam_offload) {
10027                 snprintf(roam_count_str, sizeof(roam_count_str), "x"); // Unknown
10028         } else {
10029                 snprintf(roam_count_str, sizeof(roam_count_str), "%d", cfg->roam_count);
10030         }
10031         cfg->roam_count = 0;
10032
10033         WL_ERR(("BSSID:" MACDBG " SSID %s \n", MAC2STRDBG(eabuf), bi->SSID));
10034         WL_ERR(("freq:%d, BW:%s, RSSI:%d dBm, Rate:%d Mbps, 11mode:%d, stream:%d,"
10035                                 "MU-MIMO:%d, Passpoint:%d, SNR:%d, Noise:%d, \n"
10036                                 "akm:%s roam:%s \n",
10037                                 freq, wf_chspec_to_bw_str(bi->chanspec),
10038                                 dtoh32(bi->RSSI), (rate / 2), mode_80211, nss,
10039                                 ie_mu_mimo_cap, ie_11u_rel_num, bi->SNR, bi->phy_noise,
10040                                 akm_str, roam_count_str));
10041
10042         if (ie) {
10043                 snprintf(cfg->bss_info, GET_BSS_INFO_LEN,
10044                                 "%02x:%02x:%02x %d %s %d %s %d %d %d %d %d %d %s %s",
10045                                 eabuf[0], eabuf[1], eabuf[2],
10046                                 freq, wf_chspec_to_bw_str(bi->chanspec),
10047                                 dtoh32(bi->RSSI), rate_str, mode_80211, nss,
10048                                 ie_mu_mimo_cap, ie_11u_rel_num,
10049                                 bi->SNR, bi->phy_noise, akm_str, roam_count_str);
10050         } else {
10051                 //ie_mu_mimo_cap and ie_11u_rel_num is unknow.
10052                 snprintf(cfg->bss_info, GET_BSS_INFO_LEN,
10053                                 "%02x:%02x:%02x %d %s %d %s %d %d x x %d %d %s %s",
10054                                 eabuf[0], eabuf[1], eabuf[2],
10055                                 freq, wf_chspec_to_bw_str(bi->chanspec),
10056                                 dtoh32(bi->RSSI), rate_str, mode_80211, nss,
10057                                 bi->SNR, bi->phy_noise, akm_str, roam_count_str);
10058         }
10059
10060
10061         return 0;
10062 }
10063
10064 s32 wl_cfg80211_get_bss_info(struct net_device *dev, char* cmd, int total_len)
10065 {
10066         struct bcm_cfg80211 *cfg = NULL;
10067
10068         cfg = g_bcm_cfg;
10069
10070         if (cfg == NULL) {
10071                 return -1;
10072         }
10073
10074         memset(cmd, 0, total_len);
10075         memcpy(cmd, cfg->bss_info, GET_BSS_INFO_LEN);
10076
10077         WL_ERR(("cmd: %s \n", cmd));
10078
10079         return GET_BSS_INFO_LEN;
10080 }
10081
10082 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
10083
10084 static s32
10085 wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10086         const wl_event_msg_t *e, void *data)
10087 {
10088         bool act;
10089         struct net_device *ndev = NULL;
10090         s32 err = 0;
10091         u32 event = ntoh32(e->event_type);
10092         struct wiphy *wiphy = NULL;
10093         struct cfg80211_bss *bss = NULL;
10094         struct wlc_ssid *ssid = NULL;
10095         u8 *bssid = 0;
10096
10097         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10098
10099         if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
10100                 err = wl_notify_connect_status_ap(cfg, ndev, e, data);
10101         } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS) {
10102                 err = wl_notify_connect_status_ibss(cfg, ndev, e, data);
10103         } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_BSS) {
10104                 WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
10105                         ntoh32(e->event_type), ntoh32(e->status), ndev));
10106                 if (event == WLC_E_ASSOC || event == WLC_E_AUTH) {
10107                         wl_get_auth_assoc_status(cfg, ndev, e);
10108                         return 0;
10109                 }
10110                 DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
10111                 if (wl_is_linkup(cfg, e, ndev)) {
10112                         wl_link_up(cfg);
10113                         act = true;
10114                         if (!wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
10115 #ifdef DHD_LOSSLESS_ROAMING
10116                                         bool is_connected = wl_get_drv_status(cfg, CONNECTED, ndev);
10117 #endif
10118
10119                                         printf("wl_bss_connect_done succeeded with " MACDBG "\n",
10120                                                 MAC2STRDBG((const u8*)(&e->addr)));
10121                                         wl_bss_connect_done(cfg, ndev, e, data, true);
10122                                         dhd_conf_set_fw_string_cmd(cfg->pub, "phy_oclscdenable", cfg->pub->conf->phy_oclscdenable, 0, FALSE);
10123                                         WL_DBG(("joined in BSS network \"%s\"\n",
10124                                         ((struct wlc_ssid *)
10125                                          wl_read_prof(cfg, ndev, WL_PROF_SSID))->SSID));
10126 #ifdef DHD_LOSSLESS_ROAMING
10127                                         if (event == WLC_E_LINK && is_connected &&
10128                                                         !cfg->roam_offload) {
10129                                                 wl_bss_roaming_done(cfg, ndev, e, data);
10130                                         }
10131 #endif /* DHD_LOSSLESS_ROAMING */
10132
10133                                 }
10134                         wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
10135                         wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
10136                         dhd_conf_set_wme(cfg->pub);
10137
10138                 } else if (wl_is_linkdown(cfg, e)) {
10139 #ifdef DHD_LOSSLESS_ROAMING
10140                         wl_del_roam_timeout(cfg);
10141 #endif
10142 #ifdef P2PLISTEN_AP_SAMECHN
10143                         if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
10144                                 wl_cfg80211_set_p2p_resp_ap_chn(ndev, 0);
10145                                 cfg->p2p_resp_apchn_status = false;
10146                                 WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
10147                         }
10148 #endif /* P2PLISTEN_AP_SAMECHN */
10149                         wl_cfg80211_cancel_scan(cfg);
10150
10151 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
10152                         if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
10153                                 wl_get_bss_info(cfg, ndev, (u8*)(&e->addr));
10154                         }
10155 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
10156                         /* Explicitly calling unlink to remove BSS in CFG */
10157                         wiphy = bcmcfg_to_wiphy(cfg);
10158                         ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
10159                         bssid = (u8 *)wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10160                         if (ssid && bssid) {
10161                                 bss = cfg80211_get_bss(wiphy, NULL, bssid,
10162                                         ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS,
10163                                         WLAN_CAPABILITY_ESS);
10164                                 if (bss) {
10165                                         cfg80211_unlink_bss(wiphy, bss);
10166                                 }
10167                         }
10168
10169                         if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
10170                                 scb_val_t scbval;
10171                                 u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10172                                 s32 reason = 0;
10173                                 struct ether_addr bssid_dongle;
10174                                 struct ether_addr bssid_null = {{0, 0, 0, 0, 0, 0}};
10175
10176                                 if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND)
10177                                         reason = ntoh32(e->reason);
10178                                 /* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */
10179                                 reason = (reason == WLAN_REASON_UNSPECIFIED)? 0 : reason;
10180
10181                                 printf("link down if %s may call cfg80211_disconnected. "
10182                                         "event : %d, reason=%d from " MACDBG "\n",
10183                                         ndev->name, event, ntoh32(e->reason),
10184                                         MAC2STRDBG((const u8*)(&e->addr)));
10185
10186                                 /* roam offload does not sync BSSID always, get it from dongle */
10187                                 if (cfg->roam_offload) {
10188                                         if (wldev_ioctl(ndev, WLC_GET_BSSID, &bssid_dongle,
10189                                                         sizeof(bssid_dongle), false) == BCME_OK) {
10190                                                 /* if not roam case, it would return null bssid */
10191                                                 if (memcmp(&bssid_dongle, &bssid_null,
10192                                                                 ETHER_ADDR_LEN) != 0) {
10193                                                         curbssid = (u8 *)&bssid_dongle;
10194                                                 }
10195                                         }
10196                                 }
10197                                 if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) {
10198                                         bool fw_assoc_state = TRUE;
10199                                         dhd_pub_t *dhd = (dhd_pub_t *)cfg->pub;
10200                                         fw_assoc_state = dhd_is_associated(dhd, e->ifidx, &err);
10201                                         if (!fw_assoc_state) {
10202                                                 WL_ERR(("Even sends up even different BSSID"
10203                                                         " cur: " MACDBG " event: " MACDBG"\n",
10204                                                         MAC2STRDBG(curbssid),
10205                                                         MAC2STRDBG((const u8*)(&e->addr))));
10206                                         } else {
10207                                                 WL_ERR(("BSSID of event is not the connected BSSID"
10208                                                         "(ignore it) cur: " MACDBG
10209                                                         " event: " MACDBG"\n",
10210                                                         MAC2STRDBG(curbssid),
10211                                                         MAC2STRDBG((const u8*)(&e->addr))));
10212                                                 return 0;
10213                                         }
10214                                 }
10215                                 if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) {
10216                                         // terence 20130703: Fix for wrong group_capab (timing issue)
10217                                         cfg->p2p_disconnected = 1;
10218                                 }
10219                                 memcpy(&cfg->disconnected_bssid, curbssid, ETHER_ADDR_LEN);
10220                                 wl_clr_drv_status(cfg, CONNECTED, ndev);
10221                                 if (! wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
10222                                         /* To make sure disconnect, explictly send dissassoc
10223                                         *  for BSSID 00:00:00:00:00:00 issue
10224                                         */
10225                                         scbval.val = WLAN_REASON_DEAUTH_LEAVING;
10226
10227                                         memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
10228                                         scbval.val = htod32(scbval.val);
10229                                         err = wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
10230                                                 sizeof(scb_val_t), true);
10231                                         if (err < 0) {
10232                                                 WL_ERR(("WLC_DISASSOC error %d\n", err));
10233                                                 err = 0;
10234                                         }
10235                                         CFG80211_DISCONNECTED(ndev, reason, NULL, 0,
10236                                                         false, GFP_KERNEL);
10237                                         wl_link_down(cfg);
10238                                         wl_init_prof(cfg, ndev);
10239                                         memset(&cfg->last_roamed_addr, 0, ETHER_ADDR_LEN);
10240                                 }
10241                         }
10242                         else if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
10243                                 printf("link down, during connecting\n");
10244 #ifdef ESCAN_RESULT_PATCH
10245                                 if ((memcmp(connect_req_bssid, broad_bssid, ETHER_ADDR_LEN) == 0) ||
10246                                         (memcmp(&e->addr, broad_bssid, ETHER_ADDR_LEN) == 0) ||
10247                                         (memcmp(&e->addr, connect_req_bssid, ETHER_ADDR_LEN) == 0))
10248                                         /* In case this event comes while associating another AP */
10249 #endif /* ESCAN_RESULT_PATCH */
10250                                         wl_bss_connect_done(cfg, ndev, e, data, false);
10251                         }
10252                         wl_clr_drv_status(cfg, DISCONNECTING, ndev);
10253
10254                         /* if link down, bsscfg is diabled */
10255                         if (ndev != bcmcfg_to_prmry_ndev(cfg))
10256                                 complete(&cfg->iface_disable);
10257
10258                 } else if (wl_is_nonetwork(cfg, e)) {
10259                         printf("connect failed event=%d e->status %d e->reason %d \n",
10260                                 event, (int)ntoh32(e->status), (int)ntoh32(e->reason));
10261 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
10262                         if (event == WLC_E_SET_SSID) {
10263                                 wl_get_connect_failed_status(cfg, e);
10264                         }
10265 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
10266                         /* Clean up any pending scan request */
10267                         wl_cfg80211_cancel_scan(cfg);
10268                         if (wl_get_drv_status(cfg, CONNECTING, ndev))
10269                                 wl_bss_connect_done(cfg, ndev, e, data, false);
10270                 } else {
10271                         WL_DBG(("%s nothing\n", __FUNCTION__));
10272                 }
10273                 DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
10274         }
10275                 else {
10276                 WL_ERR(("Invalid ndev status %d\n", wl_get_mode_by_netdev(cfg, ndev)));
10277         }
10278         return err;
10279 }
10280
10281 void wl_cfg80211_set_rmc_pid(int pid)
10282 {
10283         struct bcm_cfg80211 *cfg = g_bcm_cfg;
10284         if (pid > 0)
10285                 cfg->rmc_event_pid = pid;
10286         WL_DBG(("set pid for rmc event : pid=%d\n", pid));
10287 }
10288
10289 #ifdef WL_RELMCAST
10290 static s32
10291 wl_notify_rmc_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10292         const wl_event_msg_t *e, void *data)
10293 {
10294         u32 evt = ntoh32(e->event_type);
10295         u32 reason = ntoh32(e->reason);
10296         int ret = -1;
10297
10298         switch (reason) {
10299                 case WLC_E_REASON_RMC_AR_LOST:
10300                 case WLC_E_REASON_RMC_AR_NO_ACK:
10301                         if (cfg->rmc_event_pid != 0) {
10302                                 ret = wl_netlink_send_msg(cfg->rmc_event_pid,
10303                                         RMC_EVENT_LEADER_CHECK_FAIL,
10304                                         cfg->rmc_event_seq++, NULL, 0);
10305                         }
10306                         break;
10307                 default:
10308                         break;
10309         }
10310         WL_DBG(("rmcevent : evt=%d, pid=%d, ret=%d\n", evt, cfg->rmc_event_pid, ret));
10311         return ret;
10312 }
10313 #endif /* WL_RELMCAST */
10314 static s32
10315 wl_notify_roaming_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10316         const wl_event_msg_t *e, void *data)
10317 {
10318         bool act;
10319         struct net_device *ndev = NULL;
10320         s32 err = 0;
10321         u32 event = be32_to_cpu(e->event_type);
10322         u32 status = be32_to_cpu(e->status);
10323 #ifdef DHD_LOSSLESS_ROAMING
10324         struct wl_security *sec;
10325 #endif
10326         WL_DBG(("Enter \n"));
10327
10328         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10329
10330         if ((!cfg->disable_roam_event) && (event == WLC_E_BSSID)) {
10331                 wl_add_remove_eventmsg(ndev, WLC_E_ROAM, false);
10332                 cfg->disable_roam_event = TRUE;
10333         }
10334
10335         if ((cfg->disable_roam_event) && (event == WLC_E_ROAM))
10336                 return err;
10337
10338         if ((event == WLC_E_ROAM || event == WLC_E_BSSID) && status == WLC_E_STATUS_SUCCESS) {
10339                 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
10340 #ifdef DHD_LOSSLESS_ROAMING
10341                         if (cfg->roam_offload) {
10342                                 wl_bss_roaming_done(cfg, ndev, e, data);
10343                                 wl_del_roam_timeout(cfg);
10344                         }
10345                         else {
10346                                 sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
10347                                 /* In order to reduce roaming delay, wl_bss_roaming_done is
10348                                  * early called with WLC_E_LINK event. It is called from
10349                                  * here only if WLC_E_LINK event is blocked for specific
10350                                  * security type.
10351                                  */
10352                                 if (IS_AKM_SUITE_FT(sec)) {
10353                                         wl_bss_roaming_done(cfg, ndev, e, data);
10354                                 }
10355                                 /* Roam timer is deleted mostly from wl_cfg80211_change_station
10356                                  * after roaming is finished successfully. We need to delete
10357                                  * the timer from here only for some security types that aren't
10358                                  * using wl_cfg80211_change_station to authorize SCB
10359                                  */
10360                                 if (IS_AKM_SUITE_FT(sec) || IS_AKM_SUITE_CCKM(sec)) {
10361                                         wl_del_roam_timeout(cfg);
10362                                 }
10363                         }
10364 #else
10365                         wl_bss_roaming_done(cfg, ndev, e, data);
10366 #endif /* DHD_LOSSLESS_ROAMING */
10367                 } else {
10368                         wl_bss_connect_done(cfg, ndev, e, data, true);
10369                 }
10370                 act = true;
10371                 wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
10372                 wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
10373         }
10374 #ifdef DHD_LOSSLESS_ROAMING
10375         else if ((event == WLC_E_ROAM || event == WLC_E_BSSID) && status != WLC_E_STATUS_SUCCESS) {
10376                 wl_del_roam_timeout(cfg);
10377         }
10378 #endif
10379         return err;
10380 }
10381
10382 #ifdef QOS_MAP_SET
10383 /* up range from low to high with up value */
10384 static bool
10385 up_table_set(uint8 *up_table, uint8 up, uint8 low, uint8 high)
10386 {
10387         int i;
10388
10389         if (up > 7 || low > high || low >= UP_TABLE_MAX || high >= UP_TABLE_MAX) {
10390                 return FALSE;
10391         }
10392
10393         for (i = low; i <= high; i++) {
10394                 up_table[i] = up;
10395         }
10396
10397         return TRUE;
10398 }
10399
10400 /* set user priority table */
10401 static void
10402 wl_set_up_table(uint8 *up_table, bcm_tlv_t *qos_map_ie)
10403 {
10404         uint8 len;
10405
10406         if (up_table == NULL || qos_map_ie == NULL) {
10407                 return;
10408         }
10409
10410         /* clear table to check table was set or not */
10411         memset(up_table, 0xff, UP_TABLE_MAX);
10412
10413         /* length of QoS Map IE must be 16+n*2, n is number of exceptions */
10414         if (qos_map_ie != NULL && qos_map_ie->id == DOT11_MNG_QOS_MAP_ID &&
10415                         (len = qos_map_ie->len) >= QOS_MAP_FIXED_LENGTH &&
10416                         (len % 2) == 0) {
10417                 uint8 *except_ptr = (uint8 *)qos_map_ie->data;
10418                 uint8 except_len = len - QOS_MAP_FIXED_LENGTH;
10419                 uint8 *range_ptr = except_ptr + except_len;
10420                 int i;
10421
10422                 /* fill in ranges */
10423                 for (i = 0; i < QOS_MAP_FIXED_LENGTH; i += 2) {
10424                         uint8 low = range_ptr[i];
10425                         uint8 high = range_ptr[i + 1];
10426                         if (low == 255 && high == 255) {
10427                                 continue;
10428                         }
10429
10430                         if (!up_table_set(up_table, i / 2, low, high)) {
10431                                 /* clear the table on failure */
10432                                 memset(up_table, 0xff, UP_TABLE_MAX);
10433                                 return;
10434                         }
10435                 }
10436
10437                 /* update exceptions */
10438                 for (i = 0; i < except_len; i += 2) {
10439                         uint8 dscp = except_ptr[i];
10440                         uint8 up = except_ptr[i+1];
10441
10442                         /* exceptions with invalid dscp/up are ignored */
10443                         up_table_set(up_table, up, dscp, dscp);
10444                 }
10445         }
10446
10447         if (wl_dbg_level & WL_DBG_DBG) {
10448                 prhex("UP table", up_table, UP_TABLE_MAX);
10449         }
10450 }
10451
10452 /* get user priority table */
10453 uint8 *
10454 wl_get_up_table(void)
10455 {
10456         return (uint8 *)(g_bcm_cfg->up_table);
10457 }
10458 #endif /* QOS_MAP_SET */
10459
10460 #ifdef DHD_LOSSLESS_ROAMING
10461 static s32
10462 wl_notify_roam_prep_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10463         const wl_event_msg_t *e, void *data)
10464 {
10465         s32 err = 0;
10466         struct wl_security *sec;
10467         struct net_device *ndev;
10468         dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
10469
10470         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10471
10472         sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
10473         /* Disable Lossless Roaming for specific AKM suite
10474          * Any other AKM suite can be added below if transition time
10475          * is delayed because of Lossless Roaming
10476          * and it causes any certication failure
10477          */
10478         if (IS_AKM_SUITE_FT(sec)) {
10479                 return err;
10480         }
10481
10482         dhdp->dequeue_prec_map = 1 << PRIO_8021D_NC;
10483         /* Restore flow control  */
10484         dhd_txflowcontrol(dhdp, ALL_INTERFACES, OFF);
10485
10486         mod_timer(&cfg->roam_timeout, jiffies + msecs_to_jiffies(WL_ROAM_TIMEOUT_MS));
10487
10488         return err;
10489 }
10490 #endif /* DHD_LOSSLESS_ROAMING */
10491
10492 static s32
10493 wl_notify_idsup_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10494                 const wl_event_msg_t *e, void *data)
10495 {
10496         s32 err = 0;
10497 #if defined(WL_VENDOR_EXT_SUPPORT)
10498         u32 idsup_status;
10499         u32 reason = ntoh32(e->reason);
10500         struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10501         struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
10502 #endif /* defined(WL_VENDOR_EXT_SUPPORT) */
10503
10504         if (cfg->roam_offload) {
10505 #if defined(WL_VENDOR_EXT_SUPPORT)
10506                 switch (reason) {
10507                         case WLC_E_SUP_WPA_PSK_TMO:
10508                                 idsup_status = IDSUP_EVENT_4WAY_HANDSHAKE_TIMEOUT;
10509                                 break;
10510                         case WLC_E_SUP_OTHER:
10511                                 idsup_status = IDSUP_EVENT_SUCCESS;
10512                                 break;
10513                         default:
10514                                 WL_ERR(("Other type at IDSUP. "
10515                                                 "event=%d e->status %d e->reason %d \n",
10516                                                 (int)ntoh32(e->event_type), (int)ntoh32(e->status),
10517                                                 (int)ntoh32(e->reason)));
10518                                 return err;
10519                 }
10520
10521                 err = wl_cfgvendor_send_async_event(wiphy, ndev,
10522                                 BRCM_VENDOR_EVENT_IDSUP_STATUS, &idsup_status, sizeof(u32));
10523 #endif /* defined(WL_VENDOR_EXT_SUPPORT) */
10524         }
10525         return err;
10526 }
10527
10528 #ifdef CUSTOM_EVENT_PM_WAKE
10529 static s32
10530 wl_check_pmstatus(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10531                 const wl_event_msg_t *e, void *data)
10532 {
10533         s32 err = 0;
10534         struct net_device *ndev = NULL;
10535         u8 *pbuf = NULL;
10536         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10537
10538         pbuf = kzalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
10539         if (pbuf == NULL) {
10540                 WL_ERR(("failed to allocate local pbuf\n"));
10541                 return -ENOMEM;
10542         }
10543
10544         err = wldev_iovar_getbuf_bsscfg(ndev, "dump",
10545                 "pm", strlen("pm"), pbuf, WLC_IOCTL_MEDLEN, 0, &cfg->ioctl_buf_sync);
10546
10547         if (err) {
10548                 WL_ERR(("dump ioctl err = %d", err));
10549         } else {
10550                 WL_ERR(("PM status : %s\n", pbuf));
10551         }
10552
10553         if (pbuf) {
10554                 kfree(pbuf);
10555         }
10556         return err;
10557 }
10558 #endif /* CUSTOM_EVENT_PM_WAKE */
10559
10560 static s32 wl_get_assoc_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev)
10561 {
10562         wl_assoc_info_t assoc_info;
10563         struct wl_connect_info *conn_info = wl_to_conn(cfg);
10564         s32 err = 0;
10565 #ifdef QOS_MAP_SET
10566         bcm_tlv_t * qos_map_ie = NULL;
10567 #endif /* QOS_MAP_SET */
10568
10569         WL_DBG(("Enter \n"));
10570         err = wldev_iovar_getbuf(ndev, "assoc_info", NULL, 0, cfg->extra_buf,
10571                 WL_ASSOC_INFO_MAX, NULL);
10572         if (unlikely(err)) {
10573                 WL_ERR(("could not get assoc info (%d)\n", err));
10574                 return err;
10575         }
10576         memcpy(&assoc_info, cfg->extra_buf, sizeof(wl_assoc_info_t));
10577         assoc_info.req_len = htod32(assoc_info.req_len);
10578         assoc_info.resp_len = htod32(assoc_info.resp_len);
10579         assoc_info.flags = htod32(assoc_info.flags);
10580         if (conn_info->req_ie_len) {
10581                 conn_info->req_ie_len = 0;
10582                 bzero(conn_info->req_ie, sizeof(conn_info->req_ie));
10583         }
10584         if (conn_info->resp_ie_len) {
10585                 conn_info->resp_ie_len = 0;
10586                 bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie));
10587         }
10588         if (assoc_info.req_len) {
10589                 err = wldev_iovar_getbuf(ndev, "assoc_req_ies", NULL, 0, cfg->extra_buf,
10590                         WL_ASSOC_INFO_MAX, NULL);
10591                 if (unlikely(err)) {
10592                         WL_ERR(("could not get assoc req (%d)\n", err));
10593                         return err;
10594                 }
10595                 conn_info->req_ie_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
10596                 if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
10597                         conn_info->req_ie_len -= ETHER_ADDR_LEN;
10598                 }
10599                 if (conn_info->req_ie_len <= MAX_REQ_LINE)
10600                         memcpy(conn_info->req_ie, cfg->extra_buf, conn_info->req_ie_len);
10601                 else {
10602                         WL_ERR(("IE size %d above max %d size \n",
10603                                 conn_info->req_ie_len, MAX_REQ_LINE));
10604                         return err;
10605                 }
10606         } else {
10607                 conn_info->req_ie_len = 0;
10608         }
10609         if (assoc_info.resp_len) {
10610                 err = wldev_iovar_getbuf(ndev, "assoc_resp_ies", NULL, 0, cfg->extra_buf,
10611                         WL_ASSOC_INFO_MAX, NULL);
10612                 if (unlikely(err)) {
10613                         WL_ERR(("could not get assoc resp (%d)\n", err));
10614                         return err;
10615                 }
10616                 conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp);
10617                 if (conn_info->resp_ie_len <= MAX_REQ_LINE) {
10618                         memcpy(conn_info->resp_ie, cfg->extra_buf, conn_info->resp_ie_len);
10619                 } else {
10620                         WL_ERR(("IE size %d above max %d size \n",
10621                                 conn_info->resp_ie_len, MAX_REQ_LINE));
10622                         return err;
10623                 }
10624
10625 #ifdef QOS_MAP_SET
10626                 /* find qos map set ie */
10627                 if ((qos_map_ie = bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
10628                                 DOT11_MNG_QOS_MAP_ID)) != NULL) {
10629                         WL_DBG((" QoS map set IE found in assoc response\n"));
10630                         if (!cfg->up_table) {
10631                                 cfg->up_table = kmalloc(UP_TABLE_MAX, GFP_KERNEL);
10632                         }
10633                         wl_set_up_table(cfg->up_table, qos_map_ie);
10634                 } else {
10635                         kfree(cfg->up_table);
10636                         cfg->up_table = NULL;
10637                 }
10638 #endif /* QOS_MAP_SET */
10639         } else {
10640                 conn_info->resp_ie_len = 0;
10641         }
10642         WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
10643                 conn_info->resp_ie_len));
10644
10645         return err;
10646 }
10647
10648 static s32 wl_ch_to_chanspec(struct net_device *dev, int ch, struct wl_join_params *join_params,
10649         size_t *join_params_size)
10650 {
10651         struct bcm_cfg80211 *cfg;
10652         s32 bssidx = -1;
10653         chanspec_t chanspec = 0, chspec;
10654
10655         if (ch != 0) {
10656                 cfg = (struct bcm_cfg80211 *)wiphy_priv(dev->ieee80211_ptr->wiphy);
10657                 if (cfg && cfg->rcc_enabled) {
10658                 } else {
10659                         join_params->params.chanspec_num = 1;
10660                         join_params->params.chanspec_list[0] = ch;
10661
10662                         if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
10663                                 chanspec |= WL_CHANSPEC_BAND_2G;
10664                         else
10665                                 chanspec |= WL_CHANSPEC_BAND_5G;
10666
10667                         /* Get the min_bw set for the interface */
10668                         chspec = wl_cfg80211_ulb_get_min_bw_chspec(dev->ieee80211_ptr, bssidx);
10669                         if (chspec == INVCHANSPEC) {
10670                                 WL_ERR(("Invalid chanspec \n"));
10671                                 return -EINVAL;
10672                         }
10673                         chanspec |= chspec;
10674                         chanspec |= WL_CHANSPEC_CTL_SB_NONE;
10675
10676                         *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
10677                                 join_params->params.chanspec_num * sizeof(chanspec_t);
10678
10679                         join_params->params.chanspec_list[0]  &= WL_CHANSPEC_CHAN_MASK;
10680                         join_params->params.chanspec_list[0] |= chanspec;
10681                         join_params->params.chanspec_list[0] =
10682                                 wl_chspec_host_to_driver(join_params->params.chanspec_list[0]);
10683
10684                         join_params->params.chanspec_num =
10685                                 htod32(join_params->params.chanspec_num);
10686                 }
10687
10688                 WL_DBG(("join_params->params.chanspec_list[0]= %X, %d channels\n",
10689                         join_params->params.chanspec_list[0],
10690                         join_params->params.chanspec_num));
10691         }
10692         return 0;
10693 }
10694
10695 static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool roam)
10696 {
10697         struct wl_bss_info *bi;
10698         struct wlc_ssid *ssid;
10699         struct bcm_tlv *tim;
10700         s32 beacon_interval;
10701         s32 dtim_period;
10702         size_t ie_len;
10703         u8 *ie;
10704         u8 *curbssid;
10705         s32 err = 0;
10706         struct wiphy *wiphy;
10707         u32 channel;
10708
10709         wiphy = bcmcfg_to_wiphy(cfg);
10710
10711         ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
10712         curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10713
10714         mutex_lock(&cfg->usr_sync);
10715
10716         *(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
10717         err = wldev_ioctl(ndev, WLC_GET_BSS_INFO,
10718                 cfg->extra_buf, WL_EXTRA_BUF_MAX, false);
10719         if (unlikely(err)) {
10720                 WL_ERR(("Could not get bss info %d\n", err));
10721                 goto update_bss_info_out;
10722         }
10723         bi = (struct wl_bss_info *)(cfg->extra_buf + 4);
10724         channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
10725         wl_update_prof(cfg, ndev, NULL, &channel, WL_PROF_CHAN);
10726
10727         if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) {
10728                 WL_ERR(("Bssid doesn't match\n"));
10729                 err = -EIO;
10730                 goto update_bss_info_out;
10731         }
10732         err = wl_inform_single_bss(cfg, bi, roam);
10733         if (unlikely(err))
10734                 goto update_bss_info_out;
10735
10736         ie = ((u8 *)bi) + bi->ie_offset;
10737         ie_len = bi->ie_length;
10738         beacon_interval = cpu_to_le16(bi->beacon_period);
10739         tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
10740         if (tim) {
10741                 dtim_period = tim->data[1];
10742         } else {
10743                 /*
10744                 * active scan was done so we could not get dtim
10745                 * information out of probe response.
10746                 * so we speficially query dtim information.
10747                 */
10748                 err = wldev_ioctl(ndev, WLC_GET_DTIMPRD,
10749                         &dtim_period, sizeof(dtim_period), false);
10750                 if (unlikely(err)) {
10751                         WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
10752                         goto update_bss_info_out;
10753                 }
10754         }
10755
10756         wl_update_prof(cfg, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT);
10757         wl_update_prof(cfg, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
10758
10759 update_bss_info_out:
10760         if (unlikely(err)) {
10761                 WL_ERR(("Failed with error %d\n", err));
10762         }
10763         mutex_unlock(&cfg->usr_sync);
10764         return err;
10765 }
10766
10767 static s32
10768 wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
10769         const wl_event_msg_t *e, void *data)
10770 {
10771         struct wl_connect_info *conn_info = wl_to_conn(cfg);
10772         s32 err = 0;
10773         u8 *curbssid;
10774 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
10775         struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
10776         struct ieee80211_supported_band *band;
10777         struct ieee80211_channel *notify_channel = NULL;
10778         u32 *channel;
10779         u32 freq;
10780 #endif 
10781
10782
10783         if (memcmp(&cfg->last_roamed_addr, &e->addr, ETHER_ADDR_LEN) == 0) {
10784                 WL_INFORM(("BSSID already updated\n"));
10785                 return err;
10786         }
10787
10788         /* Skip calling cfg80211_roamed If current bssid and
10789          * roamed bssid are same. Also clear timer roam_timeout.
10790          */
10791         curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10792         if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) == 0) {
10793                 WL_ERR(("BSS already present, Skipping roamed event to upper layer\n"));
10794 #ifdef DHD_LOSSLESS_ROAMING
10795                 wl_del_roam_timeout(cfg);
10796 #endif  /* DHD_LOSSLESS_ROAMING */
10797                 return  err;
10798         }
10799
10800         wl_get_assoc_ies(cfg, ndev);
10801         wl_update_prof(cfg, ndev, NULL, (const void *)(e->addr.octet), WL_PROF_BSSID);
10802         curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10803         wl_update_bss_info(cfg, ndev, true);
10804         wl_update_pmklist(ndev, cfg->pmk_list, err);
10805
10806 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
10807         /* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */
10808         channel = (u32 *)wl_read_prof(cfg, ndev, WL_PROF_CHAN);
10809         if (*channel <= CH_MAX_2G_CHANNEL)
10810                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
10811         else
10812                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
10813         freq = ieee80211_channel_to_frequency(*channel, band->band);
10814         notify_channel = ieee80211_get_channel(wiphy, freq);
10815 #endif 
10816         printf("wl_bss_roaming_done succeeded to " MACDBG "\n",
10817                 MAC2STRDBG((const u8*)(&e->addr)));
10818         dhd_conf_set_wme(cfg->pub);
10819
10820         cfg80211_roamed(ndev,
10821 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
10822                 notify_channel,
10823 #endif
10824                 curbssid,
10825                 conn_info->req_ie, conn_info->req_ie_len,
10826                 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
10827         WL_DBG(("Report roaming result\n"));
10828
10829         memcpy(&cfg->last_roamed_addr, (void *)&e->addr, ETHER_ADDR_LEN);
10830         wl_set_drv_status(cfg, CONNECTED, ndev);
10831
10832 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
10833         cfg->roam_count++;
10834 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
10835
10836         return err;
10837 }
10838
10839 static s32
10840 wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
10841         const wl_event_msg_t *e, void *data, bool completed)
10842 {
10843         struct wl_connect_info *conn_info = wl_to_conn(cfg);
10844         struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
10845 #if defined(CUSTOM_SET_CPUCORE)
10846         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
10847 #endif 
10848         s32 err = 0;
10849         u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10850         if (!sec) {
10851                 WL_ERR(("sec is NULL\n"));
10852                 return -ENODEV;
10853         }
10854         WL_DBG((" enter\n"));
10855 #ifdef ESCAN_RESULT_PATCH
10856         if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
10857                 if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) {
10858                         WL_DBG((" Connected event of connected device e=%d s=%d, ignore it\n",
10859                                 ntoh32(e->event_type), ntoh32(e->status)));
10860                         return err;
10861                 }
10862         }
10863         if (memcmp(curbssid, broad_bssid, ETHER_ADDR_LEN) == 0 &&
10864                 memcmp(broad_bssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) {
10865                 WL_DBG(("copy bssid\n"));
10866                 memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN);
10867         }
10868
10869 #else
10870         if (cfg->scan_request) {
10871                 wl_notify_escan_complete(cfg, ndev, true, true);
10872         }
10873 #endif /* ESCAN_RESULT_PATCH */
10874         if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
10875                 wl_cfg80211_scan_abort(cfg);
10876                 wl_clr_drv_status(cfg, CONNECTING, ndev);
10877                 if (completed) {
10878                         wl_get_assoc_ies(cfg, ndev);
10879                         wl_update_prof(cfg, ndev, NULL, (const void *)(e->addr.octet),
10880                                 WL_PROF_BSSID);
10881                         curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10882                         wl_update_bss_info(cfg, ndev, false);
10883                         wl_update_pmklist(ndev, cfg->pmk_list, err);
10884                         wl_set_drv_status(cfg, CONNECTED, ndev);
10885                         if (ndev != bcmcfg_to_prmry_ndev(cfg)) {
10886 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
10887                                 init_completion(&cfg->iface_disable);
10888 #else
10889                                 /* reinitialize completion to clear previous count */
10890                                 INIT_COMPLETION(cfg->iface_disable);
10891 #endif
10892                         }
10893 #ifdef CUSTOM_SET_CPUCORE
10894                         if (wl_get_chan_isvht80(ndev, dhd)) {
10895                                 if (ndev == bcmcfg_to_prmry_ndev(cfg))
10896                                         dhd->chan_isvht80 |= DHD_FLAG_STA_MODE; /* STA mode */
10897                                 else if (is_p2p_group_iface(ndev->ieee80211_ptr))
10898                                         dhd->chan_isvht80 |= DHD_FLAG_P2P_MODE; /* p2p mode */
10899                                 dhd_set_cpucore(dhd, TRUE);
10900                         }
10901 #endif /* CUSTOM_SET_CPUCORE */
10902
10903                 }
10904                 cfg80211_connect_result(ndev,
10905                         curbssid,
10906                         conn_info->req_ie,
10907                         conn_info->req_ie_len,
10908                         conn_info->resp_ie,
10909                         conn_info->resp_ie_len,
10910                         completed ? WLAN_STATUS_SUCCESS :
10911                         (sec->auth_assoc_res_status) ?
10912                         sec->auth_assoc_res_status :
10913                         WLAN_STATUS_UNSPECIFIED_FAILURE,
10914                         GFP_KERNEL);
10915                 if (completed) {
10916                         WL_INFORM(("Report connect result - connection succeeded\n"));
10917                         dhd_conf_set_wme(cfg->pub);
10918                 } else
10919                         WL_ERR(("Report connect result - connection failed\n"));
10920         }
10921 #ifdef CONFIG_TCPACK_FASTTX
10922         if (wl_get_chan_isvht80(ndev, dhd))
10923                 wldev_iovar_setint(ndev, "tcpack_fast_tx", 0);
10924         else
10925                 wldev_iovar_setint(ndev, "tcpack_fast_tx", 1);
10926 #endif /* CONFIG_TCPACK_FASTTX */
10927
10928         return err;
10929 }
10930
10931 static s32
10932 wl_notify_mic_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10933         const wl_event_msg_t *e, void *data)
10934 {
10935         struct net_device *ndev = NULL;
10936         u16 flags = ntoh16(e->flags);
10937         enum nl80211_key_type key_type;
10938
10939         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10940
10941         mutex_lock(&cfg->usr_sync);
10942         if (flags & WLC_EVENT_MSG_GROUP)
10943                 key_type = NL80211_KEYTYPE_GROUP;
10944         else
10945                 key_type = NL80211_KEYTYPE_PAIRWISE;
10946
10947         cfg80211_michael_mic_failure(ndev, (const u8 *)&e->addr, key_type, -1,
10948                 NULL, GFP_KERNEL);
10949         mutex_unlock(&cfg->usr_sync);
10950
10951         return 0;
10952 }
10953
10954 #ifdef BT_WIFI_HANDOVER
10955 static s32
10956 wl_notify_bt_wifi_handover_req(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10957         const wl_event_msg_t *e, void *data)
10958 {
10959         struct net_device *ndev = NULL;
10960         u32 event = ntoh32(e->event_type);
10961         u32 datalen = ntoh32(e->datalen);
10962         s32 err;
10963
10964         WL_ERR(("wl_notify_bt_wifi_handover_req: event_type : %d, datalen : %d\n", event, datalen));
10965         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10966         err = wl_genl_send_msg(ndev, event, data, (u16)datalen, 0, 0);
10967
10968         return err;
10969 }
10970 #endif /* BT_WIFI_HANDOVER */
10971
10972 #ifdef PNO_SUPPORT
10973 static s32
10974 wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10975         const wl_event_msg_t *e, void *data)
10976 {
10977         struct net_device *ndev = NULL;
10978
10979         WL_ERR((">>> PNO Event\n"));
10980
10981         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10982
10983 #ifndef WL_SCHED_SCAN
10984         mutex_lock(&cfg->usr_sync);
10985         /* TODO: Use cfg80211_sched_scan_results(wiphy); */
10986         CFG80211_DISCONNECTED(ndev, 0, NULL, 0, false, GFP_KERNEL);
10987         mutex_unlock(&cfg->usr_sync);
10988 #else
10989         /* If cfg80211 scheduled scan is supported, report the pno results via sched
10990          * scan results
10991          */
10992         wl_notify_sched_scan_results(cfg, ndev, e, data);
10993 #endif /* WL_SCHED_SCAN */
10994         return 0;
10995 }
10996 #endif /* PNO_SUPPORT */
10997
10998 #ifdef GSCAN_SUPPORT
10999 static s32
11000 wl_notify_gscan_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
11001         const wl_event_msg_t *e, void *data)
11002 {
11003         s32 err = 0;
11004         u32 event = be32_to_cpu(e->event_type);
11005         void *ptr;
11006         int send_evt_bytes = 0;
11007         int batch_event_result_dummy = 0;
11008         struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
11009         struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
11010         u32 len = ntoh32(e->datalen);
11011
11012         switch (event) {
11013                 case WLC_E_PFN_SWC:
11014                         ptr = dhd_dev_swc_scan_event(ndev, data, &send_evt_bytes);
11015                         if (send_evt_bytes) {
11016                                 wl_cfgvendor_send_async_event(wiphy, ndev,
11017                                     GOOGLE_GSCAN_SIGNIFICANT_EVENT, ptr, send_evt_bytes);
11018                                 kfree(ptr);
11019                         }
11020                         break;
11021                 case WLC_E_PFN_BEST_BATCHING:
11022                         err = dhd_dev_retrieve_batch_scan(ndev);
11023                         if (err < 0) {
11024                                 WL_ERR(("Batch retrieval already in progress %d\n", err));
11025                         } else {
11026                                 wl_cfgvendor_send_async_event(wiphy, ndev,
11027                                     GOOGLE_GSCAN_BATCH_SCAN_EVENT,
11028                                      &batch_event_result_dummy, sizeof(int));
11029                         }
11030                         break;
11031                 case WLC_E_PFN_SCAN_COMPLETE:
11032                         batch_event_result_dummy = WIFI_SCAN_COMPLETE;
11033                         wl_cfgvendor_send_async_event(wiphy, ndev,
11034                                 GOOGLE_SCAN_COMPLETE_EVENT,
11035                                 &batch_event_result_dummy, sizeof(int));
11036                         break;
11037                 case WLC_E_PFN_BSSID_NET_FOUND:
11038                         ptr = dhd_dev_hotlist_scan_event(ndev, data, &send_evt_bytes,
11039                               HOTLIST_FOUND);
11040                         if (ptr) {
11041                                 wl_cfgvendor_send_hotlist_event(wiphy, ndev,
11042                                  ptr, send_evt_bytes, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT);
11043                                 dhd_dev_gscan_hotlist_cache_cleanup(ndev, HOTLIST_FOUND);
11044                         }
11045                         break;
11046                 case WLC_E_PFN_BSSID_NET_LOST:
11047                         /* WLC_E_PFN_BSSID_NET_LOST is conflict shared with WLC_E_PFN_SCAN_ALLGONE
11048                          * We currently do not use WLC_E_PFN_SCAN_ALLGONE, so if we get it, ignore
11049                          */
11050                         if (len) {
11051                                 ptr = dhd_dev_hotlist_scan_event(ndev, data, &send_evt_bytes,
11052                                             HOTLIST_LOST);
11053                                 if (ptr) {
11054                                         wl_cfgvendor_send_hotlist_event(wiphy, ndev,
11055                                          ptr, send_evt_bytes, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT);
11056                                         dhd_dev_gscan_hotlist_cache_cleanup(ndev, HOTLIST_LOST);
11057                                 }
11058                         }
11059                         break;
11060                 case WLC_E_PFN_GSCAN_FULL_RESULT:
11061                         ptr = dhd_dev_process_full_gscan_result(ndev, data, &send_evt_bytes);
11062                         if (ptr) {
11063                                 wl_cfgvendor_send_async_event(wiphy, ndev,
11064                                     GOOGLE_SCAN_FULL_RESULTS_EVENT, ptr, send_evt_bytes);
11065                                 kfree(ptr);
11066                         }
11067                         break;
11068                 default:
11069                         WL_ERR(("%s: Unexpected event! - %d\n", __FUNCTION__, event));
11070
11071         }
11072         return err;
11073 }
11074 #endif /* GSCAN_SUPPORT */
11075
11076 static s32
11077 wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
11078         const wl_event_msg_t *e, void *data)
11079 {
11080         struct channel_info channel_inform;
11081         struct wl_scan_results *bss_list;
11082         struct net_device *ndev = NULL;
11083         u32 len = WL_SCAN_BUF_MAX;
11084         s32 err = 0;
11085         unsigned long flags;
11086
11087         WL_DBG(("Enter \n"));
11088         if (!wl_get_drv_status(cfg, SCANNING, ndev)) {
11089                 WL_ERR(("scan is not ready \n"));
11090                 return err;
11091         }
11092         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
11093
11094         mutex_lock(&cfg->usr_sync);
11095         wl_clr_drv_status(cfg, SCANNING, ndev);
11096         err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
11097                 sizeof(channel_inform), false);
11098         if (unlikely(err)) {
11099                 WL_ERR(("scan busy (%d)\n", err));
11100                 goto scan_done_out;
11101         }
11102         channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
11103         if (unlikely(channel_inform.scan_channel)) {
11104
11105                 WL_DBG(("channel_inform.scan_channel (%d)\n",
11106                         channel_inform.scan_channel));
11107         }
11108         cfg->bss_list = cfg->scan_results;
11109         bss_list = cfg->bss_list;
11110         memset(bss_list, 0, len);
11111         bss_list->buflen = htod32(len);
11112         err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, false);
11113         if (unlikely(err) && unlikely(!cfg->scan_suppressed)) {
11114                 WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
11115                 err = -EINVAL;
11116                 goto scan_done_out;
11117         }
11118         bss_list->buflen = dtoh32(bss_list->buflen);
11119         bss_list->version = dtoh32(bss_list->version);
11120         bss_list->count = dtoh32(bss_list->count);
11121
11122         err = wl_inform_bss(cfg);
11123
11124 scan_done_out:
11125         del_timer_sync(&cfg->scan_timeout);
11126         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
11127         if (cfg->scan_request) {
11128                 cfg80211_scan_done(cfg->scan_request, false);
11129                 cfg->scan_request = NULL;
11130         }
11131         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
11132         WL_DBG(("cfg80211_scan_done\n"));
11133         mutex_unlock(&cfg->usr_sync);
11134         return err;
11135 }
11136
11137 static s32
11138 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
11139         const struct ether_addr *sa, const struct ether_addr *bssid,
11140         u8 **pheader, u32 *body_len, u8 *pbody)
11141 {
11142         struct dot11_management_header *hdr;
11143         u32 totlen = 0;
11144         s32 err = 0;
11145         u8 *offset;
11146         u32 prebody_len = *body_len;
11147         switch (fc) {
11148                 case FC_ASSOC_REQ:
11149                         /* capability , listen interval */
11150                         totlen = DOT11_ASSOC_REQ_FIXED_LEN;
11151                         *body_len += DOT11_ASSOC_REQ_FIXED_LEN;
11152                         break;
11153
11154                 case FC_REASSOC_REQ:
11155                         /* capability, listen inteval, ap address */
11156                         totlen = DOT11_REASSOC_REQ_FIXED_LEN;
11157                         *body_len += DOT11_REASSOC_REQ_FIXED_LEN;
11158                         break;
11159         }
11160         totlen += DOT11_MGMT_HDR_LEN + prebody_len;
11161         *pheader = kzalloc(totlen, GFP_KERNEL);
11162         if (*pheader == NULL) {
11163                 WL_ERR(("memory alloc failed \n"));
11164                 return -ENOMEM;
11165         }
11166         hdr = (struct dot11_management_header *) (*pheader);
11167         hdr->fc = htol16(fc);
11168         hdr->durid = 0;
11169         hdr->seq = 0;
11170         offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
11171         bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
11172         bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
11173         bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
11174         if ((pbody != NULL) && prebody_len)
11175                 bcopy((const char*)pbody, offset, prebody_len);
11176         *body_len = totlen;
11177         return err;
11178 }
11179
11180
11181 void
11182 wl_stop_wait_next_action_frame(struct bcm_cfg80211 *cfg, struct net_device *ndev)
11183 {
11184         if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
11185                 if (timer_pending(&cfg->p2p->listen_timer)) {
11186                         del_timer_sync(&cfg->p2p->listen_timer);
11187                 }
11188                 if (cfg->afx_hdl != NULL) {
11189                         if (cfg->afx_hdl->dev != NULL) {
11190                                 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
11191                                 wl_clr_drv_status(cfg, FINDING_COMMON_CHANNEL, cfg->afx_hdl->dev);
11192                         }
11193                         cfg->afx_hdl->peer_chan = WL_INVALID;
11194                 }
11195                 complete(&cfg->act_frm_scan);
11196                 WL_DBG(("*** Wake UP ** Working afx searching is cleared\n"));
11197         } else if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM)) {
11198                 if (!(wl_get_p2p_status(cfg, ACTION_TX_COMPLETED) ||
11199                         wl_get_p2p_status(cfg, ACTION_TX_NOACK)))
11200                         wl_set_p2p_status(cfg, ACTION_TX_COMPLETED);
11201
11202                 WL_DBG(("*** Wake UP ** abort actframe iovar\n"));
11203                 /* if channel is not zero, "actfame" uses off channel scan.
11204                  * So abort scan for off channel completion.
11205                  */
11206                 if (cfg->af_sent_channel)
11207                         wl_cfg80211_scan_abort(cfg);
11208         }
11209 #ifdef WL_CFG80211_SYNC_GON
11210         else if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
11211                 WL_DBG(("*** Wake UP ** abort listen for next af frame\n"));
11212                 /* So abort scan to cancel listen */
11213                 wl_cfg80211_scan_abort(cfg);
11214         }
11215 #endif /* WL_CFG80211_SYNC_GON */
11216 }
11217
11218 #if defined(WLTDLS)
11219 bool wl_cfg80211_is_tdls_tunneled_frame(void *frame, u32 frame_len)
11220 {
11221         unsigned char *data;
11222
11223         if (frame == NULL) {
11224                 WL_ERR(("Invalid frame \n"));
11225                 return false;
11226         }
11227
11228         if (frame_len < 5) {
11229                 WL_ERR(("Invalid frame length [%d] \n", frame_len));
11230                 return false;
11231         }
11232
11233         data = frame;
11234
11235         if (!memcmp(data, TDLS_TUNNELED_PRB_REQ, 5) ||
11236                 !memcmp(data, TDLS_TUNNELED_PRB_RESP, 5)) {
11237                 WL_DBG(("TDLS Vendor Specific Received type\n"));
11238                 return true;
11239         }
11240
11241         return false;
11242 }
11243 #endif /* WLTDLS */
11244
11245
11246 int wl_cfg80211_get_ioctl_version(void)
11247 {
11248         return ioctl_version;
11249 }
11250
11251 static s32
11252 wl_notify_rx_mgmt_frame(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
11253         const wl_event_msg_t *e, void *data)
11254 {
11255         struct ieee80211_supported_band *band;
11256         struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
11257         struct ether_addr da;
11258         struct ether_addr bssid;
11259         bool isfree = false;
11260         s32 err = 0;
11261         s32 freq;
11262         struct net_device *ndev = NULL;
11263         wifi_p2p_pub_act_frame_t *act_frm = NULL;
11264         wifi_p2p_action_frame_t *p2p_act_frm = NULL;
11265         wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
11266 #if defined(WLTDLS) && defined(TDLS_MSG_ONLY_WFD)
11267         dhd_pub_t *dhdp;
11268 #endif /* WLTDLS && TDLS_MSG_ONLY_WFD */
11269         wl_event_rx_frame_data_t *rxframe =
11270                 (wl_event_rx_frame_data_t*)data;
11271         u32 event = ntoh32(e->event_type);
11272         u8 *mgmt_frame;
11273         u8 bsscfgidx = e->bsscfgidx;
11274         u32 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t);
11275         u16 channel = ((ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK));
11276
11277         memset(&bssid, 0, ETHER_ADDR_LEN);
11278
11279         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
11280
11281         if (channel <= CH_MAX_2G_CHANNEL)
11282                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
11283         else
11284                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
11285         if (!band) {
11286                 WL_ERR(("No valid band\n"));
11287                 return -EINVAL;
11288         }
11289 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
11290         freq = ieee80211_channel_to_frequency(channel);
11291         (void)band->band;
11292 #else
11293         freq = ieee80211_channel_to_frequency(channel, band->band);
11294 #endif
11295         if (event == WLC_E_ACTION_FRAME_RX) {
11296                 wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
11297                         NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &cfg->ioctl_buf_sync);
11298
11299                 err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
11300                 if (err < 0)
11301                          WL_ERR(("WLC_GET_BSSID error %d\n", err));
11302                 memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
11303                 err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid,
11304                         &mgmt_frame, &mgmt_frame_len,
11305                         (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1));
11306                 if (err < 0) {
11307                         WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n",
11308                                 mgmt_frame_len, channel, freq));
11309                         goto exit;
11310                 }
11311                 isfree = true;
11312                 if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11313                         mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
11314                         act_frm = (wifi_p2p_pub_act_frame_t *)
11315                                         (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
11316                 } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11317                         mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
11318                         p2p_act_frm = (wifi_p2p_action_frame_t *)
11319                                         (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
11320                         (void) p2p_act_frm;
11321                 } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11322                         mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
11323
11324                         sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)
11325                                         (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
11326                         if (sd_act_frm && wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
11327                                 if (cfg->next_af_subtype == sd_act_frm->action) {
11328                                         WL_DBG(("We got a right next frame of SD!(%d)\n",
11329                                                 sd_act_frm->action));
11330                                         wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
11331
11332                                         /* Stop waiting for next AF. */
11333                                         wl_stop_wait_next_action_frame(cfg, ndev);
11334                                 }
11335                         }
11336                         (void) sd_act_frm;
11337 #ifdef WLTDLS
11338                 } else if ((mgmt_frame[DOT11_MGMT_HDR_LEN] == TDLS_AF_CATEGORY) ||
11339                                 (wl_cfg80211_is_tdls_tunneled_frame(
11340                                     &mgmt_frame[DOT11_MGMT_HDR_LEN],
11341                                     mgmt_frame_len - DOT11_MGMT_HDR_LEN))) {
11342                         if (mgmt_frame[DOT11_MGMT_HDR_LEN] == TDLS_AF_CATEGORY) {
11343                                 WL_ERR((" TDLS Action Frame Received type = %d \n",
11344                                         mgmt_frame[DOT11_MGMT_HDR_LEN + 1]));
11345                         }
11346 #ifdef TDLS_MSG_ONLY_WFD
11347                         dhdp = (dhd_pub_t *)(cfg->pub);
11348                         if (!dhdp->tdls_mode) {
11349                                 WL_DBG((" TDLS Frame filtered \n"));
11350                                 return 0;
11351                         }
11352 #else
11353                         if (mgmt_frame[DOT11_MGMT_HDR_LEN + 1] == TDLS_ACTION_SETUP_RESP) {
11354                                 cfg->tdls_mgmt_frame = mgmt_frame;
11355                                 cfg->tdls_mgmt_frame_len = mgmt_frame_len;
11356                                 cfg->tdls_mgmt_freq = freq;
11357                                 return 0;
11358                         }
11359 #endif /* TDLS_MSG_ONLY_WFD */
11360 #endif /* WLTDLS */
11361 #ifdef QOS_MAP_SET
11362                 } else if (mgmt_frame[DOT11_MGMT_HDR_LEN] == DOT11_ACTION_CAT_QOS) {
11363                         /* update QoS map set table */
11364                         bcm_tlv_t * qos_map_ie = NULL;
11365                         if ((qos_map_ie = bcm_parse_tlvs(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11366                                         mgmt_frame_len - DOT11_MGMT_HDR_LEN,
11367                                         DOT11_MNG_QOS_MAP_ID)) != NULL) {
11368                                 WL_DBG((" QoS map set IE found in QoS action frame\n"));
11369                                 if (!cfg->up_table) {
11370                                         cfg->up_table = kmalloc(UP_TABLE_MAX, GFP_KERNEL);
11371                                 }
11372                                 wl_set_up_table(cfg->up_table, qos_map_ie);
11373                         } else {
11374                                 kfree(cfg->up_table);
11375                                 cfg->up_table = NULL;
11376                         }
11377 #endif /* QOS_MAP_SET */
11378                 } else {
11379                         /*
11380                          *  if we got normal action frame and ndev is p2p0,
11381                          *  we have to change ndev from p2p0 to wlan0
11382                          */
11383
11384
11385                         if (cfg->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
11386                                 u8 action = 0;
11387                                 if (wl_get_public_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11388                                         mgmt_frame_len - DOT11_MGMT_HDR_LEN, &action) != BCME_OK) {
11389                                         WL_DBG(("Recived action is not public action frame\n"));
11390                                 } else if (cfg->next_af_subtype == action) {
11391                                         WL_DBG(("Recived action is the waiting action(%d)\n",
11392                                                 action));
11393                                         wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
11394
11395                                         /* Stop waiting for next AF. */
11396                                         wl_stop_wait_next_action_frame(cfg, ndev);
11397                                 }
11398                         }
11399                 }
11400
11401                 if (act_frm) {
11402
11403                         if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
11404                                 if (cfg->next_af_subtype == act_frm->subtype) {
11405                                         WL_DBG(("We got a right next frame!(%d)\n",
11406                                                 act_frm->subtype));
11407                                         wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
11408
11409                                         if (cfg->next_af_subtype == P2P_PAF_GON_CONF) {
11410                                                 OSL_SLEEP(20);
11411                                         }
11412
11413                                         /* Stop waiting for next AF. */
11414                                         wl_stop_wait_next_action_frame(cfg, ndev);
11415                                 }
11416                         }
11417                 }
11418
11419                 wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN],
11420                         mgmt_frame_len - DOT11_MGMT_HDR_LEN, channel);
11421                 /*
11422                  * After complete GO Negotiation, roll back to mpc mode
11423                  */
11424                 if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) ||
11425                         (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
11426                         wldev_iovar_setint(ndev, "mpc", 1);
11427                 }
11428                 if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) {
11429                         WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
11430                         wl_clr_p2p_status(cfg, GO_NEG_PHASE);
11431                 }
11432         } else if (event == WLC_E_PROBREQ_MSG) {
11433
11434                 /* Handle probe reqs frame
11435                  * WPS-AP certification 4.2.13
11436                  */
11437                 struct parsed_ies prbreq_ies;
11438                 u32 prbreq_ie_len = 0;
11439                 bool pbc = 0;
11440
11441                 WL_DBG((" Event WLC_E_PROBREQ_MSG received\n"));
11442                 mgmt_frame = (u8 *)(data);
11443                 mgmt_frame_len = ntoh32(e->datalen);
11444
11445                 prbreq_ie_len = mgmt_frame_len - DOT11_MGMT_HDR_LEN;
11446
11447                 /* Parse prob_req IEs */
11448                 if (wl_cfg80211_parse_ies(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11449                         prbreq_ie_len, &prbreq_ies) < 0) {
11450                         WL_ERR(("Prob req get IEs failed\n"));
11451                         return 0;
11452                 }
11453                 if (prbreq_ies.wps_ie != NULL) {
11454                         wl_validate_wps_ie((char *)prbreq_ies.wps_ie, prbreq_ies.wps_ie_len, &pbc);
11455                         WL_DBG((" wps_ie exist pbc = %d\n", pbc));
11456                         /* if pbc method, send prob_req mgmt frame to upper layer */
11457                         if (!pbc)
11458                                 return 0;
11459                 } else
11460                         return 0;
11461         } else {
11462                 mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
11463
11464                 /* wpa supplicant use probe request event for restarting another GON Req.
11465                  * but it makes GON Req repetition.
11466                  * so if src addr of prb req is same as my target device,
11467                  * do not send probe request event during sending action frame.
11468                  */
11469                 if (event == WLC_E_P2P_PROBREQ_MSG) {
11470                         WL_DBG((" Event %s\n", (event == WLC_E_P2P_PROBREQ_MSG) ?
11471                                 "WLC_E_P2P_PROBREQ_MSG":"WLC_E_PROBREQ_MSG"));
11472
11473
11474                         /* Filter any P2P probe reqs arriving during the
11475                          * GO-NEG Phase
11476                          */
11477                         if (cfg->p2p &&
11478 #if defined(P2P_IE_MISSING_FIX)
11479                                 cfg->p2p_prb_noti &&
11480 #endif
11481                                 wl_get_p2p_status(cfg, GO_NEG_PHASE)) {
11482                                 WL_DBG(("Filtering P2P probe_req while "
11483                                         "being in GO-Neg state\n"));
11484                                 return 0;
11485                         }
11486                 }
11487         }
11488
11489         if (discover_cfgdev(cfgdev, cfg))
11490                 WL_DBG(("Rx Managment frame For P2P Discovery Interface \n"));
11491         else
11492                 WL_DBG(("Rx Managment frame For Iface (%s) \n", ndev->name));
11493
11494 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
11495         cfg80211_rx_mgmt(cfgdev, freq, 0,  mgmt_frame, mgmt_frame_len, 0);
11496 #elif(LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
11497         cfg80211_rx_mgmt(cfgdev, freq, 0,  mgmt_frame, mgmt_frame_len, 0, GFP_ATOMIC);
11498 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
11499         defined(WL_COMPAT_WIRELESS)
11500         cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
11501 #else
11502         cfg80211_rx_mgmt(cfgdev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
11503 #endif /* LINUX_VERSION >= VERSION(3, 14, 0) */
11504
11505         WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n",
11506                 mgmt_frame_len, ntoh32(e->datalen), channel, freq));
11507 exit:
11508         if (isfree)
11509                 kfree(mgmt_frame);
11510         return 0;
11511 }
11512
11513 #ifdef WL_SCHED_SCAN
11514 /* If target scan is not reliable, set the below define to "1" to do a
11515  * full escan
11516  */
11517 #define FULL_ESCAN_ON_PFN_NET_FOUND             0
11518 static s32
11519 wl_notify_sched_scan_results(struct bcm_cfg80211 *cfg, struct net_device *ndev,
11520         const wl_event_msg_t *e, void *data)
11521 {
11522         wl_pfn_net_info_t *netinfo, *pnetinfo;
11523         struct wiphy *wiphy     = bcmcfg_to_wiphy(cfg);
11524         int err = 0;
11525         struct cfg80211_scan_request *request = NULL;
11526         struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
11527         struct ieee80211_channel *channel = NULL;
11528         int channel_req = 0;
11529         int band = 0;
11530         struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data;
11531         int n_pfn_results = pfn_result->count;
11532
11533         WL_DBG(("Enter\n"));
11534
11535         if (e->event_type == WLC_E_PFN_NET_LOST) {
11536                 WL_PNO(("PFN NET LOST event. Do Nothing \n"));
11537                 return 0;
11538         }
11539         WL_PNO((">>> PFN NET FOUND event. count:%d \n", n_pfn_results));
11540         if (n_pfn_results > 0) {
11541                 int i;
11542
11543                 if (n_pfn_results > MAX_PFN_LIST_COUNT)
11544                         n_pfn_results = MAX_PFN_LIST_COUNT;
11545                 pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t)
11546                                 - sizeof(wl_pfn_net_info_t));
11547
11548                 memset(&ssid, 0x00, sizeof(ssid));
11549
11550                 request = kzalloc(sizeof(*request)
11551                         + sizeof(*request->channels) * n_pfn_results,
11552                         GFP_KERNEL);
11553                 channel = (struct ieee80211_channel *)kzalloc(
11554                         (sizeof(struct ieee80211_channel) * n_pfn_results),
11555                         GFP_KERNEL);
11556                 if (!request || !channel) {
11557                         WL_ERR(("No memory"));
11558                         err = -ENOMEM;
11559                         goto out_err;
11560                 }
11561
11562                 request->wiphy = wiphy;
11563
11564                 for (i = 0; i < n_pfn_results; i++) {
11565                         netinfo = &pnetinfo[i];
11566                         if (!netinfo) {
11567                                 WL_ERR(("Invalid netinfo ptr. index:%d", i));
11568                                 err = -EINVAL;
11569                                 goto out_err;
11570                         }
11571                         WL_PNO((">>> SSID:%s Channel:%d \n",
11572                                 netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel));
11573                         /* PFN result doesn't have all the info which are required by the supplicant
11574                          * (For e.g IEs) Do a target Escan so that sched scan results are reported
11575                          * via wl_inform_single_bss in the required format. Escan does require the
11576                          * scan request in the form of cfg80211_scan_request. For timebeing, create
11577                          * cfg80211_scan_request one out of the received PNO event.
11578                          */
11579                         memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID,
11580                                 netinfo->pfnsubnet.SSID_len);
11581                         ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len;
11582                         request->n_ssids++;
11583
11584                         channel_req = netinfo->pfnsubnet.channel;
11585                         band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
11586                                 : NL80211_BAND_5GHZ;
11587                         channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band);
11588                         channel[i].band = band;
11589                         channel[i].flags |= IEEE80211_CHAN_NO_HT40;
11590                         request->channels[i] = &channel[i];
11591                         request->n_channels++;
11592                 }
11593
11594                 /* assign parsed ssid array */
11595                 if (request->n_ssids)
11596                         request->ssids = &ssid[0];
11597
11598                 if (wl_get_drv_status_all(cfg, SCANNING)) {
11599                         /* Abort any on-going scan */
11600                         wl_notify_escan_complete(cfg, ndev, true, true);
11601                 }
11602
11603                 if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
11604                         WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
11605                         err = wl_cfgp2p_discover_enable_search(cfg, false);
11606                         if (unlikely(err)) {
11607                                 wl_clr_drv_status(cfg, SCANNING, ndev);
11608                                 goto out_err;
11609                         }
11610                         p2p_scan(cfg) = false;
11611                 }
11612
11613                 wl_set_drv_status(cfg, SCANNING, ndev);
11614 #if FULL_ESCAN_ON_PFN_NET_FOUND
11615                 WL_PNO((">>> Doing Full ESCAN on PNO event\n"));
11616                 err = wl_do_escan(cfg, wiphy, ndev, NULL);
11617 #else
11618                 WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
11619                 err = wl_do_escan(cfg, wiphy, ndev, request);
11620 #endif
11621                 if (err) {
11622                         wl_clr_drv_status(cfg, SCANNING, ndev);
11623                         goto out_err;
11624                 }
11625                 cfg->sched_scan_running = TRUE;
11626         }
11627         else {
11628                 WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
11629         }
11630 out_err:
11631         if (request)
11632                 kfree(request);
11633         if (channel)
11634                 kfree(channel);
11635         return err;
11636 }
11637 #endif /* WL_SCHED_SCAN */
11638
11639 static void wl_init_conf(struct wl_conf *conf)
11640 {
11641         WL_DBG(("Enter \n"));
11642         conf->frag_threshold = (u32)-1;
11643         conf->rts_threshold = (u32)-1;
11644         conf->retry_short = (u32)-1;
11645         conf->retry_long = (u32)-1;
11646         conf->tx_power = -1;
11647 }
11648
11649 static void wl_init_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev)
11650 {
11651         unsigned long flags;
11652         struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
11653
11654         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
11655         memset(profile, 0, sizeof(struct wl_profile));
11656         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
11657 }
11658
11659 static void wl_init_event_handler(struct bcm_cfg80211 *cfg)
11660 {
11661         memset(cfg->evt_handler, 0, sizeof(cfg->evt_handler));
11662
11663         cfg->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
11664         cfg->evt_handler[WLC_E_AUTH] = wl_notify_connect_status;
11665         cfg->evt_handler[WLC_E_ASSOC] = wl_notify_connect_status;
11666         cfg->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
11667         cfg->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
11668         cfg->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
11669         cfg->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
11670         cfg->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
11671         cfg->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
11672         cfg->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;
11673         cfg->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
11674         cfg->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;
11675         cfg->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;
11676         cfg->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
11677         cfg->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
11678         cfg->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
11679         cfg->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
11680         cfg->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
11681         cfg->evt_handler[WLC_E_JOIN] = wl_notify_connect_status;
11682         cfg->evt_handler[WLC_E_START] = wl_notify_connect_status;
11683 #ifdef PNO_SUPPORT
11684         cfg->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status;
11685 #endif /* PNO_SUPPORT */
11686 #ifdef GSCAN_SUPPORT
11687         cfg->evt_handler[WLC_E_PFN_BEST_BATCHING] = wl_notify_gscan_event;
11688         cfg->evt_handler[WLC_E_PFN_SCAN_COMPLETE] = wl_notify_gscan_event;
11689         cfg->evt_handler[WLC_E_PFN_GSCAN_FULL_RESULT] = wl_notify_gscan_event;
11690         cfg->evt_handler[WLC_E_PFN_SWC] = wl_notify_gscan_event;
11691         cfg->evt_handler[WLC_E_PFN_BSSID_NET_FOUND] = wl_notify_gscan_event;
11692         cfg->evt_handler[WLC_E_PFN_BSSID_NET_LOST] = wl_notify_gscan_event;
11693 #endif /* GSCAN_SUPPORT */
11694 #ifdef WLTDLS
11695         cfg->evt_handler[WLC_E_TDLS_PEER_EVENT] = wl_tdls_event_handler;
11696 #endif /* WLTDLS */
11697         cfg->evt_handler[WLC_E_BSSID] = wl_notify_roaming_status;
11698 #ifdef  WL_RELMCAST
11699         cfg->evt_handler[WLC_E_RMC_EVENT] = wl_notify_rmc_status;
11700 #endif
11701 #ifdef BT_WIFI_HANDOVER
11702         cfg->evt_handler[WLC_E_BT_WIFI_HANDOVER_REQ] = wl_notify_bt_wifi_handover_req;
11703 #endif
11704 #ifdef WL_NAN
11705         cfg->evt_handler[WLC_E_NAN] = wl_cfgnan_notify_nan_status;
11706         cfg->evt_handler[WLC_E_PROXD] = wl_cfgnan_notify_proxd_status;
11707 #endif /* WL_NAN */
11708         cfg->evt_handler[WLC_E_CSA_COMPLETE_IND] = wl_csa_complete_ind;
11709 #ifdef DHD_LOSSLESS_ROAMING
11710         cfg->evt_handler[WLC_E_ROAM_PREP] = wl_notify_roam_prep_status;
11711 #endif
11712         cfg->evt_handler[WLC_E_AP_STARTED] = wl_ap_start_ind;
11713 #ifdef CUSTOM_EVENT_PM_WAKE
11714         cfg->evt_handler[WLC_E_EXCESS_PM_WAKE_EVENT] = wl_check_pmstatus;
11715 #endif /* CUSTOM_EVENT_PM_WAKE */
11716         cfg->evt_handler[WLC_E_PSK_SUP] = wl_notify_idsup_status;
11717 }
11718
11719 #if defined(STATIC_WL_PRIV_STRUCT)
11720 static void
11721 wl_init_escan_result_buf(struct bcm_cfg80211 *cfg)
11722 {
11723         cfg->escan_info.escan_buf = DHD_OS_PREALLOC(cfg->pub,
11724                 DHD_PREALLOC_WIPHY_ESCAN0, ESCAN_BUF_SIZE);
11725         bzero(cfg->escan_info.escan_buf, ESCAN_BUF_SIZE);
11726 }
11727
11728 static void
11729 wl_deinit_escan_result_buf(struct bcm_cfg80211 *cfg)
11730 {
11731         cfg->escan_info.escan_buf = NULL;
11732
11733 }
11734 #endif /* STATIC_WL_PRIV_STRUCT */
11735
11736 static s32 wl_init_priv_mem(struct bcm_cfg80211 *cfg)
11737 {
11738         WL_DBG(("Enter \n"));
11739
11740         cfg->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
11741         if (unlikely(!cfg->scan_results)) {
11742                 WL_ERR(("Scan results alloc failed\n"));
11743                 goto init_priv_mem_out;
11744         }
11745         cfg->conf = (void *)kzalloc(sizeof(*cfg->conf), GFP_KERNEL);
11746         if (unlikely(!cfg->conf)) {
11747                 WL_ERR(("wl_conf alloc failed\n"));
11748                 goto init_priv_mem_out;
11749         }
11750         cfg->scan_req_int =
11751             (void *)kzalloc(sizeof(*cfg->scan_req_int), GFP_KERNEL);
11752         if (unlikely(!cfg->scan_req_int)) {
11753                 WL_ERR(("Scan req alloc failed\n"));
11754                 goto init_priv_mem_out;
11755         }
11756         cfg->ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
11757         if (unlikely(!cfg->ioctl_buf)) {
11758                 WL_ERR(("Ioctl buf alloc failed\n"));
11759                 goto init_priv_mem_out;
11760         }
11761         cfg->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
11762         if (unlikely(!cfg->escan_ioctl_buf)) {
11763                 WL_ERR(("Ioctl buf alloc failed\n"));
11764                 goto init_priv_mem_out;
11765         }
11766         cfg->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
11767         if (unlikely(!cfg->extra_buf)) {
11768                 WL_ERR(("Extra buf alloc failed\n"));
11769                 goto init_priv_mem_out;
11770         }
11771         cfg->pmk_list = (void *)kzalloc(sizeof(*cfg->pmk_list), GFP_KERNEL);
11772         if (unlikely(!cfg->pmk_list)) {
11773                 WL_ERR(("pmk list alloc failed\n"));
11774                 goto init_priv_mem_out;
11775         }
11776 #if defined(STATIC_WL_PRIV_STRUCT)
11777         cfg->conn_info = (void *)kzalloc(sizeof(*cfg->conn_info), GFP_KERNEL);
11778         if (unlikely(!cfg->conn_info)) {
11779                 WL_ERR(("cfg->conn_info  alloc failed\n"));
11780                 goto init_priv_mem_out;
11781         }
11782         cfg->ie = (void *)kzalloc(sizeof(*cfg->ie), GFP_KERNEL);
11783         if (unlikely(!cfg->ie)) {
11784                 WL_ERR(("cfg->ie  alloc failed\n"));
11785                 goto init_priv_mem_out;
11786         }
11787         wl_init_escan_result_buf(cfg);
11788 #endif /* STATIC_WL_PRIV_STRUCT */
11789         cfg->afx_hdl = (void *)kzalloc(sizeof(*cfg->afx_hdl), GFP_KERNEL);
11790         if (unlikely(!cfg->afx_hdl)) {
11791                 WL_ERR(("afx hdl  alloc failed\n"));
11792                 goto init_priv_mem_out;
11793         } else {
11794                 init_completion(&cfg->act_frm_scan);
11795                 init_completion(&cfg->wait_next_af);
11796
11797                 INIT_WORK(&cfg->afx_hdl->work, wl_cfg80211_afx_handler);
11798         }
11799 #ifdef WLTDLS
11800         if (cfg->tdls_mgmt_frame) {
11801                 kfree(cfg->tdls_mgmt_frame);
11802                 cfg->tdls_mgmt_frame = NULL;
11803         }
11804 #endif /* WLTDLS */
11805         return 0;
11806
11807 init_priv_mem_out:
11808         wl_deinit_priv_mem(cfg);
11809
11810         return -ENOMEM;
11811 }
11812
11813 static void wl_deinit_priv_mem(struct bcm_cfg80211 *cfg)
11814 {
11815         kfree(cfg->scan_results);
11816         cfg->scan_results = NULL;
11817         kfree(cfg->conf);
11818         cfg->conf = NULL;
11819         kfree(cfg->scan_req_int);
11820         cfg->scan_req_int = NULL;
11821         kfree(cfg->ioctl_buf);
11822         cfg->ioctl_buf = NULL;
11823         kfree(cfg->escan_ioctl_buf);
11824         cfg->escan_ioctl_buf = NULL;
11825         kfree(cfg->extra_buf);
11826         cfg->extra_buf = NULL;
11827         kfree(cfg->pmk_list);
11828         cfg->pmk_list = NULL;
11829 #if defined(STATIC_WL_PRIV_STRUCT)
11830         kfree(cfg->conn_info);
11831         cfg->conn_info = NULL;
11832         kfree(cfg->ie);
11833         cfg->ie = NULL;
11834         wl_deinit_escan_result_buf(cfg);
11835 #endif /* STATIC_WL_PRIV_STRUCT */
11836         if (cfg->afx_hdl) {
11837                 cancel_work_sync(&cfg->afx_hdl->work);
11838                 kfree(cfg->afx_hdl);
11839                 cfg->afx_hdl = NULL;
11840         }
11841
11842 }
11843
11844 static s32 wl_create_event_handler(struct bcm_cfg80211 *cfg)
11845 {
11846         int ret = 0;
11847         WL_DBG(("Enter \n"));
11848
11849         /* Do not use DHD in cfg driver */
11850         cfg->event_tsk.thr_pid = -1;
11851
11852         PROC_START(wl_event_handler, cfg, &cfg->event_tsk, 0, "wl_event_handler");
11853         if (cfg->event_tsk.thr_pid < 0)
11854                 ret = -ENOMEM;
11855         return ret;
11856 }
11857
11858 static void wl_destroy_event_handler(struct bcm_cfg80211 *cfg)
11859 {
11860         if (cfg->event_tsk.thr_pid >= 0)
11861                 PROC_STOP(&cfg->event_tsk);
11862 }
11863
11864 void wl_terminate_event_handler(void)
11865 {
11866         struct bcm_cfg80211 *cfg = g_bcm_cfg;
11867
11868         if (cfg) {
11869                 wl_destroy_event_handler(cfg);
11870                 wl_flush_eq(cfg);
11871         }
11872 }
11873
11874 static void wl_scan_timeout(unsigned long data)
11875 {
11876         wl_event_msg_t msg;
11877         struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
11878         struct wireless_dev *wdev = NULL;
11879         struct net_device *ndev = NULL;
11880         struct wl_scan_results *bss_list;
11881         struct wl_bss_info *bi = NULL;
11882         s32 i;
11883         u32 channel;
11884 #if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
11885         dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
11886         uint32 prev_memdump_mode = dhdp->memdump_enabled;
11887 #endif /* DHD_DEBUG && BCMPCIE */
11888
11889         if (!(cfg->scan_request)) {
11890                 WL_ERR(("timer expired but no scan request\n"));
11891                 return;
11892         }
11893
11894         bss_list = wl_escan_get_buf(cfg, FALSE);
11895         if (!bss_list) {
11896                 WL_ERR(("bss_list is null. Didn't receive any partial scan results\n"));
11897         } else {
11898                 WL_ERR(("scanned AP count (%d)\n", bss_list->count));
11899
11900                 bi = next_bss(bss_list, bi);
11901                 for_each_bss(bss_list, bi, i) {
11902                         channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
11903                         WL_ERR(("SSID :%s  Channel :%d\n", bi->SSID, channel));
11904                 }
11905         }
11906
11907 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
11908         if (cfg->scan_request->dev)
11909                 wdev = cfg->scan_request->dev->ieee80211_ptr;
11910 #else
11911         wdev = cfg->scan_request->wdev;
11912 #endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
11913         if (!wdev) {
11914                 WL_ERR(("No wireless_dev present\n"));
11915                 return;
11916         }
11917         ndev = wdev_to_wlc_ndev(wdev, cfg);
11918
11919         bzero(&msg, sizeof(wl_event_msg_t));
11920         WL_ERR(("timer expired\n"));
11921 #if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
11922         if (dhdp->memdump_enabled) {
11923                 dhdp->memdump_enabled = DUMP_MEMFILE;
11924                 dhdp->memdump_type = DUMP_TYPE_SCAN_TIMEOUT;
11925                 dhd_bus_mem_dump(dhdp);
11926                 dhdp->memdump_enabled = prev_memdump_mode;
11927         }
11928 #endif /* DHD_DEBUG && BCMPCIE */
11929         msg.event_type = hton32(WLC_E_ESCAN_RESULT);
11930         msg.status = hton32(WLC_E_STATUS_TIMEOUT);
11931         msg.reason = 0xFFFFFFFF;
11932         wl_cfg80211_event(ndev, &msg, NULL);
11933 #ifdef CUSTOMER_HW4_DEBUG
11934         if (!wl_scan_timeout_dbg_enabled)
11935                 wl_scan_timeout_dbg_set();
11936 #endif /* CUSTOMER_HW4_DEBUG */
11937
11938         // terence 20130729: workaround to fix out of memory in firmware
11939 //      if (dhd_conf_get_chip(dhd_get_pub(dev)) == BCM43362_CHIP_ID) {
11940 //              WL_ERR(("Send hang event\n"));
11941 //              net_os_send_hang_message(dev);
11942 //      }
11943 }
11944
11945 #ifdef DHD_LOSSLESS_ROAMING
11946 static void wl_del_roam_timeout(struct bcm_cfg80211 *cfg)
11947 {
11948         dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
11949
11950         /* restore prec_map to ALLPRIO */
11951         dhdp->dequeue_prec_map = ALLPRIO;
11952         if (timer_pending(&cfg->roam_timeout)) {
11953                 del_timer_sync(&cfg->roam_timeout);
11954         }
11955
11956 }
11957
11958 static void wl_roam_timeout(unsigned long data)
11959 {
11960         struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
11961         dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
11962
11963         WL_ERR(("roam timer expired\n"));
11964
11965         /* restore prec_map to ALLPRIO */
11966         dhdp->dequeue_prec_map = ALLPRIO;
11967 }
11968
11969 #endif /* DHD_LOSSLESS_ROAMING */
11970
11971 static s32
11972 wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
11973         unsigned long state, void *ptr)
11974 {
11975 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
11976         struct net_device *dev = ptr;
11977 #else
11978         struct net_device *dev = netdev_notifier_info_to_dev(ptr);
11979 #endif /* LINUX_VERSION < VERSION(3, 11, 0) */
11980         struct wireless_dev *wdev = ndev_to_wdev(dev);
11981         struct bcm_cfg80211 *cfg = g_bcm_cfg;
11982
11983 #ifdef DHD_IFDEBUG
11984         WL_ERR(("Enter \n"));
11985 #endif
11986
11987         if (!wdev || !cfg || dev == bcmcfg_to_prmry_ndev(cfg))
11988                 return NOTIFY_DONE;
11989
11990         switch (state) {
11991                 case NETDEV_DOWN:
11992                 {
11993 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
11994                         int max_wait_timeout = 2;
11995                         int max_wait_count = 100;
11996                         int refcnt = 0;
11997                         unsigned long limit = jiffies + max_wait_timeout * HZ;
11998 #ifdef DHD_IFDEBUG
11999                         WL_ERR(("NETDEV_DOWN(+) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12000 #endif
12001                         while (work_pending(&wdev->cleanup_work)) {
12002                                 if (refcnt%5 == 0) {
12003                                         WL_ERR(("[NETDEV_DOWN] wait for "
12004                                                 "complete of cleanup_work"
12005                                                 " (%d th)\n", refcnt));
12006                                 }
12007                                 if (!time_before(jiffies, limit)) {
12008                                         WL_ERR(("[NETDEV_DOWN] cleanup_work"
12009                                                 " of CFG80211 is not"
12010                                                 " completed in %d sec\n",
12011                                                 max_wait_timeout));
12012                                         break;
12013                                 }
12014                                 if (refcnt >= max_wait_count) {
12015                                         WL_ERR(("[NETDEV_DOWN] cleanup_work"
12016                                                 " of CFG80211 is not"
12017                                                 " completed in %d loop\n",
12018                                                 max_wait_count));
12019                                         break;
12020                                 }
12021                                 set_current_state(TASK_INTERRUPTIBLE);
12022                                 (void)schedule_timeout(100);
12023                                 set_current_state(TASK_RUNNING);
12024                                 refcnt++;
12025                         }
12026 #ifdef DHD_IFDEBUG
12027                         WL_ERR(("NETDEV_DOWN(-) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12028 #endif
12029 #endif /* LINUX_VERSION < VERSION(3, 14, 0) */
12030                         break;
12031                 }
12032                 case NETDEV_UNREGISTER:
12033 #ifdef DHD_IFDEBUG
12034                         WL_ERR(("NETDEV_UNREGISTER(+) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12035 #endif
12036                         /* after calling list_del_rcu(&wdev->list) */
12037                         wl_cfg80211_clear_per_bss_ies(cfg,
12038                                 wl_get_bssidx_by_wdev(cfg, wdev));
12039                         wl_dealloc_netinfo_by_wdev(cfg, wdev);
12040 #ifdef DHD_IFDEBUG
12041                         WL_ERR(("NETDEV_UNREGISTER(-) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12042 #endif
12043                         break;
12044                 case NETDEV_GOING_DOWN:
12045                         /*
12046                          * At NETDEV_DOWN state, wdev_cleanup_work work will be called.
12047                          * In front of door, the function checks whether current scan
12048                          * is working or not. If the scanning is still working,
12049                          * wdev_cleanup_work call WARN_ON and make the scan done forcibly.
12050                          */
12051 #ifdef DHD_IFDEBUG
12052                         WL_ERR(("NETDEV_GOING_DOWN wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12053 #endif
12054                         if (wl_get_drv_status(cfg, SCANNING, dev))
12055                                 wl_notify_escan_complete(cfg, dev, true, true);
12056                         break;
12057         }
12058         return NOTIFY_DONE;
12059 }
12060
12061 static struct notifier_block wl_cfg80211_netdev_notifier = {
12062         .notifier_call = wl_cfg80211_netdev_notifier_call,
12063 };
12064
12065 /*
12066  * to make sure we won't register the same notifier twice, otherwise a loop is likely to be
12067  * created in kernel notifier link list (with 'next' pointing to itself)
12068  */
12069 static bool wl_cfg80211_netdev_notifier_registered = FALSE;
12070
12071 static void wl_cfg80211_cancel_scan(struct bcm_cfg80211 *cfg)
12072 {
12073         struct wireless_dev *wdev = NULL;
12074         struct net_device *ndev = NULL;
12075
12076         if (!cfg->scan_request)
12077                 return;
12078
12079 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
12080         if (cfg->scan_request->dev)
12081                 wdev = cfg->scan_request->dev->ieee80211_ptr;
12082 #else
12083         wdev = cfg->scan_request->wdev;
12084 #endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
12085
12086         if (!wdev) {
12087                 WL_ERR(("No wireless_dev present\n"));
12088                 return;
12089         }
12090
12091         ndev = wdev_to_wlc_ndev(wdev, cfg);
12092         wl_notify_escan_complete(cfg, ndev, true, true);
12093         WL_ERR(("Scan aborted! \n"));
12094 }
12095
12096 static void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg)
12097 {
12098         wl_scan_params_t *params = NULL;
12099         s32 params_size = 0;
12100         s32 err = BCME_OK;
12101         struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
12102         if (!in_atomic()) {
12103                 /* Our scan params only need space for 1 channel and 0 ssids */
12104                 params = wl_cfg80211_scan_alloc_params(-1, 0, &params_size);
12105                 if (params == NULL) {
12106                         WL_ERR(("scan params allocation failed \n"));
12107                         err = -ENOMEM;
12108                 } else {
12109                         /* Do a scan abort to stop the driver's scan engine */
12110                         err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true);
12111                         if (err < 0) {
12112                                 WL_ERR(("scan abort  failed \n"));
12113                         }
12114                         kfree(params);
12115                 }
12116         }
12117 #ifdef WLTDLS
12118         if (cfg->tdls_mgmt_frame) {
12119                 kfree(cfg->tdls_mgmt_frame);
12120                 cfg->tdls_mgmt_frame = NULL;
12121         }
12122 #endif /* WLTDLS */
12123 }
12124
12125 static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
12126         struct net_device *ndev,
12127         bool aborted, bool fw_abort)
12128 {
12129         s32 err = BCME_OK;
12130         unsigned long flags;
12131         struct net_device *dev;
12132
12133         WL_DBG(("Enter \n"));
12134
12135         mutex_lock(&cfg->scan_complete);
12136
12137         if (!ndev) {
12138                 WL_ERR(("ndev is null\n"));
12139                 err = BCME_ERROR;
12140                 goto out;
12141         }
12142
12143         if (cfg->escan_info.ndev != ndev) {
12144                 WL_ERR(("ndev is different %p %p\n", cfg->escan_info.ndev, ndev));
12145                 err = BCME_ERROR;
12146                 goto out;
12147         }
12148
12149         if (cfg->scan_request) {
12150                 dev = bcmcfg_to_prmry_ndev(cfg);
12151 #if defined(WL_ENABLE_P2P_IF)
12152                 if (cfg->scan_request->dev != cfg->p2p_net)
12153                         dev = cfg->scan_request->dev;
12154 #elif defined(WL_CFG80211_P2P_DEV_IF)
12155                 if (cfg->scan_request->wdev->iftype != NL80211_IFTYPE_P2P_DEVICE) {
12156 #ifdef DHD_IFDEBUG
12157                         WL_ERR(("%s: dev: %p\n", __FUNCTION__, cfg->scan_request->wdev->netdev));
12158 #endif
12159                         dev = cfg->scan_request->wdev->netdev;
12160                 }
12161 #endif /* WL_ENABLE_P2P_IF */
12162         }
12163         else {
12164                 WL_DBG(("cfg->scan_request is NULL may be internal scan."
12165                         "doing scan_abort for ndev %p primary %p",
12166                                 ndev, bcmcfg_to_prmry_ndev(cfg)));
12167                 dev = ndev;
12168         }
12169         if (fw_abort && !in_atomic())
12170                 wl_cfg80211_scan_abort(cfg);
12171         if (timer_pending(&cfg->scan_timeout))
12172                 del_timer_sync(&cfg->scan_timeout);
12173 #if defined(ESCAN_RESULT_PATCH)
12174         if (likely(cfg->scan_request)) {
12175                 cfg->bss_list = wl_escan_get_buf(cfg, aborted);
12176                 wl_inform_bss(cfg);
12177         }
12178 #endif /* ESCAN_RESULT_PATCH */
12179         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
12180 #ifdef WL_SCHED_SCAN
12181         if (cfg->sched_scan_req && !cfg->scan_request) {
12182                 WL_PNO((">>> REPORTING SCHED SCAN RESULTS \n"));
12183                 if (!aborted)
12184                         cfg80211_sched_scan_results(cfg->sched_scan_req->wiphy);
12185                 cfg->sched_scan_running = FALSE;
12186                 cfg->sched_scan_req = NULL;
12187         }
12188 #endif /* WL_SCHED_SCAN */
12189         if (likely(cfg->scan_request)) {
12190                 cfg80211_scan_done(cfg->scan_request, aborted);
12191                 cfg->scan_request = NULL;
12192                 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
12193                 DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
12194         }
12195         if (p2p_is_on(cfg))
12196                 wl_clr_p2p_status(cfg, SCANNING);
12197         wl_clr_drv_status(cfg, SCANNING, dev);
12198         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
12199
12200 out:
12201         mutex_unlock(&cfg->scan_complete);
12202         return err;
12203 }
12204
12205 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12206 static void
12207 wl_cfg80211_find_removal_candidate(wl_bss_info_t *bss, removal_element_t *candidate)
12208 {
12209         int idx;
12210         for (idx = 0; idx < BUF_OVERFLOW_MGMT_COUNT; idx++) {
12211                 int len = BUF_OVERFLOW_MGMT_COUNT - idx - 1;
12212                 if (bss->RSSI < candidate[idx].RSSI) {
12213                         if (len)
12214                                 memcpy(&candidate[idx + 1], &candidate[idx],
12215                                         sizeof(removal_element_t) * len);
12216                         candidate[idx].RSSI = bss->RSSI;
12217                         candidate[idx].length = bss->length;
12218                         memcpy(&candidate[idx].BSSID, &bss->BSSID, ETHER_ADDR_LEN);
12219                         return;
12220                 }
12221         }
12222 }
12223
12224 static void
12225 wl_cfg80211_remove_lowRSSI_info(wl_scan_results_t *list, removal_element_t *candidate,
12226         wl_bss_info_t *bi)
12227 {
12228         int idx1, idx2;
12229         int total_delete_len = 0;
12230         for (idx1 = 0; idx1 < BUF_OVERFLOW_MGMT_COUNT; idx1++) {
12231                 int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
12232                 wl_bss_info_t *bss = NULL;
12233                 if (candidate[idx1].RSSI >= bi->RSSI)
12234                         continue;
12235                 for (idx2 = 0; idx2 < list->count; idx2++) {
12236                         bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) :
12237                                 list->bss_info;
12238                         if (!bcmp(&candidate[idx1].BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
12239                                 candidate[idx1].RSSI == bss->RSSI &&
12240                                 candidate[idx1].length == dtoh32(bss->length)) {
12241                                 u32 delete_len = dtoh32(bss->length);
12242                                 WL_DBG(("delete scan info of " MACDBG " to add new AP\n",
12243                                         MAC2STRDBG(bss->BSSID.octet)));
12244                                 if (idx2 < list->count -1) {
12245                                         memmove((u8 *)bss, (u8 *)bss + delete_len,
12246                                                 list->buflen - cur_len - delete_len);
12247                                 }
12248                                 list->buflen -= delete_len;
12249                                 list->count--;
12250                                 total_delete_len += delete_len;
12251                                 /* if delete_len is greater than or equal to result length */
12252                                 if (total_delete_len >= bi->length) {
12253                                         return;
12254                                 }
12255                                 break;
12256                         }
12257                         cur_len += dtoh32(bss->length);
12258                 }
12259         }
12260 }
12261 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12262
12263 static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12264         const wl_event_msg_t *e, void *data)
12265 {
12266         s32 err = BCME_OK;
12267         s32 status = ntoh32(e->status);
12268         wl_bss_info_t *bi;
12269         wl_escan_result_t *escan_result;
12270         wl_bss_info_t *bss = NULL;
12271         wl_scan_results_t *list;
12272         wifi_p2p_ie_t * p2p_ie;
12273         struct net_device *ndev = NULL;
12274         u32 bi_length;
12275         u32 i;
12276         u8 *p2p_dev_addr = NULL;
12277         u16 channel;
12278         struct ieee80211_supported_band *band;
12279
12280         WL_DBG((" enter event type : %d, status : %d \n",
12281                 ntoh32(e->event_type), ntoh32(e->status)));
12282
12283         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
12284
12285         mutex_lock(&cfg->usr_sync);
12286         /* P2P SCAN is coming from primary interface */
12287         if (wl_get_p2p_status(cfg, SCANNING)) {
12288                 if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM))
12289                         ndev = cfg->afx_hdl->dev;
12290                 else
12291                         ndev = cfg->escan_info.ndev;
12292
12293         }
12294         if (!ndev || (!wl_get_drv_status(cfg, SCANNING, ndev) && !cfg->sched_scan_running)) {
12295                 WL_ERR(("escan is not ready ndev %p drv_status 0x%x e_type %d e_states %d\n",
12296                         ndev, wl_get_drv_status(cfg, SCANNING, ndev),
12297                         ntoh32(e->event_type), ntoh32(e->status)));
12298                 goto exit;
12299         }
12300         escan_result = (wl_escan_result_t *)data;
12301
12302         if (status == WLC_E_STATUS_PARTIAL) {
12303                 WL_INFORM(("WLC_E_STATUS_PARTIAL \n"));
12304                 if (!escan_result) {
12305                         WL_ERR(("Invalid escan result (NULL pointer)\n"));
12306                         goto exit;
12307                 }
12308                 if (dtoh16(escan_result->bss_count) != 1) {
12309                         WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
12310                         goto exit;
12311                 }
12312                 bi = escan_result->bss_info;
12313                 if (!bi) {
12314                         WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
12315                         goto exit;
12316                 }
12317                 bi_length = dtoh32(bi->length);
12318                 if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
12319                         WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length));
12320                         goto exit;
12321                 }
12322
12323                 /* +++++ terence 20130524: skip invalid bss */
12324                 channel =
12325                         bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
12326                 if (channel <= CH_MAX_2G_CHANNEL)
12327                         band = bcmcfg_to_wiphy(cfg)->bands[IEEE80211_BAND_2GHZ];
12328                 else
12329                         band = bcmcfg_to_wiphy(cfg)->bands[IEEE80211_BAND_5GHZ];
12330                 if (!band) {
12331                         WL_ERR(("No valid band\n"));
12332                         goto exit;
12333                 }
12334                 if (!dhd_conf_match_channel(cfg->pub, channel))
12335                         goto exit;
12336                 /* ----- terence 20130524: skip invalid bss */
12337
12338                 if (wl_escan_check_sync_id(status, escan_result->sync_id,
12339                                 cfg->escan_info.cur_sync_id) < 0)
12340                         goto exit;
12341
12342                 if (!(bcmcfg_to_wiphy(cfg)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
12343                         if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
12344                                 WL_DBG(("Ignoring IBSS result\n"));
12345                                 goto exit;
12346                         }
12347                 }
12348
12349                 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
12350                         p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
12351                         if (p2p_dev_addr && !memcmp(p2p_dev_addr,
12352                                 cfg->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
12353                                 s32 channel = wf_chspec_ctlchan(
12354                                         wl_chspec_driver_to_host(bi->chanspec));
12355
12356                                 if ((channel > MAXCHANNEL) || (channel <= 0))
12357                                         channel = WL_INVALID;
12358                                 else
12359                                         WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
12360                                                 " channel : %d\n",
12361                                                 MAC2STRDBG(cfg->afx_hdl->tx_dst_addr.octet),
12362                                                 channel));
12363
12364                                 wl_clr_p2p_status(cfg, SCANNING);
12365                                 cfg->afx_hdl->peer_chan = channel;
12366                                 complete(&cfg->act_frm_scan);
12367                                 goto exit;
12368                         }
12369
12370                 } else {
12371                         int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
12372 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12373                         removal_element_t candidate[BUF_OVERFLOW_MGMT_COUNT];
12374                         int remove_lower_rssi = FALSE;
12375
12376                         bzero(candidate, sizeof(removal_element_t)*BUF_OVERFLOW_MGMT_COUNT);
12377 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12378
12379                         list = wl_escan_get_buf(cfg, FALSE);
12380                         if (scan_req_match(cfg)) {
12381                                 /* p2p scan && allow only probe response */
12382                                 if ((cfg->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
12383                                         (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
12384                                         goto exit;
12385                                 if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset,
12386                                         bi->ie_length)) == NULL) {
12387                                                 WL_ERR(("Couldn't find P2PIE in probe"
12388                                                         " response/beacon\n"));
12389                                                 goto exit;
12390                                 }
12391                         }
12392 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12393                         if (bi_length > ESCAN_BUF_SIZE - list->buflen)
12394                                 remove_lower_rssi = TRUE;
12395 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12396
12397                         WL_SCAN(("%s("MACDBG") RSSI %d flags 0x%x length %d\n", bi->SSID,
12398                                 MAC2STRDBG(bi->BSSID.octet), bi->RSSI, bi->flags, bi->length));
12399                         for (i = 0; i < list->count; i++) {
12400                                 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
12401                                         : list->bss_info;
12402 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12403                                 WL_TRACE(("%s("MACDBG"), i=%d bss: RSSI %d list->count %d\n",
12404                                         bss->SSID, MAC2STRDBG(bss->BSSID.octet),
12405                                         i, bss->RSSI, list->count));
12406
12407                                 if (remove_lower_rssi)
12408                                         wl_cfg80211_find_removal_candidate(bss, candidate);
12409 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12410
12411                                 if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
12412                                         (CHSPEC_BAND(wl_chspec_driver_to_host(bi->chanspec))
12413                                         == CHSPEC_BAND(wl_chspec_driver_to_host(bss->chanspec))) &&
12414                                         bi->SSID_len == bss->SSID_len &&
12415                                         !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
12416
12417                                         /* do not allow beacon data to update
12418                                         *the data recd from a probe response
12419                                         */
12420                                         if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) &&
12421                                                 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
12422                                                 goto exit;
12423
12424                                         WL_SCAN(("%s("MACDBG"), i=%d prev: RSSI %d"
12425                                                 " flags 0x%x, new: RSSI %d flags 0x%x\n",
12426                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet), i,
12427                                                 bss->RSSI, bss->flags, bi->RSSI, bi->flags));
12428
12429                                         if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
12430                                                 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) {
12431                                                 /* preserve max RSSI if the measurements are
12432                                                 * both on-channel or both off-channel
12433                                                 */
12434                                                 WL_SCAN(("%s("MACDBG"), same onchan"
12435                                                 ", RSSI: prev %d new %d\n",
12436                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
12437                                                 bss->RSSI, bi->RSSI));
12438                                                 bi->RSSI = MAX(bss->RSSI, bi->RSSI);
12439                                         } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
12440                                                 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
12441                                                 /* preserve the on-channel rssi measurement
12442                                                 * if the new measurement is off channel
12443                                                 */
12444                                                 WL_SCAN(("%s("MACDBG"), prev onchan"
12445                                                 ", RSSI: prev %d new %d\n",
12446                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
12447                                                 bss->RSSI, bi->RSSI));
12448                                                 bi->RSSI = bss->RSSI;
12449                                                 bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
12450                                         }
12451                                         if (dtoh32(bss->length) != bi_length) {
12452                                                 u32 prev_len = dtoh32(bss->length);
12453
12454                                                 WL_SCAN(("bss info replacement"
12455                                                         " is occured(bcast:%d->probresp%d)\n",
12456                                                         bss->ie_length, bi->ie_length));
12457                                                 WL_SCAN(("%s("MACDBG"), replacement!(%d -> %d)\n",
12458                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
12459                                                 prev_len, bi_length));
12460
12461                                                 if (list->buflen - prev_len + bi_length
12462                                                         > ESCAN_BUF_SIZE) {
12463                                                         WL_ERR(("Buffer is too small: keep the"
12464                                                                 " previous result of this AP\n"));
12465                                                         /* Only update RSSI */
12466                                                         bss->RSSI = bi->RSSI;
12467                                                         bss->flags |= (bi->flags
12468                                                                 & WL_BSS_FLAGS_RSSI_ONCHANNEL);
12469                                                         goto exit;
12470                                                 }
12471
12472                                                 if (i < list->count - 1) {
12473                                                         /* memory copy required by this case only */
12474                                                         memmove((u8 *)bss + bi_length,
12475                                                                 (u8 *)bss + prev_len,
12476                                                                 list->buflen - cur_len - prev_len);
12477                                                 }
12478                                                 list->buflen -= prev_len;
12479                                                 list->buflen += bi_length;
12480                                         }
12481                                         list->version = dtoh32(bi->version);
12482                                         memcpy((u8 *)bss, (u8 *)bi, bi_length);
12483                                         goto exit;
12484                                 }
12485                                 cur_len += dtoh32(bss->length);
12486                         }
12487                         if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
12488 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12489                                 wl_cfg80211_remove_lowRSSI_info(list, candidate, bi);
12490                                 if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
12491                                         WL_DBG(("RSSI(" MACDBG ") is too low(%d) to add Buffer\n",
12492                                                 MAC2STRDBG(bi->BSSID.octet), bi->RSSI));
12493                                         goto exit;
12494                                 }
12495 #else
12496                                 WL_ERR(("Buffer is too small: ignoring\n"));
12497                                 goto exit;
12498 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12499                         }
12500
12501                         memcpy(&(((char *)list)[list->buflen]), bi, bi_length);
12502                         list->version = dtoh32(bi->version);
12503                         list->buflen += bi_length;
12504                         list->count++;
12505
12506                         /*
12507                          * !Broadcast && number of ssid = 1 && number of channels =1
12508                          * means specific scan to association
12509                          */
12510                         if (wl_cfgp2p_is_p2p_specific_scan(cfg->scan_request)) {
12511                                 WL_ERR(("P2P assoc scan fast aborted.\n"));
12512                                 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, false, true);
12513                                 goto exit;
12514                         }
12515                 }
12516         }
12517         else if (status == WLC_E_STATUS_SUCCESS) {
12518                 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
12519                 wl_escan_print_sync_id(status, cfg->escan_info.cur_sync_id,
12520                         escan_result->sync_id);
12521
12522                 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
12523                         WL_INFORM(("ACTION FRAME SCAN DONE\n"));
12524                         wl_clr_p2p_status(cfg, SCANNING);
12525                         wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
12526                         if (cfg->afx_hdl->peer_chan == WL_INVALID)
12527                                 complete(&cfg->act_frm_scan);
12528                 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
12529                         WL_INFORM(("ESCAN COMPLETED\n"));
12530                         cfg->bss_list = wl_escan_get_buf(cfg, FALSE);
12531                         if (!scan_req_match(cfg)) {
12532                                 WL_TRACE_HW4(("SCAN COMPLETED: scanned AP count=%d\n",
12533                                         cfg->bss_list->count));
12534                         }
12535                         wl_inform_bss(cfg);
12536                         wl_notify_escan_complete(cfg, ndev, false, false);
12537                 }
12538                 wl_escan_increment_sync_id(cfg, SCAN_BUF_NEXT);
12539 #ifdef CUSTOMER_HW4_DEBUG
12540                 if (wl_scan_timeout_dbg_enabled)
12541                         wl_scan_timeout_dbg_clear();
12542 #endif /* CUSTOMER_HW4_DEBUG */
12543         } else if ((status == WLC_E_STATUS_ABORT) || (status == WLC_E_STATUS_NEWSCAN) ||
12544                 (status == WLC_E_STATUS_11HQUIET) || (status == WLC_E_STATUS_CS_ABORT) ||
12545                 (status == WLC_E_STATUS_NEWASSOC)) {
12546                 /* Handle all cases of scan abort */
12547                 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
12548                 wl_escan_print_sync_id(status, escan_result->sync_id,
12549                         cfg->escan_info.cur_sync_id);
12550                 WL_DBG(("ESCAN ABORT reason: %d\n", status));
12551                 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
12552                         WL_INFORM(("ACTION FRAME SCAN DONE\n"));
12553                         wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
12554                         wl_clr_p2p_status(cfg, SCANNING);
12555                         if (cfg->afx_hdl->peer_chan == WL_INVALID)
12556                                 complete(&cfg->act_frm_scan);
12557                 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
12558                         WL_INFORM(("ESCAN ABORTED\n"));
12559                         cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
12560                         if (!scan_req_match(cfg)) {
12561                                 WL_TRACE_HW4(("scan_req_match=0: scanned AP count=%d\n",
12562                                         cfg->bss_list->count));
12563                         }
12564                         wl_inform_bss(cfg);
12565                         wl_notify_escan_complete(cfg, ndev, true, false);
12566                 } else {
12567                         /* If there is no pending host initiated scan, do nothing */
12568                         WL_DBG(("ESCAN ABORT: No pending scans. Ignoring event.\n"));
12569                 }
12570                 wl_escan_increment_sync_id(cfg, SCAN_BUF_CNT);
12571         } else if (status == WLC_E_STATUS_TIMEOUT) {
12572                 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", cfg->scan_request));
12573                 WL_ERR(("reason[0x%x]\n", e->reason));
12574                 if (e->reason == 0xFFFFFFFF) {
12575                         wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
12576                 }
12577         } else {
12578                 WL_ERR(("unexpected Escan Event %d : abort\n", status));
12579                 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
12580                 wl_escan_print_sync_id(status, escan_result->sync_id,
12581                         cfg->escan_info.cur_sync_id);
12582                 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
12583                         WL_INFORM(("ACTION FRAME SCAN DONE\n"));
12584                         wl_clr_p2p_status(cfg, SCANNING);
12585                         wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
12586                         if (cfg->afx_hdl->peer_chan == WL_INVALID)
12587                                 complete(&cfg->act_frm_scan);
12588                 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
12589                         cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
12590                         if (!scan_req_match(cfg)) {
12591                                 WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): "
12592                                         "scanned AP count=%d\n",
12593                                         cfg->bss_list->count));
12594                         }
12595                         wl_inform_bss(cfg);
12596                         wl_notify_escan_complete(cfg, ndev, true, false);
12597                 }
12598                 wl_escan_increment_sync_id(cfg, 2);
12599         }
12600 exit:
12601         mutex_unlock(&cfg->usr_sync);
12602         return err;
12603 }
12604
12605 static void wl_cfg80211_concurrent_roam(struct bcm_cfg80211 *cfg, int enable)
12606 {
12607         u32 connected_cnt  = wl_get_drv_status_all(cfg, CONNECTED);
12608         bool p2p_connected  = wl_cfgp2p_vif_created(cfg);
12609         struct net_info *iter, *next;
12610
12611         if (!cfg->roamoff_on_concurrent)
12612                 return;
12613         if (enable && (p2p_connected||(connected_cnt > 1))) {
12614 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12615         4 && __GNUC_MINOR__ >= 6))
12616 _Pragma("GCC diagnostic push")
12617 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
12618 #endif
12619                 for_each_ndev(cfg, iter, next) {
12620                         if (iter->ndev && iter->wdev &&
12621                                         iter->wdev->iftype == NL80211_IFTYPE_STATION) {
12622                                 if (wldev_iovar_setint(iter->ndev, "roam_off", TRUE)
12623                                                 == BCME_OK) {
12624                                         iter->roam_off = TRUE;
12625                                 }
12626                                 else {
12627                                         WL_ERR(("error to enable roam_off\n"));
12628                                 }
12629                         }
12630                 }
12631 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12632         4 && __GNUC_MINOR__ >= 6))
12633 _Pragma("GCC diagnostic pop")
12634 #endif
12635         }
12636         else if (!enable) {
12637 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12638         4 && __GNUC_MINOR__ >= 6))
12639 _Pragma("GCC diagnostic push")
12640 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
12641 #endif
12642                 for_each_ndev(cfg, iter, next) {
12643                         if (iter->ndev && iter->wdev &&
12644                                         iter->wdev->iftype == NL80211_IFTYPE_STATION) {
12645                                 if (iter->roam_off != WL_INVALID) {
12646                                         if (wldev_iovar_setint(iter->ndev, "roam_off", FALSE)
12647                                                         == BCME_OK) {
12648                                                 iter->roam_off = FALSE;
12649                                         }
12650                                         else {
12651                                                 WL_ERR(("error to disable roam_off\n"));
12652                                         }
12653                                 }
12654                         }
12655                 }
12656 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12657         4 && __GNUC_MINOR__ >= 6))
12658 _Pragma("GCC diagnostic pop")
12659 #endif
12660         }
12661         return;
12662 }
12663
12664 static void wl_cfg80211_determine_vsdb_mode(struct bcm_cfg80211 *cfg)
12665 {
12666         struct net_info *iter, *next;
12667         u32 ctl_chan = 0;
12668         u32 chanspec = 0;
12669         u32 pre_ctl_chan = 0;
12670         u32 connected_cnt  = wl_get_drv_status_all(cfg, CONNECTED);
12671         cfg->vsdb_mode = false;
12672
12673         if (connected_cnt <= 1)  {
12674                 return;
12675         }
12676 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12677         4 && __GNUC_MINOR__ >= 6))
12678 _Pragma("GCC diagnostic push")
12679 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
12680 #endif
12681         for_each_ndev(cfg, iter, next) {
12682                 /* p2p discovery iface ndev could be null */
12683                 if (iter->ndev) {
12684                         chanspec = 0;
12685                         ctl_chan = 0;
12686                         if (wl_get_drv_status(cfg, CONNECTED, iter->ndev)) {
12687                                 if (wldev_iovar_getint(iter->ndev, "chanspec",
12688                                         (s32 *)&chanspec) == BCME_OK) {
12689                                         chanspec = wl_chspec_driver_to_host(chanspec);
12690                                         ctl_chan = wf_chspec_ctlchan(chanspec);
12691                                         wl_update_prof(cfg, iter->ndev, NULL,
12692                                                 &ctl_chan, WL_PROF_CHAN);
12693                                 }
12694                                 if (!cfg->vsdb_mode) {
12695                                         if (!pre_ctl_chan && ctl_chan)
12696                                                 pre_ctl_chan = ctl_chan;
12697                                         else if (pre_ctl_chan && (pre_ctl_chan != ctl_chan)) {
12698                                                 cfg->vsdb_mode = true;
12699                                         }
12700                                 }
12701                         }
12702                 }
12703         }
12704 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12705         4 && __GNUC_MINOR__ >= 6))
12706 _Pragma("GCC diagnostic pop")
12707 #endif
12708         printf("%s concurrency is enabled\n", cfg->vsdb_mode ? "Multi Channel" : "Same Channel");
12709         return;
12710 }
12711
12712 #if defined(DISABLE_FRAMEBURST_VSDB) && defined(USE_WFA_CERT_CONF)
12713 extern int g_frameburst;
12714 #endif /* DISABLE_FRAMEBURST_VSDB && USE_WFA_CERT_CONF */
12715
12716 static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_net_info,
12717         enum wl_status state, bool set)
12718 {
12719         s32 pm = PM_FAST;
12720         s32 err = BCME_OK;
12721         u32 mode;
12722         u32 chan = 0;
12723         struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
12724         dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
12725         if (dhd->busstate == DHD_BUS_DOWN) {
12726                 WL_ERR(("%s : busstate is DHD_BUS_DOWN!\n", __FUNCTION__));
12727                 return 0;
12728         }
12729         WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n",
12730                 state, set, _net_info->pm_restore, _net_info->ndev->name));
12731
12732         if (state != WL_STATUS_CONNECTED)
12733                 return 0;
12734         mode = wl_get_mode_by_netdev(cfg, _net_info->ndev);
12735         if (set) {
12736                 wl_cfg80211_concurrent_roam(cfg, 1);
12737                 wl_cfg80211_determine_vsdb_mode(cfg);
12738                 if (mode == WL_MODE_AP) {
12739                         if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false))
12740                                 WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
12741                 }
12742
12743                 pm = PM_OFF;
12744                 if ((err = wldev_ioctl(_net_info->ndev, WLC_SET_PM, &pm,
12745                                 sizeof(pm), true)) != 0) {
12746                         if (err == -ENODEV)
12747                                 WL_DBG(("%s:netdev not ready\n",
12748                                         _net_info->ndev->name));
12749                         else
12750                                 WL_ERR(("%s:error (%d)\n",
12751                                         _net_info->ndev->name, err));
12752
12753                         wl_cfg80211_update_power_mode(_net_info->ndev);
12754                 }
12755                 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_SHORT);
12756 #if defined(WLTDLS)
12757                 if (wl_cfg80211_is_concurrent_mode()) {
12758                         err = wldev_iovar_setint(primary_dev, "tdls_enable", 0);
12759                 }
12760 #endif /* defined(WLTDLS) */
12761
12762 #ifdef DISABLE_FRAMEBURST_VSDB
12763 #ifdef USE_WFA_CERT_CONF
12764                 if (g_frameburst)
12765 #endif /* USE_WFA_CERT_CONF */
12766                 {
12767                         if (wl_cfg80211_is_concurrent_mode()) {
12768                                 int frameburst = 0;
12769                                 if (wldev_ioctl(primary_dev, WLC_SET_FAKEFRAG, &frameburst,
12770                                         sizeof(frameburst), true) != 0) {
12771                                         WL_DBG(("frameburst set error\n"));
12772                                 }
12773                                 WL_DBG(("Frameburst Disabled\n"));
12774                         }
12775                 }
12776 #endif /* DISABLE_FRAMEBURST_VSDB */
12777         } else { /* clear */
12778                 chan = 0;
12779                 /* clear chan information when the net device is disconnected */
12780                 wl_update_prof(cfg, _net_info->ndev, NULL, &chan, WL_PROF_CHAN);
12781                 wl_cfg80211_determine_vsdb_mode(cfg);
12782                 if (primary_dev == _net_info->ndev) {
12783                         pm = PM_FAST;
12784                         if ((err = wldev_ioctl(_net_info->ndev, WLC_SET_PM, &pm,
12785                                         sizeof(pm), true)) != 0) {
12786                                 if (err == -ENODEV)
12787                                         WL_DBG(("%s:netdev not ready\n",
12788                                                 _net_info->ndev->name));
12789                                 else
12790                                         WL_ERR(("%s:error (%d)\n",
12791                                                 _net_info->ndev->name, err));
12792
12793                                 wl_cfg80211_update_power_mode(_net_info->ndev);
12794                         }
12795                 }
12796
12797                 wl_cfg80211_concurrent_roam(cfg, 0);
12798 #if defined(WLTDLS)
12799                 if (!wl_cfg80211_is_concurrent_mode()) {
12800                         err = wldev_iovar_setint(primary_dev, "tdls_enable", 1);
12801                 }
12802 #endif /* defined(WLTDLS) */
12803
12804 #ifdef DISABLE_FRAMEBURST_VSDB
12805 #ifdef USE_WFA_CERT_CONF
12806                 if (g_frameburst)
12807 #endif /* USE_WFA_CERT_CONF */
12808                 {
12809                         int frameburst = 1;
12810                         if (wldev_ioctl(primary_dev, WLC_SET_FAKEFRAG, &frameburst,
12811                                 sizeof(frameburst), true) != 0) {
12812                                 WL_DBG(("frameburst set error\n"));
12813                         }
12814                         WL_DBG(("Frameburst Enabled\n"));
12815                 }
12816 #endif /* DISABLE_FRAMEBURST_VSDB */
12817         }
12818         return err;
12819 }
12820 static s32 wl_init_scan(struct bcm_cfg80211 *cfg)
12821 {
12822         int err = 0;
12823
12824         cfg->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
12825         cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
12826         wl_escan_init_sync_id(cfg);
12827
12828         /* Init scan_timeout timer */
12829         init_timer(&cfg->scan_timeout);
12830         cfg->scan_timeout.data = (unsigned long) cfg;
12831         cfg->scan_timeout.function = wl_scan_timeout;
12832
12833         return err;
12834 }
12835
12836 #ifdef DHD_LOSSLESS_ROAMING
12837 static s32 wl_init_roam_timeout(struct bcm_cfg80211 *cfg)
12838 {
12839         int err = 0;
12840
12841         /* Init roam timer */
12842         init_timer(&cfg->roam_timeout);
12843         cfg->roam_timeout.data = (unsigned long) cfg;
12844         cfg->roam_timeout.function = wl_roam_timeout;
12845
12846         return err;
12847 }
12848 #endif /* DHD_LOSSLESS_ROAMING */
12849
12850 static s32 wl_init_priv(struct bcm_cfg80211 *cfg)
12851 {
12852         struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
12853         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
12854         s32 err = 0;
12855
12856         cfg->scan_request = NULL;
12857         cfg->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
12858         cfg->roam_on = false;
12859         cfg->active_scan = true;
12860         cfg->rf_blocked = false;
12861         cfg->vsdb_mode = false;
12862 #if defined(BCMSDIO)
12863         cfg->wlfc_on = false;
12864 #endif 
12865         cfg->roamoff_on_concurrent = true;
12866         cfg->disable_roam_event = false;
12867         cfg->cfgdev_bssidx = -1;
12868         /* register interested state */
12869         set_bit(WL_STATUS_CONNECTED, &cfg->interrested_state);
12870         spin_lock_init(&cfg->cfgdrv_lock);
12871         mutex_init(&cfg->ioctl_buf_sync);
12872         init_waitqueue_head(&cfg->netif_change_event);
12873         init_completion(&cfg->send_af_done);
12874         init_completion(&cfg->iface_disable);
12875         wl_init_eq(cfg);
12876         err = wl_init_priv_mem(cfg);
12877         if (err)
12878                 return err;
12879         if (wl_create_event_handler(cfg))
12880                 return -ENOMEM;
12881         wl_init_event_handler(cfg);
12882         mutex_init(&cfg->usr_sync);
12883         mutex_init(&cfg->event_sync);
12884         mutex_init(&cfg->scan_complete);
12885         err = wl_init_scan(cfg);
12886         if (err)
12887                 return err;
12888 #ifdef DHD_LOSSLESS_ROAMING
12889         err = wl_init_roam_timeout(cfg);
12890         if (err) {
12891                 return err;
12892         }
12893 #endif /* DHD_LOSSLESS_ROAMING */
12894         wl_init_conf(cfg->conf);
12895         wl_init_prof(cfg, ndev);
12896         wl_link_down(cfg);
12897         DNGL_FUNC(dhd_cfg80211_init, (cfg));
12898
12899         return err;
12900 }
12901
12902 static void wl_deinit_priv(struct bcm_cfg80211 *cfg)
12903 {
12904         DNGL_FUNC(dhd_cfg80211_deinit, (cfg));
12905         wl_destroy_event_handler(cfg);
12906         wl_flush_eq(cfg);
12907         wl_link_down(cfg);
12908         del_timer_sync(&cfg->scan_timeout);
12909 #ifdef DHD_LOSSLESS_ROAMING
12910         del_timer_sync(&cfg->roam_timeout);
12911 #endif
12912         wl_deinit_priv_mem(cfg);
12913         if (wl_cfg80211_netdev_notifier_registered) {
12914                 wl_cfg80211_netdev_notifier_registered = FALSE;
12915                 unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
12916         }
12917 }
12918
12919 #if defined(WL_ENABLE_P2P_IF)
12920 static s32 wl_cfg80211_attach_p2p(void)
12921 {
12922         struct bcm_cfg80211 *cfg = g_bcm_cfg;
12923
12924         WL_TRACE(("Enter \n"));
12925
12926         if (wl_cfgp2p_register_ndev(cfg) < 0) {
12927                 WL_ERR(("P2P attach failed. \n"));
12928                 return -ENODEV;
12929         }
12930
12931         return 0;
12932 }
12933
12934 static s32  wl_cfg80211_detach_p2p(void)
12935 {
12936         struct bcm_cfg80211 *cfg = g_bcm_cfg;
12937         struct wireless_dev *wdev;
12938
12939         WL_DBG(("Enter \n"));
12940         if (!cfg) {
12941                 WL_ERR(("Invalid Ptr\n"));
12942                 return -EINVAL;
12943         } else
12944                 wdev = cfg->p2p_wdev;
12945
12946         if (!wdev) {
12947                 WL_ERR(("Invalid Ptr\n"));
12948                 return -EINVAL;
12949         }
12950
12951         wl_cfgp2p_unregister_ndev(cfg);
12952
12953         cfg->p2p_wdev = NULL;
12954         cfg->p2p_net = NULL;
12955         WL_DBG(("Freeing 0x%p \n", wdev));
12956         kfree(wdev);
12957
12958         return 0;
12959 }
12960 #endif 
12961
12962 s32 wl_cfg80211_attach_post(struct net_device *ndev)
12963 {
12964         struct bcm_cfg80211 * cfg = NULL;
12965         s32 err = 0;
12966         s32 ret = 0;
12967         WL_TRACE(("In\n"));
12968         if (unlikely(!ndev)) {
12969                 WL_ERR(("ndev is invaild\n"));
12970                 return -ENODEV;
12971         }
12972         cfg = g_bcm_cfg;
12973         if (unlikely(!cfg)) {
12974                 WL_ERR(("cfg is invaild\n"));
12975                 return -EINVAL;
12976         }
12977         if (!wl_get_drv_status(cfg, READY, ndev)) {
12978                 if (cfg->wdev) {
12979                         ret = wl_cfgp2p_supported(cfg, ndev);
12980                         if (ret > 0) {
12981 #if !defined(WL_ENABLE_P2P_IF)
12982                                 cfg->wdev->wiphy->interface_modes |=
12983                                         (BIT(NL80211_IFTYPE_P2P_CLIENT)|
12984                                         BIT(NL80211_IFTYPE_P2P_GO));
12985 #endif /* !WL_ENABLE_P2P_IF */
12986                                 if ((err = wl_cfgp2p_init_priv(cfg)) != 0)
12987                                         goto fail;
12988
12989 #if defined(WL_ENABLE_P2P_IF)
12990                                 if (cfg->p2p_net) {
12991                                         /* Update MAC addr for p2p0 interface here. */
12992                                         memcpy(cfg->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN);
12993                                         cfg->p2p_net->dev_addr[0] |= 0x02;
12994                                         printf("%s: p2p_dev_addr="MACDBG "\n",
12995                                                 cfg->p2p_net->name,
12996                                                 MAC2STRDBG(cfg->p2p_net->dev_addr));
12997                                 } else {
12998                                         WL_ERR(("p2p_net not yet populated."
12999                                         " Couldn't update the MAC Address for p2p0 \n"));
13000                                         return -ENODEV;
13001                                 }
13002 #endif /* WL_ENABLE_P2P_IF */
13003                                 cfg->p2p_supported = true;
13004                         } else if (ret == 0) {
13005                                 if ((err = wl_cfgp2p_init_priv(cfg)) != 0)
13006                                         goto fail;
13007                         } else {
13008                                 /* SDIO bus timeout */
13009                                 err = -ENODEV;
13010                                 goto fail;
13011                         }
13012                 }
13013         }
13014         wl_set_drv_status(cfg, READY, ndev);
13015 fail:
13016         return err;
13017 }
13018
13019 s32 wl_cfg80211_attach(struct net_device *ndev, void *context)
13020 {
13021         struct wireless_dev *wdev;
13022         struct bcm_cfg80211 *cfg;
13023         s32 err = 0;
13024         struct device *dev;
13025
13026         WL_TRACE(("In\n"));
13027         if (!ndev) {
13028                 WL_ERR(("ndev is invaild\n"));
13029                 return -ENODEV;
13030         }
13031         WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev()));
13032         dev = wl_cfg80211_get_parent_dev();
13033
13034         wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
13035         if (unlikely(!wdev)) {
13036                 WL_ERR(("Could not allocate wireless device\n"));
13037                 return -ENOMEM;
13038         }
13039         err = wl_setup_wiphy(wdev, dev, context);
13040         if (unlikely(err)) {
13041                 kfree(wdev);
13042                 return -ENOMEM;
13043         }
13044         wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
13045         cfg = (struct bcm_cfg80211 *)wiphy_priv(wdev->wiphy);
13046         cfg->wdev = wdev;
13047         cfg->pub = context;
13048         INIT_LIST_HEAD(&cfg->net_list);
13049         spin_lock_init(&cfg->net_list_sync);
13050         ndev->ieee80211_ptr = wdev;
13051         SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
13052         wdev->netdev = ndev;
13053         cfg->state_notifier = wl_notifier_change_state;
13054         err = wl_alloc_netinfo(cfg, ndev, wdev, WL_MODE_BSS, PM_ENABLE, 0);
13055         if (err) {
13056                 WL_ERR(("Failed to alloc net_info (%d)\n", err));
13057                 goto cfg80211_attach_out;
13058         }
13059         err = wl_init_priv(cfg);
13060         if (err) {
13061                 WL_ERR(("Failed to init iwm_priv (%d)\n", err));
13062                 goto cfg80211_attach_out;
13063         }
13064
13065         err = wl_setup_rfkill(cfg, TRUE);
13066         if (err) {
13067                 WL_ERR(("Failed to setup rfkill %d\n", err));
13068                 goto cfg80211_attach_out;
13069         }
13070 #ifdef DEBUGFS_CFG80211
13071         err = wl_setup_debugfs(cfg);
13072         if (err) {
13073                 WL_ERR(("Failed to setup debugfs %d\n", err));
13074                 goto cfg80211_attach_out;
13075         }
13076 #endif
13077         if (!wl_cfg80211_netdev_notifier_registered) {
13078                 wl_cfg80211_netdev_notifier_registered = TRUE;
13079                 err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier);
13080                 if (err) {
13081                         wl_cfg80211_netdev_notifier_registered = FALSE;
13082                         WL_ERR(("Failed to register notifierl %d\n", err));
13083                         goto cfg80211_attach_out;
13084                 }
13085         }
13086 #if defined(COEX_DHCP)
13087         cfg->btcoex_info = wl_cfg80211_btcoex_init(cfg->wdev->netdev);
13088         if (!cfg->btcoex_info)
13089                 goto cfg80211_attach_out;
13090 #endif 
13091 #if defined(SUPPORT_RANDOM_MAC_SCAN)
13092         cfg->random_mac_enabled = FALSE;
13093 #endif /* SUPPORT_RANDOM_MAC_SCAN */
13094         g_bcm_cfg = cfg;
13095
13096 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
13097         wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier;
13098 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
13099
13100 #if defined(WL_ENABLE_P2P_IF)
13101         err = wl_cfg80211_attach_p2p();
13102         if (err)
13103                 goto cfg80211_attach_out;
13104 #endif 
13105
13106         INIT_DELAYED_WORK(&cfg->pm_enable_work, wl_cfg80211_work_handler);
13107         mutex_init(&cfg->pm_sync);
13108
13109         return err;
13110
13111 cfg80211_attach_out:
13112         wl_setup_rfkill(cfg, FALSE);
13113         wl_free_wdev(cfg);
13114         return err;
13115 }
13116
13117 void wl_cfg80211_detach(void *para)
13118 {
13119         struct bcm_cfg80211 *cfg;
13120
13121         (void)para;
13122         cfg = g_bcm_cfg;
13123
13124         WL_TRACE(("In\n"));
13125
13126         wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
13127
13128 #if defined(COEX_DHCP)
13129         wl_cfg80211_btcoex_deinit();
13130         cfg->btcoex_info = NULL;
13131 #endif 
13132
13133         wl_setup_rfkill(cfg, FALSE);
13134 #ifdef DEBUGFS_CFG80211
13135         wl_free_debugfs(cfg);
13136 #endif
13137         if (cfg->p2p_supported) {
13138                 if (timer_pending(&cfg->p2p->listen_timer))
13139                         del_timer_sync(&cfg->p2p->listen_timer);
13140                 wl_cfgp2p_deinit_priv(cfg);
13141         }
13142
13143         if (timer_pending(&cfg->scan_timeout))
13144                 del_timer_sync(&cfg->scan_timeout);
13145 #ifdef DHD_LOSSLESS_ROAMING
13146         if (timer_pending(&cfg->roam_timeout)) {
13147                 del_timer_sync(&cfg->roam_timeout);
13148         }
13149 #endif /* DHD_LOSSLESS_ROAMING */
13150
13151 #if defined(WL_CFG80211_P2P_DEV_IF)
13152         if (cfg->p2p_wdev)
13153                 wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
13154 #endif /* WL_CFG80211_P2P_DEV_IF  */
13155 #if defined(WL_ENABLE_P2P_IF)
13156         wl_cfg80211_detach_p2p();
13157 #endif 
13158
13159         wl_cfg80211_ibss_vsie_free(cfg);
13160         wl_cfg80211_clear_mgmt_vndr_ies(cfg);
13161         wl_deinit_priv(cfg);
13162         g_bcm_cfg = NULL;
13163         wl_cfg80211_clear_parent_dev();
13164         wl_free_wdev(cfg);
13165 #if defined(RSSIAVG)
13166         wl_free_rssi_cache(&g_rssi_cache_ctrl);
13167         wl_free_rssi_cache(&g_connected_rssi_cache_ctrl);
13168 #endif
13169 #if defined(BSSCACHE)
13170         wl_release_bss_cache_ctrl(&g_bss_cache_ctrl);
13171 #endif
13172         /* PLEASE do NOT call any function after wl_free_wdev, the driver's private
13173          * structure "cfg", which is the private part of wiphy, has been freed in
13174          * wl_free_wdev !!!!!!!!!!!
13175          */
13176 }
13177
13178 static void wl_wakeup_event(struct bcm_cfg80211 *cfg)
13179 {
13180         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
13181
13182         if (dhd->up && (cfg->event_tsk.thr_pid >= 0)) {
13183                 up(&cfg->event_tsk.sema);
13184         }
13185 }
13186
13187 static s32 wl_event_handler(void *data)
13188 {
13189         struct bcm_cfg80211 *cfg = NULL;
13190         struct wl_event_q *e;
13191         tsk_ctl_t *tsk = (tsk_ctl_t *)data;
13192         struct wireless_dev *wdev = NULL;
13193
13194         cfg = (struct bcm_cfg80211 *)tsk->parent;
13195
13196         printf("tsk Enter, tsk = 0x%p\n", tsk);
13197
13198         while (down_interruptible (&tsk->sema) == 0) {
13199                 SMP_RD_BARRIER_DEPENDS();
13200                 if (tsk->terminated) {
13201                         break;
13202                 }
13203                 while ((e = wl_deq_event(cfg))) {
13204                         WL_DBG(("event type (%d), ifidx: %d bssidx: %d \n",
13205                                 e->etype, e->emsg.ifidx, e->emsg.bsscfgidx));
13206
13207                         if (e->emsg.ifidx > WL_MAX_IFS) {
13208                                 WL_ERR((" Event ifidx not in range. val:%d \n", e->emsg.ifidx));
13209                                 goto fail;
13210                         }
13211
13212                         if (!(wdev = wl_get_wdev_by_bssidx(cfg, e->emsg.bsscfgidx))) {
13213                                 /* For WLC_E_IF would be handled by wl_host_event */
13214                                 if (e->etype != WLC_E_IF)
13215                                         WL_ERR(("No wdev corresponding to bssidx: 0x%x found!"
13216                                                 " Ignoring event.\n", e->emsg.bsscfgidx));
13217                         } else if (e->etype < WLC_E_LAST && cfg->evt_handler[e->etype]) {
13218                                 dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
13219                                 if (dhd->busstate == DHD_BUS_DOWN) {
13220                                         WL_ERR((": BUS is DOWN.\n"));
13221                                 } else {
13222 #ifdef DHD_IFDEBUG
13223                                         if (cfg->iface_cnt == 0) {
13224                                                 wl_dump_ifinfo(cfg);
13225                                         }
13226 #endif
13227                                         cfg->evt_handler[e->etype](cfg, wdev_to_cfgdev(wdev),
13228                                                 &e->emsg, e->edata);
13229                                 }
13230                         } else {
13231                                 WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
13232                         }
13233 fail:
13234                         wl_put_event(e);
13235                         DHD_EVENT_WAKE_UNLOCK(cfg->pub);
13236                 }
13237         }
13238         printf("%s: was terminated\n", __FUNCTION__);
13239         complete_and_exit(&tsk->completed, 0);
13240         return 0;
13241 }
13242
13243 void
13244 wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
13245 {
13246         u32 event_type = ntoh32(e->event_type);
13247         struct bcm_cfg80211 *cfg = g_bcm_cfg;
13248         struct net_info *netinfo;
13249
13250 #if (WL_DBG_LEVEL > 0)
13251         s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
13252             wl_dbg_estr[event_type] : (s8 *) "Unknown";
13253         WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
13254 #endif /* (WL_DBG_LEVEL > 0) */
13255
13256         if (cfg->event_tsk.thr_pid == -1) {
13257                 WL_ERR(("Event handler is not created\n"));
13258                 return;
13259         }
13260
13261         if ((cfg == NULL) || (cfg->p2p_supported && cfg->p2p == NULL)) {
13262                 WL_ERR(("Stale event ignored\n"));
13263                 return;
13264         }
13265
13266         if (wl_get_p2p_status(cfg, IF_CHANGING) || wl_get_p2p_status(cfg, IF_ADDING)) {
13267                 WL_ERR(("during IF change, ignore event %d\n", event_type));
13268                 return;
13269         }
13270
13271 #ifdef DHD_IFDEBUG
13272         if (event_type != WLC_E_ESCAN_RESULT) {
13273                 WL_ERR(("Event_type %d , status : %d, reason : %d, bssidx:%d \n",
13274                         event_type, ntoh32(e->status), ntoh32(e->reason), e->bsscfgidx));
13275         }
13276 #endif
13277         netinfo = wl_get_netinfo_by_bssidx(cfg, e->bsscfgidx);
13278         if (!netinfo) {
13279                 /* Since the netinfo entry is not there, the netdev entry is not
13280                  * created via cfg80211 interface. so the event is not of interest
13281                  * to the cfg80211 layer.
13282                  */
13283                 WL_ERR(("ignore event %d, not interested\n", event_type));
13284                 return;
13285         }
13286
13287         if (event_type == WLC_E_PFN_NET_FOUND) {
13288                 WL_DBG((" PNOEVENT: PNO_NET_FOUND\n"));
13289         }
13290         else if (event_type == WLC_E_PFN_NET_LOST) {
13291                 WL_DBG((" PNOEVENT: PNO_NET_LOST\n"));
13292         }
13293
13294         DHD_EVENT_WAKE_LOCK(cfg->pub);
13295         if (likely(!wl_enq_event(cfg, ndev, event_type, e, data))) {
13296                 wl_wakeup_event(cfg);
13297         } else {
13298                 DHD_EVENT_WAKE_UNLOCK(cfg->pub);
13299         }
13300 }
13301
13302 static void wl_init_eq(struct bcm_cfg80211 *cfg)
13303 {
13304         wl_init_eq_lock(cfg);
13305         INIT_LIST_HEAD(&cfg->eq_list);
13306 }
13307
13308 static void wl_flush_eq(struct bcm_cfg80211 *cfg)
13309 {
13310         struct wl_event_q *e;
13311         unsigned long flags;
13312
13313         flags = wl_lock_eq(cfg);
13314         while (!list_empty_careful(&cfg->eq_list)) {
13315                 BCM_SET_LIST_FIRST_ENTRY(e, &cfg->eq_list, struct wl_event_q, eq_list);
13316                 list_del(&e->eq_list);
13317                 kfree(e);
13318         }
13319         wl_unlock_eq(cfg, flags);
13320 }
13321
13322 /*
13323 * retrieve first queued event from head
13324 */
13325
13326 static struct wl_event_q *wl_deq_event(struct bcm_cfg80211 *cfg)
13327 {
13328         struct wl_event_q *e = NULL;
13329         unsigned long flags;
13330
13331         flags = wl_lock_eq(cfg);
13332         if (likely(!list_empty(&cfg->eq_list))) {
13333                 BCM_SET_LIST_FIRST_ENTRY(e, &cfg->eq_list, struct wl_event_q, eq_list);
13334                 list_del(&e->eq_list);
13335         }
13336         wl_unlock_eq(cfg, flags);
13337
13338         return e;
13339 }
13340
13341 /*
13342  * push event to tail of the queue
13343  */
13344
13345 static s32
13346 wl_enq_event(struct bcm_cfg80211 *cfg, struct net_device *ndev, u32 event,
13347         const wl_event_msg_t *msg, void *data)
13348 {
13349         struct wl_event_q *e;
13350         s32 err = 0;
13351         uint32 evtq_size;
13352         uint32 data_len;
13353         unsigned long flags;
13354         gfp_t aflags;
13355
13356         data_len = 0;
13357         if (data)
13358                 data_len = ntoh32(msg->datalen);
13359         evtq_size = sizeof(struct wl_event_q) + data_len;
13360         aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
13361         e = kzalloc(evtq_size, aflags);
13362         if (unlikely(!e)) {
13363                 WL_ERR(("event alloc failed\n"));
13364                 return -ENOMEM;
13365         }
13366         e->etype = event;
13367         memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
13368         if (data)
13369                 memcpy(e->edata, data, data_len);
13370         flags = wl_lock_eq(cfg);
13371         list_add_tail(&e->eq_list, &cfg->eq_list);
13372         wl_unlock_eq(cfg, flags);
13373
13374         return err;
13375 }
13376
13377 static void wl_put_event(struct wl_event_q *e)
13378 {
13379         kfree(e);
13380 }
13381
13382 static s32 wl_config_ifmode(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 iftype)
13383 {
13384         s32 infra = 0;
13385         s32 err = 0;
13386         s32 mode = 0;
13387         switch (iftype) {
13388         case NL80211_IFTYPE_MONITOR:
13389         case NL80211_IFTYPE_WDS:
13390                 WL_ERR(("type (%d) : currently we do not support this mode\n",
13391                         iftype));
13392                 err = -EINVAL;
13393                 return err;
13394         case NL80211_IFTYPE_ADHOC:
13395                 mode = WL_MODE_IBSS;
13396                 break;
13397         case NL80211_IFTYPE_STATION:
13398         case NL80211_IFTYPE_P2P_CLIENT:
13399                 mode = WL_MODE_BSS;
13400                 infra = 1;
13401                 break;
13402         case NL80211_IFTYPE_AP:
13403         case NL80211_IFTYPE_P2P_GO:
13404                 mode = WL_MODE_AP;
13405                 infra = 1;
13406                 break;
13407         default:
13408                 err = -EINVAL;
13409                 WL_ERR(("invalid type (%d)\n", iftype));
13410                 return err;
13411         }
13412         infra = htod32(infra);
13413         err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true);
13414         if (unlikely(err)) {
13415                 WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
13416                 return err;
13417         }
13418
13419         wl_set_mode_by_netdev(cfg, ndev, mode);
13420
13421         return 0;
13422 }
13423
13424 void wl_cfg80211_add_to_eventbuffer(struct wl_eventmsg_buf *ev, u16 event, bool set)
13425 {
13426         if (!ev || (event > WLC_E_LAST))
13427                 return;
13428
13429         if (ev->num < MAX_EVENT_BUF_NUM) {
13430                 ev->event[ev->num].type = event;
13431                 ev->event[ev->num].set = set;
13432                 ev->num++;
13433         } else {
13434                 WL_ERR(("evenbuffer doesn't support > %u events. Update"
13435                         " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM));
13436                 ASSERT(0);
13437         }
13438 }
13439
13440 s32 wl_cfg80211_apply_eventbuffer(
13441         struct net_device *ndev,
13442         struct bcm_cfg80211 *cfg,
13443         wl_eventmsg_buf_t *ev)
13444 {
13445         char eventmask[WL_EVENTING_MASK_LEN];
13446         int i, ret = 0;
13447         s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
13448
13449         if (!ev || (!ev->num))
13450                 return -EINVAL;
13451
13452         mutex_lock(&cfg->event_sync);
13453
13454         /* Read event_msgs mask */
13455         bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
13456                 sizeof(iovbuf));
13457         ret = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
13458         if (unlikely(ret)) {
13459                 WL_ERR(("Get event_msgs error (%d)\n", ret));
13460                 goto exit;
13461         }
13462         memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
13463
13464         /* apply the set bits */
13465         for (i = 0; i < ev->num; i++) {
13466                 if (ev->event[i].set)
13467                         setbit(eventmask, ev->event[i].type);
13468                 else
13469                         clrbit(eventmask, ev->event[i].type);
13470         }
13471
13472         /* Write updated Event mask */
13473         bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
13474                 sizeof(iovbuf));
13475         ret = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
13476         if (unlikely(ret)) {
13477                 WL_ERR(("Set event_msgs error (%d)\n", ret));
13478         }
13479
13480 exit:
13481         mutex_unlock(&cfg->event_sync);
13482         return ret;
13483 }
13484
13485 s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add)
13486 {
13487         s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
13488         s8 eventmask[WL_EVENTING_MASK_LEN];
13489         s32 err = 0;
13490         struct bcm_cfg80211 *cfg = g_bcm_cfg;
13491
13492         if (!ndev || !cfg)
13493                 return -ENODEV;
13494
13495         mutex_lock(&cfg->event_sync);
13496
13497         /* Setup event_msgs */
13498         bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
13499                 sizeof(iovbuf));
13500         err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
13501         if (unlikely(err)) {
13502                 WL_ERR(("Get event_msgs error (%d)\n", err));
13503                 goto eventmsg_out;
13504         }
13505         memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
13506         if (add) {
13507                 setbit(eventmask, event);
13508         } else {
13509                 clrbit(eventmask, event);
13510         }
13511         bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
13512                 sizeof(iovbuf));
13513         err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
13514         if (unlikely(err)) {
13515                 WL_ERR(("Set event_msgs error (%d)\n", err));
13516                 goto eventmsg_out;
13517         }
13518
13519 eventmsg_out:
13520         mutex_unlock(&cfg->event_sync);
13521         return err;
13522 }
13523
13524 static int wl_construct_reginfo(struct bcm_cfg80211 *cfg, s32 bw_cap)
13525 {
13526         struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
13527         struct ieee80211_channel *band_chan_arr = NULL;
13528         wl_uint32_list_t *list;
13529         u32 i, j, index, n_2g, n_5g, band, channel, array_size;
13530         u32 *n_cnt = NULL;
13531         chanspec_t c = 0;
13532         s32 err = BCME_OK;
13533         bool update;
13534         bool ht40_allowed;
13535         u8 *pbuf = NULL;
13536         bool dfs_radar_disabled = FALSE;
13537
13538 #define LOCAL_BUF_LEN 1024
13539         pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL);
13540
13541         if (pbuf == NULL) {
13542                 WL_ERR(("failed to allocate local buf\n"));
13543                 return -ENOMEM;
13544         }
13545         list = (wl_uint32_list_t *)(void *)pbuf;
13546         list->count = htod32(WL_NUMCHANSPECS);
13547
13548
13549         err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
13550                 0, pbuf, LOCAL_BUF_LEN, 0, &cfg->ioctl_buf_sync);
13551         if (err != 0) {
13552                 WL_ERR(("get chanspecs failed with %d\n", err));
13553                 kfree(pbuf);
13554                 return err;
13555         }
13556 #undef LOCAL_BUF_LEN
13557
13558         list = (wl_uint32_list_t *)(void *)pbuf;
13559         band = array_size = n_2g = n_5g = 0;
13560         for (i = 0; i < dtoh32(list->count); i++) {
13561                 index = 0;
13562                 update = false;
13563                 ht40_allowed = false;
13564                 c = (chanspec_t)dtoh32(list->element[i]);
13565                 c = wl_chspec_driver_to_host(c);
13566                 channel = wf_chspec_ctlchan(c);
13567
13568                 if (!CHSPEC_IS40(c) && ! CHSPEC_IS20(c)) {
13569                         WL_DBG(("HT80/160/80p80 center channel : %d\n", channel));
13570                         continue;
13571                 }
13572                 if (CHSPEC_IS2G(c) && (channel >= CH_MIN_2G_CHANNEL) &&
13573                         (channel <= CH_MAX_2G_CHANNEL)) {
13574                         band_chan_arr = __wl_2ghz_channels;
13575                         array_size = ARRAYSIZE(__wl_2ghz_channels);
13576                         n_cnt = &n_2g;
13577                         band = IEEE80211_BAND_2GHZ;
13578                         ht40_allowed = (bw_cap  == WLC_N_BW_40ALL)? true : false;
13579                 } else if (CHSPEC_IS5G(c) && channel >= CH_MIN_5G_CHANNEL) {
13580                         band_chan_arr = __wl_5ghz_a_channels;
13581                         array_size = ARRAYSIZE(__wl_5ghz_a_channels);
13582                         n_cnt = &n_5g;
13583                         band = IEEE80211_BAND_5GHZ;
13584                         ht40_allowed = (bw_cap  == WLC_N_BW_20ALL)? false : true;
13585                 } else {
13586                         WL_ERR(("Invalid channel Sepc. 0x%x.\n", c));
13587                         continue;
13588                 }
13589                 if (!ht40_allowed && CHSPEC_IS40(c))
13590                         continue;
13591                 for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
13592                         if (band_chan_arr[j].hw_value == channel) {
13593                                 update = true;
13594                                 break;
13595                         }
13596                 }
13597                 if (update)
13598                         index = j;
13599                 else
13600                         index = *n_cnt;
13601                 if (!dhd_conf_match_channel(cfg->pub, channel))
13602                         continue;
13603                 if (index <  array_size) {
13604 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
13605                         band_chan_arr[index].center_freq =
13606                                 ieee80211_channel_to_frequency(channel);
13607 #else
13608                         band_chan_arr[index].center_freq =
13609                                 ieee80211_channel_to_frequency(channel, band);
13610 #endif
13611                         band_chan_arr[index].hw_value = channel;
13612                         WL_DBG(("channel = %d\n", channel));
13613
13614                         if (CHSPEC_IS40(c) && ht40_allowed) {
13615                                 /* assuming the order is HT20, HT40 Upper,
13616                                  *  HT40 lower from chanspecs
13617                                  */
13618                                 u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
13619                                 if (CHSPEC_SB_UPPER(c)) {
13620                                         if (ht40_flag == IEEE80211_CHAN_NO_HT40)
13621                                                 band_chan_arr[index].flags &=
13622                                                         ~IEEE80211_CHAN_NO_HT40;
13623                                         band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
13624                                 } else {
13625                                         /* It should be one of
13626                                          * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
13627                                          */
13628                                         band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
13629                                         if (ht40_flag == IEEE80211_CHAN_NO_HT40)
13630                                                 band_chan_arr[index].flags |=
13631                                                         IEEE80211_CHAN_NO_HT40MINUS;
13632                                 }
13633                         } else {
13634                                 band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
13635                                 if (!dfs_radar_disabled) {
13636                                         if (band == IEEE80211_BAND_2GHZ)
13637                                                 channel |= WL_CHANSPEC_BAND_2G;
13638                                         else
13639                                                 channel |= WL_CHANSPEC_BAND_5G;
13640                                         channel |= WL_CHANSPEC_BW_20;
13641                                         channel = wl_chspec_host_to_driver(channel);
13642                                         err = wldev_iovar_getint(dev, "per_chan_info", &channel);
13643                                         if (!err) {
13644                                                 if (channel & WL_CHAN_RADAR) {
13645 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
13646                                                         band_chan_arr[index].flags |=
13647                                                                 (IEEE80211_CHAN_RADAR
13648                                                                 | IEEE80211_CHAN_NO_IBSS);
13649 #else
13650                                                         band_chan_arr[index].flags |=
13651                                                                 IEEE80211_CHAN_RADAR;
13652 #endif
13653                                                 }
13654
13655                                                 if (channel & WL_CHAN_PASSIVE)
13656 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
13657                                                         band_chan_arr[index].flags |=
13658                                                                 IEEE80211_CHAN_PASSIVE_SCAN;
13659 #else
13660                                                         band_chan_arr[index].flags |=
13661                                                                 IEEE80211_CHAN_NO_IR;
13662 #endif
13663                                         } else if (err == BCME_UNSUPPORTED) {
13664                                                 dfs_radar_disabled = TRUE;
13665                                                 WL_ERR(("does not support per_chan_info\n"));
13666                                         }
13667                                 }
13668                         }
13669                         if (!update)
13670                                 (*n_cnt)++;
13671                 }
13672
13673         }
13674         __wl_band_2ghz.n_channels = n_2g;
13675         __wl_band_5ghz_a.n_channels = n_5g;
13676         kfree(pbuf);
13677         return err;
13678 }
13679
13680 s32 wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify)
13681 {
13682         struct wiphy *wiphy;
13683         struct net_device *dev;
13684         u32 bandlist[3];
13685         u32 nband = 0;
13686         u32 i = 0;
13687         s32 err = 0;
13688         s32 index = 0;
13689         s32 nmode = 0;
13690 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
13691         u32 j = 0;
13692         s32 vhtmode = 0;
13693         s32 txstreams = 0;
13694         s32 rxstreams = 0;
13695         s32 ldpc_cap = 0;
13696         s32 stbc_rx = 0;
13697         s32 stbc_tx = 0;
13698         s32 txbf_bfe_cap = 0;
13699         s32 txbf_bfr_cap = 0;
13700 #endif 
13701         bool rollback_lock = false;
13702         s32 bw_cap = 0;
13703         s32 cur_band = -1;
13704         struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS] = {NULL, };
13705
13706         if (cfg == NULL) {
13707                 cfg = g_bcm_cfg;
13708                 mutex_lock(&cfg->usr_sync);
13709                 rollback_lock = true;
13710         }
13711         dev = bcmcfg_to_prmry_ndev(cfg);
13712
13713         memset(bandlist, 0, sizeof(bandlist));
13714         err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist,
13715                 sizeof(bandlist), false);
13716         if (unlikely(err)) {
13717                 WL_ERR(("error read bandlist (%d)\n", err));
13718                 goto end_bands;
13719         }
13720         err = wldev_ioctl(dev, WLC_GET_BAND, &cur_band,
13721                 sizeof(s32), false);
13722         if (unlikely(err)) {
13723                 WL_ERR(("error (%d)\n", err));
13724                 goto end_bands;
13725         }
13726
13727         err = wldev_iovar_getint(dev, "nmode", &nmode);
13728         if (unlikely(err)) {
13729                 WL_ERR(("error reading nmode (%d)\n", err));
13730         }
13731
13732 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
13733         err = wldev_iovar_getint(dev, "vhtmode", &vhtmode);
13734         if (unlikely(err)) {
13735                 WL_ERR(("error reading vhtmode (%d)\n", err));
13736         }
13737
13738         if (vhtmode) {
13739                 err = wldev_iovar_getint(dev, "txstreams", &txstreams);
13740                 if (unlikely(err)) {
13741                         WL_ERR(("error reading txstreams (%d)\n", err));
13742                 }
13743
13744                 err = wldev_iovar_getint(dev, "rxstreams", &rxstreams);
13745                 if (unlikely(err)) {
13746                         WL_ERR(("error reading rxstreams (%d)\n", err));
13747                 }
13748
13749                 err = wldev_iovar_getint(dev, "ldpc_cap", &ldpc_cap);
13750                 if (unlikely(err)) {
13751                         WL_ERR(("error reading ldpc_cap (%d)\n", err));
13752                 }
13753
13754                 err = wldev_iovar_getint(dev, "stbc_rx", &stbc_rx);
13755                 if (unlikely(err)) {
13756                         WL_ERR(("error reading stbc_rx (%d)\n", err));
13757                 }
13758
13759                 err = wldev_iovar_getint(dev, "stbc_tx", &stbc_tx);
13760                 if (unlikely(err)) {
13761                         WL_ERR(("error reading stbc_tx (%d)\n", err));
13762                 }
13763
13764                 err = wldev_iovar_getint(dev, "txbf_bfe_cap", &txbf_bfe_cap);
13765                 if (unlikely(err)) {
13766                         WL_ERR(("error reading txbf_bfe_cap (%d)\n", err));
13767                 }
13768
13769                 err = wldev_iovar_getint(dev, "txbf_bfr_cap", &txbf_bfr_cap);
13770                 if (unlikely(err)) {
13771                         WL_ERR(("error reading txbf_bfr_cap (%d)\n", err));
13772                 }
13773         }
13774 #endif 
13775
13776         /* For nmode and vhtmode   check bw cap */
13777         if (nmode ||
13778 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
13779                 vhtmode ||
13780 #endif 
13781                 0) {
13782                 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
13783                 if (unlikely(err)) {
13784                         WL_ERR(("error get mimo_bw_cap (%d)\n", err));
13785                 }
13786         }
13787
13788         err = wl_construct_reginfo(cfg, bw_cap);
13789         if (err) {
13790                 WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
13791                 if (err != BCME_UNSUPPORTED)
13792                         goto end_bands;
13793                 err = 0;
13794         }
13795         wiphy = bcmcfg_to_wiphy(cfg);
13796         nband = bandlist[0];
13797
13798         for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) {
13799                 index = -1;
13800                 if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
13801                         bands[IEEE80211_BAND_5GHZ] =
13802                                 &__wl_band_5ghz_a;
13803                         index = IEEE80211_BAND_5GHZ;
13804                         if (nmode && (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G))
13805                                 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
13806
13807 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
13808                         /* VHT capabilities. */
13809                         if (vhtmode) {
13810                                 /* Supported */
13811                                 bands[index]->vht_cap.vht_supported = TRUE;
13812
13813                                 for (j = 1; j <= VHT_CAP_MCS_MAP_NSS_MAX; j++) {
13814                                         /* TX stream rates. */
13815                                         if (j <= txstreams) {
13816                                                 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_0_9,
13817                                                         bands[index]->vht_cap.vht_mcs.tx_mcs_map);
13818                                         } else {
13819                                                 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_NONE,
13820                                                         bands[index]->vht_cap.vht_mcs.tx_mcs_map);
13821                                         }
13822
13823                                         /* RX stream rates. */
13824                                         if (j <= rxstreams) {
13825                                                 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_0_9,
13826                                                         bands[index]->vht_cap.vht_mcs.rx_mcs_map);
13827                                         } else {
13828                                                 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_NONE,
13829                                                         bands[index]->vht_cap.vht_mcs.rx_mcs_map);
13830                                         }
13831                                 }
13832
13833
13834                                 /* Capabilities */
13835                                 /* 80 MHz is mandatory */
13836                                 bands[index]->vht_cap.cap |=
13837                                         IEEE80211_VHT_CAP_SHORT_GI_80;
13838
13839                                 if (WL_BW_CAP_160MHZ(bw_cap)) {
13840                                         bands[index]->vht_cap.cap |=
13841                                                 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
13842                                         bands[index]->vht_cap.cap |=
13843                                                 IEEE80211_VHT_CAP_SHORT_GI_160;
13844                                 }
13845
13846                                 bands[index]->vht_cap.cap |=
13847                                         IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
13848
13849                                 if (ldpc_cap)
13850                                         bands[index]->vht_cap.cap |=
13851                                                 IEEE80211_VHT_CAP_RXLDPC;
13852
13853                                 if (stbc_tx)
13854                                         bands[index]->vht_cap.cap |=
13855                                                 IEEE80211_VHT_CAP_TXSTBC;
13856
13857                                 if (stbc_rx)
13858                                         bands[index]->vht_cap.cap |=
13859                                                 (stbc_rx << VHT_CAP_INFO_RX_STBC_SHIFT);
13860
13861                                 if (txbf_bfe_cap)
13862                                         bands[index]->vht_cap.cap |=
13863                                                 IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
13864
13865                                 if (txbf_bfr_cap) {
13866                                         bands[index]->vht_cap.cap |=
13867                                                 IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
13868                                 }
13869
13870                                 if (txbf_bfe_cap || txbf_bfr_cap) {
13871                                         bands[index]->vht_cap.cap |=
13872                                                 (2 << VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT);
13873                                         bands[index]->vht_cap.cap |=
13874                                                 ((txstreams - 1) <<
13875                                                         VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT);
13876                                         bands[index]->vht_cap.cap |=
13877                                                 IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
13878                                 }
13879
13880                                 /* AMPDU length limit, support max 1MB (2 ^ (13 + 7)) */
13881                                 bands[index]->vht_cap.cap |=
13882                                         (7 << VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT);
13883                                 WL_INFORM(("%s band[%d] vht_enab=%d vht_cap=%08x "
13884                                         "vht_rx_mcs_map=%04x vht_tx_mcs_map=%04x\n",
13885                                         __FUNCTION__, index,
13886                                         bands[index]->vht_cap.vht_supported,
13887                                         bands[index]->vht_cap.cap,
13888                                         bands[index]->vht_cap.vht_mcs.rx_mcs_map,
13889                                         bands[index]->vht_cap.vht_mcs.tx_mcs_map));
13890                         }
13891 #endif 
13892                 }
13893                 else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
13894                         bands[IEEE80211_BAND_2GHZ] =
13895                                 &__wl_band_2ghz;
13896                         index = IEEE80211_BAND_2GHZ;
13897                         if (bw_cap == WLC_N_BW_40ALL)
13898                                 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
13899                 }
13900
13901                 if ((index >= 0) && nmode) {
13902                         bands[index]->ht_cap.cap |=
13903                                 (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40);
13904                         bands[index]->ht_cap.ht_supported = TRUE;
13905                         bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
13906                         bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
13907                         /* An HT shall support all EQM rates for one spatial stream */
13908                         bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
13909                 }
13910
13911         }
13912
13913         wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
13914         wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
13915
13916         /* check if any bands populated otherwise makes 2Ghz as default */
13917         if (wiphy->bands[IEEE80211_BAND_2GHZ] == NULL &&
13918                 wiphy->bands[IEEE80211_BAND_5GHZ] == NULL) {
13919                 /* Setup 2Ghz band as default */
13920                 wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
13921         }
13922
13923         if (notify)
13924                 wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
13925
13926 end_bands:
13927         if (rollback_lock)
13928                 mutex_unlock(&cfg->usr_sync);
13929         return err;
13930 }
13931
13932 static s32 __wl_cfg80211_up(struct bcm_cfg80211 *cfg)
13933 {
13934         s32 err = 0;
13935         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
13936         struct wireless_dev *wdev = ndev->ieee80211_ptr;
13937
13938         WL_DBG(("In\n"));
13939
13940         err = wl_create_event_handler(cfg);
13941         if (err) {
13942                 WL_ERR(("wl_create_event_handler failed\n"));
13943                 return err;
13944         }
13945         wl_init_event_handler(cfg);
13946
13947         err = dhd_config_dongle(cfg);
13948         if (unlikely(err))
13949                 return err;
13950
13951         err = wl_config_ifmode(cfg, ndev, wdev->iftype);
13952         if (unlikely(err && err != -EINPROGRESS)) {
13953                 WL_ERR(("wl_config_ifmode failed\n"));
13954                 if (err == -1) {
13955                         WL_ERR(("return error %d\n", err));
13956                         return err;
13957                 }
13958         }
13959
13960         err = wl_init_scan(cfg);
13961         if (err) {
13962                 WL_ERR(("wl_init_scan failed\n"));
13963                 return err;
13964         }
13965         err = wl_update_wiphybands(cfg, true);
13966         if (unlikely(err)) {
13967                 WL_ERR(("wl_update_wiphybands failed\n"));
13968                 if (err == -1) {
13969                         WL_ERR(("return error %d\n", err));
13970                         return err;
13971                 }
13972         }
13973 #ifdef DHD_LOSSLESS_ROAMING
13974         if (timer_pending(&cfg->roam_timeout)) {
13975                 del_timer_sync(&cfg->roam_timeout);
13976         }
13977 #endif /* DHD_LOSSLESS_ROAMING */
13978
13979         err = dhd_monitor_init(cfg->pub);
13980
13981         wl_set_drv_status(cfg, READY, ndev);
13982         return err;
13983 }
13984
13985 static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg)
13986 {
13987         s32 err = 0;
13988         unsigned long flags;
13989         struct net_info *iter, *next;
13990         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
13991 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
13992         struct net_device *p2p_net = cfg->p2p_net;
13993 #endif 
13994 #ifdef PROP_TXSTATUS_VSDB
13995 #if defined(BCMSDIO)
13996         dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
13997 #endif
13998 #endif /* PROP_TXSTATUS_VSDB */
13999         WL_DBG(("In\n"));
14000         /* Delete pm_enable_work */
14001         wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
14002
14003 #ifdef WL_NAN
14004         wl_cfgnan_stop_handler(ndev, g_bcm_cfg, NULL, 0, NULL);
14005 #endif /* WL_NAN */
14006
14007         if (cfg->p2p_supported) {
14008                 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
14009 #ifdef PROP_TXSTATUS_VSDB
14010 #if defined(BCMSDIO)
14011                 if (wl_cfgp2p_vif_created(cfg)) {
14012                         bool enabled = false;
14013                         dhd_wlfc_get_enable(dhd, &enabled);
14014                         if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
14015                                 dhd->op_mode != DHD_FLAG_IBSS_MODE) {
14016                                 dhd_wlfc_deinit(dhd);
14017                                 cfg->wlfc_on = false;
14018                         }
14019                 }
14020 #endif 
14021 #endif /* PROP_TXSTATUS_VSDB */
14022         }
14023
14024
14025         /* If primary BSS is operational (for e.g SoftAP), bring it down */
14026         if (wl_cfgp2p_bss_isup(ndev, 0)) {
14027                 if (wl_cfgp2p_bss(cfg, ndev, 0, 0) < 0)
14028                         WL_ERR(("BSS down failed \n"));
14029         }
14030
14031         /* Check if cfg80211 interface is already down */
14032         if (!wl_get_drv_status(cfg, READY, ndev))
14033                 return err;     /* it is even not ready */
14034
14035         /* clear all the security setting on primary Interface */
14036         wl_cfg80211_clear_security(cfg);
14037
14038 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14039         4 && __GNUC_MINOR__ >= 6))
14040 _Pragma("GCC diagnostic push")
14041 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
14042 #endif
14043         for_each_ndev(cfg, iter, next) {
14044                 if (iter->ndev) /* p2p discovery iface is null */
14045                         wl_set_drv_status(cfg, SCAN_ABORTING, iter->ndev);
14046         }
14047 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14048         4 && __GNUC_MINOR__ >= 6))
14049 _Pragma("GCC diagnostic pop")
14050 #endif
14051
14052 #ifdef P2P_LISTEN_OFFLOADING
14053         wl_cfg80211_p2plo_deinit(cfg);
14054 #endif /* P2P_LISTEN_OFFLOADING */
14055
14056         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
14057         if (cfg->scan_request) {
14058                 cfg80211_scan_done(cfg->scan_request, true);
14059                 cfg->scan_request = NULL;
14060         }
14061         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
14062 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14063         4 && __GNUC_MINOR__ >= 6))
14064 _Pragma("GCC diagnostic push")
14065 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
14066 #endif
14067         for_each_ndev(cfg, iter, next) {
14068                 /* p2p discovery iface ndev ptr could be null */
14069                 if (iter->ndev == NULL)
14070                         continue;
14071                 wl_clr_drv_status(cfg, READY, iter->ndev);
14072                 wl_clr_drv_status(cfg, SCANNING, iter->ndev);
14073                 wl_clr_drv_status(cfg, SCAN_ABORTING, iter->ndev);
14074                 wl_clr_drv_status(cfg, CONNECTING, iter->ndev);
14075                 wl_clr_drv_status(cfg, CONNECTED, iter->ndev);
14076                 wl_clr_drv_status(cfg, DISCONNECTING, iter->ndev);
14077                 wl_clr_drv_status(cfg, AP_CREATED, iter->ndev);
14078                 wl_clr_drv_status(cfg, AP_CREATING, iter->ndev);
14079         }
14080 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14081         4 && __GNUC_MINOR__ >= 6))
14082 _Pragma("GCC diagnostic pop")
14083 #endif
14084         bcmcfg_to_prmry_ndev(cfg)->ieee80211_ptr->iftype =
14085                 NL80211_IFTYPE_STATION;
14086 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
14087                 if (p2p_net)
14088                         dev_close(p2p_net);
14089 #endif 
14090
14091         /* Avoid deadlock from wl_cfg80211_down */
14092         mutex_unlock(&cfg->usr_sync);
14093         wl_destroy_event_handler(cfg);
14094         mutex_lock(&cfg->usr_sync);
14095         wl_flush_eq(cfg);
14096         wl_link_down(cfg);
14097         if (cfg->p2p_supported) {
14098                 if (timer_pending(&cfg->p2p->listen_timer))
14099                         del_timer_sync(&cfg->p2p->listen_timer);
14100                 wl_cfgp2p_down(cfg);
14101         }
14102
14103         if (timer_pending(&cfg->scan_timeout)) {
14104                 del_timer_sync(&cfg->scan_timeout);
14105         }
14106
14107         DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
14108
14109         dhd_monitor_uninit();
14110 #ifdef WLAIBSS_MCHAN
14111         bcm_cfg80211_del_ibss_if(cfg->wdev->wiphy, cfg->ibss_cfgdev);
14112 #endif /* WLAIBSS_MCHAN */
14113
14114 #if defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF)
14115         /* Clean up if not removed already */
14116         if (cfg->bss_cfgdev)
14117                 wl_cfg80211_del_iface(cfg->wdev->wiphy, cfg->bss_cfgdev);
14118 #endif /* defined (WL_VIRTUAL_APSTA) || defined (DUAL_STA_STATIC_IF) */
14119
14120 #ifdef WL11U
14121         /* Clear interworking element. */
14122         if (cfg->wl11u) {
14123                 cfg->wl11u = FALSE;
14124                 cfg->iw_ie_len = 0;
14125                 memset(cfg->iw_ie, 0, IW_IES_MAX_BUF_LEN);
14126         }
14127 #endif /* WL11U */
14128
14129 #ifdef CUSTOMER_HW4_DEBUG
14130         if (wl_scan_timeout_dbg_enabled)
14131                 wl_scan_timeout_dbg_clear();
14132 #endif /* CUSTOMER_HW4_DEBUG */
14133
14134         cfg->disable_roam_event = false;
14135
14136         DNGL_FUNC(dhd_cfg80211_down, (cfg));
14137
14138 #ifdef DHD_IFDEBUG
14139         /* Printout all netinfo entries */
14140         wl_probe_wdev_all(cfg);
14141 #endif /* DHD_IFDEBUG */
14142
14143         return err;
14144 }
14145
14146 s32 wl_cfg80211_up(void *para)
14147 {
14148         struct bcm_cfg80211 *cfg;
14149         s32 err = 0;
14150         int val = 1;
14151         dhd_pub_t *dhd;
14152 #ifdef DISABLE_PM_BCNRX
14153         s32 interr = 0;
14154         uint param = 0;
14155         s8 iovbuf[WLC_IOCTL_SMLEN];
14156 #endif /* DISABLE_PM_BCNRX */
14157
14158         (void)para;
14159         WL_DBG(("In\n"));
14160         cfg = g_bcm_cfg;
14161
14162         if ((err = wldev_ioctl(bcmcfg_to_prmry_ndev(cfg), WLC_GET_VERSION, &val,
14163                 sizeof(int), false) < 0)) {
14164                 WL_ERR(("WLC_GET_VERSION failed, err=%d\n", err));
14165                 return err;
14166         }
14167         val = dtoh32(val);
14168         if (val != WLC_IOCTL_VERSION && val != 1) {
14169                 WL_ERR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
14170                         val, WLC_IOCTL_VERSION));
14171                 return BCME_VERSION;
14172         }
14173         ioctl_version = val;
14174         WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version));
14175
14176         mutex_lock(&cfg->usr_sync);
14177         dhd = (dhd_pub_t *)(cfg->pub);
14178         if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
14179                 err = wl_cfg80211_attach_post(bcmcfg_to_prmry_ndev(cfg));
14180                 if (unlikely(err)) {
14181                         mutex_unlock(&cfg->usr_sync);
14182                         return err;
14183                 }
14184         }
14185         err = __wl_cfg80211_up(cfg);
14186         if (unlikely(err))
14187                 WL_ERR(("__wl_cfg80211_up failed\n"));
14188
14189
14190
14191         /* IOVAR configurations with 'up' condition */
14192 #ifdef DISABLE_PM_BCNRX
14193         bcm_mkiovar("pm_bcnrx", (char *)&param, 4, iovbuf, sizeof(iovbuf));
14194         interr = wldev_ioctl(bcmcfg_to_prmry_ndev(cfg), WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
14195         if (unlikely(interr))
14196                 WL_ERR(("Set pm_bcnrx returned (%d)\n", interr));
14197 #endif /* DISABLE_PM_BCNRX */
14198
14199         mutex_unlock(&cfg->usr_sync);
14200
14201 #ifdef WLAIBSS_MCHAN
14202         bcm_cfg80211_add_ibss_if(cfg->wdev->wiphy, IBSS_IF_NAME);
14203 #endif /* WLAIBSS_MCHAN */
14204
14205 #ifdef DUAL_STA_STATIC_IF
14206 #ifdef WL_VIRTUAL_APSTA
14207 #error "Both DUAL STA and DUAL_STA_STATIC_IF can't be enabled together"
14208 #endif
14209         /* Static Interface support is currently supported only for STA only builds (without P2P) */
14210         wl_cfg80211_create_iface(cfg->wdev->wiphy, NL80211_IFTYPE_STATION, NULL, "wlan%d");
14211 #endif /* DUAL_STA_STATIC_IF */
14212
14213         return err;
14214 }
14215
14216 /* Private Event to Supplicant with indication that chip hangs */
14217 int wl_cfg80211_hang(struct net_device *dev, u16 reason)
14218 {
14219         struct bcm_cfg80211 *cfg;
14220         dhd_pub_t *dhd;
14221 #if defined(SOFTAP_SEND_HANGEVT)
14222         /* specifc mac address used for hang event */
14223         uint8 hang_mac[ETHER_ADDR_LEN] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
14224 #endif /* SOFTAP_SEND_HANGEVT */
14225         if (!g_bcm_cfg) {
14226                 return BCME_ERROR;
14227         }
14228
14229         cfg = g_bcm_cfg;
14230         dhd = (dhd_pub_t *)(cfg->pub);
14231
14232 #ifdef DHD_USE_EXTENDED_HANG_REASON
14233         if (dhd->hang_reason != 0) {
14234                 reason = dhd->hang_reason;
14235         }
14236 #endif /* DHD_USE_EXTENDED_HANG_REASON */
14237
14238         WL_ERR(("In : chip crash eventing, reason=0x%x\n", (uint32)(dhd->hang_reason)));
14239         wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
14240 #if defined(SOFTAP_SEND_HANGEVT)
14241         if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
14242                 cfg80211_del_sta(dev, hang_mac, GFP_ATOMIC);
14243         } else
14244 #endif /* SOFTAP_SEND_HANGEVT */
14245         {
14246                 CFG80211_DISCONNECTED(dev, reason, NULL, 0, false, GFP_KERNEL);
14247         }
14248 #if defined(RSSIAVG)
14249         wl_free_rssi_cache(&g_rssi_cache_ctrl);
14250 #endif
14251 #if defined(BSSCACHE)
14252         wl_free_bss_cache(&g_bss_cache_ctrl);
14253 #endif
14254         if (cfg != NULL) {
14255                 wl_link_down(cfg);
14256         }
14257         return 0;
14258 }
14259
14260 s32 wl_cfg80211_down(void *para)
14261 {
14262         struct bcm_cfg80211 *cfg;
14263         s32 err = 0;
14264
14265         (void)para;
14266         WL_DBG(("In\n"));
14267         cfg = g_bcm_cfg;
14268         mutex_lock(&cfg->usr_sync);
14269 #if defined(RSSIAVG)
14270         wl_free_rssi_cache(&g_rssi_cache_ctrl);
14271 #endif
14272 #if defined(BSSCACHE)
14273         wl_free_bss_cache(&g_bss_cache_ctrl);
14274 #endif
14275         err = __wl_cfg80211_down(cfg);
14276         mutex_unlock(&cfg->usr_sync);
14277
14278         return err;
14279 }
14280
14281 static void *wl_read_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 item)
14282 {
14283         unsigned long flags;
14284         void *rptr = NULL;
14285         struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
14286
14287         if (!profile)
14288                 return NULL;
14289         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
14290         switch (item) {
14291         case WL_PROF_SEC:
14292                 rptr = &profile->sec;
14293                 break;
14294         case WL_PROF_ACT:
14295                 rptr = &profile->active;
14296                 break;
14297         case WL_PROF_BSSID:
14298                 rptr = profile->bssid;
14299                 break;
14300         case WL_PROF_SSID:
14301                 rptr = &profile->ssid;
14302                 break;
14303         case WL_PROF_CHAN:
14304                 rptr = &profile->channel;
14305                 break;
14306         }
14307         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
14308         if (!rptr)
14309                 WL_ERR(("invalid item (%d)\n", item));
14310         return rptr;
14311 }
14312
14313 static s32
14314 wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
14315         const wl_event_msg_t *e, const void *data, s32 item)
14316 {
14317         s32 err = 0;
14318         const struct wlc_ssid *ssid;
14319         unsigned long flags;
14320         struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
14321
14322         if (!profile)
14323                 return WL_INVALID;
14324         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
14325         switch (item) {
14326         case WL_PROF_SSID:
14327                 ssid = (const wlc_ssid_t *) data;
14328                 memset(profile->ssid.SSID, 0,
14329                         sizeof(profile->ssid.SSID));
14330                 memcpy(profile->ssid.SSID, ssid->SSID, ssid->SSID_len);
14331                 profile->ssid.SSID_len = ssid->SSID_len;
14332                 break;
14333         case WL_PROF_BSSID:
14334                 if (data)
14335                         memcpy(profile->bssid, data, ETHER_ADDR_LEN);
14336                 else
14337                         memset(profile->bssid, 0, ETHER_ADDR_LEN);
14338                 break;
14339         case WL_PROF_SEC:
14340                 memcpy(&profile->sec, data, sizeof(profile->sec));
14341                 break;
14342         case WL_PROF_ACT:
14343                 profile->active = *(const bool *)data;
14344                 break;
14345         case WL_PROF_BEACONINT:
14346                 profile->beacon_interval = *(const u16 *)data;
14347                 break;
14348         case WL_PROF_DTIMPERIOD:
14349                 profile->dtim_period = *(const u8 *)data;
14350                 break;
14351         case WL_PROF_CHAN:
14352                 profile->channel = *(const u32*)data;
14353                 break;
14354         default:
14355                 err = -EOPNOTSUPP;
14356                 break;
14357         }
14358         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
14359
14360         if (err == -EOPNOTSUPP)
14361                 WL_ERR(("unsupported item (%d)\n", item));
14362
14363         return err;
14364 }
14365
14366 void wl_cfg80211_dbg_level(u32 level)
14367 {
14368         /*
14369         * prohibit to change debug level
14370         * by insmod parameter.
14371         * eventually debug level will be configured
14372         * in compile time by using CONFIG_XXX
14373         */
14374         /* wl_dbg_level = level; */
14375 }
14376
14377 static bool wl_is_ibssmode(struct bcm_cfg80211 *cfg, struct net_device *ndev)
14378 {
14379         return wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS;
14380 }
14381
14382 static __used bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg)
14383 {
14384         return cfg->ibss_starter;
14385 }
14386
14387 static void wl_rst_ie(struct bcm_cfg80211 *cfg)
14388 {
14389         struct wl_ie *ie = wl_to_ie(cfg);
14390
14391         ie->offset = 0;
14392 }
14393
14394 static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v)
14395 {
14396         struct wl_ie *ie = wl_to_ie(cfg);
14397         s32 err = 0;
14398
14399         if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
14400                 WL_ERR(("ei crosses buffer boundary\n"));
14401                 return -ENOSPC;
14402         }
14403         ie->buf[ie->offset] = t;
14404         ie->buf[ie->offset + 1] = l;
14405         memcpy(&ie->buf[ie->offset + 2], v, l);
14406         ie->offset += l + 2;
14407
14408         return err;
14409 }
14410
14411 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, const u8 *ie_stream, u32 *ie_size,
14412         bool roam)
14413 {
14414         u8 *ssidie;
14415         /* cfg80211_find_ie defined in kernel returning const u8 */
14416 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14417         4 && __GNUC_MINOR__ >= 6))
14418 _Pragma("GCC diagnostic push")
14419 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
14420 #endif
14421         ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size);
14422 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14423         4 && __GNUC_MINOR__ >= 6))
14424 _Pragma("GCC diagnostic pop")
14425 #endif
14426         if (!ssidie)
14427                 return;
14428         if (ssidie[1] != bi->SSID_len) {
14429                 if (ssidie[1]) {
14430                         WL_ERR(("%s: Wrong SSID len: %d != %d\n",
14431                                 __FUNCTION__, ssidie[1], bi->SSID_len));
14432                 }
14433                 if (roam) {
14434                         WL_ERR(("Changing the SSID Info.\n"));
14435                         memmove(ssidie + bi->SSID_len + 2,
14436                                 (ssidie + 2) + ssidie[1],
14437                                 *ie_size - (ssidie + 2 + ssidie[1] - ie_stream));
14438                         memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
14439                         *ie_size = *ie_size + bi->SSID_len - ssidie[1];
14440                         ssidie[1] = bi->SSID_len;
14441                 }
14442                 return;
14443         }
14444         if (*(ssidie + 2) == '\0')
14445                  memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
14446         return;
14447 }
14448
14449 static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size)
14450 {
14451         struct wl_ie *ie = wl_to_ie(cfg);
14452         s32 err = 0;
14453
14454         if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
14455                 WL_ERR(("ei_stream crosses buffer boundary\n"));
14456                 return -ENOSPC;
14457         }
14458         memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
14459         ie->offset += ie_size;
14460
14461         return err;
14462 }
14463
14464 static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size)
14465 {
14466         struct wl_ie *ie = wl_to_ie(cfg);
14467         s32 err = 0;
14468
14469         if (unlikely(ie->offset > dst_size)) {
14470                 WL_ERR(("dst_size is not enough\n"));
14471                 return -ENOSPC;
14472         }
14473         memcpy(dst, &ie->buf[0], ie->offset);
14474
14475         return err;
14476 }
14477
14478 static u32 wl_get_ielen(struct bcm_cfg80211 *cfg)
14479 {
14480         struct wl_ie *ie = wl_to_ie(cfg);
14481
14482         return ie->offset;
14483 }
14484
14485 static void wl_link_up(struct bcm_cfg80211 *cfg)
14486 {
14487         cfg->link_up = true;
14488 }
14489
14490 static void wl_link_down(struct bcm_cfg80211 *cfg)
14491 {
14492         struct wl_connect_info *conn_info = wl_to_conn(cfg);
14493
14494         WL_DBG(("In\n"));
14495         cfg->link_up = false;
14496         conn_info->req_ie_len = 0;
14497         conn_info->resp_ie_len = 0;
14498 }
14499
14500 static unsigned long wl_lock_eq(struct bcm_cfg80211 *cfg)
14501 {
14502         unsigned long flags;
14503
14504         spin_lock_irqsave(&cfg->eq_lock, flags);
14505         return flags;
14506 }
14507
14508 static void wl_unlock_eq(struct bcm_cfg80211 *cfg, unsigned long flags)
14509 {
14510         spin_unlock_irqrestore(&cfg->eq_lock, flags);
14511 }
14512
14513 static void wl_init_eq_lock(struct bcm_cfg80211 *cfg)
14514 {
14515         spin_lock_init(&cfg->eq_lock);
14516 }
14517
14518 static void wl_delay(u32 ms)
14519 {
14520         if (in_atomic() || (ms < jiffies_to_msecs(1))) {
14521                 OSL_DELAY(ms*1000);
14522         } else {
14523                 OSL_SLEEP(ms);
14524         }
14525 }
14526
14527 s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
14528 {
14529         struct bcm_cfg80211 *cfg = g_bcm_cfg;
14530         struct ether_addr primary_mac;
14531         if (!cfg->p2p)
14532                 return -1;
14533         if (!p2p_is_on(cfg)) {
14534                 get_primary_mac(cfg, &primary_mac);
14535                 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
14536         } else {
14537                 memcpy(p2pdev_addr->octet, wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE).octet,
14538                         ETHER_ADDR_LEN);
14539         }
14540
14541         return 0;
14542 }
14543 s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
14544 {
14545         struct bcm_cfg80211 *cfg;
14546
14547         cfg = g_bcm_cfg;
14548
14549         return wl_cfgp2p_set_p2p_noa(cfg, net, buf, len);
14550 }
14551
14552 s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
14553 {
14554         struct bcm_cfg80211 *cfg;
14555         cfg = g_bcm_cfg;
14556
14557         return wl_cfgp2p_get_p2p_noa(cfg, net, buf, len);
14558 }
14559
14560 s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
14561 {
14562         struct bcm_cfg80211 *cfg;
14563         cfg = g_bcm_cfg;
14564
14565         return wl_cfgp2p_set_p2p_ps(cfg, net, buf, len);
14566 }
14567
14568 s32 wl_cfg80211_set_p2p_ecsa(struct net_device *net, char* buf, int len)
14569 {
14570         struct bcm_cfg80211 *cfg;
14571         cfg = g_bcm_cfg;
14572
14573         return wl_cfgp2p_set_p2p_ecsa(cfg, net, buf, len);
14574 }
14575
14576 #ifdef P2PLISTEN_AP_SAMECHN
14577 s32 wl_cfg80211_set_p2p_resp_ap_chn(struct net_device *net, s32 enable)
14578 {
14579         s32 ret = wldev_iovar_setint(net, "p2p_resp_ap_chn", enable);
14580
14581         if ((ret == 0) && enable) {
14582                 /* disable PM for p2p responding on infra AP channel */
14583                 s32 pm = PM_OFF;
14584
14585                 ret = wldev_ioctl(net, WLC_SET_PM, &pm, sizeof(pm), true);
14586         }
14587
14588         return ret;
14589 }
14590 #endif /* P2PLISTEN_AP_SAMECHN */
14591
14592 s32 wl_cfg80211_channel_to_freq(u32 channel)
14593 {
14594         int freq = 0;
14595
14596 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
14597         freq = ieee80211_channel_to_frequency(channel);
14598 #else
14599         {
14600                 u16 band = 0;
14601                 if (channel <= CH_MAX_2G_CHANNEL)
14602                         band = IEEE80211_BAND_2GHZ;
14603                 else
14604                         band = IEEE80211_BAND_5GHZ;
14605                 freq = ieee80211_channel_to_frequency(channel, band);
14606         }
14607 #endif
14608         return freq;
14609 }
14610
14611
14612 #ifdef WLTDLS
14613 static s32
14614 wl_tdls_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
14615         const wl_event_msg_t *e, void *data) {
14616
14617         struct net_device *ndev = NULL;
14618         u32 reason = ntoh32(e->reason);
14619         s8 *msg = NULL;
14620
14621         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
14622
14623         switch (reason) {
14624         case WLC_E_TDLS_PEER_DISCOVERED :
14625                 msg = " TDLS PEER DISCOVERD ";
14626                 break;
14627         case WLC_E_TDLS_PEER_CONNECTED :
14628 #ifdef PCIE_FULL_DONGLE
14629                 dhd_tdls_update_peer_info(ndev, TRUE, (uint8 *)&e->addr.octet[0]);
14630 #endif /* PCIE_FULL_DONGLE */
14631                 if (cfg->tdls_mgmt_frame) {
14632 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
14633                         cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
14634                                 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len, 0);
14635 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14636                         cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
14637                                 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
14638                                 0, GFP_ATOMIC);
14639 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
14640         defined(WL_COMPAT_WIRELESS)
14641                         cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
14642                                 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
14643                                 GFP_ATOMIC);
14644 #else
14645                         cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq,
14646                                 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
14647                                 GFP_ATOMIC);
14648 #endif /* LINUX_VERSION >= VERSION(3, 12, 0) */
14649                 }
14650                 msg = " TDLS PEER CONNECTED ";
14651                 break;
14652         case WLC_E_TDLS_PEER_DISCONNECTED :
14653 #ifdef PCIE_FULL_DONGLE
14654                 dhd_tdls_update_peer_info(ndev, FALSE, (uint8 *)&e->addr.octet[0]);
14655 #endif /* PCIE_FULL_DONGLE */
14656                 if (cfg->tdls_mgmt_frame) {
14657                         kfree(cfg->tdls_mgmt_frame);
14658                         cfg->tdls_mgmt_frame = NULL;
14659                         cfg->tdls_mgmt_freq = 0;
14660                 }
14661                 msg = "TDLS PEER DISCONNECTED ";
14662                 break;
14663         }
14664         if (msg) {
14665                 WL_ERR(("%s: " MACDBG " on %s ndev\n", msg, MAC2STRDBG((u8*)(&e->addr)),
14666                         (bcmcfg_to_prmry_ndev(cfg) == ndev) ? "primary" : "secondary"));
14667         }
14668         return 0;
14669
14670 }
14671 #endif  /* WLTDLS */
14672
14673 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
14674 static s32
14675 #if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \
14676         KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14677 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
14678         u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
14679         u32 peer_capability, const u8 *data, size_t len)
14680 #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) && \
14681                 (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
14682 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
14683         const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
14684         u32 peer_capability, const u8 *data, size_t len)
14685 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
14686 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
14687         const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
14688         u32 peer_capability, bool initiator, const u8 *data, size_t len)
14689 #else
14690 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
14691         u8 *peer, u8 action_code, u8 dialog_token, u16 status_code, const u8 *data,
14692         size_t len)
14693 #endif  /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
14694 {
14695         s32 ret = 0;
14696 #ifdef WLTDLS
14697         struct bcm_cfg80211 *cfg;
14698         tdls_wfd_ie_iovar_t info;
14699         memset(&info, 0, sizeof(tdls_wfd_ie_iovar_t));
14700         cfg = g_bcm_cfg;
14701
14702 #if defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)
14703         /* Some customer platform back ported this feature from kernel 3.15 to kernel 3.10
14704         * and that cuases build error
14705         */
14706         BCM_REFERENCE(peer_capability);
14707 #endif  /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
14708
14709         switch (action_code) {
14710         /* We need to set TDLS Wifi Display IE to firmware
14711          * using tdls_wfd_ie iovar
14712          */
14713         case WLAN_TDLS_SET_PROBE_WFD_IE:
14714                 WL_ERR(("%s WLAN_TDLS_SET_PROBE_WFD_IE\n", __FUNCTION__));
14715                 info.mode = TDLS_WFD_PROBE_IE_TX;
14716                 memcpy(&info.data, data, len);
14717                 info.length = len;
14718                 break;
14719         case WLAN_TDLS_SET_SETUP_WFD_IE:
14720                 WL_ERR(("%s WLAN_TDLS_SET_SETUP_WFD_IE\n", __FUNCTION__));
14721                 info.mode = TDLS_WFD_IE_TX;
14722                 memcpy(&info.data, data, len);
14723                 info.length = len;
14724                 break;
14725         case WLAN_TDLS_SET_WFD_ENABLED:
14726                 WL_ERR(("%s WLAN_TDLS_SET_MODE_WFD_ENABLED\n", __FUNCTION__));
14727                 dhd_tdls_set_mode((dhd_pub_t *)(cfg->pub), true);
14728                 goto out;
14729         case WLAN_TDLS_SET_WFD_DISABLED:
14730                 WL_ERR(("%s WLAN_TDLS_SET_MODE_WFD_DISABLED\n", __FUNCTION__));
14731                 dhd_tdls_set_mode((dhd_pub_t *)(cfg->pub), false);
14732                 goto out;
14733         default:
14734                 WL_ERR(("Unsupported action code : %d\n", action_code));
14735                 goto out;
14736         }
14737
14738         ret = wldev_iovar_setbuf(dev, "tdls_wfd_ie", &info, sizeof(info),
14739                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
14740
14741         if (ret) {
14742                 WL_ERR(("tdls_wfd_ie error %d\n", ret));
14743         }
14744 out:
14745 #endif /* WLTDLS */
14746         return ret;
14747 }
14748
14749 static s32
14750 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
14751 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
14752         const u8 *peer, enum nl80211_tdls_operation oper)
14753 #else
14754 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
14755         u8 *peer, enum nl80211_tdls_operation oper)
14756 #endif
14757 {
14758         s32 ret = 0;
14759 #ifdef WLTDLS
14760         struct bcm_cfg80211 *cfg;
14761         tdls_iovar_t info;
14762         dhd_pub_t *dhdp;
14763         bool tdls_auto_mode = false;
14764         cfg = g_bcm_cfg;
14765         dhdp = (dhd_pub_t *)(cfg->pub);
14766         memset(&info, 0, sizeof(tdls_iovar_t));
14767         if (peer) {
14768                 memcpy(&info.ea, peer, ETHER_ADDR_LEN);
14769         } else {
14770                 return -1;
14771         }
14772         switch (oper) {
14773         case NL80211_TDLS_DISCOVERY_REQ:
14774                 /* If the discovery request is broadcast then we need to set
14775                  * info.mode to Tunneled Probe Request
14776                  */
14777                 if (memcmp(peer, (const uint8 *)BSSID_BROADCAST, ETHER_ADDR_LEN) == 0) {
14778                         info.mode = TDLS_MANUAL_EP_WFD_TPQ;
14779                         WL_ERR(("%s TDLS TUNNELED PRBOBE REQUEST\n", __FUNCTION__));
14780                 } else {
14781                         info.mode = TDLS_MANUAL_EP_DISCOVERY;
14782                 }
14783                 break;
14784         case NL80211_TDLS_SETUP:
14785                 if (dhdp->tdls_mode == true) {
14786                         info.mode = TDLS_MANUAL_EP_CREATE;
14787                         tdls_auto_mode = false;
14788                         ret = dhd_tdls_enable(dev, false, tdls_auto_mode, NULL);
14789                         if (ret < 0) {
14790                                 return ret;
14791                         }
14792                 } else {
14793                         tdls_auto_mode = true;
14794                 }
14795                 break;
14796         case NL80211_TDLS_TEARDOWN:
14797                 info.mode = TDLS_MANUAL_EP_DELETE;
14798                 break;
14799         default:
14800                 WL_ERR(("Unsupported operation : %d\n", oper));
14801                 goto out;
14802         }
14803         /* turn on TDLS */
14804         ret = dhd_tdls_enable(dev, true, tdls_auto_mode, NULL);
14805         if (ret < 0) {
14806                 return ret;
14807         }
14808         if (info.mode) {
14809                 ret = wldev_iovar_setbuf(dev, "tdls_endpoint", &info, sizeof(info),
14810                         cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
14811                 if (ret) {
14812                         WL_ERR(("tdls_endpoint error %d\n", ret));
14813                 }
14814         }
14815 out:
14816 #endif /* WLTDLS */
14817         return ret;
14818 }
14819 #endif 
14820
14821 s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *ndev, char *buf, int len,
14822         enum wl_management_type type)
14823 {
14824         struct bcm_cfg80211 *cfg;
14825         s32 ret = 0;
14826         struct ether_addr primary_mac;
14827         s32 bssidx = 0;
14828         s32 pktflag = 0;
14829         cfg = g_bcm_cfg;
14830
14831         if (wl_get_drv_status(cfg, AP_CREATING, ndev)) {
14832                 /* Vendor IEs should be set to FW
14833                  * after SoftAP interface is brought up
14834                  */
14835                 WL_DBG(("Skipping set IE since AP is not up \n"));
14836                 goto exit;
14837         } else  if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
14838                 /* Either stand alone AP case or P2P discovery */
14839                 if (wl_get_drv_status(cfg, AP_CREATED, ndev)) {
14840                         /* Stand alone AP case on primary interface */
14841                         WL_DBG(("Apply IEs for Primary AP Interface \n"));
14842                         bssidx = 0;
14843                 } else {
14844                         /* P2P Discovery case (p2p listen) */
14845                         if (!cfg->p2p->on) {
14846                                 /* Turn on Discovery interface */
14847                                 get_primary_mac(cfg, &primary_mac);
14848                                 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
14849                                 p2p_on(cfg) = true;
14850                                 ret = wl_cfgp2p_enable_discovery(cfg, ndev, NULL, 0);
14851                                 if (unlikely(ret)) {
14852                                         WL_ERR(("Enable discovery failed \n"));
14853                                         goto exit;
14854                                 }
14855                         }
14856                         WL_DBG(("Apply IEs for P2P Discovery Iface \n"));
14857                         ndev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
14858                         bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
14859                 }
14860         } else {
14861                 /* Virtual AP/ P2P Group Interface */
14862                 WL_DBG(("Apply IEs for iface:%s\n", ndev->name));
14863                 bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
14864         }
14865
14866         if (ndev != NULL) {
14867                 switch (type) {
14868                         case WL_BEACON:
14869                                 pktflag = VNDR_IE_BEACON_FLAG;
14870                                 break;
14871                         case WL_PROBE_RESP:
14872                                 pktflag = VNDR_IE_PRBRSP_FLAG;
14873                                 break;
14874                         case WL_ASSOC_RESP:
14875                                 pktflag = VNDR_IE_ASSOCRSP_FLAG;
14876                                 break;
14877                 }
14878                 if (pktflag) {
14879                         ret = wl_cfg80211_set_mgmt_vndr_ies(cfg,
14880                                 ndev_to_cfgdev(ndev), bssidx, pktflag, buf, len);
14881                 }
14882         }
14883 exit:
14884         return ret;
14885 }
14886
14887 #ifdef WL_SUPPORT_AUTO_CHANNEL
14888 static s32
14889 wl_cfg80211_set_auto_channel_scan_state(struct net_device *ndev)
14890 {
14891         u32 val = 0;
14892         s32 ret = BCME_ERROR;
14893         struct bcm_cfg80211 *cfg = g_bcm_cfg;
14894         struct wiphy *wiphy;
14895         /* Disable mpc, to avoid automatic interface down. */
14896         val = 0;
14897
14898         wiphy = bcmcfg_to_wiphy(cfg);
14899         if (wl_check_dongle_idle(wiphy) != TRUE) {
14900                 WL_ERR(("FW is busy to add interface"));
14901                 return ret;
14902         }
14903         ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
14904                 sizeof(val), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
14905                 &cfg->ioctl_buf_sync);
14906         if (ret < 0) {
14907                 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
14908                 goto done;
14909         }
14910
14911         /* Set interface up, explicitly. */
14912         val = 1;
14913
14914         ret = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
14915         if (ret < 0) {
14916                 WL_ERR(("set interface up failed, error = %d\n", ret));
14917                 goto done;
14918         }
14919
14920         /* Stop all scan explicitly, till auto channel selection complete. */
14921         wl_set_drv_status(cfg, SCANNING, ndev);
14922         if (cfg->escan_info.ndev == NULL) {
14923                 ret = BCME_OK;
14924                 goto done;
14925         }
14926         ret = wl_notify_escan_complete(cfg, ndev, true, true);
14927         if (ret < 0) {
14928                 WL_ERR(("set scan abort failed, error = %d\n", ret));
14929                 goto done;
14930         }
14931
14932 done:
14933         return ret;
14934 }
14935
14936 static bool
14937 wl_cfg80211_valid_channel_p2p(int channel)
14938 {
14939         bool valid = false;
14940
14941         /* channel 1 to 14 */
14942         if ((channel >= 1) && (channel <= 14)) {
14943                 valid = true;
14944         }
14945         /* channel 36 to 48 */
14946         else if ((channel >= 36) && (channel <= 48)) {
14947                 valid = true;
14948         }
14949         /* channel 149 to 161 */
14950         else if ((channel >= 149) && (channel <= 161)) {
14951                 valid = true;
14952         }
14953         else {
14954                 valid = false;
14955                 WL_INFORM(("invalid P2P chanspec, channel = %d\n", channel));
14956         }
14957
14958         return valid;
14959 }
14960
14961 s32
14962 wl_cfg80211_get_chanspecs_2g(struct net_device *ndev, void *buf, s32 buflen)
14963 {
14964         s32 ret = BCME_ERROR;
14965         struct bcm_cfg80211 *cfg = NULL;
14966         wl_uint32_list_t *list = NULL;
14967         chanspec_t chanspec = 0;
14968
14969         memset(buf, 0, buflen);
14970
14971         cfg = g_bcm_cfg;
14972         list = (wl_uint32_list_t *)buf;
14973         list->count = htod32(WL_NUMCHANSPECS);
14974
14975         /* Restrict channels to 2.4GHz, 20MHz BW, no SB. */
14976         chanspec |= (WL_CHANSPEC_BAND_2G | WL_CHANSPEC_BW_20 |
14977                 WL_CHANSPEC_CTL_SB_NONE);
14978         chanspec = wl_chspec_host_to_driver(chanspec);
14979
14980         ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
14981                 sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
14982         if (ret < 0) {
14983                 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
14984         }
14985
14986         return ret;
14987 }
14988
14989 s32
14990 wl_cfg80211_get_chanspecs_5g(struct net_device *ndev, void *buf, s32 buflen)
14991 {
14992         u32 channel = 0;
14993         s32 ret = BCME_ERROR;
14994         s32 i = 0;
14995         s32 j = 0;
14996         struct bcm_cfg80211 *cfg = NULL;
14997         wl_uint32_list_t *list = NULL;
14998         chanspec_t chanspec = 0;
14999
15000         memset(buf, 0, buflen);
15001
15002         cfg = g_bcm_cfg;
15003         list = (wl_uint32_list_t *)buf;
15004         list->count = htod32(WL_NUMCHANSPECS);
15005
15006         /* Restrict channels to 5GHz, 20MHz BW, no SB. */
15007         chanspec |= (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_20 |
15008                 WL_CHANSPEC_CTL_SB_NONE);
15009         chanspec = wl_chspec_host_to_driver(chanspec);
15010
15011         ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
15012                 sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
15013         if (ret < 0) {
15014                 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
15015                 goto done;
15016         }
15017
15018         /* Skip DFS and inavlid P2P channel. */
15019         for (i = 0, j = 0; i < dtoh32(list->count); i++) {
15020                 chanspec = (chanspec_t) dtoh32(list->element[i]);
15021                 channel = CHSPEC_CHANNEL(chanspec);
15022
15023                 ret = wldev_iovar_getint(ndev, "per_chan_info", &channel);
15024                 if (ret < 0) {
15025                         WL_ERR(("get 'per_chan_info' failed, error = %d\n", ret));
15026                         goto done;
15027                 }
15028
15029                 if (CHANNEL_IS_RADAR(channel) ||
15030                         !(wl_cfg80211_valid_channel_p2p(CHSPEC_CHANNEL(chanspec)))) {
15031                         continue;
15032                 } else {
15033                         list->element[j] = list->element[i];
15034                 }
15035
15036                 j++;
15037         }
15038
15039         list->count = j;
15040
15041 done:
15042         return ret;
15043 }
15044
15045 static s32
15046 wl_cfg80211_get_best_channel(struct net_device *ndev, void *buf, int buflen,
15047         int *channel)
15048 {
15049         s32 ret = BCME_ERROR;
15050         int chosen = 0;
15051         int retry = 0;
15052         uint chip;
15053
15054         /* Start auto channel selection scan. */
15055         ret = wldev_ioctl(ndev, WLC_START_CHANNEL_SEL, buf, buflen, true);
15056         if (ret < 0) {
15057                 WL_ERR(("can't start auto channel scan, error = %d\n", ret));
15058                 *channel = 0;
15059                 goto done;
15060         }
15061
15062         /* Wait for auto channel selection, worst case possible delay is 5250ms. */
15063         retry = CHAN_SEL_RETRY_COUNT;
15064
15065         while (retry--) {
15066                 OSL_SLEEP(CHAN_SEL_IOCTL_DELAY);
15067
15068                 ret = wldev_ioctl(ndev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen),
15069                         false);
15070                 if ((ret == 0) && (dtoh32(chosen) != 0)) {
15071                         chip = dhd_conf_get_chip(dhd_get_pub(ndev));
15072                         if (chip != BCM43362_CHIP_ID && chip != BCM4330_CHIP_ID) {
15073                                 u32 chanspec = 0;
15074                                 int ctl_chan;
15075                                 chanspec = wl_chspec_driver_to_host(chosen);
15076                                 printf("selected chanspec = 0x%x\n", chanspec);
15077                                 ctl_chan = wf_chspec_ctlchan(chanspec);
15078                                 printf("selected ctl_chan = 0x%x\n", ctl_chan);
15079                                 *channel = (u16)(ctl_chan & 0x00FF);
15080                         } else
15081                                 *channel = (u16)(chosen & 0x00FF);
15082                         WL_INFORM(("selected channel = %d\n", *channel));
15083                         break;
15084                 }
15085                 WL_INFORM(("attempt = %d, ret = %d, chosen = %d\n",
15086                         (CHAN_SEL_RETRY_COUNT - retry), ret, dtoh32(chosen)));
15087         }
15088
15089         if (retry <= 0) {
15090                 WL_ERR(("failure, auto channel selection timed out\n"));
15091                 *channel = 0;
15092                 ret = BCME_ERROR;
15093         }
15094
15095 done:
15096         return ret;
15097 }
15098
15099 static s32
15100 wl_cfg80211_restore_auto_channel_scan_state(struct net_device *ndev)
15101 {
15102         u32 val = 0;
15103         s32 ret = BCME_ERROR;
15104         struct bcm_cfg80211 *cfg = g_bcm_cfg;
15105
15106         /* Clear scan stop driver status. */
15107         wl_clr_drv_status(cfg, SCANNING, ndev);
15108
15109         /* Enable mpc back to 1, irrespective of initial state. */
15110         val = 1;
15111
15112         ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
15113                 sizeof(val), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
15114                 &cfg->ioctl_buf_sync);
15115         if (ret < 0) {
15116                 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
15117         }
15118
15119         return ret;
15120 }
15121
15122 s32
15123 wl_cfg80211_get_best_channels(struct net_device *dev, char* cmd, int total_len)
15124 {
15125         int channel = 0, band, band_cur;
15126         s32 ret = BCME_ERROR;
15127         u8 *buf = NULL;
15128         char *pos = cmd;
15129         struct bcm_cfg80211 *cfg = NULL;
15130         struct net_device *ndev = NULL;
15131
15132         memset(cmd, 0, total_len);
15133
15134         buf = kmalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
15135         if (buf == NULL) {
15136                 WL_ERR(("failed to allocate chanspec buffer\n"));
15137                 return -ENOMEM;
15138         }
15139
15140         /*
15141          * Always use primary interface, irrespective of interface on which
15142          * command came.
15143          */
15144         cfg = g_bcm_cfg;
15145         ndev = bcmcfg_to_prmry_ndev(cfg);
15146
15147         /*
15148          * Make sure that FW and driver are in right state to do auto channel
15149          * selection scan.
15150          */
15151         ret = wl_cfg80211_set_auto_channel_scan_state(ndev);
15152         if (ret < 0) {
15153                 WL_ERR(("can't set auto channel scan state, error = %d\n", ret));
15154                 goto done;
15155         }
15156
15157         /* Best channel selection in 2.4GHz band. */
15158         ret = wl_cfg80211_get_chanspecs_2g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
15159         if (ret < 0) {
15160                 WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
15161                 goto done;
15162         }
15163
15164         ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
15165                 &channel);
15166         if (ret < 0) {
15167                 WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
15168                 goto done;
15169         }
15170
15171         if (CHANNEL_IS_2G(channel)) {
15172                 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
15173         } else {
15174                 WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel));
15175                 channel = 0;
15176         }
15177
15178         pos += snprintf(pos, total_len, "%04d ", channel);
15179
15180         // terence 20140120: fix for some chipsets only return 2.4GHz channel (4330b2/43341b0/4339a0)
15181         ret = wldev_ioctl(dev, WLC_GET_BAND, &band_cur, sizeof(band_cur), false);
15182         band = band_cur==WLC_BAND_2G ? band_cur : WLC_BAND_5G;
15183         ret = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), true);
15184         if (ret < 0)
15185                 WL_ERR(("WLC_SET_BAND error %d\n", ret));
15186
15187         /* Best channel selection in 5GHz band. */
15188         ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
15189         if (ret < 0) {
15190                 WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret));
15191                 goto done;
15192         }
15193
15194         ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
15195                 &channel);
15196         if (ret < 0) {
15197                 WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret));
15198                 goto done;
15199         }
15200
15201         if (CHANNEL_IS_5G(channel)) {
15202                 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
15203         } else {
15204                 WL_ERR(("invalid 5GHz channel, channel = %d\n", channel));
15205                 channel = 0;
15206         }
15207
15208         ret = wldev_ioctl(dev, WLC_SET_BAND, &band_cur, sizeof(band_cur), true);
15209         if (ret < 0)
15210                 WL_ERR(("WLC_SET_BAND error %d\n", ret));
15211
15212         pos += snprintf(pos, total_len, "%04d ", channel);
15213
15214         /* Set overall best channel same as 5GHz best channel. */
15215         pos += snprintf(pos, total_len, "%04d ", channel);
15216
15217 done:
15218         if (NULL != buf) {
15219                 kfree(buf);
15220         }
15221
15222         /* Restore FW and driver back to normal state. */
15223         ret = wl_cfg80211_restore_auto_channel_scan_state(ndev);
15224         if (ret < 0) {
15225                 WL_ERR(("can't restore auto channel scan state, error = %d\n", ret));
15226         }
15227
15228         printf("%s: channel %s\n", __FUNCTION__, cmd);
15229
15230         return (pos - cmd);
15231 }
15232 #endif /* WL_SUPPORT_AUTO_CHANNEL */
15233
15234 static const struct rfkill_ops wl_rfkill_ops = {
15235         .set_block = wl_rfkill_set
15236 };
15237
15238 static int wl_rfkill_set(void *data, bool blocked)
15239 {
15240         struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
15241
15242         WL_DBG(("Enter \n"));
15243         WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked"));
15244
15245         if (!cfg)
15246                 return -EINVAL;
15247
15248         cfg->rf_blocked = blocked;
15249
15250         return 0;
15251 }
15252
15253 static int wl_setup_rfkill(struct bcm_cfg80211 *cfg, bool setup)
15254 {
15255         s32 err = 0;
15256
15257         WL_DBG(("Enter \n"));
15258         if (!cfg)
15259                 return -EINVAL;
15260         if (setup) {
15261                 cfg->rfkill = rfkill_alloc("brcmfmac-wifi",
15262                         wl_cfg80211_get_parent_dev(),
15263                         RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)cfg);
15264
15265                 if (!cfg->rfkill) {
15266                         err = -ENOMEM;
15267                         goto err_out;
15268                 }
15269
15270                 err = rfkill_register(cfg->rfkill);
15271
15272                 if (err)
15273                         rfkill_destroy(cfg->rfkill);
15274         } else {
15275                 if (!cfg->rfkill) {
15276                         err = -ENOMEM;
15277                         goto err_out;
15278                 }
15279
15280                 rfkill_unregister(cfg->rfkill);
15281                 rfkill_destroy(cfg->rfkill);
15282         }
15283
15284 err_out:
15285         return err;
15286 }
15287
15288 #ifdef DEBUGFS_CFG80211
15289 /**
15290 * Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level
15291 * to turn on SCAN and DBG log.
15292 * To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level
15293 * To see current setting of debug level,
15294 * cat /sys/kernel/debug/dhd/debug_level
15295 */
15296 static ssize_t
15297 wl_debuglevel_write(struct file *file, const char __user *userbuf,
15298         size_t count, loff_t *ppos)
15299 {
15300         char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)], sublog[S_SUBLOGLEVEL];
15301         char *params, *token, *colon;
15302         uint i, tokens, log_on = 0;
15303         memset(tbuf, 0, sizeof(tbuf));
15304         memset(sublog, 0, sizeof(sublog));
15305         if (copy_from_user(&tbuf, userbuf, min_t(size_t, (sizeof(tbuf) - 1), count)))
15306                 return -EFAULT;
15307
15308         params = &tbuf[0];
15309         colon = strchr(params, '\n');
15310         if (colon != NULL)
15311                 *colon = '\0';
15312         while ((token = strsep(&params, " ")) != NULL) {
15313                 memset(sublog, 0, sizeof(sublog));
15314                 if (token == NULL || !*token)
15315                         break;
15316                 if (*token == '\0')
15317                         continue;
15318                 colon = strchr(token, ':');
15319                 if (colon != NULL) {
15320                         *colon = ' ';
15321                 }
15322                 tokens = sscanf(token, "%s %u", sublog, &log_on);
15323                 if (colon != NULL)
15324                         *colon = ':';
15325
15326                 if (tokens == 2) {
15327                                 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
15328                                         if (!strncmp(sublog, sublogname_map[i].sublogname,
15329                                                 strlen(sublogname_map[i].sublogname))) {
15330                                                 if (log_on)
15331                                                         wl_dbg_level |=
15332                                                         (sublogname_map[i].log_level);
15333                                                 else
15334                                                         wl_dbg_level &=
15335                                                         ~(sublogname_map[i].log_level);
15336                                         }
15337                                 }
15338                 } else
15339                         WL_ERR(("%s: can't parse '%s' as a "
15340                                "SUBMODULE:LEVEL (%d tokens)\n",
15341                                tbuf, token, tokens));
15342
15343
15344         }
15345         return count;
15346 }
15347
15348 static ssize_t
15349 wl_debuglevel_read(struct file *file, char __user *user_buf,
15350         size_t count, loff_t *ppos)
15351 {
15352         char *param;
15353         char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)];
15354         uint i;
15355         memset(tbuf, 0, sizeof(tbuf));
15356         param = &tbuf[0];
15357         for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
15358                 param += snprintf(param, sizeof(tbuf) - 1, "%s:%d ",
15359                         sublogname_map[i].sublogname,
15360                         (wl_dbg_level & sublogname_map[i].log_level) ? 1 : 0);
15361         }
15362         *param = '\n';
15363         return simple_read_from_buffer(user_buf, count, ppos, tbuf, strlen(&tbuf[0]));
15364
15365 }
15366 static const struct file_operations fops_debuglevel = {
15367         .open = NULL,
15368         .write = wl_debuglevel_write,
15369         .read = wl_debuglevel_read,
15370         .owner = THIS_MODULE,
15371         .llseek = NULL,
15372 };
15373
15374 static s32 wl_setup_debugfs(struct bcm_cfg80211 *cfg)
15375 {
15376         s32 err = 0;
15377         struct dentry *_dentry;
15378         if (!cfg)
15379                 return -EINVAL;
15380         cfg->debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
15381         if (!cfg->debugfs || IS_ERR(cfg->debugfs)) {
15382                 if (cfg->debugfs == ERR_PTR(-ENODEV))
15383                         WL_ERR(("Debugfs is not enabled on this kernel\n"));
15384                 else
15385                         WL_ERR(("Can not create debugfs directory\n"));
15386                 cfg->debugfs = NULL;
15387                 goto exit;
15388
15389         }
15390         _dentry = debugfs_create_file("debug_level", S_IRUSR | S_IWUSR,
15391                 cfg->debugfs, cfg, &fops_debuglevel);
15392         if (!_dentry || IS_ERR(_dentry)) {
15393                 WL_ERR(("failed to create debug_level debug file\n"));
15394                 wl_free_debugfs(cfg);
15395         }
15396 exit:
15397         return err;
15398 }
15399 static s32 wl_free_debugfs(struct bcm_cfg80211 *cfg)
15400 {
15401         if (!cfg)
15402                 return -EINVAL;
15403         if (cfg->debugfs)
15404                 debugfs_remove_recursive(cfg->debugfs);
15405         cfg->debugfs = NULL;
15406         return 0;
15407 }
15408 #endif /* DEBUGFS_CFG80211 */
15409
15410 struct device *wl_cfg80211_get_parent_dev(void)
15411 {
15412         return cfg80211_parent_dev;
15413 }
15414
15415 void wl_cfg80211_set_parent_dev(void *dev)
15416 {
15417         cfg80211_parent_dev = dev;
15418 }
15419
15420 static void wl_cfg80211_clear_parent_dev(void)
15421 {
15422         cfg80211_parent_dev = NULL;
15423 }
15424
15425 void get_primary_mac(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
15426 {
15427         wldev_iovar_getbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg), "cur_etheraddr", NULL,
15428                 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
15429         memcpy(mac->octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
15430 }
15431 static bool check_dev_role_integrity(struct bcm_cfg80211 *cfg, u32 dev_role)
15432 {
15433         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
15434         if (((dev_role == NL80211_IFTYPE_AP) &&
15435                 !(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) ||
15436                 ((dev_role == NL80211_IFTYPE_P2P_GO) &&
15437                 !(dhd->op_mode & DHD_FLAG_P2P_GO_MODE)))
15438         {
15439                 WL_ERR(("device role select failed role:%d op_mode:%d \n", dev_role, dhd->op_mode));
15440                 return false;
15441         }
15442         return true;
15443 }
15444
15445 int wl_cfg80211_do_driver_init(struct net_device *net)
15446 {
15447         struct bcm_cfg80211 *cfg = *(struct bcm_cfg80211 **)netdev_priv(net);
15448
15449         if (!cfg || !cfg->wdev)
15450                 return -EINVAL;
15451
15452         if (dhd_do_driver_init(cfg->wdev->netdev) < 0)
15453                 return -1;
15454
15455         return 0;
15456 }
15457
15458 void wl_cfg80211_enable_trace(u32 level)
15459 {
15460         wl_dbg_level = level;
15461         printf("%s: wl_dbg_level = 0x%x\n", __FUNCTION__, wl_dbg_level);
15462 }
15463
15464 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
15465         2, 0))
15466 static s32
15467 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
15468         bcm_struct_cfgdev *cfgdev, u64 cookie)
15469 {
15470         /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION
15471          * is passed with CMD_FRAME. This callback is supposed to cancel
15472          * the OFFCHANNEL Wait. Since we are already taking care of that
15473          *  with the tx_mgmt logic, do nothing here.
15474          */
15475
15476         return 0;
15477 }
15478 #endif /* WL_SUPPORT_BACKPORTED_PATCHES || KERNEL >= 3.2.0 */
15479
15480 #ifdef WL11U
15481 bcm_tlv_t *
15482 wl_cfg80211_find_interworking_ie(u8 *parse, u32 len)
15483 {
15484         bcm_tlv_t *ie;
15485
15486         while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_INTERWORKING_ID))) {
15487                         return (bcm_tlv_t *)ie;
15488         }
15489         return NULL;
15490 }
15491
15492
15493 static s32
15494 wl_cfg80211_add_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx, s32 pktflag,
15495             uint8 ie_id, uint8 *data, uint8 data_len)
15496 {
15497         s32 err = BCME_OK;
15498         s32 buf_len;
15499         s32 iecount;
15500         ie_setbuf_t *ie_setbuf;
15501
15502         if (ie_id != DOT11_MNG_INTERWORKING_ID)
15503                 return BCME_UNSUPPORTED;
15504
15505         /* Validate the pktflag parameter */
15506         if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
15507                     VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
15508                     VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG|
15509                     VNDR_IE_CUSTOM_FLAG))) {
15510                 WL_ERR(("cfg80211 Add IE: Invalid packet flag 0x%x\n", pktflag));
15511                 return -1;
15512         }
15513
15514         /* use VNDR_IE_CUSTOM_FLAG flags for none vendor IE . currently fixed value */
15515         pktflag = htod32(pktflag);
15516
15517         buf_len = sizeof(ie_setbuf_t) + data_len - 1;
15518         ie_setbuf = (ie_setbuf_t *) kzalloc(buf_len, GFP_KERNEL);
15519
15520         if (!ie_setbuf) {
15521                 WL_ERR(("Error allocating buffer for IE\n"));
15522                 return -ENOMEM;
15523         }
15524
15525         if (cfg->iw_ie_len == data_len && !memcmp(cfg->iw_ie, data, data_len)) {
15526                 WL_ERR(("Previous IW IE is equals to current IE\n"));
15527                 err = BCME_OK;
15528                 goto exit;
15529         }
15530
15531         strncpy(ie_setbuf->cmd, "add", VNDR_IE_CMD_LEN - 1);
15532         ie_setbuf->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
15533
15534         /* Buffer contains only 1 IE */
15535         iecount = htod32(1);
15536         memcpy((void *)&ie_setbuf->ie_buffer.iecount, &iecount, sizeof(int));
15537         memcpy((void *)&ie_setbuf->ie_buffer.ie_list[0].pktflag, &pktflag, sizeof(uint32));
15538
15539         /* Now, add the IE to the buffer */
15540         ie_setbuf->ie_buffer.ie_list[0].ie_data.id = ie_id;
15541
15542         /* if already set with previous values, delete it first */
15543         if (cfg->iw_ie_len != 0) {
15544                 WL_DBG(("Different IW_IE was already set. clear first\n"));
15545
15546                 ie_setbuf->ie_buffer.ie_list[0].ie_data.len = 0;
15547
15548                 err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
15549                         cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
15550
15551                 if (err != BCME_OK)
15552                         goto exit;
15553         }
15554
15555         ie_setbuf->ie_buffer.ie_list[0].ie_data.len = data_len;
15556         memcpy((uchar *)&ie_setbuf->ie_buffer.ie_list[0].ie_data.data[0], data, data_len);
15557
15558         err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
15559                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
15560
15561         if (err == BCME_OK) {
15562                 memcpy(cfg->iw_ie, data, data_len);
15563                 cfg->iw_ie_len = data_len;
15564                 cfg->wl11u = TRUE;
15565
15566                 err = wldev_iovar_setint_bsscfg(ndev, "grat_arp", 1, bssidx);
15567         }
15568
15569 exit:
15570         if (ie_setbuf)
15571                 kfree(ie_setbuf);
15572         return err;
15573 }
15574 #endif /* WL11U */
15575
15576 s32
15577 wl_cfg80211_dfs_ap_move(struct net_device *ndev, char *data, char *command, int total_len)
15578 {
15579         struct bcm_cfg80211 *cfg = g_bcm_cfg;
15580         char ioctl_buf[50];
15581         int err = 0;
15582         uint32 val = 0;
15583         chanspec_t chanspec = 0;
15584         int abort;
15585         int bytes_written = 0;
15586         wl_dfs_ap_move_status_t *status;
15587         char chanbuf[CHANSPEC_STR_LEN];
15588         const char *dfs_state_str[DFS_SCAN_S_MAX] = {
15589                 "Radar Free On Channel",
15590                 "Radar Found On Channel",
15591                 "Radar Scan In Progress",
15592                 "Radar Scan Aborted",
15593                 "RSDB Mode switch in Progress For Scan"
15594         };
15595         if (ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
15596                 bytes_written = snprintf(command, total_len, "AP is not UP\n");
15597                 return bytes_written;
15598         }
15599         if (!*data) {
15600                 if ((err = wldev_iovar_getbuf(ndev, "dfs_ap_move", NULL, 0,
15601                                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN,  &cfg->ioctl_buf_sync))) {
15602                         WL_ERR(("setting dfs_ap_move failed with err=%d \n", err));
15603                         return err;
15604                 }
15605                 status = (wl_dfs_ap_move_status_t *)cfg->ioctl_buf;
15606
15607                 if (status->version != WL_DFS_AP_MOVE_VERSION) {
15608                         err = BCME_UNSUPPORTED;
15609                         WL_ERR(("err=%d version=%d\n", err, status->version));
15610                         return err;
15611                 }
15612
15613                 if (status->move_status != (int8) DFS_SCAN_S_IDLE) {
15614                         chanspec = wl_chspec_driver_to_host(status->chanspec);
15615                         if (chanspec != 0 && chanspec != INVCHANSPEC) {
15616                                 wf_chspec_ntoa(chanspec, chanbuf);
15617                                 bytes_written = snprintf(command, total_len,
15618                                         "AP Target Chanspec %s (0x%x)\n", chanbuf, chanspec);
15619                         }
15620                         bytes_written += snprintf(command + bytes_written, total_len,
15621                                          "%s\n", dfs_state_str[status->move_status]);
15622                         return bytes_written;
15623                 } else {
15624                         bytes_written = snprintf(command, total_len, "dfs AP move in IDLE state\n");
15625                         return bytes_written;
15626                 }
15627
15628         }
15629
15630         abort = bcm_atoi(data);
15631         if (abort == -1) {
15632                 if ((err = wldev_iovar_setbuf(ndev, "dfs_ap_move", &abort,
15633                                 sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
15634                         WL_ERR(("seting dfs_ap_move failed with err %d\n", err));
15635                         return err;
15636                 }
15637         } else {
15638                 chanspec = wf_chspec_aton(data);
15639                 if (chanspec != 0) {
15640                         val = wl_chspec_host_to_driver(chanspec);
15641                         if (val != INVCHANSPEC) {
15642                                 if ((err = wldev_iovar_setbuf(ndev, "dfs_ap_move", &val,
15643                                         sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
15644                                         WL_ERR(("seting dfs_ap_move failed with err %d\n", err));
15645                                         return err;
15646                                 }
15647                                 WL_DBG((" set dfs_ap_move successfull"));
15648                         } else {
15649                                 err = BCME_USAGE_ERROR;
15650                         }
15651                 }
15652         }
15653         return err;
15654 }
15655
15656 s32
15657 wl_cfg80211_wbtext_config(struct net_device *ndev, char *data, char *command, int total_len)
15658 {
15659         uint i = 0;
15660         struct bcm_cfg80211 *cfg = g_bcm_cfg;
15661         wl_roam_prof_band_t *rp;
15662         int err = -EINVAL, bytes_written = 0;
15663         size_t len = strlen(data);
15664         int rp_len = 0;
15665         data[len] = '\0';
15666         rp = (wl_roam_prof_band_t *) kzalloc(sizeof(*rp)
15667                         * WL_MAX_ROAM_PROF_BRACKETS, GFP_KERNEL);
15668         if (unlikely(!rp)) {
15669                 WL_ERR(("%s: failed to allocate memory\n", __func__));
15670                 err =  -ENOMEM;
15671                 goto exit;
15672         }
15673
15674         rp->ver = WL_MAX_ROAM_PROF_VER;
15675         if (*data && (!strncmp(data, "b", 1))) {
15676                 rp->band = WLC_BAND_2G;
15677         } else if (*data && (!strncmp(data, "a", 1))) {
15678                 rp->band = WLC_BAND_5G;
15679         } else {
15680                 err = snprintf(command, total_len, "Missing band\n");
15681                 goto exit;
15682         }
15683         data++;
15684         rp->len = 0;
15685         /* Getting roam profile  from fw */
15686         if ((err = wldev_iovar_getbuf(ndev, "roam_prof", rp, sizeof(*rp),
15687                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN,  &cfg->ioctl_buf_sync))) {
15688                 WL_ERR(("Getting roam_profile failed with err=%d \n", err));
15689                 goto exit;
15690         }
15691         memcpy(rp, cfg->ioctl_buf, sizeof(*rp) * WL_MAX_ROAM_PROF_BRACKETS);
15692         /* roam_prof version get */
15693         if (rp->ver != WL_MAX_ROAM_PROF_VER) {
15694                 WL_ERR(("bad version (=%d) in return data\n", rp->ver));
15695                 err = -EINVAL;
15696                 goto exit;
15697         }
15698         if ((rp->len % sizeof(wl_roam_prof_t)) != 0) {
15699                 WL_ERR(("bad length (=%d) in return data\n", rp->len));
15700                 err = -EINVAL;
15701                 goto exit;
15702         }
15703
15704         if (!*data) {
15705                 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
15706                         /* printing contents of roam profile data from fw and exits
15707                          * if code hits any of one of the below condtion. If remaining
15708                          * length of buffer is less than roam profile size or
15709                          * if there is no valid entry.
15710                          */
15711                         if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
15712                                 (rp->roam_prof[i].fullscan_period == 0)) {
15713                                 break;
15714                         }
15715                         bytes_written += snprintf(command+bytes_written,
15716                                         total_len, "RSSI[%d,%d] CU(trigger:%d%%: duration:%ds)\n",
15717                                         rp->roam_prof[i].roam_trigger, rp->roam_prof[i].rssi_lower,
15718                                         rp->roam_prof[i].channel_usage,
15719                                         rp->roam_prof[i].cu_avg_calc_dur);
15720                 }
15721                 err = bytes_written;
15722                 goto exit;
15723         } else {
15724                 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
15725                         /* reading contents of roam profile data from fw and exits
15726                          * if code hits any of one of the below condtion, If remaining
15727                          * length of buffer is less than roam profile size or if there
15728                          * is no valid entry.
15729                          */
15730                         if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
15731                                 (rp->roam_prof[i].fullscan_period == 0)) {
15732                                 break;
15733                         }
15734                 }
15735                 /* Do not set roam_prof from upper layer if fw doesn't have 2 rows */
15736                 if (i != 2) {
15737                         WL_ERR(("FW must have 2 rows to fill roam_prof\n"));
15738                         err = -EINVAL;
15739                         goto exit;
15740                 }
15741                 /* setting roam profile to fw */
15742                 data++;
15743                 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
15744                         rp->roam_prof[i].roam_trigger = simple_strtol(data, &data, 10);
15745                         data++;
15746                         rp->roam_prof[i].rssi_lower = simple_strtol(data, &data, 10);
15747                         data++;
15748                         rp->roam_prof[i].channel_usage = simple_strtol(data, &data, 10);
15749                         data++;
15750                         rp->roam_prof[i].cu_avg_calc_dur = simple_strtol(data, &data, 10);
15751
15752                         rp_len += sizeof(wl_roam_prof_t);
15753                         if (*data == '\0') {
15754                                 break;
15755                         }
15756                         data++;
15757                 }
15758                 if (i != 1) {
15759                         WL_ERR(("Only two roam_prof rows supported.\n"));
15760                         err = -EINVAL;
15761                         goto exit;
15762                 }
15763                 rp->len = rp_len;
15764                 if ((err = wldev_iovar_setbuf(ndev, "roam_prof", rp,
15765                                 sizeof(*rp), cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL)) < 0) {
15766                         WL_ERR(("seting roam_profile failed with err %d\n", err));
15767                 }
15768         }
15769 exit:
15770         if (rp) {
15771                 kfree(rp);
15772         }
15773         return err;
15774 }
15775
15776 int wl_cfg80211_wbtext_weight_config(struct net_device *ndev, char *data,
15777                 char *command, int total_len)
15778 {
15779         struct bcm_cfg80211 *cfg = g_bcm_cfg;
15780         int bytes_written = 0, err = -EINVAL, argc = 0;
15781         char rssi[5], band[5], weight[5];
15782         char *endptr = NULL;
15783         wnm_bss_select_weight_cfg_t *bwcfg;
15784
15785         bwcfg = kzalloc(sizeof(*bwcfg), GFP_KERNEL);
15786         if (unlikely(!bwcfg)) {
15787                 WL_ERR(("%s: failed to allocate memory\n", __func__));
15788                 err = -ENOMEM;
15789                 goto exit;
15790         }
15791         bwcfg->version =  WNM_BSSLOAD_MONITOR_VERSION;
15792         bwcfg->type = 0;
15793         bwcfg->weight = 0;
15794
15795         argc = sscanf(data, "%s %s %s", rssi, band, weight);
15796
15797         if (!strcasecmp(rssi, "rssi"))
15798                 bwcfg->type = WNM_BSS_SELECT_TYPE_RSSI;
15799         else if (!strcasecmp(rssi, "cu"))
15800                 bwcfg->type = WNM_BSS_SELECT_TYPE_CU;
15801         else {
15802                 /* Usage DRIVER WBTEXT_WEIGHT_CONFIG <rssi/cu> <band> <weight> */
15803                 WL_ERR(("%s: Command usage error\n", __func__));
15804                 goto exit;
15805         }
15806
15807         if (!strcasecmp(band, "a"))
15808                 bwcfg->band = WLC_BAND_5G;
15809         else if (!strcasecmp(band, "b"))
15810                 bwcfg->band = WLC_BAND_2G;
15811         else if (!strcasecmp(band, "all"))
15812                 bwcfg->band = WLC_BAND_ALL;
15813         else {
15814                 WL_ERR(("%s: Command usage error\n", __func__));
15815                 goto exit;
15816         }
15817
15818         if (argc == 2) {
15819                 /* If there is no data after band, getting wnm_bss_select_weight from fw */
15820                 if (bwcfg->band == WLC_BAND_ALL) {
15821                         WL_ERR(("band option \"all\" is for set only, not get\n"));
15822                         goto exit;
15823                 }
15824                 if ((err = wldev_iovar_getbuf(ndev, "wnm_bss_select_weight", bwcfg,
15825                                 sizeof(*bwcfg),
15826                                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN,  &cfg->ioctl_buf_sync))) {
15827                         WL_ERR(("Getting wnm_bss_select_weight failed with err=%d \n", err));
15828                         goto exit;
15829                 }
15830                 memcpy(bwcfg, cfg->ioctl_buf, sizeof(*bwcfg));
15831                 bytes_written = snprintf(command, total_len, "%s %s weight = %d\n",
15832                         (bwcfg->type == WNM_BSS_SELECT_TYPE_RSSI) ? "RSSI" : "CU",
15833                         (bwcfg->band == WLC_BAND_2G) ? "2G" : "5G", bwcfg->weight);
15834                 err = bytes_written;
15835                 goto exit;
15836         } else {
15837                 /* if weight is non integer returns command usage error */
15838                 bwcfg->weight = simple_strtol(weight, &endptr, 0);
15839                 if (*endptr != '\0') {
15840                         WL_ERR(("%s: Command usage error", __func__));
15841                         goto exit;
15842                 }
15843                 /* setting weight for iovar wnm_bss_select_weight to fw */
15844                 if ((err = wldev_iovar_setbuf(ndev, "wnm_bss_select_weight", bwcfg,
15845                                 sizeof(*bwcfg),
15846                                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN,  &cfg->ioctl_buf_sync))) {
15847                         WL_ERR(("Getting wnm_bss_select_weight failed with err=%d\n", err));
15848                 }
15849         }
15850 exit:
15851         if (bwcfg) {
15852                 kfree(bwcfg);
15853         }
15854         return err;
15855 }
15856
15857 /* WBTEXT_TUPLE_MIN_LEN_CHECK :strlen(low)+" "+strlen(high)+" "+strlen(factor) */
15858 #define WBTEXT_TUPLE_MIN_LEN_CHECK 5
15859
15860 int wl_cfg80211_wbtext_table_config(struct net_device *ndev, char *data,
15861         char *command, int total_len)
15862 {
15863         struct bcm_cfg80211 *cfg = g_bcm_cfg;
15864         int bytes_written = 0, err = -EINVAL;
15865         char rssi[5], band[5];
15866         int btcfg_len = 0, i = 0, parsed_len = 0;
15867         wnm_bss_select_factor_cfg_t *btcfg;
15868         size_t slen = strlen(data);
15869         char *start_addr = NULL;
15870         data[slen] = '\0';
15871
15872         btcfg = kzalloc((sizeof(*btcfg) + sizeof(*btcfg) *
15873                         WL_FACTOR_TABLE_MAX_LIMIT), GFP_KERNEL);
15874         if (unlikely(!btcfg)) {
15875                 WL_ERR(("%s: failed to allocate memory\n", __func__));
15876                 err = -ENOMEM;
15877                 goto exit;
15878         }
15879
15880         btcfg->version = WNM_BSS_SELECT_FACTOR_VERSION;
15881         btcfg->band = WLC_BAND_AUTO;
15882         btcfg->type = 0;
15883         btcfg->count = 0;
15884
15885         sscanf(data, "%s %s", rssi, band);
15886
15887         if (!strcasecmp(rssi, "rssi")) {
15888                 btcfg->type = WNM_BSS_SELECT_TYPE_RSSI;
15889         }
15890         else if (!strcasecmp(rssi, "cu")) {
15891                 btcfg->type = WNM_BSS_SELECT_TYPE_CU;
15892         }
15893         else {
15894                 WL_ERR(("%s: Command usage error\n", __func__));
15895                 goto exit;
15896         }
15897
15898         if (!strcasecmp(band, "a")) {
15899                 btcfg->band = WLC_BAND_5G;
15900         }
15901         else if (!strcasecmp(band, "b")) {
15902                 btcfg->band = WLC_BAND_2G;
15903         }
15904         else if (!strcasecmp(band, "all")) {
15905                 btcfg->band = WLC_BAND_ALL;
15906         }
15907         else {
15908                 WL_ERR(("%s: Command usage, Wrong band\n", __func__));
15909                 goto exit;
15910         }
15911
15912         if ((slen - 1) == (strlen(rssi) + strlen(band))) {
15913                 /* Getting factor table using iovar 'wnm_bss_select_table' from fw */
15914                 if ((err = wldev_iovar_getbuf(ndev, "wnm_bss_select_table", btcfg,
15915                                 sizeof(*btcfg),
15916                                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN,  &cfg->ioctl_buf_sync))) {
15917                         WL_ERR(("Getting wnm_bss_select_table failed with err=%d \n", err));
15918                         goto exit;
15919                 }
15920                 memcpy(btcfg, cfg->ioctl_buf, sizeof(*btcfg));
15921                 memcpy(btcfg, cfg->ioctl_buf, (btcfg->count+1) * sizeof(*btcfg));
15922
15923                 bytes_written += snprintf(command + bytes_written, total_len,
15924                                         "No of entries in table: %d\n", btcfg->count);
15925                 bytes_written += snprintf(command + bytes_written, total_len, "%s factor table\n",
15926                                 (btcfg->type == WNM_BSS_SELECT_TYPE_RSSI) ? "RSSI" : "CU");
15927                 bytes_written += snprintf(command + bytes_written, total_len,
15928                                         "low\thigh\tfactor\n");
15929                 for (i = 0; i <= btcfg->count-1; i++) {
15930                         bytes_written += snprintf(command + bytes_written, total_len,
15931                                 "%d\t%d\t%d\n", btcfg->params[i].low, btcfg->params[i].high,
15932                                 btcfg->params[i].factor);
15933                 }
15934                 err = bytes_written;
15935                 goto exit;
15936         } else {
15937                 memset(btcfg->params, 0, sizeof(*btcfg) * WL_FACTOR_TABLE_MAX_LIMIT);
15938                 data += (strlen(rssi) + strlen(band) + 2);
15939                 start_addr = data;
15940                 slen = slen - (strlen(rssi) + strlen(band) + 2);
15941                 for (i = 0; i < WL_FACTOR_TABLE_MAX_LIMIT; i++) {
15942                         if (parsed_len + WBTEXT_TUPLE_MIN_LEN_CHECK <= slen) {
15943                                 btcfg->params[i].low = simple_strtol(data, &data, 10);
15944                                 data++;
15945                                 btcfg->params[i].high = simple_strtol(data, &data, 10);
15946                                 data++;
15947                                 btcfg->params[i].factor = simple_strtol(data, &data, 10);
15948                                 btcfg->count++;
15949                                 if (*data == '\0') {
15950                                         break;
15951                                 }
15952                                 data++;
15953                                 parsed_len = data - start_addr;
15954                         } else {
15955                                 WL_ERR(("%s:Command usage:less no of args\n", __func__));
15956                                 goto exit;
15957                         }
15958                 }
15959                 btcfg_len = sizeof(*btcfg) + ((btcfg->count) * sizeof(*btcfg));
15960                 if ((err = wldev_iovar_setbuf(ndev, "wnm_bss_select_table", btcfg, btcfg_len,
15961                                 cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL)) < 0) {
15962                         WL_ERR(("seting wnm_bss_select_table failed with err %d\n", err));
15963                         goto exit;
15964                 }
15965         }
15966 exit:
15967         if (btcfg) {
15968                 kfree(btcfg);
15969         }
15970         return err;
15971 }
15972
15973 s32
15974 wl_cfg80211_wbtext_delta_config(struct net_device *ndev, char *data, char *command, int total_len)
15975 {
15976         uint i = 0;
15977         struct bcm_cfg80211 *cfg = g_bcm_cfg;
15978         int err = -EINVAL, bytes_written = 0, argc = 0, val, len = 0;
15979         char delta[5], band[5], *endptr = NULL;
15980         wl_roam_prof_band_t *rp;
15981
15982         rp = (wl_roam_prof_band_t *) kzalloc(sizeof(*rp)
15983                         * WL_MAX_ROAM_PROF_BRACKETS, GFP_KERNEL);
15984         if (unlikely(!rp)) {
15985                 WL_ERR(("%s: failed to allocate memory\n", __func__));
15986                 err = -ENOMEM;
15987                 goto exit;
15988         }
15989
15990         argc = sscanf(data, "%s %s", band, delta);
15991         if (!strcasecmp(band, "a"))
15992                 rp->band = WLC_BAND_5G;
15993         else if (!strcasecmp(band, "b"))
15994                 rp->band = WLC_BAND_2G;
15995         else {
15996                 WL_ERR(("%s: Missing band\n", __func__));
15997                 goto exit;
15998         }
15999         /* Getting roam profile  from fw */
16000         if ((err = wldev_iovar_getbuf(ndev, "roam_prof", rp, sizeof(*rp),
16001                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN,  &cfg->ioctl_buf_sync))) {
16002                 WL_ERR(("Getting roam_profile failed with err=%d \n", err));
16003                 goto exit;
16004         }
16005         memcpy(rp, cfg->ioctl_buf, sizeof(wl_roam_prof_band_t));
16006         if (rp->ver != WL_MAX_ROAM_PROF_VER) {
16007                 WL_ERR(("bad version (=%d) in return data\n", rp->ver));
16008                 err = -EINVAL;
16009                 goto exit;
16010         }
16011         if ((rp->len % sizeof(wl_roam_prof_t)) != 0) {
16012                 WL_ERR(("bad length (=%d) in return data\n", rp->len));
16013                 err = -EINVAL;
16014                 goto exit;
16015         }
16016
16017         if (argc == 2) {
16018                 /* if delta is non integer returns command usage error */
16019                 val = simple_strtol(delta, &endptr, 0);
16020                 if (*endptr != '\0') {
16021                         WL_ERR(("%s: Command usage error", __func__));
16022                         goto exit;
16023                 }
16024                 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
16025                 /*
16026                  * Checking contents of roam profile data from fw and exits
16027                  * if code hits below condtion. If remaining length of buffer is
16028                  * less than roam profile size or if there is no valid entry.
16029                  */
16030                         if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
16031                                 (rp->roam_prof[i].fullscan_period == 0)) {
16032                                 break;
16033                         }
16034                         if (rp->roam_prof[i].channel_usage != 0) {
16035                                 rp->roam_prof[i].roam_delta = val;
16036                         }
16037                         len += sizeof(wl_roam_prof_t);
16038                 }
16039         }
16040         else {
16041                 if (rp->roam_prof[i].channel_usage != 0) {
16042                         bytes_written = snprintf(command, total_len,
16043                                 "%s Delta %d\n", (rp->band == WLC_BAND_2G) ? "2G" : "5G",
16044                                 rp->roam_prof[0].roam_delta);
16045                 }
16046                 err = bytes_written;
16047                 goto exit;
16048         }
16049         rp->len = len;
16050         if ((err = wldev_iovar_setbuf(ndev, "roam_prof", rp,
16051                         sizeof(*rp), cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL)) < 0) {
16052                 WL_ERR(("seting roam_profile failed with err %d\n", err));
16053         }
16054 exit :
16055         if (rp) {
16056                 kfree(rp);
16057         }
16058         return err;
16059 }
16060
16061
16062 int wl_cfg80211_scan_stop(bcm_struct_cfgdev *cfgdev)
16063 {
16064         struct bcm_cfg80211 *cfg = NULL;
16065         struct net_device *ndev = NULL;
16066         unsigned long flags;
16067         int clear_flag = 0;
16068         int ret = 0;
16069
16070         WL_TRACE(("Enter\n"));
16071
16072         cfg = g_bcm_cfg;
16073         if (!cfg)
16074                 return -EINVAL;
16075
16076         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
16077
16078         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
16079 #ifdef WL_CFG80211_P2P_DEV_IF
16080         if (cfg->scan_request && cfg->scan_request->wdev == cfgdev)
16081 #else
16082         if (cfg->scan_request && cfg->scan_request->dev == cfgdev)
16083 #endif
16084         {
16085                 cfg80211_scan_done(cfg->scan_request, true);
16086                 cfg->scan_request = NULL;
16087                 clear_flag = 1;
16088         }
16089         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
16090
16091         if (clear_flag)
16092                 wl_clr_drv_status(cfg, SCANNING, ndev);
16093
16094         return ret;
16095 }
16096
16097 bool wl_cfg80211_is_concurrent_mode(void)
16098 {
16099         if ((g_bcm_cfg) && (wl_get_drv_status_all(g_bcm_cfg, CONNECTED) > 1)) {
16100                 return true;
16101         } else {
16102                 return false;
16103         }
16104 }
16105
16106 void* wl_cfg80211_get_dhdp()
16107 {
16108         struct bcm_cfg80211 *cfg = g_bcm_cfg;
16109
16110         return cfg->pub;
16111 }
16112
16113 bool wl_cfg80211_is_p2p_active(void)
16114 {
16115         return (g_bcm_cfg && g_bcm_cfg->p2p);
16116 }
16117
16118 bool wl_cfg80211_is_roam_offload(void)
16119 {
16120         return (g_bcm_cfg && g_bcm_cfg->roam_offload);
16121 }
16122
16123 bool wl_cfg80211_is_event_from_connected_bssid(const wl_event_msg_t *e, int ifidx)
16124 {
16125         dhd_pub_t *dhd = NULL;
16126         struct net_device *ndev = NULL;
16127         u8 *curbssid = NULL;
16128
16129         dhd = (dhd_pub_t *)(g_bcm_cfg->pub);
16130
16131         if (dhd) {
16132                 ndev = dhd_idx2net(dhd, ifidx);
16133         }
16134
16135         if (!dhd || !ndev) {
16136                 return false;
16137         }
16138
16139         curbssid = wl_read_prof(g_bcm_cfg, ndev, WL_PROF_BSSID);
16140
16141         return memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) == 0;
16142 }
16143
16144 static void wl_cfg80211_work_handler(struct work_struct * work)
16145 {
16146         struct bcm_cfg80211 *cfg = NULL;
16147         struct net_info *iter, *next;
16148         s32 err = BCME_OK;
16149         s32 pm = PM_FAST;
16150         BCM_SET_CONTAINER_OF(cfg, work, struct bcm_cfg80211, pm_enable_work.work);
16151         WL_DBG(("Enter \n"));
16152 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16153         4 && __GNUC_MINOR__ >= 6))
16154 _Pragma("GCC diagnostic push")
16155 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16156 #endif
16157         for_each_ndev(cfg, iter, next) {
16158                 /* p2p discovery iface ndev could be null */
16159                 if (iter->ndev) {
16160                         if (!wl_get_drv_status(cfg, CONNECTED, iter->ndev) ||
16161                                 (wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_BSS &&
16162                                 wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_IBSS))
16163                                 continue;
16164                         if (iter->ndev) {
16165                                 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM,
16166                                                 &pm, sizeof(pm), true)) != 0) {
16167                                         if (err == -ENODEV)
16168                                                 WL_DBG(("%s:netdev not ready\n",
16169                                                         iter->ndev->name));
16170                                         else
16171                                                 WL_ERR(("%s:error (%d)\n",
16172                                                         iter->ndev->name, err));
16173                                 } else
16174                                         wl_cfg80211_update_power_mode(iter->ndev);
16175                         }
16176                 }
16177         }
16178 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16179         4 && __GNUC_MINOR__ >= 6))
16180         _Pragma("GCC diagnostic pop")
16181 #endif
16182         DHD_OS_WAKE_UNLOCK(cfg->pub);
16183 }
16184
16185 u8
16186 wl_get_action_category(void *frame, u32 frame_len)
16187 {
16188         u8 category;
16189         u8 *ptr = (u8 *)frame;
16190         if (frame == NULL)
16191                 return DOT11_ACTION_CAT_ERR_MASK;
16192         if (frame_len < DOT11_ACTION_HDR_LEN)
16193                 return DOT11_ACTION_CAT_ERR_MASK;
16194         category = ptr[DOT11_ACTION_CAT_OFF];
16195         WL_INFORM(("Action Category: %d\n", category));
16196         return category;
16197 }
16198
16199 int
16200 wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action)
16201 {
16202         u8 *ptr = (u8 *)frame;
16203         if (frame == NULL || ret_action == NULL)
16204                 return BCME_ERROR;
16205         if (frame_len < DOT11_ACTION_HDR_LEN)
16206                 return BCME_ERROR;
16207         if (DOT11_ACTION_CAT_PUBLIC != wl_get_action_category(frame, frame_len))
16208                 return BCME_ERROR;
16209         *ret_action = ptr[DOT11_ACTION_ACT_OFF];
16210         WL_INFORM(("Public Action : %d\n", *ret_action));
16211         return BCME_OK;
16212 }
16213
16214
16215 static int
16216 wl_cfg80211_delayed_roam(struct bcm_cfg80211 *cfg, struct net_device *ndev,
16217         const struct ether_addr *bssid)
16218 {
16219         s32 err;
16220         wl_event_msg_t e;
16221
16222         bzero(&e, sizeof(e));
16223         e.event_type = cpu_to_be32(WLC_E_BSSID);
16224         memcpy(&e.addr, bssid, ETHER_ADDR_LEN);
16225         /* trigger the roam event handler */
16226         WL_INFORM(("Delayed roam to " MACDBG "\n", MAC2STRDBG((u8*)(bssid))));
16227         err = wl_notify_roaming_status(cfg, ndev_to_cfgdev(ndev), &e, NULL);
16228
16229         return err;
16230 }
16231
16232 static s32
16233 wl_cfg80211_parse_vndr_ies(u8 *parse, u32 len,
16234     struct parsed_vndr_ies *vndr_ies)
16235 {
16236         s32 err = BCME_OK;
16237         vndr_ie_t *vndrie;
16238         bcm_tlv_t *ie;
16239         struct parsed_vndr_ie_info *parsed_info;
16240         u32 count = 0;
16241         s32 remained_len;
16242
16243         remained_len = (s32)len;
16244         memset(vndr_ies, 0, sizeof(*vndr_ies));
16245
16246         WL_INFORM(("---> len %d\n", len));
16247         ie = (bcm_tlv_t *) parse;
16248         if (!bcm_valid_tlv(ie, remained_len))
16249                 ie = NULL;
16250         while (ie) {
16251                 if (count >= MAX_VNDR_IE_NUMBER)
16252                         break;
16253                 if (ie->id == DOT11_MNG_VS_ID) {
16254                         vndrie = (vndr_ie_t *) ie;
16255                         /* len should be bigger than OUI length + one data length at least */
16256                         if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) {
16257                                 WL_ERR(("%s: invalid vndr ie. length is too small %d\n",
16258                                         __FUNCTION__, vndrie->len));
16259                                 goto end;
16260                         }
16261                         /* if wpa or wme ie, do not add ie */
16262                         if (!bcmp(vndrie->oui, (u8*)WPA_OUI, WPA_OUI_LEN) &&
16263                                 ((vndrie->data[0] == WPA_OUI_TYPE) ||
16264                                 (vndrie->data[0] == WME_OUI_TYPE))) {
16265                                 CFGP2P_DBG(("Found WPA/WME oui. Do not add it\n"));
16266                                 goto end;
16267                         }
16268
16269                         parsed_info = &vndr_ies->ie_info[count++];
16270
16271                         /* save vndr ie information */
16272                         parsed_info->ie_ptr = (char *)vndrie;
16273                         parsed_info->ie_len = (vndrie->len + TLV_HDR_LEN);
16274                         memcpy(&parsed_info->vndrie, vndrie, sizeof(vndr_ie_t));
16275                         vndr_ies->count = count;
16276
16277                         WL_DBG(("\t ** OUI %02x %02x %02x, type 0x%02x len:%d\n",
16278                         parsed_info->vndrie.oui[0], parsed_info->vndrie.oui[1],
16279                         parsed_info->vndrie.oui[2], parsed_info->vndrie.data[0],
16280                         parsed_info->ie_len));
16281                 }
16282 end:
16283                 ie = bcm_next_tlv(ie, &remained_len);
16284         }
16285         return err;
16286 }
16287
16288 s32
16289 wl_cfg80211_clear_per_bss_ies(struct bcm_cfg80211 *cfg, s32 bssidx)
16290 {
16291         s32 index;
16292         struct net_info *netinfo;
16293         s32 vndrie_flag[] = {VNDR_IE_BEACON_FLAG, VNDR_IE_PRBRSP_FLAG,
16294                 VNDR_IE_ASSOCRSP_FLAG, VNDR_IE_PRBREQ_FLAG, VNDR_IE_ASSOCREQ_FLAG};
16295
16296         netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
16297         if (!netinfo || !netinfo->wdev) {
16298                 WL_ERR(("netinfo or netinfo->wdev is NULL\n"));
16299                 return -1;
16300         }
16301
16302         WL_DBG(("clear management vendor IEs for bssidx:%d \n", bssidx));
16303         /* Clear the IEs set in the firmware so that host is in sync with firmware */
16304         for (index = 0; index < ARRAYSIZE(vndrie_flag); index++) {
16305                 if (wl_cfg80211_set_mgmt_vndr_ies(cfg, wdev_to_cfgdev(netinfo->wdev),
16306                         bssidx, vndrie_flag[index], NULL, 0) < 0)
16307                         WL_ERR(("vndr_ies clear failed. Ignoring.. \n"));
16308         }
16309
16310         return 0;
16311 }
16312
16313 s32
16314 wl_cfg80211_clear_mgmt_vndr_ies(struct bcm_cfg80211 *cfg)
16315 {
16316         struct net_info *iter, *next;
16317
16318         WL_DBG(("clear management vendor IEs \n"));
16319 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16320         4 && __GNUC_MINOR__ >= 6))
16321 _Pragma("GCC diagnostic push")
16322 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16323 #endif
16324         for_each_ndev(cfg, iter, next) {
16325                 wl_cfg80211_clear_per_bss_ies(cfg, iter->bssidx);
16326         }
16327 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16328         4 && __GNUC_MINOR__ >= 6))
16329 _Pragma("GCC diagnostic pop")
16330 #endif
16331         return 0;
16332 }
16333
16334 #define WL_VNDR_IE_MAXLEN 2048
16335 static s8 g_mgmt_ie_buf[WL_VNDR_IE_MAXLEN];
16336 int
16337 wl_cfg80211_set_mgmt_vndr_ies(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
16338         s32 bssidx, s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len)
16339 {
16340         struct net_device *ndev = NULL;
16341         s32 ret = BCME_OK;
16342         u8  *curr_ie_buf = NULL;
16343         u8  *mgmt_ie_buf = NULL;
16344         u32 mgmt_ie_buf_len = 0;
16345         u32 *mgmt_ie_len = 0;
16346         u32 del_add_ie_buf_len = 0;
16347         u32 total_ie_buf_len = 0;
16348         u32 parsed_ie_buf_len = 0;
16349         struct parsed_vndr_ies old_vndr_ies;
16350         struct parsed_vndr_ies new_vndr_ies;
16351         s32 i;
16352         u8 *ptr;
16353         s32 remained_buf_len;
16354         wl_bss_vndr_ies_t *ies = NULL;
16355         struct net_info *netinfo;
16356
16357         WL_DBG(("Enter. pktflag:0x%x bssidx:%x vnd_ie_len:%d \n",
16358                 pktflag, bssidx, vndr_ie_len));
16359
16360         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
16361
16362         if (bssidx > WL_MAX_IFS) {
16363                 WL_ERR(("bssidx > supported concurrent Ifaces \n"));
16364                 return -EINVAL;
16365         }
16366
16367         netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
16368         if (!netinfo) {
16369                 WL_ERR(("net_info ptr is NULL \n"));
16370                 return -EINVAL;
16371         }
16372
16373         /* Clear the global buffer */
16374         memset(g_mgmt_ie_buf, 0, sizeof(g_mgmt_ie_buf));
16375         curr_ie_buf = g_mgmt_ie_buf;
16376         ies = &netinfo->bss.ies;
16377
16378         switch (pktflag) {
16379                 case VNDR_IE_PRBRSP_FLAG :
16380                         mgmt_ie_buf = ies->probe_res_ie;
16381                         mgmt_ie_len = &ies->probe_res_ie_len;
16382                         mgmt_ie_buf_len = sizeof(ies->probe_res_ie);
16383                         break;
16384                 case VNDR_IE_ASSOCRSP_FLAG :
16385                         mgmt_ie_buf = ies->assoc_res_ie;
16386                         mgmt_ie_len = &ies->assoc_res_ie_len;
16387                         mgmt_ie_buf_len = sizeof(ies->assoc_res_ie);
16388                         break;
16389                 case VNDR_IE_BEACON_FLAG :
16390                         mgmt_ie_buf = ies->beacon_ie;
16391                         mgmt_ie_len = &ies->beacon_ie_len;
16392                         mgmt_ie_buf_len = sizeof(ies->beacon_ie);
16393                         break;
16394                 case VNDR_IE_PRBREQ_FLAG :
16395                         mgmt_ie_buf = ies->probe_req_ie;
16396                         mgmt_ie_len = &ies->probe_req_ie_len;
16397                         mgmt_ie_buf_len = sizeof(ies->probe_req_ie);
16398                         break;
16399                 case VNDR_IE_ASSOCREQ_FLAG :
16400                         mgmt_ie_buf = ies->assoc_req_ie;
16401                         mgmt_ie_len = &ies->assoc_req_ie_len;
16402                         mgmt_ie_buf_len = sizeof(ies->assoc_req_ie);
16403                         break;
16404                 default:
16405                         mgmt_ie_buf = NULL;
16406                         mgmt_ie_len = NULL;
16407                         WL_ERR(("not suitable packet type (%d)\n", pktflag));
16408                         return BCME_ERROR;
16409         }
16410
16411         if (vndr_ie_len > mgmt_ie_buf_len) {
16412                 WL_ERR(("extra IE size too big\n"));
16413                 ret = -ENOMEM;
16414         } else {
16415                 /* parse and save new vndr_ie in curr_ie_buff before comparing it */
16416                 if (vndr_ie && vndr_ie_len && curr_ie_buf) {
16417                         ptr = curr_ie_buf;
16418 /* must discard vndr_ie constness, attempt to change vndr_ie arg to non-const
16419  * causes cascade of errors in other places, fix involves const casts there
16420  */
16421 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16422         4 && __GNUC_MINOR__ >= 6))
16423 _Pragma("GCC diagnostic push")
16424 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16425 #endif
16426                         if ((ret = wl_cfg80211_parse_vndr_ies((u8 *)vndr_ie,
16427                                 vndr_ie_len, &new_vndr_ies)) < 0) {
16428                                 WL_ERR(("parse vndr ie failed \n"));
16429                                 goto exit;
16430                         }
16431 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16432         4 && __GNUC_MINOR__ >= 6))
16433 _Pragma("GCC diagnostic pop")
16434 #endif
16435                         for (i = 0; i < new_vndr_ies.count; i++) {
16436                                 struct parsed_vndr_ie_info *vndrie_info =
16437                                         &new_vndr_ies.ie_info[i];
16438
16439                                 if ((parsed_ie_buf_len + vndrie_info->ie_len) > WL_VNDR_IE_MAXLEN) {
16440                                         WL_ERR(("IE size is too big (%d > %d)\n",
16441                                                 parsed_ie_buf_len, WL_VNDR_IE_MAXLEN));
16442                                         ret = -EINVAL;
16443                                         goto exit;
16444                                 }
16445
16446                                 memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr,
16447                                         vndrie_info->ie_len);
16448                                 parsed_ie_buf_len += vndrie_info->ie_len;
16449                         }
16450                 }
16451
16452                 if (mgmt_ie_buf != NULL) {
16453                         if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) &&
16454                                 (memcmp(mgmt_ie_buf, curr_ie_buf, parsed_ie_buf_len) == 0)) {
16455                                 WL_INFORM(("Previous mgmt IE is equals to current IE"));
16456                                 goto exit;
16457                         }
16458
16459                         /* parse old vndr_ie */
16460                         if ((ret = wl_cfg80211_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len,
16461                                 &old_vndr_ies)) < 0) {
16462                                 WL_ERR(("parse vndr ie failed \n"));
16463                                 goto exit;
16464                         }
16465                         /* make a command to delete old ie */
16466                         for (i = 0; i < old_vndr_ies.count; i++) {
16467                                 struct parsed_vndr_ie_info *vndrie_info =
16468                                 &old_vndr_ies.ie_info[i];
16469
16470                                 WL_INFORM(("DELETED ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
16471                                         vndrie_info->vndrie.id, vndrie_info->vndrie.len,
16472                                         vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1],
16473                                         vndrie_info->vndrie.oui[2]));
16474
16475                                 del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
16476                                         pktflag, vndrie_info->vndrie.oui,
16477                                         vndrie_info->vndrie.id,
16478                                         vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
16479                                         vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
16480                                         "del");
16481
16482                                 curr_ie_buf += del_add_ie_buf_len;
16483                                 total_ie_buf_len += del_add_ie_buf_len;
16484                         }
16485                 }
16486
16487                 *mgmt_ie_len = 0;
16488                 /* Add if there is any extra IE */
16489                 if (mgmt_ie_buf && parsed_ie_buf_len) {
16490                         ptr = mgmt_ie_buf;
16491
16492                         remained_buf_len = mgmt_ie_buf_len;
16493
16494                         /* make a command to add new ie */
16495                         for (i = 0; i < new_vndr_ies.count; i++) {
16496                                 struct parsed_vndr_ie_info *vndrie_info =
16497                                         &new_vndr_ies.ie_info[i];
16498
16499                                 WL_INFORM(("ADDED ID : %d, Len: %d(%d), OUI:%02x:%02x:%02x\n",
16500                                         vndrie_info->vndrie.id, vndrie_info->vndrie.len,
16501                                         vndrie_info->ie_len - 2,
16502                                         vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1],
16503                                         vndrie_info->vndrie.oui[2]));
16504
16505                                 del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
16506                                         pktflag, vndrie_info->vndrie.oui,
16507                                         vndrie_info->vndrie.id,
16508                                         vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
16509                                         vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
16510                                         "add");
16511
16512                                 /* verify remained buf size before copy data */
16513                                 if (remained_buf_len >= vndrie_info->ie_len) {
16514                                         remained_buf_len -= vndrie_info->ie_len;
16515                                 } else {
16516                                         WL_ERR(("no space in mgmt_ie_buf: pktflag = %d, "
16517                                         "found vndr ies # = %d(cur %d), remained len %d, "
16518                                         "cur mgmt_ie_len %d, new ie len = %d\n",
16519                                         pktflag, new_vndr_ies.count, i, remained_buf_len,
16520                                         *mgmt_ie_len, vndrie_info->ie_len));
16521                                         break;
16522                                 }
16523
16524                                 /* save the parsed IE in cfg struct */
16525                                 memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr,
16526                                         vndrie_info->ie_len);
16527                                 *mgmt_ie_len += vndrie_info->ie_len;
16528                                 curr_ie_buf += del_add_ie_buf_len;
16529                                 total_ie_buf_len += del_add_ie_buf_len;
16530                         }
16531                 }
16532
16533                 if (total_ie_buf_len && cfg->ioctl_buf != NULL) {
16534                         ret  = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", g_mgmt_ie_buf,
16535                                 total_ie_buf_len, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
16536                                 bssidx, &cfg->ioctl_buf_sync);
16537                         if (ret)
16538                                 WL_ERR(("vndr ie set error : %d\n", ret));
16539                 }
16540         }
16541 exit:
16542
16543 return ret;
16544 }
16545
16546 #ifdef WL_CFG80211_ACL
16547 static int
16548 wl_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *cfgdev,
16549         const struct cfg80211_acl_data *acl)
16550 {
16551         int i;
16552         int ret = 0;
16553         int macnum = 0;
16554         int macmode = MACLIST_MODE_DISABLED;
16555         struct maclist *list;
16556
16557         /* get the MAC filter mode */
16558         if (acl && acl->acl_policy == NL80211_ACL_POLICY_DENY_UNLESS_LISTED) {
16559                 macmode = MACLIST_MODE_ALLOW;
16560         } else if (acl && acl->acl_policy == NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
16561         acl->n_acl_entries) {
16562                 macmode = MACLIST_MODE_DENY;
16563         }
16564
16565         /* if acl == NULL, macmode is still disabled.. */
16566         if (macmode == MACLIST_MODE_DISABLED) {
16567                 if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, NULL)) != 0)
16568                         WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
16569
16570                 return ret;
16571         }
16572
16573         macnum = acl->n_acl_entries;
16574         if (macnum < 0 || macnum > MAX_NUM_MAC_FILT) {
16575                 WL_ERR(("%s : invalid number of MAC address entries %d\n",
16576                         __FUNCTION__, macnum));
16577                 return -1;
16578         }
16579
16580         /* allocate memory for the MAC list */
16581         list = (struct maclist*)kmalloc(sizeof(int) +
16582                 sizeof(struct ether_addr) * macnum, GFP_KERNEL);
16583         if (!list) {
16584                 WL_ERR(("%s : failed to allocate memory\n", __FUNCTION__));
16585                 return -1;
16586         }
16587
16588         /* prepare the MAC list */
16589         list->count = htod32(macnum);
16590         for (i = 0; i < macnum; i++) {
16591                 memcpy(&list->ea[i], &acl->mac_addrs[i], ETHER_ADDR_LEN);
16592         }
16593         /* set the list */
16594         if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, list)) != 0)
16595                 WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
16596
16597         kfree(list);
16598
16599         return ret;
16600 }
16601 #endif /* WL_CFG80211_ACL */
16602
16603 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
16604 int wl_chspec_chandef(chanspec_t chanspec,
16605 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
16606         struct cfg80211_chan_def *chandef,
16607 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
16608         struct chan_info *chaninfo,
16609 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */
16610 struct wiphy *wiphy)
16611
16612 {
16613         uint16 freq = 0;
16614         int chan_type = 0;
16615         int channel = 0;
16616         struct ieee80211_channel *chan;
16617
16618         if (!chandef) {
16619                 return -1;
16620         }
16621         channel = CHSPEC_CHANNEL(chanspec);
16622
16623         switch (CHSPEC_BW(chanspec)) {
16624                 case WL_CHANSPEC_BW_20:
16625                         chan_type = NL80211_CHAN_HT20;
16626                         break;
16627                 case WL_CHANSPEC_BW_40:
16628                 {
16629                         if (CHSPEC_SB_UPPER(chanspec)) {
16630                                 channel += CH_10MHZ_APART;
16631                         } else {
16632                                 channel -= CH_10MHZ_APART;
16633                         }
16634                 }
16635                         chan_type = NL80211_CHAN_HT40PLUS;
16636                         break;
16637
16638 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16639                 case WL_CHANSPEC_BW_80:
16640                 case WL_CHANSPEC_BW_8080:
16641                 {
16642                         uint16 sb = CHSPEC_CTL_SB(chanspec);
16643
16644                         if (sb == WL_CHANSPEC_CTL_SB_LL) {
16645                                 channel -= (CH_10MHZ_APART + CH_20MHZ_APART);
16646                         } else if (sb == WL_CHANSPEC_CTL_SB_LU) {
16647                                 channel -= CH_10MHZ_APART;
16648                         } else if (sb == WL_CHANSPEC_CTL_SB_UL) {
16649                                 channel += CH_10MHZ_APART;
16650                         } else {
16651                                 /* WL_CHANSPEC_CTL_SB_UU */
16652                                 channel += (CH_10MHZ_APART + CH_20MHZ_APART);
16653                         }
16654
16655                         if (sb == WL_CHANSPEC_CTL_SB_LL || sb == WL_CHANSPEC_CTL_SB_LU)
16656                                 chan_type = NL80211_CHAN_HT40MINUS;
16657                         else if (sb == WL_CHANSPEC_CTL_SB_UL || sb == WL_CHANSPEC_CTL_SB_UU)
16658                                 chan_type = NL80211_CHAN_HT40PLUS;
16659                 }
16660                         break;
16661 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16662                 default:
16663                         chan_type = NL80211_CHAN_HT20;
16664                         break;
16665
16666         }
16667
16668         if (CHSPEC_IS5G(chanspec))
16669                 freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_5GHZ);
16670         else
16671                 freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_2GHZ);
16672
16673         chan = ieee80211_get_channel(wiphy, freq);
16674         WL_DBG(("channel:%d freq:%d chan_type: %d chan_ptr:%p \n",
16675                 channel, freq, chan_type, chan));
16676
16677         if (unlikely(!chan)) {
16678                 /* fw and cfg80211 channel lists are not in sync */
16679                 WL_ERR(("Couldn't find matching channel in wiphy channel list \n"));
16680                 ASSERT(0);
16681                 return -EINVAL;
16682         }
16683
16684 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16685         cfg80211_chandef_create(chandef, chan, chan_type);
16686 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
16687         \
16688         \
16689         \
16690         0)))
16691         chaninfo->freq = freq;
16692         chaninfo->chan_type = chan_type;
16693 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16694         return 0;
16695 }
16696
16697 void
16698 wl_cfg80211_ch_switch_notify(struct net_device *dev, uint16 chanspec, struct wiphy *wiphy)
16699 {
16700         u32 freq;
16701 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16702         struct cfg80211_chan_def chandef;
16703 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
16704         \
16705         \
16706         \
16707         0)))
16708         struct chan_info chaninfo;
16709 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16710
16711         if (!wiphy) {
16712                 printf("wiphy is null\n");
16713                 return;
16714         }
16715 #ifndef ALLOW_CHSW_EVT
16716         /* Channel switch support is only for AP/GO/ADHOC/MESH */
16717         if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION ||
16718                 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) {
16719                 WL_ERR(("No channel switch notify support for STA/GC\n"));
16720                 return;
16721         }
16722 #endif /* !ALLOW_CHSW_EVT */
16723 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16724         if (wl_chspec_chandef(chanspec, &chandef, wiphy))
16725 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
16726         if (wl_chspec_chandef(chanspec, &chaninfo, wiphy))
16727 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16728         {
16729                 WL_ERR(("%s:chspec_chandef failed\n", __FUNCTION__));
16730                 return;
16731         }
16732 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16733         freq = chandef.chan ? chandef.chan->center_freq : chandef.center_freq1;
16734         cfg80211_ch_switch_notify(dev, &chandef);
16735 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
16736         freq = chan_info.freq;
16737         cfg80211_ch_switch_notify(dev, chan_info.freq, chan_info.chan_type);
16738 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16739
16740         WL_ERR(("Channel switch notification for freq: %d chanspec: 0x%x\n", freq, chanspec));
16741         return;
16742 }
16743 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
16744
16745 #ifdef WL11ULB
16746 s32
16747 wl_cfg80211_set_ulb_mode(struct net_device *dev, int mode)
16748 {
16749         int ret;
16750         int cur_mode;
16751
16752         ret = wldev_iovar_getint(dev, "ulb_mode", &cur_mode);
16753         if (unlikely(ret)) {
16754                 WL_ERR(("[ULB] ulb_mode get failed. ret:%d \n", ret));
16755                 return ret;
16756         }
16757
16758         if (cur_mode == mode) {
16759                 /* If request mode is same as that of the current mode, then
16760                  * do nothing (Avoid unnecessary wl down and up).
16761                  */
16762                 WL_INFORM(("[ULB] No change in ulb_mode. Do nothing.\n"));
16763                 return 0;
16764         }
16765
16766         /* setting of ulb_mode requires wl to be down */
16767         ret = wldev_ioctl(dev, WLC_DOWN, NULL, 0, true);
16768         if (unlikely(ret)) {
16769                 WL_ERR(("[ULB] WLC_DOWN command failed:[%d]\n", ret));
16770                 return ret;
16771         }
16772
16773         if (mode >= MAX_SUPP_ULB_MODES) {
16774                 WL_ERR(("[ULB] unsupported ulb_mode :[%d]\n", mode));
16775                 return -EINVAL;
16776         }
16777
16778         ret = wldev_iovar_setint(dev, "ulb_mode", mode);
16779         if (unlikely(ret)) {
16780                 WL_ERR(("[ULB] ulb_mode set failed. ret:%d \n", ret));
16781                 return ret;
16782         }
16783
16784         ret = wldev_ioctl(dev, WLC_UP, NULL, 0, true);
16785         if (unlikely(ret)) {
16786                 WL_ERR(("[ULB] WLC_DOWN command failed:[%d]\n", ret));
16787                 return ret;
16788         }
16789
16790         WL_DBG(("[ULB] ulb_mode set to %d successfully \n", mode));
16791
16792         return ret;
16793 }
16794
16795 static s32
16796 wl_cfg80211_ulbbw_to_ulbchspec(u32 bw)
16797 {
16798         if (bw == ULB_BW_DISABLED) {
16799                 return WL_CHANSPEC_BW_20;
16800         } else if (bw == ULB_BW_10MHZ) {
16801                 return WL_CHANSPEC_BW_10;
16802         } else if (bw == ULB_BW_5MHZ) {
16803                 return WL_CHANSPEC_BW_5;
16804         } else if (bw == ULB_BW_2P5MHZ) {
16805                 return WL_CHANSPEC_BW_2P5;
16806         } else {
16807                 WL_ERR(("[ULB] unsupported value for ulb_bw \n"));
16808                 return -EINVAL;
16809         }
16810 }
16811
16812 static chanspec_t
16813 wl_cfg80211_ulb_get_min_bw_chspec(struct wireless_dev *wdev, s32 bssidx)
16814 {
16815         struct bcm_cfg80211 *cfg = g_bcm_cfg;
16816         struct net_info *_netinfo;
16817
16818         /*
16819          *  Return the chspec value corresponding to the
16820          *  BW setting for a particular interface
16821          */
16822         if (wdev) {
16823                 /* if wdev is provided, use it */
16824                 _netinfo = wl_get_netinfo_by_wdev(cfg, wdev);
16825         } else if (bssidx >= 0) {
16826                 /* if wdev is not provided, use it */
16827                 _netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
16828         } else {
16829                 WL_ERR(("[ULB] wdev/bssidx not provided\n"));
16830                 return INVCHANSPEC;
16831         }
16832
16833         if (unlikely(!_netinfo)) {
16834                 WL_ERR(("[ULB] net_info is null \n"));
16835                 return INVCHANSPEC;
16836         }
16837
16838         if (_netinfo->ulb_bw) {
16839                 WL_DBG(("[ULB] wdev_ptr:%p ulb_bw:0x%x \n", _netinfo->wdev, _netinfo->ulb_bw));
16840                 return wl_cfg80211_ulbbw_to_ulbchspec(_netinfo->ulb_bw);
16841         } else {
16842                 return WL_CHANSPEC_BW_20;
16843         }
16844 }
16845
16846 static s32
16847 wl_cfg80211_get_ulb_bw(struct wireless_dev *wdev)
16848 {
16849         struct bcm_cfg80211 *cfg = g_bcm_cfg;
16850         struct net_info *_netinfo = wl_get_netinfo_by_wdev(cfg, wdev);
16851
16852         /*
16853          *  Return the ulb_bw setting for a
16854          *  particular interface
16855          */
16856         if (unlikely(!_netinfo)) {
16857                 WL_ERR(("[ULB] net_info is null \n"));
16858                 return -1;
16859         }
16860
16861         return _netinfo->ulb_bw;
16862 }
16863
16864 s32
16865 wl_cfg80211_set_ulb_bw(struct net_device *dev,
16866         u32 ulb_bw,  char *ifname)
16867 {
16868         struct bcm_cfg80211 *cfg = g_bcm_cfg;
16869         int ret;
16870         int mode;
16871         struct net_info *_netinfo = NULL, *iter, *next;
16872         u32 bssidx;
16873         enum nl80211_iftype iftype;
16874
16875         if (!ifname)
16876                 return -EINVAL;
16877
16878         WL_DBG(("[ULB] Enter. bw_type:%d \n", ulb_bw));
16879
16880         ret = wldev_iovar_getint(dev, "ulb_mode", &mode);
16881         if (unlikely(ret)) {
16882                 WL_ERR(("[ULB] ulb_mode not supported \n"));
16883                 return ret;
16884         }
16885
16886         if (mode != ULB_MODE_STD_ALONE_MODE) {
16887                 WL_ERR(("[ULB] ulb bw modification allowed only in stand-alone mode\n"));
16888                 return -EINVAL;
16889         }
16890
16891         if (ulb_bw >= MAX_SUPP_ULB_BW) {
16892                 WL_ERR(("[ULB] unsupported value (%d) for ulb_bw \n", ulb_bw));
16893                 return -EINVAL;
16894         }
16895
16896 #ifdef WL_CFG80211_P2P_DEV_IF
16897         if (strcmp(ifname, "p2p-dev-wlan0") == 0) {
16898                 iftype = NL80211_IFTYPE_P2P_DEVICE;
16899                 /* Use wdev corresponding to the dedicated p2p discovery interface */
16900                 if (likely(cfg->p2p_wdev)) {
16901                         _netinfo = wl_get_netinfo_by_wdev(cfg, cfg->p2p_wdev);
16902                 } else {
16903                         return -ENODEV;
16904                 }
16905         }
16906 #endif /* WL_CFG80211_P2P_DEV_IF */
16907         if (!_netinfo) {
16908                 for_each_ndev(cfg, iter, next) {
16909                         if (iter->ndev) {
16910                                 if (strncmp(iter->ndev->name, ifname, strlen(ifname)) == 0) {
16911                                         _netinfo = wl_get_netinfo_by_netdev(cfg, iter->ndev);
16912                                         iftype = NL80211_IFTYPE_STATION;
16913                                 }
16914                         }
16915                 }
16916         }
16917
16918         if (!_netinfo)
16919                 return -ENODEV;
16920         bssidx = _netinfo->bssidx;
16921         _netinfo->ulb_bw = ulb_bw;
16922
16923
16924         WL_DBG(("[ULB] Applying ulb_bw:%d for bssidx:%d \n", ulb_bw, bssidx));
16925         ret = wldev_iovar_setbuf_bsscfg(dev, "ulb_bw", (void *)&ulb_bw, 4,
16926                 cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx,
16927                 &cfg->ioctl_buf_sync);
16928         if (unlikely(ret)) {
16929                 WL_ERR(("[ULB] ulb_bw set failed. ret:%d \n", ret));
16930                 return ret;
16931         }
16932
16933         return ret;
16934 }
16935 #endif /* WL11ULB */
16936
16937 static void
16938 wl_ap_channel_ind(struct bcm_cfg80211 *cfg,
16939         struct net_device *ndev,
16940         chanspec_t chanspec)
16941 {
16942         u32 channel = LCHSPEC_CHANNEL(chanspec);
16943
16944         WL_DBG(("(%s) AP channel:%d chspec:0x%x \n",
16945                 ndev->name, channel, chanspec));
16946         if (cfg->ap_oper_channel && (cfg->ap_oper_channel != channel)) {
16947                 /*
16948                  * If cached channel is different from the channel indicated
16949                  * by the event, notify user space about the channel switch.
16950                  */
16951 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
16952                 wl_cfg80211_ch_switch_notify(ndev, chanspec, bcmcfg_to_wiphy(cfg));
16953 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
16954                 cfg->ap_oper_channel = channel;
16955         }
16956 }
16957
16958 static s32
16959 wl_ap_start_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
16960 const wl_event_msg_t *e, void *data)
16961 {
16962         struct net_device *ndev = NULL;
16963         chanspec_t chanspec;
16964         u32 channel;
16965
16966         WL_DBG(("Enter\n"));
16967         if (unlikely(e->status)) {
16968                 WL_ERR(("status:0x%x \n", e->status));
16969                 return -1;
16970         }
16971
16972         if (!data) {
16973                 return -EINVAL;
16974         }
16975
16976         if (likely(cfgdev)) {
16977                 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
16978                 chanspec = *((chanspec_t *)data);
16979                 channel =  LCHSPEC_CHANNEL(chanspec);
16980
16981                 if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
16982                         /* For AP/GO role */
16983                         wl_ap_channel_ind(cfg, ndev, chanspec);
16984                 }
16985         }
16986
16987         return 0;
16988 }
16989
16990 static s32
16991 wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
16992 const wl_event_msg_t *e, void *data)
16993 {
16994         int error = 0;
16995         u32 chanspec = 0;
16996         struct net_device *ndev = NULL;
16997         struct wiphy *wiphy = NULL;
16998
16999         WL_DBG(("Enter\n"));
17000         if (unlikely(e->status)) {
17001                 WL_ERR(("status:0x%x \n", e->status));
17002                 return -1;
17003         }
17004
17005         if (likely(cfgdev)) {
17006                 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
17007                 wiphy = bcmcfg_to_wiphy(cfg);
17008                 error = wldev_iovar_getint(ndev, "chanspec", &chanspec);
17009                 if (unlikely(error)) {
17010                         WL_ERR(("Get chanspec error: %d \n", error));
17011                         return -1;
17012                 }
17013
17014                 if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
17015                         /* For AP/GO role */
17016                         wl_ap_channel_ind(cfg, ndev, chanspec);
17017                 } else {
17018 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
17019                         wl_cfg80211_ch_switch_notify(ndev, chanspec, wiphy);
17020 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
17021                 }
17022
17023         }
17024
17025         return 0;
17026 }
17027
17028 #ifdef WL_NAN
17029 int
17030 wl_cfg80211_nan_cmd_handler(struct net_device *ndev, char *cmd, int cmd_len)
17031 {
17032         return wl_cfgnan_cmd_handler(ndev, g_bcm_cfg, cmd, cmd_len);
17033 }
17034 #endif /* WL_NAN */
17035
17036 void wl_cfg80211_clear_security(struct bcm_cfg80211 *cfg)
17037 {
17038         struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
17039         int err;
17040
17041         /* Clear the security settings on the primary Interface */
17042         err = wldev_iovar_setint(dev, "wsec", 0);
17043         if (unlikely(err)) {
17044                 WL_ERR(("wsec clear failed \n"));
17045         }
17046         err = wldev_iovar_setint(dev, "auth", 0);
17047         if (unlikely(err)) {
17048                 WL_ERR(("auth clear failed \n"));
17049         }
17050         err = wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
17051         if (unlikely(err)) {
17052                 WL_ERR(("wpa_auth clear failed \n"));
17053         }
17054 }
17055
17056 #ifdef WL_CFG80211_P2P_DEV_IF
17057 void wl_cfg80211_del_p2p_wdev(void)
17058 {
17059         struct bcm_cfg80211 *cfg = g_bcm_cfg;
17060         struct wireless_dev *wdev = NULL;
17061
17062         WL_DBG(("Enter \n"));
17063         if (!cfg) {
17064                 WL_ERR(("Invalid Ptr\n"));
17065                 return;
17066         } else {
17067                 wdev = cfg->p2p_wdev;
17068         }
17069
17070         if (wdev && cfg->down_disc_if) {
17071                 wl_cfgp2p_del_p2p_disc_if(wdev, cfg);
17072                 cfg->down_disc_if = FALSE;
17073         }
17074 }
17075 #endif /* WL_CFG80211_P2P_DEV_IF */
17076
17077 #if defined(WL_SUPPORT_AUTO_CHANNEL)
17078 int
17079 wl_cfg80211_set_spect(struct net_device *dev, int spect)
17080 {
17081         struct bcm_cfg80211 *cfg = g_bcm_cfg;
17082         int down = 1;
17083         int up = 1;
17084         int err = BCME_OK;
17085
17086         if (!wl_get_drv_status_all(cfg, CONNECTED)) {
17087                 err = wldev_ioctl(dev, WLC_DOWN, &down, sizeof(down), true);
17088                 if (err) {
17089                         WL_ERR(("%s: WLC_DOWN failed: code: %d\n", __func__, err));
17090                         return err;
17091                 }
17092
17093                 err = wldev_ioctl(dev, WLC_SET_SPECT_MANAGMENT, &spect, sizeof(spect), true);
17094                 if (err) {
17095                         WL_ERR(("%s: error setting spect: code: %d\n", __func__, err));
17096                         return err;
17097                 }
17098
17099                 err = wldev_ioctl(dev, WLC_UP, &up, sizeof(up), true);
17100                 if (err) {
17101                         WL_ERR(("%s: WLC_UP failed: code: %d\n", __func__, err));
17102                         return err;
17103                 }
17104         }
17105         return err;
17106 }
17107
17108 int
17109 wl_cfg80211_get_sta_channel(void)
17110 {
17111         struct net_device *ndev = bcmcfg_to_prmry_ndev(g_bcm_cfg);
17112         int channel = 0;
17113
17114         if (wl_get_drv_status(g_bcm_cfg, CONNECTED, ndev)) {
17115                 channel = g_bcm_cfg->channel;
17116         }
17117         return channel;
17118 }
17119 #endif /* WL_SUPPORT_AUTO_CHANNEL */
17120 #ifdef P2P_LISTEN_OFFLOADING
17121 s32
17122 wl_cfg80211_p2plo_deinit(struct bcm_cfg80211 *cfg)
17123 {
17124         s32 bssidx;
17125         int ret = 0;
17126         int p2plo_pause = 0;
17127         if (!cfg || !cfg->p2p) {
17128                 WL_ERR(("Wl %p or cfg->p2p %p is null\n",
17129                         cfg, cfg ? cfg->p2p : 0));
17130                 return 0;
17131         }
17132
17133         bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
17134         ret = wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg),
17135                         "p2po_stop", (void*)&p2plo_pause, sizeof(p2plo_pause),
17136                         cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, NULL);
17137         if (ret < 0) {
17138                 WL_ERR(("p2po_stop Failed :%d\n", ret));
17139         }
17140
17141         return  ret;
17142 }
17143 s32
17144 wl_cfg80211_p2plo_listen_start(struct net_device *dev, u8 *buf, int len)
17145 {
17146         struct bcm_cfg80211 *cfg = g_bcm_cfg;
17147         s32 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
17148         wl_p2plo_listen_t p2plo_listen;
17149         int ret = -EAGAIN;
17150         int channel = 0;
17151         int period = 0;
17152         int interval = 0;
17153         int count = 0;
17154
17155         if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg)) {
17156                 WL_ERR(("Sending Action Frames. Try it again.\n"));
17157                 goto exit;
17158         }
17159
17160         if (wl_get_drv_status_all(cfg, SCANNING)) {
17161                 WL_ERR(("Scanning already\n"));
17162                 goto exit;
17163         }
17164
17165         if (wl_get_drv_status(cfg, SCAN_ABORTING, dev)) {
17166                 WL_ERR(("Scanning being aborted\n"));
17167                 goto exit;
17168         }
17169
17170         if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
17171                 WL_ERR(("p2p listen offloading already running\n"));
17172                 goto exit;
17173         }
17174
17175         /* Just in case if it is not enabled */
17176         if ((ret = wl_cfgp2p_enable_discovery(cfg, dev, NULL, 0)) < 0) {
17177                 WL_ERR(("cfgp2p_enable discovery failed"));
17178                 goto exit;
17179         }
17180
17181         bzero(&p2plo_listen, sizeof(wl_p2plo_listen_t));
17182
17183         if (len) {
17184                 sscanf(buf, " %10d %10d %10d %10d", &channel, &period, &interval, &count);
17185                 if ((channel == 0) || (period == 0) ||
17186                         (interval == 0) || (count == 0)) {
17187                         WL_ERR(("Wrong argument %d/%d/%d/%d \n",
17188                                 channel, period, interval, count));
17189                         ret = -EAGAIN;
17190                         goto exit;
17191                 }
17192                 p2plo_listen.period = period;
17193                 p2plo_listen.interval = interval;
17194                 p2plo_listen.count = count;
17195
17196                 WL_ERR(("channel:%d period:%d, interval:%d count:%d\n",
17197                                 channel, period, interval, count));
17198         } else {
17199                 WL_ERR(("Argument len is wrong.\n"));
17200                 ret = -EAGAIN;
17201                 goto exit;
17202         }
17203
17204         if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen_channel", (void*)&channel,
17205                         sizeof(channel), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
17206                         bssidx, &cfg->ioctl_buf_sync)) < 0) {
17207                 WL_ERR(("p2po_listen_channel Failed :%d\n", ret));
17208                 goto exit;
17209         }
17210
17211         if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen", (void*)&p2plo_listen,
17212                         sizeof(wl_p2plo_listen_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
17213                         bssidx, &cfg->ioctl_buf_sync)) < 0) {
17214                 WL_ERR(("p2po_listen Failed :%d\n", ret));
17215                 goto exit;
17216         }
17217
17218         wl_set_p2p_status(cfg, DISC_IN_PROGRESS);
17219         cfg->last_roc_id = P2PO_COOKIE;
17220 exit :
17221         return ret;
17222 }
17223 s32
17224 wl_cfg80211_p2plo_listen_stop(struct net_device *dev)
17225 {
17226         struct bcm_cfg80211 *cfg = g_bcm_cfg;
17227         s32 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
17228         int ret = -EAGAIN;
17229
17230         if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_stop", NULL,
17231                         0, cfg->ioctl_buf, WLC_IOCTL_SMLEN,
17232                         bssidx, &cfg->ioctl_buf_sync)) < 0) {
17233                 WL_ERR(("p2po_stop Failed :%d\n", ret));
17234                 goto exit;
17235         }
17236
17237 exit:
17238         return ret;
17239 }
17240 #endif /* P2P_LISTEN_OFFLOADING */
17241 u64
17242 wl_cfg80211_get_new_roc_id(struct bcm_cfg80211 *cfg)
17243 {
17244         u64 id = 0;
17245         id = ++cfg->last_roc_id;
17246 #ifdef  P2P_LISTEN_OFFLOADING
17247         if (id == P2PO_COOKIE) {
17248                 id = ++cfg->last_roc_id;
17249         }
17250 #endif /* P2P_LISTEN_OFFLOADING */
17251         if (id == 0)
17252                 id = ++cfg->last_roc_id;
17253         return id;
17254 }
17255
17256 #if defined(SUPPORT_RANDOM_MAC_SCAN)
17257 int
17258 wl_cfg80211_set_random_mac(struct net_device *dev, bool enable)
17259 {
17260         struct bcm_cfg80211 *cfg = g_bcm_cfg;
17261         int ret;
17262
17263         if (cfg->random_mac_enabled == enable) {
17264                 WL_ERR(("Random MAC already %s\n", enable ? "Enabled" : "Disabled"));
17265                 return BCME_OK;
17266         }
17267
17268         if (enable) {
17269                 ret = wl_cfg80211_random_mac_enable(dev);
17270         } else {
17271                 ret = wl_cfg80211_random_mac_disable(dev);
17272         }
17273
17274         if (!ret) {
17275                 cfg->random_mac_enabled = enable;
17276         }
17277
17278         return ret;
17279 }
17280
17281 int
17282 wl_cfg80211_random_mac_enable(struct net_device *dev)
17283 {
17284         u8 current_mac[ETH_ALEN] = {0, };
17285         s32 err = BCME_ERROR;
17286         uint8 buffer[20] = {0, };
17287         wl_scanmac_t *sm = NULL;
17288         int len = 0;
17289         wl_scanmac_enable_t *sm_enable = NULL;
17290         wl_scanmac_config_t *sm_config = NULL;
17291         struct bcm_cfg80211 *cfg = g_bcm_cfg;
17292
17293         if (wl_get_drv_status_all(cfg, CONNECTED) || wl_get_drv_status_all(cfg, CONNECTING) ||
17294             wl_get_drv_status_all(cfg, AP_CREATED) || wl_get_drv_status_all(cfg, AP_CREATING)) {
17295                 WL_ERR(("Fail to Set random mac, current state is wrong\n"));
17296                 return err;
17297         }
17298
17299         /* Read current mac address */
17300         err = wldev_iovar_getbuf_bsscfg(dev, "cur_etheraddr",
17301                 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
17302
17303         if (err != BCME_OK) {
17304                 WL_ERR(("failed to get current dongle mac address\n"));
17305                 return err;
17306         }
17307
17308         memcpy(current_mac, cfg->ioctl_buf, ETH_ALEN);
17309
17310         /* Enable scan mac */
17311         sm = (wl_scanmac_t *)buffer;
17312         sm_enable = (wl_scanmac_enable_t *)sm->data;
17313         sm->len = sizeof(*sm_enable);
17314         sm_enable->enable = 1;
17315         len = OFFSETOF(wl_scanmac_t, data) + sm->len;
17316         sm->subcmd_id = WL_SCANMAC_SUBCMD_ENABLE;
17317
17318         err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
17319                 sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
17320
17321         if (err != BCME_OK) {
17322                 WL_ERR(("failed to enable scanmac, err=%d\n", err));
17323                 return err;
17324         }
17325
17326         /* Configure scanmac */
17327         memset(buffer, 0x0, sizeof(buffer));
17328         sm_config = (wl_scanmac_config_t *)sm->data;
17329         sm->len = sizeof(*sm_config);
17330         sm->subcmd_id = WL_SCANMAC_SUBCMD_CONFIG;
17331         sm_config->scan_bitmap = WL_SCANMAC_SCAN_UNASSOC;
17332
17333         /* Set current mac address */
17334         memcpy(&sm_config->mac.octet, current_mac, ETH_ALEN);
17335         sm_config->mac.octet[3] = 0x0;
17336         sm_config->mac.octet[4] = 0x0;
17337         sm_config->mac.octet[5] = 0x0;
17338
17339         /* Set randomize mac address(last 3bytes) */
17340         memset(&sm_config->random_mask.octet, 0x0, ETH_ALEN);
17341         sm_config->random_mask.octet[3] = 0xff;
17342         sm_config->random_mask.octet[4] = 0xff;
17343         sm_config->random_mask.octet[5] = 0xff;
17344
17345         len = OFFSETOF(wl_scanmac_t, data) + sm->len;
17346
17347         err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
17348                 sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
17349
17350         if (err != BCME_OK) {
17351                 WL_ERR(("failed scanmac configuration\n"));
17352
17353                 /* Disable scan mac for clean-up */
17354                 wl_cfg80211_random_mac_disable(dev);
17355                 return err;
17356         }
17357
17358         WL_ERR(("random MAC enable done"));
17359         return err;
17360 }
17361
17362 int
17363 wl_cfg80211_random_mac_disable(struct net_device *dev)
17364 {
17365         s32 err = BCME_ERROR;
17366         uint8 buffer[20] = {0, };
17367         wl_scanmac_t *sm = NULL;
17368         int len = 0;
17369         wl_scanmac_enable_t *sm_enable = NULL;
17370         struct bcm_cfg80211 *cfg = g_bcm_cfg;
17371
17372         sm = (wl_scanmac_t *)buffer;
17373         sm_enable = (wl_scanmac_enable_t *)sm->data;
17374         sm->len = sizeof(*sm_enable);
17375         sm_enable->enable = 0;
17376         len = OFFSETOF(wl_scanmac_t, data) + sm->len;
17377
17378         sm->subcmd_id = WL_SCANMAC_SUBCMD_ENABLE;
17379
17380         err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
17381                 sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
17382
17383         if (err != BCME_OK) {
17384                 WL_ERR(("failed to disable scanmac, err=%d\n", err));
17385                 return err;
17386         }
17387
17388         WL_ERR(("random MAC disable done\n"));
17389         return err;
17390 }
17391 #endif /* SUPPORT_RANDOM_MAC_SCAN */
17392
17393 int
17394 wl_cfg80211_iface_count(void)
17395 {
17396         struct bcm_cfg80211 *cfg = g_bcm_cfg;
17397         struct net_info *iter, *next;
17398         int iface_count = 0;
17399
17400         for_each_ndev(cfg, iter, next) {
17401                 if (iter->ndev) {
17402                         iface_count++;
17403                 }
17404         }
17405         return iface_count;
17406 }
17407
17408 #ifdef DHD_LOG_DUMP
17409 struct bcm_cfg80211*
17410 wl_get_bcm_cfg80211_ptr(void)
17411 {
17412         return g_bcm_cfg;
17413 }
17414 #endif /* DHD_LOG_DUMP */
17415
17416 #define CHECK_DONGLE_IDLE_TIME  50
17417 #define CHECK_DONGLE_IDLE_CNT   100
17418 int
17419 wl_check_dongle_idle(struct wiphy *wiphy)
17420 {
17421         int error = 0;
17422         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
17423         struct net_device *primary_ndev;
17424         int retry = 0;
17425         struct channel_info ci;
17426         if (!cfg)
17427                 return FALSE;
17428         /* Use primary I/F for sending cmds down to firmware */
17429         primary_ndev = bcmcfg_to_prmry_ndev(cfg);
17430
17431         while (retry++ < CHECK_DONGLE_IDLE_CNT) {
17432                 error = wldev_ioctl(primary_ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false);
17433                 if (error != BCME_OK || ci.scan_channel != 0) {
17434                         WL_ERR(("Firmware is busy(err:%d scan channel:%d). wait %dms\n",
17435                                 error, ci.scan_channel, CHECK_DONGLE_IDLE_TIME));
17436                 } else {
17437                         break;
17438                 }
17439                 wl_delay(CHECK_DONGLE_IDLE_TIME);
17440         }
17441         if (retry >= CHECK_DONGLE_IDLE_CNT) {
17442                 WL_ERR(("DONGLE is BUSY too long\n"));
17443                 return FALSE;
17444         }
17445         WL_DBG(("DONGLE is idle\n"));
17446         return TRUE;
17447 }