ARM64: DTS: Add rk3399-firefly uart4 device, node as /dev/ttyS1
[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                         /* terence 20160426: fix softap issue */
8173                         err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true);
8174                         if (err < 0) {
8175                                 WL_ERR(("setting AP mode failed %d \n", err));
8176                                 err = -ENOTSUPP;
8177                                 goto exit;
8178                         }
8179                         err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
8180                         if (err < 0) {
8181                                 WL_ERR(("SET INFRA error %d\n", err));
8182                                 err = -ENOTSUPP;
8183                                 goto exit;
8184                         }
8185                         err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
8186                         if (unlikely(err)) {
8187                                 WL_ERR(("WLC_UP error (%d)\n", err));
8188                                 err = -EINVAL;
8189                                 goto exit;
8190                         }
8191                 }
8192
8193                 /* Turn on the MPC */
8194                 wldev_iovar_setint(dev, "mpc", 1);
8195
8196                  wl_cfg80211_clear_per_bss_ies(cfg, bssidx);
8197         } else {
8198                 WL_DBG(("Stopping P2P GO \n"));
8199                 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE((dhd_pub_t *)(cfg->pub),
8200                         DHD_EVENT_TIMEOUT_MS*3);
8201                 DHD_OS_WAKE_LOCK_TIMEOUT((dhd_pub_t *)(cfg->pub));
8202         }
8203
8204 exit:
8205
8206         if (dev_role == NL80211_IFTYPE_AP) {
8207                 /* clear the AP mode */
8208                 dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
8209         }
8210         return err;
8211 }
8212
8213 static s32
8214 wl_cfg80211_change_beacon(
8215         struct wiphy *wiphy,
8216         struct net_device *dev,
8217         struct cfg80211_beacon_data *info)
8218 {
8219         s32 err = BCME_OK;
8220         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8221         struct parsed_ies ies;
8222         u32 dev_role = 0;
8223         s32 bssidx = 0;
8224         bool pbc = 0;
8225
8226         WL_DBG(("Enter \n"));
8227
8228         if (dev == bcmcfg_to_prmry_ndev(cfg)) {
8229                 dev_role = NL80211_IFTYPE_AP;
8230         }
8231 #if defined(WL_ENABLE_P2P_IF)
8232         else if (dev == cfg->p2p_net) {
8233                 /* Group Add request on p2p0 */
8234                 dev = bcmcfg_to_prmry_ndev(cfg);
8235                 dev_role = NL80211_IFTYPE_P2P_GO;
8236         }
8237 #endif /* WL_ENABLE_P2P_IF */
8238
8239         if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
8240                 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
8241                 return BCME_ERROR;
8242         }
8243
8244         if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
8245                 dev_role = NL80211_IFTYPE_P2P_GO;
8246         }
8247
8248         if (!check_dev_role_integrity(cfg, dev_role)) {
8249                 err = -EINVAL;
8250                 goto fail;
8251         }
8252
8253         if ((dev_role == NL80211_IFTYPE_P2P_GO) && (cfg->p2p_wdev == NULL)) {
8254                 WL_ERR(("P2P already down status!\n"));
8255                 err = BCME_ERROR;
8256                 goto fail;
8257         }
8258
8259         /* Parse IEs */
8260         if ((err = wl_cfg80211_parse_ap_ies(dev, info, &ies)) < 0) {
8261                 WL_ERR(("Parse IEs failed \n"));
8262                 goto fail;
8263         }
8264
8265         /* Set IEs to FW */
8266         if ((err = wl_cfg80211_set_ies(dev, info, bssidx)) < 0) {
8267                 WL_ERR(("Set IEs failed \n"));
8268                 goto fail;
8269         }
8270
8271         if (dev_role == NL80211_IFTYPE_AP) {
8272                 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
8273                         WL_ERR(("Hostapd update sec failed \n"));
8274                         err = -EINVAL;
8275                         goto fail;
8276                 }
8277                 /* Enable Probe Req filter, WPS-AP certification 4.2.13 */
8278                 if ((dev_role == NL80211_IFTYPE_AP) && (ies.wps_ie != NULL)) {
8279                         wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
8280                         WL_DBG((" WPS AP, wps_ie is exists pbc=%d\n", pbc));
8281                         if (pbc)
8282                                 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
8283                         else
8284                                 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
8285                 }
8286         }
8287
8288 fail:
8289         return err;
8290 }
8291 #else
8292 static s32
8293 wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
8294         struct beacon_parameters *info)
8295 {
8296         s32 err = BCME_OK;
8297         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8298         s32 ie_offset = 0;
8299         s32 bssidx = 0;
8300         u32 dev_role = NL80211_IFTYPE_AP;
8301         struct parsed_ies ies;
8302         bcm_tlv_t *ssid_ie;
8303         bool pbc = 0;
8304         bool privacy;
8305         bool is_bss_up = 0;
8306         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
8307
8308         WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
8309                 info->interval, info->dtim_period, info->head_len, info->tail_len));
8310
8311         if (dev == bcmcfg_to_prmry_ndev(cfg)) {
8312                 dev_role = NL80211_IFTYPE_AP;
8313         }
8314 #if defined(WL_ENABLE_P2P_IF)
8315         else if (dev == cfg->p2p_net) {
8316                 /* Group Add request on p2p0 */
8317                 dev = bcmcfg_to_prmry_ndev(cfg);
8318                 dev_role = NL80211_IFTYPE_P2P_GO;
8319         }
8320 #endif /* WL_ENABLE_P2P_IF */
8321
8322         if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
8323                 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
8324                 return BCME_ERROR;
8325         }
8326
8327         if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
8328                 dev_role = NL80211_IFTYPE_P2P_GO;
8329         } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
8330                 dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
8331         }
8332
8333         if (!check_dev_role_integrity(cfg, dev_role)) {
8334                 err = -ENODEV;
8335                 goto fail;
8336         }
8337
8338         if ((dev_role == NL80211_IFTYPE_P2P_GO) && (cfg->p2p_wdev == NULL)) {
8339                 WL_ERR(("P2P already down status!\n"));
8340                 err = BCME_ERROR;
8341                 goto fail;
8342         }
8343
8344         ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
8345         /* find the SSID */
8346         if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
8347                 info->head_len - ie_offset,
8348                 DOT11_MNG_SSID_ID)) != NULL) {
8349                 if (dev_role == NL80211_IFTYPE_AP) {
8350                         /* Store the hostapd SSID */
8351                         memset(&cfg->hostapd_ssid.SSID[0], 0x00, 32);
8352                         memcpy(&cfg->hostapd_ssid.SSID[0], ssid_ie->data, ssid_ie->len);
8353                         cfg->hostapd_ssid.SSID_len = ssid_ie->len;
8354                 } else {
8355                                 /* P2P GO */
8356                         memset(&cfg->p2p->ssid.SSID[0], 0x00, 32);
8357                         memcpy(cfg->p2p->ssid.SSID, ssid_ie->data, ssid_ie->len);
8358                         cfg->p2p->ssid.SSID_len = ssid_ie->len;
8359                 }
8360         }
8361
8362         if (wl_cfg80211_parse_ies((u8 *)info->tail,
8363                 info->tail_len, &ies) < 0) {
8364                 WL_ERR(("Beacon get IEs failed \n"));
8365                 err = -EINVAL;
8366                 goto fail;
8367         }
8368
8369         if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
8370                 VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
8371                 info->tail_len)) < 0) {
8372                 WL_ERR(("Beacon set IEs failed \n"));
8373                 goto fail;
8374         } else {
8375                 WL_DBG(("Applied Vndr IEs for Beacon \n"));
8376         }
8377
8378 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
8379         if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
8380                 VNDR_IE_PRBRSP_FLAG, (u8 *)info->proberesp_ies,
8381                 info->proberesp_ies_len)) < 0) {
8382                 WL_ERR(("ProbeRsp set IEs failed \n"));
8383                 goto fail;
8384         } else {
8385                 WL_DBG(("Applied Vndr IEs for ProbeRsp \n"));
8386         }
8387 #endif
8388
8389         is_bss_up = wl_cfgp2p_bss_isup(dev, bssidx);
8390
8391 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
8392         privacy = info->privacy;
8393 #else
8394         privacy = 0;
8395 #endif
8396         if (!is_bss_up &&
8397                 (wl_cfg80211_bcn_validate_sec(dev, &ies, dev_role, bssidx, privacy) < 0))
8398         {
8399                 WL_ERR(("Beacon set security failed \n"));
8400                 err = -EINVAL;
8401                 goto fail;
8402         }
8403
8404         /* Set BI and DTIM period */
8405         if (info->interval) {
8406                 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
8407                         &info->interval, sizeof(s32), true)) < 0) {
8408                         WL_ERR(("Beacon Interval Set Error, %d\n", err));
8409                         return err;
8410                 }
8411         }
8412         if (info->dtim_period) {
8413                 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
8414                         &info->dtim_period, sizeof(s32), true)) < 0) {
8415                         WL_ERR(("DTIM Interval Set Error, %d\n", err));
8416                         return err;
8417                 }
8418         }
8419
8420         /* If bss is already up, skip bring up */
8421         if (!is_bss_up &&
8422                 (err = wl_cfg80211_bcn_bringup_ap(dev, &ies, dev_role, bssidx)) < 0)
8423         {
8424                 WL_ERR(("Beacon bring up AP/GO failed \n"));
8425                 goto fail;
8426         }
8427
8428         /* Set GC/STA SCB expiry timings. */
8429         if ((err = wl_cfg80211_set_scb_timings(cfg, dev))) {
8430                 WL_ERR(("scb setting failed \n"));
8431                 goto fail;
8432         }
8433
8434         if (wl_get_drv_status(cfg, AP_CREATED, dev)) {
8435                 /* Soft AP already running. Update changed params */
8436                 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
8437                         WL_ERR(("Hostapd update sec failed \n"));
8438                         err = -EINVAL;
8439                         goto fail;
8440                 }
8441         }
8442
8443         /* Enable Probe Req filter */
8444         if (((dev_role == NL80211_IFTYPE_P2P_GO) ||
8445                 (dev_role == NL80211_IFTYPE_AP)) && (ies.wps_ie != NULL)) {
8446                 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
8447                 if (pbc)
8448                         wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
8449         }
8450
8451         WL_DBG(("** ADD/SET beacon done **\n"));
8452
8453 fail:
8454         if (err) {
8455                 WL_ERR(("ADD/SET beacon failed\n"));
8456                 wldev_iovar_setint(dev, "mpc", 1);
8457                 if (dev_role == NL80211_IFTYPE_AP) {
8458                         /* clear the AP mode */
8459                         dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
8460                 }
8461         }
8462         return err;
8463
8464 }
8465 #endif 
8466
8467 #ifdef WL_SCHED_SCAN
8468 #define PNO_TIME                30
8469 #define PNO_REPEAT              4
8470 #define PNO_FREQ_EXPO_MAX       2
8471 static bool
8472 is_ssid_in_list(struct cfg80211_ssid *ssid, struct cfg80211_ssid *ssid_list, int count)
8473 {
8474         int i;
8475
8476         if (!ssid || !ssid_list)
8477                 return FALSE;
8478
8479         for (i = 0; i < count; i++) {
8480                 if (ssid->ssid_len == ssid_list[i].ssid_len) {
8481                         if (strncmp(ssid->ssid, ssid_list[i].ssid, ssid->ssid_len) == 0)
8482                                 return TRUE;
8483                 }
8484         }
8485         return FALSE;
8486 }
8487
8488 static int
8489 wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
8490                              struct net_device *dev,
8491                              struct cfg80211_sched_scan_request *request)
8492 {
8493         ushort pno_time = PNO_TIME;
8494         int pno_repeat = PNO_REPEAT;
8495         int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
8496         wlc_ssid_ext_t ssids_local[MAX_PFN_LIST_COUNT];
8497         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8498         struct cfg80211_ssid *ssid = NULL;
8499         struct cfg80211_ssid *hidden_ssid_list = NULL;
8500         int ssid_cnt = 0;
8501         int i;
8502         int ret = 0;
8503
8504         if (!request) {
8505                 WL_ERR(("Sched scan request was NULL\n"));
8506                 return -EINVAL;
8507         }
8508
8509         WL_DBG(("Enter \n"));
8510         WL_PNO((">>> SCHED SCAN START\n"));
8511         WL_PNO(("Enter n_match_sets:%d   n_ssids:%d \n",
8512                 request->n_match_sets, request->n_ssids));
8513         WL_PNO(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
8514                 request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max));
8515
8516
8517         if (!request->n_ssids || !request->n_match_sets) {
8518                 WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids));
8519                 return -EINVAL;
8520         }
8521
8522         memset(&ssids_local, 0, sizeof(ssids_local));
8523
8524         if (request->n_ssids > 0) {
8525                 hidden_ssid_list = request->ssids;
8526         }
8527
8528         for (i = 0; i < request->n_match_sets && ssid_cnt < MAX_PFN_LIST_COUNT; i++) {
8529                 ssid = &request->match_sets[i].ssid;
8530                 /* No need to include null ssid */
8531                 if (ssid->ssid_len) {
8532                         memcpy(ssids_local[ssid_cnt].SSID, ssid->ssid, ssid->ssid_len);
8533                         ssids_local[ssid_cnt].SSID_len = ssid->ssid_len;
8534                         if (is_ssid_in_list(ssid, hidden_ssid_list, request->n_ssids)) {
8535                                 ssids_local[ssid_cnt].hidden = TRUE;
8536                                 WL_PNO((">>> PNO hidden SSID (%s) \n", ssid->ssid));
8537                         } else {
8538                                 ssids_local[ssid_cnt].hidden = FALSE;
8539                                 WL_PNO((">>> PNO non-hidden SSID (%s) \n", ssid->ssid));
8540                         }
8541                         ssid_cnt++;
8542                 }
8543         }
8544
8545         if (ssid_cnt) {
8546                 if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, ssid_cnt,
8547                         pno_time, pno_repeat, pno_freq_expo_max, NULL, 0)) < 0) {
8548                         WL_ERR(("PNO setup failed!! ret=%d \n", ret));
8549                         return -EINVAL;
8550                 }
8551                 cfg->sched_scan_req = request;
8552         } else {
8553                 return -EINVAL;
8554         }
8555
8556         return 0;
8557 }
8558
8559 static int
8560 wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
8561 {
8562         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8563
8564         WL_DBG(("Enter \n"));
8565         WL_PNO((">>> SCHED SCAN STOP\n"));
8566
8567         if (dhd_dev_pno_stop_for_ssid(dev) < 0)
8568                 WL_ERR(("PNO Stop for SSID failed"));
8569
8570         if (cfg->scan_request && cfg->sched_scan_running) {
8571                 WL_PNO((">>> Sched scan running. Aborting it..\n"));
8572                 wl_notify_escan_complete(cfg, dev, true, true);
8573         }
8574
8575          cfg->sched_scan_req = NULL;
8576          cfg->sched_scan_running = FALSE;
8577
8578         return 0;
8579 }
8580 #endif /* WL_SCHED_SCAN */
8581
8582 #ifdef WL_SUPPORT_ACS
8583 /*
8584  * Currently the dump_obss IOVAR is returning string as output so we need to
8585  * parse the output buffer in an unoptimized way. Going forward if we get the
8586  * IOVAR output in binary format this method can be optimized
8587  */
8588 static int wl_parse_dump_obss(char *buf, struct wl_dump_survey *survey)
8589 {
8590         int i;
8591         char *token;
8592         char delim[] = " \n";
8593
8594         token = strsep(&buf, delim);
8595         while (token != NULL) {
8596                 if (!strcmp(token, "OBSS")) {
8597                         for (i = 0; i < OBSS_TOKEN_IDX; i++)
8598                                 token = strsep(&buf, delim);
8599                         survey->obss = simple_strtoul(token, NULL, 10);
8600                 }
8601
8602                 if (!strcmp(token, "IBSS")) {
8603                         for (i = 0; i < IBSS_TOKEN_IDX; i++)
8604                                 token = strsep(&buf, delim);
8605                         survey->ibss = simple_strtoul(token, NULL, 10);
8606                 }
8607
8608                 if (!strcmp(token, "TXDur")) {
8609                         for (i = 0; i < TX_TOKEN_IDX; i++)
8610                                 token = strsep(&buf, delim);
8611                         survey->tx = simple_strtoul(token, NULL, 10);
8612                 }
8613
8614                 if (!strcmp(token, "Category")) {
8615                         for (i = 0; i < CTG_TOKEN_IDX; i++)
8616                                 token = strsep(&buf, delim);
8617                         survey->no_ctg = simple_strtoul(token, NULL, 10);
8618                 }
8619
8620                 if (!strcmp(token, "Packet")) {
8621                         for (i = 0; i < PKT_TOKEN_IDX; i++)
8622                                 token = strsep(&buf, delim);
8623                         survey->no_pckt = simple_strtoul(token, NULL, 10);
8624                 }
8625
8626                 if (!strcmp(token, "Opp(time):")) {
8627                         for (i = 0; i < IDLE_TOKEN_IDX; i++)
8628                                 token = strsep(&buf, delim);
8629                         survey->idle = simple_strtoul(token, NULL, 10);
8630                 }
8631
8632                 token = strsep(&buf, delim);
8633         }
8634
8635         return 0;
8636 }
8637
8638 static int wl_dump_obss(struct net_device *ndev, cca_msrmnt_query req,
8639         struct wl_dump_survey *survey)
8640 {
8641         cca_stats_n_flags *results;
8642         char *buf;
8643         int retry, err;
8644
8645         buf = kzalloc(sizeof(char) * WLC_IOCTL_MAXLEN, GFP_KERNEL);
8646         if (unlikely(!buf)) {
8647                 WL_ERR(("%s: buf alloc failed\n", __func__));
8648                 return -ENOMEM;
8649         }
8650
8651         retry = IOCTL_RETRY_COUNT;
8652         while (retry--) {
8653                 err = wldev_iovar_getbuf(ndev, "dump_obss", &req, sizeof(req),
8654                         buf, WLC_IOCTL_MAXLEN, NULL);
8655                 if (err >=  0) {
8656                         break;
8657                 }
8658                 WL_DBG(("attempt = %d, err = %d, \n",
8659                         (IOCTL_RETRY_COUNT - retry), err));
8660         }
8661
8662         if (retry <= 0) {
8663                 WL_ERR(("failure, dump_obss IOVAR failed\n"));
8664                 err = -EINVAL;
8665                 goto exit;
8666         }
8667
8668         results = (cca_stats_n_flags *)(buf);
8669         wl_parse_dump_obss(results->buf, survey);
8670         kfree(buf);
8671
8672         return 0;
8673 exit:
8674         kfree(buf);
8675         return err;
8676 }
8677
8678 static int wl_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
8679         int idx, struct survey_info *info)
8680 {
8681         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8682         struct wl_dump_survey *survey;
8683         struct ieee80211_supported_band *band;
8684         struct ieee80211_channel*chan;
8685         cca_msrmnt_query req;
8686         int val, err, noise, retry;
8687
8688         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
8689         if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
8690                 return -ENOENT;
8691         }
8692         band = wiphy->bands[IEEE80211_BAND_2GHZ];
8693         if (band && idx >= band->n_channels) {
8694                 idx -= band->n_channels;
8695                 band = NULL;
8696         }
8697
8698         if (!band || idx >= band->n_channels) {
8699                 /* Move to 5G band */
8700                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
8701                 if (idx >= band->n_channels) {
8702                         return -ENOENT;
8703                 }
8704         }
8705
8706         chan = &band->channels[idx];
8707         /* Setting current channel to the requested channel */
8708         if ((err = wl_cfg80211_set_channel(wiphy, ndev, chan,
8709                 NL80211_CHAN_HT20) < 0)) {
8710                 WL_ERR(("Set channel failed \n"));
8711         }
8712
8713         if (!idx) {
8714                 /* Disable mpc */
8715                 val = 0;
8716                 err = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
8717                         sizeof(val), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
8718                         &cfg->ioctl_buf_sync);
8719                 if (err < 0) {
8720                         WL_ERR(("set 'mpc' failed, error = %d\n", err));
8721                 }
8722
8723                 /* Set interface up, explicitly. */
8724                 val = 1;
8725                 err = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
8726                 if (err < 0) {
8727                         WL_ERR(("set interface up failed, error = %d\n", err));
8728                 }
8729         }
8730
8731         /* Get noise value */
8732         retry = IOCTL_RETRY_COUNT;
8733         while (retry--) {
8734                 err = wldev_ioctl(ndev, WLC_GET_PHY_NOISE, &noise,
8735                         sizeof(noise), false);
8736                 if (err >=  0) {
8737                         break;
8738                 }
8739                 WL_DBG(("attempt = %d, err = %d, \n",
8740                         (IOCTL_RETRY_COUNT - retry), err));
8741         }
8742
8743         if (retry <= 0) {
8744                 WL_ERR(("Get Phy Noise failed, error = %d\n", err));
8745                 noise = CHAN_NOISE_DUMMY;
8746         }
8747
8748         survey = (struct wl_dump_survey *) kzalloc(sizeof(struct wl_dump_survey),
8749                 GFP_KERNEL);
8750         if (unlikely(!survey)) {
8751                 WL_ERR(("%s: alloc failed\n", __func__));
8752                 return -ENOMEM;
8753         }
8754
8755         /* Start Measurement for obss stats on current channel */
8756         req.msrmnt_query = 0;
8757         req.time_req = ACS_MSRMNT_DELAY;
8758         if ((err = wl_dump_obss(ndev, req, survey)) < 0) {
8759                 goto exit;
8760         }
8761
8762         /*
8763          * Wait for the meaurement to complete, adding a buffer value of 10 to take
8764          * into consideration any delay in IOVAR completion
8765          */
8766         msleep(ACS_MSRMNT_DELAY + 10);
8767
8768         /* Issue IOVAR to collect measurement results */
8769         req.msrmnt_query = 1;
8770         if ((err = wl_dump_obss(ndev, req, survey)) < 0) {
8771                 goto exit;
8772         }
8773
8774         info->channel = chan;
8775         info->noise = noise;
8776         info->channel_time = ACS_MSRMNT_DELAY;
8777         info->channel_time_busy = ACS_MSRMNT_DELAY - survey->idle;
8778         info->channel_time_rx = survey->obss + survey->ibss + survey->no_ctg +
8779                 survey->no_pckt;
8780         info->channel_time_tx = survey->tx;
8781         info->filled = SURVEY_INFO_NOISE_DBM |SURVEY_INFO_CHANNEL_TIME |
8782                 SURVEY_INFO_CHANNEL_TIME_BUSY | SURVEY_INFO_CHANNEL_TIME_RX |
8783                 SURVEY_INFO_CHANNEL_TIME_TX;
8784         kfree(survey);
8785
8786         return 0;
8787 exit:
8788         kfree(survey);
8789         return err;
8790 }
8791 #endif /* WL_SUPPORT_ACS */
8792
8793 static struct cfg80211_ops wl_cfg80211_ops = {
8794         .add_virtual_intf = wl_cfg80211_add_virtual_iface,
8795         .del_virtual_intf = wl_cfg80211_del_virtual_iface,
8796         .change_virtual_intf = wl_cfg80211_change_virtual_iface,
8797 #if defined(WL_CFG80211_P2P_DEV_IF)
8798         .start_p2p_device = wl_cfgp2p_start_p2p_device,
8799         .stop_p2p_device = wl_cfgp2p_stop_p2p_device,
8800 #endif /* WL_CFG80211_P2P_DEV_IF */
8801         .scan = wl_cfg80211_scan,
8802         .set_wiphy_params = wl_cfg80211_set_wiphy_params,
8803         .join_ibss = wl_cfg80211_join_ibss,
8804         .leave_ibss = wl_cfg80211_leave_ibss,
8805         .get_station = wl_cfg80211_get_station,
8806         .set_tx_power = wl_cfg80211_set_tx_power,
8807         .get_tx_power = wl_cfg80211_get_tx_power,
8808         .add_key = wl_cfg80211_add_key,
8809         .del_key = wl_cfg80211_del_key,
8810         .get_key = wl_cfg80211_get_key,
8811         .set_default_key = wl_cfg80211_config_default_key,
8812         .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
8813         .set_power_mgmt = wl_cfg80211_set_power_mgmt,
8814         .connect = wl_cfg80211_connect,
8815         .disconnect = wl_cfg80211_disconnect,
8816         .suspend = wl_cfg80211_suspend,
8817         .resume = wl_cfg80211_resume,
8818         .set_pmksa = wl_cfg80211_set_pmksa,
8819         .del_pmksa = wl_cfg80211_del_pmksa,
8820         .flush_pmksa = wl_cfg80211_flush_pmksa,
8821         .remain_on_channel = wl_cfg80211_remain_on_channel,
8822         .cancel_remain_on_channel = wl_cfg80211_cancel_remain_on_channel,
8823         .mgmt_tx = wl_cfg80211_mgmt_tx,
8824         .mgmt_frame_register = wl_cfg80211_mgmt_frame_register,
8825         .change_bss = wl_cfg80211_change_bss,
8826 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
8827         .set_channel = wl_cfg80211_set_channel,
8828 #endif 
8829 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
8830         .set_beacon = wl_cfg80211_add_set_beacon,
8831         .add_beacon = wl_cfg80211_add_set_beacon,
8832 #else
8833         .change_beacon = wl_cfg80211_change_beacon,
8834         .start_ap = wl_cfg80211_start_ap,
8835         .stop_ap = wl_cfg80211_stop_ap,
8836 #endif 
8837 #ifdef WL_SCHED_SCAN
8838         .sched_scan_start = wl_cfg80211_sched_scan_start,
8839         .sched_scan_stop = wl_cfg80211_sched_scan_stop,
8840 #endif /* WL_SCHED_SCAN */
8841 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
8842         2, 0))
8843         .del_station = wl_cfg80211_del_station,
8844         .change_station = wl_cfg80211_change_station,
8845         .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait,
8846 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */
8847 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
8848         .tdls_mgmt = wl_cfg80211_tdls_mgmt,
8849         .tdls_oper = wl_cfg80211_tdls_oper,
8850 #endif 
8851 #ifdef WL_SUPPORT_ACS
8852         .dump_survey = wl_cfg80211_dump_survey,
8853 #endif /* WL_SUPPORT_ACS */
8854 #ifdef WL_CFG80211_ACL
8855         .set_mac_acl = wl_cfg80211_set_mac_acl,
8856 #endif /* WL_CFG80211_ACL */
8857 };
8858
8859 s32 wl_mode_to_nl80211_iftype(s32 mode)
8860 {
8861         s32 err = 0;
8862
8863         switch (mode) {
8864         case WL_MODE_BSS:
8865                 return NL80211_IFTYPE_STATION;
8866         case WL_MODE_IBSS:
8867                 return NL80211_IFTYPE_ADHOC;
8868         case WL_MODE_AP:
8869                 return NL80211_IFTYPE_AP;
8870         default:
8871                 return NL80211_IFTYPE_UNSPECIFIED;
8872         }
8873
8874         return err;
8875 }
8876
8877 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
8878 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
8879 #define WL_CFG80211_REG_NOTIFIER() static int wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
8880 #else
8881 #define WL_CFG80211_REG_NOTIFIER() static void wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
8882 #endif /* kernel version < 3.9.0 */
8883 #endif
8884
8885 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
8886 WL_CFG80211_REG_NOTIFIER()
8887 {
8888         struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy);
8889         int ret = 0;
8890         int revinfo = -1;
8891
8892         if (!request || !cfg) {
8893                 WL_ERR(("Invalid arg\n"));
8894 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
8895                 return -EINVAL;
8896 #else
8897                 return;
8898 #endif /* kernel version < 3.9.0 */
8899         }
8900
8901         WL_DBG(("ccode: %c%c Initiator: %d\n",
8902                 request->alpha2[0], request->alpha2[1], request->initiator));
8903
8904         /* We support only REGDOM_SET_BY_USER as of now */
8905         if ((request->initiator != NL80211_REGDOM_SET_BY_USER) &&
8906                 (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
8907                 WL_ERR(("reg_notifier for intiator:%d not supported : set default\n",
8908                         request->initiator));
8909                 /* in case of no supported country by regdb
8910                      lets driver setup platform default Locale
8911                 */
8912         }
8913
8914         WL_ERR(("Set country code %c%c from %s\n",
8915                 request->alpha2[0], request->alpha2[1],
8916                 ((request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) ? " 11d AP" : "User")));
8917
8918         if ((ret = wldev_set_country(bcmcfg_to_prmry_ndev(cfg), request->alpha2,
8919                 false, (request->initiator == NL80211_REGDOM_SET_BY_USER ? true : false),
8920                 revinfo)) < 0) {
8921                 WL_ERR(("set country Failed :%d\n", ret));
8922         }
8923
8924 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
8925         return ret;
8926 #else
8927         return;
8928 #endif /* kernel version < 3.9.0 */
8929 }
8930 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
8931
8932 #ifdef CONFIG_PM
8933 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
8934 static const struct wiphy_wowlan_support brcm_wowlan_support = {
8935         .flags = WIPHY_WOWLAN_ANY,
8936         .n_patterns = WL_WOWLAN_MAX_PATTERNS,
8937         .pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN,
8938         .pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN,
8939 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
8940         .max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN,
8941 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
8942 };
8943 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
8944 #if 0
8945 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8946 static struct cfg80211_wowlan brcm_wowlan_config = {
8947         .disconnect = true,
8948         .gtk_rekey_failure = true,
8949         .eap_identity_req = true,
8950         .four_way_handshake = true,
8951 };
8952 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
8953 #endif
8954 #endif /* CONFIG_PM */
8955
8956 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, void *context)
8957 {
8958         s32 err = 0;
8959 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
8960         dhd_pub_t *dhd = (dhd_pub_t *)context;
8961         BCM_REFERENCE(dhd);
8962
8963         if (!dhd) {
8964                 WL_ERR(("DHD is NULL!!"));
8965                 err = -ENODEV;
8966                 return err;
8967         }
8968 #endif 
8969
8970         wdev->wiphy =
8971             wiphy_new(&wl_cfg80211_ops, sizeof(struct bcm_cfg80211));
8972         if (unlikely(!wdev->wiphy)) {
8973                 WL_ERR(("Couldn not allocate wiphy device\n"));
8974                 err = -ENOMEM;
8975                 return err;
8976         }
8977         set_wiphy_dev(wdev->wiphy, sdiofunc_dev);
8978         wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX;
8979         /* Report  how many SSIDs Driver can support per Scan request */
8980         wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX;
8981         wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
8982 #ifdef WL_SCHED_SCAN
8983         wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT;
8984         wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT;
8985         wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX;
8986         wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8987 #endif /* WL_SCHED_SCAN */
8988         wdev->wiphy->interface_modes =
8989                 BIT(NL80211_IFTYPE_STATION)
8990                 | BIT(NL80211_IFTYPE_ADHOC)
8991 #if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
8992                 | BIT(NL80211_IFTYPE_MONITOR)
8993 #endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
8994 #if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)
8995                 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8996                 | BIT(NL80211_IFTYPE_P2P_GO)
8997 #endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */
8998 #if defined(WL_CFG80211_P2P_DEV_IF)
8999                 | BIT(NL80211_IFTYPE_P2P_DEVICE)
9000 #endif /* WL_CFG80211_P2P_DEV_IF */
9001                 | BIT(NL80211_IFTYPE_AP);
9002
9003 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
9004         (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
9005         WL_DBG(("Setting interface combinations for common mode\n"));
9006         wdev->wiphy->iface_combinations = common_iface_combinations;
9007         wdev->wiphy->n_iface_combinations =
9008                 ARRAY_SIZE(common_iface_combinations);
9009 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
9010
9011         wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
9012
9013         wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
9014         wdev->wiphy->cipher_suites = __wl_cipher_suites;
9015         wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
9016         wdev->wiphy->max_remain_on_channel_duration = 5000;
9017         wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes;
9018 #ifndef WL_POWERSAVE_DISABLED
9019         wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
9020 #else
9021         wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
9022 #endif                          /* !WL_POWERSAVE_DISABLED */
9023         wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK |
9024                 WIPHY_FLAG_4ADDR_AP |
9025 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39))
9026                 WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS |
9027 #endif
9028                 WIPHY_FLAG_4ADDR_STATION;
9029 #if ((defined(ROAM_ENABLE) || defined(BCMFW_ROAM_ENABLE)) && (LINUX_VERSION_CODE >= \
9030         KERNEL_VERSION(3, 2, 0)))
9031         /*
9032          * If FW ROAM flag is advertised, upper layer wouldn't provide
9033          * the bssid & freq in the connect command. This will result a
9034          * delay in initial connection time due to firmware doing a full
9035          * channel scan to figure out the channel & bssid. However kernel
9036          * ver >= 3.15, provides bssid_hint & freq_hint and hence kernel
9037          * ver >= 3.15 won't have any issue. So if this flags need to be
9038          * advertised for kernel < 3.15, suggest to use RCC along with it
9039          * to avoid the initial connection delay.
9040          */
9041         wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
9042 #endif 
9043 #ifdef UNSET_FW_ROAM_WIPHY_FLAG
9044         wdev->wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_FW_ROAM;
9045 #endif /* UNSET_FW_ROAM_WIPHY_FLAG */
9046 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
9047         wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
9048                 WIPHY_FLAG_OFFCHAN_TX;
9049 #endif
9050 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
9051         4, 0))
9052         /* From 3.4 kernel ownards AP_SME flag can be advertised
9053          * to remove the patch from supplicant
9054          */
9055         wdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
9056
9057 #ifdef WL_CFG80211_ACL
9058         /* Configure ACL capabilities. */
9059         wdev->wiphy->max_acl_mac_addrs = MAX_NUM_MAC_FILT;
9060 #endif
9061
9062 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9063         /* Supplicant distinguish between the SoftAP mode and other
9064          * modes (e.g. P2P, WPS, HS2.0) when it builds the probe
9065          * response frame from Supplicant MR1 and Kernel 3.4.0 or
9066          * later version. To add Vendor specific IE into the
9067          * probe response frame in case of SoftAP mode,
9068          * AP_PROBE_RESP_OFFLOAD flag is set to wiphy->flags variable.
9069          */
9070         if (dhd_get_fw_mode(dhd->info) == DHD_FLAG_HOSTAP_MODE) {
9071                 wdev->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
9072                 wdev->wiphy->probe_resp_offload = 0;
9073         }
9074 #endif 
9075 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
9076
9077 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
9078         wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
9079 #endif
9080
9081 #if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
9082         /*
9083          * From linux-3.10 kernel, wowlan packet filter is mandated to avoid the
9084          * disconnection of connected network before suspend. So a dummy wowlan
9085          * filter is configured for kernels linux-3.8 and above.
9086          */
9087
9088 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9089         wdev->wiphy->wowlan = &brcm_wowlan_support;
9090         /* If this is not provided cfg stack will get disconnect
9091          * during suspend.
9092          */
9093         //wdev->wiphy->wowlan_config = &brcm_wowlan_config;
9094 #else
9095         wdev->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
9096         wdev->wiphy->wowlan.n_patterns = WL_WOWLAN_MAX_PATTERNS;
9097         wdev->wiphy->wowlan.pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN;
9098         wdev->wiphy->wowlan.pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN;
9099 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
9100         wdev->wiphy->wowlan.max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN;
9101 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
9102 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
9103 #endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
9104
9105         WL_DBG(("Registering custom regulatory)\n"));
9106 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
9107         wdev->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
9108 #else
9109         wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
9110 #endif
9111         wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom);
9112 #if defined(WL_VENDOR_EXT_SUPPORT)
9113         WL_ERR(("Registering Vendor80211\n"));
9114         err = wl_cfgvendor_attach(wdev->wiphy);
9115         if (unlikely(err < 0)) {
9116                 WL_ERR(("Couldn not attach vendor commands (%d)\n", err));
9117         }
9118 #endif /* defined(WL_VENDOR_EXT_SUPPORT) */
9119         /* Now we can register wiphy with cfg80211 module */
9120         err = wiphy_register(wdev->wiphy);
9121         if (unlikely(err < 0)) {
9122                 WL_ERR(("Couldn not register wiphy device (%d)\n", err));
9123                 wiphy_free(wdev->wiphy);
9124         }
9125
9126 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \
9127         KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS)
9128         wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS;
9129 #endif
9130
9131         return err;
9132 }
9133
9134 static void wl_free_wdev(struct bcm_cfg80211 *cfg)
9135 {
9136         struct wireless_dev *wdev = cfg->wdev;
9137         struct wiphy *wiphy = NULL;
9138         if (!wdev) {
9139                 WL_ERR(("wdev is invalid\n"));
9140                 return;
9141         }
9142         if (wdev->wiphy) {
9143                 wiphy = wdev->wiphy;
9144
9145 #if defined(WL_VENDOR_EXT_SUPPORT)
9146                 wl_cfgvendor_detach(wdev->wiphy);
9147 #endif /* if defined(WL_VENDOR_EXT_SUPPORT) */
9148 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9149                 /* Reset wowlan & wowlan_config before Unregister to avoid  Kernel Panic */
9150                 WL_DBG(("wl_free_wdev Clearing wowlan Config \n"));
9151                 wdev->wiphy->wowlan = NULL;
9152                 wdev->wiphy->wowlan_config = NULL;
9153 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
9154                 wiphy_unregister(wdev->wiphy);
9155                 wdev->wiphy->dev.parent = NULL;
9156                 wdev->wiphy = NULL;
9157         }
9158
9159         wl_delete_all_netinfo(cfg);
9160         if (wiphy)
9161                 wiphy_free(wiphy);
9162
9163         /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "cfg",
9164          * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
9165          */
9166 }
9167
9168 static s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
9169 {
9170         struct wl_scan_results *bss_list;
9171         struct wl_bss_info *bi = NULL;  /* must be initialized */
9172         s32 err = 0;
9173         s32 i;
9174 #if defined(RSSIAVG)
9175         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
9176         int rssi;
9177 #endif
9178 #if defined(BSSCACHE)
9179         wl_bss_cache_t *node;
9180 #endif
9181
9182         bss_list = cfg->bss_list;
9183
9184         /* Free cache in p2p scanning*/
9185         if (p2p_is_on(cfg) && p2p_scan(cfg)) {
9186 #if defined(RSSIAVG)
9187                 wl_free_rssi_cache(&g_rssi_cache_ctrl);
9188 #endif
9189 #if defined(BSSCACHE)
9190                 wl_free_bss_cache(&g_bss_cache_ctrl);
9191 #endif
9192         }
9193
9194         /* Delete disconnected cache */
9195 #if defined(BSSCACHE)
9196         wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
9197 #if defined(RSSIAVG)
9198         wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
9199 #endif
9200         if (cfg->p2p_disconnected == 0)
9201                 memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN);
9202 #endif
9203
9204         /* Update cache */
9205 #if defined(RSSIAVG)
9206         wl_update_rssi_cache(&g_rssi_cache_ctrl, bss_list);
9207         if (!in_atomic())
9208                 wl_update_connected_rssi_cache(ndev, &g_rssi_cache_ctrl, &rssi);
9209 #endif
9210 #if defined(BSSCACHE)
9211         wl_update_bss_cache(&g_bss_cache_ctrl,
9212 #if defined(RSSIAVG)
9213                 &g_rssi_cache_ctrl,
9214 #endif
9215                 bss_list);
9216 #endif
9217
9218         /* delete dirty cache */
9219 #if defined(RSSIAVG)
9220         wl_delete_dirty_rssi_cache(&g_rssi_cache_ctrl);
9221         wl_reset_rssi_cache(&g_rssi_cache_ctrl);
9222 #endif
9223 #if defined(BSSCACHE)
9224         wl_delete_dirty_bss_cache(&g_bss_cache_ctrl);
9225         wl_reset_bss_cache(&g_bss_cache_ctrl);
9226 #endif
9227
9228 #if defined(BSSCACHE)
9229         if (cfg->p2p_disconnected > 0) {
9230                 // terence 20130703: Fix for wrong group_capab (timing issue)
9231                 wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
9232 #if defined(RSSIAVG)
9233                 wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
9234 #endif
9235         }
9236         WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
9237         node = g_bss_cache_ctrl.m_cache_head;
9238         for (i=0; node && i<WL_AP_MAX; i++) {
9239                 bi = node->results.bss_info;
9240                 err = wl_inform_single_bss(cfg, bi, false);
9241                 node = node->next;
9242         }
9243 #else
9244         WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
9245         bi = next_bss(bss_list, bi);
9246         for_each_bss(bss_list, bi, i) {
9247                 if (cfg->p2p_disconnected > 0 && !memcmp(&bi->BSSID, &cfg->disconnected_bssid, ETHER_ADDR_LEN))
9248                         continue;
9249                 err = wl_inform_single_bss(cfg, bi, false);
9250         }
9251 #endif
9252
9253         if (cfg->p2p_disconnected > 0) {
9254                 // terence 20130703: Fix for wrong group_capab (timing issue)
9255                 cfg->p2p_disconnected++;
9256                 if (cfg->p2p_disconnected >= REPEATED_SCAN_RESULT_CNT+1) {
9257                         cfg->p2p_disconnected = 0;
9258                         memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN);
9259                 }
9260         }
9261
9262         return err;
9263 }
9264
9265 static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi, bool roam)
9266 {
9267         struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
9268         struct ieee80211_mgmt *mgmt;
9269         struct ieee80211_channel *channel;
9270         struct ieee80211_supported_band *band;
9271         struct wl_cfg80211_bss_info *notif_bss_info;
9272         struct wl_scan_req *sr = wl_to_sr(cfg);
9273         struct beacon_proberesp *beacon_proberesp;
9274         struct cfg80211_bss *cbss = NULL;
9275         s32 mgmt_type;
9276         s32 signal;
9277         u32 freq;
9278         s32 err = 0;
9279         gfp_t aflags;
9280
9281         if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
9282                 WL_DBG(("Beacon is larger than buffer. Discarding\n"));
9283                 return err;
9284         }
9285         aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
9286         notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt)
9287                 - sizeof(u8) + WL_BSS_INFO_MAX, aflags);
9288         if (unlikely(!notif_bss_info)) {
9289                 WL_ERR(("notif_bss_info alloc failed\n"));
9290                 return -ENOMEM;
9291         }
9292         mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
9293         notif_bss_info->channel =
9294                 wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
9295
9296         if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
9297                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
9298         else
9299                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
9300         if (!band) {
9301                 WL_ERR(("No valid band\n"));
9302                 kfree(notif_bss_info);
9303                 return -EINVAL;
9304         }
9305         notif_bss_info->rssi = dtoh16(bi->RSSI);
9306 #if defined(RSSIAVG)
9307         notif_bss_info->rssi = wl_get_avg_rssi(&g_rssi_cache_ctrl, &bi->BSSID);
9308         if (notif_bss_info->rssi == RSSI_MINVAL)
9309                 notif_bss_info->rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
9310 #endif
9311 #if defined(RSSIOFFSET)
9312         notif_bss_info->rssi = wl_update_rssi_offset(bcmcfg_to_prmry_ndev(cfg), notif_bss_info->rssi);
9313 #endif
9314 #if !defined(RSSIAVG) && !defined(RSSIOFFSET)
9315         // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
9316         notif_bss_info->rssi = MIN(notif_bss_info->rssi, RSSI_MAXVAL);
9317 #endif
9318         memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
9319         mgmt_type = cfg->active_scan ?
9320                 IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
9321         if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
9322             mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
9323         }
9324         beacon_proberesp = cfg->active_scan ?
9325                 (struct beacon_proberesp *)&mgmt->u.probe_resp :
9326                 (struct beacon_proberesp *)&mgmt->u.beacon;
9327         beacon_proberesp->timestamp = 0;
9328         beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
9329         beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
9330         wl_rst_ie(cfg);
9331         wl_update_hidden_ap_ie(bi, ((u8 *) bi) + bi->ie_offset, &bi->ie_length, roam);
9332         wl_mrg_ie(cfg, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
9333         wl_cp_ie(cfg, beacon_proberesp->variable, WL_BSS_INFO_MAX -
9334                 offsetof(struct wl_cfg80211_bss_info, frame_buf));
9335         notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
9336                 u.beacon.variable) + wl_get_ielen(cfg);
9337 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
9338         freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
9339         (void)band->band;
9340 #else
9341         freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band);
9342 #endif
9343         if (freq == 0) {
9344                 WL_ERR(("Invalid channel, fail to change channel to freq\n"));
9345                 kfree(notif_bss_info);
9346                 return -EINVAL;
9347         }
9348         channel = ieee80211_get_channel(wiphy, freq);
9349         WL_SCAN(("BSSID %pM, channel %2d, rssi %3d, capa 0x04%x, mgmt_type %d, "
9350                 "frame_len %d, SSID \"%s\"\n", &bi->BSSID, notif_bss_info->channel,
9351                 notif_bss_info->rssi, mgmt->u.beacon.capab_info, mgmt_type,
9352                 notif_bss_info->frame_len, bi->SSID));
9353         if (unlikely(!channel)) {
9354                 WL_ERR(("ieee80211_get_channel error, freq=%d, channel=%d\n",
9355                         freq, notif_bss_info->channel));
9356                 kfree(notif_bss_info);
9357                 return -EINVAL;
9358         }
9359
9360         signal = notif_bss_info->rssi * 100;
9361         if (!mgmt->u.probe_resp.timestamp) {
9362 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
9363                 struct timespec ts;
9364                 get_monotonic_boottime(&ts);
9365                 mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000)
9366                                 + ts.tv_nsec / 1000;
9367 #else
9368                 struct timeval tv;
9369                 do_gettimeofday(&tv);
9370                 mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec*1000000)
9371                                 + tv.tv_usec;
9372 #endif
9373         }
9374
9375
9376         cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
9377                 le16_to_cpu(notif_bss_info->frame_len), signal, aflags);
9378         if (unlikely(!cbss)) {
9379                 WL_ERR(("cfg80211_inform_bss_frame error\n"));
9380                 kfree(notif_bss_info);
9381                 return -EINVAL;
9382         }
9383
9384
9385 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
9386         cfg80211_put_bss(wiphy, cbss);
9387 #else
9388         cfg80211_put_bss(cbss);
9389 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
9390         kfree(notif_bss_info);
9391         return err;
9392 }
9393
9394 static bool wl_is_linkup(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e, struct net_device *ndev)
9395 {
9396         u32 event = ntoh32(e->event_type);
9397         u32 status =  ntoh32(e->status);
9398         u16 flags = ntoh16(e->flags);
9399
9400         WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
9401         if (event == WLC_E_SET_SSID) {
9402                 if (status == WLC_E_STATUS_SUCCESS) {
9403                         if (!wl_is_ibssmode(cfg, ndev))
9404                                 return true;
9405                 }
9406         } else if (event == WLC_E_LINK) {
9407                 if (flags & WLC_EVENT_MSG_LINK)
9408                         return true;
9409         }
9410
9411         WL_DBG(("wl_is_linkup false\n"));
9412         return false;
9413 }
9414
9415 static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
9416 {
9417         u32 event = ntoh32(e->event_type);
9418         u16 flags = ntoh16(e->flags);
9419
9420         if (event == WLC_E_DEAUTH_IND ||
9421         event == WLC_E_DISASSOC_IND ||
9422         event == WLC_E_DISASSOC ||
9423         event == WLC_E_DEAUTH) {
9424 #if (WL_DBG_LEVEL > 0)
9425         WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
9426 #endif /* (WL_DBG_LEVEL > 0) */
9427                 return true;
9428         } else if (event == WLC_E_LINK) {
9429                 if (!(flags & WLC_EVENT_MSG_LINK)) {
9430 #if (WL_DBG_LEVEL > 0)
9431         WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
9432 #endif /* (WL_DBG_LEVEL > 0) */
9433                         return true;
9434                 }
9435         }
9436
9437         return false;
9438 }
9439
9440 static bool wl_is_nonetwork(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
9441 {
9442         u32 event = ntoh32(e->event_type);
9443         u32 status = ntoh32(e->status);
9444
9445         if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS)
9446                 return true;
9447         if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS)
9448                 return true;
9449
9450         return false;
9451 }
9452
9453 /* The mainline kernel >= 3.2.0 has support for indicating new/del station
9454  * to AP/P2P GO via events. If this change is backported to kernel for which
9455  * this driver is being built, then define WL_CFG80211_STA_EVENT. You
9456  * should use this new/del sta event mechanism for BRCM supplicant >= 22.
9457  */
9458 static s32
9459 wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
9460         const wl_event_msg_t *e, void *data)
9461 {
9462         s32 err = 0;
9463         u32 event = ntoh32(e->event_type);
9464         u32 reason = ntoh32(e->reason);
9465         u32 len = ntoh32(e->datalen);
9466         u32 status = ntoh32(e->status);
9467
9468 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
9469         bool isfree = false;
9470         u8 *mgmt_frame;
9471         u8 bsscfgidx = e->bsscfgidx;
9472         s32 freq;
9473         s32 channel;
9474         u8 *body = NULL;
9475         u16 fc = 0;
9476
9477         struct ieee80211_supported_band *band;
9478         struct ether_addr da;
9479         struct ether_addr bssid;
9480         struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
9481         channel_info_t ci;
9482 #else
9483         struct station_info sinfo;
9484 #endif 
9485
9486         WL_DBG(("event %d status %d reason %d\n", event, ntoh32(e->status), reason));
9487         /* if link down, bsscfg is disabled. */
9488         if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
9489                 wl_get_p2p_status(cfg, IF_DELETING) && (ndev != bcmcfg_to_prmry_ndev(cfg))) {
9490                 wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
9491                 WL_INFORM(("AP mode link down !! \n"));
9492                 complete(&cfg->iface_disable);
9493                 return 0;
9494         }
9495
9496         if ((event == WLC_E_LINK) && (status == WLC_E_STATUS_SUCCESS) &&
9497                 (reason == WLC_E_REASON_INITIAL_ASSOC) &&
9498                 (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP)) {
9499                 if (!wl_get_drv_status(cfg, AP_CREATED, ndev)) {
9500                         /* AP/GO brought up successfull in firmware */
9501                         WL_ERR(("** AP/GO Link up event **\n"));
9502                         wl_set_drv_status(cfg, AP_CREATED, ndev);
9503                         wake_up_interruptible(&cfg->netif_change_event);
9504                         return 0;
9505                 }
9506         }
9507
9508         if (event == WLC_E_DISASSOC_IND || event == WLC_E_DEAUTH_IND || event == WLC_E_DEAUTH) {
9509                 WL_ERR(("event %s(%d) status %d reason %d\n",
9510                 bcmevent_get_name(event), event, ntoh32(e->status), reason));
9511         }
9512
9513 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
9514         WL_DBG(("Enter \n"));
9515         if (!len && (event == WLC_E_DEAUTH)) {
9516                 len = 2; /* reason code field */
9517                 data = &reason;
9518         }
9519         if (len) {
9520                 body = kzalloc(len, GFP_KERNEL);
9521
9522                 if (body == NULL) {
9523                         WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
9524                         return WL_INVALID;
9525                 }
9526         }
9527         memset(&bssid, 0, ETHER_ADDR_LEN);
9528         WL_DBG(("Enter event %d ndev %p\n", event, ndev));
9529         if (wl_get_mode_by_netdev(cfg, ndev) == WL_INVALID) {
9530                 kfree(body);
9531                 return WL_INVALID;
9532         }
9533         if (len)
9534                 memcpy(body, data, len);
9535
9536         wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
9537                 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &cfg->ioctl_buf_sync);
9538         memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
9539         err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
9540         switch (event) {
9541                 case WLC_E_ASSOC_IND:
9542                         fc = FC_ASSOC_REQ;
9543                         break;
9544                 case WLC_E_REASSOC_IND:
9545                         fc = FC_REASSOC_REQ;
9546                         break;
9547                 case WLC_E_DISASSOC_IND:
9548                         fc = FC_DISASSOC;
9549                         break;
9550                 case WLC_E_DEAUTH_IND:
9551                         fc = FC_DISASSOC;
9552                         break;
9553                 case WLC_E_DEAUTH:
9554                         fc = FC_DISASSOC;
9555                         break;
9556                 default:
9557                         fc = 0;
9558                         goto exit;
9559         }
9560         if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) {
9561                 kfree(body);
9562                 return err;
9563         }
9564
9565         channel = dtoh32(ci.hw_channel);
9566         if (channel <= CH_MAX_2G_CHANNEL)
9567                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
9568         else
9569                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
9570         if (!band) {
9571                 WL_ERR(("No valid band\n"));
9572                 if (body)
9573                         kfree(body);
9574                 return -EINVAL;
9575         }
9576 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
9577         freq = ieee80211_channel_to_frequency(channel);
9578         (void)band->band;
9579 #else
9580         freq = ieee80211_channel_to_frequency(channel, band->band);
9581 #endif
9582
9583         err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
9584                 &mgmt_frame, &len, body);
9585         if (err < 0)
9586                 goto exit;
9587         isfree = true;
9588
9589         if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) {
9590 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) && (LINUX_VERSION_CODE < \
9591         KERNEL_VERSION(3, 18, 0)))
9592                 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
9593
9594 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
9595                 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len);
9596 #else
9597                 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
9598 #endif 
9599         } else if (event == WLC_E_DISASSOC_IND) {
9600 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9601                 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
9602 #else
9603                 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
9604 #endif 
9605         } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
9606 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9607                 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
9608 #else
9609                 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
9610 #endif 
9611         }
9612
9613 exit:
9614         if (isfree)
9615                 kfree(mgmt_frame);
9616         if (body)
9617                 kfree(body);
9618 #else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
9619         sinfo.filled = 0;
9620         if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
9621                 reason == DOT11_SC_SUCCESS) {
9622                 /* Linux ver >= 4.0 assoc_req_ies_len is used instead of
9623                  * STATION_INFO_ASSOC_REQ_IES flag
9624                  */
9625 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
9626                 sinfo.filled = STA_INFO_BIT(INFO_ASSOC_REQ_IES);
9627 #endif /*  (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) */
9628                 if (!data) {
9629                         WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
9630                         return -EINVAL;
9631                 }
9632                 sinfo.assoc_req_ies = data;
9633                 sinfo.assoc_req_ies_len = len;
9634                 printf("%s: connected device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
9635                 cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
9636         } else if (event == WLC_E_DISASSOC_IND) {
9637                 printf("%s: disassociated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
9638                 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
9639         } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
9640                 printf("%s: deauthenticated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
9641                 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
9642         }
9643 #endif 
9644         return err;
9645 }
9646
9647 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
9648 #define MAX_ASSOC_REJECT_ERR_STATUS 5
9649 int wl_get_connect_failed_status(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
9650 {
9651         u32 status = ntoh32(e->status);
9652
9653         cfg->assoc_reject_status = 0;
9654
9655         if (status == WLC_E_STATUS_FAIL) {
9656                 WL_ERR(("auth assoc status event=%d e->status %d e->reason %d \n",
9657                         ntoh32(cfg->event_auth_assoc.event_type),
9658                         (int)ntoh32(cfg->event_auth_assoc.status),
9659                         (int)ntoh32(cfg->event_auth_assoc.reason)));
9660
9661                 switch ((int)ntoh32(cfg->event_auth_assoc.status)) {
9662                         case WLC_E_STATUS_NO_ACK:
9663                                 cfg->assoc_reject_status = 1;
9664                                 break;
9665                         case WLC_E_STATUS_FAIL:
9666                                 cfg->assoc_reject_status = 2;
9667                                 break;
9668                         case WLC_E_STATUS_UNSOLICITED:
9669                                 cfg->assoc_reject_status = 3;
9670                                 break;
9671                         case WLC_E_STATUS_TIMEOUT:
9672                                 cfg->assoc_reject_status = 4;
9673                                 break;
9674                         case WLC_E_STATUS_ABORT:
9675                                 cfg->assoc_reject_status = 5;
9676                                 break;
9677                         default:
9678                                 break;
9679                 }
9680                 if (cfg->assoc_reject_status) {
9681                         if (ntoh32(cfg->event_auth_assoc.event_type) == WLC_E_ASSOC) {
9682                                 cfg->assoc_reject_status += MAX_ASSOC_REJECT_ERR_STATUS;
9683                         }
9684                 }
9685         }
9686
9687         WL_ERR(("assoc_reject_status %d \n", cfg->assoc_reject_status));
9688
9689         return 0;
9690 }
9691
9692 s32 wl_cfg80211_get_connect_failed_status(struct net_device *dev, char* cmd, int total_len)
9693 {
9694         struct bcm_cfg80211 *cfg = NULL;
9695         int bytes_written = 0;
9696
9697         cfg = g_bcm_cfg;
9698
9699         if (cfg == NULL) {
9700                 return -1;
9701         }
9702
9703         memset(cmd, 0, total_len);
9704         bytes_written = snprintf(cmd, 30, "assoc_reject.status %d", cfg->assoc_reject_status);
9705
9706         WL_ERR(("cmd: %s \n", cmd));
9707
9708         return bytes_written;
9709 }
9710 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
9711
9712 static s32
9713 wl_get_auth_assoc_status(struct bcm_cfg80211 *cfg, struct net_device *ndev,
9714         const wl_event_msg_t *e)
9715 {
9716         u32 reason = ntoh32(e->reason);
9717         u32 event = ntoh32(e->event_type);
9718         struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
9719         WL_DBG(("event type : %d, reason : %d\n", event, reason));
9720
9721 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
9722         memcpy(&cfg->event_auth_assoc, e, sizeof(wl_event_msg_t));
9723         WL_ERR(("event=%d status %d reason %d \n",
9724                 ntoh32(cfg->event_auth_assoc.event_type),
9725                 ntoh32(cfg->event_auth_assoc.status),
9726                 ntoh32(cfg->event_auth_assoc.reason)));
9727 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
9728         if (sec) {
9729                 switch (event) {
9730                 case WLC_E_ASSOC:
9731                 case WLC_E_AUTH:
9732                                 sec->auth_assoc_res_status = reason;
9733                 default:
9734                         break;
9735                 }
9736         } else
9737                 WL_ERR(("sec is NULL\n"));
9738         return 0;
9739 }
9740
9741 static s32
9742 wl_notify_connect_status_ibss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
9743         const wl_event_msg_t *e, void *data)
9744 {
9745         s32 err = 0;
9746         u32 event = ntoh32(e->event_type);
9747         u16 flags = ntoh16(e->flags);
9748         u32 status =  ntoh32(e->status);
9749         bool active;
9750 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
9751         struct ieee80211_channel *channel = NULL;
9752         struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
9753         u32 chanspec, chan;
9754         u32 freq, band;
9755 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
9756
9757         if (event == WLC_E_JOIN) {
9758                 WL_DBG(("joined in IBSS network\n"));
9759         }
9760         if (event == WLC_E_START) {
9761                 WL_DBG(("started IBSS network\n"));
9762         }
9763         if (event == WLC_E_JOIN || event == WLC_E_START ||
9764                 (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
9765 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
9766                 err = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
9767                 if (unlikely(err)) {
9768                         WL_ERR(("Could not get chanspec %d\n", err));
9769                         return err;
9770                 }
9771                 chan = wf_chspec_ctlchan(wl_chspec_driver_to_host(chanspec));
9772                 band = (chan <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
9773                 freq = ieee80211_channel_to_frequency(chan, band);
9774                 channel = ieee80211_get_channel(wiphy, freq);
9775 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
9776                 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
9777                         /* ROAM or Redundant */
9778                         u8 *cur_bssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
9779                         if (memcmp(cur_bssid, &e->addr, ETHER_ADDR_LEN) == 0) {
9780                                 WL_DBG(("IBSS connected event from same BSSID("
9781                                         MACDBG "), ignore it\n", MAC2STRDBG(cur_bssid)));
9782                                 return err;
9783                         }
9784                         WL_INFORM(("IBSS BSSID is changed from " MACDBG " to " MACDBG "\n",
9785                                 MAC2STRDBG(cur_bssid), MAC2STRDBG((const u8 *)&e->addr)));
9786                         wl_get_assoc_ies(cfg, ndev);
9787                         wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
9788                         wl_update_bss_info(cfg, ndev, false);
9789 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
9790                         cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, channel, GFP_KERNEL);
9791 #else
9792                         cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, GFP_KERNEL);
9793 #endif
9794                 }
9795                 else {
9796                         /* New connection */
9797                         WL_INFORM(("IBSS connected to " MACDBG "\n",
9798                                 MAC2STRDBG((const u8 *)&e->addr)));
9799                         wl_link_up(cfg);
9800                         wl_get_assoc_ies(cfg, ndev);
9801                         wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
9802                         wl_update_bss_info(cfg, ndev, false);
9803 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
9804                         cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, channel, GFP_KERNEL);
9805 #else
9806                         cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, GFP_KERNEL);
9807 #endif
9808                         wl_set_drv_status(cfg, CONNECTED, ndev);
9809                         active = true;
9810                         wl_update_prof(cfg, ndev, NULL, (const void *)&active, WL_PROF_ACT);
9811                 }
9812         } else if ((event == WLC_E_LINK && !(flags & WLC_EVENT_MSG_LINK)) ||
9813                 event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
9814                 wl_clr_drv_status(cfg, CONNECTED, ndev);
9815                 wl_link_down(cfg);
9816                 wl_init_prof(cfg, ndev);
9817         }
9818         else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
9819                 WL_DBG(("no action - join fail (IBSS mode)\n"));
9820         }
9821         else {
9822                 WL_DBG(("no action (IBSS mode)\n"));
9823 }
9824         return err;
9825 }
9826
9827 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
9828 #define WiFiALL_OUI         "\x50\x6F\x9A"  /* Wi-FiAll OUI */
9829 #define WiFiALL_OUI_LEN     3
9830 #define WiFiALL_OUI_TYPE    16
9831
9832 int wl_get_bss_info(struct bcm_cfg80211 *cfg, struct net_device *dev, uint8 *mac)
9833 {
9834         s32 err = 0;
9835         struct wl_bss_info *bi;
9836         uint8 eabuf[ETHER_ADDR_LEN];
9837         u32 rate, channel, freq, supported_rate, nss = 0, mcs_map, mode_80211 = 0;
9838         char rate_str[4];
9839         u8 *ie = NULL;
9840         u32 ie_len;
9841         struct wiphy *wiphy;
9842         struct cfg80211_bss *bss;
9843         bcm_tlv_t *interworking_ie = NULL;
9844         bcm_tlv_t *tlv_ie = NULL;
9845         bcm_tlv_t *vht_ie = NULL;
9846         vndr_ie_t *vndrie;
9847         int16 ie_11u_rel_num = -1, ie_mu_mimo_cap = -1;
9848         u32 i, remained_len, count = 0;
9849         char roam_count_str[4], akm_str[4];
9850         s32 val = 0;
9851
9852         /* get BSS information */
9853
9854         strncpy(cfg->bss_info, "x x x x x x x x x x x x x", GET_BSS_INFO_LEN);
9855
9856         *(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
9857
9858         err = wldev_ioctl(dev, WLC_GET_BSS_INFO, cfg->extra_buf, WL_EXTRA_BUF_MAX, false);
9859         if (unlikely(err)) {
9860                 WL_ERR(("Could not get bss info %d\n", err));
9861                 cfg->roam_count = 0;
9862                 return -1;
9863         }
9864
9865         if (!mac) {
9866                 WL_ERR(("mac is null \n"));
9867                 cfg->roam_count = 0;
9868                 return -1;
9869         }
9870
9871         memcpy(eabuf, mac, ETHER_ADDR_LEN);
9872
9873         bi = (struct wl_bss_info *)(cfg->extra_buf + 4);
9874         channel = wf_chspec_ctlchan(bi->chanspec);
9875
9876 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
9877         freq = ieee80211_channel_to_frequency(channel);
9878 #else
9879         if (channel > 14) {
9880                 freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
9881         } else {
9882                 freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
9883         }
9884 #endif
9885
9886         err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
9887         if (err) {
9888                 WL_ERR(("Could not get rate (%d)\n", err));
9889                 snprintf(rate_str, sizeof(rate_str), "x"); // Unknown
9890
9891         } else {
9892                 rate = dtoh32(rate);
9893                 snprintf(rate_str, sizeof(rate_str), "%d", (rate/2));
9894         }
9895
9896         //supported maximum rate
9897         supported_rate = (bi->rateset.rates[bi->rateset.count - 1] & 0x7f) / 2;
9898
9899         if (supported_rate < 12) {
9900                 mode_80211 = 0; //11b maximum rate is 11Mbps. 11b mode
9901         } else {
9902                 //It's not HT Capable case.
9903                 if (channel > 14) {
9904                         mode_80211 = 3; // 11a mode
9905                 } else {
9906                         mode_80211 = 1; // 11g mode
9907                 }
9908         }
9909
9910         if (bi->n_cap) {
9911                 /* check Rx MCS Map for HT */
9912                 nss = 0;
9913                 mode_80211 = 2;
9914                 for (i = 0; i < MAX_STREAMS_SUPPORTED; i++) {
9915                         int8 bitmap = 0xFF;
9916                         if (i == MAX_STREAMS_SUPPORTED-1) {
9917                                 bitmap = 0x7F;
9918                         }
9919                         if (bi->basic_mcs[i] & bitmap) {
9920                                 nss++;
9921                         }
9922                 }
9923         }
9924
9925         if (bi->vht_cap) {
9926                 nss = 0;
9927                 mode_80211 = 4;
9928                 for (i = 1; i <= VHT_CAP_MCS_MAP_NSS_MAX; i++) {
9929                         mcs_map = VHT_MCS_MAP_GET_MCS_PER_SS(i, dtoh16(bi->vht_rxmcsmap));
9930                         if (mcs_map != VHT_CAP_MCS_MAP_NONE) {
9931                                 nss++;
9932                         }
9933                 }
9934         }
9935
9936         if (nss) {
9937                 nss = nss - 1;
9938         }
9939
9940         wiphy = bcmcfg_to_wiphy(cfg);
9941         bss = cfg80211_get_bss(wiphy, NULL, eabuf,
9942                         bi->SSID, strlen(bi->SSID), WLAN_CAPABILITY_ESS,
9943                         WLAN_CAPABILITY_ESS);
9944
9945         if (!bss) {
9946                 WL_ERR(("Could not find the AP\n"));
9947         } else {
9948 #if defined(WL_CFG80211_P2P_DEV_IF)
9949                 ie = (u8 *)bss->ies->data;
9950                 ie_len = bss->ies->len;
9951 #else
9952                 ie = bss->information_elements;
9953                 ie_len = bss->len_information_elements;
9954 #endif /* WL_CFG80211_P2P_DEV_IF */
9955         }
9956
9957         if (ie) {
9958                 ie_mu_mimo_cap = 0;
9959                 ie_11u_rel_num = 0;
9960
9961                 if (bi->vht_cap) {
9962                         if ((vht_ie = bcm_parse_tlvs(ie, (u32)ie_len,
9963                                         DOT11_MNG_VHT_CAP_ID)) != NULL) {
9964                                 ie_mu_mimo_cap = (vht_ie->data[2] & 0x08) >> 3;
9965                         }
9966                 }
9967
9968                 if ((interworking_ie = bcm_parse_tlvs(ie, (u32)ie_len,
9969                                 DOT11_MNG_INTERWORKING_ID)) != NULL) {
9970                         if ((tlv_ie = bcm_parse_tlvs(ie, (u32)ie_len, DOT11_MNG_VS_ID)) != NULL) {
9971                                 remained_len = ie_len;
9972
9973                                 while (tlv_ie) {
9974                                         if (count > MAX_VNDR_IE_NUMBER)
9975                                                 break;
9976
9977                                         if (tlv_ie->id == DOT11_MNG_VS_ID) {
9978                                                 vndrie = (vndr_ie_t *) tlv_ie;
9979
9980                                                 if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) {
9981                                                         WL_ERR(("%s: invalid vndr ie."
9982                                                                 "length is too small %d\n",
9983                                                                 __FUNCTION__, vndrie->len));
9984                                                         break;
9985                                                 }
9986
9987                                                 if (!bcmp(vndrie->oui,
9988                                                         (u8*)WiFiALL_OUI, WiFiALL_OUI_LEN) &&
9989                                                         (vndrie->data[0] == WiFiALL_OUI_TYPE))
9990                                                 {
9991                                                         WL_ERR(("Found Wi-FiAll OUI oui.\n"));
9992                                                         ie_11u_rel_num = vndrie->data[1];
9993                                                         ie_11u_rel_num = (ie_11u_rel_num & 0xf0)>>4;
9994                                                         ie_11u_rel_num += 1;
9995
9996                                                         break;
9997                                                 }
9998                                         }
9999                                         count++;
10000                                         tlv_ie = bcm_next_tlv(tlv_ie, &remained_len);
10001                                 }
10002                         }
10003                 }
10004         }
10005
10006         for (i = 0; i < bi->SSID_len; i++) {
10007                 if (bi->SSID[i] == ' ') {
10008                         bi->SSID[i] = '_';
10009                 }
10010         }
10011
10012         //0 : None, 1 : OKC, 2 : FT, 3 : CCKM
10013         err = wldev_iovar_getint(dev, "wpa_auth", &val);
10014         if (unlikely(err)) {
10015                 WL_ERR(("could not get wpa_auth (%d)\n", err));
10016                 snprintf(akm_str, sizeof(akm_str), "x"); // Unknown
10017         } else {
10018                 WL_ERR(("wpa_auth val %d \n", val));
10019 #if defined(BCMEXTCCX)
10020                 if (val & (WPA_AUTH_CCKM | WPA2_AUTH_CCKM)) {
10021                         snprintf(akm_str, sizeof(akm_str), "3");
10022                 } else
10023 #endif  
10024                 if (val & WPA2_AUTH_FT) {
10025                         snprintf(akm_str, sizeof(akm_str), "2");
10026                 } else if (val & (WPA_AUTH_UNSPECIFIED | WPA2_AUTH_UNSPECIFIED)) {
10027                         snprintf(akm_str, sizeof(akm_str), "1");
10028                 } else {
10029                         snprintf(akm_str, sizeof(akm_str), "0");
10030                 }
10031         }
10032
10033         if (cfg->roam_offload) {
10034                 snprintf(roam_count_str, sizeof(roam_count_str), "x"); // Unknown
10035         } else {
10036                 snprintf(roam_count_str, sizeof(roam_count_str), "%d", cfg->roam_count);
10037         }
10038         cfg->roam_count = 0;
10039
10040         WL_ERR(("BSSID:" MACDBG " SSID %s \n", MAC2STRDBG(eabuf), bi->SSID));
10041         WL_ERR(("freq:%d, BW:%s, RSSI:%d dBm, Rate:%d Mbps, 11mode:%d, stream:%d,"
10042                                 "MU-MIMO:%d, Passpoint:%d, SNR:%d, Noise:%d, \n"
10043                                 "akm:%s roam:%s \n",
10044                                 freq, wf_chspec_to_bw_str(bi->chanspec),
10045                                 dtoh32(bi->RSSI), (rate / 2), mode_80211, nss,
10046                                 ie_mu_mimo_cap, ie_11u_rel_num, bi->SNR, bi->phy_noise,
10047                                 akm_str, roam_count_str));
10048
10049         if (ie) {
10050                 snprintf(cfg->bss_info, GET_BSS_INFO_LEN,
10051                                 "%02x:%02x:%02x %d %s %d %s %d %d %d %d %d %d %s %s",
10052                                 eabuf[0], eabuf[1], eabuf[2],
10053                                 freq, wf_chspec_to_bw_str(bi->chanspec),
10054                                 dtoh32(bi->RSSI), rate_str, mode_80211, nss,
10055                                 ie_mu_mimo_cap, ie_11u_rel_num,
10056                                 bi->SNR, bi->phy_noise, akm_str, roam_count_str);
10057         } else {
10058                 //ie_mu_mimo_cap and ie_11u_rel_num is unknow.
10059                 snprintf(cfg->bss_info, GET_BSS_INFO_LEN,
10060                                 "%02x:%02x:%02x %d %s %d %s %d %d x x %d %d %s %s",
10061                                 eabuf[0], eabuf[1], eabuf[2],
10062                                 freq, wf_chspec_to_bw_str(bi->chanspec),
10063                                 dtoh32(bi->RSSI), rate_str, mode_80211, nss,
10064                                 bi->SNR, bi->phy_noise, akm_str, roam_count_str);
10065         }
10066
10067
10068         return 0;
10069 }
10070
10071 s32 wl_cfg80211_get_bss_info(struct net_device *dev, char* cmd, int total_len)
10072 {
10073         struct bcm_cfg80211 *cfg = NULL;
10074
10075         cfg = g_bcm_cfg;
10076
10077         if (cfg == NULL) {
10078                 return -1;
10079         }
10080
10081         memset(cmd, 0, total_len);
10082         memcpy(cmd, cfg->bss_info, GET_BSS_INFO_LEN);
10083
10084         WL_ERR(("cmd: %s \n", cmd));
10085
10086         return GET_BSS_INFO_LEN;
10087 }
10088
10089 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
10090
10091 static s32
10092 wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10093         const wl_event_msg_t *e, void *data)
10094 {
10095         bool act;
10096         struct net_device *ndev = NULL;
10097         s32 err = 0;
10098         u32 event = ntoh32(e->event_type);
10099         struct wiphy *wiphy = NULL;
10100         struct cfg80211_bss *bss = NULL;
10101         struct wlc_ssid *ssid = NULL;
10102         u8 *bssid = 0;
10103
10104         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10105
10106         if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
10107                 err = wl_notify_connect_status_ap(cfg, ndev, e, data);
10108         } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS) {
10109                 err = wl_notify_connect_status_ibss(cfg, ndev, e, data);
10110         } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_BSS) {
10111                 WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
10112                         ntoh32(e->event_type), ntoh32(e->status), ndev));
10113                 if (event == WLC_E_ASSOC || event == WLC_E_AUTH) {
10114                         wl_get_auth_assoc_status(cfg, ndev, e);
10115                         return 0;
10116                 }
10117                 DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
10118                 if (wl_is_linkup(cfg, e, ndev)) {
10119                         wl_link_up(cfg);
10120                         act = true;
10121                         if (!wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
10122 #ifdef DHD_LOSSLESS_ROAMING
10123                                         bool is_connected = wl_get_drv_status(cfg, CONNECTED, ndev);
10124 #endif
10125
10126                                         printf("wl_bss_connect_done succeeded with " MACDBG "\n",
10127                                                 MAC2STRDBG((const u8*)(&e->addr)));
10128                                         wl_bss_connect_done(cfg, ndev, e, data, true);
10129                                         dhd_conf_set_fw_string_cmd(cfg->pub, "phy_oclscdenable", cfg->pub->conf->phy_oclscdenable, 0, FALSE);
10130                                         WL_DBG(("joined in BSS network \"%s\"\n",
10131                                         ((struct wlc_ssid *)
10132                                          wl_read_prof(cfg, ndev, WL_PROF_SSID))->SSID));
10133 #ifdef DHD_LOSSLESS_ROAMING
10134                                         if (event == WLC_E_LINK && is_connected &&
10135                                                         !cfg->roam_offload) {
10136                                                 wl_bss_roaming_done(cfg, ndev, e, data);
10137                                         }
10138 #endif /* DHD_LOSSLESS_ROAMING */
10139
10140                                 }
10141                         wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
10142                         wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
10143                         dhd_conf_set_wme(cfg->pub);
10144
10145                 } else if (wl_is_linkdown(cfg, e)) {
10146 #ifdef DHD_LOSSLESS_ROAMING
10147                         wl_del_roam_timeout(cfg);
10148 #endif
10149 #ifdef P2PLISTEN_AP_SAMECHN
10150                         if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
10151                                 wl_cfg80211_set_p2p_resp_ap_chn(ndev, 0);
10152                                 cfg->p2p_resp_apchn_status = false;
10153                                 WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
10154                         }
10155 #endif /* P2PLISTEN_AP_SAMECHN */
10156                         wl_cfg80211_cancel_scan(cfg);
10157
10158 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
10159                         if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
10160                                 wl_get_bss_info(cfg, ndev, (u8*)(&e->addr));
10161                         }
10162 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
10163                         /* Explicitly calling unlink to remove BSS in CFG */
10164                         wiphy = bcmcfg_to_wiphy(cfg);
10165                         ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
10166                         bssid = (u8 *)wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10167                         if (ssid && bssid) {
10168                                 bss = cfg80211_get_bss(wiphy, NULL, bssid,
10169                                         ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS,
10170                                         WLAN_CAPABILITY_ESS);
10171                                 if (bss) {
10172                                         cfg80211_unlink_bss(wiphy, bss);
10173                                 }
10174                         }
10175
10176                         if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
10177                                 scb_val_t scbval;
10178                                 u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10179                                 s32 reason = 0;
10180                                 struct ether_addr bssid_dongle;
10181                                 struct ether_addr bssid_null = {{0, 0, 0, 0, 0, 0}};
10182
10183                                 if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND)
10184                                         reason = ntoh32(e->reason);
10185                                 /* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */
10186                                 reason = (reason == WLAN_REASON_UNSPECIFIED)? 0 : reason;
10187
10188                                 printf("link down if %s may call cfg80211_disconnected. "
10189                                         "event : %d, reason=%d from " MACDBG "\n",
10190                                         ndev->name, event, ntoh32(e->reason),
10191                                         MAC2STRDBG((const u8*)(&e->addr)));
10192
10193                                 /* roam offload does not sync BSSID always, get it from dongle */
10194                                 if (cfg->roam_offload) {
10195                                         if (wldev_ioctl(ndev, WLC_GET_BSSID, &bssid_dongle,
10196                                                         sizeof(bssid_dongle), false) == BCME_OK) {
10197                                                 /* if not roam case, it would return null bssid */
10198                                                 if (memcmp(&bssid_dongle, &bssid_null,
10199                                                                 ETHER_ADDR_LEN) != 0) {
10200                                                         curbssid = (u8 *)&bssid_dongle;
10201                                                 }
10202                                         }
10203                                 }
10204                                 if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) {
10205                                         bool fw_assoc_state = TRUE;
10206                                         dhd_pub_t *dhd = (dhd_pub_t *)cfg->pub;
10207                                         fw_assoc_state = dhd_is_associated(dhd, e->ifidx, &err);
10208                                         if (!fw_assoc_state) {
10209                                                 WL_ERR(("Even sends up even different BSSID"
10210                                                         " cur: " MACDBG " event: " MACDBG"\n",
10211                                                         MAC2STRDBG(curbssid),
10212                                                         MAC2STRDBG((const u8*)(&e->addr))));
10213                                         } else {
10214                                                 WL_ERR(("BSSID of event is not the connected BSSID"
10215                                                         "(ignore it) cur: " MACDBG
10216                                                         " event: " MACDBG"\n",
10217                                                         MAC2STRDBG(curbssid),
10218                                                         MAC2STRDBG((const u8*)(&e->addr))));
10219                                                 return 0;
10220                                         }
10221                                 }
10222                                 if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) {
10223                                         // terence 20130703: Fix for wrong group_capab (timing issue)
10224                                         cfg->p2p_disconnected = 1;
10225                                 }
10226                                 memcpy(&cfg->disconnected_bssid, curbssid, ETHER_ADDR_LEN);
10227                                 wl_clr_drv_status(cfg, CONNECTED, ndev);
10228                                 if (! wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
10229                                         /* To make sure disconnect, explictly send dissassoc
10230                                         *  for BSSID 00:00:00:00:00:00 issue
10231                                         */
10232                                         scbval.val = WLAN_REASON_DEAUTH_LEAVING;
10233
10234                                         memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
10235                                         scbval.val = htod32(scbval.val);
10236                                         err = wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
10237                                                 sizeof(scb_val_t), true);
10238                                         if (err < 0) {
10239                                                 WL_ERR(("WLC_DISASSOC error %d\n", err));
10240                                                 err = 0;
10241                                         }
10242                                         CFG80211_DISCONNECTED(ndev, reason, NULL, 0,
10243                                                         false, GFP_KERNEL);
10244                                         wl_link_down(cfg);
10245                                         wl_init_prof(cfg, ndev);
10246                                         memset(&cfg->last_roamed_addr, 0, ETHER_ADDR_LEN);
10247                                 }
10248                         }
10249                         else if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
10250                                 printf("link down, during connecting\n");
10251 #ifdef ESCAN_RESULT_PATCH
10252                                 if ((memcmp(connect_req_bssid, broad_bssid, ETHER_ADDR_LEN) == 0) ||
10253                                         (memcmp(&e->addr, broad_bssid, ETHER_ADDR_LEN) == 0) ||
10254                                         (memcmp(&e->addr, connect_req_bssid, ETHER_ADDR_LEN) == 0))
10255                                         /* In case this event comes while associating another AP */
10256 #endif /* ESCAN_RESULT_PATCH */
10257                                         wl_bss_connect_done(cfg, ndev, e, data, false);
10258                         }
10259                         wl_clr_drv_status(cfg, DISCONNECTING, ndev);
10260
10261                         /* if link down, bsscfg is diabled */
10262                         if (ndev != bcmcfg_to_prmry_ndev(cfg))
10263                                 complete(&cfg->iface_disable);
10264
10265                 } else if (wl_is_nonetwork(cfg, e)) {
10266                         printf("connect failed event=%d e->status %d e->reason %d \n",
10267                                 event, (int)ntoh32(e->status), (int)ntoh32(e->reason));
10268 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
10269                         if (event == WLC_E_SET_SSID) {
10270                                 wl_get_connect_failed_status(cfg, e);
10271                         }
10272 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
10273                         /* Clean up any pending scan request */
10274                         wl_cfg80211_cancel_scan(cfg);
10275                         if (wl_get_drv_status(cfg, CONNECTING, ndev))
10276                                 wl_bss_connect_done(cfg, ndev, e, data, false);
10277                 } else {
10278                         WL_DBG(("%s nothing\n", __FUNCTION__));
10279                 }
10280                 DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
10281         }
10282                 else {
10283                 WL_ERR(("Invalid ndev status %d\n", wl_get_mode_by_netdev(cfg, ndev)));
10284         }
10285         return err;
10286 }
10287
10288 void wl_cfg80211_set_rmc_pid(int pid)
10289 {
10290         struct bcm_cfg80211 *cfg = g_bcm_cfg;
10291         if (pid > 0)
10292                 cfg->rmc_event_pid = pid;
10293         WL_DBG(("set pid for rmc event : pid=%d\n", pid));
10294 }
10295
10296 #ifdef WL_RELMCAST
10297 static s32
10298 wl_notify_rmc_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10299         const wl_event_msg_t *e, void *data)
10300 {
10301         u32 evt = ntoh32(e->event_type);
10302         u32 reason = ntoh32(e->reason);
10303         int ret = -1;
10304
10305         switch (reason) {
10306                 case WLC_E_REASON_RMC_AR_LOST:
10307                 case WLC_E_REASON_RMC_AR_NO_ACK:
10308                         if (cfg->rmc_event_pid != 0) {
10309                                 ret = wl_netlink_send_msg(cfg->rmc_event_pid,
10310                                         RMC_EVENT_LEADER_CHECK_FAIL,
10311                                         cfg->rmc_event_seq++, NULL, 0);
10312                         }
10313                         break;
10314                 default:
10315                         break;
10316         }
10317         WL_DBG(("rmcevent : evt=%d, pid=%d, ret=%d\n", evt, cfg->rmc_event_pid, ret));
10318         return ret;
10319 }
10320 #endif /* WL_RELMCAST */
10321 static s32
10322 wl_notify_roaming_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10323         const wl_event_msg_t *e, void *data)
10324 {
10325         bool act;
10326         struct net_device *ndev = NULL;
10327         s32 err = 0;
10328         u32 event = be32_to_cpu(e->event_type);
10329         u32 status = be32_to_cpu(e->status);
10330 #ifdef DHD_LOSSLESS_ROAMING
10331         struct wl_security *sec;
10332 #endif
10333         WL_DBG(("Enter \n"));
10334
10335         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10336
10337         if ((!cfg->disable_roam_event) && (event == WLC_E_BSSID)) {
10338                 wl_add_remove_eventmsg(ndev, WLC_E_ROAM, false);
10339                 cfg->disable_roam_event = TRUE;
10340         }
10341
10342         if ((cfg->disable_roam_event) && (event == WLC_E_ROAM))
10343                 return err;
10344
10345         if ((event == WLC_E_ROAM || event == WLC_E_BSSID) && status == WLC_E_STATUS_SUCCESS) {
10346                 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
10347 #ifdef DHD_LOSSLESS_ROAMING
10348                         if (cfg->roam_offload) {
10349                                 wl_bss_roaming_done(cfg, ndev, e, data);
10350                                 wl_del_roam_timeout(cfg);
10351                         }
10352                         else {
10353                                 sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
10354                                 /* In order to reduce roaming delay, wl_bss_roaming_done is
10355                                  * early called with WLC_E_LINK event. It is called from
10356                                  * here only if WLC_E_LINK event is blocked for specific
10357                                  * security type.
10358                                  */
10359                                 if (IS_AKM_SUITE_FT(sec)) {
10360                                         wl_bss_roaming_done(cfg, ndev, e, data);
10361                                 }
10362                                 /* Roam timer is deleted mostly from wl_cfg80211_change_station
10363                                  * after roaming is finished successfully. We need to delete
10364                                  * the timer from here only for some security types that aren't
10365                                  * using wl_cfg80211_change_station to authorize SCB
10366                                  */
10367                                 if (IS_AKM_SUITE_FT(sec) || IS_AKM_SUITE_CCKM(sec)) {
10368                                         wl_del_roam_timeout(cfg);
10369                                 }
10370                         }
10371 #else
10372                         wl_bss_roaming_done(cfg, ndev, e, data);
10373 #endif /* DHD_LOSSLESS_ROAMING */
10374                 } else {
10375                         wl_bss_connect_done(cfg, ndev, e, data, true);
10376                 }
10377                 act = true;
10378                 wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
10379                 wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
10380         }
10381 #ifdef DHD_LOSSLESS_ROAMING
10382         else if ((event == WLC_E_ROAM || event == WLC_E_BSSID) && status != WLC_E_STATUS_SUCCESS) {
10383                 wl_del_roam_timeout(cfg);
10384         }
10385 #endif
10386         return err;
10387 }
10388
10389 #ifdef QOS_MAP_SET
10390 /* up range from low to high with up value */
10391 static bool
10392 up_table_set(uint8 *up_table, uint8 up, uint8 low, uint8 high)
10393 {
10394         int i;
10395
10396         if (up > 7 || low > high || low >= UP_TABLE_MAX || high >= UP_TABLE_MAX) {
10397                 return FALSE;
10398         }
10399
10400         for (i = low; i <= high; i++) {
10401                 up_table[i] = up;
10402         }
10403
10404         return TRUE;
10405 }
10406
10407 /* set user priority table */
10408 static void
10409 wl_set_up_table(uint8 *up_table, bcm_tlv_t *qos_map_ie)
10410 {
10411         uint8 len;
10412
10413         if (up_table == NULL || qos_map_ie == NULL) {
10414                 return;
10415         }
10416
10417         /* clear table to check table was set or not */
10418         memset(up_table, 0xff, UP_TABLE_MAX);
10419
10420         /* length of QoS Map IE must be 16+n*2, n is number of exceptions */
10421         if (qos_map_ie != NULL && qos_map_ie->id == DOT11_MNG_QOS_MAP_ID &&
10422                         (len = qos_map_ie->len) >= QOS_MAP_FIXED_LENGTH &&
10423                         (len % 2) == 0) {
10424                 uint8 *except_ptr = (uint8 *)qos_map_ie->data;
10425                 uint8 except_len = len - QOS_MAP_FIXED_LENGTH;
10426                 uint8 *range_ptr = except_ptr + except_len;
10427                 int i;
10428
10429                 /* fill in ranges */
10430                 for (i = 0; i < QOS_MAP_FIXED_LENGTH; i += 2) {
10431                         uint8 low = range_ptr[i];
10432                         uint8 high = range_ptr[i + 1];
10433                         if (low == 255 && high == 255) {
10434                                 continue;
10435                         }
10436
10437                         if (!up_table_set(up_table, i / 2, low, high)) {
10438                                 /* clear the table on failure */
10439                                 memset(up_table, 0xff, UP_TABLE_MAX);
10440                                 return;
10441                         }
10442                 }
10443
10444                 /* update exceptions */
10445                 for (i = 0; i < except_len; i += 2) {
10446                         uint8 dscp = except_ptr[i];
10447                         uint8 up = except_ptr[i+1];
10448
10449                         /* exceptions with invalid dscp/up are ignored */
10450                         up_table_set(up_table, up, dscp, dscp);
10451                 }
10452         }
10453
10454         if (wl_dbg_level & WL_DBG_DBG) {
10455                 prhex("UP table", up_table, UP_TABLE_MAX);
10456         }
10457 }
10458
10459 /* get user priority table */
10460 uint8 *
10461 wl_get_up_table(void)
10462 {
10463         return (uint8 *)(g_bcm_cfg->up_table);
10464 }
10465 #endif /* QOS_MAP_SET */
10466
10467 #ifdef DHD_LOSSLESS_ROAMING
10468 static s32
10469 wl_notify_roam_prep_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10470         const wl_event_msg_t *e, void *data)
10471 {
10472         s32 err = 0;
10473         struct wl_security *sec;
10474         struct net_device *ndev;
10475         dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
10476
10477         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10478
10479         sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
10480         /* Disable Lossless Roaming for specific AKM suite
10481          * Any other AKM suite can be added below if transition time
10482          * is delayed because of Lossless Roaming
10483          * and it causes any certication failure
10484          */
10485         if (IS_AKM_SUITE_FT(sec)) {
10486                 return err;
10487         }
10488
10489         dhdp->dequeue_prec_map = 1 << PRIO_8021D_NC;
10490         /* Restore flow control  */
10491         dhd_txflowcontrol(dhdp, ALL_INTERFACES, OFF);
10492
10493         mod_timer(&cfg->roam_timeout, jiffies + msecs_to_jiffies(WL_ROAM_TIMEOUT_MS));
10494
10495         return err;
10496 }
10497 #endif /* DHD_LOSSLESS_ROAMING */
10498
10499 static s32
10500 wl_notify_idsup_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10501                 const wl_event_msg_t *e, void *data)
10502 {
10503         s32 err = 0;
10504 #if defined(WL_VENDOR_EXT_SUPPORT)
10505         u32 idsup_status;
10506         u32 reason = ntoh32(e->reason);
10507         struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10508         struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
10509 #endif /* defined(WL_VENDOR_EXT_SUPPORT) */
10510
10511         if (cfg->roam_offload) {
10512 #if defined(WL_VENDOR_EXT_SUPPORT)
10513                 switch (reason) {
10514                         case WLC_E_SUP_WPA_PSK_TMO:
10515                                 idsup_status = IDSUP_EVENT_4WAY_HANDSHAKE_TIMEOUT;
10516                                 break;
10517                         case WLC_E_SUP_OTHER:
10518                                 idsup_status = IDSUP_EVENT_SUCCESS;
10519                                 break;
10520                         default:
10521                                 WL_ERR(("Other type at IDSUP. "
10522                                                 "event=%d e->status %d e->reason %d \n",
10523                                                 (int)ntoh32(e->event_type), (int)ntoh32(e->status),
10524                                                 (int)ntoh32(e->reason)));
10525                                 return err;
10526                 }
10527
10528                 err = wl_cfgvendor_send_async_event(wiphy, ndev,
10529                                 BRCM_VENDOR_EVENT_IDSUP_STATUS, &idsup_status, sizeof(u32));
10530 #endif /* defined(WL_VENDOR_EXT_SUPPORT) */
10531         }
10532         return err;
10533 }
10534
10535 #ifdef CUSTOM_EVENT_PM_WAKE
10536 static s32
10537 wl_check_pmstatus(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10538                 const wl_event_msg_t *e, void *data)
10539 {
10540         s32 err = 0;
10541         struct net_device *ndev = NULL;
10542         u8 *pbuf = NULL;
10543         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10544
10545         pbuf = kzalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
10546         if (pbuf == NULL) {
10547                 WL_ERR(("failed to allocate local pbuf\n"));
10548                 return -ENOMEM;
10549         }
10550
10551         err = wldev_iovar_getbuf_bsscfg(ndev, "dump",
10552                 "pm", strlen("pm"), pbuf, WLC_IOCTL_MEDLEN, 0, &cfg->ioctl_buf_sync);
10553
10554         if (err) {
10555                 WL_ERR(("dump ioctl err = %d", err));
10556         } else {
10557                 WL_ERR(("PM status : %s\n", pbuf));
10558         }
10559
10560         if (pbuf) {
10561                 kfree(pbuf);
10562         }
10563         return err;
10564 }
10565 #endif /* CUSTOM_EVENT_PM_WAKE */
10566
10567 static s32 wl_get_assoc_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev)
10568 {
10569         wl_assoc_info_t assoc_info;
10570         struct wl_connect_info *conn_info = wl_to_conn(cfg);
10571         s32 err = 0;
10572 #ifdef QOS_MAP_SET
10573         bcm_tlv_t * qos_map_ie = NULL;
10574 #endif /* QOS_MAP_SET */
10575
10576         WL_DBG(("Enter \n"));
10577         err = wldev_iovar_getbuf(ndev, "assoc_info", NULL, 0, cfg->extra_buf,
10578                 WL_ASSOC_INFO_MAX, NULL);
10579         if (unlikely(err)) {
10580                 WL_ERR(("could not get assoc info (%d)\n", err));
10581                 return err;
10582         }
10583         memcpy(&assoc_info, cfg->extra_buf, sizeof(wl_assoc_info_t));
10584         assoc_info.req_len = htod32(assoc_info.req_len);
10585         assoc_info.resp_len = htod32(assoc_info.resp_len);
10586         assoc_info.flags = htod32(assoc_info.flags);
10587         if (conn_info->req_ie_len) {
10588                 conn_info->req_ie_len = 0;
10589                 bzero(conn_info->req_ie, sizeof(conn_info->req_ie));
10590         }
10591         if (conn_info->resp_ie_len) {
10592                 conn_info->resp_ie_len = 0;
10593                 bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie));
10594         }
10595         if (assoc_info.req_len) {
10596                 err = wldev_iovar_getbuf(ndev, "assoc_req_ies", NULL, 0, cfg->extra_buf,
10597                         WL_ASSOC_INFO_MAX, NULL);
10598                 if (unlikely(err)) {
10599                         WL_ERR(("could not get assoc req (%d)\n", err));
10600                         return err;
10601                 }
10602                 conn_info->req_ie_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
10603                 if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
10604                         conn_info->req_ie_len -= ETHER_ADDR_LEN;
10605                 }
10606                 if (conn_info->req_ie_len <= MAX_REQ_LINE)
10607                         memcpy(conn_info->req_ie, cfg->extra_buf, conn_info->req_ie_len);
10608                 else {
10609                         WL_ERR(("IE size %d above max %d size \n",
10610                                 conn_info->req_ie_len, MAX_REQ_LINE));
10611                         return err;
10612                 }
10613         } else {
10614                 conn_info->req_ie_len = 0;
10615         }
10616         if (assoc_info.resp_len) {
10617                 err = wldev_iovar_getbuf(ndev, "assoc_resp_ies", NULL, 0, cfg->extra_buf,
10618                         WL_ASSOC_INFO_MAX, NULL);
10619                 if (unlikely(err)) {
10620                         WL_ERR(("could not get assoc resp (%d)\n", err));
10621                         return err;
10622                 }
10623                 conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp);
10624                 if (conn_info->resp_ie_len <= MAX_REQ_LINE) {
10625                         memcpy(conn_info->resp_ie, cfg->extra_buf, conn_info->resp_ie_len);
10626                 } else {
10627                         WL_ERR(("IE size %d above max %d size \n",
10628                                 conn_info->resp_ie_len, MAX_REQ_LINE));
10629                         return err;
10630                 }
10631
10632 #ifdef QOS_MAP_SET
10633                 /* find qos map set ie */
10634                 if ((qos_map_ie = bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
10635                                 DOT11_MNG_QOS_MAP_ID)) != NULL) {
10636                         WL_DBG((" QoS map set IE found in assoc response\n"));
10637                         if (!cfg->up_table) {
10638                                 cfg->up_table = kmalloc(UP_TABLE_MAX, GFP_KERNEL);
10639                         }
10640                         wl_set_up_table(cfg->up_table, qos_map_ie);
10641                 } else {
10642                         kfree(cfg->up_table);
10643                         cfg->up_table = NULL;
10644                 }
10645 #endif /* QOS_MAP_SET */
10646         } else {
10647                 conn_info->resp_ie_len = 0;
10648         }
10649         WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
10650                 conn_info->resp_ie_len));
10651
10652         return err;
10653 }
10654
10655 static s32 wl_ch_to_chanspec(struct net_device *dev, int ch, struct wl_join_params *join_params,
10656         size_t *join_params_size)
10657 {
10658         struct bcm_cfg80211 *cfg;
10659         s32 bssidx = -1;
10660         chanspec_t chanspec = 0, chspec;
10661
10662         if (ch != 0) {
10663                 cfg = (struct bcm_cfg80211 *)wiphy_priv(dev->ieee80211_ptr->wiphy);
10664                 if (cfg && cfg->rcc_enabled) {
10665                 } else {
10666                         join_params->params.chanspec_num = 1;
10667                         join_params->params.chanspec_list[0] = ch;
10668
10669                         if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
10670                                 chanspec |= WL_CHANSPEC_BAND_2G;
10671                         else
10672                                 chanspec |= WL_CHANSPEC_BAND_5G;
10673
10674                         /* Get the min_bw set for the interface */
10675                         chspec = wl_cfg80211_ulb_get_min_bw_chspec(dev->ieee80211_ptr, bssidx);
10676                         if (chspec == INVCHANSPEC) {
10677                                 WL_ERR(("Invalid chanspec \n"));
10678                                 return -EINVAL;
10679                         }
10680                         chanspec |= chspec;
10681                         chanspec |= WL_CHANSPEC_CTL_SB_NONE;
10682
10683                         *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
10684                                 join_params->params.chanspec_num * sizeof(chanspec_t);
10685
10686                         join_params->params.chanspec_list[0]  &= WL_CHANSPEC_CHAN_MASK;
10687                         join_params->params.chanspec_list[0] |= chanspec;
10688                         join_params->params.chanspec_list[0] =
10689                                 wl_chspec_host_to_driver(join_params->params.chanspec_list[0]);
10690
10691                         join_params->params.chanspec_num =
10692                                 htod32(join_params->params.chanspec_num);
10693                 }
10694
10695                 WL_DBG(("join_params->params.chanspec_list[0]= %X, %d channels\n",
10696                         join_params->params.chanspec_list[0],
10697                         join_params->params.chanspec_num));
10698         }
10699         return 0;
10700 }
10701
10702 static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool roam)
10703 {
10704         struct wl_bss_info *bi;
10705         struct wlc_ssid *ssid;
10706         struct bcm_tlv *tim;
10707         s32 beacon_interval;
10708         s32 dtim_period;
10709         size_t ie_len;
10710         u8 *ie;
10711         u8 *curbssid;
10712         s32 err = 0;
10713         struct wiphy *wiphy;
10714         u32 channel;
10715
10716         wiphy = bcmcfg_to_wiphy(cfg);
10717
10718         ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
10719         curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10720
10721         mutex_lock(&cfg->usr_sync);
10722
10723         *(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
10724         err = wldev_ioctl(ndev, WLC_GET_BSS_INFO,
10725                 cfg->extra_buf, WL_EXTRA_BUF_MAX, false);
10726         if (unlikely(err)) {
10727                 WL_ERR(("Could not get bss info %d\n", err));
10728                 goto update_bss_info_out;
10729         }
10730         bi = (struct wl_bss_info *)(cfg->extra_buf + 4);
10731         channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
10732         wl_update_prof(cfg, ndev, NULL, &channel, WL_PROF_CHAN);
10733
10734         if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) {
10735                 WL_ERR(("Bssid doesn't match\n"));
10736                 err = -EIO;
10737                 goto update_bss_info_out;
10738         }
10739         err = wl_inform_single_bss(cfg, bi, roam);
10740         if (unlikely(err))
10741                 goto update_bss_info_out;
10742
10743         ie = ((u8 *)bi) + bi->ie_offset;
10744         ie_len = bi->ie_length;
10745         beacon_interval = cpu_to_le16(bi->beacon_period);
10746         tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
10747         if (tim) {
10748                 dtim_period = tim->data[1];
10749         } else {
10750                 /*
10751                 * active scan was done so we could not get dtim
10752                 * information out of probe response.
10753                 * so we speficially query dtim information.
10754                 */
10755                 err = wldev_ioctl(ndev, WLC_GET_DTIMPRD,
10756                         &dtim_period, sizeof(dtim_period), false);
10757                 if (unlikely(err)) {
10758                         WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
10759                         goto update_bss_info_out;
10760                 }
10761         }
10762
10763         wl_update_prof(cfg, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT);
10764         wl_update_prof(cfg, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
10765
10766 update_bss_info_out:
10767         if (unlikely(err)) {
10768                 WL_ERR(("Failed with error %d\n", err));
10769         }
10770         mutex_unlock(&cfg->usr_sync);
10771         return err;
10772 }
10773
10774 static s32
10775 wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
10776         const wl_event_msg_t *e, void *data)
10777 {
10778         struct wl_connect_info *conn_info = wl_to_conn(cfg);
10779         s32 err = 0;
10780         u8 *curbssid;
10781 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
10782         struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
10783         struct ieee80211_supported_band *band;
10784         struct ieee80211_channel *notify_channel = NULL;
10785         u32 *channel;
10786         u32 freq;
10787 #endif 
10788
10789
10790         if (memcmp(&cfg->last_roamed_addr, &e->addr, ETHER_ADDR_LEN) == 0) {
10791                 WL_INFORM(("BSSID already updated\n"));
10792                 return err;
10793         }
10794
10795         /* Skip calling cfg80211_roamed If current bssid and
10796          * roamed bssid are same. Also clear timer roam_timeout.
10797          */
10798         curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10799         if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) == 0) {
10800                 WL_ERR(("BSS already present, Skipping roamed event to upper layer\n"));
10801 #ifdef DHD_LOSSLESS_ROAMING
10802                 wl_del_roam_timeout(cfg);
10803 #endif  /* DHD_LOSSLESS_ROAMING */
10804                 return  err;
10805         }
10806
10807         wl_get_assoc_ies(cfg, ndev);
10808         wl_update_prof(cfg, ndev, NULL, (const void *)(e->addr.octet), WL_PROF_BSSID);
10809         curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10810         wl_update_bss_info(cfg, ndev, true);
10811         wl_update_pmklist(ndev, cfg->pmk_list, err);
10812
10813 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
10814         /* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */
10815         channel = (u32 *)wl_read_prof(cfg, ndev, WL_PROF_CHAN);
10816         if (*channel <= CH_MAX_2G_CHANNEL)
10817                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
10818         else
10819                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
10820         freq = ieee80211_channel_to_frequency(*channel, band->band);
10821         notify_channel = ieee80211_get_channel(wiphy, freq);
10822 #endif 
10823         printf("wl_bss_roaming_done succeeded to " MACDBG "\n",
10824                 MAC2STRDBG((const u8*)(&e->addr)));
10825         dhd_conf_set_wme(cfg->pub);
10826
10827         cfg80211_roamed(ndev,
10828 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
10829                 notify_channel,
10830 #endif
10831                 curbssid,
10832                 conn_info->req_ie, conn_info->req_ie_len,
10833                 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
10834         WL_DBG(("Report roaming result\n"));
10835
10836         memcpy(&cfg->last_roamed_addr, (void *)&e->addr, ETHER_ADDR_LEN);
10837         wl_set_drv_status(cfg, CONNECTED, ndev);
10838
10839 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
10840         cfg->roam_count++;
10841 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
10842
10843         return err;
10844 }
10845
10846 static s32
10847 wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
10848         const wl_event_msg_t *e, void *data, bool completed)
10849 {
10850         struct wl_connect_info *conn_info = wl_to_conn(cfg);
10851         struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
10852 #if defined(CUSTOM_SET_CPUCORE)
10853         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
10854 #endif 
10855         s32 err = 0;
10856         u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10857         if (!sec) {
10858                 WL_ERR(("sec is NULL\n"));
10859                 return -ENODEV;
10860         }
10861         WL_DBG((" enter\n"));
10862 #ifdef ESCAN_RESULT_PATCH
10863         if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
10864                 if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) {
10865                         WL_DBG((" Connected event of connected device e=%d s=%d, ignore it\n",
10866                                 ntoh32(e->event_type), ntoh32(e->status)));
10867                         return err;
10868                 }
10869         }
10870         if (memcmp(curbssid, broad_bssid, ETHER_ADDR_LEN) == 0 &&
10871                 memcmp(broad_bssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) {
10872                 WL_DBG(("copy bssid\n"));
10873                 memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN);
10874         }
10875
10876 #else
10877         if (cfg->scan_request) {
10878                 wl_notify_escan_complete(cfg, ndev, true, true);
10879         }
10880 #endif /* ESCAN_RESULT_PATCH */
10881         if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
10882                 wl_cfg80211_scan_abort(cfg);
10883                 wl_clr_drv_status(cfg, CONNECTING, ndev);
10884                 if (completed) {
10885                         wl_get_assoc_ies(cfg, ndev);
10886                         wl_update_prof(cfg, ndev, NULL, (const void *)(e->addr.octet),
10887                                 WL_PROF_BSSID);
10888                         curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10889                         wl_update_bss_info(cfg, ndev, false);
10890                         wl_update_pmklist(ndev, cfg->pmk_list, err);
10891                         wl_set_drv_status(cfg, CONNECTED, ndev);
10892                         if (ndev != bcmcfg_to_prmry_ndev(cfg)) {
10893 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
10894                                 init_completion(&cfg->iface_disable);
10895 #else
10896                                 /* reinitialize completion to clear previous count */
10897                                 INIT_COMPLETION(cfg->iface_disable);
10898 #endif
10899                         }
10900 #ifdef CUSTOM_SET_CPUCORE
10901                         if (wl_get_chan_isvht80(ndev, dhd)) {
10902                                 if (ndev == bcmcfg_to_prmry_ndev(cfg))
10903                                         dhd->chan_isvht80 |= DHD_FLAG_STA_MODE; /* STA mode */
10904                                 else if (is_p2p_group_iface(ndev->ieee80211_ptr))
10905                                         dhd->chan_isvht80 |= DHD_FLAG_P2P_MODE; /* p2p mode */
10906                                 dhd_set_cpucore(dhd, TRUE);
10907                         }
10908 #endif /* CUSTOM_SET_CPUCORE */
10909
10910                 }
10911                 cfg80211_connect_result(ndev,
10912                         curbssid,
10913                         conn_info->req_ie,
10914                         conn_info->req_ie_len,
10915                         conn_info->resp_ie,
10916                         conn_info->resp_ie_len,
10917                         completed ? WLAN_STATUS_SUCCESS :
10918                         (sec->auth_assoc_res_status) ?
10919                         sec->auth_assoc_res_status :
10920                         WLAN_STATUS_UNSPECIFIED_FAILURE,
10921                         GFP_KERNEL);
10922                 if (completed) {
10923                         WL_INFORM(("Report connect result - connection succeeded\n"));
10924                         dhd_conf_set_wme(cfg->pub);
10925                 } else
10926                         WL_ERR(("Report connect result - connection failed\n"));
10927         }
10928 #ifdef CONFIG_TCPACK_FASTTX
10929         if (wl_get_chan_isvht80(ndev, dhd))
10930                 wldev_iovar_setint(ndev, "tcpack_fast_tx", 0);
10931         else
10932                 wldev_iovar_setint(ndev, "tcpack_fast_tx", 1);
10933 #endif /* CONFIG_TCPACK_FASTTX */
10934
10935         return err;
10936 }
10937
10938 static s32
10939 wl_notify_mic_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10940         const wl_event_msg_t *e, void *data)
10941 {
10942         struct net_device *ndev = NULL;
10943         u16 flags = ntoh16(e->flags);
10944         enum nl80211_key_type key_type;
10945
10946         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10947
10948         mutex_lock(&cfg->usr_sync);
10949         if (flags & WLC_EVENT_MSG_GROUP)
10950                 key_type = NL80211_KEYTYPE_GROUP;
10951         else
10952                 key_type = NL80211_KEYTYPE_PAIRWISE;
10953
10954         cfg80211_michael_mic_failure(ndev, (const u8 *)&e->addr, key_type, -1,
10955                 NULL, GFP_KERNEL);
10956         mutex_unlock(&cfg->usr_sync);
10957
10958         return 0;
10959 }
10960
10961 #ifdef BT_WIFI_HANDOVER
10962 static s32
10963 wl_notify_bt_wifi_handover_req(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10964         const wl_event_msg_t *e, void *data)
10965 {
10966         struct net_device *ndev = NULL;
10967         u32 event = ntoh32(e->event_type);
10968         u32 datalen = ntoh32(e->datalen);
10969         s32 err;
10970
10971         WL_ERR(("wl_notify_bt_wifi_handover_req: event_type : %d, datalen : %d\n", event, datalen));
10972         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10973         err = wl_genl_send_msg(ndev, event, data, (u16)datalen, 0, 0);
10974
10975         return err;
10976 }
10977 #endif /* BT_WIFI_HANDOVER */
10978
10979 #ifdef PNO_SUPPORT
10980 static s32
10981 wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10982         const wl_event_msg_t *e, void *data)
10983 {
10984         struct net_device *ndev = NULL;
10985
10986         WL_ERR((">>> PNO Event\n"));
10987
10988         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10989
10990 #ifndef WL_SCHED_SCAN
10991         mutex_lock(&cfg->usr_sync);
10992         /* TODO: Use cfg80211_sched_scan_results(wiphy); */
10993         CFG80211_DISCONNECTED(ndev, 0, NULL, 0, false, GFP_KERNEL);
10994         mutex_unlock(&cfg->usr_sync);
10995 #else
10996         /* If cfg80211 scheduled scan is supported, report the pno results via sched
10997          * scan results
10998          */
10999         wl_notify_sched_scan_results(cfg, ndev, e, data);
11000 #endif /* WL_SCHED_SCAN */
11001         return 0;
11002 }
11003 #endif /* PNO_SUPPORT */
11004
11005 #ifdef GSCAN_SUPPORT
11006 static s32
11007 wl_notify_gscan_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
11008         const wl_event_msg_t *e, void *data)
11009 {
11010         s32 err = 0;
11011         u32 event = be32_to_cpu(e->event_type);
11012         void *ptr;
11013         int send_evt_bytes = 0;
11014         int batch_event_result_dummy = 0;
11015         struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
11016         struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
11017         u32 len = ntoh32(e->datalen);
11018
11019         switch (event) {
11020                 case WLC_E_PFN_SWC:
11021                         ptr = dhd_dev_swc_scan_event(ndev, data, &send_evt_bytes);
11022                         if (send_evt_bytes) {
11023                                 wl_cfgvendor_send_async_event(wiphy, ndev,
11024                                     GOOGLE_GSCAN_SIGNIFICANT_EVENT, ptr, send_evt_bytes);
11025                                 kfree(ptr);
11026                         }
11027                         break;
11028                 case WLC_E_PFN_BEST_BATCHING:
11029                         err = dhd_dev_retrieve_batch_scan(ndev);
11030                         if (err < 0) {
11031                                 WL_ERR(("Batch retrieval already in progress %d\n", err));
11032                         } else {
11033                                 wl_cfgvendor_send_async_event(wiphy, ndev,
11034                                     GOOGLE_GSCAN_BATCH_SCAN_EVENT,
11035                                      &batch_event_result_dummy, sizeof(int));
11036                         }
11037                         break;
11038                 case WLC_E_PFN_SCAN_COMPLETE:
11039                         batch_event_result_dummy = WIFI_SCAN_COMPLETE;
11040                         wl_cfgvendor_send_async_event(wiphy, ndev,
11041                                 GOOGLE_SCAN_COMPLETE_EVENT,
11042                                 &batch_event_result_dummy, sizeof(int));
11043                         break;
11044                 case WLC_E_PFN_BSSID_NET_FOUND:
11045                         ptr = dhd_dev_hotlist_scan_event(ndev, data, &send_evt_bytes,
11046                               HOTLIST_FOUND);
11047                         if (ptr) {
11048                                 wl_cfgvendor_send_hotlist_event(wiphy, ndev,
11049                                  ptr, send_evt_bytes, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT);
11050                                 dhd_dev_gscan_hotlist_cache_cleanup(ndev, HOTLIST_FOUND);
11051                         }
11052                         break;
11053                 case WLC_E_PFN_BSSID_NET_LOST:
11054                         /* WLC_E_PFN_BSSID_NET_LOST is conflict shared with WLC_E_PFN_SCAN_ALLGONE
11055                          * We currently do not use WLC_E_PFN_SCAN_ALLGONE, so if we get it, ignore
11056                          */
11057                         if (len) {
11058                                 ptr = dhd_dev_hotlist_scan_event(ndev, data, &send_evt_bytes,
11059                                             HOTLIST_LOST);
11060                                 if (ptr) {
11061                                         wl_cfgvendor_send_hotlist_event(wiphy, ndev,
11062                                          ptr, send_evt_bytes, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT);
11063                                         dhd_dev_gscan_hotlist_cache_cleanup(ndev, HOTLIST_LOST);
11064                                 }
11065                         }
11066                         break;
11067                 case WLC_E_PFN_GSCAN_FULL_RESULT:
11068                         ptr = dhd_dev_process_full_gscan_result(ndev, data, &send_evt_bytes);
11069                         if (ptr) {
11070                                 wl_cfgvendor_send_async_event(wiphy, ndev,
11071                                     GOOGLE_SCAN_FULL_RESULTS_EVENT, ptr, send_evt_bytes);
11072                                 kfree(ptr);
11073                         }
11074                         break;
11075                 default:
11076                         WL_ERR(("%s: Unexpected event! - %d\n", __FUNCTION__, event));
11077
11078         }
11079         return err;
11080 }
11081 #endif /* GSCAN_SUPPORT */
11082
11083 static s32
11084 wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
11085         const wl_event_msg_t *e, void *data)
11086 {
11087         struct channel_info channel_inform;
11088         struct wl_scan_results *bss_list;
11089         struct net_device *ndev = NULL;
11090         u32 len = WL_SCAN_BUF_MAX;
11091         s32 err = 0;
11092         unsigned long flags;
11093
11094         WL_DBG(("Enter \n"));
11095         if (!wl_get_drv_status(cfg, SCANNING, ndev)) {
11096                 WL_ERR(("scan is not ready \n"));
11097                 return err;
11098         }
11099         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
11100
11101         mutex_lock(&cfg->usr_sync);
11102         wl_clr_drv_status(cfg, SCANNING, ndev);
11103         err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
11104                 sizeof(channel_inform), false);
11105         if (unlikely(err)) {
11106                 WL_ERR(("scan busy (%d)\n", err));
11107                 goto scan_done_out;
11108         }
11109         channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
11110         if (unlikely(channel_inform.scan_channel)) {
11111
11112                 WL_DBG(("channel_inform.scan_channel (%d)\n",
11113                         channel_inform.scan_channel));
11114         }
11115         cfg->bss_list = cfg->scan_results;
11116         bss_list = cfg->bss_list;
11117         memset(bss_list, 0, len);
11118         bss_list->buflen = htod32(len);
11119         err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, false);
11120         if (unlikely(err) && unlikely(!cfg->scan_suppressed)) {
11121                 WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
11122                 err = -EINVAL;
11123                 goto scan_done_out;
11124         }
11125         bss_list->buflen = dtoh32(bss_list->buflen);
11126         bss_list->version = dtoh32(bss_list->version);
11127         bss_list->count = dtoh32(bss_list->count);
11128
11129         err = wl_inform_bss(cfg);
11130
11131 scan_done_out:
11132         del_timer_sync(&cfg->scan_timeout);
11133         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
11134         if (cfg->scan_request) {
11135                 cfg80211_scan_done(cfg->scan_request, false);
11136                 cfg->scan_request = NULL;
11137         }
11138         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
11139         WL_DBG(("cfg80211_scan_done\n"));
11140         mutex_unlock(&cfg->usr_sync);
11141         return err;
11142 }
11143
11144 static s32
11145 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
11146         const struct ether_addr *sa, const struct ether_addr *bssid,
11147         u8 **pheader, u32 *body_len, u8 *pbody)
11148 {
11149         struct dot11_management_header *hdr;
11150         u32 totlen = 0;
11151         s32 err = 0;
11152         u8 *offset;
11153         u32 prebody_len = *body_len;
11154         switch (fc) {
11155                 case FC_ASSOC_REQ:
11156                         /* capability , listen interval */
11157                         totlen = DOT11_ASSOC_REQ_FIXED_LEN;
11158                         *body_len += DOT11_ASSOC_REQ_FIXED_LEN;
11159                         break;
11160
11161                 case FC_REASSOC_REQ:
11162                         /* capability, listen inteval, ap address */
11163                         totlen = DOT11_REASSOC_REQ_FIXED_LEN;
11164                         *body_len += DOT11_REASSOC_REQ_FIXED_LEN;
11165                         break;
11166         }
11167         totlen += DOT11_MGMT_HDR_LEN + prebody_len;
11168         *pheader = kzalloc(totlen, GFP_KERNEL);
11169         if (*pheader == NULL) {
11170                 WL_ERR(("memory alloc failed \n"));
11171                 return -ENOMEM;
11172         }
11173         hdr = (struct dot11_management_header *) (*pheader);
11174         hdr->fc = htol16(fc);
11175         hdr->durid = 0;
11176         hdr->seq = 0;
11177         offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
11178         bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
11179         bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
11180         bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
11181         if ((pbody != NULL) && prebody_len)
11182                 bcopy((const char*)pbody, offset, prebody_len);
11183         *body_len = totlen;
11184         return err;
11185 }
11186
11187
11188 void
11189 wl_stop_wait_next_action_frame(struct bcm_cfg80211 *cfg, struct net_device *ndev)
11190 {
11191         if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
11192                 if (timer_pending(&cfg->p2p->listen_timer)) {
11193                         del_timer_sync(&cfg->p2p->listen_timer);
11194                 }
11195                 if (cfg->afx_hdl != NULL) {
11196                         if (cfg->afx_hdl->dev != NULL) {
11197                                 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
11198                                 wl_clr_drv_status(cfg, FINDING_COMMON_CHANNEL, cfg->afx_hdl->dev);
11199                         }
11200                         cfg->afx_hdl->peer_chan = WL_INVALID;
11201                 }
11202                 complete(&cfg->act_frm_scan);
11203                 WL_DBG(("*** Wake UP ** Working afx searching is cleared\n"));
11204         } else if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM)) {
11205                 if (!(wl_get_p2p_status(cfg, ACTION_TX_COMPLETED) ||
11206                         wl_get_p2p_status(cfg, ACTION_TX_NOACK)))
11207                         wl_set_p2p_status(cfg, ACTION_TX_COMPLETED);
11208
11209                 WL_DBG(("*** Wake UP ** abort actframe iovar\n"));
11210                 /* if channel is not zero, "actfame" uses off channel scan.
11211                  * So abort scan for off channel completion.
11212                  */
11213                 if (cfg->af_sent_channel)
11214                         wl_cfg80211_scan_abort(cfg);
11215         }
11216 #ifdef WL_CFG80211_SYNC_GON
11217         else if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
11218                 WL_DBG(("*** Wake UP ** abort listen for next af frame\n"));
11219                 /* So abort scan to cancel listen */
11220                 wl_cfg80211_scan_abort(cfg);
11221         }
11222 #endif /* WL_CFG80211_SYNC_GON */
11223 }
11224
11225 #if defined(WLTDLS)
11226 bool wl_cfg80211_is_tdls_tunneled_frame(void *frame, u32 frame_len)
11227 {
11228         unsigned char *data;
11229
11230         if (frame == NULL) {
11231                 WL_ERR(("Invalid frame \n"));
11232                 return false;
11233         }
11234
11235         if (frame_len < 5) {
11236                 WL_ERR(("Invalid frame length [%d] \n", frame_len));
11237                 return false;
11238         }
11239
11240         data = frame;
11241
11242         if (!memcmp(data, TDLS_TUNNELED_PRB_REQ, 5) ||
11243                 !memcmp(data, TDLS_TUNNELED_PRB_RESP, 5)) {
11244                 WL_DBG(("TDLS Vendor Specific Received type\n"));
11245                 return true;
11246         }
11247
11248         return false;
11249 }
11250 #endif /* WLTDLS */
11251
11252
11253 int wl_cfg80211_get_ioctl_version(void)
11254 {
11255         return ioctl_version;
11256 }
11257
11258 static s32
11259 wl_notify_rx_mgmt_frame(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
11260         const wl_event_msg_t *e, void *data)
11261 {
11262         struct ieee80211_supported_band *band;
11263         struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
11264         struct ether_addr da;
11265         struct ether_addr bssid;
11266         bool isfree = false;
11267         s32 err = 0;
11268         s32 freq;
11269         struct net_device *ndev = NULL;
11270         wifi_p2p_pub_act_frame_t *act_frm = NULL;
11271         wifi_p2p_action_frame_t *p2p_act_frm = NULL;
11272         wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
11273 #if defined(WLTDLS) && defined(TDLS_MSG_ONLY_WFD)
11274         dhd_pub_t *dhdp;
11275 #endif /* WLTDLS && TDLS_MSG_ONLY_WFD */
11276         wl_event_rx_frame_data_t *rxframe =
11277                 (wl_event_rx_frame_data_t*)data;
11278         u32 event = ntoh32(e->event_type);
11279         u8 *mgmt_frame;
11280         u8 bsscfgidx = e->bsscfgidx;
11281         u32 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t);
11282         u16 channel = ((ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK));
11283
11284         memset(&bssid, 0, ETHER_ADDR_LEN);
11285
11286         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
11287
11288         if (channel <= CH_MAX_2G_CHANNEL)
11289                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
11290         else
11291                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
11292         if (!band) {
11293                 WL_ERR(("No valid band\n"));
11294                 return -EINVAL;
11295         }
11296 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
11297         freq = ieee80211_channel_to_frequency(channel);
11298         (void)band->band;
11299 #else
11300         freq = ieee80211_channel_to_frequency(channel, band->band);
11301 #endif
11302         if (event == WLC_E_ACTION_FRAME_RX) {
11303                 wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
11304                         NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &cfg->ioctl_buf_sync);
11305
11306                 err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
11307                 if (err < 0)
11308                          WL_ERR(("WLC_GET_BSSID error %d\n", err));
11309                 memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
11310                 err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid,
11311                         &mgmt_frame, &mgmt_frame_len,
11312                         (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1));
11313                 if (err < 0) {
11314                         WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n",
11315                                 mgmt_frame_len, channel, freq));
11316                         goto exit;
11317                 }
11318                 isfree = true;
11319                 if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11320                         mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
11321                         act_frm = (wifi_p2p_pub_act_frame_t *)
11322                                         (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
11323                 } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11324                         mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
11325                         p2p_act_frm = (wifi_p2p_action_frame_t *)
11326                                         (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
11327                         (void) p2p_act_frm;
11328                 } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11329                         mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
11330
11331                         sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)
11332                                         (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
11333                         if (sd_act_frm && wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
11334                                 if (cfg->next_af_subtype == sd_act_frm->action) {
11335                                         WL_DBG(("We got a right next frame of SD!(%d)\n",
11336                                                 sd_act_frm->action));
11337                                         wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
11338
11339                                         /* Stop waiting for next AF. */
11340                                         wl_stop_wait_next_action_frame(cfg, ndev);
11341                                 }
11342                         }
11343                         (void) sd_act_frm;
11344 #ifdef WLTDLS
11345                 } else if ((mgmt_frame[DOT11_MGMT_HDR_LEN] == TDLS_AF_CATEGORY) ||
11346                                 (wl_cfg80211_is_tdls_tunneled_frame(
11347                                     &mgmt_frame[DOT11_MGMT_HDR_LEN],
11348                                     mgmt_frame_len - DOT11_MGMT_HDR_LEN))) {
11349                         if (mgmt_frame[DOT11_MGMT_HDR_LEN] == TDLS_AF_CATEGORY) {
11350                                 WL_ERR((" TDLS Action Frame Received type = %d \n",
11351                                         mgmt_frame[DOT11_MGMT_HDR_LEN + 1]));
11352                         }
11353 #ifdef TDLS_MSG_ONLY_WFD
11354                         dhdp = (dhd_pub_t *)(cfg->pub);
11355                         if (!dhdp->tdls_mode) {
11356                                 WL_DBG((" TDLS Frame filtered \n"));
11357                                 return 0;
11358                         }
11359 #else
11360                         if (mgmt_frame[DOT11_MGMT_HDR_LEN + 1] == TDLS_ACTION_SETUP_RESP) {
11361                                 cfg->tdls_mgmt_frame = mgmt_frame;
11362                                 cfg->tdls_mgmt_frame_len = mgmt_frame_len;
11363                                 cfg->tdls_mgmt_freq = freq;
11364                                 return 0;
11365                         }
11366 #endif /* TDLS_MSG_ONLY_WFD */
11367 #endif /* WLTDLS */
11368 #ifdef QOS_MAP_SET
11369                 } else if (mgmt_frame[DOT11_MGMT_HDR_LEN] == DOT11_ACTION_CAT_QOS) {
11370                         /* update QoS map set table */
11371                         bcm_tlv_t * qos_map_ie = NULL;
11372                         if ((qos_map_ie = bcm_parse_tlvs(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11373                                         mgmt_frame_len - DOT11_MGMT_HDR_LEN,
11374                                         DOT11_MNG_QOS_MAP_ID)) != NULL) {
11375                                 WL_DBG((" QoS map set IE found in QoS action frame\n"));
11376                                 if (!cfg->up_table) {
11377                                         cfg->up_table = kmalloc(UP_TABLE_MAX, GFP_KERNEL);
11378                                 }
11379                                 wl_set_up_table(cfg->up_table, qos_map_ie);
11380                         } else {
11381                                 kfree(cfg->up_table);
11382                                 cfg->up_table = NULL;
11383                         }
11384 #endif /* QOS_MAP_SET */
11385                 } else {
11386                         /*
11387                          *  if we got normal action frame and ndev is p2p0,
11388                          *  we have to change ndev from p2p0 to wlan0
11389                          */
11390
11391
11392                         if (cfg->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
11393                                 u8 action = 0;
11394                                 if (wl_get_public_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11395                                         mgmt_frame_len - DOT11_MGMT_HDR_LEN, &action) != BCME_OK) {
11396                                         WL_DBG(("Recived action is not public action frame\n"));
11397                                 } else if (cfg->next_af_subtype == action) {
11398                                         WL_DBG(("Recived action is the waiting action(%d)\n",
11399                                                 action));
11400                                         wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
11401
11402                                         /* Stop waiting for next AF. */
11403                                         wl_stop_wait_next_action_frame(cfg, ndev);
11404                                 }
11405                         }
11406                 }
11407
11408                 if (act_frm) {
11409
11410                         if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
11411                                 if (cfg->next_af_subtype == act_frm->subtype) {
11412                                         WL_DBG(("We got a right next frame!(%d)\n",
11413                                                 act_frm->subtype));
11414                                         wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
11415
11416                                         if (cfg->next_af_subtype == P2P_PAF_GON_CONF) {
11417                                                 OSL_SLEEP(20);
11418                                         }
11419
11420                                         /* Stop waiting for next AF. */
11421                                         wl_stop_wait_next_action_frame(cfg, ndev);
11422                                 }
11423                         }
11424                 }
11425
11426                 wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN],
11427                         mgmt_frame_len - DOT11_MGMT_HDR_LEN, channel);
11428                 /*
11429                  * After complete GO Negotiation, roll back to mpc mode
11430                  */
11431                 if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) ||
11432                         (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
11433                         wldev_iovar_setint(ndev, "mpc", 1);
11434                 }
11435                 if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) {
11436                         WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
11437                         wl_clr_p2p_status(cfg, GO_NEG_PHASE);
11438                 }
11439         } else if (event == WLC_E_PROBREQ_MSG) {
11440
11441                 /* Handle probe reqs frame
11442                  * WPS-AP certification 4.2.13
11443                  */
11444                 struct parsed_ies prbreq_ies;
11445                 u32 prbreq_ie_len = 0;
11446                 bool pbc = 0;
11447
11448                 WL_DBG((" Event WLC_E_PROBREQ_MSG received\n"));
11449                 mgmt_frame = (u8 *)(data);
11450                 mgmt_frame_len = ntoh32(e->datalen);
11451
11452                 prbreq_ie_len = mgmt_frame_len - DOT11_MGMT_HDR_LEN;
11453
11454                 /* Parse prob_req IEs */
11455                 if (wl_cfg80211_parse_ies(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11456                         prbreq_ie_len, &prbreq_ies) < 0) {
11457                         WL_ERR(("Prob req get IEs failed\n"));
11458                         return 0;
11459                 }
11460                 if (prbreq_ies.wps_ie != NULL) {
11461                         wl_validate_wps_ie((char *)prbreq_ies.wps_ie, prbreq_ies.wps_ie_len, &pbc);
11462                         WL_DBG((" wps_ie exist pbc = %d\n", pbc));
11463                         /* if pbc method, send prob_req mgmt frame to upper layer */
11464                         if (!pbc)
11465                                 return 0;
11466                 } else
11467                         return 0;
11468         } else {
11469                 mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
11470
11471                 /* wpa supplicant use probe request event for restarting another GON Req.
11472                  * but it makes GON Req repetition.
11473                  * so if src addr of prb req is same as my target device,
11474                  * do not send probe request event during sending action frame.
11475                  */
11476                 if (event == WLC_E_P2P_PROBREQ_MSG) {
11477                         WL_DBG((" Event %s\n", (event == WLC_E_P2P_PROBREQ_MSG) ?
11478                                 "WLC_E_P2P_PROBREQ_MSG":"WLC_E_PROBREQ_MSG"));
11479
11480
11481                         /* Filter any P2P probe reqs arriving during the
11482                          * GO-NEG Phase
11483                          */
11484                         if (cfg->p2p &&
11485 #if defined(P2P_IE_MISSING_FIX)
11486                                 cfg->p2p_prb_noti &&
11487 #endif
11488                                 wl_get_p2p_status(cfg, GO_NEG_PHASE)) {
11489                                 WL_DBG(("Filtering P2P probe_req while "
11490                                         "being in GO-Neg state\n"));
11491                                 return 0;
11492                         }
11493                 }
11494         }
11495
11496         if (discover_cfgdev(cfgdev, cfg))
11497                 WL_DBG(("Rx Managment frame For P2P Discovery Interface \n"));
11498         else
11499                 WL_DBG(("Rx Managment frame For Iface (%s) \n", ndev->name));
11500
11501 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
11502         cfg80211_rx_mgmt(cfgdev, freq, 0,  mgmt_frame, mgmt_frame_len, 0);
11503 #elif(LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
11504         cfg80211_rx_mgmt(cfgdev, freq, 0,  mgmt_frame, mgmt_frame_len, 0, GFP_ATOMIC);
11505 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
11506         defined(WL_COMPAT_WIRELESS)
11507         cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
11508 #else
11509         cfg80211_rx_mgmt(cfgdev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
11510 #endif /* LINUX_VERSION >= VERSION(3, 14, 0) */
11511
11512         WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n",
11513                 mgmt_frame_len, ntoh32(e->datalen), channel, freq));
11514 exit:
11515         if (isfree)
11516                 kfree(mgmt_frame);
11517         return 0;
11518 }
11519
11520 #ifdef WL_SCHED_SCAN
11521 /* If target scan is not reliable, set the below define to "1" to do a
11522  * full escan
11523  */
11524 #define FULL_ESCAN_ON_PFN_NET_FOUND             0
11525 static s32
11526 wl_notify_sched_scan_results(struct bcm_cfg80211 *cfg, struct net_device *ndev,
11527         const wl_event_msg_t *e, void *data)
11528 {
11529         wl_pfn_net_info_t *netinfo, *pnetinfo;
11530         struct wiphy *wiphy     = bcmcfg_to_wiphy(cfg);
11531         int err = 0;
11532         struct cfg80211_scan_request *request = NULL;
11533         struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
11534         struct ieee80211_channel *channel = NULL;
11535         int channel_req = 0;
11536         int band = 0;
11537         struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data;
11538         int n_pfn_results = pfn_result->count;
11539
11540         WL_DBG(("Enter\n"));
11541
11542         if (e->event_type == WLC_E_PFN_NET_LOST) {
11543                 WL_PNO(("PFN NET LOST event. Do Nothing \n"));
11544                 return 0;
11545         }
11546         WL_PNO((">>> PFN NET FOUND event. count:%d \n", n_pfn_results));
11547         if (n_pfn_results > 0) {
11548                 int i;
11549
11550                 if (n_pfn_results > MAX_PFN_LIST_COUNT)
11551                         n_pfn_results = MAX_PFN_LIST_COUNT;
11552                 pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t)
11553                                 - sizeof(wl_pfn_net_info_t));
11554
11555                 memset(&ssid, 0x00, sizeof(ssid));
11556
11557                 request = kzalloc(sizeof(*request)
11558                         + sizeof(*request->channels) * n_pfn_results,
11559                         GFP_KERNEL);
11560                 channel = (struct ieee80211_channel *)kzalloc(
11561                         (sizeof(struct ieee80211_channel) * n_pfn_results),
11562                         GFP_KERNEL);
11563                 if (!request || !channel) {
11564                         WL_ERR(("No memory"));
11565                         err = -ENOMEM;
11566                         goto out_err;
11567                 }
11568
11569                 request->wiphy = wiphy;
11570
11571                 for (i = 0; i < n_pfn_results; i++) {
11572                         netinfo = &pnetinfo[i];
11573                         if (!netinfo) {
11574                                 WL_ERR(("Invalid netinfo ptr. index:%d", i));
11575                                 err = -EINVAL;
11576                                 goto out_err;
11577                         }
11578                         WL_PNO((">>> SSID:%s Channel:%d \n",
11579                                 netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel));
11580                         /* PFN result doesn't have all the info which are required by the supplicant
11581                          * (For e.g IEs) Do a target Escan so that sched scan results are reported
11582                          * via wl_inform_single_bss in the required format. Escan does require the
11583                          * scan request in the form of cfg80211_scan_request. For timebeing, create
11584                          * cfg80211_scan_request one out of the received PNO event.
11585                          */
11586                         memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID,
11587                                 netinfo->pfnsubnet.SSID_len);
11588                         ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len;
11589                         request->n_ssids++;
11590
11591                         channel_req = netinfo->pfnsubnet.channel;
11592                         band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
11593                                 : NL80211_BAND_5GHZ;
11594                         channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band);
11595                         channel[i].band = band;
11596                         channel[i].flags |= IEEE80211_CHAN_NO_HT40;
11597                         request->channels[i] = &channel[i];
11598                         request->n_channels++;
11599                 }
11600
11601                 /* assign parsed ssid array */
11602                 if (request->n_ssids)
11603                         request->ssids = &ssid[0];
11604
11605                 if (wl_get_drv_status_all(cfg, SCANNING)) {
11606                         /* Abort any on-going scan */
11607                         wl_notify_escan_complete(cfg, ndev, true, true);
11608                 }
11609
11610                 if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
11611                         WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
11612                         err = wl_cfgp2p_discover_enable_search(cfg, false);
11613                         if (unlikely(err)) {
11614                                 wl_clr_drv_status(cfg, SCANNING, ndev);
11615                                 goto out_err;
11616                         }
11617                         p2p_scan(cfg) = false;
11618                 }
11619
11620                 wl_set_drv_status(cfg, SCANNING, ndev);
11621 #if FULL_ESCAN_ON_PFN_NET_FOUND
11622                 WL_PNO((">>> Doing Full ESCAN on PNO event\n"));
11623                 err = wl_do_escan(cfg, wiphy, ndev, NULL);
11624 #else
11625                 WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
11626                 err = wl_do_escan(cfg, wiphy, ndev, request);
11627 #endif
11628                 if (err) {
11629                         wl_clr_drv_status(cfg, SCANNING, ndev);
11630                         goto out_err;
11631                 }
11632                 cfg->sched_scan_running = TRUE;
11633         }
11634         else {
11635                 WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
11636         }
11637 out_err:
11638         if (request)
11639                 kfree(request);
11640         if (channel)
11641                 kfree(channel);
11642         return err;
11643 }
11644 #endif /* WL_SCHED_SCAN */
11645
11646 static void wl_init_conf(struct wl_conf *conf)
11647 {
11648         WL_DBG(("Enter \n"));
11649         conf->frag_threshold = (u32)-1;
11650         conf->rts_threshold = (u32)-1;
11651         conf->retry_short = (u32)-1;
11652         conf->retry_long = (u32)-1;
11653         conf->tx_power = -1;
11654 }
11655
11656 static void wl_init_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev)
11657 {
11658         unsigned long flags;
11659         struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
11660
11661         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
11662         memset(profile, 0, sizeof(struct wl_profile));
11663         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
11664 }
11665
11666 static void wl_init_event_handler(struct bcm_cfg80211 *cfg)
11667 {
11668         memset(cfg->evt_handler, 0, sizeof(cfg->evt_handler));
11669
11670         cfg->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
11671         cfg->evt_handler[WLC_E_AUTH] = wl_notify_connect_status;
11672         cfg->evt_handler[WLC_E_ASSOC] = wl_notify_connect_status;
11673         cfg->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
11674         cfg->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
11675         cfg->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
11676         cfg->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
11677         cfg->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
11678         cfg->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
11679         cfg->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;
11680         cfg->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
11681         cfg->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;
11682         cfg->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;
11683         cfg->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
11684         cfg->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
11685         cfg->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
11686         cfg->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
11687         cfg->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
11688         cfg->evt_handler[WLC_E_JOIN] = wl_notify_connect_status;
11689         cfg->evt_handler[WLC_E_START] = wl_notify_connect_status;
11690 #ifdef PNO_SUPPORT
11691         cfg->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status;
11692 #endif /* PNO_SUPPORT */
11693 #ifdef GSCAN_SUPPORT
11694         cfg->evt_handler[WLC_E_PFN_BEST_BATCHING] = wl_notify_gscan_event;
11695         cfg->evt_handler[WLC_E_PFN_SCAN_COMPLETE] = wl_notify_gscan_event;
11696         cfg->evt_handler[WLC_E_PFN_GSCAN_FULL_RESULT] = wl_notify_gscan_event;
11697         cfg->evt_handler[WLC_E_PFN_SWC] = wl_notify_gscan_event;
11698         cfg->evt_handler[WLC_E_PFN_BSSID_NET_FOUND] = wl_notify_gscan_event;
11699         cfg->evt_handler[WLC_E_PFN_BSSID_NET_LOST] = wl_notify_gscan_event;
11700 #endif /* GSCAN_SUPPORT */
11701 #ifdef WLTDLS
11702         cfg->evt_handler[WLC_E_TDLS_PEER_EVENT] = wl_tdls_event_handler;
11703 #endif /* WLTDLS */
11704         cfg->evt_handler[WLC_E_BSSID] = wl_notify_roaming_status;
11705 #ifdef  WL_RELMCAST
11706         cfg->evt_handler[WLC_E_RMC_EVENT] = wl_notify_rmc_status;
11707 #endif
11708 #ifdef BT_WIFI_HANDOVER
11709         cfg->evt_handler[WLC_E_BT_WIFI_HANDOVER_REQ] = wl_notify_bt_wifi_handover_req;
11710 #endif
11711 #ifdef WL_NAN
11712         cfg->evt_handler[WLC_E_NAN] = wl_cfgnan_notify_nan_status;
11713         cfg->evt_handler[WLC_E_PROXD] = wl_cfgnan_notify_proxd_status;
11714 #endif /* WL_NAN */
11715         cfg->evt_handler[WLC_E_CSA_COMPLETE_IND] = wl_csa_complete_ind;
11716 #ifdef DHD_LOSSLESS_ROAMING
11717         cfg->evt_handler[WLC_E_ROAM_PREP] = wl_notify_roam_prep_status;
11718 #endif
11719         cfg->evt_handler[WLC_E_AP_STARTED] = wl_ap_start_ind;
11720 #ifdef CUSTOM_EVENT_PM_WAKE
11721         cfg->evt_handler[WLC_E_EXCESS_PM_WAKE_EVENT] = wl_check_pmstatus;
11722 #endif /* CUSTOM_EVENT_PM_WAKE */
11723         cfg->evt_handler[WLC_E_PSK_SUP] = wl_notify_idsup_status;
11724 }
11725
11726 #if defined(STATIC_WL_PRIV_STRUCT)
11727 static void
11728 wl_init_escan_result_buf(struct bcm_cfg80211 *cfg)
11729 {
11730         cfg->escan_info.escan_buf = DHD_OS_PREALLOC(cfg->pub,
11731                 DHD_PREALLOC_WIPHY_ESCAN0, ESCAN_BUF_SIZE);
11732         bzero(cfg->escan_info.escan_buf, ESCAN_BUF_SIZE);
11733 }
11734
11735 static void
11736 wl_deinit_escan_result_buf(struct bcm_cfg80211 *cfg)
11737 {
11738         cfg->escan_info.escan_buf = NULL;
11739
11740 }
11741 #endif /* STATIC_WL_PRIV_STRUCT */
11742
11743 static s32 wl_init_priv_mem(struct bcm_cfg80211 *cfg)
11744 {
11745         WL_DBG(("Enter \n"));
11746
11747         cfg->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
11748         if (unlikely(!cfg->scan_results)) {
11749                 WL_ERR(("Scan results alloc failed\n"));
11750                 goto init_priv_mem_out;
11751         }
11752         cfg->conf = (void *)kzalloc(sizeof(*cfg->conf), GFP_KERNEL);
11753         if (unlikely(!cfg->conf)) {
11754                 WL_ERR(("wl_conf alloc failed\n"));
11755                 goto init_priv_mem_out;
11756         }
11757         cfg->scan_req_int =
11758             (void *)kzalloc(sizeof(*cfg->scan_req_int), GFP_KERNEL);
11759         if (unlikely(!cfg->scan_req_int)) {
11760                 WL_ERR(("Scan req alloc failed\n"));
11761                 goto init_priv_mem_out;
11762         }
11763         cfg->ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
11764         if (unlikely(!cfg->ioctl_buf)) {
11765                 WL_ERR(("Ioctl buf alloc failed\n"));
11766                 goto init_priv_mem_out;
11767         }
11768         cfg->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
11769         if (unlikely(!cfg->escan_ioctl_buf)) {
11770                 WL_ERR(("Ioctl buf alloc failed\n"));
11771                 goto init_priv_mem_out;
11772         }
11773         cfg->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
11774         if (unlikely(!cfg->extra_buf)) {
11775                 WL_ERR(("Extra buf alloc failed\n"));
11776                 goto init_priv_mem_out;
11777         }
11778         cfg->pmk_list = (void *)kzalloc(sizeof(*cfg->pmk_list), GFP_KERNEL);
11779         if (unlikely(!cfg->pmk_list)) {
11780                 WL_ERR(("pmk list alloc failed\n"));
11781                 goto init_priv_mem_out;
11782         }
11783 #if defined(STATIC_WL_PRIV_STRUCT)
11784         cfg->conn_info = (void *)kzalloc(sizeof(*cfg->conn_info), GFP_KERNEL);
11785         if (unlikely(!cfg->conn_info)) {
11786                 WL_ERR(("cfg->conn_info  alloc failed\n"));
11787                 goto init_priv_mem_out;
11788         }
11789         cfg->ie = (void *)kzalloc(sizeof(*cfg->ie), GFP_KERNEL);
11790         if (unlikely(!cfg->ie)) {
11791                 WL_ERR(("cfg->ie  alloc failed\n"));
11792                 goto init_priv_mem_out;
11793         }
11794         wl_init_escan_result_buf(cfg);
11795 #endif /* STATIC_WL_PRIV_STRUCT */
11796         cfg->afx_hdl = (void *)kzalloc(sizeof(*cfg->afx_hdl), GFP_KERNEL);
11797         if (unlikely(!cfg->afx_hdl)) {
11798                 WL_ERR(("afx hdl  alloc failed\n"));
11799                 goto init_priv_mem_out;
11800         } else {
11801                 init_completion(&cfg->act_frm_scan);
11802                 init_completion(&cfg->wait_next_af);
11803
11804                 INIT_WORK(&cfg->afx_hdl->work, wl_cfg80211_afx_handler);
11805         }
11806 #ifdef WLTDLS
11807         if (cfg->tdls_mgmt_frame) {
11808                 kfree(cfg->tdls_mgmt_frame);
11809                 cfg->tdls_mgmt_frame = NULL;
11810         }
11811 #endif /* WLTDLS */
11812         return 0;
11813
11814 init_priv_mem_out:
11815         wl_deinit_priv_mem(cfg);
11816
11817         return -ENOMEM;
11818 }
11819
11820 static void wl_deinit_priv_mem(struct bcm_cfg80211 *cfg)
11821 {
11822         kfree(cfg->scan_results);
11823         cfg->scan_results = NULL;
11824         kfree(cfg->conf);
11825         cfg->conf = NULL;
11826         kfree(cfg->scan_req_int);
11827         cfg->scan_req_int = NULL;
11828         kfree(cfg->ioctl_buf);
11829         cfg->ioctl_buf = NULL;
11830         kfree(cfg->escan_ioctl_buf);
11831         cfg->escan_ioctl_buf = NULL;
11832         kfree(cfg->extra_buf);
11833         cfg->extra_buf = NULL;
11834         kfree(cfg->pmk_list);
11835         cfg->pmk_list = NULL;
11836 #if defined(STATIC_WL_PRIV_STRUCT)
11837         kfree(cfg->conn_info);
11838         cfg->conn_info = NULL;
11839         kfree(cfg->ie);
11840         cfg->ie = NULL;
11841         wl_deinit_escan_result_buf(cfg);
11842 #endif /* STATIC_WL_PRIV_STRUCT */
11843         if (cfg->afx_hdl) {
11844                 cancel_work_sync(&cfg->afx_hdl->work);
11845                 kfree(cfg->afx_hdl);
11846                 cfg->afx_hdl = NULL;
11847         }
11848
11849 }
11850
11851 static s32 wl_create_event_handler(struct bcm_cfg80211 *cfg)
11852 {
11853         int ret = 0;
11854         WL_DBG(("Enter \n"));
11855
11856         /* Do not use DHD in cfg driver */
11857         cfg->event_tsk.thr_pid = -1;
11858
11859         PROC_START(wl_event_handler, cfg, &cfg->event_tsk, 0, "wl_event_handler");
11860         if (cfg->event_tsk.thr_pid < 0)
11861                 ret = -ENOMEM;
11862         return ret;
11863 }
11864
11865 static void wl_destroy_event_handler(struct bcm_cfg80211 *cfg)
11866 {
11867         if (cfg->event_tsk.thr_pid >= 0)
11868                 PROC_STOP(&cfg->event_tsk);
11869 }
11870
11871 void wl_terminate_event_handler(void)
11872 {
11873         struct bcm_cfg80211 *cfg = g_bcm_cfg;
11874
11875         if (cfg) {
11876                 wl_destroy_event_handler(cfg);
11877                 wl_flush_eq(cfg);
11878         }
11879 }
11880
11881 static void wl_scan_timeout(unsigned long data)
11882 {
11883         wl_event_msg_t msg;
11884         struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
11885         struct wireless_dev *wdev = NULL;
11886         struct net_device *ndev = NULL;
11887         struct wl_scan_results *bss_list;
11888         struct wl_bss_info *bi = NULL;
11889         s32 i;
11890         u32 channel;
11891 #if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
11892         dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
11893         uint32 prev_memdump_mode = dhdp->memdump_enabled;
11894 #endif /* DHD_DEBUG && BCMPCIE */
11895
11896         if (!(cfg->scan_request)) {
11897                 WL_ERR(("timer expired but no scan request\n"));
11898                 return;
11899         }
11900
11901         bss_list = wl_escan_get_buf(cfg, FALSE);
11902         if (!bss_list) {
11903                 WL_ERR(("bss_list is null. Didn't receive any partial scan results\n"));
11904         } else {
11905                 WL_ERR(("scanned AP count (%d)\n", bss_list->count));
11906
11907                 bi = next_bss(bss_list, bi);
11908                 for_each_bss(bss_list, bi, i) {
11909                         channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
11910                         WL_ERR(("SSID :%s  Channel :%d\n", bi->SSID, channel));
11911                 }
11912         }
11913
11914 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
11915         if (cfg->scan_request->dev)
11916                 wdev = cfg->scan_request->dev->ieee80211_ptr;
11917 #else
11918         wdev = cfg->scan_request->wdev;
11919 #endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
11920         if (!wdev) {
11921                 WL_ERR(("No wireless_dev present\n"));
11922                 return;
11923         }
11924         ndev = wdev_to_wlc_ndev(wdev, cfg);
11925
11926         bzero(&msg, sizeof(wl_event_msg_t));
11927         WL_ERR(("timer expired\n"));
11928 #if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
11929         if (dhdp->memdump_enabled) {
11930                 dhdp->memdump_enabled = DUMP_MEMFILE;
11931                 dhdp->memdump_type = DUMP_TYPE_SCAN_TIMEOUT;
11932                 dhd_bus_mem_dump(dhdp);
11933                 dhdp->memdump_enabled = prev_memdump_mode;
11934         }
11935 #endif /* DHD_DEBUG && BCMPCIE */
11936         msg.event_type = hton32(WLC_E_ESCAN_RESULT);
11937         msg.status = hton32(WLC_E_STATUS_TIMEOUT);
11938         msg.reason = 0xFFFFFFFF;
11939         wl_cfg80211_event(ndev, &msg, NULL);
11940 #ifdef CUSTOMER_HW4_DEBUG
11941         if (!wl_scan_timeout_dbg_enabled)
11942                 wl_scan_timeout_dbg_set();
11943 #endif /* CUSTOMER_HW4_DEBUG */
11944
11945         // terence 20130729: workaround to fix out of memory in firmware
11946 //      if (dhd_conf_get_chip(dhd_get_pub(dev)) == BCM43362_CHIP_ID) {
11947 //              WL_ERR(("Send hang event\n"));
11948 //              net_os_send_hang_message(dev);
11949 //      }
11950 }
11951
11952 #ifdef DHD_LOSSLESS_ROAMING
11953 static void wl_del_roam_timeout(struct bcm_cfg80211 *cfg)
11954 {
11955         dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
11956
11957         /* restore prec_map to ALLPRIO */
11958         dhdp->dequeue_prec_map = ALLPRIO;
11959         if (timer_pending(&cfg->roam_timeout)) {
11960                 del_timer_sync(&cfg->roam_timeout);
11961         }
11962
11963 }
11964
11965 static void wl_roam_timeout(unsigned long data)
11966 {
11967         struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
11968         dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
11969
11970         WL_ERR(("roam timer expired\n"));
11971
11972         /* restore prec_map to ALLPRIO */
11973         dhdp->dequeue_prec_map = ALLPRIO;
11974 }
11975
11976 #endif /* DHD_LOSSLESS_ROAMING */
11977
11978 static s32
11979 wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
11980         unsigned long state, void *ptr)
11981 {
11982 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
11983         struct net_device *dev = ptr;
11984 #else
11985         struct net_device *dev = netdev_notifier_info_to_dev(ptr);
11986 #endif /* LINUX_VERSION < VERSION(3, 11, 0) */
11987         struct wireless_dev *wdev = ndev_to_wdev(dev);
11988         struct bcm_cfg80211 *cfg = g_bcm_cfg;
11989
11990 #ifdef DHD_IFDEBUG
11991         WL_ERR(("Enter \n"));
11992 #endif
11993
11994         if (!wdev || !cfg || dev == bcmcfg_to_prmry_ndev(cfg))
11995                 return NOTIFY_DONE;
11996
11997         switch (state) {
11998                 case NETDEV_DOWN:
11999                 {
12000 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
12001                         int max_wait_timeout = 2;
12002                         int max_wait_count = 100;
12003                         int refcnt = 0;
12004                         unsigned long limit = jiffies + max_wait_timeout * HZ;
12005 #ifdef DHD_IFDEBUG
12006                         WL_ERR(("NETDEV_DOWN(+) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12007 #endif
12008                         while (work_pending(&wdev->cleanup_work)) {
12009                                 if (refcnt%5 == 0) {
12010                                         WL_ERR(("[NETDEV_DOWN] wait for "
12011                                                 "complete of cleanup_work"
12012                                                 " (%d th)\n", refcnt));
12013                                 }
12014                                 if (!time_before(jiffies, limit)) {
12015                                         WL_ERR(("[NETDEV_DOWN] cleanup_work"
12016                                                 " of CFG80211 is not"
12017                                                 " completed in %d sec\n",
12018                                                 max_wait_timeout));
12019                                         break;
12020                                 }
12021                                 if (refcnt >= max_wait_count) {
12022                                         WL_ERR(("[NETDEV_DOWN] cleanup_work"
12023                                                 " of CFG80211 is not"
12024                                                 " completed in %d loop\n",
12025                                                 max_wait_count));
12026                                         break;
12027                                 }
12028                                 set_current_state(TASK_INTERRUPTIBLE);
12029                                 (void)schedule_timeout(100);
12030                                 set_current_state(TASK_RUNNING);
12031                                 refcnt++;
12032                         }
12033 #ifdef DHD_IFDEBUG
12034                         WL_ERR(("NETDEV_DOWN(-) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12035 #endif
12036 #endif /* LINUX_VERSION < VERSION(3, 14, 0) */
12037                         break;
12038                 }
12039                 case NETDEV_UNREGISTER:
12040 #ifdef DHD_IFDEBUG
12041                         WL_ERR(("NETDEV_UNREGISTER(+) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12042 #endif
12043                         /* after calling list_del_rcu(&wdev->list) */
12044                         wl_cfg80211_clear_per_bss_ies(cfg,
12045                                 wl_get_bssidx_by_wdev(cfg, wdev));
12046                         wl_dealloc_netinfo_by_wdev(cfg, wdev);
12047 #ifdef DHD_IFDEBUG
12048                         WL_ERR(("NETDEV_UNREGISTER(-) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12049 #endif
12050                         break;
12051                 case NETDEV_GOING_DOWN:
12052                         /*
12053                          * At NETDEV_DOWN state, wdev_cleanup_work work will be called.
12054                          * In front of door, the function checks whether current scan
12055                          * is working or not. If the scanning is still working,
12056                          * wdev_cleanup_work call WARN_ON and make the scan done forcibly.
12057                          */
12058 #ifdef DHD_IFDEBUG
12059                         WL_ERR(("NETDEV_GOING_DOWN wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12060 #endif
12061                         if (wl_get_drv_status(cfg, SCANNING, dev))
12062                                 wl_notify_escan_complete(cfg, dev, true, true);
12063                         break;
12064         }
12065         return NOTIFY_DONE;
12066 }
12067
12068 static struct notifier_block wl_cfg80211_netdev_notifier = {
12069         .notifier_call = wl_cfg80211_netdev_notifier_call,
12070 };
12071
12072 /*
12073  * to make sure we won't register the same notifier twice, otherwise a loop is likely to be
12074  * created in kernel notifier link list (with 'next' pointing to itself)
12075  */
12076 static bool wl_cfg80211_netdev_notifier_registered = FALSE;
12077
12078 static void wl_cfg80211_cancel_scan(struct bcm_cfg80211 *cfg)
12079 {
12080         struct wireless_dev *wdev = NULL;
12081         struct net_device *ndev = NULL;
12082
12083         if (!cfg->scan_request)
12084                 return;
12085
12086 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
12087         if (cfg->scan_request->dev)
12088                 wdev = cfg->scan_request->dev->ieee80211_ptr;
12089 #else
12090         wdev = cfg->scan_request->wdev;
12091 #endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
12092
12093         if (!wdev) {
12094                 WL_ERR(("No wireless_dev present\n"));
12095                 return;
12096         }
12097
12098         ndev = wdev_to_wlc_ndev(wdev, cfg);
12099         wl_notify_escan_complete(cfg, ndev, true, true);
12100         WL_ERR(("Scan aborted! \n"));
12101 }
12102
12103 static void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg)
12104 {
12105         wl_scan_params_t *params = NULL;
12106         s32 params_size = 0;
12107         s32 err = BCME_OK;
12108         struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
12109         if (!in_atomic()) {
12110                 /* Our scan params only need space for 1 channel and 0 ssids */
12111                 params = wl_cfg80211_scan_alloc_params(-1, 0, &params_size);
12112                 if (params == NULL) {
12113                         WL_ERR(("scan params allocation failed \n"));
12114                         err = -ENOMEM;
12115                 } else {
12116                         /* Do a scan abort to stop the driver's scan engine */
12117                         err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true);
12118                         if (err < 0) {
12119                                 WL_ERR(("scan abort  failed \n"));
12120                         }
12121                         kfree(params);
12122                 }
12123         }
12124 #ifdef WLTDLS
12125         if (cfg->tdls_mgmt_frame) {
12126                 kfree(cfg->tdls_mgmt_frame);
12127                 cfg->tdls_mgmt_frame = NULL;
12128         }
12129 #endif /* WLTDLS */
12130 }
12131
12132 static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
12133         struct net_device *ndev,
12134         bool aborted, bool fw_abort)
12135 {
12136         s32 err = BCME_OK;
12137         unsigned long flags;
12138         struct net_device *dev;
12139
12140         WL_DBG(("Enter \n"));
12141
12142         mutex_lock(&cfg->scan_complete);
12143
12144         if (!ndev) {
12145                 WL_ERR(("ndev is null\n"));
12146                 err = BCME_ERROR;
12147                 goto out;
12148         }
12149
12150         if (cfg->escan_info.ndev != ndev) {
12151                 WL_ERR(("ndev is different %p %p\n", cfg->escan_info.ndev, ndev));
12152                 err = BCME_ERROR;
12153                 goto out;
12154         }
12155
12156         if (cfg->scan_request) {
12157                 dev = bcmcfg_to_prmry_ndev(cfg);
12158 #if defined(WL_ENABLE_P2P_IF)
12159                 if (cfg->scan_request->dev != cfg->p2p_net)
12160                         dev = cfg->scan_request->dev;
12161 #elif defined(WL_CFG80211_P2P_DEV_IF)
12162                 if (cfg->scan_request->wdev->iftype != NL80211_IFTYPE_P2P_DEVICE) {
12163 #ifdef DHD_IFDEBUG
12164                         WL_ERR(("%s: dev: %p\n", __FUNCTION__, cfg->scan_request->wdev->netdev));
12165 #endif
12166                         dev = cfg->scan_request->wdev->netdev;
12167                 }
12168 #endif /* WL_ENABLE_P2P_IF */
12169         }
12170         else {
12171                 WL_DBG(("cfg->scan_request is NULL may be internal scan."
12172                         "doing scan_abort for ndev %p primary %p",
12173                                 ndev, bcmcfg_to_prmry_ndev(cfg)));
12174                 dev = ndev;
12175         }
12176         if (fw_abort && !in_atomic())
12177                 wl_cfg80211_scan_abort(cfg);
12178         if (timer_pending(&cfg->scan_timeout))
12179                 del_timer_sync(&cfg->scan_timeout);
12180 #if defined(ESCAN_RESULT_PATCH)
12181         if (likely(cfg->scan_request)) {
12182                 cfg->bss_list = wl_escan_get_buf(cfg, aborted);
12183                 wl_inform_bss(cfg);
12184         }
12185 #endif /* ESCAN_RESULT_PATCH */
12186         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
12187 #ifdef WL_SCHED_SCAN
12188         if (cfg->sched_scan_req && !cfg->scan_request) {
12189                 WL_PNO((">>> REPORTING SCHED SCAN RESULTS \n"));
12190                 if (!aborted)
12191                         cfg80211_sched_scan_results(cfg->sched_scan_req->wiphy);
12192                 cfg->sched_scan_running = FALSE;
12193                 cfg->sched_scan_req = NULL;
12194         }
12195 #endif /* WL_SCHED_SCAN */
12196         if (likely(cfg->scan_request)) {
12197                 cfg80211_scan_done(cfg->scan_request, aborted);
12198                 cfg->scan_request = NULL;
12199                 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
12200                 DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
12201         }
12202         if (p2p_is_on(cfg))
12203                 wl_clr_p2p_status(cfg, SCANNING);
12204         wl_clr_drv_status(cfg, SCANNING, dev);
12205         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
12206
12207 out:
12208         mutex_unlock(&cfg->scan_complete);
12209         return err;
12210 }
12211
12212 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12213 static void
12214 wl_cfg80211_find_removal_candidate(wl_bss_info_t *bss, removal_element_t *candidate)
12215 {
12216         int idx;
12217         for (idx = 0; idx < BUF_OVERFLOW_MGMT_COUNT; idx++) {
12218                 int len = BUF_OVERFLOW_MGMT_COUNT - idx - 1;
12219                 if (bss->RSSI < candidate[idx].RSSI) {
12220                         if (len)
12221                                 memcpy(&candidate[idx + 1], &candidate[idx],
12222                                         sizeof(removal_element_t) * len);
12223                         candidate[idx].RSSI = bss->RSSI;
12224                         candidate[idx].length = bss->length;
12225                         memcpy(&candidate[idx].BSSID, &bss->BSSID, ETHER_ADDR_LEN);
12226                         return;
12227                 }
12228         }
12229 }
12230
12231 static void
12232 wl_cfg80211_remove_lowRSSI_info(wl_scan_results_t *list, removal_element_t *candidate,
12233         wl_bss_info_t *bi)
12234 {
12235         int idx1, idx2;
12236         int total_delete_len = 0;
12237         for (idx1 = 0; idx1 < BUF_OVERFLOW_MGMT_COUNT; idx1++) {
12238                 int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
12239                 wl_bss_info_t *bss = NULL;
12240                 if (candidate[idx1].RSSI >= bi->RSSI)
12241                         continue;
12242                 for (idx2 = 0; idx2 < list->count; idx2++) {
12243                         bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) :
12244                                 list->bss_info;
12245                         if (!bcmp(&candidate[idx1].BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
12246                                 candidate[idx1].RSSI == bss->RSSI &&
12247                                 candidate[idx1].length == dtoh32(bss->length)) {
12248                                 u32 delete_len = dtoh32(bss->length);
12249                                 WL_DBG(("delete scan info of " MACDBG " to add new AP\n",
12250                                         MAC2STRDBG(bss->BSSID.octet)));
12251                                 if (idx2 < list->count -1) {
12252                                         memmove((u8 *)bss, (u8 *)bss + delete_len,
12253                                                 list->buflen - cur_len - delete_len);
12254                                 }
12255                                 list->buflen -= delete_len;
12256                                 list->count--;
12257                                 total_delete_len += delete_len;
12258                                 /* if delete_len is greater than or equal to result length */
12259                                 if (total_delete_len >= bi->length) {
12260                                         return;
12261                                 }
12262                                 break;
12263                         }
12264                         cur_len += dtoh32(bss->length);
12265                 }
12266         }
12267 }
12268 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12269
12270 static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12271         const wl_event_msg_t *e, void *data)
12272 {
12273         s32 err = BCME_OK;
12274         s32 status = ntoh32(e->status);
12275         wl_bss_info_t *bi;
12276         wl_escan_result_t *escan_result;
12277         wl_bss_info_t *bss = NULL;
12278         wl_scan_results_t *list;
12279         wifi_p2p_ie_t * p2p_ie;
12280         struct net_device *ndev = NULL;
12281         u32 bi_length;
12282         u32 i;
12283         u8 *p2p_dev_addr = NULL;
12284         u16 channel;
12285         struct ieee80211_supported_band *band;
12286
12287         WL_DBG((" enter event type : %d, status : %d \n",
12288                 ntoh32(e->event_type), ntoh32(e->status)));
12289
12290         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
12291
12292         mutex_lock(&cfg->usr_sync);
12293         /* P2P SCAN is coming from primary interface */
12294         if (wl_get_p2p_status(cfg, SCANNING)) {
12295                 if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM))
12296                         ndev = cfg->afx_hdl->dev;
12297                 else
12298                         ndev = cfg->escan_info.ndev;
12299
12300         }
12301         if (!ndev || (!wl_get_drv_status(cfg, SCANNING, ndev) && !cfg->sched_scan_running)) {
12302                 WL_DBG(("escan is not ready ndev %p drv_status 0x%x e_type %d e_states %d\n",
12303                         ndev, wl_get_drv_status(cfg, SCANNING, ndev),
12304                         ntoh32(e->event_type), ntoh32(e->status)));
12305                 goto exit;
12306         }
12307         escan_result = (wl_escan_result_t *)data;
12308
12309         if (status == WLC_E_STATUS_PARTIAL) {
12310                 WL_INFORM(("WLC_E_STATUS_PARTIAL \n"));
12311                 if (!escan_result) {
12312                         WL_ERR(("Invalid escan result (NULL pointer)\n"));
12313                         goto exit;
12314                 }
12315                 if (dtoh16(escan_result->bss_count) != 1) {
12316                         WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
12317                         goto exit;
12318                 }
12319                 bi = escan_result->bss_info;
12320                 if (!bi) {
12321                         WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
12322                         goto exit;
12323                 }
12324                 bi_length = dtoh32(bi->length);
12325                 if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
12326                         WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length));
12327                         goto exit;
12328                 }
12329
12330                 /* +++++ terence 20130524: skip invalid bss */
12331                 channel =
12332                         bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
12333                 if (channel <= CH_MAX_2G_CHANNEL)
12334                         band = bcmcfg_to_wiphy(cfg)->bands[IEEE80211_BAND_2GHZ];
12335                 else
12336                         band = bcmcfg_to_wiphy(cfg)->bands[IEEE80211_BAND_5GHZ];
12337                 if (!band) {
12338                         WL_ERR(("No valid band\n"));
12339                         goto exit;
12340                 }
12341                 if (!dhd_conf_match_channel(cfg->pub, channel))
12342                         goto exit;
12343                 /* ----- terence 20130524: skip invalid bss */
12344
12345                 if (wl_escan_check_sync_id(status, escan_result->sync_id,
12346                                 cfg->escan_info.cur_sync_id) < 0)
12347                         goto exit;
12348
12349                 if (!(bcmcfg_to_wiphy(cfg)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
12350                         if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
12351                                 WL_DBG(("Ignoring IBSS result\n"));
12352                                 goto exit;
12353                         }
12354                 }
12355
12356                 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
12357                         p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
12358                         if (p2p_dev_addr && !memcmp(p2p_dev_addr,
12359                                 cfg->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
12360                                 s32 channel = wf_chspec_ctlchan(
12361                                         wl_chspec_driver_to_host(bi->chanspec));
12362
12363                                 if ((channel > MAXCHANNEL) || (channel <= 0))
12364                                         channel = WL_INVALID;
12365                                 else
12366                                         WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
12367                                                 " channel : %d\n",
12368                                                 MAC2STRDBG(cfg->afx_hdl->tx_dst_addr.octet),
12369                                                 channel));
12370
12371                                 wl_clr_p2p_status(cfg, SCANNING);
12372                                 cfg->afx_hdl->peer_chan = channel;
12373                                 complete(&cfg->act_frm_scan);
12374                                 goto exit;
12375                         }
12376
12377                 } else {
12378                         int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
12379 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12380                         removal_element_t candidate[BUF_OVERFLOW_MGMT_COUNT];
12381                         int remove_lower_rssi = FALSE;
12382
12383                         bzero(candidate, sizeof(removal_element_t)*BUF_OVERFLOW_MGMT_COUNT);
12384 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12385
12386                         list = wl_escan_get_buf(cfg, FALSE);
12387                         if (scan_req_match(cfg)) {
12388                                 /* p2p scan && allow only probe response */
12389                                 if ((cfg->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
12390                                         (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
12391                                         goto exit;
12392                                 if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset,
12393                                         bi->ie_length)) == NULL) {
12394                                                 WL_ERR(("Couldn't find P2PIE in probe"
12395                                                         " response/beacon\n"));
12396                                                 goto exit;
12397                                 }
12398                         }
12399 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12400                         if (bi_length > ESCAN_BUF_SIZE - list->buflen)
12401                                 remove_lower_rssi = TRUE;
12402 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12403
12404                         WL_SCAN(("%s("MACDBG") RSSI %d flags 0x%x length %d\n", bi->SSID,
12405                                 MAC2STRDBG(bi->BSSID.octet), bi->RSSI, bi->flags, bi->length));
12406                         for (i = 0; i < list->count; i++) {
12407                                 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
12408                                         : list->bss_info;
12409 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12410                                 WL_TRACE(("%s("MACDBG"), i=%d bss: RSSI %d list->count %d\n",
12411                                         bss->SSID, MAC2STRDBG(bss->BSSID.octet),
12412                                         i, bss->RSSI, list->count));
12413
12414                                 if (remove_lower_rssi)
12415                                         wl_cfg80211_find_removal_candidate(bss, candidate);
12416 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12417
12418                                 if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
12419                                         (CHSPEC_BAND(wl_chspec_driver_to_host(bi->chanspec))
12420                                         == CHSPEC_BAND(wl_chspec_driver_to_host(bss->chanspec))) &&
12421                                         bi->SSID_len == bss->SSID_len &&
12422                                         !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
12423
12424                                         /* do not allow beacon data to update
12425                                         *the data recd from a probe response
12426                                         */
12427                                         if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) &&
12428                                                 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
12429                                                 goto exit;
12430
12431                                         WL_SCAN(("%s("MACDBG"), i=%d prev: RSSI %d"
12432                                                 " flags 0x%x, new: RSSI %d flags 0x%x\n",
12433                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet), i,
12434                                                 bss->RSSI, bss->flags, bi->RSSI, bi->flags));
12435
12436                                         if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
12437                                                 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) {
12438                                                 /* preserve max RSSI if the measurements are
12439                                                 * both on-channel or both off-channel
12440                                                 */
12441                                                 WL_SCAN(("%s("MACDBG"), same onchan"
12442                                                 ", RSSI: prev %d new %d\n",
12443                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
12444                                                 bss->RSSI, bi->RSSI));
12445                                                 bi->RSSI = MAX(bss->RSSI, bi->RSSI);
12446                                         } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
12447                                                 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
12448                                                 /* preserve the on-channel rssi measurement
12449                                                 * if the new measurement is off channel
12450                                                 */
12451                                                 WL_SCAN(("%s("MACDBG"), prev onchan"
12452                                                 ", RSSI: prev %d new %d\n",
12453                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
12454                                                 bss->RSSI, bi->RSSI));
12455                                                 bi->RSSI = bss->RSSI;
12456                                                 bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
12457                                         }
12458                                         if (dtoh32(bss->length) != bi_length) {
12459                                                 u32 prev_len = dtoh32(bss->length);
12460
12461                                                 WL_SCAN(("bss info replacement"
12462                                                         " is occured(bcast:%d->probresp%d)\n",
12463                                                         bss->ie_length, bi->ie_length));
12464                                                 WL_SCAN(("%s("MACDBG"), replacement!(%d -> %d)\n",
12465                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
12466                                                 prev_len, bi_length));
12467
12468                                                 if (list->buflen - prev_len + bi_length
12469                                                         > ESCAN_BUF_SIZE) {
12470                                                         WL_ERR(("Buffer is too small: keep the"
12471                                                                 " previous result of this AP\n"));
12472                                                         /* Only update RSSI */
12473                                                         bss->RSSI = bi->RSSI;
12474                                                         bss->flags |= (bi->flags
12475                                                                 & WL_BSS_FLAGS_RSSI_ONCHANNEL);
12476                                                         goto exit;
12477                                                 }
12478
12479                                                 if (i < list->count - 1) {
12480                                                         /* memory copy required by this case only */
12481                                                         memmove((u8 *)bss + bi_length,
12482                                                                 (u8 *)bss + prev_len,
12483                                                                 list->buflen - cur_len - prev_len);
12484                                                 }
12485                                                 list->buflen -= prev_len;
12486                                                 list->buflen += bi_length;
12487                                         }
12488                                         list->version = dtoh32(bi->version);
12489                                         memcpy((u8 *)bss, (u8 *)bi, bi_length);
12490                                         goto exit;
12491                                 }
12492                                 cur_len += dtoh32(bss->length);
12493                         }
12494                         if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
12495 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12496                                 wl_cfg80211_remove_lowRSSI_info(list, candidate, bi);
12497                                 if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
12498                                         WL_DBG(("RSSI(" MACDBG ") is too low(%d) to add Buffer\n",
12499                                                 MAC2STRDBG(bi->BSSID.octet), bi->RSSI));
12500                                         goto exit;
12501                                 }
12502 #else
12503                                 WL_ERR(("Buffer is too small: ignoring\n"));
12504                                 goto exit;
12505 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12506                         }
12507
12508                         memcpy(&(((char *)list)[list->buflen]), bi, bi_length);
12509                         list->version = dtoh32(bi->version);
12510                         list->buflen += bi_length;
12511                         list->count++;
12512
12513                         /*
12514                          * !Broadcast && number of ssid = 1 && number of channels =1
12515                          * means specific scan to association
12516                          */
12517                         if (wl_cfgp2p_is_p2p_specific_scan(cfg->scan_request)) {
12518                                 WL_ERR(("P2P assoc scan fast aborted.\n"));
12519                                 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, false, true);
12520                                 goto exit;
12521                         }
12522                 }
12523         }
12524         else if (status == WLC_E_STATUS_SUCCESS) {
12525                 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
12526                 wl_escan_print_sync_id(status, cfg->escan_info.cur_sync_id,
12527                         escan_result->sync_id);
12528
12529                 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
12530                         WL_INFORM(("ACTION FRAME SCAN DONE\n"));
12531                         wl_clr_p2p_status(cfg, SCANNING);
12532                         wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
12533                         if (cfg->afx_hdl->peer_chan == WL_INVALID)
12534                                 complete(&cfg->act_frm_scan);
12535                 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
12536                         WL_INFORM(("ESCAN COMPLETED\n"));
12537                         cfg->bss_list = wl_escan_get_buf(cfg, FALSE);
12538                         if (!scan_req_match(cfg)) {
12539                                 WL_TRACE_HW4(("SCAN COMPLETED: scanned AP count=%d\n",
12540                                         cfg->bss_list->count));
12541                         }
12542                         wl_inform_bss(cfg);
12543                         wl_notify_escan_complete(cfg, ndev, false, false);
12544                 }
12545                 wl_escan_increment_sync_id(cfg, SCAN_BUF_NEXT);
12546 #ifdef CUSTOMER_HW4_DEBUG
12547                 if (wl_scan_timeout_dbg_enabled)
12548                         wl_scan_timeout_dbg_clear();
12549 #endif /* CUSTOMER_HW4_DEBUG */
12550         } else if ((status == WLC_E_STATUS_ABORT) || (status == WLC_E_STATUS_NEWSCAN) ||
12551                 (status == WLC_E_STATUS_11HQUIET) || (status == WLC_E_STATUS_CS_ABORT) ||
12552                 (status == WLC_E_STATUS_NEWASSOC)) {
12553                 /* Handle all cases of scan abort */
12554                 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
12555                 wl_escan_print_sync_id(status, escan_result->sync_id,
12556                         cfg->escan_info.cur_sync_id);
12557                 WL_DBG(("ESCAN ABORT reason: %d\n", status));
12558                 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
12559                         WL_INFORM(("ACTION FRAME SCAN DONE\n"));
12560                         wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
12561                         wl_clr_p2p_status(cfg, SCANNING);
12562                         if (cfg->afx_hdl->peer_chan == WL_INVALID)
12563                                 complete(&cfg->act_frm_scan);
12564                 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
12565                         WL_INFORM(("ESCAN ABORTED\n"));
12566                         cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
12567                         if (!scan_req_match(cfg)) {
12568                                 WL_TRACE_HW4(("scan_req_match=0: scanned AP count=%d\n",
12569                                         cfg->bss_list->count));
12570                         }
12571                         wl_inform_bss(cfg);
12572                         wl_notify_escan_complete(cfg, ndev, true, false);
12573                 } else {
12574                         /* If there is no pending host initiated scan, do nothing */
12575                         WL_DBG(("ESCAN ABORT: No pending scans. Ignoring event.\n"));
12576                 }
12577                 wl_escan_increment_sync_id(cfg, SCAN_BUF_CNT);
12578         } else if (status == WLC_E_STATUS_TIMEOUT) {
12579                 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", cfg->scan_request));
12580                 WL_ERR(("reason[0x%x]\n", e->reason));
12581                 if (e->reason == 0xFFFFFFFF) {
12582                         wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
12583                 }
12584         } else {
12585                 WL_ERR(("unexpected Escan Event %d : abort\n", status));
12586                 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
12587                 wl_escan_print_sync_id(status, escan_result->sync_id,
12588                         cfg->escan_info.cur_sync_id);
12589                 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
12590                         WL_INFORM(("ACTION FRAME SCAN DONE\n"));
12591                         wl_clr_p2p_status(cfg, SCANNING);
12592                         wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
12593                         if (cfg->afx_hdl->peer_chan == WL_INVALID)
12594                                 complete(&cfg->act_frm_scan);
12595                 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
12596                         cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
12597                         if (!scan_req_match(cfg)) {
12598                                 WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): "
12599                                         "scanned AP count=%d\n",
12600                                         cfg->bss_list->count));
12601                         }
12602                         wl_inform_bss(cfg);
12603                         wl_notify_escan_complete(cfg, ndev, true, false);
12604                 }
12605                 wl_escan_increment_sync_id(cfg, 2);
12606         }
12607 exit:
12608         mutex_unlock(&cfg->usr_sync);
12609         return err;
12610 }
12611
12612 static void wl_cfg80211_concurrent_roam(struct bcm_cfg80211 *cfg, int enable)
12613 {
12614         u32 connected_cnt  = wl_get_drv_status_all(cfg, CONNECTED);
12615         bool p2p_connected  = wl_cfgp2p_vif_created(cfg);
12616         struct net_info *iter, *next;
12617
12618         if (!cfg->roamoff_on_concurrent)
12619                 return;
12620         if (enable && (p2p_connected||(connected_cnt > 1))) {
12621 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12622         4 && __GNUC_MINOR__ >= 6))
12623 _Pragma("GCC diagnostic push")
12624 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
12625 #endif
12626                 for_each_ndev(cfg, iter, next) {
12627                         if (iter->ndev && iter->wdev &&
12628                                         iter->wdev->iftype == NL80211_IFTYPE_STATION) {
12629                                 if (wldev_iovar_setint(iter->ndev, "roam_off", TRUE)
12630                                                 == BCME_OK) {
12631                                         iter->roam_off = TRUE;
12632                                 }
12633                                 else {
12634                                         WL_ERR(("error to enable roam_off\n"));
12635                                 }
12636                         }
12637                 }
12638 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12639         4 && __GNUC_MINOR__ >= 6))
12640 _Pragma("GCC diagnostic pop")
12641 #endif
12642         }
12643         else if (!enable) {
12644 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12645         4 && __GNUC_MINOR__ >= 6))
12646 _Pragma("GCC diagnostic push")
12647 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
12648 #endif
12649                 for_each_ndev(cfg, iter, next) {
12650                         if (iter->ndev && iter->wdev &&
12651                                         iter->wdev->iftype == NL80211_IFTYPE_STATION) {
12652                                 if (iter->roam_off != WL_INVALID) {
12653                                         if (wldev_iovar_setint(iter->ndev, "roam_off", FALSE)
12654                                                         == BCME_OK) {
12655                                                 iter->roam_off = FALSE;
12656                                         }
12657                                         else {
12658                                                 WL_ERR(("error to disable roam_off\n"));
12659                                         }
12660                                 }
12661                         }
12662                 }
12663 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12664         4 && __GNUC_MINOR__ >= 6))
12665 _Pragma("GCC diagnostic pop")
12666 #endif
12667         }
12668         return;
12669 }
12670
12671 static void wl_cfg80211_determine_vsdb_mode(struct bcm_cfg80211 *cfg)
12672 {
12673         struct net_info *iter, *next;
12674         u32 ctl_chan = 0;
12675         u32 chanspec = 0;
12676         u32 pre_ctl_chan = 0;
12677         u32 connected_cnt  = wl_get_drv_status_all(cfg, CONNECTED);
12678         cfg->vsdb_mode = false;
12679
12680         if (connected_cnt <= 1)  {
12681                 return;
12682         }
12683 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12684         4 && __GNUC_MINOR__ >= 6))
12685 _Pragma("GCC diagnostic push")
12686 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
12687 #endif
12688         for_each_ndev(cfg, iter, next) {
12689                 /* p2p discovery iface ndev could be null */
12690                 if (iter->ndev) {
12691                         chanspec = 0;
12692                         ctl_chan = 0;
12693                         if (wl_get_drv_status(cfg, CONNECTED, iter->ndev)) {
12694                                 if (wldev_iovar_getint(iter->ndev, "chanspec",
12695                                         (s32 *)&chanspec) == BCME_OK) {
12696                                         chanspec = wl_chspec_driver_to_host(chanspec);
12697                                         ctl_chan = wf_chspec_ctlchan(chanspec);
12698                                         wl_update_prof(cfg, iter->ndev, NULL,
12699                                                 &ctl_chan, WL_PROF_CHAN);
12700                                 }
12701                                 if (!cfg->vsdb_mode) {
12702                                         if (!pre_ctl_chan && ctl_chan)
12703                                                 pre_ctl_chan = ctl_chan;
12704                                         else if (pre_ctl_chan && (pre_ctl_chan != ctl_chan)) {
12705                                                 cfg->vsdb_mode = true;
12706                                         }
12707                                 }
12708                         }
12709                 }
12710         }
12711 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12712         4 && __GNUC_MINOR__ >= 6))
12713 _Pragma("GCC diagnostic pop")
12714 #endif
12715         printf("%s concurrency is enabled\n", cfg->vsdb_mode ? "Multi Channel" : "Same Channel");
12716         return;
12717 }
12718
12719 #if defined(DISABLE_FRAMEBURST_VSDB) && defined(USE_WFA_CERT_CONF)
12720 extern int g_frameburst;
12721 #endif /* DISABLE_FRAMEBURST_VSDB && USE_WFA_CERT_CONF */
12722
12723 static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_net_info,
12724         enum wl_status state, bool set)
12725 {
12726         s32 pm = PM_FAST;
12727         s32 err = BCME_OK;
12728         u32 mode;
12729         u32 chan = 0;
12730         struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
12731         dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
12732         if (dhd->busstate == DHD_BUS_DOWN) {
12733                 WL_ERR(("%s : busstate is DHD_BUS_DOWN!\n", __FUNCTION__));
12734                 return 0;
12735         }
12736         WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n",
12737                 state, set, _net_info->pm_restore, _net_info->ndev->name));
12738
12739         if (state != WL_STATUS_CONNECTED)
12740                 return 0;
12741         mode = wl_get_mode_by_netdev(cfg, _net_info->ndev);
12742         if (set) {
12743                 wl_cfg80211_concurrent_roam(cfg, 1);
12744                 wl_cfg80211_determine_vsdb_mode(cfg);
12745                 if (mode == WL_MODE_AP) {
12746                         if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false))
12747                                 WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
12748                 }
12749
12750                 pm = PM_OFF;
12751                 if ((err = wldev_ioctl(_net_info->ndev, WLC_SET_PM, &pm,
12752                                 sizeof(pm), true)) != 0) {
12753                         if (err == -ENODEV)
12754                                 WL_DBG(("%s:netdev not ready\n",
12755                                         _net_info->ndev->name));
12756                         else
12757                                 WL_ERR(("%s:error (%d)\n",
12758                                         _net_info->ndev->name, err));
12759
12760                         wl_cfg80211_update_power_mode(_net_info->ndev);
12761                 }
12762                 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_SHORT);
12763 #if defined(WLTDLS)
12764                 if (wl_cfg80211_is_concurrent_mode()) {
12765                         err = wldev_iovar_setint(primary_dev, "tdls_enable", 0);
12766                 }
12767 #endif /* defined(WLTDLS) */
12768
12769 #ifdef DISABLE_FRAMEBURST_VSDB
12770 #ifdef USE_WFA_CERT_CONF
12771                 if (g_frameburst)
12772 #endif /* USE_WFA_CERT_CONF */
12773                 {
12774                         if (wl_cfg80211_is_concurrent_mode()) {
12775                                 int frameburst = 0;
12776                                 if (wldev_ioctl(primary_dev, WLC_SET_FAKEFRAG, &frameburst,
12777                                         sizeof(frameburst), true) != 0) {
12778                                         WL_DBG(("frameburst set error\n"));
12779                                 }
12780                                 WL_DBG(("Frameburst Disabled\n"));
12781                         }
12782                 }
12783 #endif /* DISABLE_FRAMEBURST_VSDB */
12784         } else { /* clear */
12785                 chan = 0;
12786                 /* clear chan information when the net device is disconnected */
12787                 wl_update_prof(cfg, _net_info->ndev, NULL, &chan, WL_PROF_CHAN);
12788                 wl_cfg80211_determine_vsdb_mode(cfg);
12789                 if (primary_dev == _net_info->ndev) {
12790                         pm = PM_FAST;
12791                         if ((err = wldev_ioctl(_net_info->ndev, WLC_SET_PM, &pm,
12792                                         sizeof(pm), true)) != 0) {
12793                                 if (err == -ENODEV)
12794                                         WL_DBG(("%s:netdev not ready\n",
12795                                                 _net_info->ndev->name));
12796                                 else
12797                                         WL_ERR(("%s:error (%d)\n",
12798                                                 _net_info->ndev->name, err));
12799
12800                                 wl_cfg80211_update_power_mode(_net_info->ndev);
12801                         }
12802                 }
12803
12804                 wl_cfg80211_concurrent_roam(cfg, 0);
12805 #if defined(WLTDLS)
12806                 if (!wl_cfg80211_is_concurrent_mode()) {
12807                         err = wldev_iovar_setint(primary_dev, "tdls_enable", 1);
12808                 }
12809 #endif /* defined(WLTDLS) */
12810
12811 #ifdef DISABLE_FRAMEBURST_VSDB
12812 #ifdef USE_WFA_CERT_CONF
12813                 if (g_frameburst)
12814 #endif /* USE_WFA_CERT_CONF */
12815                 {
12816                         int frameburst = 1;
12817                         if (wldev_ioctl(primary_dev, WLC_SET_FAKEFRAG, &frameburst,
12818                                 sizeof(frameburst), true) != 0) {
12819                                 WL_DBG(("frameburst set error\n"));
12820                         }
12821                         WL_DBG(("Frameburst Enabled\n"));
12822                 }
12823 #endif /* DISABLE_FRAMEBURST_VSDB */
12824         }
12825         return err;
12826 }
12827 static s32 wl_init_scan(struct bcm_cfg80211 *cfg)
12828 {
12829         int err = 0;
12830
12831         cfg->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
12832         cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
12833         wl_escan_init_sync_id(cfg);
12834
12835         /* Init scan_timeout timer */
12836         init_timer(&cfg->scan_timeout);
12837         cfg->scan_timeout.data = (unsigned long) cfg;
12838         cfg->scan_timeout.function = wl_scan_timeout;
12839
12840         return err;
12841 }
12842
12843 #ifdef DHD_LOSSLESS_ROAMING
12844 static s32 wl_init_roam_timeout(struct bcm_cfg80211 *cfg)
12845 {
12846         int err = 0;
12847
12848         /* Init roam timer */
12849         init_timer(&cfg->roam_timeout);
12850         cfg->roam_timeout.data = (unsigned long) cfg;
12851         cfg->roam_timeout.function = wl_roam_timeout;
12852
12853         return err;
12854 }
12855 #endif /* DHD_LOSSLESS_ROAMING */
12856
12857 static s32 wl_init_priv(struct bcm_cfg80211 *cfg)
12858 {
12859         struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
12860         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
12861         s32 err = 0;
12862
12863         cfg->scan_request = NULL;
12864         cfg->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
12865         cfg->roam_on = false;
12866         cfg->active_scan = true;
12867         cfg->rf_blocked = false;
12868         cfg->vsdb_mode = false;
12869 #if defined(BCMSDIO)
12870         cfg->wlfc_on = false;
12871 #endif 
12872         cfg->roamoff_on_concurrent = true;
12873         cfg->disable_roam_event = false;
12874         cfg->cfgdev_bssidx = -1;
12875         /* register interested state */
12876         set_bit(WL_STATUS_CONNECTED, &cfg->interrested_state);
12877         spin_lock_init(&cfg->cfgdrv_lock);
12878         mutex_init(&cfg->ioctl_buf_sync);
12879         init_waitqueue_head(&cfg->netif_change_event);
12880         init_completion(&cfg->send_af_done);
12881         init_completion(&cfg->iface_disable);
12882         wl_init_eq(cfg);
12883         err = wl_init_priv_mem(cfg);
12884         if (err)
12885                 return err;
12886         if (wl_create_event_handler(cfg))
12887                 return -ENOMEM;
12888         wl_init_event_handler(cfg);
12889         mutex_init(&cfg->usr_sync);
12890         mutex_init(&cfg->event_sync);
12891         mutex_init(&cfg->scan_complete);
12892         err = wl_init_scan(cfg);
12893         if (err)
12894                 return err;
12895 #ifdef DHD_LOSSLESS_ROAMING
12896         err = wl_init_roam_timeout(cfg);
12897         if (err) {
12898                 return err;
12899         }
12900 #endif /* DHD_LOSSLESS_ROAMING */
12901         wl_init_conf(cfg->conf);
12902         wl_init_prof(cfg, ndev);
12903         wl_link_down(cfg);
12904         DNGL_FUNC(dhd_cfg80211_init, (cfg));
12905
12906         return err;
12907 }
12908
12909 static void wl_deinit_priv(struct bcm_cfg80211 *cfg)
12910 {
12911         DNGL_FUNC(dhd_cfg80211_deinit, (cfg));
12912         wl_destroy_event_handler(cfg);
12913         wl_flush_eq(cfg);
12914         wl_link_down(cfg);
12915         del_timer_sync(&cfg->scan_timeout);
12916 #ifdef DHD_LOSSLESS_ROAMING
12917         del_timer_sync(&cfg->roam_timeout);
12918 #endif
12919         wl_deinit_priv_mem(cfg);
12920         if (wl_cfg80211_netdev_notifier_registered) {
12921                 wl_cfg80211_netdev_notifier_registered = FALSE;
12922                 unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
12923         }
12924 }
12925
12926 #if defined(WL_ENABLE_P2P_IF)
12927 static s32 wl_cfg80211_attach_p2p(void)
12928 {
12929         struct bcm_cfg80211 *cfg = g_bcm_cfg;
12930
12931         WL_TRACE(("Enter \n"));
12932
12933         if (wl_cfgp2p_register_ndev(cfg) < 0) {
12934                 WL_ERR(("P2P attach failed. \n"));
12935                 return -ENODEV;
12936         }
12937
12938         return 0;
12939 }
12940
12941 static s32  wl_cfg80211_detach_p2p(void)
12942 {
12943         struct bcm_cfg80211 *cfg = g_bcm_cfg;
12944         struct wireless_dev *wdev;
12945
12946         WL_DBG(("Enter \n"));
12947         if (!cfg) {
12948                 WL_ERR(("Invalid Ptr\n"));
12949                 return -EINVAL;
12950         } else
12951                 wdev = cfg->p2p_wdev;
12952
12953         if (!wdev) {
12954                 WL_ERR(("Invalid Ptr\n"));
12955                 return -EINVAL;
12956         }
12957
12958         wl_cfgp2p_unregister_ndev(cfg);
12959
12960         cfg->p2p_wdev = NULL;
12961         cfg->p2p_net = NULL;
12962         WL_DBG(("Freeing 0x%p \n", wdev));
12963         kfree(wdev);
12964
12965         return 0;
12966 }
12967 #endif 
12968
12969 s32 wl_cfg80211_attach_post(struct net_device *ndev)
12970 {
12971         struct bcm_cfg80211 * cfg = NULL;
12972         s32 err = 0;
12973         s32 ret = 0;
12974         WL_TRACE(("In\n"));
12975         if (unlikely(!ndev)) {
12976                 WL_ERR(("ndev is invaild\n"));
12977                 return -ENODEV;
12978         }
12979         cfg = g_bcm_cfg;
12980         if (unlikely(!cfg)) {
12981                 WL_ERR(("cfg is invaild\n"));
12982                 return -EINVAL;
12983         }
12984         if (!wl_get_drv_status(cfg, READY, ndev)) {
12985                 if (cfg->wdev) {
12986                         ret = wl_cfgp2p_supported(cfg, ndev);
12987                         if (ret > 0) {
12988 #if !defined(WL_ENABLE_P2P_IF)
12989                                 cfg->wdev->wiphy->interface_modes |=
12990                                         (BIT(NL80211_IFTYPE_P2P_CLIENT)|
12991                                         BIT(NL80211_IFTYPE_P2P_GO));
12992 #endif /* !WL_ENABLE_P2P_IF */
12993                                 if ((err = wl_cfgp2p_init_priv(cfg)) != 0)
12994                                         goto fail;
12995
12996 #if defined(WL_ENABLE_P2P_IF)
12997                                 if (cfg->p2p_net) {
12998                                         /* Update MAC addr for p2p0 interface here. */
12999                                         memcpy(cfg->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN);
13000                                         cfg->p2p_net->dev_addr[0] |= 0x02;
13001                                         printf("%s: p2p_dev_addr="MACDBG "\n",
13002                                                 cfg->p2p_net->name,
13003                                                 MAC2STRDBG(cfg->p2p_net->dev_addr));
13004                                 } else {
13005                                         WL_ERR(("p2p_net not yet populated."
13006                                         " Couldn't update the MAC Address for p2p0 \n"));
13007                                         return -ENODEV;
13008                                 }
13009 #endif /* WL_ENABLE_P2P_IF */
13010                                 cfg->p2p_supported = true;
13011                         } else if (ret == 0) {
13012                                 if ((err = wl_cfgp2p_init_priv(cfg)) != 0)
13013                                         goto fail;
13014                         } else {
13015                                 /* SDIO bus timeout */
13016                                 err = -ENODEV;
13017                                 goto fail;
13018                         }
13019                 }
13020         }
13021         wl_set_drv_status(cfg, READY, ndev);
13022 fail:
13023         return err;
13024 }
13025
13026 s32 wl_cfg80211_attach(struct net_device *ndev, void *context)
13027 {
13028         struct wireless_dev *wdev;
13029         struct bcm_cfg80211 *cfg;
13030         s32 err = 0;
13031         struct device *dev;
13032
13033         WL_TRACE(("In\n"));
13034         if (!ndev) {
13035                 WL_ERR(("ndev is invaild\n"));
13036                 return -ENODEV;
13037         }
13038         WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev()));
13039         dev = wl_cfg80211_get_parent_dev();
13040
13041         wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
13042         if (unlikely(!wdev)) {
13043                 WL_ERR(("Could not allocate wireless device\n"));
13044                 return -ENOMEM;
13045         }
13046         err = wl_setup_wiphy(wdev, dev, context);
13047         if (unlikely(err)) {
13048                 kfree(wdev);
13049                 return -ENOMEM;
13050         }
13051         wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
13052         cfg = (struct bcm_cfg80211 *)wiphy_priv(wdev->wiphy);
13053         cfg->wdev = wdev;
13054         cfg->pub = context;
13055         INIT_LIST_HEAD(&cfg->net_list);
13056         spin_lock_init(&cfg->net_list_sync);
13057         ndev->ieee80211_ptr = wdev;
13058         SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
13059         wdev->netdev = ndev;
13060         cfg->state_notifier = wl_notifier_change_state;
13061         err = wl_alloc_netinfo(cfg, ndev, wdev, WL_MODE_BSS, PM_ENABLE, 0);
13062         if (err) {
13063                 WL_ERR(("Failed to alloc net_info (%d)\n", err));
13064                 goto cfg80211_attach_out;
13065         }
13066         err = wl_init_priv(cfg);
13067         if (err) {
13068                 WL_ERR(("Failed to init iwm_priv (%d)\n", err));
13069                 goto cfg80211_attach_out;
13070         }
13071
13072         err = wl_setup_rfkill(cfg, TRUE);
13073         if (err) {
13074                 WL_ERR(("Failed to setup rfkill %d\n", err));
13075                 goto cfg80211_attach_out;
13076         }
13077 #ifdef DEBUGFS_CFG80211
13078         err = wl_setup_debugfs(cfg);
13079         if (err) {
13080                 WL_ERR(("Failed to setup debugfs %d\n", err));
13081                 goto cfg80211_attach_out;
13082         }
13083 #endif
13084         if (!wl_cfg80211_netdev_notifier_registered) {
13085                 wl_cfg80211_netdev_notifier_registered = TRUE;
13086                 err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier);
13087                 if (err) {
13088                         wl_cfg80211_netdev_notifier_registered = FALSE;
13089                         WL_ERR(("Failed to register notifierl %d\n", err));
13090                         goto cfg80211_attach_out;
13091                 }
13092         }
13093 #if defined(COEX_DHCP)
13094         cfg->btcoex_info = wl_cfg80211_btcoex_init(cfg->wdev->netdev);
13095         if (!cfg->btcoex_info)
13096                 goto cfg80211_attach_out;
13097 #endif 
13098 #if defined(SUPPORT_RANDOM_MAC_SCAN)
13099         cfg->random_mac_enabled = FALSE;
13100 #endif /* SUPPORT_RANDOM_MAC_SCAN */
13101         g_bcm_cfg = cfg;
13102
13103 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
13104         wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier;
13105 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
13106
13107 #if defined(WL_ENABLE_P2P_IF)
13108         err = wl_cfg80211_attach_p2p();
13109         if (err)
13110                 goto cfg80211_attach_out;
13111 #endif 
13112
13113         INIT_DELAYED_WORK(&cfg->pm_enable_work, wl_cfg80211_work_handler);
13114         mutex_init(&cfg->pm_sync);
13115
13116         return err;
13117
13118 cfg80211_attach_out:
13119         wl_setup_rfkill(cfg, FALSE);
13120         wl_free_wdev(cfg);
13121         return err;
13122 }
13123
13124 void wl_cfg80211_detach(void *para)
13125 {
13126         struct bcm_cfg80211 *cfg;
13127
13128         (void)para;
13129         cfg = g_bcm_cfg;
13130
13131         WL_TRACE(("In\n"));
13132
13133         wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
13134
13135 #if defined(COEX_DHCP)
13136         wl_cfg80211_btcoex_deinit();
13137         cfg->btcoex_info = NULL;
13138 #endif 
13139
13140         wl_setup_rfkill(cfg, FALSE);
13141 #ifdef DEBUGFS_CFG80211
13142         wl_free_debugfs(cfg);
13143 #endif
13144         if (cfg->p2p_supported) {
13145                 if (timer_pending(&cfg->p2p->listen_timer))
13146                         del_timer_sync(&cfg->p2p->listen_timer);
13147                 wl_cfgp2p_deinit_priv(cfg);
13148         }
13149
13150         if (timer_pending(&cfg->scan_timeout))
13151                 del_timer_sync(&cfg->scan_timeout);
13152 #ifdef DHD_LOSSLESS_ROAMING
13153         if (timer_pending(&cfg->roam_timeout)) {
13154                 del_timer_sync(&cfg->roam_timeout);
13155         }
13156 #endif /* DHD_LOSSLESS_ROAMING */
13157
13158 #if defined(WL_CFG80211_P2P_DEV_IF)
13159         if (cfg->p2p_wdev)
13160                 wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
13161 #endif /* WL_CFG80211_P2P_DEV_IF  */
13162 #if defined(WL_ENABLE_P2P_IF)
13163         wl_cfg80211_detach_p2p();
13164 #endif 
13165
13166         wl_cfg80211_ibss_vsie_free(cfg);
13167         wl_cfg80211_clear_mgmt_vndr_ies(cfg);
13168         wl_deinit_priv(cfg);
13169         g_bcm_cfg = NULL;
13170         wl_cfg80211_clear_parent_dev();
13171         wl_free_wdev(cfg);
13172 #if defined(RSSIAVG)
13173         wl_free_rssi_cache(&g_rssi_cache_ctrl);
13174         wl_free_rssi_cache(&g_connected_rssi_cache_ctrl);
13175 #endif
13176 #if defined(BSSCACHE)
13177         wl_release_bss_cache_ctrl(&g_bss_cache_ctrl);
13178 #endif
13179         /* PLEASE do NOT call any function after wl_free_wdev, the driver's private
13180          * structure "cfg", which is the private part of wiphy, has been freed in
13181          * wl_free_wdev !!!!!!!!!!!
13182          */
13183 }
13184
13185 static void wl_wakeup_event(struct bcm_cfg80211 *cfg)
13186 {
13187         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
13188
13189         if (dhd->up && (cfg->event_tsk.thr_pid >= 0)) {
13190                 up(&cfg->event_tsk.sema);
13191         }
13192 }
13193
13194 static s32 wl_event_handler(void *data)
13195 {
13196         struct bcm_cfg80211 *cfg = NULL;
13197         struct wl_event_q *e;
13198         tsk_ctl_t *tsk = (tsk_ctl_t *)data;
13199         struct wireless_dev *wdev = NULL;
13200
13201         cfg = (struct bcm_cfg80211 *)tsk->parent;
13202
13203         printf("tsk Enter, tsk = 0x%p\n", tsk);
13204
13205         while (down_interruptible (&tsk->sema) == 0) {
13206                 SMP_RD_BARRIER_DEPENDS();
13207                 if (tsk->terminated) {
13208                         break;
13209                 }
13210                 while ((e = wl_deq_event(cfg))) {
13211                         WL_DBG(("event type (%d), ifidx: %d bssidx: %d \n",
13212                                 e->etype, e->emsg.ifidx, e->emsg.bsscfgidx));
13213
13214                         if (e->emsg.ifidx > WL_MAX_IFS) {
13215                                 WL_ERR((" Event ifidx not in range. val:%d \n", e->emsg.ifidx));
13216                                 goto fail;
13217                         }
13218
13219                         if (!(wdev = wl_get_wdev_by_bssidx(cfg, e->emsg.bsscfgidx))) {
13220                                 /* For WLC_E_IF would be handled by wl_host_event */
13221                                 if (e->etype != WLC_E_IF)
13222                                         WL_ERR(("No wdev corresponding to bssidx: 0x%x found!"
13223                                                 " Ignoring event.\n", e->emsg.bsscfgidx));
13224                         } else if (e->etype < WLC_E_LAST && cfg->evt_handler[e->etype]) {
13225                                 dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
13226                                 if (dhd->busstate == DHD_BUS_DOWN) {
13227                                         WL_ERR((": BUS is DOWN.\n"));
13228                                 } else {
13229 #ifdef DHD_IFDEBUG
13230                                         if (cfg->iface_cnt == 0) {
13231                                                 wl_dump_ifinfo(cfg);
13232                                         }
13233 #endif
13234                                         cfg->evt_handler[e->etype](cfg, wdev_to_cfgdev(wdev),
13235                                                 &e->emsg, e->edata);
13236                                 }
13237                         } else {
13238                                 WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
13239                         }
13240 fail:
13241                         wl_put_event(e);
13242                         DHD_EVENT_WAKE_UNLOCK(cfg->pub);
13243                 }
13244         }
13245         printf("%s: was terminated\n", __FUNCTION__);
13246         complete_and_exit(&tsk->completed, 0);
13247         return 0;
13248 }
13249
13250 void
13251 wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
13252 {
13253         u32 event_type = ntoh32(e->event_type);
13254         struct bcm_cfg80211 *cfg = g_bcm_cfg;
13255         struct net_info *netinfo;
13256
13257 #if (WL_DBG_LEVEL > 0)
13258         s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
13259             wl_dbg_estr[event_type] : (s8 *) "Unknown";
13260         WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
13261 #endif /* (WL_DBG_LEVEL > 0) */
13262
13263         if (cfg->event_tsk.thr_pid == -1) {
13264                 WL_ERR(("Event handler is not created\n"));
13265                 return;
13266         }
13267
13268         if ((cfg == NULL) || (cfg->p2p_supported && cfg->p2p == NULL)) {
13269                 WL_ERR(("Stale event ignored\n"));
13270                 return;
13271         }
13272
13273         if (wl_get_p2p_status(cfg, IF_CHANGING) || wl_get_p2p_status(cfg, IF_ADDING)) {
13274                 WL_ERR(("during IF change, ignore event %d\n", event_type));
13275                 return;
13276         }
13277
13278 #ifdef DHD_IFDEBUG
13279         if (event_type != WLC_E_ESCAN_RESULT) {
13280                 WL_ERR(("Event_type %d , status : %d, reason : %d, bssidx:%d \n",
13281                         event_type, ntoh32(e->status), ntoh32(e->reason), e->bsscfgidx));
13282         }
13283 #endif
13284         netinfo = wl_get_netinfo_by_bssidx(cfg, e->bsscfgidx);
13285         if (!netinfo) {
13286                 /* Since the netinfo entry is not there, the netdev entry is not
13287                  * created via cfg80211 interface. so the event is not of interest
13288                  * to the cfg80211 layer.
13289                  */
13290                 WL_ERR(("ignore event %d, not interested\n", event_type));
13291                 return;
13292         }
13293
13294         if (event_type == WLC_E_PFN_NET_FOUND) {
13295                 WL_DBG((" PNOEVENT: PNO_NET_FOUND\n"));
13296         }
13297         else if (event_type == WLC_E_PFN_NET_LOST) {
13298                 WL_DBG((" PNOEVENT: PNO_NET_LOST\n"));
13299         }
13300
13301         DHD_EVENT_WAKE_LOCK(cfg->pub);
13302         if (likely(!wl_enq_event(cfg, ndev, event_type, e, data))) {
13303                 wl_wakeup_event(cfg);
13304         } else {
13305                 DHD_EVENT_WAKE_UNLOCK(cfg->pub);
13306         }
13307 }
13308
13309 static void wl_init_eq(struct bcm_cfg80211 *cfg)
13310 {
13311         wl_init_eq_lock(cfg);
13312         INIT_LIST_HEAD(&cfg->eq_list);
13313 }
13314
13315 static void wl_flush_eq(struct bcm_cfg80211 *cfg)
13316 {
13317         struct wl_event_q *e;
13318         unsigned long flags;
13319
13320         flags = wl_lock_eq(cfg);
13321         while (!list_empty_careful(&cfg->eq_list)) {
13322                 BCM_SET_LIST_FIRST_ENTRY(e, &cfg->eq_list, struct wl_event_q, eq_list);
13323                 list_del(&e->eq_list);
13324                 kfree(e);
13325         }
13326         wl_unlock_eq(cfg, flags);
13327 }
13328
13329 /*
13330 * retrieve first queued event from head
13331 */
13332
13333 static struct wl_event_q *wl_deq_event(struct bcm_cfg80211 *cfg)
13334 {
13335         struct wl_event_q *e = NULL;
13336         unsigned long flags;
13337
13338         flags = wl_lock_eq(cfg);
13339         if (likely(!list_empty(&cfg->eq_list))) {
13340                 BCM_SET_LIST_FIRST_ENTRY(e, &cfg->eq_list, struct wl_event_q, eq_list);
13341                 list_del(&e->eq_list);
13342         }
13343         wl_unlock_eq(cfg, flags);
13344
13345         return e;
13346 }
13347
13348 /*
13349  * push event to tail of the queue
13350  */
13351
13352 static s32
13353 wl_enq_event(struct bcm_cfg80211 *cfg, struct net_device *ndev, u32 event,
13354         const wl_event_msg_t *msg, void *data)
13355 {
13356         struct wl_event_q *e;
13357         s32 err = 0;
13358         uint32 evtq_size;
13359         uint32 data_len;
13360         unsigned long flags;
13361         gfp_t aflags;
13362
13363         data_len = 0;
13364         if (data)
13365                 data_len = ntoh32(msg->datalen);
13366         evtq_size = sizeof(struct wl_event_q) + data_len;
13367         aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
13368         e = kzalloc(evtq_size, aflags);
13369         if (unlikely(!e)) {
13370                 WL_ERR(("event alloc failed\n"));
13371                 return -ENOMEM;
13372         }
13373         e->etype = event;
13374         memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
13375         if (data)
13376                 memcpy(e->edata, data, data_len);
13377         flags = wl_lock_eq(cfg);
13378         list_add_tail(&e->eq_list, &cfg->eq_list);
13379         wl_unlock_eq(cfg, flags);
13380
13381         return err;
13382 }
13383
13384 static void wl_put_event(struct wl_event_q *e)
13385 {
13386         kfree(e);
13387 }
13388
13389 static s32 wl_config_ifmode(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 iftype)
13390 {
13391         s32 infra = 0;
13392         s32 err = 0;
13393         s32 mode = 0;
13394         switch (iftype) {
13395         case NL80211_IFTYPE_MONITOR:
13396         case NL80211_IFTYPE_WDS:
13397                 WL_ERR(("type (%d) : currently we do not support this mode\n",
13398                         iftype));
13399                 err = -EINVAL;
13400                 return err;
13401         case NL80211_IFTYPE_ADHOC:
13402                 mode = WL_MODE_IBSS;
13403                 break;
13404         case NL80211_IFTYPE_STATION:
13405         case NL80211_IFTYPE_P2P_CLIENT:
13406                 mode = WL_MODE_BSS;
13407                 infra = 1;
13408                 break;
13409         case NL80211_IFTYPE_AP:
13410         case NL80211_IFTYPE_P2P_GO:
13411                 mode = WL_MODE_AP;
13412                 infra = 1;
13413                 break;
13414         default:
13415                 err = -EINVAL;
13416                 WL_ERR(("invalid type (%d)\n", iftype));
13417                 return err;
13418         }
13419         infra = htod32(infra);
13420         err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true);
13421         if (unlikely(err)) {
13422                 WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
13423                 return err;
13424         }
13425
13426         wl_set_mode_by_netdev(cfg, ndev, mode);
13427
13428         return 0;
13429 }
13430
13431 void wl_cfg80211_add_to_eventbuffer(struct wl_eventmsg_buf *ev, u16 event, bool set)
13432 {
13433         if (!ev || (event > WLC_E_LAST))
13434                 return;
13435
13436         if (ev->num < MAX_EVENT_BUF_NUM) {
13437                 ev->event[ev->num].type = event;
13438                 ev->event[ev->num].set = set;
13439                 ev->num++;
13440         } else {
13441                 WL_ERR(("evenbuffer doesn't support > %u events. Update"
13442                         " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM));
13443                 ASSERT(0);
13444         }
13445 }
13446
13447 s32 wl_cfg80211_apply_eventbuffer(
13448         struct net_device *ndev,
13449         struct bcm_cfg80211 *cfg,
13450         wl_eventmsg_buf_t *ev)
13451 {
13452         char eventmask[WL_EVENTING_MASK_LEN];
13453         int i, ret = 0;
13454         s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
13455
13456         if (!ev || (!ev->num))
13457                 return -EINVAL;
13458
13459         mutex_lock(&cfg->event_sync);
13460
13461         /* Read event_msgs mask */
13462         bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
13463                 sizeof(iovbuf));
13464         ret = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
13465         if (unlikely(ret)) {
13466                 WL_ERR(("Get event_msgs error (%d)\n", ret));
13467                 goto exit;
13468         }
13469         memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
13470
13471         /* apply the set bits */
13472         for (i = 0; i < ev->num; i++) {
13473                 if (ev->event[i].set)
13474                         setbit(eventmask, ev->event[i].type);
13475                 else
13476                         clrbit(eventmask, ev->event[i].type);
13477         }
13478
13479         /* Write updated Event mask */
13480         bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
13481                 sizeof(iovbuf));
13482         ret = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
13483         if (unlikely(ret)) {
13484                 WL_ERR(("Set event_msgs error (%d)\n", ret));
13485         }
13486
13487 exit:
13488         mutex_unlock(&cfg->event_sync);
13489         return ret;
13490 }
13491
13492 s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add)
13493 {
13494         s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
13495         s8 eventmask[WL_EVENTING_MASK_LEN];
13496         s32 err = 0;
13497         struct bcm_cfg80211 *cfg = g_bcm_cfg;
13498
13499         if (!ndev || !cfg)
13500                 return -ENODEV;
13501
13502         mutex_lock(&cfg->event_sync);
13503
13504         /* Setup event_msgs */
13505         bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
13506                 sizeof(iovbuf));
13507         err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
13508         if (unlikely(err)) {
13509                 WL_ERR(("Get event_msgs error (%d)\n", err));
13510                 goto eventmsg_out;
13511         }
13512         memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
13513         if (add) {
13514                 setbit(eventmask, event);
13515         } else {
13516                 clrbit(eventmask, event);
13517         }
13518         bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
13519                 sizeof(iovbuf));
13520         err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
13521         if (unlikely(err)) {
13522                 WL_ERR(("Set event_msgs error (%d)\n", err));
13523                 goto eventmsg_out;
13524         }
13525
13526 eventmsg_out:
13527         mutex_unlock(&cfg->event_sync);
13528         return err;
13529 }
13530
13531 static int wl_construct_reginfo(struct bcm_cfg80211 *cfg, s32 bw_cap)
13532 {
13533         struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
13534         struct ieee80211_channel *band_chan_arr = NULL;
13535         wl_uint32_list_t *list;
13536         u32 i, j, index, n_2g, n_5g, band, channel, array_size;
13537         u32 *n_cnt = NULL;
13538         chanspec_t c = 0;
13539         s32 err = BCME_OK;
13540         bool update;
13541         bool ht40_allowed;
13542         u8 *pbuf = NULL;
13543         bool dfs_radar_disabled = FALSE;
13544
13545 #define LOCAL_BUF_LEN 1024
13546         pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL);
13547
13548         if (pbuf == NULL) {
13549                 WL_ERR(("failed to allocate local buf\n"));
13550                 return -ENOMEM;
13551         }
13552         list = (wl_uint32_list_t *)(void *)pbuf;
13553         list->count = htod32(WL_NUMCHANSPECS);
13554
13555
13556         err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
13557                 0, pbuf, LOCAL_BUF_LEN, 0, &cfg->ioctl_buf_sync);
13558         if (err != 0) {
13559                 WL_ERR(("get chanspecs failed with %d\n", err));
13560                 kfree(pbuf);
13561                 return err;
13562         }
13563 #undef LOCAL_BUF_LEN
13564
13565         list = (wl_uint32_list_t *)(void *)pbuf;
13566         band = array_size = n_2g = n_5g = 0;
13567         for (i = 0; i < dtoh32(list->count); i++) {
13568                 index = 0;
13569                 update = false;
13570                 ht40_allowed = false;
13571                 c = (chanspec_t)dtoh32(list->element[i]);
13572                 c = wl_chspec_driver_to_host(c);
13573                 channel = wf_chspec_ctlchan(c);
13574
13575                 if (!CHSPEC_IS40(c) && ! CHSPEC_IS20(c)) {
13576                         WL_DBG(("HT80/160/80p80 center channel : %d\n", channel));
13577                         continue;
13578                 }
13579                 if (CHSPEC_IS2G(c) && (channel >= CH_MIN_2G_CHANNEL) &&
13580                         (channel <= CH_MAX_2G_CHANNEL)) {
13581                         band_chan_arr = __wl_2ghz_channels;
13582                         array_size = ARRAYSIZE(__wl_2ghz_channels);
13583                         n_cnt = &n_2g;
13584                         band = IEEE80211_BAND_2GHZ;
13585                         ht40_allowed = (bw_cap  == WLC_N_BW_40ALL)? true : false;
13586                 } else if (CHSPEC_IS5G(c) && channel >= CH_MIN_5G_CHANNEL) {
13587                         band_chan_arr = __wl_5ghz_a_channels;
13588                         array_size = ARRAYSIZE(__wl_5ghz_a_channels);
13589                         n_cnt = &n_5g;
13590                         band = IEEE80211_BAND_5GHZ;
13591                         ht40_allowed = (bw_cap  == WLC_N_BW_20ALL)? false : true;
13592                 } else {
13593                         WL_ERR(("Invalid channel Sepc. 0x%x.\n", c));
13594                         continue;
13595                 }
13596                 if (!ht40_allowed && CHSPEC_IS40(c))
13597                         continue;
13598                 for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
13599                         if (band_chan_arr[j].hw_value == channel) {
13600                                 update = true;
13601                                 break;
13602                         }
13603                 }
13604                 if (update)
13605                         index = j;
13606                 else
13607                         index = *n_cnt;
13608                 if (!dhd_conf_match_channel(cfg->pub, channel))
13609                         continue;
13610                 if (index <  array_size) {
13611 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
13612                         band_chan_arr[index].center_freq =
13613                                 ieee80211_channel_to_frequency(channel);
13614 #else
13615                         band_chan_arr[index].center_freq =
13616                                 ieee80211_channel_to_frequency(channel, band);
13617 #endif
13618                         band_chan_arr[index].hw_value = channel;
13619                         WL_DBG(("channel = %d\n", channel));
13620
13621                         if (CHSPEC_IS40(c) && ht40_allowed) {
13622                                 /* assuming the order is HT20, HT40 Upper,
13623                                  *  HT40 lower from chanspecs
13624                                  */
13625                                 u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
13626                                 if (CHSPEC_SB_UPPER(c)) {
13627                                         if (ht40_flag == IEEE80211_CHAN_NO_HT40)
13628                                                 band_chan_arr[index].flags &=
13629                                                         ~IEEE80211_CHAN_NO_HT40;
13630                                         band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
13631                                 } else {
13632                                         /* It should be one of
13633                                          * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
13634                                          */
13635                                         band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
13636                                         if (ht40_flag == IEEE80211_CHAN_NO_HT40)
13637                                                 band_chan_arr[index].flags |=
13638                                                         IEEE80211_CHAN_NO_HT40MINUS;
13639                                 }
13640                         } else {
13641                                 band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
13642                                 if (!dfs_radar_disabled) {
13643                                         if (band == IEEE80211_BAND_2GHZ)
13644                                                 channel |= WL_CHANSPEC_BAND_2G;
13645                                         else
13646                                                 channel |= WL_CHANSPEC_BAND_5G;
13647                                         channel |= WL_CHANSPEC_BW_20;
13648                                         channel = wl_chspec_host_to_driver(channel);
13649                                         err = wldev_iovar_getint(dev, "per_chan_info", &channel);
13650                                         if (!err) {
13651                                                 if (channel & WL_CHAN_RADAR) {
13652 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
13653                                                         band_chan_arr[index].flags |=
13654                                                                 (IEEE80211_CHAN_RADAR
13655                                                                 | IEEE80211_CHAN_NO_IBSS);
13656 #else
13657                                                         band_chan_arr[index].flags |=
13658                                                                 IEEE80211_CHAN_RADAR;
13659 #endif
13660                                                 }
13661
13662                                                 if (channel & WL_CHAN_PASSIVE)
13663 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
13664                                                         band_chan_arr[index].flags |=
13665                                                                 IEEE80211_CHAN_PASSIVE_SCAN;
13666 #else
13667                                                         band_chan_arr[index].flags |=
13668                                                                 IEEE80211_CHAN_NO_IR;
13669 #endif
13670                                         } else if (err == BCME_UNSUPPORTED) {
13671                                                 dfs_radar_disabled = TRUE;
13672                                                 WL_ERR(("does not support per_chan_info\n"));
13673                                         }
13674                                 }
13675                         }
13676                         if (!update)
13677                                 (*n_cnt)++;
13678                 }
13679
13680         }
13681         __wl_band_2ghz.n_channels = n_2g;
13682         __wl_band_5ghz_a.n_channels = n_5g;
13683         kfree(pbuf);
13684         return err;
13685 }
13686
13687 s32 wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify)
13688 {
13689         struct wiphy *wiphy;
13690         struct net_device *dev;
13691         u32 bandlist[3];
13692         u32 nband = 0;
13693         u32 i = 0;
13694         s32 err = 0;
13695         s32 index = 0;
13696         s32 nmode = 0;
13697 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
13698         u32 j = 0;
13699         s32 vhtmode = 0;
13700         s32 txstreams = 0;
13701         s32 rxstreams = 0;
13702         s32 ldpc_cap = 0;
13703         s32 stbc_rx = 0;
13704         s32 stbc_tx = 0;
13705         s32 txbf_bfe_cap = 0;
13706         s32 txbf_bfr_cap = 0;
13707 #endif 
13708         bool rollback_lock = false;
13709         s32 bw_cap = 0;
13710         s32 cur_band = -1;
13711         struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS] = {NULL, };
13712
13713         if (cfg == NULL) {
13714                 cfg = g_bcm_cfg;
13715                 mutex_lock(&cfg->usr_sync);
13716                 rollback_lock = true;
13717         }
13718         dev = bcmcfg_to_prmry_ndev(cfg);
13719
13720         memset(bandlist, 0, sizeof(bandlist));
13721         err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist,
13722                 sizeof(bandlist), false);
13723         if (unlikely(err)) {
13724                 WL_ERR(("error read bandlist (%d)\n", err));
13725                 goto end_bands;
13726         }
13727         err = wldev_ioctl(dev, WLC_GET_BAND, &cur_band,
13728                 sizeof(s32), false);
13729         if (unlikely(err)) {
13730                 WL_ERR(("error (%d)\n", err));
13731                 goto end_bands;
13732         }
13733
13734         err = wldev_iovar_getint(dev, "nmode", &nmode);
13735         if (unlikely(err)) {
13736                 WL_ERR(("error reading nmode (%d)\n", err));
13737         }
13738
13739 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
13740         err = wldev_iovar_getint(dev, "vhtmode", &vhtmode);
13741         if (unlikely(err)) {
13742                 WL_ERR(("error reading vhtmode (%d)\n", err));
13743         }
13744
13745         if (vhtmode) {
13746                 err = wldev_iovar_getint(dev, "txstreams", &txstreams);
13747                 if (unlikely(err)) {
13748                         WL_ERR(("error reading txstreams (%d)\n", err));
13749                 }
13750
13751                 err = wldev_iovar_getint(dev, "rxstreams", &rxstreams);
13752                 if (unlikely(err)) {
13753                         WL_ERR(("error reading rxstreams (%d)\n", err));
13754                 }
13755
13756                 err = wldev_iovar_getint(dev, "ldpc_cap", &ldpc_cap);
13757                 if (unlikely(err)) {
13758                         WL_ERR(("error reading ldpc_cap (%d)\n", err));
13759                 }
13760
13761                 err = wldev_iovar_getint(dev, "stbc_rx", &stbc_rx);
13762                 if (unlikely(err)) {
13763                         WL_ERR(("error reading stbc_rx (%d)\n", err));
13764                 }
13765
13766                 err = wldev_iovar_getint(dev, "stbc_tx", &stbc_tx);
13767                 if (unlikely(err)) {
13768                         WL_ERR(("error reading stbc_tx (%d)\n", err));
13769                 }
13770
13771                 err = wldev_iovar_getint(dev, "txbf_bfe_cap", &txbf_bfe_cap);
13772                 if (unlikely(err)) {
13773                         WL_ERR(("error reading txbf_bfe_cap (%d)\n", err));
13774                 }
13775
13776                 err = wldev_iovar_getint(dev, "txbf_bfr_cap", &txbf_bfr_cap);
13777                 if (unlikely(err)) {
13778                         WL_ERR(("error reading txbf_bfr_cap (%d)\n", err));
13779                 }
13780         }
13781 #endif 
13782
13783         /* For nmode and vhtmode   check bw cap */
13784         if (nmode ||
13785 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
13786                 vhtmode ||
13787 #endif 
13788                 0) {
13789                 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
13790                 if (unlikely(err)) {
13791                         WL_ERR(("error get mimo_bw_cap (%d)\n", err));
13792                 }
13793         }
13794
13795         err = wl_construct_reginfo(cfg, bw_cap);
13796         if (err) {
13797                 WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
13798                 if (err != BCME_UNSUPPORTED)
13799                         goto end_bands;
13800                 err = 0;
13801         }
13802         wiphy = bcmcfg_to_wiphy(cfg);
13803         nband = bandlist[0];
13804
13805         for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) {
13806                 index = -1;
13807                 if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
13808                         bands[IEEE80211_BAND_5GHZ] =
13809                                 &__wl_band_5ghz_a;
13810                         index = IEEE80211_BAND_5GHZ;
13811                         if (nmode && (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G))
13812                                 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
13813
13814 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
13815                         /* VHT capabilities. */
13816                         if (vhtmode) {
13817                                 /* Supported */
13818                                 bands[index]->vht_cap.vht_supported = TRUE;
13819
13820                                 for (j = 1; j <= VHT_CAP_MCS_MAP_NSS_MAX; j++) {
13821                                         /* TX stream rates. */
13822                                         if (j <= txstreams) {
13823                                                 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_0_9,
13824                                                         bands[index]->vht_cap.vht_mcs.tx_mcs_map);
13825                                         } else {
13826                                                 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_NONE,
13827                                                         bands[index]->vht_cap.vht_mcs.tx_mcs_map);
13828                                         }
13829
13830                                         /* RX stream rates. */
13831                                         if (j <= rxstreams) {
13832                                                 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_0_9,
13833                                                         bands[index]->vht_cap.vht_mcs.rx_mcs_map);
13834                                         } else {
13835                                                 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_NONE,
13836                                                         bands[index]->vht_cap.vht_mcs.rx_mcs_map);
13837                                         }
13838                                 }
13839
13840
13841                                 /* Capabilities */
13842                                 /* 80 MHz is mandatory */
13843                                 bands[index]->vht_cap.cap |=
13844                                         IEEE80211_VHT_CAP_SHORT_GI_80;
13845
13846                                 if (WL_BW_CAP_160MHZ(bw_cap)) {
13847                                         bands[index]->vht_cap.cap |=
13848                                                 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
13849                                         bands[index]->vht_cap.cap |=
13850                                                 IEEE80211_VHT_CAP_SHORT_GI_160;
13851                                 }
13852
13853                                 bands[index]->vht_cap.cap |=
13854                                         IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
13855
13856                                 if (ldpc_cap)
13857                                         bands[index]->vht_cap.cap |=
13858                                                 IEEE80211_VHT_CAP_RXLDPC;
13859
13860                                 if (stbc_tx)
13861                                         bands[index]->vht_cap.cap |=
13862                                                 IEEE80211_VHT_CAP_TXSTBC;
13863
13864                                 if (stbc_rx)
13865                                         bands[index]->vht_cap.cap |=
13866                                                 (stbc_rx << VHT_CAP_INFO_RX_STBC_SHIFT);
13867
13868                                 if (txbf_bfe_cap)
13869                                         bands[index]->vht_cap.cap |=
13870                                                 IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
13871
13872                                 if (txbf_bfr_cap) {
13873                                         bands[index]->vht_cap.cap |=
13874                                                 IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
13875                                 }
13876
13877                                 if (txbf_bfe_cap || txbf_bfr_cap) {
13878                                         bands[index]->vht_cap.cap |=
13879                                                 (2 << VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT);
13880                                         bands[index]->vht_cap.cap |=
13881                                                 ((txstreams - 1) <<
13882                                                         VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT);
13883                                         bands[index]->vht_cap.cap |=
13884                                                 IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
13885                                 }
13886
13887                                 /* AMPDU length limit, support max 1MB (2 ^ (13 + 7)) */
13888                                 bands[index]->vht_cap.cap |=
13889                                         (7 << VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT);
13890                                 WL_INFORM(("%s band[%d] vht_enab=%d vht_cap=%08x "
13891                                         "vht_rx_mcs_map=%04x vht_tx_mcs_map=%04x\n",
13892                                         __FUNCTION__, index,
13893                                         bands[index]->vht_cap.vht_supported,
13894                                         bands[index]->vht_cap.cap,
13895                                         bands[index]->vht_cap.vht_mcs.rx_mcs_map,
13896                                         bands[index]->vht_cap.vht_mcs.tx_mcs_map));
13897                         }
13898 #endif 
13899                 }
13900                 else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
13901                         bands[IEEE80211_BAND_2GHZ] =
13902                                 &__wl_band_2ghz;
13903                         index = IEEE80211_BAND_2GHZ;
13904                         if (bw_cap == WLC_N_BW_40ALL)
13905                                 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
13906                 }
13907
13908                 if ((index >= 0) && nmode) {
13909                         bands[index]->ht_cap.cap |=
13910                                 (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40);
13911                         bands[index]->ht_cap.ht_supported = TRUE;
13912                         bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
13913                         bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
13914                         /* An HT shall support all EQM rates for one spatial stream */
13915                         bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
13916                 }
13917
13918         }
13919
13920         wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
13921         wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
13922
13923         /* check if any bands populated otherwise makes 2Ghz as default */
13924         if (wiphy->bands[IEEE80211_BAND_2GHZ] == NULL &&
13925                 wiphy->bands[IEEE80211_BAND_5GHZ] == NULL) {
13926                 /* Setup 2Ghz band as default */
13927                 wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
13928         }
13929
13930         if (notify)
13931                 wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
13932
13933 end_bands:
13934         if (rollback_lock)
13935                 mutex_unlock(&cfg->usr_sync);
13936         return err;
13937 }
13938
13939 static s32 __wl_cfg80211_up(struct bcm_cfg80211 *cfg)
13940 {
13941         s32 err = 0;
13942         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
13943         struct wireless_dev *wdev = ndev->ieee80211_ptr;
13944
13945         WL_DBG(("In\n"));
13946
13947         err = wl_create_event_handler(cfg);
13948         if (err) {
13949                 WL_ERR(("wl_create_event_handler failed\n"));
13950                 return err;
13951         }
13952         wl_init_event_handler(cfg);
13953
13954         err = dhd_config_dongle(cfg);
13955         if (unlikely(err))
13956                 return err;
13957
13958         err = wl_config_ifmode(cfg, ndev, wdev->iftype);
13959         if (unlikely(err && err != -EINPROGRESS)) {
13960                 WL_ERR(("wl_config_ifmode failed\n"));
13961                 if (err == -1) {
13962                         WL_ERR(("return error %d\n", err));
13963                         return err;
13964                 }
13965         }
13966
13967         err = wl_init_scan(cfg);
13968         if (err) {
13969                 WL_ERR(("wl_init_scan failed\n"));
13970                 return err;
13971         }
13972         err = wl_update_wiphybands(cfg, true);
13973         if (unlikely(err)) {
13974                 WL_ERR(("wl_update_wiphybands failed\n"));
13975                 if (err == -1) {
13976                         WL_ERR(("return error %d\n", err));
13977                         return err;
13978                 }
13979         }
13980 #ifdef DHD_LOSSLESS_ROAMING
13981         if (timer_pending(&cfg->roam_timeout)) {
13982                 del_timer_sync(&cfg->roam_timeout);
13983         }
13984 #endif /* DHD_LOSSLESS_ROAMING */
13985
13986         err = dhd_monitor_init(cfg->pub);
13987
13988         wl_set_drv_status(cfg, READY, ndev);
13989         return err;
13990 }
13991
13992 static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg)
13993 {
13994         s32 err = 0;
13995         unsigned long flags;
13996         struct net_info *iter, *next;
13997         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
13998 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
13999         struct net_device *p2p_net = cfg->p2p_net;
14000 #endif 
14001 #ifdef PROP_TXSTATUS_VSDB
14002 #if defined(BCMSDIO)
14003         dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
14004 #endif
14005 #endif /* PROP_TXSTATUS_VSDB */
14006         WL_DBG(("In\n"));
14007         /* Delete pm_enable_work */
14008         wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
14009
14010 #ifdef WL_NAN
14011         wl_cfgnan_stop_handler(ndev, g_bcm_cfg, NULL, 0, NULL);
14012 #endif /* WL_NAN */
14013
14014         if (cfg->p2p_supported) {
14015                 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
14016 #ifdef PROP_TXSTATUS_VSDB
14017 #if defined(BCMSDIO)
14018                 if (wl_cfgp2p_vif_created(cfg)) {
14019                         bool enabled = false;
14020                         dhd_wlfc_get_enable(dhd, &enabled);
14021                         if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
14022                                 dhd->op_mode != DHD_FLAG_IBSS_MODE) {
14023                                 dhd_wlfc_deinit(dhd);
14024                                 cfg->wlfc_on = false;
14025                         }
14026                 }
14027 #endif 
14028 #endif /* PROP_TXSTATUS_VSDB */
14029         }
14030
14031
14032         /* If primary BSS is operational (for e.g SoftAP), bring it down */
14033         if (wl_cfgp2p_bss_isup(ndev, 0)) {
14034                 if (wl_cfgp2p_bss(cfg, ndev, 0, 0) < 0)
14035                         WL_ERR(("BSS down failed \n"));
14036         }
14037
14038         /* Check if cfg80211 interface is already down */
14039         if (!wl_get_drv_status(cfg, READY, ndev))
14040                 return err;     /* it is even not ready */
14041
14042         /* clear all the security setting on primary Interface */
14043         wl_cfg80211_clear_security(cfg);
14044
14045 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14046         4 && __GNUC_MINOR__ >= 6))
14047 _Pragma("GCC diagnostic push")
14048 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
14049 #endif
14050         for_each_ndev(cfg, iter, next) {
14051                 if (iter->ndev) /* p2p discovery iface is null */
14052                         wl_set_drv_status(cfg, SCAN_ABORTING, iter->ndev);
14053         }
14054 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14055         4 && __GNUC_MINOR__ >= 6))
14056 _Pragma("GCC diagnostic pop")
14057 #endif
14058
14059 #ifdef P2P_LISTEN_OFFLOADING
14060         wl_cfg80211_p2plo_deinit(cfg);
14061 #endif /* P2P_LISTEN_OFFLOADING */
14062
14063         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
14064         if (cfg->scan_request) {
14065                 cfg80211_scan_done(cfg->scan_request, true);
14066                 cfg->scan_request = NULL;
14067         }
14068         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
14069 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14070         4 && __GNUC_MINOR__ >= 6))
14071 _Pragma("GCC diagnostic push")
14072 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
14073 #endif
14074         for_each_ndev(cfg, iter, next) {
14075                 /* p2p discovery iface ndev ptr could be null */
14076                 if (iter->ndev == NULL)
14077                         continue;
14078                 wl_clr_drv_status(cfg, READY, iter->ndev);
14079                 wl_clr_drv_status(cfg, SCANNING, iter->ndev);
14080                 wl_clr_drv_status(cfg, SCAN_ABORTING, iter->ndev);
14081                 wl_clr_drv_status(cfg, CONNECTING, iter->ndev);
14082                 wl_clr_drv_status(cfg, CONNECTED, iter->ndev);
14083                 wl_clr_drv_status(cfg, DISCONNECTING, iter->ndev);
14084                 wl_clr_drv_status(cfg, AP_CREATED, iter->ndev);
14085                 wl_clr_drv_status(cfg, AP_CREATING, iter->ndev);
14086         }
14087 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14088         4 && __GNUC_MINOR__ >= 6))
14089 _Pragma("GCC diagnostic pop")
14090 #endif
14091         bcmcfg_to_prmry_ndev(cfg)->ieee80211_ptr->iftype =
14092                 NL80211_IFTYPE_STATION;
14093 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
14094                 if (p2p_net)
14095                         dev_close(p2p_net);
14096 #endif 
14097
14098         /* Avoid deadlock from wl_cfg80211_down */
14099         mutex_unlock(&cfg->usr_sync);
14100         wl_destroy_event_handler(cfg);
14101         mutex_lock(&cfg->usr_sync);
14102         wl_flush_eq(cfg);
14103         wl_link_down(cfg);
14104         if (cfg->p2p_supported) {
14105                 if (timer_pending(&cfg->p2p->listen_timer))
14106                         del_timer_sync(&cfg->p2p->listen_timer);
14107                 wl_cfgp2p_down(cfg);
14108         }
14109
14110         if (timer_pending(&cfg->scan_timeout)) {
14111                 del_timer_sync(&cfg->scan_timeout);
14112         }
14113
14114         DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
14115
14116         dhd_monitor_uninit();
14117 #ifdef WLAIBSS_MCHAN
14118         bcm_cfg80211_del_ibss_if(cfg->wdev->wiphy, cfg->ibss_cfgdev);
14119 #endif /* WLAIBSS_MCHAN */
14120
14121 #if defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF)
14122         /* Clean up if not removed already */
14123         if (cfg->bss_cfgdev)
14124                 wl_cfg80211_del_iface(cfg->wdev->wiphy, cfg->bss_cfgdev);
14125 #endif /* defined (WL_VIRTUAL_APSTA) || defined (DUAL_STA_STATIC_IF) */
14126
14127 #ifdef WL11U
14128         /* Clear interworking element. */
14129         if (cfg->wl11u) {
14130                 cfg->wl11u = FALSE;
14131                 cfg->iw_ie_len = 0;
14132                 memset(cfg->iw_ie, 0, IW_IES_MAX_BUF_LEN);
14133         }
14134 #endif /* WL11U */
14135
14136 #ifdef CUSTOMER_HW4_DEBUG
14137         if (wl_scan_timeout_dbg_enabled)
14138                 wl_scan_timeout_dbg_clear();
14139 #endif /* CUSTOMER_HW4_DEBUG */
14140
14141         cfg->disable_roam_event = false;
14142
14143         DNGL_FUNC(dhd_cfg80211_down, (cfg));
14144
14145 #ifdef DHD_IFDEBUG
14146         /* Printout all netinfo entries */
14147         wl_probe_wdev_all(cfg);
14148 #endif /* DHD_IFDEBUG */
14149
14150         return err;
14151 }
14152
14153 s32 wl_cfg80211_up(void *para)
14154 {
14155         struct bcm_cfg80211 *cfg;
14156         s32 err = 0;
14157         int val = 1;
14158         dhd_pub_t *dhd;
14159 #ifdef DISABLE_PM_BCNRX
14160         s32 interr = 0;
14161         uint param = 0;
14162         s8 iovbuf[WLC_IOCTL_SMLEN];
14163 #endif /* DISABLE_PM_BCNRX */
14164
14165         (void)para;
14166         WL_DBG(("In\n"));
14167         cfg = g_bcm_cfg;
14168
14169         if ((err = wldev_ioctl(bcmcfg_to_prmry_ndev(cfg), WLC_GET_VERSION, &val,
14170                 sizeof(int), false) < 0)) {
14171                 WL_ERR(("WLC_GET_VERSION failed, err=%d\n", err));
14172                 return err;
14173         }
14174         val = dtoh32(val);
14175         if (val != WLC_IOCTL_VERSION && val != 1) {
14176                 WL_ERR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
14177                         val, WLC_IOCTL_VERSION));
14178                 return BCME_VERSION;
14179         }
14180         ioctl_version = val;
14181         WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version));
14182
14183         mutex_lock(&cfg->usr_sync);
14184         dhd = (dhd_pub_t *)(cfg->pub);
14185         if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
14186                 err = wl_cfg80211_attach_post(bcmcfg_to_prmry_ndev(cfg));
14187                 if (unlikely(err)) {
14188                         mutex_unlock(&cfg->usr_sync);
14189                         return err;
14190                 }
14191         }
14192         err = __wl_cfg80211_up(cfg);
14193         if (unlikely(err))
14194                 WL_ERR(("__wl_cfg80211_up failed\n"));
14195
14196
14197
14198         /* IOVAR configurations with 'up' condition */
14199 #ifdef DISABLE_PM_BCNRX
14200         bcm_mkiovar("pm_bcnrx", (char *)&param, 4, iovbuf, sizeof(iovbuf));
14201         interr = wldev_ioctl(bcmcfg_to_prmry_ndev(cfg), WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
14202         if (unlikely(interr))
14203                 WL_ERR(("Set pm_bcnrx returned (%d)\n", interr));
14204 #endif /* DISABLE_PM_BCNRX */
14205
14206         mutex_unlock(&cfg->usr_sync);
14207
14208 #ifdef WLAIBSS_MCHAN
14209         bcm_cfg80211_add_ibss_if(cfg->wdev->wiphy, IBSS_IF_NAME);
14210 #endif /* WLAIBSS_MCHAN */
14211
14212 #ifdef DUAL_STA_STATIC_IF
14213 #ifdef WL_VIRTUAL_APSTA
14214 #error "Both DUAL STA and DUAL_STA_STATIC_IF can't be enabled together"
14215 #endif
14216         /* Static Interface support is currently supported only for STA only builds (without P2P) */
14217         wl_cfg80211_create_iface(cfg->wdev->wiphy, NL80211_IFTYPE_STATION, NULL, "wlan%d");
14218 #endif /* DUAL_STA_STATIC_IF */
14219
14220         return err;
14221 }
14222
14223 /* Private Event to Supplicant with indication that chip hangs */
14224 int wl_cfg80211_hang(struct net_device *dev, u16 reason)
14225 {
14226         struct bcm_cfg80211 *cfg;
14227         dhd_pub_t *dhd;
14228 #if defined(SOFTAP_SEND_HANGEVT)
14229         /* specifc mac address used for hang event */
14230         uint8 hang_mac[ETHER_ADDR_LEN] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
14231 #endif /* SOFTAP_SEND_HANGEVT */
14232         if (!g_bcm_cfg) {
14233                 return BCME_ERROR;
14234         }
14235
14236         cfg = g_bcm_cfg;
14237         dhd = (dhd_pub_t *)(cfg->pub);
14238
14239 #ifdef DHD_USE_EXTENDED_HANG_REASON
14240         if (dhd->hang_reason != 0) {
14241                 reason = dhd->hang_reason;
14242         }
14243 #endif /* DHD_USE_EXTENDED_HANG_REASON */
14244
14245         WL_ERR(("In : chip crash eventing, reason=0x%x\n", (uint32)(dhd->hang_reason)));
14246         wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
14247 #if defined(SOFTAP_SEND_HANGEVT)
14248         if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
14249                 cfg80211_del_sta(dev, hang_mac, GFP_ATOMIC);
14250         } else
14251 #endif /* SOFTAP_SEND_HANGEVT */
14252         {
14253                 CFG80211_DISCONNECTED(dev, reason, NULL, 0, false, GFP_KERNEL);
14254         }
14255 #if defined(RSSIAVG)
14256         wl_free_rssi_cache(&g_rssi_cache_ctrl);
14257 #endif
14258 #if defined(BSSCACHE)
14259         wl_free_bss_cache(&g_bss_cache_ctrl);
14260 #endif
14261         if (cfg != NULL) {
14262                 wl_link_down(cfg);
14263         }
14264         return 0;
14265 }
14266
14267 s32 wl_cfg80211_down(void *para)
14268 {
14269         struct bcm_cfg80211 *cfg;
14270         s32 err = 0;
14271
14272         (void)para;
14273         WL_DBG(("In\n"));
14274         cfg = g_bcm_cfg;
14275         mutex_lock(&cfg->usr_sync);
14276 #if defined(RSSIAVG)
14277         wl_free_rssi_cache(&g_rssi_cache_ctrl);
14278 #endif
14279 #if defined(BSSCACHE)
14280         wl_free_bss_cache(&g_bss_cache_ctrl);
14281 #endif
14282         err = __wl_cfg80211_down(cfg);
14283         mutex_unlock(&cfg->usr_sync);
14284
14285         return err;
14286 }
14287
14288 static void *wl_read_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 item)
14289 {
14290         unsigned long flags;
14291         void *rptr = NULL;
14292         struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
14293
14294         if (!profile)
14295                 return NULL;
14296         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
14297         switch (item) {
14298         case WL_PROF_SEC:
14299                 rptr = &profile->sec;
14300                 break;
14301         case WL_PROF_ACT:
14302                 rptr = &profile->active;
14303                 break;
14304         case WL_PROF_BSSID:
14305                 rptr = profile->bssid;
14306                 break;
14307         case WL_PROF_SSID:
14308                 rptr = &profile->ssid;
14309                 break;
14310         case WL_PROF_CHAN:
14311                 rptr = &profile->channel;
14312                 break;
14313         }
14314         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
14315         if (!rptr)
14316                 WL_ERR(("invalid item (%d)\n", item));
14317         return rptr;
14318 }
14319
14320 static s32
14321 wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
14322         const wl_event_msg_t *e, const void *data, s32 item)
14323 {
14324         s32 err = 0;
14325         const struct wlc_ssid *ssid;
14326         unsigned long flags;
14327         struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
14328
14329         if (!profile)
14330                 return WL_INVALID;
14331         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
14332         switch (item) {
14333         case WL_PROF_SSID:
14334                 ssid = (const wlc_ssid_t *) data;
14335                 memset(profile->ssid.SSID, 0,
14336                         sizeof(profile->ssid.SSID));
14337                 memcpy(profile->ssid.SSID, ssid->SSID, ssid->SSID_len);
14338                 profile->ssid.SSID_len = ssid->SSID_len;
14339                 break;
14340         case WL_PROF_BSSID:
14341                 if (data)
14342                         memcpy(profile->bssid, data, ETHER_ADDR_LEN);
14343                 else
14344                         memset(profile->bssid, 0, ETHER_ADDR_LEN);
14345                 break;
14346         case WL_PROF_SEC:
14347                 memcpy(&profile->sec, data, sizeof(profile->sec));
14348                 break;
14349         case WL_PROF_ACT:
14350                 profile->active = *(const bool *)data;
14351                 break;
14352         case WL_PROF_BEACONINT:
14353                 profile->beacon_interval = *(const u16 *)data;
14354                 break;
14355         case WL_PROF_DTIMPERIOD:
14356                 profile->dtim_period = *(const u8 *)data;
14357                 break;
14358         case WL_PROF_CHAN:
14359                 profile->channel = *(const u32*)data;
14360                 break;
14361         default:
14362                 err = -EOPNOTSUPP;
14363                 break;
14364         }
14365         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
14366
14367         if (err == -EOPNOTSUPP)
14368                 WL_ERR(("unsupported item (%d)\n", item));
14369
14370         return err;
14371 }
14372
14373 void wl_cfg80211_dbg_level(u32 level)
14374 {
14375         /*
14376         * prohibit to change debug level
14377         * by insmod parameter.
14378         * eventually debug level will be configured
14379         * in compile time by using CONFIG_XXX
14380         */
14381         /* wl_dbg_level = level; */
14382 }
14383
14384 static bool wl_is_ibssmode(struct bcm_cfg80211 *cfg, struct net_device *ndev)
14385 {
14386         return wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS;
14387 }
14388
14389 static __used bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg)
14390 {
14391         return cfg->ibss_starter;
14392 }
14393
14394 static void wl_rst_ie(struct bcm_cfg80211 *cfg)
14395 {
14396         struct wl_ie *ie = wl_to_ie(cfg);
14397
14398         ie->offset = 0;
14399 }
14400
14401 static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v)
14402 {
14403         struct wl_ie *ie = wl_to_ie(cfg);
14404         s32 err = 0;
14405
14406         if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
14407                 WL_ERR(("ei crosses buffer boundary\n"));
14408                 return -ENOSPC;
14409         }
14410         ie->buf[ie->offset] = t;
14411         ie->buf[ie->offset + 1] = l;
14412         memcpy(&ie->buf[ie->offset + 2], v, l);
14413         ie->offset += l + 2;
14414
14415         return err;
14416 }
14417
14418 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, const u8 *ie_stream, u32 *ie_size,
14419         bool roam)
14420 {
14421         u8 *ssidie;
14422         /* cfg80211_find_ie defined in kernel returning const u8 */
14423 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14424         4 && __GNUC_MINOR__ >= 6))
14425 _Pragma("GCC diagnostic push")
14426 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
14427 #endif
14428         ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size);
14429 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14430         4 && __GNUC_MINOR__ >= 6))
14431 _Pragma("GCC diagnostic pop")
14432 #endif
14433         if (!ssidie)
14434                 return;
14435         if (ssidie[1] != bi->SSID_len) {
14436                 if (ssidie[1]) {
14437                         WL_ERR(("%s: Wrong SSID len: %d != %d\n",
14438                                 __FUNCTION__, ssidie[1], bi->SSID_len));
14439                 }
14440                 if (roam) {
14441                         WL_ERR(("Changing the SSID Info.\n"));
14442                         memmove(ssidie + bi->SSID_len + 2,
14443                                 (ssidie + 2) + ssidie[1],
14444                                 *ie_size - (ssidie + 2 + ssidie[1] - ie_stream));
14445                         memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
14446                         *ie_size = *ie_size + bi->SSID_len - ssidie[1];
14447                         ssidie[1] = bi->SSID_len;
14448                 }
14449                 return;
14450         }
14451         if (*(ssidie + 2) == '\0')
14452                  memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
14453         return;
14454 }
14455
14456 static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size)
14457 {
14458         struct wl_ie *ie = wl_to_ie(cfg);
14459         s32 err = 0;
14460
14461         if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
14462                 WL_ERR(("ei_stream crosses buffer boundary\n"));
14463                 return -ENOSPC;
14464         }
14465         memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
14466         ie->offset += ie_size;
14467
14468         return err;
14469 }
14470
14471 static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size)
14472 {
14473         struct wl_ie *ie = wl_to_ie(cfg);
14474         s32 err = 0;
14475
14476         if (unlikely(ie->offset > dst_size)) {
14477                 WL_ERR(("dst_size is not enough\n"));
14478                 return -ENOSPC;
14479         }
14480         memcpy(dst, &ie->buf[0], ie->offset);
14481
14482         return err;
14483 }
14484
14485 static u32 wl_get_ielen(struct bcm_cfg80211 *cfg)
14486 {
14487         struct wl_ie *ie = wl_to_ie(cfg);
14488
14489         return ie->offset;
14490 }
14491
14492 static void wl_link_up(struct bcm_cfg80211 *cfg)
14493 {
14494         cfg->link_up = true;
14495 }
14496
14497 static void wl_link_down(struct bcm_cfg80211 *cfg)
14498 {
14499         struct wl_connect_info *conn_info = wl_to_conn(cfg);
14500
14501         WL_DBG(("In\n"));
14502         cfg->link_up = false;
14503         conn_info->req_ie_len = 0;
14504         conn_info->resp_ie_len = 0;
14505 }
14506
14507 static unsigned long wl_lock_eq(struct bcm_cfg80211 *cfg)
14508 {
14509         unsigned long flags;
14510
14511         spin_lock_irqsave(&cfg->eq_lock, flags);
14512         return flags;
14513 }
14514
14515 static void wl_unlock_eq(struct bcm_cfg80211 *cfg, unsigned long flags)
14516 {
14517         spin_unlock_irqrestore(&cfg->eq_lock, flags);
14518 }
14519
14520 static void wl_init_eq_lock(struct bcm_cfg80211 *cfg)
14521 {
14522         spin_lock_init(&cfg->eq_lock);
14523 }
14524
14525 static void wl_delay(u32 ms)
14526 {
14527         if (in_atomic() || (ms < jiffies_to_msecs(1))) {
14528                 OSL_DELAY(ms*1000);
14529         } else {
14530                 OSL_SLEEP(ms);
14531         }
14532 }
14533
14534 s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
14535 {
14536         struct bcm_cfg80211 *cfg = g_bcm_cfg;
14537         struct ether_addr primary_mac;
14538         if (!cfg->p2p)
14539                 return -1;
14540         if (!p2p_is_on(cfg)) {
14541                 get_primary_mac(cfg, &primary_mac);
14542                 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
14543         } else {
14544                 memcpy(p2pdev_addr->octet, wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE).octet,
14545                         ETHER_ADDR_LEN);
14546         }
14547
14548         return 0;
14549 }
14550 s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
14551 {
14552         struct bcm_cfg80211 *cfg;
14553
14554         cfg = g_bcm_cfg;
14555
14556         return wl_cfgp2p_set_p2p_noa(cfg, net, buf, len);
14557 }
14558
14559 s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
14560 {
14561         struct bcm_cfg80211 *cfg;
14562         cfg = g_bcm_cfg;
14563
14564         return wl_cfgp2p_get_p2p_noa(cfg, net, buf, len);
14565 }
14566
14567 s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
14568 {
14569         struct bcm_cfg80211 *cfg;
14570         cfg = g_bcm_cfg;
14571
14572         return wl_cfgp2p_set_p2p_ps(cfg, net, buf, len);
14573 }
14574
14575 s32 wl_cfg80211_set_p2p_ecsa(struct net_device *net, char* buf, int len)
14576 {
14577         struct bcm_cfg80211 *cfg;
14578         cfg = g_bcm_cfg;
14579
14580         return wl_cfgp2p_set_p2p_ecsa(cfg, net, buf, len);
14581 }
14582
14583 #ifdef P2PLISTEN_AP_SAMECHN
14584 s32 wl_cfg80211_set_p2p_resp_ap_chn(struct net_device *net, s32 enable)
14585 {
14586         s32 ret = wldev_iovar_setint(net, "p2p_resp_ap_chn", enable);
14587
14588         if ((ret == 0) && enable) {
14589                 /* disable PM for p2p responding on infra AP channel */
14590                 s32 pm = PM_OFF;
14591
14592                 ret = wldev_ioctl(net, WLC_SET_PM, &pm, sizeof(pm), true);
14593         }
14594
14595         return ret;
14596 }
14597 #endif /* P2PLISTEN_AP_SAMECHN */
14598
14599 s32 wl_cfg80211_channel_to_freq(u32 channel)
14600 {
14601         int freq = 0;
14602
14603 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
14604         freq = ieee80211_channel_to_frequency(channel);
14605 #else
14606         {
14607                 u16 band = 0;
14608                 if (channel <= CH_MAX_2G_CHANNEL)
14609                         band = IEEE80211_BAND_2GHZ;
14610                 else
14611                         band = IEEE80211_BAND_5GHZ;
14612                 freq = ieee80211_channel_to_frequency(channel, band);
14613         }
14614 #endif
14615         return freq;
14616 }
14617
14618
14619 #ifdef WLTDLS
14620 static s32
14621 wl_tdls_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
14622         const wl_event_msg_t *e, void *data) {
14623
14624         struct net_device *ndev = NULL;
14625         u32 reason = ntoh32(e->reason);
14626         s8 *msg = NULL;
14627
14628         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
14629
14630         switch (reason) {
14631         case WLC_E_TDLS_PEER_DISCOVERED :
14632                 msg = " TDLS PEER DISCOVERD ";
14633                 break;
14634         case WLC_E_TDLS_PEER_CONNECTED :
14635 #ifdef PCIE_FULL_DONGLE
14636                 dhd_tdls_update_peer_info(ndev, TRUE, (uint8 *)&e->addr.octet[0]);
14637 #endif /* PCIE_FULL_DONGLE */
14638                 if (cfg->tdls_mgmt_frame) {
14639 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
14640                         cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
14641                                 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len, 0);
14642 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14643                         cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
14644                                 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
14645                                 0, GFP_ATOMIC);
14646 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
14647         defined(WL_COMPAT_WIRELESS)
14648                         cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
14649                                 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
14650                                 GFP_ATOMIC);
14651 #else
14652                         cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq,
14653                                 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
14654                                 GFP_ATOMIC);
14655 #endif /* LINUX_VERSION >= VERSION(3, 12, 0) */
14656                 }
14657                 msg = " TDLS PEER CONNECTED ";
14658                 break;
14659         case WLC_E_TDLS_PEER_DISCONNECTED :
14660 #ifdef PCIE_FULL_DONGLE
14661                 dhd_tdls_update_peer_info(ndev, FALSE, (uint8 *)&e->addr.octet[0]);
14662 #endif /* PCIE_FULL_DONGLE */
14663                 if (cfg->tdls_mgmt_frame) {
14664                         kfree(cfg->tdls_mgmt_frame);
14665                         cfg->tdls_mgmt_frame = NULL;
14666                         cfg->tdls_mgmt_freq = 0;
14667                 }
14668                 msg = "TDLS PEER DISCONNECTED ";
14669                 break;
14670         }
14671         if (msg) {
14672                 WL_ERR(("%s: " MACDBG " on %s ndev\n", msg, MAC2STRDBG((u8*)(&e->addr)),
14673                         (bcmcfg_to_prmry_ndev(cfg) == ndev) ? "primary" : "secondary"));
14674         }
14675         return 0;
14676
14677 }
14678 #endif  /* WLTDLS */
14679
14680 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
14681 static s32
14682 #if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \
14683         KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14684 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
14685         u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
14686         u32 peer_capability, const u8 *data, size_t len)
14687 #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) && \
14688                 (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
14689 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
14690         const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
14691         u32 peer_capability, const u8 *data, size_t len)
14692 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
14693 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
14694         const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
14695         u32 peer_capability, bool initiator, const u8 *data, size_t len)
14696 #else
14697 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
14698         u8 *peer, u8 action_code, u8 dialog_token, u16 status_code, const u8 *data,
14699         size_t len)
14700 #endif  /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
14701 {
14702         s32 ret = 0;
14703 #ifdef WLTDLS
14704         struct bcm_cfg80211 *cfg;
14705         tdls_wfd_ie_iovar_t info;
14706         memset(&info, 0, sizeof(tdls_wfd_ie_iovar_t));
14707         cfg = g_bcm_cfg;
14708
14709 #if defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)
14710         /* Some customer platform back ported this feature from kernel 3.15 to kernel 3.10
14711         * and that cuases build error
14712         */
14713         BCM_REFERENCE(peer_capability);
14714 #endif  /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
14715
14716         switch (action_code) {
14717         /* We need to set TDLS Wifi Display IE to firmware
14718          * using tdls_wfd_ie iovar
14719          */
14720         case WLAN_TDLS_SET_PROBE_WFD_IE:
14721                 WL_ERR(("%s WLAN_TDLS_SET_PROBE_WFD_IE\n", __FUNCTION__));
14722                 info.mode = TDLS_WFD_PROBE_IE_TX;
14723                 memcpy(&info.data, data, len);
14724                 info.length = len;
14725                 break;
14726         case WLAN_TDLS_SET_SETUP_WFD_IE:
14727                 WL_ERR(("%s WLAN_TDLS_SET_SETUP_WFD_IE\n", __FUNCTION__));
14728                 info.mode = TDLS_WFD_IE_TX;
14729                 memcpy(&info.data, data, len);
14730                 info.length = len;
14731                 break;
14732         case WLAN_TDLS_SET_WFD_ENABLED:
14733                 WL_ERR(("%s WLAN_TDLS_SET_MODE_WFD_ENABLED\n", __FUNCTION__));
14734                 dhd_tdls_set_mode((dhd_pub_t *)(cfg->pub), true);
14735                 goto out;
14736         case WLAN_TDLS_SET_WFD_DISABLED:
14737                 WL_ERR(("%s WLAN_TDLS_SET_MODE_WFD_DISABLED\n", __FUNCTION__));
14738                 dhd_tdls_set_mode((dhd_pub_t *)(cfg->pub), false);
14739                 goto out;
14740         default:
14741                 WL_ERR(("Unsupported action code : %d\n", action_code));
14742                 goto out;
14743         }
14744
14745         ret = wldev_iovar_setbuf(dev, "tdls_wfd_ie", &info, sizeof(info),
14746                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
14747
14748         if (ret) {
14749                 WL_ERR(("tdls_wfd_ie error %d\n", ret));
14750         }
14751 out:
14752 #endif /* WLTDLS */
14753         return ret;
14754 }
14755
14756 static s32
14757 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
14758 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
14759         const u8 *peer, enum nl80211_tdls_operation oper)
14760 #else
14761 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
14762         u8 *peer, enum nl80211_tdls_operation oper)
14763 #endif
14764 {
14765         s32 ret = 0;
14766 #ifdef WLTDLS
14767         struct bcm_cfg80211 *cfg;
14768         tdls_iovar_t info;
14769         dhd_pub_t *dhdp;
14770         bool tdls_auto_mode = false;
14771         cfg = g_bcm_cfg;
14772         dhdp = (dhd_pub_t *)(cfg->pub);
14773         memset(&info, 0, sizeof(tdls_iovar_t));
14774         if (peer) {
14775                 memcpy(&info.ea, peer, ETHER_ADDR_LEN);
14776         } else {
14777                 return -1;
14778         }
14779         switch (oper) {
14780         case NL80211_TDLS_DISCOVERY_REQ:
14781                 /* If the discovery request is broadcast then we need to set
14782                  * info.mode to Tunneled Probe Request
14783                  */
14784                 if (memcmp(peer, (const uint8 *)BSSID_BROADCAST, ETHER_ADDR_LEN) == 0) {
14785                         info.mode = TDLS_MANUAL_EP_WFD_TPQ;
14786                         WL_ERR(("%s TDLS TUNNELED PRBOBE REQUEST\n", __FUNCTION__));
14787                 } else {
14788                         info.mode = TDLS_MANUAL_EP_DISCOVERY;
14789                 }
14790                 break;
14791         case NL80211_TDLS_SETUP:
14792                 if (dhdp->tdls_mode == true) {
14793                         info.mode = TDLS_MANUAL_EP_CREATE;
14794                         tdls_auto_mode = false;
14795                         ret = dhd_tdls_enable(dev, false, tdls_auto_mode, NULL);
14796                         if (ret < 0) {
14797                                 return ret;
14798                         }
14799                 } else {
14800                         tdls_auto_mode = true;
14801                 }
14802                 break;
14803         case NL80211_TDLS_TEARDOWN:
14804                 info.mode = TDLS_MANUAL_EP_DELETE;
14805                 break;
14806         default:
14807                 WL_ERR(("Unsupported operation : %d\n", oper));
14808                 goto out;
14809         }
14810         /* turn on TDLS */
14811         ret = dhd_tdls_enable(dev, true, tdls_auto_mode, NULL);
14812         if (ret < 0) {
14813                 return ret;
14814         }
14815         if (info.mode) {
14816                 ret = wldev_iovar_setbuf(dev, "tdls_endpoint", &info, sizeof(info),
14817                         cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
14818                 if (ret) {
14819                         WL_ERR(("tdls_endpoint error %d\n", ret));
14820                 }
14821         }
14822 out:
14823 #endif /* WLTDLS */
14824         return ret;
14825 }
14826 #endif 
14827
14828 s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *ndev, char *buf, int len,
14829         enum wl_management_type type)
14830 {
14831         struct bcm_cfg80211 *cfg;
14832         s32 ret = 0;
14833         struct ether_addr primary_mac;
14834         s32 bssidx = 0;
14835         s32 pktflag = 0;
14836         cfg = g_bcm_cfg;
14837
14838         if (wl_get_drv_status(cfg, AP_CREATING, ndev)) {
14839                 /* Vendor IEs should be set to FW
14840                  * after SoftAP interface is brought up
14841                  */
14842                 WL_DBG(("Skipping set IE since AP is not up \n"));
14843                 goto exit;
14844         } else  if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
14845                 /* Either stand alone AP case or P2P discovery */
14846                 if (wl_get_drv_status(cfg, AP_CREATED, ndev)) {
14847                         /* Stand alone AP case on primary interface */
14848                         WL_DBG(("Apply IEs for Primary AP Interface \n"));
14849                         bssidx = 0;
14850                 } else {
14851                         /* P2P Discovery case (p2p listen) */
14852                         if (!cfg->p2p->on) {
14853                                 /* Turn on Discovery interface */
14854                                 get_primary_mac(cfg, &primary_mac);
14855                                 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
14856                                 p2p_on(cfg) = true;
14857                                 ret = wl_cfgp2p_enable_discovery(cfg, ndev, NULL, 0);
14858                                 if (unlikely(ret)) {
14859                                         WL_ERR(("Enable discovery failed \n"));
14860                                         goto exit;
14861                                 }
14862                         }
14863                         WL_DBG(("Apply IEs for P2P Discovery Iface \n"));
14864                         ndev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
14865                         bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
14866                 }
14867         } else {
14868                 /* Virtual AP/ P2P Group Interface */
14869                 WL_DBG(("Apply IEs for iface:%s\n", ndev->name));
14870                 bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
14871         }
14872
14873         if (ndev != NULL) {
14874                 switch (type) {
14875                         case WL_BEACON:
14876                                 pktflag = VNDR_IE_BEACON_FLAG;
14877                                 break;
14878                         case WL_PROBE_RESP:
14879                                 pktflag = VNDR_IE_PRBRSP_FLAG;
14880                                 break;
14881                         case WL_ASSOC_RESP:
14882                                 pktflag = VNDR_IE_ASSOCRSP_FLAG;
14883                                 break;
14884                 }
14885                 if (pktflag) {
14886                         ret = wl_cfg80211_set_mgmt_vndr_ies(cfg,
14887                                 ndev_to_cfgdev(ndev), bssidx, pktflag, buf, len);
14888                 }
14889         }
14890 exit:
14891         return ret;
14892 }
14893
14894 #ifdef WL_SUPPORT_AUTO_CHANNEL
14895 static s32
14896 wl_cfg80211_set_auto_channel_scan_state(struct net_device *ndev)
14897 {
14898         u32 val = 0;
14899         s32 ret = BCME_ERROR;
14900         struct bcm_cfg80211 *cfg = g_bcm_cfg;
14901         struct wiphy *wiphy;
14902         /* Disable mpc, to avoid automatic interface down. */
14903         val = 0;
14904
14905         wiphy = bcmcfg_to_wiphy(cfg);
14906         if (wl_check_dongle_idle(wiphy) != TRUE) {
14907                 WL_ERR(("FW is busy to add interface"));
14908                 return ret;
14909         }
14910         ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
14911                 sizeof(val), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
14912                 &cfg->ioctl_buf_sync);
14913         if (ret < 0) {
14914                 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
14915                 goto done;
14916         }
14917
14918         /* Set interface up, explicitly. */
14919         val = 1;
14920
14921         ret = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
14922         if (ret < 0) {
14923                 WL_ERR(("set interface up failed, error = %d\n", ret));
14924                 goto done;
14925         }
14926
14927         /* Stop all scan explicitly, till auto channel selection complete. */
14928         wl_set_drv_status(cfg, SCANNING, ndev);
14929         if (cfg->escan_info.ndev == NULL) {
14930                 ret = BCME_OK;
14931                 goto done;
14932         }
14933         ret = wl_notify_escan_complete(cfg, ndev, true, true);
14934         if (ret < 0) {
14935                 WL_ERR(("set scan abort failed, error = %d\n", ret));
14936                 goto done;
14937         }
14938
14939 done:
14940         return ret;
14941 }
14942
14943 static bool
14944 wl_cfg80211_valid_channel_p2p(int channel)
14945 {
14946         bool valid = false;
14947
14948         /* channel 1 to 14 */
14949         if ((channel >= 1) && (channel <= 14)) {
14950                 valid = true;
14951         }
14952         /* channel 36 to 48 */
14953         else if ((channel >= 36) && (channel <= 48)) {
14954                 valid = true;
14955         }
14956         /* channel 149 to 161 */
14957         else if ((channel >= 149) && (channel <= 161)) {
14958                 valid = true;
14959         }
14960         else {
14961                 valid = false;
14962                 WL_INFORM(("invalid P2P chanspec, channel = %d\n", channel));
14963         }
14964
14965         return valid;
14966 }
14967
14968 s32
14969 wl_cfg80211_get_chanspecs_2g(struct net_device *ndev, void *buf, s32 buflen)
14970 {
14971         s32 ret = BCME_ERROR;
14972         struct bcm_cfg80211 *cfg = NULL;
14973         wl_uint32_list_t *list = NULL;
14974         chanspec_t chanspec = 0;
14975
14976         memset(buf, 0, buflen);
14977
14978         cfg = g_bcm_cfg;
14979         list = (wl_uint32_list_t *)buf;
14980         list->count = htod32(WL_NUMCHANSPECS);
14981
14982         /* Restrict channels to 2.4GHz, 20MHz BW, no SB. */
14983         chanspec |= (WL_CHANSPEC_BAND_2G | WL_CHANSPEC_BW_20 |
14984                 WL_CHANSPEC_CTL_SB_NONE);
14985         chanspec = wl_chspec_host_to_driver(chanspec);
14986
14987         ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
14988                 sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
14989         if (ret < 0) {
14990                 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
14991         }
14992
14993         return ret;
14994 }
14995
14996 s32
14997 wl_cfg80211_get_chanspecs_5g(struct net_device *ndev, void *buf, s32 buflen)
14998 {
14999         u32 channel = 0;
15000         s32 ret = BCME_ERROR;
15001         s32 i = 0;
15002         s32 j = 0;
15003         struct bcm_cfg80211 *cfg = NULL;
15004         wl_uint32_list_t *list = NULL;
15005         chanspec_t chanspec = 0;
15006
15007         memset(buf, 0, buflen);
15008
15009         cfg = g_bcm_cfg;
15010         list = (wl_uint32_list_t *)buf;
15011         list->count = htod32(WL_NUMCHANSPECS);
15012
15013         /* Restrict channels to 5GHz, 20MHz BW, no SB. */
15014         chanspec |= (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_20 |
15015                 WL_CHANSPEC_CTL_SB_NONE);
15016         chanspec = wl_chspec_host_to_driver(chanspec);
15017
15018         ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
15019                 sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
15020         if (ret < 0) {
15021                 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
15022                 goto done;
15023         }
15024
15025         /* Skip DFS and inavlid P2P channel. */
15026         for (i = 0, j = 0; i < dtoh32(list->count); i++) {
15027                 chanspec = (chanspec_t) dtoh32(list->element[i]);
15028                 channel = CHSPEC_CHANNEL(chanspec);
15029
15030                 ret = wldev_iovar_getint(ndev, "per_chan_info", &channel);
15031                 if (ret < 0) {
15032                         WL_ERR(("get 'per_chan_info' failed, error = %d\n", ret));
15033                         goto done;
15034                 }
15035
15036                 if (CHANNEL_IS_RADAR(channel) ||
15037                         !(wl_cfg80211_valid_channel_p2p(CHSPEC_CHANNEL(chanspec)))) {
15038                         continue;
15039                 } else {
15040                         list->element[j] = list->element[i];
15041                 }
15042
15043                 j++;
15044         }
15045
15046         list->count = j;
15047
15048 done:
15049         return ret;
15050 }
15051
15052 static s32
15053 wl_cfg80211_get_best_channel(struct net_device *ndev, void *buf, int buflen,
15054         int *channel)
15055 {
15056         s32 ret = BCME_ERROR;
15057         int chosen = 0;
15058         int retry = 0;
15059         uint chip;
15060
15061         /* Start auto channel selection scan. */
15062         ret = wldev_ioctl(ndev, WLC_START_CHANNEL_SEL, buf, buflen, true);
15063         if (ret < 0) {
15064                 WL_ERR(("can't start auto channel scan, error = %d\n", ret));
15065                 *channel = 0;
15066                 goto done;
15067         }
15068
15069         /* Wait for auto channel selection, worst case possible delay is 5250ms. */
15070         retry = CHAN_SEL_RETRY_COUNT;
15071
15072         while (retry--) {
15073                 OSL_SLEEP(CHAN_SEL_IOCTL_DELAY);
15074
15075                 ret = wldev_ioctl(ndev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen),
15076                         false);
15077                 if ((ret == 0) && (dtoh32(chosen) != 0)) {
15078                         chip = dhd_conf_get_chip(dhd_get_pub(ndev));
15079                         if (chip != BCM43362_CHIP_ID && chip != BCM4330_CHIP_ID) {
15080                                 u32 chanspec = 0;
15081                                 int ctl_chan;
15082                                 chanspec = wl_chspec_driver_to_host(chosen);
15083                                 printf("selected chanspec = 0x%x\n", chanspec);
15084                                 ctl_chan = wf_chspec_ctlchan(chanspec);
15085                                 printf("selected ctl_chan = 0x%x\n", ctl_chan);
15086                                 *channel = (u16)(ctl_chan & 0x00FF);
15087                         } else
15088                                 *channel = (u16)(chosen & 0x00FF);
15089                         WL_INFORM(("selected channel = %d\n", *channel));
15090                         break;
15091                 }
15092                 WL_INFORM(("attempt = %d, ret = %d, chosen = %d\n",
15093                         (CHAN_SEL_RETRY_COUNT - retry), ret, dtoh32(chosen)));
15094         }
15095
15096         if (retry <= 0) {
15097                 WL_ERR(("failure, auto channel selection timed out\n"));
15098                 *channel = 0;
15099                 ret = BCME_ERROR;
15100         }
15101
15102 done:
15103         return ret;
15104 }
15105
15106 static s32
15107 wl_cfg80211_restore_auto_channel_scan_state(struct net_device *ndev)
15108 {
15109         u32 val = 0;
15110         s32 ret = BCME_ERROR;
15111         struct bcm_cfg80211 *cfg = g_bcm_cfg;
15112
15113         /* Clear scan stop driver status. */
15114         wl_clr_drv_status(cfg, SCANNING, ndev);
15115
15116         /* Enable mpc back to 1, irrespective of initial state. */
15117         val = 1;
15118
15119         ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
15120                 sizeof(val), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
15121                 &cfg->ioctl_buf_sync);
15122         if (ret < 0) {
15123                 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
15124         }
15125
15126         return ret;
15127 }
15128
15129 s32
15130 wl_cfg80211_get_best_channels(struct net_device *dev, char* cmd, int total_len)
15131 {
15132         int channel = 0, band, band_cur;
15133         s32 ret = BCME_ERROR;
15134         u8 *buf = NULL;
15135         char *pos = cmd;
15136         struct bcm_cfg80211 *cfg = NULL;
15137         struct net_device *ndev = NULL;
15138
15139         memset(cmd, 0, total_len);
15140
15141         buf = kmalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
15142         if (buf == NULL) {
15143                 WL_ERR(("failed to allocate chanspec buffer\n"));
15144                 return -ENOMEM;
15145         }
15146
15147         /*
15148          * Always use primary interface, irrespective of interface on which
15149          * command came.
15150          */
15151         cfg = g_bcm_cfg;
15152         ndev = bcmcfg_to_prmry_ndev(cfg);
15153
15154         /*
15155          * Make sure that FW and driver are in right state to do auto channel
15156          * selection scan.
15157          */
15158         ret = wl_cfg80211_set_auto_channel_scan_state(ndev);
15159         if (ret < 0) {
15160                 WL_ERR(("can't set auto channel scan state, error = %d\n", ret));
15161                 goto done;
15162         }
15163
15164         /* Best channel selection in 2.4GHz band. */
15165         ret = wl_cfg80211_get_chanspecs_2g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
15166         if (ret < 0) {
15167                 WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
15168                 goto done;
15169         }
15170
15171         ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
15172                 &channel);
15173         if (ret < 0) {
15174                 WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
15175                 goto done;
15176         }
15177
15178         if (CHANNEL_IS_2G(channel)) {
15179                 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
15180         } else {
15181                 WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel));
15182                 channel = 0;
15183         }
15184
15185         pos += snprintf(pos, total_len, "%04d ", channel);
15186
15187         // terence 20140120: fix for some chipsets only return 2.4GHz channel (4330b2/43341b0/4339a0)
15188         ret = wldev_ioctl(dev, WLC_GET_BAND, &band_cur, sizeof(band_cur), false);
15189         band = band_cur==WLC_BAND_2G ? band_cur : WLC_BAND_5G;
15190         ret = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), true);
15191         if (ret < 0)
15192                 WL_ERR(("WLC_SET_BAND error %d\n", ret));
15193
15194         /* Best channel selection in 5GHz band. */
15195         ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
15196         if (ret < 0) {
15197                 WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret));
15198                 goto done;
15199         }
15200
15201         ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
15202                 &channel);
15203         if (ret < 0) {
15204                 WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret));
15205                 goto done;
15206         }
15207
15208         if (CHANNEL_IS_5G(channel)) {
15209                 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
15210         } else {
15211                 WL_ERR(("invalid 5GHz channel, channel = %d\n", channel));
15212                 channel = 0;
15213         }
15214
15215         ret = wldev_ioctl(dev, WLC_SET_BAND, &band_cur, sizeof(band_cur), true);
15216         if (ret < 0)
15217                 WL_ERR(("WLC_SET_BAND error %d\n", ret));
15218
15219         pos += snprintf(pos, total_len, "%04d ", channel);
15220
15221         /* Set overall best channel same as 5GHz best channel. */
15222         pos += snprintf(pos, total_len, "%04d ", channel);
15223
15224 done:
15225         if (NULL != buf) {
15226                 kfree(buf);
15227         }
15228
15229         /* Restore FW and driver back to normal state. */
15230         ret = wl_cfg80211_restore_auto_channel_scan_state(ndev);
15231         if (ret < 0) {
15232                 WL_ERR(("can't restore auto channel scan state, error = %d\n", ret));
15233         }
15234
15235         printf("%s: channel %s\n", __FUNCTION__, cmd);
15236
15237         return (pos - cmd);
15238 }
15239 #endif /* WL_SUPPORT_AUTO_CHANNEL */
15240
15241 static const struct rfkill_ops wl_rfkill_ops = {
15242         .set_block = wl_rfkill_set
15243 };
15244
15245 static int wl_rfkill_set(void *data, bool blocked)
15246 {
15247         struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
15248
15249         WL_DBG(("Enter \n"));
15250         WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked"));
15251
15252         if (!cfg)
15253                 return -EINVAL;
15254
15255         cfg->rf_blocked = blocked;
15256
15257         return 0;
15258 }
15259
15260 static int wl_setup_rfkill(struct bcm_cfg80211 *cfg, bool setup)
15261 {
15262         s32 err = 0;
15263
15264         WL_DBG(("Enter \n"));
15265         if (!cfg)
15266                 return -EINVAL;
15267         if (setup) {
15268                 cfg->rfkill = rfkill_alloc("brcmfmac-wifi",
15269                         wl_cfg80211_get_parent_dev(),
15270                         RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)cfg);
15271
15272                 if (!cfg->rfkill) {
15273                         err = -ENOMEM;
15274                         goto err_out;
15275                 }
15276
15277                 err = rfkill_register(cfg->rfkill);
15278
15279                 if (err)
15280                         rfkill_destroy(cfg->rfkill);
15281         } else {
15282                 if (!cfg->rfkill) {
15283                         err = -ENOMEM;
15284                         goto err_out;
15285                 }
15286
15287                 rfkill_unregister(cfg->rfkill);
15288                 rfkill_destroy(cfg->rfkill);
15289         }
15290
15291 err_out:
15292         return err;
15293 }
15294
15295 #ifdef DEBUGFS_CFG80211
15296 /**
15297 * Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level
15298 * to turn on SCAN and DBG log.
15299 * To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level
15300 * To see current setting of debug level,
15301 * cat /sys/kernel/debug/dhd/debug_level
15302 */
15303 static ssize_t
15304 wl_debuglevel_write(struct file *file, const char __user *userbuf,
15305         size_t count, loff_t *ppos)
15306 {
15307         char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)], sublog[S_SUBLOGLEVEL];
15308         char *params, *token, *colon;
15309         uint i, tokens, log_on = 0;
15310         memset(tbuf, 0, sizeof(tbuf));
15311         memset(sublog, 0, sizeof(sublog));
15312         if (copy_from_user(&tbuf, userbuf, min_t(size_t, (sizeof(tbuf) - 1), count)))
15313                 return -EFAULT;
15314
15315         params = &tbuf[0];
15316         colon = strchr(params, '\n');
15317         if (colon != NULL)
15318                 *colon = '\0';
15319         while ((token = strsep(&params, " ")) != NULL) {
15320                 memset(sublog, 0, sizeof(sublog));
15321                 if (token == NULL || !*token)
15322                         break;
15323                 if (*token == '\0')
15324                         continue;
15325                 colon = strchr(token, ':');
15326                 if (colon != NULL) {
15327                         *colon = ' ';
15328                 }
15329                 tokens = sscanf(token, "%s %u", sublog, &log_on);
15330                 if (colon != NULL)
15331                         *colon = ':';
15332
15333                 if (tokens == 2) {
15334                                 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
15335                                         if (!strncmp(sublog, sublogname_map[i].sublogname,
15336                                                 strlen(sublogname_map[i].sublogname))) {
15337                                                 if (log_on)
15338                                                         wl_dbg_level |=
15339                                                         (sublogname_map[i].log_level);
15340                                                 else
15341                                                         wl_dbg_level &=
15342                                                         ~(sublogname_map[i].log_level);
15343                                         }
15344                                 }
15345                 } else
15346                         WL_ERR(("%s: can't parse '%s' as a "
15347                                "SUBMODULE:LEVEL (%d tokens)\n",
15348                                tbuf, token, tokens));
15349
15350
15351         }
15352         return count;
15353 }
15354
15355 static ssize_t
15356 wl_debuglevel_read(struct file *file, char __user *user_buf,
15357         size_t count, loff_t *ppos)
15358 {
15359         char *param;
15360         char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)];
15361         uint i;
15362         memset(tbuf, 0, sizeof(tbuf));
15363         param = &tbuf[0];
15364         for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
15365                 param += snprintf(param, sizeof(tbuf) - 1, "%s:%d ",
15366                         sublogname_map[i].sublogname,
15367                         (wl_dbg_level & sublogname_map[i].log_level) ? 1 : 0);
15368         }
15369         *param = '\n';
15370         return simple_read_from_buffer(user_buf, count, ppos, tbuf, strlen(&tbuf[0]));
15371
15372 }
15373 static const struct file_operations fops_debuglevel = {
15374         .open = NULL,
15375         .write = wl_debuglevel_write,
15376         .read = wl_debuglevel_read,
15377         .owner = THIS_MODULE,
15378         .llseek = NULL,
15379 };
15380
15381 static s32 wl_setup_debugfs(struct bcm_cfg80211 *cfg)
15382 {
15383         s32 err = 0;
15384         struct dentry *_dentry;
15385         if (!cfg)
15386                 return -EINVAL;
15387         cfg->debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
15388         if (!cfg->debugfs || IS_ERR(cfg->debugfs)) {
15389                 if (cfg->debugfs == ERR_PTR(-ENODEV))
15390                         WL_ERR(("Debugfs is not enabled on this kernel\n"));
15391                 else
15392                         WL_ERR(("Can not create debugfs directory\n"));
15393                 cfg->debugfs = NULL;
15394                 goto exit;
15395
15396         }
15397         _dentry = debugfs_create_file("debug_level", S_IRUSR | S_IWUSR,
15398                 cfg->debugfs, cfg, &fops_debuglevel);
15399         if (!_dentry || IS_ERR(_dentry)) {
15400                 WL_ERR(("failed to create debug_level debug file\n"));
15401                 wl_free_debugfs(cfg);
15402         }
15403 exit:
15404         return err;
15405 }
15406 static s32 wl_free_debugfs(struct bcm_cfg80211 *cfg)
15407 {
15408         if (!cfg)
15409                 return -EINVAL;
15410         if (cfg->debugfs)
15411                 debugfs_remove_recursive(cfg->debugfs);
15412         cfg->debugfs = NULL;
15413         return 0;
15414 }
15415 #endif /* DEBUGFS_CFG80211 */
15416
15417 struct device *wl_cfg80211_get_parent_dev(void)
15418 {
15419         return cfg80211_parent_dev;
15420 }
15421
15422 void wl_cfg80211_set_parent_dev(void *dev)
15423 {
15424         cfg80211_parent_dev = dev;
15425 }
15426
15427 static void wl_cfg80211_clear_parent_dev(void)
15428 {
15429         cfg80211_parent_dev = NULL;
15430 }
15431
15432 void get_primary_mac(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
15433 {
15434         wldev_iovar_getbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg), "cur_etheraddr", NULL,
15435                 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
15436         memcpy(mac->octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
15437 }
15438 static bool check_dev_role_integrity(struct bcm_cfg80211 *cfg, u32 dev_role)
15439 {
15440         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
15441         if (((dev_role == NL80211_IFTYPE_AP) &&
15442                 !(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) ||
15443                 ((dev_role == NL80211_IFTYPE_P2P_GO) &&
15444                 !(dhd->op_mode & DHD_FLAG_P2P_GO_MODE)))
15445         {
15446                 WL_ERR(("device role select failed role:%d op_mode:%d \n", dev_role, dhd->op_mode));
15447                 return false;
15448         }
15449         return true;
15450 }
15451
15452 int wl_cfg80211_do_driver_init(struct net_device *net)
15453 {
15454         struct bcm_cfg80211 *cfg = *(struct bcm_cfg80211 **)netdev_priv(net);
15455
15456         if (!cfg || !cfg->wdev)
15457                 return -EINVAL;
15458
15459         if (dhd_do_driver_init(cfg->wdev->netdev) < 0)
15460                 return -1;
15461
15462         return 0;
15463 }
15464
15465 void wl_cfg80211_enable_trace(u32 level)
15466 {
15467         wl_dbg_level = level;
15468         printf("%s: wl_dbg_level = 0x%x\n", __FUNCTION__, wl_dbg_level);
15469 }
15470
15471 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
15472         2, 0))
15473 static s32
15474 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
15475         bcm_struct_cfgdev *cfgdev, u64 cookie)
15476 {
15477         /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION
15478          * is passed with CMD_FRAME. This callback is supposed to cancel
15479          * the OFFCHANNEL Wait. Since we are already taking care of that
15480          *  with the tx_mgmt logic, do nothing here.
15481          */
15482
15483         return 0;
15484 }
15485 #endif /* WL_SUPPORT_BACKPORTED_PATCHES || KERNEL >= 3.2.0 */
15486
15487 #ifdef WL11U
15488 bcm_tlv_t *
15489 wl_cfg80211_find_interworking_ie(u8 *parse, u32 len)
15490 {
15491         bcm_tlv_t *ie;
15492
15493         while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_INTERWORKING_ID))) {
15494                         return (bcm_tlv_t *)ie;
15495         }
15496         return NULL;
15497 }
15498
15499
15500 static s32
15501 wl_cfg80211_add_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx, s32 pktflag,
15502             uint8 ie_id, uint8 *data, uint8 data_len)
15503 {
15504         s32 err = BCME_OK;
15505         s32 buf_len;
15506         s32 iecount;
15507         ie_setbuf_t *ie_setbuf;
15508
15509         if (ie_id != DOT11_MNG_INTERWORKING_ID)
15510                 return BCME_UNSUPPORTED;
15511
15512         /* Validate the pktflag parameter */
15513         if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
15514                     VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
15515                     VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG|
15516                     VNDR_IE_CUSTOM_FLAG))) {
15517                 WL_ERR(("cfg80211 Add IE: Invalid packet flag 0x%x\n", pktflag));
15518                 return -1;
15519         }
15520
15521         /* use VNDR_IE_CUSTOM_FLAG flags for none vendor IE . currently fixed value */
15522         pktflag = htod32(pktflag);
15523
15524         buf_len = sizeof(ie_setbuf_t) + data_len - 1;
15525         ie_setbuf = (ie_setbuf_t *) kzalloc(buf_len, GFP_KERNEL);
15526
15527         if (!ie_setbuf) {
15528                 WL_ERR(("Error allocating buffer for IE\n"));
15529                 return -ENOMEM;
15530         }
15531
15532         if (cfg->iw_ie_len == data_len && !memcmp(cfg->iw_ie, data, data_len)) {
15533                 WL_ERR(("Previous IW IE is equals to current IE\n"));
15534                 err = BCME_OK;
15535                 goto exit;
15536         }
15537
15538         strncpy(ie_setbuf->cmd, "add", VNDR_IE_CMD_LEN - 1);
15539         ie_setbuf->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
15540
15541         /* Buffer contains only 1 IE */
15542         iecount = htod32(1);
15543         memcpy((void *)&ie_setbuf->ie_buffer.iecount, &iecount, sizeof(int));
15544         memcpy((void *)&ie_setbuf->ie_buffer.ie_list[0].pktflag, &pktflag, sizeof(uint32));
15545
15546         /* Now, add the IE to the buffer */
15547         ie_setbuf->ie_buffer.ie_list[0].ie_data.id = ie_id;
15548
15549         /* if already set with previous values, delete it first */
15550         if (cfg->iw_ie_len != 0) {
15551                 WL_DBG(("Different IW_IE was already set. clear first\n"));
15552
15553                 ie_setbuf->ie_buffer.ie_list[0].ie_data.len = 0;
15554
15555                 err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
15556                         cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
15557
15558                 if (err != BCME_OK)
15559                         goto exit;
15560         }
15561
15562         ie_setbuf->ie_buffer.ie_list[0].ie_data.len = data_len;
15563         memcpy((uchar *)&ie_setbuf->ie_buffer.ie_list[0].ie_data.data[0], data, data_len);
15564
15565         err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
15566                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
15567
15568         if (err == BCME_OK) {
15569                 memcpy(cfg->iw_ie, data, data_len);
15570                 cfg->iw_ie_len = data_len;
15571                 cfg->wl11u = TRUE;
15572
15573                 err = wldev_iovar_setint_bsscfg(ndev, "grat_arp", 1, bssidx);
15574         }
15575
15576 exit:
15577         if (ie_setbuf)
15578                 kfree(ie_setbuf);
15579         return err;
15580 }
15581 #endif /* WL11U */
15582
15583 s32
15584 wl_cfg80211_dfs_ap_move(struct net_device *ndev, char *data, char *command, int total_len)
15585 {
15586         struct bcm_cfg80211 *cfg = g_bcm_cfg;
15587         char ioctl_buf[50];
15588         int err = 0;
15589         uint32 val = 0;
15590         chanspec_t chanspec = 0;
15591         int abort;
15592         int bytes_written = 0;
15593         wl_dfs_ap_move_status_t *status;
15594         char chanbuf[CHANSPEC_STR_LEN];
15595         const char *dfs_state_str[DFS_SCAN_S_MAX] = {
15596                 "Radar Free On Channel",
15597                 "Radar Found On Channel",
15598                 "Radar Scan In Progress",
15599                 "Radar Scan Aborted",
15600                 "RSDB Mode switch in Progress For Scan"
15601         };
15602         if (ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
15603                 bytes_written = snprintf(command, total_len, "AP is not UP\n");
15604                 return bytes_written;
15605         }
15606         if (!*data) {
15607                 if ((err = wldev_iovar_getbuf(ndev, "dfs_ap_move", NULL, 0,
15608                                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN,  &cfg->ioctl_buf_sync))) {
15609                         WL_ERR(("setting dfs_ap_move failed with err=%d \n", err));
15610                         return err;
15611                 }
15612                 status = (wl_dfs_ap_move_status_t *)cfg->ioctl_buf;
15613
15614                 if (status->version != WL_DFS_AP_MOVE_VERSION) {
15615                         err = BCME_UNSUPPORTED;
15616                         WL_ERR(("err=%d version=%d\n", err, status->version));
15617                         return err;
15618                 }
15619
15620                 if (status->move_status != (int8) DFS_SCAN_S_IDLE) {
15621                         chanspec = wl_chspec_driver_to_host(status->chanspec);
15622                         if (chanspec != 0 && chanspec != INVCHANSPEC) {
15623                                 wf_chspec_ntoa(chanspec, chanbuf);
15624                                 bytes_written = snprintf(command, total_len,
15625                                         "AP Target Chanspec %s (0x%x)\n", chanbuf, chanspec);
15626                         }
15627                         bytes_written += snprintf(command + bytes_written, total_len,
15628                                          "%s\n", dfs_state_str[status->move_status]);
15629                         return bytes_written;
15630                 } else {
15631                         bytes_written = snprintf(command, total_len, "dfs AP move in IDLE state\n");
15632                         return bytes_written;
15633                 }
15634
15635         }
15636
15637         abort = bcm_atoi(data);
15638         if (abort == -1) {
15639                 if ((err = wldev_iovar_setbuf(ndev, "dfs_ap_move", &abort,
15640                                 sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
15641                         WL_ERR(("seting dfs_ap_move failed with err %d\n", err));
15642                         return err;
15643                 }
15644         } else {
15645                 chanspec = wf_chspec_aton(data);
15646                 if (chanspec != 0) {
15647                         val = wl_chspec_host_to_driver(chanspec);
15648                         if (val != INVCHANSPEC) {
15649                                 if ((err = wldev_iovar_setbuf(ndev, "dfs_ap_move", &val,
15650                                         sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
15651                                         WL_ERR(("seting dfs_ap_move failed with err %d\n", err));
15652                                         return err;
15653                                 }
15654                                 WL_DBG((" set dfs_ap_move successfull"));
15655                         } else {
15656                                 err = BCME_USAGE_ERROR;
15657                         }
15658                 }
15659         }
15660         return err;
15661 }
15662
15663 s32
15664 wl_cfg80211_wbtext_config(struct net_device *ndev, char *data, char *command, int total_len)
15665 {
15666         uint i = 0;
15667         struct bcm_cfg80211 *cfg = g_bcm_cfg;
15668         wl_roam_prof_band_t *rp;
15669         int err = -EINVAL, bytes_written = 0;
15670         size_t len = strlen(data);
15671         int rp_len = 0;
15672         data[len] = '\0';
15673         rp = (wl_roam_prof_band_t *) kzalloc(sizeof(*rp)
15674                         * WL_MAX_ROAM_PROF_BRACKETS, GFP_KERNEL);
15675         if (unlikely(!rp)) {
15676                 WL_ERR(("%s: failed to allocate memory\n", __func__));
15677                 err =  -ENOMEM;
15678                 goto exit;
15679         }
15680
15681         rp->ver = WL_MAX_ROAM_PROF_VER;
15682         if (*data && (!strncmp(data, "b", 1))) {
15683                 rp->band = WLC_BAND_2G;
15684         } else if (*data && (!strncmp(data, "a", 1))) {
15685                 rp->band = WLC_BAND_5G;
15686         } else {
15687                 err = snprintf(command, total_len, "Missing band\n");
15688                 goto exit;
15689         }
15690         data++;
15691         rp->len = 0;
15692         /* Getting roam profile  from fw */
15693         if ((err = wldev_iovar_getbuf(ndev, "roam_prof", rp, sizeof(*rp),
15694                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN,  &cfg->ioctl_buf_sync))) {
15695                 WL_ERR(("Getting roam_profile failed with err=%d \n", err));
15696                 goto exit;
15697         }
15698         memcpy(rp, cfg->ioctl_buf, sizeof(*rp) * WL_MAX_ROAM_PROF_BRACKETS);
15699         /* roam_prof version get */
15700         if (rp->ver != WL_MAX_ROAM_PROF_VER) {
15701                 WL_ERR(("bad version (=%d) in return data\n", rp->ver));
15702                 err = -EINVAL;
15703                 goto exit;
15704         }
15705         if ((rp->len % sizeof(wl_roam_prof_t)) != 0) {
15706                 WL_ERR(("bad length (=%d) in return data\n", rp->len));
15707                 err = -EINVAL;
15708                 goto exit;
15709         }
15710
15711         if (!*data) {
15712                 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
15713                         /* printing contents of roam profile data from fw and exits
15714                          * if code hits any of one of the below condtion. If remaining
15715                          * length of buffer is less than roam profile size or
15716                          * if there is no valid entry.
15717                          */
15718                         if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
15719                                 (rp->roam_prof[i].fullscan_period == 0)) {
15720                                 break;
15721                         }
15722                         bytes_written += snprintf(command+bytes_written,
15723                                         total_len, "RSSI[%d,%d] CU(trigger:%d%%: duration:%ds)\n",
15724                                         rp->roam_prof[i].roam_trigger, rp->roam_prof[i].rssi_lower,
15725                                         rp->roam_prof[i].channel_usage,
15726                                         rp->roam_prof[i].cu_avg_calc_dur);
15727                 }
15728                 err = bytes_written;
15729                 goto exit;
15730         } else {
15731                 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
15732                         /* reading contents of roam profile data from fw and exits
15733                          * if code hits any of one of the below condtion, If remaining
15734                          * length of buffer is less than roam profile size or if there
15735                          * is no valid entry.
15736                          */
15737                         if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
15738                                 (rp->roam_prof[i].fullscan_period == 0)) {
15739                                 break;
15740                         }
15741                 }
15742                 /* Do not set roam_prof from upper layer if fw doesn't have 2 rows */
15743                 if (i != 2) {
15744                         WL_ERR(("FW must have 2 rows to fill roam_prof\n"));
15745                         err = -EINVAL;
15746                         goto exit;
15747                 }
15748                 /* setting roam profile to fw */
15749                 data++;
15750                 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
15751                         rp->roam_prof[i].roam_trigger = simple_strtol(data, &data, 10);
15752                         data++;
15753                         rp->roam_prof[i].rssi_lower = simple_strtol(data, &data, 10);
15754                         data++;
15755                         rp->roam_prof[i].channel_usage = simple_strtol(data, &data, 10);
15756                         data++;
15757                         rp->roam_prof[i].cu_avg_calc_dur = simple_strtol(data, &data, 10);
15758
15759                         rp_len += sizeof(wl_roam_prof_t);
15760                         if (*data == '\0') {
15761                                 break;
15762                         }
15763                         data++;
15764                 }
15765                 if (i != 1) {
15766                         WL_ERR(("Only two roam_prof rows supported.\n"));
15767                         err = -EINVAL;
15768                         goto exit;
15769                 }
15770                 rp->len = rp_len;
15771                 if ((err = wldev_iovar_setbuf(ndev, "roam_prof", rp,
15772                                 sizeof(*rp), cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL)) < 0) {
15773                         WL_ERR(("seting roam_profile failed with err %d\n", err));
15774                 }
15775         }
15776 exit:
15777         if (rp) {
15778                 kfree(rp);
15779         }
15780         return err;
15781 }
15782
15783 int wl_cfg80211_wbtext_weight_config(struct net_device *ndev, char *data,
15784                 char *command, int total_len)
15785 {
15786         struct bcm_cfg80211 *cfg = g_bcm_cfg;
15787         int bytes_written = 0, err = -EINVAL, argc = 0;
15788         char rssi[5], band[5], weight[5];
15789         char *endptr = NULL;
15790         wnm_bss_select_weight_cfg_t *bwcfg;
15791
15792         bwcfg = kzalloc(sizeof(*bwcfg), GFP_KERNEL);
15793         if (unlikely(!bwcfg)) {
15794                 WL_ERR(("%s: failed to allocate memory\n", __func__));
15795                 err = -ENOMEM;
15796                 goto exit;
15797         }
15798         bwcfg->version =  WNM_BSSLOAD_MONITOR_VERSION;
15799         bwcfg->type = 0;
15800         bwcfg->weight = 0;
15801
15802         argc = sscanf(data, "%s %s %s", rssi, band, weight);
15803
15804         if (!strcasecmp(rssi, "rssi"))
15805                 bwcfg->type = WNM_BSS_SELECT_TYPE_RSSI;
15806         else if (!strcasecmp(rssi, "cu"))
15807                 bwcfg->type = WNM_BSS_SELECT_TYPE_CU;
15808         else {
15809                 /* Usage DRIVER WBTEXT_WEIGHT_CONFIG <rssi/cu> <band> <weight> */
15810                 WL_ERR(("%s: Command usage error\n", __func__));
15811                 goto exit;
15812         }
15813
15814         if (!strcasecmp(band, "a"))
15815                 bwcfg->band = WLC_BAND_5G;
15816         else if (!strcasecmp(band, "b"))
15817                 bwcfg->band = WLC_BAND_2G;
15818         else if (!strcasecmp(band, "all"))
15819                 bwcfg->band = WLC_BAND_ALL;
15820         else {
15821                 WL_ERR(("%s: Command usage error\n", __func__));
15822                 goto exit;
15823         }
15824
15825         if (argc == 2) {
15826                 /* If there is no data after band, getting wnm_bss_select_weight from fw */
15827                 if (bwcfg->band == WLC_BAND_ALL) {
15828                         WL_ERR(("band option \"all\" is for set only, not get\n"));
15829                         goto exit;
15830                 }
15831                 if ((err = wldev_iovar_getbuf(ndev, "wnm_bss_select_weight", bwcfg,
15832                                 sizeof(*bwcfg),
15833                                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN,  &cfg->ioctl_buf_sync))) {
15834                         WL_ERR(("Getting wnm_bss_select_weight failed with err=%d \n", err));
15835                         goto exit;
15836                 }
15837                 memcpy(bwcfg, cfg->ioctl_buf, sizeof(*bwcfg));
15838                 bytes_written = snprintf(command, total_len, "%s %s weight = %d\n",
15839                         (bwcfg->type == WNM_BSS_SELECT_TYPE_RSSI) ? "RSSI" : "CU",
15840                         (bwcfg->band == WLC_BAND_2G) ? "2G" : "5G", bwcfg->weight);
15841                 err = bytes_written;
15842                 goto exit;
15843         } else {
15844                 /* if weight is non integer returns command usage error */
15845                 bwcfg->weight = simple_strtol(weight, &endptr, 0);
15846                 if (*endptr != '\0') {
15847                         WL_ERR(("%s: Command usage error", __func__));
15848                         goto exit;
15849                 }
15850                 /* setting weight for iovar wnm_bss_select_weight to fw */
15851                 if ((err = wldev_iovar_setbuf(ndev, "wnm_bss_select_weight", bwcfg,
15852                                 sizeof(*bwcfg),
15853                                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN,  &cfg->ioctl_buf_sync))) {
15854                         WL_ERR(("Getting wnm_bss_select_weight failed with err=%d\n", err));
15855                 }
15856         }
15857 exit:
15858         if (bwcfg) {
15859                 kfree(bwcfg);
15860         }
15861         return err;
15862 }
15863
15864 /* WBTEXT_TUPLE_MIN_LEN_CHECK :strlen(low)+" "+strlen(high)+" "+strlen(factor) */
15865 #define WBTEXT_TUPLE_MIN_LEN_CHECK 5
15866
15867 int wl_cfg80211_wbtext_table_config(struct net_device *ndev, char *data,
15868         char *command, int total_len)
15869 {
15870         struct bcm_cfg80211 *cfg = g_bcm_cfg;
15871         int bytes_written = 0, err = -EINVAL;
15872         char rssi[5], band[5];
15873         int btcfg_len = 0, i = 0, parsed_len = 0;
15874         wnm_bss_select_factor_cfg_t *btcfg;
15875         size_t slen = strlen(data);
15876         char *start_addr = NULL;
15877         data[slen] = '\0';
15878
15879         btcfg = kzalloc((sizeof(*btcfg) + sizeof(*btcfg) *
15880                         WL_FACTOR_TABLE_MAX_LIMIT), GFP_KERNEL);
15881         if (unlikely(!btcfg)) {
15882                 WL_ERR(("%s: failed to allocate memory\n", __func__));
15883                 err = -ENOMEM;
15884                 goto exit;
15885         }
15886
15887         btcfg->version = WNM_BSS_SELECT_FACTOR_VERSION;
15888         btcfg->band = WLC_BAND_AUTO;
15889         btcfg->type = 0;
15890         btcfg->count = 0;
15891
15892         sscanf(data, "%s %s", rssi, band);
15893
15894         if (!strcasecmp(rssi, "rssi")) {
15895                 btcfg->type = WNM_BSS_SELECT_TYPE_RSSI;
15896         }
15897         else if (!strcasecmp(rssi, "cu")) {
15898                 btcfg->type = WNM_BSS_SELECT_TYPE_CU;
15899         }
15900         else {
15901                 WL_ERR(("%s: Command usage error\n", __func__));
15902                 goto exit;
15903         }
15904
15905         if (!strcasecmp(band, "a")) {
15906                 btcfg->band = WLC_BAND_5G;
15907         }
15908         else if (!strcasecmp(band, "b")) {
15909                 btcfg->band = WLC_BAND_2G;
15910         }
15911         else if (!strcasecmp(band, "all")) {
15912                 btcfg->band = WLC_BAND_ALL;
15913         }
15914         else {
15915                 WL_ERR(("%s: Command usage, Wrong band\n", __func__));
15916                 goto exit;
15917         }
15918
15919         if ((slen - 1) == (strlen(rssi) + strlen(band))) {
15920                 /* Getting factor table using iovar 'wnm_bss_select_table' from fw */
15921                 if ((err = wldev_iovar_getbuf(ndev, "wnm_bss_select_table", btcfg,
15922                                 sizeof(*btcfg),
15923                                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN,  &cfg->ioctl_buf_sync))) {
15924                         WL_ERR(("Getting wnm_bss_select_table failed with err=%d \n", err));
15925                         goto exit;
15926                 }
15927                 memcpy(btcfg, cfg->ioctl_buf, sizeof(*btcfg));
15928                 memcpy(btcfg, cfg->ioctl_buf, (btcfg->count+1) * sizeof(*btcfg));
15929
15930                 bytes_written += snprintf(command + bytes_written, total_len,
15931                                         "No of entries in table: %d\n", btcfg->count);
15932                 bytes_written += snprintf(command + bytes_written, total_len, "%s factor table\n",
15933                                 (btcfg->type == WNM_BSS_SELECT_TYPE_RSSI) ? "RSSI" : "CU");
15934                 bytes_written += snprintf(command + bytes_written, total_len,
15935                                         "low\thigh\tfactor\n");
15936                 for (i = 0; i <= btcfg->count-1; i++) {
15937                         bytes_written += snprintf(command + bytes_written, total_len,
15938                                 "%d\t%d\t%d\n", btcfg->params[i].low, btcfg->params[i].high,
15939                                 btcfg->params[i].factor);
15940                 }
15941                 err = bytes_written;
15942                 goto exit;
15943         } else {
15944                 memset(btcfg->params, 0, sizeof(*btcfg) * WL_FACTOR_TABLE_MAX_LIMIT);
15945                 data += (strlen(rssi) + strlen(band) + 2);
15946                 start_addr = data;
15947                 slen = slen - (strlen(rssi) + strlen(band) + 2);
15948                 for (i = 0; i < WL_FACTOR_TABLE_MAX_LIMIT; i++) {
15949                         if (parsed_len + WBTEXT_TUPLE_MIN_LEN_CHECK <= slen) {
15950                                 btcfg->params[i].low = simple_strtol(data, &data, 10);
15951                                 data++;
15952                                 btcfg->params[i].high = simple_strtol(data, &data, 10);
15953                                 data++;
15954                                 btcfg->params[i].factor = simple_strtol(data, &data, 10);
15955                                 btcfg->count++;
15956                                 if (*data == '\0') {
15957                                         break;
15958                                 }
15959                                 data++;
15960                                 parsed_len = data - start_addr;
15961                         } else {
15962                                 WL_ERR(("%s:Command usage:less no of args\n", __func__));
15963                                 goto exit;
15964                         }
15965                 }
15966                 btcfg_len = sizeof(*btcfg) + ((btcfg->count) * sizeof(*btcfg));
15967                 if ((err = wldev_iovar_setbuf(ndev, "wnm_bss_select_table", btcfg, btcfg_len,
15968                                 cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL)) < 0) {
15969                         WL_ERR(("seting wnm_bss_select_table failed with err %d\n", err));
15970                         goto exit;
15971                 }
15972         }
15973 exit:
15974         if (btcfg) {
15975                 kfree(btcfg);
15976         }
15977         return err;
15978 }
15979
15980 s32
15981 wl_cfg80211_wbtext_delta_config(struct net_device *ndev, char *data, char *command, int total_len)
15982 {
15983         uint i = 0;
15984         struct bcm_cfg80211 *cfg = g_bcm_cfg;
15985         int err = -EINVAL, bytes_written = 0, argc = 0, val, len = 0;
15986         char delta[5], band[5], *endptr = NULL;
15987         wl_roam_prof_band_t *rp;
15988
15989         rp = (wl_roam_prof_band_t *) kzalloc(sizeof(*rp)
15990                         * WL_MAX_ROAM_PROF_BRACKETS, GFP_KERNEL);
15991         if (unlikely(!rp)) {
15992                 WL_ERR(("%s: failed to allocate memory\n", __func__));
15993                 err = -ENOMEM;
15994                 goto exit;
15995         }
15996
15997         argc = sscanf(data, "%s %s", band, delta);
15998         if (!strcasecmp(band, "a"))
15999                 rp->band = WLC_BAND_5G;
16000         else if (!strcasecmp(band, "b"))
16001                 rp->band = WLC_BAND_2G;
16002         else {
16003                 WL_ERR(("%s: Missing band\n", __func__));
16004                 goto exit;
16005         }
16006         /* Getting roam profile  from fw */
16007         if ((err = wldev_iovar_getbuf(ndev, "roam_prof", rp, sizeof(*rp),
16008                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN,  &cfg->ioctl_buf_sync))) {
16009                 WL_ERR(("Getting roam_profile failed with err=%d \n", err));
16010                 goto exit;
16011         }
16012         memcpy(rp, cfg->ioctl_buf, sizeof(wl_roam_prof_band_t));
16013         if (rp->ver != WL_MAX_ROAM_PROF_VER) {
16014                 WL_ERR(("bad version (=%d) in return data\n", rp->ver));
16015                 err = -EINVAL;
16016                 goto exit;
16017         }
16018         if ((rp->len % sizeof(wl_roam_prof_t)) != 0) {
16019                 WL_ERR(("bad length (=%d) in return data\n", rp->len));
16020                 err = -EINVAL;
16021                 goto exit;
16022         }
16023
16024         if (argc == 2) {
16025                 /* if delta is non integer returns command usage error */
16026                 val = simple_strtol(delta, &endptr, 0);
16027                 if (*endptr != '\0') {
16028                         WL_ERR(("%s: Command usage error", __func__));
16029                         goto exit;
16030                 }
16031                 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
16032                 /*
16033                  * Checking contents of roam profile data from fw and exits
16034                  * if code hits below condtion. If remaining length of buffer is
16035                  * less than roam profile size or if there is no valid entry.
16036                  */
16037                         if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
16038                                 (rp->roam_prof[i].fullscan_period == 0)) {
16039                                 break;
16040                         }
16041                         if (rp->roam_prof[i].channel_usage != 0) {
16042                                 rp->roam_prof[i].roam_delta = val;
16043                         }
16044                         len += sizeof(wl_roam_prof_t);
16045                 }
16046         }
16047         else {
16048                 if (rp->roam_prof[i].channel_usage != 0) {
16049                         bytes_written = snprintf(command, total_len,
16050                                 "%s Delta %d\n", (rp->band == WLC_BAND_2G) ? "2G" : "5G",
16051                                 rp->roam_prof[0].roam_delta);
16052                 }
16053                 err = bytes_written;
16054                 goto exit;
16055         }
16056         rp->len = len;
16057         if ((err = wldev_iovar_setbuf(ndev, "roam_prof", rp,
16058                         sizeof(*rp), cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL)) < 0) {
16059                 WL_ERR(("seting roam_profile failed with err %d\n", err));
16060         }
16061 exit :
16062         if (rp) {
16063                 kfree(rp);
16064         }
16065         return err;
16066 }
16067
16068
16069 int wl_cfg80211_scan_stop(bcm_struct_cfgdev *cfgdev)
16070 {
16071         struct bcm_cfg80211 *cfg = NULL;
16072         struct net_device *ndev = NULL;
16073         unsigned long flags;
16074         int clear_flag = 0;
16075         int ret = 0;
16076
16077         WL_TRACE(("Enter\n"));
16078
16079         cfg = g_bcm_cfg;
16080         if (!cfg)
16081                 return -EINVAL;
16082
16083         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
16084
16085         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
16086 #ifdef WL_CFG80211_P2P_DEV_IF
16087         if (cfg->scan_request && cfg->scan_request->wdev == cfgdev)
16088 #else
16089         if (cfg->scan_request && cfg->scan_request->dev == cfgdev)
16090 #endif
16091         {
16092                 cfg80211_scan_done(cfg->scan_request, true);
16093                 cfg->scan_request = NULL;
16094                 clear_flag = 1;
16095         }
16096         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
16097
16098         if (clear_flag)
16099                 wl_clr_drv_status(cfg, SCANNING, ndev);
16100
16101         return ret;
16102 }
16103
16104 bool wl_cfg80211_is_concurrent_mode(void)
16105 {
16106         if ((g_bcm_cfg) && (wl_get_drv_status_all(g_bcm_cfg, CONNECTED) > 1)) {
16107                 return true;
16108         } else {
16109                 return false;
16110         }
16111 }
16112
16113 void* wl_cfg80211_get_dhdp()
16114 {
16115         struct bcm_cfg80211 *cfg = g_bcm_cfg;
16116
16117         return cfg->pub;
16118 }
16119
16120 bool wl_cfg80211_is_p2p_active(void)
16121 {
16122         return (g_bcm_cfg && g_bcm_cfg->p2p);
16123 }
16124
16125 bool wl_cfg80211_is_roam_offload(void)
16126 {
16127         return (g_bcm_cfg && g_bcm_cfg->roam_offload);
16128 }
16129
16130 bool wl_cfg80211_is_event_from_connected_bssid(const wl_event_msg_t *e, int ifidx)
16131 {
16132         dhd_pub_t *dhd = NULL;
16133         struct net_device *ndev = NULL;
16134         u8 *curbssid = NULL;
16135
16136         dhd = (dhd_pub_t *)(g_bcm_cfg->pub);
16137
16138         if (dhd) {
16139                 ndev = dhd_idx2net(dhd, ifidx);
16140         }
16141
16142         if (!dhd || !ndev) {
16143                 return false;
16144         }
16145
16146         curbssid = wl_read_prof(g_bcm_cfg, ndev, WL_PROF_BSSID);
16147
16148         return memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) == 0;
16149 }
16150
16151 static void wl_cfg80211_work_handler(struct work_struct * work)
16152 {
16153         struct bcm_cfg80211 *cfg = NULL;
16154         struct net_info *iter, *next;
16155         s32 err = BCME_OK;
16156         s32 pm = PM_FAST;
16157         BCM_SET_CONTAINER_OF(cfg, work, struct bcm_cfg80211, pm_enable_work.work);
16158         WL_DBG(("Enter \n"));
16159 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16160         4 && __GNUC_MINOR__ >= 6))
16161 _Pragma("GCC diagnostic push")
16162 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16163 #endif
16164         for_each_ndev(cfg, iter, next) {
16165                 /* p2p discovery iface ndev could be null */
16166                 if (iter->ndev) {
16167                         if (!wl_get_drv_status(cfg, CONNECTED, iter->ndev) ||
16168                                 (wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_BSS &&
16169                                 wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_IBSS))
16170                                 continue;
16171                         if (iter->ndev) {
16172                                 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM,
16173                                                 &pm, sizeof(pm), true)) != 0) {
16174                                         if (err == -ENODEV)
16175                                                 WL_DBG(("%s:netdev not ready\n",
16176                                                         iter->ndev->name));
16177                                         else
16178                                                 WL_ERR(("%s:error (%d)\n",
16179                                                         iter->ndev->name, err));
16180                                 } else
16181                                         wl_cfg80211_update_power_mode(iter->ndev);
16182                         }
16183                 }
16184         }
16185 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16186         4 && __GNUC_MINOR__ >= 6))
16187         _Pragma("GCC diagnostic pop")
16188 #endif
16189         DHD_OS_WAKE_UNLOCK(cfg->pub);
16190 }
16191
16192 u8
16193 wl_get_action_category(void *frame, u32 frame_len)
16194 {
16195         u8 category;
16196         u8 *ptr = (u8 *)frame;
16197         if (frame == NULL)
16198                 return DOT11_ACTION_CAT_ERR_MASK;
16199         if (frame_len < DOT11_ACTION_HDR_LEN)
16200                 return DOT11_ACTION_CAT_ERR_MASK;
16201         category = ptr[DOT11_ACTION_CAT_OFF];
16202         WL_INFORM(("Action Category: %d\n", category));
16203         return category;
16204 }
16205
16206 int
16207 wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action)
16208 {
16209         u8 *ptr = (u8 *)frame;
16210         if (frame == NULL || ret_action == NULL)
16211                 return BCME_ERROR;
16212         if (frame_len < DOT11_ACTION_HDR_LEN)
16213                 return BCME_ERROR;
16214         if (DOT11_ACTION_CAT_PUBLIC != wl_get_action_category(frame, frame_len))
16215                 return BCME_ERROR;
16216         *ret_action = ptr[DOT11_ACTION_ACT_OFF];
16217         WL_INFORM(("Public Action : %d\n", *ret_action));
16218         return BCME_OK;
16219 }
16220
16221
16222 static int
16223 wl_cfg80211_delayed_roam(struct bcm_cfg80211 *cfg, struct net_device *ndev,
16224         const struct ether_addr *bssid)
16225 {
16226         s32 err;
16227         wl_event_msg_t e;
16228
16229         bzero(&e, sizeof(e));
16230         e.event_type = cpu_to_be32(WLC_E_BSSID);
16231         memcpy(&e.addr, bssid, ETHER_ADDR_LEN);
16232         /* trigger the roam event handler */
16233         WL_INFORM(("Delayed roam to " MACDBG "\n", MAC2STRDBG((u8*)(bssid))));
16234         err = wl_notify_roaming_status(cfg, ndev_to_cfgdev(ndev), &e, NULL);
16235
16236         return err;
16237 }
16238
16239 static s32
16240 wl_cfg80211_parse_vndr_ies(u8 *parse, u32 len,
16241     struct parsed_vndr_ies *vndr_ies)
16242 {
16243         s32 err = BCME_OK;
16244         vndr_ie_t *vndrie;
16245         bcm_tlv_t *ie;
16246         struct parsed_vndr_ie_info *parsed_info;
16247         u32 count = 0;
16248         s32 remained_len;
16249
16250         remained_len = (s32)len;
16251         memset(vndr_ies, 0, sizeof(*vndr_ies));
16252
16253         WL_INFORM(("---> len %d\n", len));
16254         ie = (bcm_tlv_t *) parse;
16255         if (!bcm_valid_tlv(ie, remained_len))
16256                 ie = NULL;
16257         while (ie) {
16258                 if (count >= MAX_VNDR_IE_NUMBER)
16259                         break;
16260                 if (ie->id == DOT11_MNG_VS_ID) {
16261                         vndrie = (vndr_ie_t *) ie;
16262                         /* len should be bigger than OUI length + one data length at least */
16263                         if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) {
16264                                 WL_ERR(("%s: invalid vndr ie. length is too small %d\n",
16265                                         __FUNCTION__, vndrie->len));
16266                                 goto end;
16267                         }
16268                         /* if wpa or wme ie, do not add ie */
16269                         if (!bcmp(vndrie->oui, (u8*)WPA_OUI, WPA_OUI_LEN) &&
16270                                 ((vndrie->data[0] == WPA_OUI_TYPE) ||
16271                                 (vndrie->data[0] == WME_OUI_TYPE))) {
16272                                 CFGP2P_DBG(("Found WPA/WME oui. Do not add it\n"));
16273                                 goto end;
16274                         }
16275
16276                         parsed_info = &vndr_ies->ie_info[count++];
16277
16278                         /* save vndr ie information */
16279                         parsed_info->ie_ptr = (char *)vndrie;
16280                         parsed_info->ie_len = (vndrie->len + TLV_HDR_LEN);
16281                         memcpy(&parsed_info->vndrie, vndrie, sizeof(vndr_ie_t));
16282                         vndr_ies->count = count;
16283
16284                         WL_DBG(("\t ** OUI %02x %02x %02x, type 0x%02x len:%d\n",
16285                         parsed_info->vndrie.oui[0], parsed_info->vndrie.oui[1],
16286                         parsed_info->vndrie.oui[2], parsed_info->vndrie.data[0],
16287                         parsed_info->ie_len));
16288                 }
16289 end:
16290                 ie = bcm_next_tlv(ie, &remained_len);
16291         }
16292         return err;
16293 }
16294
16295 s32
16296 wl_cfg80211_clear_per_bss_ies(struct bcm_cfg80211 *cfg, s32 bssidx)
16297 {
16298         s32 index;
16299         struct net_info *netinfo;
16300         s32 vndrie_flag[] = {VNDR_IE_BEACON_FLAG, VNDR_IE_PRBRSP_FLAG,
16301                 VNDR_IE_ASSOCRSP_FLAG, VNDR_IE_PRBREQ_FLAG, VNDR_IE_ASSOCREQ_FLAG};
16302
16303         netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
16304         if (!netinfo || !netinfo->wdev) {
16305                 WL_ERR(("netinfo or netinfo->wdev is NULL\n"));
16306                 return -1;
16307         }
16308
16309         WL_DBG(("clear management vendor IEs for bssidx:%d \n", bssidx));
16310         /* Clear the IEs set in the firmware so that host is in sync with firmware */
16311         for (index = 0; index < ARRAYSIZE(vndrie_flag); index++) {
16312                 if (wl_cfg80211_set_mgmt_vndr_ies(cfg, wdev_to_cfgdev(netinfo->wdev),
16313                         bssidx, vndrie_flag[index], NULL, 0) < 0)
16314                         WL_ERR(("vndr_ies clear failed. Ignoring.. \n"));
16315         }
16316
16317         return 0;
16318 }
16319
16320 s32
16321 wl_cfg80211_clear_mgmt_vndr_ies(struct bcm_cfg80211 *cfg)
16322 {
16323         struct net_info *iter, *next;
16324
16325         WL_DBG(("clear management vendor IEs \n"));
16326 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16327         4 && __GNUC_MINOR__ >= 6))
16328 _Pragma("GCC diagnostic push")
16329 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16330 #endif
16331         for_each_ndev(cfg, iter, next) {
16332                 wl_cfg80211_clear_per_bss_ies(cfg, iter->bssidx);
16333         }
16334 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16335         4 && __GNUC_MINOR__ >= 6))
16336 _Pragma("GCC diagnostic pop")
16337 #endif
16338         return 0;
16339 }
16340
16341 #define WL_VNDR_IE_MAXLEN 2048
16342 static s8 g_mgmt_ie_buf[WL_VNDR_IE_MAXLEN];
16343 int
16344 wl_cfg80211_set_mgmt_vndr_ies(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
16345         s32 bssidx, s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len)
16346 {
16347         struct net_device *ndev = NULL;
16348         s32 ret = BCME_OK;
16349         u8  *curr_ie_buf = NULL;
16350         u8  *mgmt_ie_buf = NULL;
16351         u32 mgmt_ie_buf_len = 0;
16352         u32 *mgmt_ie_len = 0;
16353         u32 del_add_ie_buf_len = 0;
16354         u32 total_ie_buf_len = 0;
16355         u32 parsed_ie_buf_len = 0;
16356         struct parsed_vndr_ies old_vndr_ies;
16357         struct parsed_vndr_ies new_vndr_ies;
16358         s32 i;
16359         u8 *ptr;
16360         s32 remained_buf_len;
16361         wl_bss_vndr_ies_t *ies = NULL;
16362         struct net_info *netinfo;
16363
16364         WL_DBG(("Enter. pktflag:0x%x bssidx:%x vnd_ie_len:%d \n",
16365                 pktflag, bssidx, vndr_ie_len));
16366
16367         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
16368
16369         if (bssidx > WL_MAX_IFS) {
16370                 WL_ERR(("bssidx > supported concurrent Ifaces \n"));
16371                 return -EINVAL;
16372         }
16373
16374         netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
16375         if (!netinfo) {
16376                 WL_ERR(("net_info ptr is NULL \n"));
16377                 return -EINVAL;
16378         }
16379
16380         /* Clear the global buffer */
16381         memset(g_mgmt_ie_buf, 0, sizeof(g_mgmt_ie_buf));
16382         curr_ie_buf = g_mgmt_ie_buf;
16383         ies = &netinfo->bss.ies;
16384
16385         switch (pktflag) {
16386                 case VNDR_IE_PRBRSP_FLAG :
16387                         mgmt_ie_buf = ies->probe_res_ie;
16388                         mgmt_ie_len = &ies->probe_res_ie_len;
16389                         mgmt_ie_buf_len = sizeof(ies->probe_res_ie);
16390                         break;
16391                 case VNDR_IE_ASSOCRSP_FLAG :
16392                         mgmt_ie_buf = ies->assoc_res_ie;
16393                         mgmt_ie_len = &ies->assoc_res_ie_len;
16394                         mgmt_ie_buf_len = sizeof(ies->assoc_res_ie);
16395                         break;
16396                 case VNDR_IE_BEACON_FLAG :
16397                         mgmt_ie_buf = ies->beacon_ie;
16398                         mgmt_ie_len = &ies->beacon_ie_len;
16399                         mgmt_ie_buf_len = sizeof(ies->beacon_ie);
16400                         break;
16401                 case VNDR_IE_PRBREQ_FLAG :
16402                         mgmt_ie_buf = ies->probe_req_ie;
16403                         mgmt_ie_len = &ies->probe_req_ie_len;
16404                         mgmt_ie_buf_len = sizeof(ies->probe_req_ie);
16405                         break;
16406                 case VNDR_IE_ASSOCREQ_FLAG :
16407                         mgmt_ie_buf = ies->assoc_req_ie;
16408                         mgmt_ie_len = &ies->assoc_req_ie_len;
16409                         mgmt_ie_buf_len = sizeof(ies->assoc_req_ie);
16410                         break;
16411                 default:
16412                         mgmt_ie_buf = NULL;
16413                         mgmt_ie_len = NULL;
16414                         WL_ERR(("not suitable packet type (%d)\n", pktflag));
16415                         return BCME_ERROR;
16416         }
16417
16418         if (vndr_ie_len > mgmt_ie_buf_len) {
16419                 WL_ERR(("extra IE size too big\n"));
16420                 ret = -ENOMEM;
16421         } else {
16422                 /* parse and save new vndr_ie in curr_ie_buff before comparing it */
16423                 if (vndr_ie && vndr_ie_len && curr_ie_buf) {
16424                         ptr = curr_ie_buf;
16425 /* must discard vndr_ie constness, attempt to change vndr_ie arg to non-const
16426  * causes cascade of errors in other places, fix involves const casts there
16427  */
16428 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16429         4 && __GNUC_MINOR__ >= 6))
16430 _Pragma("GCC diagnostic push")
16431 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16432 #endif
16433                         if ((ret = wl_cfg80211_parse_vndr_ies((u8 *)vndr_ie,
16434                                 vndr_ie_len, &new_vndr_ies)) < 0) {
16435                                 WL_ERR(("parse vndr ie failed \n"));
16436                                 goto exit;
16437                         }
16438 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16439         4 && __GNUC_MINOR__ >= 6))
16440 _Pragma("GCC diagnostic pop")
16441 #endif
16442                         for (i = 0; i < new_vndr_ies.count; i++) {
16443                                 struct parsed_vndr_ie_info *vndrie_info =
16444                                         &new_vndr_ies.ie_info[i];
16445
16446                                 if ((parsed_ie_buf_len + vndrie_info->ie_len) > WL_VNDR_IE_MAXLEN) {
16447                                         WL_ERR(("IE size is too big (%d > %d)\n",
16448                                                 parsed_ie_buf_len, WL_VNDR_IE_MAXLEN));
16449                                         ret = -EINVAL;
16450                                         goto exit;
16451                                 }
16452
16453                                 memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr,
16454                                         vndrie_info->ie_len);
16455                                 parsed_ie_buf_len += vndrie_info->ie_len;
16456                         }
16457                 }
16458
16459                 if (mgmt_ie_buf != NULL) {
16460                         if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) &&
16461                                 (memcmp(mgmt_ie_buf, curr_ie_buf, parsed_ie_buf_len) == 0)) {
16462                                 WL_INFORM(("Previous mgmt IE is equals to current IE"));
16463                                 goto exit;
16464                         }
16465
16466                         /* parse old vndr_ie */
16467                         if ((ret = wl_cfg80211_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len,
16468                                 &old_vndr_ies)) < 0) {
16469                                 WL_ERR(("parse vndr ie failed \n"));
16470                                 goto exit;
16471                         }
16472                         /* make a command to delete old ie */
16473                         for (i = 0; i < old_vndr_ies.count; i++) {
16474                                 struct parsed_vndr_ie_info *vndrie_info =
16475                                 &old_vndr_ies.ie_info[i];
16476
16477                                 WL_INFORM(("DELETED ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
16478                                         vndrie_info->vndrie.id, vndrie_info->vndrie.len,
16479                                         vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1],
16480                                         vndrie_info->vndrie.oui[2]));
16481
16482                                 del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
16483                                         pktflag, vndrie_info->vndrie.oui,
16484                                         vndrie_info->vndrie.id,
16485                                         vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
16486                                         vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
16487                                         "del");
16488
16489                                 curr_ie_buf += del_add_ie_buf_len;
16490                                 total_ie_buf_len += del_add_ie_buf_len;
16491                         }
16492                 }
16493
16494                 *mgmt_ie_len = 0;
16495                 /* Add if there is any extra IE */
16496                 if (mgmt_ie_buf && parsed_ie_buf_len) {
16497                         ptr = mgmt_ie_buf;
16498
16499                         remained_buf_len = mgmt_ie_buf_len;
16500
16501                         /* make a command to add new ie */
16502                         for (i = 0; i < new_vndr_ies.count; i++) {
16503                                 struct parsed_vndr_ie_info *vndrie_info =
16504                                         &new_vndr_ies.ie_info[i];
16505
16506                                 WL_INFORM(("ADDED ID : %d, Len: %d(%d), OUI:%02x:%02x:%02x\n",
16507                                         vndrie_info->vndrie.id, vndrie_info->vndrie.len,
16508                                         vndrie_info->ie_len - 2,
16509                                         vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1],
16510                                         vndrie_info->vndrie.oui[2]));
16511
16512                                 del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
16513                                         pktflag, vndrie_info->vndrie.oui,
16514                                         vndrie_info->vndrie.id,
16515                                         vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
16516                                         vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
16517                                         "add");
16518
16519                                 /* verify remained buf size before copy data */
16520                                 if (remained_buf_len >= vndrie_info->ie_len) {
16521                                         remained_buf_len -= vndrie_info->ie_len;
16522                                 } else {
16523                                         WL_ERR(("no space in mgmt_ie_buf: pktflag = %d, "
16524                                         "found vndr ies # = %d(cur %d), remained len %d, "
16525                                         "cur mgmt_ie_len %d, new ie len = %d\n",
16526                                         pktflag, new_vndr_ies.count, i, remained_buf_len,
16527                                         *mgmt_ie_len, vndrie_info->ie_len));
16528                                         break;
16529                                 }
16530
16531                                 /* save the parsed IE in cfg struct */
16532                                 memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr,
16533                                         vndrie_info->ie_len);
16534                                 *mgmt_ie_len += vndrie_info->ie_len;
16535                                 curr_ie_buf += del_add_ie_buf_len;
16536                                 total_ie_buf_len += del_add_ie_buf_len;
16537                         }
16538                 }
16539
16540                 if (total_ie_buf_len && cfg->ioctl_buf != NULL) {
16541                         ret  = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", g_mgmt_ie_buf,
16542                                 total_ie_buf_len, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
16543                                 bssidx, &cfg->ioctl_buf_sync);
16544                         if (ret)
16545                                 WL_ERR(("vndr ie set error : %d\n", ret));
16546                 }
16547         }
16548 exit:
16549
16550 return ret;
16551 }
16552
16553 #ifdef WL_CFG80211_ACL
16554 static int
16555 wl_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *cfgdev,
16556         const struct cfg80211_acl_data *acl)
16557 {
16558         int i;
16559         int ret = 0;
16560         int macnum = 0;
16561         int macmode = MACLIST_MODE_DISABLED;
16562         struct maclist *list;
16563
16564         /* get the MAC filter mode */
16565         if (acl && acl->acl_policy == NL80211_ACL_POLICY_DENY_UNLESS_LISTED) {
16566                 macmode = MACLIST_MODE_ALLOW;
16567         } else if (acl && acl->acl_policy == NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
16568         acl->n_acl_entries) {
16569                 macmode = MACLIST_MODE_DENY;
16570         }
16571
16572         /* if acl == NULL, macmode is still disabled.. */
16573         if (macmode == MACLIST_MODE_DISABLED) {
16574                 if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, NULL)) != 0)
16575                         WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
16576
16577                 return ret;
16578         }
16579
16580         macnum = acl->n_acl_entries;
16581         if (macnum < 0 || macnum > MAX_NUM_MAC_FILT) {
16582                 WL_ERR(("%s : invalid number of MAC address entries %d\n",
16583                         __FUNCTION__, macnum));
16584                 return -1;
16585         }
16586
16587         /* allocate memory for the MAC list */
16588         list = (struct maclist*)kmalloc(sizeof(int) +
16589                 sizeof(struct ether_addr) * macnum, GFP_KERNEL);
16590         if (!list) {
16591                 WL_ERR(("%s : failed to allocate memory\n", __FUNCTION__));
16592                 return -1;
16593         }
16594
16595         /* prepare the MAC list */
16596         list->count = htod32(macnum);
16597         for (i = 0; i < macnum; i++) {
16598                 memcpy(&list->ea[i], &acl->mac_addrs[i], ETHER_ADDR_LEN);
16599         }
16600         /* set the list */
16601         if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, list)) != 0)
16602                 WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
16603
16604         kfree(list);
16605
16606         return ret;
16607 }
16608 #endif /* WL_CFG80211_ACL */
16609
16610 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
16611 int wl_chspec_chandef(chanspec_t chanspec,
16612 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
16613         struct cfg80211_chan_def *chandef,
16614 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
16615         struct chan_info *chaninfo,
16616 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */
16617 struct wiphy *wiphy)
16618
16619 {
16620         uint16 freq = 0;
16621         int chan_type = 0;
16622         int channel = 0;
16623         struct ieee80211_channel *chan;
16624
16625         if (!chandef) {
16626                 return -1;
16627         }
16628         channel = CHSPEC_CHANNEL(chanspec);
16629
16630         switch (CHSPEC_BW(chanspec)) {
16631                 case WL_CHANSPEC_BW_20:
16632                         chan_type = NL80211_CHAN_HT20;
16633                         break;
16634                 case WL_CHANSPEC_BW_40:
16635                 {
16636                         if (CHSPEC_SB_UPPER(chanspec)) {
16637                                 channel += CH_10MHZ_APART;
16638                         } else {
16639                                 channel -= CH_10MHZ_APART;
16640                         }
16641                 }
16642                         chan_type = NL80211_CHAN_HT40PLUS;
16643                         break;
16644
16645 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16646                 case WL_CHANSPEC_BW_80:
16647                 case WL_CHANSPEC_BW_8080:
16648                 {
16649                         uint16 sb = CHSPEC_CTL_SB(chanspec);
16650
16651                         if (sb == WL_CHANSPEC_CTL_SB_LL) {
16652                                 channel -= (CH_10MHZ_APART + CH_20MHZ_APART);
16653                         } else if (sb == WL_CHANSPEC_CTL_SB_LU) {
16654                                 channel -= CH_10MHZ_APART;
16655                         } else if (sb == WL_CHANSPEC_CTL_SB_UL) {
16656                                 channel += CH_10MHZ_APART;
16657                         } else {
16658                                 /* WL_CHANSPEC_CTL_SB_UU */
16659                                 channel += (CH_10MHZ_APART + CH_20MHZ_APART);
16660                         }
16661
16662                         if (sb == WL_CHANSPEC_CTL_SB_LL || sb == WL_CHANSPEC_CTL_SB_LU)
16663                                 chan_type = NL80211_CHAN_HT40MINUS;
16664                         else if (sb == WL_CHANSPEC_CTL_SB_UL || sb == WL_CHANSPEC_CTL_SB_UU)
16665                                 chan_type = NL80211_CHAN_HT40PLUS;
16666                 }
16667                         break;
16668 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16669                 default:
16670                         chan_type = NL80211_CHAN_HT20;
16671                         break;
16672
16673         }
16674
16675         if (CHSPEC_IS5G(chanspec))
16676                 freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_5GHZ);
16677         else
16678                 freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_2GHZ);
16679
16680         chan = ieee80211_get_channel(wiphy, freq);
16681         WL_DBG(("channel:%d freq:%d chan_type: %d chan_ptr:%p \n",
16682                 channel, freq, chan_type, chan));
16683
16684         if (unlikely(!chan)) {
16685                 /* fw and cfg80211 channel lists are not in sync */
16686                 WL_ERR(("Couldn't find matching channel in wiphy channel list \n"));
16687                 ASSERT(0);
16688                 return -EINVAL;
16689         }
16690
16691 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16692         cfg80211_chandef_create(chandef, chan, chan_type);
16693 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
16694         \
16695         \
16696         \
16697         0)))
16698         chaninfo->freq = freq;
16699         chaninfo->chan_type = chan_type;
16700 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16701         return 0;
16702 }
16703
16704 void
16705 wl_cfg80211_ch_switch_notify(struct net_device *dev, uint16 chanspec, struct wiphy *wiphy)
16706 {
16707         u32 freq;
16708 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16709         struct cfg80211_chan_def chandef;
16710 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
16711         \
16712         \
16713         \
16714         0)))
16715         struct chan_info chaninfo;
16716 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16717
16718         if (!wiphy) {
16719                 printf("wiphy is null\n");
16720                 return;
16721         }
16722 #ifndef ALLOW_CHSW_EVT
16723         /* Channel switch support is only for AP/GO/ADHOC/MESH */
16724         if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION ||
16725                 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) {
16726                 WL_ERR(("No channel switch notify support for STA/GC\n"));
16727                 return;
16728         }
16729 #endif /* !ALLOW_CHSW_EVT */
16730 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16731         if (wl_chspec_chandef(chanspec, &chandef, wiphy))
16732 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
16733         if (wl_chspec_chandef(chanspec, &chaninfo, wiphy))
16734 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16735         {
16736                 WL_ERR(("%s:chspec_chandef failed\n", __FUNCTION__));
16737                 return;
16738         }
16739 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16740         freq = chandef.chan ? chandef.chan->center_freq : chandef.center_freq1;
16741         cfg80211_ch_switch_notify(dev, &chandef);
16742 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
16743         freq = chan_info.freq;
16744         cfg80211_ch_switch_notify(dev, chan_info.freq, chan_info.chan_type);
16745 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16746
16747         WL_ERR(("Channel switch notification for freq: %d chanspec: 0x%x\n", freq, chanspec));
16748         return;
16749 }
16750 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
16751
16752 #ifdef WL11ULB
16753 s32
16754 wl_cfg80211_set_ulb_mode(struct net_device *dev, int mode)
16755 {
16756         int ret;
16757         int cur_mode;
16758
16759         ret = wldev_iovar_getint(dev, "ulb_mode", &cur_mode);
16760         if (unlikely(ret)) {
16761                 WL_ERR(("[ULB] ulb_mode get failed. ret:%d \n", ret));
16762                 return ret;
16763         }
16764
16765         if (cur_mode == mode) {
16766                 /* If request mode is same as that of the current mode, then
16767                  * do nothing (Avoid unnecessary wl down and up).
16768                  */
16769                 WL_INFORM(("[ULB] No change in ulb_mode. Do nothing.\n"));
16770                 return 0;
16771         }
16772
16773         /* setting of ulb_mode requires wl to be down */
16774         ret = wldev_ioctl(dev, WLC_DOWN, NULL, 0, true);
16775         if (unlikely(ret)) {
16776                 WL_ERR(("[ULB] WLC_DOWN command failed:[%d]\n", ret));
16777                 return ret;
16778         }
16779
16780         if (mode >= MAX_SUPP_ULB_MODES) {
16781                 WL_ERR(("[ULB] unsupported ulb_mode :[%d]\n", mode));
16782                 return -EINVAL;
16783         }
16784
16785         ret = wldev_iovar_setint(dev, "ulb_mode", mode);
16786         if (unlikely(ret)) {
16787                 WL_ERR(("[ULB] ulb_mode set failed. ret:%d \n", ret));
16788                 return ret;
16789         }
16790
16791         ret = wldev_ioctl(dev, WLC_UP, NULL, 0, true);
16792         if (unlikely(ret)) {
16793                 WL_ERR(("[ULB] WLC_DOWN command failed:[%d]\n", ret));
16794                 return ret;
16795         }
16796
16797         WL_DBG(("[ULB] ulb_mode set to %d successfully \n", mode));
16798
16799         return ret;
16800 }
16801
16802 static s32
16803 wl_cfg80211_ulbbw_to_ulbchspec(u32 bw)
16804 {
16805         if (bw == ULB_BW_DISABLED) {
16806                 return WL_CHANSPEC_BW_20;
16807         } else if (bw == ULB_BW_10MHZ) {
16808                 return WL_CHANSPEC_BW_10;
16809         } else if (bw == ULB_BW_5MHZ) {
16810                 return WL_CHANSPEC_BW_5;
16811         } else if (bw == ULB_BW_2P5MHZ) {
16812                 return WL_CHANSPEC_BW_2P5;
16813         } else {
16814                 WL_ERR(("[ULB] unsupported value for ulb_bw \n"));
16815                 return -EINVAL;
16816         }
16817 }
16818
16819 static chanspec_t
16820 wl_cfg80211_ulb_get_min_bw_chspec(struct wireless_dev *wdev, s32 bssidx)
16821 {
16822         struct bcm_cfg80211 *cfg = g_bcm_cfg;
16823         struct net_info *_netinfo;
16824
16825         /*
16826          *  Return the chspec value corresponding to the
16827          *  BW setting for a particular interface
16828          */
16829         if (wdev) {
16830                 /* if wdev is provided, use it */
16831                 _netinfo = wl_get_netinfo_by_wdev(cfg, wdev);
16832         } else if (bssidx >= 0) {
16833                 /* if wdev is not provided, use it */
16834                 _netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
16835         } else {
16836                 WL_ERR(("[ULB] wdev/bssidx not provided\n"));
16837                 return INVCHANSPEC;
16838         }
16839
16840         if (unlikely(!_netinfo)) {
16841                 WL_ERR(("[ULB] net_info is null \n"));
16842                 return INVCHANSPEC;
16843         }
16844
16845         if (_netinfo->ulb_bw) {
16846                 WL_DBG(("[ULB] wdev_ptr:%p ulb_bw:0x%x \n", _netinfo->wdev, _netinfo->ulb_bw));
16847                 return wl_cfg80211_ulbbw_to_ulbchspec(_netinfo->ulb_bw);
16848         } else {
16849                 return WL_CHANSPEC_BW_20;
16850         }
16851 }
16852
16853 static s32
16854 wl_cfg80211_get_ulb_bw(struct wireless_dev *wdev)
16855 {
16856         struct bcm_cfg80211 *cfg = g_bcm_cfg;
16857         struct net_info *_netinfo = wl_get_netinfo_by_wdev(cfg, wdev);
16858
16859         /*
16860          *  Return the ulb_bw setting for a
16861          *  particular interface
16862          */
16863         if (unlikely(!_netinfo)) {
16864                 WL_ERR(("[ULB] net_info is null \n"));
16865                 return -1;
16866         }
16867
16868         return _netinfo->ulb_bw;
16869 }
16870
16871 s32
16872 wl_cfg80211_set_ulb_bw(struct net_device *dev,
16873         u32 ulb_bw,  char *ifname)
16874 {
16875         struct bcm_cfg80211 *cfg = g_bcm_cfg;
16876         int ret;
16877         int mode;
16878         struct net_info *_netinfo = NULL, *iter, *next;
16879         u32 bssidx;
16880         enum nl80211_iftype iftype;
16881
16882         if (!ifname)
16883                 return -EINVAL;
16884
16885         WL_DBG(("[ULB] Enter. bw_type:%d \n", ulb_bw));
16886
16887         ret = wldev_iovar_getint(dev, "ulb_mode", &mode);
16888         if (unlikely(ret)) {
16889                 WL_ERR(("[ULB] ulb_mode not supported \n"));
16890                 return ret;
16891         }
16892
16893         if (mode != ULB_MODE_STD_ALONE_MODE) {
16894                 WL_ERR(("[ULB] ulb bw modification allowed only in stand-alone mode\n"));
16895                 return -EINVAL;
16896         }
16897
16898         if (ulb_bw >= MAX_SUPP_ULB_BW) {
16899                 WL_ERR(("[ULB] unsupported value (%d) for ulb_bw \n", ulb_bw));
16900                 return -EINVAL;
16901         }
16902
16903 #ifdef WL_CFG80211_P2P_DEV_IF
16904         if (strcmp(ifname, "p2p-dev-wlan0") == 0) {
16905                 iftype = NL80211_IFTYPE_P2P_DEVICE;
16906                 /* Use wdev corresponding to the dedicated p2p discovery interface */
16907                 if (likely(cfg->p2p_wdev)) {
16908                         _netinfo = wl_get_netinfo_by_wdev(cfg, cfg->p2p_wdev);
16909                 } else {
16910                         return -ENODEV;
16911                 }
16912         }
16913 #endif /* WL_CFG80211_P2P_DEV_IF */
16914         if (!_netinfo) {
16915                 for_each_ndev(cfg, iter, next) {
16916                         if (iter->ndev) {
16917                                 if (strncmp(iter->ndev->name, ifname, strlen(ifname)) == 0) {
16918                                         _netinfo = wl_get_netinfo_by_netdev(cfg, iter->ndev);
16919                                         iftype = NL80211_IFTYPE_STATION;
16920                                 }
16921                         }
16922                 }
16923         }
16924
16925         if (!_netinfo)
16926                 return -ENODEV;
16927         bssidx = _netinfo->bssidx;
16928         _netinfo->ulb_bw = ulb_bw;
16929
16930
16931         WL_DBG(("[ULB] Applying ulb_bw:%d for bssidx:%d \n", ulb_bw, bssidx));
16932         ret = wldev_iovar_setbuf_bsscfg(dev, "ulb_bw", (void *)&ulb_bw, 4,
16933                 cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx,
16934                 &cfg->ioctl_buf_sync);
16935         if (unlikely(ret)) {
16936                 WL_ERR(("[ULB] ulb_bw set failed. ret:%d \n", ret));
16937                 return ret;
16938         }
16939
16940         return ret;
16941 }
16942 #endif /* WL11ULB */
16943
16944 static void
16945 wl_ap_channel_ind(struct bcm_cfg80211 *cfg,
16946         struct net_device *ndev,
16947         chanspec_t chanspec)
16948 {
16949         u32 channel = LCHSPEC_CHANNEL(chanspec);
16950
16951         WL_DBG(("(%s) AP channel:%d chspec:0x%x \n",
16952                 ndev->name, channel, chanspec));
16953         if (cfg->ap_oper_channel && (cfg->ap_oper_channel != channel)) {
16954                 /*
16955                  * If cached channel is different from the channel indicated
16956                  * by the event, notify user space about the channel switch.
16957                  */
16958 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
16959                 wl_cfg80211_ch_switch_notify(ndev, chanspec, bcmcfg_to_wiphy(cfg));
16960 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
16961                 cfg->ap_oper_channel = channel;
16962         }
16963 }
16964
16965 static s32
16966 wl_ap_start_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
16967 const wl_event_msg_t *e, void *data)
16968 {
16969         struct net_device *ndev = NULL;
16970         chanspec_t chanspec;
16971         u32 channel;
16972
16973         WL_DBG(("Enter\n"));
16974         if (unlikely(e->status)) {
16975                 WL_ERR(("status:0x%x \n", e->status));
16976                 return -1;
16977         }
16978
16979         if (!data) {
16980                 return -EINVAL;
16981         }
16982
16983         if (likely(cfgdev)) {
16984                 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
16985                 chanspec = *((chanspec_t *)data);
16986                 channel =  LCHSPEC_CHANNEL(chanspec);
16987
16988                 if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
16989                         /* For AP/GO role */
16990                         wl_ap_channel_ind(cfg, ndev, chanspec);
16991                 }
16992         }
16993
16994         return 0;
16995 }
16996
16997 static s32
16998 wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
16999 const wl_event_msg_t *e, void *data)
17000 {
17001         int error = 0;
17002         u32 chanspec = 0;
17003         struct net_device *ndev = NULL;
17004         struct wiphy *wiphy = NULL;
17005
17006         WL_DBG(("Enter\n"));
17007         if (unlikely(e->status)) {
17008                 WL_ERR(("status:0x%x \n", e->status));
17009                 return -1;
17010         }
17011
17012         if (likely(cfgdev)) {
17013                 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
17014                 wiphy = bcmcfg_to_wiphy(cfg);
17015                 error = wldev_iovar_getint(ndev, "chanspec", &chanspec);
17016                 if (unlikely(error)) {
17017                         WL_ERR(("Get chanspec error: %d \n", error));
17018                         return -1;
17019                 }
17020
17021                 if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
17022                         /* For AP/GO role */
17023                         wl_ap_channel_ind(cfg, ndev, chanspec);
17024                 } else {
17025 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
17026                         wl_cfg80211_ch_switch_notify(ndev, chanspec, wiphy);
17027 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
17028                 }
17029
17030         }
17031
17032         return 0;
17033 }
17034
17035 #ifdef WL_NAN
17036 int
17037 wl_cfg80211_nan_cmd_handler(struct net_device *ndev, char *cmd, int cmd_len)
17038 {
17039         return wl_cfgnan_cmd_handler(ndev, g_bcm_cfg, cmd, cmd_len);
17040 }
17041 #endif /* WL_NAN */
17042
17043 void wl_cfg80211_clear_security(struct bcm_cfg80211 *cfg)
17044 {
17045         struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
17046         int err;
17047
17048         /* Clear the security settings on the primary Interface */
17049         err = wldev_iovar_setint(dev, "wsec", 0);
17050         if (unlikely(err)) {
17051                 WL_ERR(("wsec clear failed \n"));
17052         }
17053         err = wldev_iovar_setint(dev, "auth", 0);
17054         if (unlikely(err)) {
17055                 WL_ERR(("auth clear failed \n"));
17056         }
17057         err = wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
17058         if (unlikely(err)) {
17059                 WL_ERR(("wpa_auth clear failed \n"));
17060         }
17061 }
17062
17063 #ifdef WL_CFG80211_P2P_DEV_IF
17064 void wl_cfg80211_del_p2p_wdev(void)
17065 {
17066         struct bcm_cfg80211 *cfg = g_bcm_cfg;
17067         struct wireless_dev *wdev = NULL;
17068
17069         WL_DBG(("Enter \n"));
17070         if (!cfg) {
17071                 WL_ERR(("Invalid Ptr\n"));
17072                 return;
17073         } else {
17074                 wdev = cfg->p2p_wdev;
17075         }
17076
17077         if (wdev && cfg->down_disc_if) {
17078                 wl_cfgp2p_del_p2p_disc_if(wdev, cfg);
17079                 cfg->down_disc_if = FALSE;
17080         }
17081 }
17082 #endif /* WL_CFG80211_P2P_DEV_IF */
17083
17084 #if defined(WL_SUPPORT_AUTO_CHANNEL)
17085 int
17086 wl_cfg80211_set_spect(struct net_device *dev, int spect)
17087 {
17088         struct bcm_cfg80211 *cfg = g_bcm_cfg;
17089         int down = 1;
17090         int up = 1;
17091         int err = BCME_OK;
17092
17093         if (!wl_get_drv_status_all(cfg, CONNECTED)) {
17094                 err = wldev_ioctl(dev, WLC_DOWN, &down, sizeof(down), true);
17095                 if (err) {
17096                         WL_ERR(("%s: WLC_DOWN failed: code: %d\n", __func__, err));
17097                         return err;
17098                 }
17099
17100                 err = wldev_ioctl(dev, WLC_SET_SPECT_MANAGMENT, &spect, sizeof(spect), true);
17101                 if (err) {
17102                         WL_ERR(("%s: error setting spect: code: %d\n", __func__, err));
17103                         return err;
17104                 }
17105
17106                 err = wldev_ioctl(dev, WLC_UP, &up, sizeof(up), true);
17107                 if (err) {
17108                         WL_ERR(("%s: WLC_UP failed: code: %d\n", __func__, err));
17109                         return err;
17110                 }
17111         }
17112         return err;
17113 }
17114
17115 int
17116 wl_cfg80211_get_sta_channel(void)
17117 {
17118         struct net_device *ndev = bcmcfg_to_prmry_ndev(g_bcm_cfg);
17119         int channel = 0;
17120
17121         if (wl_get_drv_status(g_bcm_cfg, CONNECTED, ndev)) {
17122                 channel = g_bcm_cfg->channel;
17123         }
17124         return channel;
17125 }
17126 #endif /* WL_SUPPORT_AUTO_CHANNEL */
17127 #ifdef P2P_LISTEN_OFFLOADING
17128 s32
17129 wl_cfg80211_p2plo_deinit(struct bcm_cfg80211 *cfg)
17130 {
17131         s32 bssidx;
17132         int ret = 0;
17133         int p2plo_pause = 0;
17134         if (!cfg || !cfg->p2p) {
17135                 WL_ERR(("Wl %p or cfg->p2p %p is null\n",
17136                         cfg, cfg ? cfg->p2p : 0));
17137                 return 0;
17138         }
17139
17140         bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
17141         ret = wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg),
17142                         "p2po_stop", (void*)&p2plo_pause, sizeof(p2plo_pause),
17143                         cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, NULL);
17144         if (ret < 0) {
17145                 WL_ERR(("p2po_stop Failed :%d\n", ret));
17146         }
17147
17148         return  ret;
17149 }
17150 s32
17151 wl_cfg80211_p2plo_listen_start(struct net_device *dev, u8 *buf, int len)
17152 {
17153         struct bcm_cfg80211 *cfg = g_bcm_cfg;
17154         s32 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
17155         wl_p2plo_listen_t p2plo_listen;
17156         int ret = -EAGAIN;
17157         int channel = 0;
17158         int period = 0;
17159         int interval = 0;
17160         int count = 0;
17161
17162         if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg)) {
17163                 WL_ERR(("Sending Action Frames. Try it again.\n"));
17164                 goto exit;
17165         }
17166
17167         if (wl_get_drv_status_all(cfg, SCANNING)) {
17168                 WL_ERR(("Scanning already\n"));
17169                 goto exit;
17170         }
17171
17172         if (wl_get_drv_status(cfg, SCAN_ABORTING, dev)) {
17173                 WL_ERR(("Scanning being aborted\n"));
17174                 goto exit;
17175         }
17176
17177         if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
17178                 WL_ERR(("p2p listen offloading already running\n"));
17179                 goto exit;
17180         }
17181
17182         /* Just in case if it is not enabled */
17183         if ((ret = wl_cfgp2p_enable_discovery(cfg, dev, NULL, 0)) < 0) {
17184                 WL_ERR(("cfgp2p_enable discovery failed"));
17185                 goto exit;
17186         }
17187
17188         bzero(&p2plo_listen, sizeof(wl_p2plo_listen_t));
17189
17190         if (len) {
17191                 sscanf(buf, " %10d %10d %10d %10d", &channel, &period, &interval, &count);
17192                 if ((channel == 0) || (period == 0) ||
17193                         (interval == 0) || (count == 0)) {
17194                         WL_ERR(("Wrong argument %d/%d/%d/%d \n",
17195                                 channel, period, interval, count));
17196                         ret = -EAGAIN;
17197                         goto exit;
17198                 }
17199                 p2plo_listen.period = period;
17200                 p2plo_listen.interval = interval;
17201                 p2plo_listen.count = count;
17202
17203                 WL_ERR(("channel:%d period:%d, interval:%d count:%d\n",
17204                                 channel, period, interval, count));
17205         } else {
17206                 WL_ERR(("Argument len is wrong.\n"));
17207                 ret = -EAGAIN;
17208                 goto exit;
17209         }
17210
17211         if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen_channel", (void*)&channel,
17212                         sizeof(channel), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
17213                         bssidx, &cfg->ioctl_buf_sync)) < 0) {
17214                 WL_ERR(("p2po_listen_channel Failed :%d\n", ret));
17215                 goto exit;
17216         }
17217
17218         if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen", (void*)&p2plo_listen,
17219                         sizeof(wl_p2plo_listen_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
17220                         bssidx, &cfg->ioctl_buf_sync)) < 0) {
17221                 WL_ERR(("p2po_listen Failed :%d\n", ret));
17222                 goto exit;
17223         }
17224
17225         wl_set_p2p_status(cfg, DISC_IN_PROGRESS);
17226         cfg->last_roc_id = P2PO_COOKIE;
17227 exit :
17228         return ret;
17229 }
17230 s32
17231 wl_cfg80211_p2plo_listen_stop(struct net_device *dev)
17232 {
17233         struct bcm_cfg80211 *cfg = g_bcm_cfg;
17234         s32 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
17235         int ret = -EAGAIN;
17236
17237         if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_stop", NULL,
17238                         0, cfg->ioctl_buf, WLC_IOCTL_SMLEN,
17239                         bssidx, &cfg->ioctl_buf_sync)) < 0) {
17240                 WL_ERR(("p2po_stop Failed :%d\n", ret));
17241                 goto exit;
17242         }
17243
17244 exit:
17245         return ret;
17246 }
17247 #endif /* P2P_LISTEN_OFFLOADING */
17248 u64
17249 wl_cfg80211_get_new_roc_id(struct bcm_cfg80211 *cfg)
17250 {
17251         u64 id = 0;
17252         id = ++cfg->last_roc_id;
17253 #ifdef  P2P_LISTEN_OFFLOADING
17254         if (id == P2PO_COOKIE) {
17255                 id = ++cfg->last_roc_id;
17256         }
17257 #endif /* P2P_LISTEN_OFFLOADING */
17258         if (id == 0)
17259                 id = ++cfg->last_roc_id;
17260         return id;
17261 }
17262
17263 #if defined(SUPPORT_RANDOM_MAC_SCAN)
17264 int
17265 wl_cfg80211_set_random_mac(struct net_device *dev, bool enable)
17266 {
17267         struct bcm_cfg80211 *cfg = g_bcm_cfg;
17268         int ret;
17269
17270         if (cfg->random_mac_enabled == enable) {
17271                 WL_ERR(("Random MAC already %s\n", enable ? "Enabled" : "Disabled"));
17272                 return BCME_OK;
17273         }
17274
17275         if (enable) {
17276                 ret = wl_cfg80211_random_mac_enable(dev);
17277         } else {
17278                 ret = wl_cfg80211_random_mac_disable(dev);
17279         }
17280
17281         if (!ret) {
17282                 cfg->random_mac_enabled = enable;
17283         }
17284
17285         return ret;
17286 }
17287
17288 int
17289 wl_cfg80211_random_mac_enable(struct net_device *dev)
17290 {
17291         u8 current_mac[ETH_ALEN] = {0, };
17292         s32 err = BCME_ERROR;
17293         uint8 buffer[20] = {0, };
17294         wl_scanmac_t *sm = NULL;
17295         int len = 0;
17296         wl_scanmac_enable_t *sm_enable = NULL;
17297         wl_scanmac_config_t *sm_config = NULL;
17298         struct bcm_cfg80211 *cfg = g_bcm_cfg;
17299
17300         if (wl_get_drv_status_all(cfg, CONNECTED) || wl_get_drv_status_all(cfg, CONNECTING) ||
17301             wl_get_drv_status_all(cfg, AP_CREATED) || wl_get_drv_status_all(cfg, AP_CREATING)) {
17302                 WL_ERR(("Fail to Set random mac, current state is wrong\n"));
17303                 return err;
17304         }
17305
17306         /* Read current mac address */
17307         err = wldev_iovar_getbuf_bsscfg(dev, "cur_etheraddr",
17308                 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
17309
17310         if (err != BCME_OK) {
17311                 WL_ERR(("failed to get current dongle mac address\n"));
17312                 return err;
17313         }
17314
17315         memcpy(current_mac, cfg->ioctl_buf, ETH_ALEN);
17316
17317         /* Enable scan mac */
17318         sm = (wl_scanmac_t *)buffer;
17319         sm_enable = (wl_scanmac_enable_t *)sm->data;
17320         sm->len = sizeof(*sm_enable);
17321         sm_enable->enable = 1;
17322         len = OFFSETOF(wl_scanmac_t, data) + sm->len;
17323         sm->subcmd_id = WL_SCANMAC_SUBCMD_ENABLE;
17324
17325         err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
17326                 sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
17327
17328         if (err != BCME_OK) {
17329                 WL_ERR(("failed to enable scanmac, err=%d\n", err));
17330                 return err;
17331         }
17332
17333         /* Configure scanmac */
17334         memset(buffer, 0x0, sizeof(buffer));
17335         sm_config = (wl_scanmac_config_t *)sm->data;
17336         sm->len = sizeof(*sm_config);
17337         sm->subcmd_id = WL_SCANMAC_SUBCMD_CONFIG;
17338         sm_config->scan_bitmap = WL_SCANMAC_SCAN_UNASSOC;
17339
17340         /* Set current mac address */
17341         memcpy(&sm_config->mac.octet, current_mac, ETH_ALEN);
17342         sm_config->mac.octet[3] = 0x0;
17343         sm_config->mac.octet[4] = 0x0;
17344         sm_config->mac.octet[5] = 0x0;
17345
17346         /* Set randomize mac address(last 3bytes) */
17347         memset(&sm_config->random_mask.octet, 0x0, ETH_ALEN);
17348         sm_config->random_mask.octet[3] = 0xff;
17349         sm_config->random_mask.octet[4] = 0xff;
17350         sm_config->random_mask.octet[5] = 0xff;
17351
17352         len = OFFSETOF(wl_scanmac_t, data) + sm->len;
17353
17354         err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
17355                 sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
17356
17357         if (err != BCME_OK) {
17358                 WL_ERR(("failed scanmac configuration\n"));
17359
17360                 /* Disable scan mac for clean-up */
17361                 wl_cfg80211_random_mac_disable(dev);
17362                 return err;
17363         }
17364
17365         WL_ERR(("random MAC enable done"));
17366         return err;
17367 }
17368
17369 int
17370 wl_cfg80211_random_mac_disable(struct net_device *dev)
17371 {
17372         s32 err = BCME_ERROR;
17373         uint8 buffer[20] = {0, };
17374         wl_scanmac_t *sm = NULL;
17375         int len = 0;
17376         wl_scanmac_enable_t *sm_enable = NULL;
17377         struct bcm_cfg80211 *cfg = g_bcm_cfg;
17378
17379         sm = (wl_scanmac_t *)buffer;
17380         sm_enable = (wl_scanmac_enable_t *)sm->data;
17381         sm->len = sizeof(*sm_enable);
17382         sm_enable->enable = 0;
17383         len = OFFSETOF(wl_scanmac_t, data) + sm->len;
17384
17385         sm->subcmd_id = WL_SCANMAC_SUBCMD_ENABLE;
17386
17387         err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
17388                 sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
17389
17390         if (err != BCME_OK) {
17391                 WL_ERR(("failed to disable scanmac, err=%d\n", err));
17392                 return err;
17393         }
17394
17395         WL_ERR(("random MAC disable done\n"));
17396         return err;
17397 }
17398 #endif /* SUPPORT_RANDOM_MAC_SCAN */
17399
17400 int
17401 wl_cfg80211_iface_count(void)
17402 {
17403         struct bcm_cfg80211 *cfg = g_bcm_cfg;
17404         struct net_info *iter, *next;
17405         int iface_count = 0;
17406
17407         for_each_ndev(cfg, iter, next) {
17408                 if (iter->ndev) {
17409                         iface_count++;
17410                 }
17411         }
17412         return iface_count;
17413 }
17414
17415 #ifdef DHD_LOG_DUMP
17416 struct bcm_cfg80211*
17417 wl_get_bcm_cfg80211_ptr(void)
17418 {
17419         return g_bcm_cfg;
17420 }
17421 #endif /* DHD_LOG_DUMP */
17422
17423 #define CHECK_DONGLE_IDLE_TIME  50
17424 #define CHECK_DONGLE_IDLE_CNT   100
17425 int
17426 wl_check_dongle_idle(struct wiphy *wiphy)
17427 {
17428         int error = 0;
17429         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
17430         struct net_device *primary_ndev;
17431         int retry = 0;
17432         struct channel_info ci;
17433         if (!cfg)
17434                 return FALSE;
17435         /* Use primary I/F for sending cmds down to firmware */
17436         primary_ndev = bcmcfg_to_prmry_ndev(cfg);
17437
17438         while (retry++ < CHECK_DONGLE_IDLE_CNT) {
17439                 error = wldev_ioctl(primary_ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false);
17440                 if (error != BCME_OK || ci.scan_channel != 0) {
17441                         WL_ERR(("Firmware is busy(err:%d scan channel:%d). wait %dms\n",
17442                                 error, ci.scan_channel, CHECK_DONGLE_IDLE_TIME));
17443                 } else {
17444                         break;
17445                 }
17446                 wl_delay(CHECK_DONGLE_IDLE_TIME);
17447         }
17448         if (retry >= CHECK_DONGLE_IDLE_CNT) {
17449                 WL_ERR(("DONGLE is BUSY too long\n"));
17450                 return FALSE;
17451         }
17452         WL_DBG(("DONGLE is idle\n"));
17453         return TRUE;
17454 }