net: wireless: bcmdhd_88: Verify SSID length
[linux-3.10.git] / drivers / net / wireless / bcmdhd / wl_cfg80211.c
1 /*
2  * Linux cfg80211 driver
3  *
4  * Copyright (C) 1999-2015, Broadcom Corporation
5  * 
6  * Portions contributed by Nvidia
7  * Copyright (C) 2015 NVIDIA Corporation. All rights reserved.
8  *
9  *      Unless you and Broadcom execute a separate written software license
10  * agreement governing use of this software, this software is licensed to you
11  * under the terms of the GNU General Public License version 2 (the "GPL"),
12  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
13  * following added to such license:
14  * 
15  *      As a special exception, the copyright holders of this software give you
16  * permission to link this software with independent modules, and to copy and
17  * distribute the resulting executable under terms of your choice, provided that
18  * you also meet, for each linked independent module, the terms and conditions of
19  * the license of that module.  An independent module is a module which is not
20  * derived from this software.  The special exception does not apply to any
21  * modifications of the software.
22  * 
23  *      Notwithstanding the above, under no circumstances may you combine this
24  * software in any way with any other Broadcom software provided under a license
25  * other than the GPL, without Broadcom's express prior written consent.
26  *
27  * $Id: wl_cfg80211.c 534534 2015-02-13 11:46:03Z $
28  */
29 /* */
30 #include <typedefs.h>
31 #include "dynamic.h"
32 #include <linuxver.h>
33 #include <osl.h>
34 #include <linux/kernel.h>
35
36 #include <bcmutils.h>
37 #include <bcmwifi_channels.h>
38 #include <bcmendian.h>
39 #include <proto/ethernet.h>
40 #include <proto/802.11.h>
41 #include <linux/if_arp.h>
42 #include <asm/uaccess.h>
43
44 #include <dngl_stats.h>
45 #include <dhd.h>
46 #include <dhd_linux.h>
47 #include <dhdioctl.h>
48 #include <wlioctl.h>
49 #include <dhd_cfg80211.h>
50 #ifdef PNO_SUPPORT
51 #include <dhd_pno.h>
52 #endif /* PNO_SUPPORT */
53
54 #include <proto/ethernet.h>
55 #include <linux/kernel.h>
56 #include <linux/kthread.h>
57 #include <linux/netdevice.h>
58 #include <linux/sched.h>
59 #include <linux/etherdevice.h>
60 #include <linux/wireless.h>
61 #include <linux/ieee80211.h>
62 #include <linux/wait.h>
63 #include <net/cfg80211.h>
64 #include <net/rtnetlink.h>
65
66 #include <wlioctl.h>
67 #include <wldev_common.h>
68 #include <wl_cfg80211.h>
69 #include <wl_cfgp2p.h>
70 #include <wl_android.h>
71 #ifdef WL_NAN
72 #include <wl_cfgnan.h>
73 #endif /* WL_NAN */
74
75 #ifdef PROP_TXSTATUS
76 #include <dhd_wlfc.h>
77 #endif
78
79 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
80 #include <wl_cfgvendor.h>
81 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
82 #ifdef WL11U
83 #if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
84 #error You should enable 'WL_ENABLE_P2P_IF' or 'WL_CFG80211_P2P_DEV_IF' \
85         according to Kernel version and is supported only in Android-JB
86 #endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
87 #endif /* WL11U */
88
89 #ifdef CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA
90 #include "dhd_custom_sysfs_tegra.h"
91 #include "dhd_custom_sysfs_tegra_scan.h"
92 #endif
93
94
95 #define IW_WSEC_ENABLED(wsec)   ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
96
97 static struct device *cfg80211_parent_dev = NULL;
98 /* g_bcm_cfg should be static. Do not change */
99 static struct bcm_cfg80211 *g_bcm_cfg = NULL;
100 u32 wl_dbg_level = WL_DBG_ERR;
101
102 extern int op_mode;
103
104 #ifdef WLAIBSS_MCHAN
105 #define IBSS_IF_NAME "ibss%d"
106 #endif /* WLAIBSS_MCHAN */
107
108 #ifdef VSDB
109 /* sleep time to keep STA's connecting or connection for continuous af tx or finding a peer */
110 #define DEFAULT_SLEEP_TIME_VSDB         120
111 #define OFF_CHAN_TIME_THRESHOLD_MS      200
112 #define AF_RETRY_DELAY_TIME                     40
113
114 /* if sta is connected or connecting, sleep for a while before retry af tx or finding a peer */
115 #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg)  \
116         do {    \
117                 if (wl_get_drv_status(cfg, CONNECTED, bcmcfg_to_prmry_ndev(cfg)) ||     \
118                         wl_get_drv_status(cfg, CONNECTING, bcmcfg_to_prmry_ndev(cfg))) {        \
119                         OSL_SLEEP(DEFAULT_SLEEP_TIME_VSDB);                     \
120                 }       \
121         } while (0)
122 #else /* VSDB */
123 /* if not VSDB, do nothing */
124 #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg)
125 #endif /* VSDB */
126
127 #ifdef WL_CFG80211_SYNC_GON
128 #define WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg) \
129         (wl_get_drv_status_all(cfg, SENDING_ACT_FRM) || \
130                 wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN))
131 #else
132 #define WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg) wl_get_drv_status_all(cfg, SENDING_ACT_FRM)
133 #endif /* WL_CFG80211_SYNC_GON */
134 #define WL_IS_P2P_DEV_EVENT(e) ((e->emsg.ifidx == 0) && \
135                 (e->emsg.bsscfgidx == P2PAPI_BSSCFG_DEVICE))
136
137 #define COEX_DHCP
138
139 #define WLAN_EID_SSID   0
140 #define CH_MIN_5G_CHANNEL 34
141 #define CH_MIN_2G_CHANNEL 1
142
143
144 enum rmc_event_type {
145         RMC_EVENT_NONE,
146         RMC_EVENT_LEADER_CHECK_FAIL
147 };
148
149 /* This is to override regulatory domains defined in cfg80211 module (reg.c)
150  * By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN
151  * and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165).
152  * With respect to these flags, wpa_supplicant doesn't start p2p operations on 5GHz channels.
153  * All the chnages in world regulatory domain are to be done here.
154  */
155 static const struct ieee80211_regdomain brcm_regdom = {
156         .n_reg_rules = 4,
157         .alpha2 =  "99",
158         .reg_rules = {
159                 /* IEEE 802.11b/g, channels 1..11 */
160                 REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
161                 /* If any */
162                 /* IEEE 802.11 channel 14 - Only JP enables
163                  * this and for 802.11b only
164                  */
165                 REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
166                 /* IEEE 802.11a, channel 36..64 */
167                 REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
168                 /* IEEE 802.11a, channel 100..165 */
169                 REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
170 };
171
172 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
173         (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
174 /*
175  * Possible interface combinations supported by driver
176  *
177  * ADHOC Mode     - #ADHOC <= 1 on channels = 1
178  * SoftAP Mode    - #AP <= 1 on channels = 1
179  * STA + P2P Mode - #STA <= 2, #{P2P-GO, P2P-client} <= 1, #P2P-device <= 1
180  *                  on channels = 2
181  */
182 static const struct ieee80211_iface_limit common_if_limits[] = {
183         {
184         .max = 1,
185         .types = BIT(NL80211_IFTYPE_AP),
186         },
187         {
188         /*
189          * During P2P-GO removal, P2P-GO is first changed to STA and later only
190          * removed. So setting maximum possible number of STA interfaces according
191          * to kernel version.
192          *
193          * less than linux-3.8 - max:3 (wlan0 + p2p0 + group removal of p2p-p2p0-x)
194          * linux-3.8 and above - max:2 (wlan0 + group removal of p2p-wlan0-x)
195          */
196 #ifdef WL_ENABLE_P2P_IF
197         .max = 3,
198 #else
199         .max = 2,
200 #endif /* WL_ENABLE_P2P_IF */
201         .types = BIT(NL80211_IFTYPE_STATION),
202         },
203         {
204         .max = 2,
205         .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
206         },
207 #if defined(WL_CFG80211_P2P_DEV_IF)
208         {
209         .max = 1,
210         .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
211         },
212 #endif /* WL_CFG80211_P2P_DEV_IF */
213         {
214         .max = 1,
215         .types = BIT(NL80211_IFTYPE_ADHOC),
216         },
217 };
218 #ifdef BCM4330_CHIP
219 #define NUM_DIFF_CHANNELS 1
220 #else
221 #define NUM_DIFF_CHANNELS 2
222 #endif
223 static const struct ieee80211_iface_combination
224 common_iface_combinations[] = {
225         {
226 #ifndef CONFIG_BCMDHD_DISABLE_MCC
227         .num_different_channels = 2,
228 #else
229         .num_different_channels = 1,
230 #endif
231         .max_interfaces = 4,
232         .limits = common_if_limits,
233         .n_limits = ARRAY_SIZE(common_if_limits),
234         },
235 };
236 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
237
238 /* Data Element Definitions */
239 #define WPS_ID_CONFIG_METHODS     0x1008
240 #define WPS_ID_REQ_TYPE           0x103A
241 #define WPS_ID_DEVICE_NAME        0x1011
242 #define WPS_ID_VERSION            0x104A
243 #define WPS_ID_DEVICE_PWD_ID      0x1012
244 #define WPS_ID_REQ_DEV_TYPE       0x106A
245 #define WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS 0x1053
246 #define WPS_ID_PRIM_DEV_TYPE      0x1054
247
248 /* Device Password ID */
249 #define DEV_PW_DEFAULT 0x0000
250 #define DEV_PW_USER_SPECIFIED 0x0001,
251 #define DEV_PW_MACHINE_SPECIFIED 0x0002
252 #define DEV_PW_REKEY 0x0003
253 #define DEV_PW_PUSHBUTTON 0x0004
254 #define DEV_PW_REGISTRAR_SPECIFIED 0x0005
255
256 /* Config Methods */
257 #define WPS_CONFIG_USBA 0x0001
258 #define WPS_CONFIG_ETHERNET 0x0002
259 #define WPS_CONFIG_LABEL 0x0004
260 #define WPS_CONFIG_DISPLAY 0x0008
261 #define WPS_CONFIG_EXT_NFC_TOKEN 0x0010
262 #define WPS_CONFIG_INT_NFC_TOKEN 0x0020
263 #define WPS_CONFIG_NFC_INTERFACE 0x0040
264 #define WPS_CONFIG_PUSHBUTTON 0x0080
265 #define WPS_CONFIG_KEYPAD 0x0100
266 #define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280
267 #define WPS_CONFIG_PHY_PUSHBUTTON 0x0480
268 #define WPS_CONFIG_VIRT_DISPLAY 0x2008
269 #define WPS_CONFIG_PHY_DISPLAY 0x4008
270
271
272 #ifdef MFP
273 #define WL_AKM_SUITE_MFP_1X  0x000FAC05
274 #define WL_AKM_SUITE_MFP_PSK 0x000FAC06
275 #define WL_MFP_CAPABLE          0x1
276 #define WL_MFP_REQUIRED         0x2
277 #endif /* MFP */
278
279 #ifndef IBSS_COALESCE_ALLOWED
280 #define IBSS_COALESCE_ALLOWED 0
281 #endif
282
283 #ifndef IBSS_INITIAL_SCAN_ALLOWED
284 #define IBSS_INITIAL_SCAN_ALLOWED 0
285 #endif
286
287 #define CUSTOM_RETRY_MASK 0xff000000 /* Mask for retry counter of custom dwell time */
288 #define LONG_LISTEN_TIME 2000
289 /*
290  * cfg80211_ops api/callback list
291  */
292 static s32 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
293         const struct ether_addr *sa, const struct ether_addr *bssid,
294         u8 **pheader, u32 *body_len, u8 *pbody);
295 static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
296         struct cfg80211_scan_request *request,
297         struct cfg80211_ssid *this_ssid);
298 #if defined(WL_CFG80211_P2P_DEV_IF)
299 static s32
300 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request);
301 #else
302 static s32
303 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
304         struct cfg80211_scan_request *request);
305 #endif /* WL_CFG80211_P2P_DEV_IF */
306 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
307 #ifdef WLAIBSS_MCHAN
308 static bcm_struct_cfgdev* bcm_cfg80211_add_ibss_if(struct wiphy *wiphy, char *name);
309 static s32 bcm_cfg80211_del_ibss_if(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev);
310 #endif /* WLAIBSS_MCHAN */
311 static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
312         struct cfg80211_ibss_params *params);
313 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy,
314         struct net_device *dev);
315 static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
316         struct net_device *dev, u8 *mac,
317         struct station_info *sinfo);
318 static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
319         struct net_device *dev, bool enabled,
320         s32 timeout);
321 static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
322         struct cfg80211_connect_params *sme);
323 static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
324         u16 reason_code);
325 #if defined(WL_CFG80211_P2P_DEV_IF)
326 static s32
327 wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
328         enum nl80211_tx_power_setting type, s32 mbm);
329 #else
330 static s32
331 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
332         enum nl80211_tx_power_setting type, s32 dbm);
333 #endif /* WL_CFG80211_P2P_DEV_IF */
334 #if defined(WL_CFG80211_P2P_DEV_IF)
335 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
336         struct wireless_dev *wdev, s32 *dbm);
337 #else
338 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
339 #endif /* WL_CFG80211_P2P_DEV_IF */
340 static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
341         struct net_device *dev,
342         u8 key_idx, bool unicast, bool multicast);
343 static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
344         u8 key_idx, bool pairwise, const u8 *mac_addr,
345         struct key_params *params);
346 static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
347         u8 key_idx, bool pairwise, const u8 *mac_addr);
348 static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
349         u8 key_idx, bool pairwise, const u8 *mac_addr,
350         void *cookie, void (*callback) (void *cookie,
351         struct key_params *params));
352 static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
353         struct net_device *dev, u8 key_idx);
354 static s32 wl_cfg80211_resume(struct wiphy *wiphy);
355 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
356         2, 0))
357 static s32 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
358         bcm_struct_cfgdev *cfgdev, u64 cookie);
359 static s32 wl_cfg80211_del_station(struct wiphy *wiphy,
360         struct net_device *ndev, u8* mac_addr);
361 static s32 wl_cfg80211_change_station(struct wiphy *wiphy,
362         struct net_device *dev, u8 *mac, struct station_parameters *params);
363 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
364 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
365 static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
366 #else
367 static s32 wl_cfg80211_suspend(struct wiphy *wiphy);
368 #endif
369 static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
370         struct cfg80211_pmksa *pmksa);
371 static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
372         struct cfg80211_pmksa *pmksa);
373 static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
374         struct net_device *dev);
375 #ifdef  P2PONEINT
376 void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg);
377 #else
378 static void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg);
379 #endif
380 static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
381         struct net_device *ndev, bool aborted, bool fw_abort);
382 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
383 #if defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)
384 static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
385         u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
386         u32 peer_capability, const u8 *data, size_t len);
387 #else
388 static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
389         u8 *peer, u8 action_code, u8 dialog_token, u16 status_code, const u8 *data,
390         size_t len);
391 #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
392 static s32 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
393         u8 *peer, enum nl80211_tdls_operation oper);
394 #endif 
395 #ifdef WL_SCHED_SCAN
396 static int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev);
397 #endif
398 #if defined(DUAL_STA) || defined(DUAL_STA_STATIC_IF)
399 bcm_struct_cfgdev*
400 wl_cfg80211_create_iface(struct wiphy *wiphy, enum nl80211_iftype
401                  iface_type, u8 *mac_addr, const char *name);
402 s32
403 wl_cfg80211_del_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev);
404 #endif /* defined(DUAL_STA) || defined(DUAL_STA_STATIC_IF) */
405 chanspec_t wl_chspec_driver_to_host(chanspec_t chanspec);
406
407 /*
408  * event & event Q handlers for cfg80211 interfaces
409  */
410 static s32 wl_create_event_handler(struct bcm_cfg80211 *cfg);
411 static void wl_destroy_event_handler(struct bcm_cfg80211 *cfg);
412 static s32 wl_event_handler(void *data);
413 static void wl_init_eq(struct bcm_cfg80211 *cfg);
414 static void wl_flush_eq(struct bcm_cfg80211 *cfg);
415 static unsigned long wl_lock_eq(struct bcm_cfg80211 *cfg);
416 static void wl_unlock_eq(struct bcm_cfg80211 *cfg, unsigned long flags);
417 static void wl_init_eq_lock(struct bcm_cfg80211 *cfg);
418 static void wl_init_event_handler(struct bcm_cfg80211 *cfg);
419 static struct wl_event_q *wl_deq_event(struct bcm_cfg80211 *cfg);
420 static s32 wl_enq_event(struct bcm_cfg80211 *cfg, struct net_device *ndev, u32 type,
421         const wl_event_msg_t *msg, void *data);
422 static void wl_put_event(struct wl_event_q *e);
423 static void wl_wakeup_event(struct bcm_cfg80211 *cfg);
424 static s32 wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
425         const wl_event_msg_t *e, void *data);
426 static s32 wl_notify_connect_status(struct bcm_cfg80211 *cfg,
427         bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
428 static s32 wl_notify_roaming_status(struct bcm_cfg80211 *cfg,
429         bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
430 static s32 wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
431         const wl_event_msg_t *e, void *data);
432 static s32 wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
433         const wl_event_msg_t *e, void *data, bool completed);
434 static s32 wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
435         const wl_event_msg_t *e, void *data);
436 static s32 wl_notify_mic_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
437         const wl_event_msg_t *e, void *data);
438 #ifdef BT_WIFI_HANDOVER
439 static s32 wl_notify_bt_wifi_handover_req(struct bcm_cfg80211 *cfg,
440         bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
441 #endif /* BT_WIFI_HANDOVER */
442 #ifdef WL_SCHED_SCAN
443 static s32
444 wl_notify_sched_scan_results(struct bcm_cfg80211 *cfg, struct net_device *ndev,
445         const wl_event_msg_t *e, void *data);
446 #endif /* WL_SCHED_SCAN */
447 #ifdef PNO_SUPPORT
448 static s32 wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
449         const wl_event_msg_t *e, void *data);
450 #endif /* PNO_SUPPORT */
451 static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_net_info,
452         enum wl_status state, bool set);
453
454 #ifdef WLTDLS
455 static s32 wl_tdls_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
456         const wl_event_msg_t *e, void *data);
457 #endif /* WLTDLS */
458 /*
459  * register/deregister parent device
460  */
461 static void wl_cfg80211_clear_parent_dev(void);
462
463 /*
464  * ioctl utilites
465  */
466
467 /*
468  * cfg80211 set_wiphy_params utilities
469  */
470 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold);
471 static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold);
472 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
473
474 /*
475  * cfg profile utilities
476  */
477 static s32 wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
478         const wl_event_msg_t *e, void *data, s32 item);
479 static void *wl_read_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 item);
480 static void wl_init_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev);
481
482 /*
483  * cfg80211 connect utilites
484  */
485 static s32 wl_set_wpa_version(struct net_device *dev,
486         struct cfg80211_connect_params *sme);
487 static s32 wl_set_auth_type(struct net_device *dev,
488         struct cfg80211_connect_params *sme);
489 static s32 wl_set_set_cipher(struct net_device *dev,
490         struct cfg80211_connect_params *sme);
491 static s32 wl_set_key_mgmt(struct net_device *dev,
492         struct cfg80211_connect_params *sme);
493 static s32 wl_set_set_sharedkey(struct net_device *dev,
494         struct cfg80211_connect_params *sme);
495 static s32 wl_get_assoc_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev);
496 static void wl_ch_to_chanspec(int ch,
497         struct wl_join_params *join_params, size_t *join_params_size);
498
499 /*
500  * information element utilities
501  */
502 static void wl_rst_ie(struct bcm_cfg80211 *cfg);
503 static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v);
504 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size, bool roam);
505 static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size);
506 static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size);
507 static u32 wl_get_ielen(struct bcm_cfg80211 *cfg);
508 #ifdef MFP
509 static int wl_cfg80211_get_rsn_capa(bcm_tlv_t *wpa2ie, u8* capa);
510 #endif
511
512 #ifdef WL11U
513 bcm_tlv_t *
514 wl_cfg80211_find_interworking_ie(u8 *parse, u32 len);
515 static s32
516 wl_cfg80211_add_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx, s32 pktflag,
517             uint8 ie_id, uint8 *data, uint8 data_len);
518 #endif /* WL11U */
519
520 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev, void *data);
521 static void wl_free_wdev(struct bcm_cfg80211 *cfg);
522 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
523 static int
524 wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
525 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
526
527 static s32 wl_inform_bss(struct bcm_cfg80211 *cfg);
528 static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi, bool roam);
529 static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool roam);
530 #ifdef  P2PONEINT
531 chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy);
532 #else
533 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy);
534 #endif
535 s32 wl_cfg80211_channel_to_freq(u32 channel);
536
537
538 static void wl_cfg80211_work_handler(struct work_struct *work);
539 static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
540         u8 key_idx, const u8 *mac_addr,
541         struct key_params *params);
542 /*
543  * key indianess swap utilities
544  */
545 static void swap_key_from_BE(struct wl_wsec_key *key);
546 static void swap_key_to_BE(struct wl_wsec_key *key);
547
548 /*
549  * bcm_cfg80211 memory init/deinit utilities
550  */
551 static s32 wl_init_priv_mem(struct bcm_cfg80211 *cfg);
552 static void wl_deinit_priv_mem(struct bcm_cfg80211 *cfg);
553
554 static void wl_delay(u32 ms);
555
556 /*
557  * ibss mode utilities
558  */
559 static bool wl_is_ibssmode(struct bcm_cfg80211 *cfg, struct net_device *ndev);
560 static __used bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg);
561
562 /*
563  * link up/down , default configuration utilities
564  */
565 static s32 __wl_cfg80211_up(struct bcm_cfg80211 *cfg);
566 static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg);
567 static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e);
568 static bool wl_is_linkup(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e,
569         struct net_device *ndev);
570 static bool wl_is_nonetwork(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e);
571 static void wl_link_up(struct bcm_cfg80211 *cfg);
572 static void wl_link_down(struct bcm_cfg80211 *cfg);
573 static s32 wl_config_ifmode(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 iftype);
574 static void wl_init_conf(struct wl_conf *conf);
575 static s32 wl_cfg80211_handle_ifdel(struct bcm_cfg80211 *cfg, wl_if_event_info *if_event_info,
576         struct net_device* ndev);
577
578 int wl_cfg80211_get_ioctl_version(void);
579
580 /*
581  * find most significant bit set
582  */
583 static __used u32 wl_find_msb(u16 bit16);
584
585 /*
586  * rfkill support
587  */
588 static int wl_setup_rfkill(struct bcm_cfg80211 *cfg, bool setup);
589 static int wl_rfkill_set(void *data, bool blocked);
590 #ifdef DEBUGFS_CFG80211
591 static s32 wl_setup_debugfs(struct bcm_cfg80211 *cfg);
592 static s32 wl_free_debugfs(struct bcm_cfg80211 *cfg);
593 #endif
594
595 static wl_scan_params_t *wl_cfg80211_scan_alloc_params(int channel,
596         int nprobes, int *out_params_size);
597 static bool check_dev_role_integrity(struct bcm_cfg80211 *cfg, u32 dev_role);
598
599 #ifdef WL_CFG80211_ACL
600 /* ACL */
601 static int wl_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *cfgdev,
602         const struct cfg80211_acl_data *acl);
603 #endif /* WL_CFG80211_ACL */
604
605 /*
606  * Some external functions, TODO: move them to dhd_linux.h
607  */
608 int dhd_add_monitor(char *name, struct net_device **new_ndev);
609 int dhd_del_monitor(struct net_device *ndev);
610 int dhd_monitor_init(void *dhd_pub);
611 int dhd_monitor_uninit(void);
612 int dhd_start_xmit(struct sk_buff *skb, struct net_device *net);
613
614
615 static int wl_cfg80211_delayed_roam(struct bcm_cfg80211 *cfg, struct net_device *ndev,
616         const struct ether_addr *bssid);
617
618 static int bw2cap[] = { 0, 0, WLC_BW_CAP_20MHZ, WLC_BW_CAP_40MHZ, WLC_BW_CAP_80MHZ,
619         WLC_BW_CAP_160MHZ, WLC_BW_CAP_160MHZ };
620
621 #define RETURN_EIO_IF_NOT_UP(wlpriv)                                            \
622 do {                                                                    \
623         struct net_device *checkSysUpNDev = bcmcfg_to_prmry_ndev(wlpriv);               \
624         if (unlikely(!wl_get_drv_status(wlpriv, READY, checkSysUpNDev))) {      \
625                 WL_INFORM(("device is not ready\n"));                   \
626                 return -EIO;                                            \
627         }                                                               \
628 } while (0)
629
630 #ifdef RSSI_OFFSET
631 static s32 wl_rssi_offset(s32 rssi)
632 {
633         rssi += RSSI_OFFSET;
634         if (rssi > 0)
635                 rssi = 0;
636         return rssi;
637 }
638 #else
639 #define wl_rssi_offset(x)       x
640 #endif
641
642 #define IS_WPA_AKM(akm) ((akm) == RSN_AKM_NONE ||                       \
643                                  (akm) == RSN_AKM_UNSPECIFIED ||        \
644                                  (akm) == RSN_AKM_PSK)
645
646
647 extern int dhd_wait_pend8021x(struct net_device *dev);
648 #ifdef PROP_TXSTATUS_VSDB
649 extern int disable_proptx;
650 #endif /* PROP_TXSTATUS_VSDB */
651
652 extern int passive_channel_skip;
653
654 static s32
655 wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
656 const wl_event_msg_t *e, void *data);
657 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0)) && (LINUX_VERSION_CODE <= (3, 7, \
658         0)))
659 struct chan_info {
660         int freq;
661         int chan_type;
662 };
663 #endif
664
665
666 #if (WL_DBG_LEVEL > 0)
667 #define WL_DBG_ESTR_MAX 50
668 static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = {
669         "SET_SSID", "JOIN", "START", "AUTH", "AUTH_IND",
670         "DEAUTH", "DEAUTH_IND", "ASSOC", "ASSOC_IND", "REASSOC",
671         "REASSOC_IND", "DISASSOC", "DISASSOC_IND", "QUIET_START", "QUIET_END",
672         "BEACON_RX", "LINK", "MIC_ERROR", "NDIS_LINK", "ROAM",
673         "TXFAIL", "PMKID_CACHE", "RETROGRADE_TSF", "PRUNE", "AUTOAUTH",
674         "EAPOL_MSG", "SCAN_COMPLETE", "ADDTS_IND", "DELTS_IND", "BCNSENT_IND",
675         "BCNRX_MSG", "BCNLOST_MSG", "ROAM_PREP", "PFN_NET_FOUND",
676         "PFN_NET_LOST",
677         "RESET_COMPLETE", "JOIN_START", "ROAM_START", "ASSOC_START",
678         "IBSS_ASSOC",
679         "RADIO", "PSM_WATCHDOG", "WLC_E_CCX_ASSOC_START", "WLC_E_CCX_ASSOC_ABORT",
680         "PROBREQ_MSG",
681         "SCAN_CONFIRM_IND", "PSK_SUP", "COUNTRY_CODE_CHANGED",
682         "EXCEEDED_MEDIUM_TIME", "ICV_ERROR",
683         "UNICAST_DECODE_ERROR", "MULTICAST_DECODE_ERROR", "TRACE",
684         "WLC_E_BTA_HCI_EVENT", "IF", "WLC_E_P2P_DISC_LISTEN_COMPLETE",
685         "RSSI", "PFN_SCAN_COMPLETE", "WLC_E_EXTLOG_MSG",
686         "ACTION_FRAME", "ACTION_FRAME_COMPLETE", "WLC_E_PRE_ASSOC_IND",
687         "WLC_E_PRE_REASSOC_IND", "WLC_E_CHANNEL_ADOPTED", "WLC_E_AP_STARTED",
688         "WLC_E_DFS_AP_STOP", "WLC_E_DFS_AP_RESUME", "WLC_E_WAI_STA_EVENT",
689         "WLC_E_WAI_MSG", "WLC_E_ESCAN_RESULT", "WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE",
690         "WLC_E_PROBRESP_MSG", "WLC_E_P2P_PROBREQ_MSG", "WLC_E_DCS_REQUEST", "WLC_E_FIFO_CREDIT_MAP",
691         "WLC_E_ACTION_FRAME_RX", "WLC_E_WAKE_EVENT", "WLC_E_RM_COMPLETE"
692 };
693 #endif                          /* WL_DBG_LEVEL */
694
695 #define CHAN2G(_channel, _freq, _flags) {                       \
696         .band                   = IEEE80211_BAND_2GHZ,          \
697         .center_freq            = (_freq),                      \
698         .hw_value               = (_channel),                   \
699         .flags                  = (_flags),                     \
700         .max_antenna_gain       = 0,                            \
701         .max_power              = 30,                           \
702 }
703
704 #define CHAN5G(_channel, _flags) {                              \
705         .band                   = IEEE80211_BAND_5GHZ,          \
706         .center_freq            = 5000 + (5 * (_channel)),      \
707         .hw_value               = (_channel),                   \
708         .flags                  = (_flags),                     \
709         .max_antenna_gain       = 0,                            \
710         .max_power              = 30,                           \
711 }
712
713 #define RATE_TO_BASE100KBPS(rate)   (((rate) * 10) / 2)
714 #define RATETAB_ENT(_rateid, _flags) \
715         {                                                               \
716                 .bitrate        = RATE_TO_BASE100KBPS(_rateid),     \
717                 .hw_value       = (_rateid),                        \
718                 .flags    = (_flags),                        \
719         }
720
721 static struct ieee80211_rate __wl_rates[] = {
722         RATETAB_ENT(DOT11_RATE_1M, 0),
723         RATETAB_ENT(DOT11_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
724         RATETAB_ENT(DOT11_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
725         RATETAB_ENT(DOT11_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
726         RATETAB_ENT(DOT11_RATE_6M, 0),
727         RATETAB_ENT(DOT11_RATE_9M, 0),
728         RATETAB_ENT(DOT11_RATE_12M, 0),
729         RATETAB_ENT(DOT11_RATE_18M, 0),
730         RATETAB_ENT(DOT11_RATE_24M, 0),
731         RATETAB_ENT(DOT11_RATE_36M, 0),
732         RATETAB_ENT(DOT11_RATE_48M, 0),
733         RATETAB_ENT(DOT11_RATE_54M, 0)
734 };
735
736 #define wl_a_rates              (__wl_rates + 4)
737 #define wl_a_rates_size 8
738 #define wl_g_rates              (__wl_rates + 0)
739 #define wl_g_rates_size 12
740
741 static struct ieee80211_channel __wl_2ghz_channels[] = {
742         CHAN2G(1, 2412, 0),
743         CHAN2G(2, 2417, 0),
744         CHAN2G(3, 2422, 0),
745         CHAN2G(4, 2427, 0),
746         CHAN2G(5, 2432, 0),
747         CHAN2G(6, 2437, 0),
748         CHAN2G(7, 2442, 0),
749         CHAN2G(8, 2447, 0),
750         CHAN2G(9, 2452, 0),
751         CHAN2G(10, 2457, 0),
752         CHAN2G(11, 2462, 0),
753         CHAN2G(12, 2467, 0),
754         CHAN2G(13, 2472, 0),
755         CHAN2G(14, 2484, 0)
756 };
757
758 static struct ieee80211_channel __wl_5ghz_a_channels[] = {
759         CHAN5G(34, 0), CHAN5G(36, 0),
760         CHAN5G(38, 0), CHAN5G(40, 0),
761         CHAN5G(42, 0), CHAN5G(44, 0),
762         CHAN5G(46, 0), CHAN5G(48, 0),
763         CHAN5G(52, 0), CHAN5G(56, 0),
764         CHAN5G(60, 0), CHAN5G(64, 0),
765         CHAN5G(100, 0), CHAN5G(104, 0),
766         CHAN5G(108, 0), CHAN5G(112, 0),
767         CHAN5G(116, 0), CHAN5G(120, 0),
768         CHAN5G(124, 0), CHAN5G(128, 0),
769         CHAN5G(132, 0), CHAN5G(136, 0),
770         CHAN5G(140, 0), CHAN5G(144, 0),
771         CHAN5G(149, 0), CHAN5G(153, 0),
772         CHAN5G(157, 0), CHAN5G(161, 0),
773         CHAN5G(165, 0)
774 };
775
776 static struct ieee80211_supported_band __wl_band_2ghz = {
777         .band = IEEE80211_BAND_2GHZ,
778         .channels = __wl_2ghz_channels,
779         .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
780         .bitrates = wl_g_rates,
781         .n_bitrates = wl_g_rates_size
782 };
783
784 static struct ieee80211_supported_band __wl_band_5ghz_a = {
785         .band = IEEE80211_BAND_5GHZ,
786         .channels = __wl_5ghz_a_channels,
787         .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
788         .bitrates = wl_a_rates,
789         .n_bitrates = wl_a_rates_size
790 };
791
792 static const u32 __wl_cipher_suites[] = {
793         WLAN_CIPHER_SUITE_WEP40,
794         WLAN_CIPHER_SUITE_WEP104,
795         WLAN_CIPHER_SUITE_TKIP,
796         WLAN_CIPHER_SUITE_CCMP,
797         WLAN_CIPHER_SUITE_AES_CMAC,
798 };
799
800 #ifdef WL_SUPPORT_ACS
801 /*
802  * The firmware code required for this feature to work is currently under
803  * BCMINTERNAL flag. In future if this is to enabled we need to bring the
804  * required firmware code out of the BCMINTERNAL flag.
805  */
806 struct wl_dump_survey {
807         u32 obss;
808         u32 ibss;
809         u32 no_ctg;
810         u32 no_pckt;
811         u32 tx;
812         u32 idle;
813 };
814 #endif /* WL_SUPPORT_ACS */
815
816
817 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
818 static int maxrxpktglom = 0;
819 #endif
820
821 /* IOCtl version read from targeted driver */
822 static int ioctl_version;
823 #ifdef DEBUGFS_CFG80211
824 #define S_SUBLOGLEVEL 20
825 static const struct {
826         u32 log_level;
827         char *sublogname;
828 } sublogname_map[] = {
829         {WL_DBG_ERR, "ERR"},
830         {WL_DBG_INFO, "INFO"},
831         {WL_DBG_DBG, "DBG"},
832         {WL_DBG_SCAN, "SCAN"},
833         {WL_DBG_TRACE, "TRACE"},
834         {WL_DBG_P2P_ACTION, "P2PACTION"}
835 };
836 #endif
837
838
839 static void wl_add_remove_pm_enable_work(struct bcm_cfg80211 *cfg, bool add_remove,
840         enum wl_handler_del_type type)
841 {
842         if (cfg == NULL)
843                 return;
844
845         if (cfg->pm_enable_work_on) {
846                 if (add_remove) {
847                         schedule_delayed_work(&cfg->pm_enable_work,
848                                 msecs_to_jiffies(WL_PM_ENABLE_TIMEOUT));
849                 } else {
850                         cancel_delayed_work_sync(&cfg->pm_enable_work);
851                         switch (type) {
852                                 case WL_HANDLER_MAINTAIN:
853                                         schedule_delayed_work(&cfg->pm_enable_work,
854                                                 msecs_to_jiffies(WL_PM_ENABLE_TIMEOUT));
855                                         break;
856                                 case WL_HANDLER_PEND:
857                                         schedule_delayed_work(&cfg->pm_enable_work,
858                                                 msecs_to_jiffies(WL_PM_ENABLE_TIMEOUT*2));
859                                         break;
860                                 case WL_HANDLER_DEL:
861                                 default:
862                                         cfg->pm_enable_work_on = false;
863                                         break;
864                         }
865                 }
866         }
867 }
868
869 /* Return a new chanspec given a legacy chanspec
870  * Returns INVCHANSPEC on error
871  */
872 static chanspec_t
873 wl_chspec_from_legacy(chanspec_t legacy_chspec)
874 {
875         chanspec_t chspec;
876
877         /* get the channel number */
878         chspec = LCHSPEC_CHANNEL(legacy_chspec);
879
880         /* convert the band */
881         if (LCHSPEC_IS2G(legacy_chspec)) {
882                 chspec |= WL_CHANSPEC_BAND_2G;
883         } else {
884                 chspec |= WL_CHANSPEC_BAND_5G;
885         }
886
887         /* convert the bw and sideband */
888         if (LCHSPEC_IS20(legacy_chspec)) {
889                 chspec |= WL_CHANSPEC_BW_20;
890         } else {
891                 chspec |= WL_CHANSPEC_BW_40;
892                 if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
893                         chspec |= WL_CHANSPEC_CTL_SB_L;
894                 } else {
895                         chspec |= WL_CHANSPEC_CTL_SB_U;
896                 }
897         }
898
899         if (wf_chspec_malformed(chspec)) {
900                 WL_ERR(("wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
901                         chspec));
902                 return INVCHANSPEC;
903         }
904
905         return chspec;
906 }
907
908 /* Return a legacy chanspec given a new chanspec
909  * Returns INVCHANSPEC on error
910  */
911 static chanspec_t
912 wl_chspec_to_legacy(chanspec_t chspec)
913 {
914         chanspec_t lchspec;
915
916         if (wf_chspec_malformed(chspec)) {
917                 WL_ERR(("wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n",
918                         chspec));
919                 return INVCHANSPEC;
920         }
921
922         /* get the channel number */
923         lchspec = CHSPEC_CHANNEL(chspec);
924
925         /* convert the band */
926         if (CHSPEC_IS2G(chspec)) {
927                 lchspec |= WL_LCHANSPEC_BAND_2G;
928         } else {
929                 lchspec |= WL_LCHANSPEC_BAND_5G;
930         }
931
932         /* convert the bw and sideband */
933         if (CHSPEC_IS20(chspec)) {
934                 lchspec |= WL_LCHANSPEC_BW_20;
935                 lchspec |= WL_LCHANSPEC_CTL_SB_NONE;
936         } else if (CHSPEC_IS40(chspec)) {
937                 lchspec |= WL_LCHANSPEC_BW_40;
938                 if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_L) {
939                         lchspec |= WL_LCHANSPEC_CTL_SB_LOWER;
940                 } else {
941                         lchspec |= WL_LCHANSPEC_CTL_SB_UPPER;
942                 }
943         } else {
944                 /* cannot express the bandwidth */
945                 char chanbuf[CHANSPEC_STR_LEN];
946                 WL_ERR((
947                         "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) "
948                         "to pre-11ac format\n",
949                         wf_chspec_ntoa(chspec, chanbuf), chspec));
950                 return INVCHANSPEC;
951         }
952
953         return lchspec;
954 }
955
956 /* given a chanspec value, do the endian and chanspec version conversion to
957  * a chanspec_t value
958  * Returns INVCHANSPEC on error
959  */
960 chanspec_t
961 wl_chspec_host_to_driver(chanspec_t chanspec)
962 {
963         if (ioctl_version == 1) {
964                 chanspec = wl_chspec_to_legacy(chanspec);
965                 if (chanspec == INVCHANSPEC) {
966                         return chanspec;
967                 }
968         }
969         chanspec = htodchanspec(chanspec);
970
971         return chanspec;
972 }
973
974 /* given a channel value, do the endian and chanspec version conversion to
975  * a chanspec_t value
976  * Returns INVCHANSPEC on error
977  */
978 chanspec_t
979 wl_ch_host_to_driver(u16 channel)
980 {
981
982         chanspec_t chanspec;
983
984         chanspec = channel & WL_CHANSPEC_CHAN_MASK;
985
986         if (channel <= CH_MAX_2G_CHANNEL)
987                 chanspec |= WL_CHANSPEC_BAND_2G;
988         else
989                 chanspec |= WL_CHANSPEC_BAND_5G;
990
991         chanspec |= WL_CHANSPEC_BW_20;
992         chanspec |= WL_CHANSPEC_CTL_SB_NONE;
993
994         return wl_chspec_host_to_driver(chanspec);
995 }
996
997 /* given a chanspec value from the driver, do the endian and chanspec version conversion to
998  * a chanspec_t value
999  * Returns INVCHANSPEC on error
1000  */
1001 chanspec_t
1002 wl_chspec_driver_to_host(chanspec_t chanspec)
1003 {
1004         chanspec = dtohchanspec(chanspec);
1005         if (ioctl_version == 1) {
1006                 chanspec = wl_chspec_from_legacy(chanspec);
1007         }
1008
1009         return chanspec;
1010 }
1011
1012 /*
1013  * convert ASCII string to MAC address (colon-delimited format)
1014  * eg: 00:11:22:33:44:55
1015  */
1016 int
1017 wl_cfg80211_ether_atoe(const char *a, struct ether_addr *n)
1018 {
1019         char *c = NULL;
1020         int count = 0;
1021
1022         memset(n, 0, ETHER_ADDR_LEN);
1023         for (;;) {
1024                 n->octet[count++] = (uint8)simple_strtoul(a, &c, 16);
1025                 if (!*c++ || count == ETHER_ADDR_LEN)
1026                         break;
1027                 a = c;
1028         }
1029         return (count == ETHER_ADDR_LEN);
1030 }
1031
1032 /* convert hex string buffer to binary */
1033 int
1034 wl_cfg80211_hex_str_to_bin(unsigned char *data, int dlen, char *str)
1035 {
1036         int count, slen;
1037         int hvalue;
1038         char tmp[3] = {0};
1039         char *ptr = str, *endp = NULL;
1040
1041         if (!data || !str || !dlen) {
1042                 WL_DBG((" passed buffer is empty \n"));
1043                 return 0;
1044         }
1045
1046         slen = strlen(str);
1047         if (dlen * 2 < slen) {
1048                 WL_DBG((" destination buffer too short \n"));
1049                 return 0;
1050         }
1051
1052         if (slen % 2) {
1053                 WL_DBG((" source buffer is of odd length \n"));
1054                 return 0;
1055         }
1056
1057         for (count = 0; count < slen; count += 2) {
1058                 memcpy(tmp, ptr, 2);
1059                 hvalue = simple_strtol(tmp, &endp, 16);
1060                 if (*endp != '\0') {
1061                         WL_DBG((" non hexadecimal character encountered \n"));
1062                         return 0;
1063                 }
1064                 *data++ = (unsigned char)hvalue;
1065                 ptr += 2;
1066         }
1067
1068         return (slen / 2);
1069 }
1070
1071 /* There isn't a lot of sense in it, but you can transmit anything you like */
1072 static const struct ieee80211_txrx_stypes
1073 wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
1074         [NL80211_IFTYPE_ADHOC] = {
1075                 .tx = 0xffff,
1076                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
1077         },
1078         [NL80211_IFTYPE_STATION] = {
1079                 .tx = 0xffff,
1080                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1081                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
1082         },
1083         [NL80211_IFTYPE_AP] = {
1084                 .tx = 0xffff,
1085                 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
1086                 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
1087                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
1088                 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
1089                 BIT(IEEE80211_STYPE_AUTH >> 4) |
1090                 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
1091                 BIT(IEEE80211_STYPE_ACTION >> 4)
1092         },
1093         [NL80211_IFTYPE_AP_VLAN] = {
1094                 /* copy AP */
1095                 .tx = 0xffff,
1096                 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
1097                 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
1098                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
1099                 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
1100                 BIT(IEEE80211_STYPE_AUTH >> 4) |
1101                 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
1102                 BIT(IEEE80211_STYPE_ACTION >> 4)
1103         },
1104         [NL80211_IFTYPE_P2P_CLIENT] = {
1105                 .tx = 0xffff,
1106                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1107                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
1108         },
1109         [NL80211_IFTYPE_P2P_GO] = {
1110                 .tx = 0xffff,
1111                 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
1112                 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
1113                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
1114                 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
1115                 BIT(IEEE80211_STYPE_AUTH >> 4) |
1116                 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
1117                 BIT(IEEE80211_STYPE_ACTION >> 4)
1118         },
1119 #if defined(WL_CFG80211_P2P_DEV_IF)
1120         [NL80211_IFTYPE_P2P_DEVICE] = {
1121                 .tx = 0xffff,
1122                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1123                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
1124         },
1125 #endif /* WL_CFG80211_P2P_DEV_IF */
1126 };
1127
1128 static void swap_key_from_BE(struct wl_wsec_key *key)
1129 {
1130         key->index = htod32(key->index);
1131         key->len = htod32(key->len);
1132         key->algo = htod32(key->algo);
1133         key->flags = htod32(key->flags);
1134         key->rxiv.hi = htod32(key->rxiv.hi);
1135         key->rxiv.lo = htod16(key->rxiv.lo);
1136         key->iv_initialized = htod32(key->iv_initialized);
1137 }
1138
1139 static void swap_key_to_BE(struct wl_wsec_key *key)
1140 {
1141         key->index = dtoh32(key->index);
1142         key->len = dtoh32(key->len);
1143         key->algo = dtoh32(key->algo);
1144         key->flags = dtoh32(key->flags);
1145         key->rxiv.hi = dtoh32(key->rxiv.hi);
1146         key->rxiv.lo = dtoh16(key->rxiv.lo);
1147         key->iv_initialized = dtoh32(key->iv_initialized);
1148 }
1149
1150 /* Dump the contents of the encoded wps ie buffer and get pbc value */
1151 static void
1152 wl_validate_wps_ie(char *wps_ie, s32 wps_ie_len, bool *pbc)
1153 {
1154         #define WPS_IE_FIXED_LEN 6
1155         u16 len;
1156         u8 *subel = NULL;
1157         u16 subelt_id;
1158         u16 subelt_len;
1159         u16 val;
1160         u8 *valptr = (uint8*) &val;
1161         if (wps_ie == NULL || wps_ie_len < WPS_IE_FIXED_LEN) {
1162                 WL_ERR(("invalid argument : NULL\n"));
1163                 return;
1164         }
1165         len = (u16)wps_ie[TLV_LEN_OFF];
1166
1167         if (len > wps_ie_len) {
1168                 WL_ERR(("invalid length len %d, wps ie len %d\n", len, wps_ie_len));
1169                 return;
1170         }
1171         WL_DBG(("wps_ie len=%d\n", len));
1172         len -= 4;       /* for the WPS IE's OUI, oui_type fields */
1173         subel = wps_ie + WPS_IE_FIXED_LEN;
1174         while (len >= 4) {              /* must have attr id, attr len fields */
1175                 valptr[0] = *subel++;
1176                 valptr[1] = *subel++;
1177                 subelt_id = HTON16(val);
1178
1179                 valptr[0] = *subel++;
1180                 valptr[1] = *subel++;
1181                 subelt_len = HTON16(val);
1182
1183                 len -= 4;                       /* for the attr id, attr len fields */
1184                 len -= subelt_len;      /* for the remaining fields in this attribute */
1185                 WL_DBG((" subel=%p, subelt_id=0x%x subelt_len=%u\n",
1186                         subel, subelt_id, subelt_len));
1187
1188                 if (subelt_id == WPS_ID_VERSION) {
1189                         WL_DBG(("  attr WPS_ID_VERSION: %u\n", *subel));
1190                 } else if (subelt_id == WPS_ID_REQ_TYPE) {
1191                         WL_DBG(("  attr WPS_ID_REQ_TYPE: %u\n", *subel));
1192                 } else if (subelt_id == WPS_ID_CONFIG_METHODS) {
1193                         valptr[0] = *subel;
1194                         valptr[1] = *(subel + 1);
1195                         WL_DBG(("  attr WPS_ID_CONFIG_METHODS: %x\n", HTON16(val)));
1196                 } else if (subelt_id == WPS_ID_DEVICE_NAME) {
1197                         char devname[100];
1198                         size_t namelen = MIN(subelt_len, sizeof(devname)-1);
1199                         memcpy(devname, subel, namelen);
1200                         devname[namelen] = '\0';
1201                         WL_DBG(("  attr WPS_ID_DEVICE_NAME: %s (len %u)\n",
1202                                 devname, subelt_len));
1203                 } else if (subelt_id == WPS_ID_DEVICE_PWD_ID) {
1204                         valptr[0] = *subel;
1205                         valptr[1] = *(subel + 1);
1206                         WL_DBG(("  attr WPS_ID_DEVICE_PWD_ID: %u\n", HTON16(val)));
1207                         *pbc = (HTON16(val) == DEV_PW_PUSHBUTTON) ? true : false;
1208                 } else if (subelt_id == WPS_ID_PRIM_DEV_TYPE) {
1209                         valptr[0] = *subel;
1210                         valptr[1] = *(subel + 1);
1211                         WL_DBG(("  attr WPS_ID_PRIM_DEV_TYPE: cat=%u \n", HTON16(val)));
1212                         valptr[0] = *(subel + 6);
1213                         valptr[1] = *(subel + 7);
1214                         WL_DBG(("  attr WPS_ID_PRIM_DEV_TYPE: subcat=%u\n", HTON16(val)));
1215                 } else if (subelt_id == WPS_ID_REQ_DEV_TYPE) {
1216                         valptr[0] = *subel;
1217                         valptr[1] = *(subel + 1);
1218                         WL_DBG(("  attr WPS_ID_REQ_DEV_TYPE: cat=%u\n", HTON16(val)));
1219                         valptr[0] = *(subel + 6);
1220                         valptr[1] = *(subel + 7);
1221                         WL_DBG(("  attr WPS_ID_REQ_DEV_TYPE: subcat=%u\n", HTON16(val)));
1222                 } else if (subelt_id == WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS) {
1223                         valptr[0] = *subel;
1224                         valptr[1] = *(subel + 1);
1225                         WL_DBG(("  attr WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS"
1226                                 ": cat=%u\n", HTON16(val)));
1227                 } else {
1228                         WL_DBG(("  unknown attr 0x%x\n", subelt_id));
1229                 }
1230
1231                 subel += subelt_len;
1232         }
1233 }
1234
1235 s32 wl_set_tx_power(struct net_device *dev,
1236         enum nl80211_tx_power_setting type, s32 dbm)
1237 {
1238         s32 err = 0;
1239         s32 disable = 0;
1240         s32 txpwrqdbm;
1241         struct bcm_cfg80211 *cfg = g_bcm_cfg;
1242
1243         /* Make sure radio is off or on as far as software is concerned */
1244         disable = WL_RADIO_SW_DISABLE << 16;
1245         disable = htod32(disable);
1246         err = wldev_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable), true);
1247         if (unlikely(err)) {
1248                 WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
1249                 return err;
1250         }
1251
1252         if (dbm > 0xffff)
1253                 dbm = 0xffff;
1254         txpwrqdbm = dbm * 4;
1255         err = wldev_iovar_setbuf_bsscfg(dev, "qtxpower", (void *)&txpwrqdbm,
1256                 sizeof(txpwrqdbm), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
1257                 &cfg->ioctl_buf_sync);
1258         if (unlikely(err))
1259                 WL_ERR(("qtxpower error (%d)\n", err));
1260         else
1261                 WL_ERR(("dBm=%d, txpwrqdbm=0x%x\n", dbm, txpwrqdbm));
1262
1263         return err;
1264 }
1265
1266 s32 wl_get_tx_power(struct net_device *dev, s32 *dbm)
1267 {
1268         s32 err = 0;
1269         s32 txpwrdbm;
1270         struct bcm_cfg80211 *cfg = g_bcm_cfg;
1271
1272         err = wldev_iovar_getbuf_bsscfg(dev, "qtxpower",
1273                 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
1274         if (unlikely(err)) {
1275                 WL_ERR(("error (%d)\n", err));
1276                 return err;
1277         }
1278
1279         memcpy(&txpwrdbm, cfg->ioctl_buf, sizeof(txpwrdbm));
1280         txpwrdbm = dtoh32(txpwrdbm);
1281         *dbm = (txpwrdbm & ~WL_TXPWR_OVERRIDE) / 4;
1282
1283         WL_INFORM(("dBm=%d, txpwrdbm=0x%x\n", *dbm, txpwrdbm));
1284
1285         return err;
1286 }
1287
1288 #ifdef  P2PONEINT
1289 chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
1290 #else
1291 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
1292 #endif
1293 {
1294         chanspec_t chspec;
1295         int cur_band, err = 0;
1296         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1297         struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
1298         struct ether_addr bssid;
1299         struct wl_bss_info *bss = NULL;
1300
1301         if ((err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), false))) {
1302                 /* STA interface is not associated. So start the new interface on a temp
1303                  * channel . Later proper channel will be applied by the above framework
1304                  * via set_channel (cfg80211 API).
1305                  */
1306                 WL_DBG(("Not associated. Return a temp channel. \n"));
1307                 err = wldev_ioctl(dev, WLC_GET_BAND, &cur_band, sizeof(int), false);
1308                 if (unlikely(err)) {
1309                         WL_ERR(("Get band failed\n"));
1310                         return wl_ch_host_to_driver(WL_P2P_TEMP_CHAN);
1311                 }
1312                 if (cur_band == WLC_BAND_5G)
1313                         return wl_ch_host_to_driver(WL_P2P_TEMP_CHAN_5G);
1314                 else
1315                         return wl_ch_host_to_driver(WL_P2P_TEMP_CHAN);
1316         }
1317
1318
1319         *(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
1320         if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, cfg->extra_buf,
1321                 WL_EXTRA_BUF_MAX, false))) {
1322                         WL_ERR(("Failed to get associated bss info, use temp channel \n"));
1323                         chspec = wl_ch_host_to_driver(WL_P2P_TEMP_CHAN);
1324         }
1325         else {
1326                         bss = (struct wl_bss_info *) (cfg->extra_buf + 4);
1327                         chspec =  bss->chanspec;
1328
1329                         WL_DBG(("Valid BSS Found. chanspec:%d \n", chspec));
1330         }
1331         return chspec;
1332 }
1333
1334 static bcm_struct_cfgdev *
1335 wl_cfg80211_add_monitor_if(char *name)
1336 {
1337 #if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)
1338         WL_INFORM(("wl_cfg80211_add_monitor_if: No more support monitor interface\n"));
1339         return ERR_PTR(-EOPNOTSUPP);
1340 #else
1341         struct net_device* ndev = NULL;
1342
1343         dhd_add_monitor(name, &ndev);
1344         WL_INFORM(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev));
1345         return ndev_to_cfgdev(ndev);
1346 #endif /* WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF */
1347 }
1348
1349 static bcm_struct_cfgdev *
1350 wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
1351 #if defined(WL_CFG80211_P2P_DEV_IF)
1352         const char *name,
1353 #else
1354         char *name,
1355 #endif /* WL_CFG80211_P2P_DEV_IF */
1356         enum nl80211_iftype type, u32 *flags,
1357         struct vif_params *params)
1358 {
1359         s32 err;
1360         s32 timeout = -1;
1361         s32 wlif_type = -1;
1362         s32 mode = 0;
1363         s32 val = 0;
1364         s32 dhd_mode = 0;
1365         chanspec_t chspec;
1366         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1367         struct net_device *primary_ndev;
1368         struct net_device *new_ndev;
1369         struct ether_addr primary_mac;
1370 #ifdef PROP_TXSTATUS_VSDB
1371 #if defined(BCMSDIO)
1372         s32 up = 1;
1373         dhd_pub_t *dhd;
1374         bool enabled;
1375 #endif 
1376 #endif /* PROP_TXSTATUS_VSDB */
1377 #if defined(SUPPORT_AP_POWERSAVE)
1378         dhd_pub_t *dhd;
1379 #endif
1380
1381         if (!cfg)
1382                 return ERR_PTR(-EINVAL);
1383
1384 #ifdef PROP_TXSTATUS_VSDB
1385 if (bcmdhd_prop_txstatus_vsdb) {
1386 #if defined(BCMSDIO)
1387         dhd = (dhd_pub_t *)(cfg->pub);
1388 #endif 
1389 }
1390 #endif /* PROP_TXSTATUS_VSDB */
1391 #if defined(SUPPORT_AP_POWERSAVE)
1392         dhd = (dhd_pub_t *)(cfg->pub);
1393 #endif
1394
1395         /* Use primary I/F for sending cmds down to firmware */
1396         primary_ndev = bcmcfg_to_prmry_ndev(cfg);
1397
1398         if (unlikely(!wl_get_drv_status(cfg, READY, primary_ndev))) {
1399                 WL_ERR(("device is not ready\n"));
1400                 return ERR_PTR(-ENODEV);
1401         }
1402
1403         if (wl_get_drv_status(cfg, CONNECTING, primary_ndev)) {
1404                 WL_ERR(("Already AP connection going on\n"));
1405                 return ERR_PTR(-EBUSY);
1406         }
1407
1408         WL_DBG(("if name: %s, type: %d\n", name, type));
1409         switch (type) {
1410         case NL80211_IFTYPE_ADHOC:
1411 #ifdef WLAIBSS_MCHAN
1412                 return bcm_cfg80211_add_ibss_if(wiphy, (char *)name);
1413 #endif /* WLAIBSS_MCHAN */
1414         case NL80211_IFTYPE_AP_VLAN:
1415         case NL80211_IFTYPE_WDS:
1416         case NL80211_IFTYPE_MESH_POINT:
1417                 WL_ERR(("Unsupported interface type\n"));
1418                 mode = WL_MODE_IBSS;
1419                 return NULL;
1420         case NL80211_IFTYPE_MONITOR:
1421                 return wl_cfg80211_add_monitor_if((char *)name);
1422 #if defined(WL_CFG80211_P2P_DEV_IF)
1423         case NL80211_IFTYPE_P2P_DEVICE:
1424                 return wl_cfgp2p_add_p2p_disc_if(cfg);
1425 #endif /* WL_CFG80211_P2P_DEV_IF */
1426         case NL80211_IFTYPE_STATION:
1427 #ifdef DUAL_STA
1428 #ifdef WLAIBSS_MCHAN
1429                 if (cfg->ibss_cfgdev) {
1430                         WL_ERR(("AIBSS is already operational. "
1431                                         " AIBSS & DUALSTA can't be used together \n"));
1432                         return NULL;
1433                 }
1434 #endif /* WLAIBSS_MCHAN */
1435                 if (!name) {
1436                         WL_ERR(("Interface name not provided \n"));
1437                         return NULL;
1438                 }
1439                 return wl_cfg80211_create_iface(cfg->wdev->wiphy,
1440                         NL80211_IFTYPE_STATION, NULL, name);
1441 #endif /* DUAL_STA */
1442         case NL80211_IFTYPE_P2P_CLIENT:
1443                 wlif_type = WL_P2P_IF_CLIENT;
1444                 mode = WL_MODE_BSS;
1445                 break;
1446         case NL80211_IFTYPE_P2P_GO:
1447         case NL80211_IFTYPE_AP:
1448                 wlif_type = WL_P2P_IF_GO;
1449                 mode = WL_MODE_AP;
1450                 break;
1451         default:
1452                 WL_ERR(("Unsupported interface type\n"));
1453                 return NULL;
1454                 break;
1455         }
1456
1457         if (!name) {
1458                 WL_ERR(("name is NULL\n"));
1459                 return NULL;
1460         }
1461         if (cfg->p2p_supported && (wlif_type != -1)) {
1462                 ASSERT(cfg->p2p); /* ensure expectation of p2p initialization */
1463
1464 #ifdef PROP_TXSTATUS_VSDB
1465 if (bcmdhd_prop_txstatus_vsdb) {
1466 #if defined(BCMSDIO)
1467                 if (!dhd)
1468                         return ERR_PTR(-ENODEV);
1469 #endif 
1470 }
1471 #endif /* PROP_TXSTATUS_VSDB */
1472                 if (!cfg->p2p)
1473                         return ERR_PTR(-ENODEV);
1474
1475                 if (cfg->p2p && !cfg->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
1476                         p2p_on(cfg) = true;
1477                         wl_cfgp2p_set_firm_p2p(cfg);
1478                         wl_cfgp2p_init_discovery(cfg);
1479                         get_primary_mac(cfg, &primary_mac);
1480                         wl_cfgp2p_generate_bss_mac(&primary_mac,
1481                                 &cfg->p2p->dev_addr, &cfg->p2p->int_addr);
1482                 }
1483
1484                 memset(cfg->p2p->vir_ifname, 0, IFNAMSIZ);
1485                 strncpy(cfg->p2p->vir_ifname, name, IFNAMSIZ - 1);
1486
1487                 wl_cfg80211_scan_abort(cfg);
1488 #ifdef PROP_TXSTATUS_VSDB
1489 if (bcmdhd_prop_txstatus_vsdb) {
1490 #if defined(BCMSDIO)
1491                 if (!cfg->wlfc_on && !disable_proptx) {
1492                         dhd_wlfc_get_enable(dhd, &enabled);
1493                         if (!enabled && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
1494                                 dhd->op_mode != DHD_FLAG_IBSS_MODE) {
1495                                 dhd_wlfc_init(dhd);
1496                                 err = wldev_ioctl(primary_ndev, WLC_UP, &up, sizeof(s32), true);
1497                                 if (err < 0)
1498                                         WL_ERR(("WLC_UP return err:%d\n", err));
1499                         }
1500                         cfg->wlfc_on = true;
1501                 }
1502 #endif 
1503 }
1504 #endif /* PROP_TXSTATUS_VSDB */
1505
1506                 /* In concurrency case, STA may be already associated in a particular channel.
1507                  * so retrieve the current channel of primary interface and then start the virtual
1508                  * interface on that.
1509                  */
1510                  chspec = wl_cfg80211_get_shared_freq(wiphy);
1511
1512                 /* For P2P mode, use P2P-specific driver features to create the
1513                  * bss: "cfg p2p_ifadd"
1514                  */
1515                 wl_set_p2p_status(cfg, IF_ADDING);
1516                 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
1517                 if (wlif_type == WL_P2P_IF_GO)
1518                         wldev_iovar_setint(primary_ndev, "mpc", 0);
1519                 err = wl_cfgp2p_ifadd(cfg, &cfg->p2p->int_addr, htod32(wlif_type), chspec);
1520                 if (unlikely(err)) {
1521                         wl_clr_p2p_status(cfg, IF_ADDING);
1522                         WL_ERR((" virtual iface add failed (%d) \n", err));
1523                         return ERR_PTR(-ENOMEM);
1524                 }
1525
1526                 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
1527                         (wl_get_p2p_status(cfg, IF_ADDING) == false),
1528                         msecs_to_jiffies(MAX_WAIT_TIME));
1529
1530                 if (timeout > 0 && !wl_get_p2p_status(cfg, IF_ADDING) && cfg->if_event_info.valid) {
1531                         struct wireless_dev *vwdev;
1532                         int pm_mode = PM_ENABLE;
1533                         wl_if_event_info *event = &cfg->if_event_info;
1534
1535                         /* IF_ADD event has come back, we can proceed to to register
1536                          * the new interface now, use the interface name provided by caller (thus
1537                          * ignore the one from wlc)
1538                          */
1539                         strncpy(cfg->if_event_info.name, name, IFNAMSIZ - 1);
1540                         new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx, cfg->p2p->vir_ifname,
1541                                 event->mac, event->bssidx);
1542                         if (new_ndev == NULL)
1543                                 goto fail;
1544
1545                         wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION) = new_ndev;
1546                         wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION) = event->bssidx;
1547                         vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL);
1548                         if (unlikely(!vwdev)) {
1549                                 WL_ERR(("Could not allocate wireless device\n"));
1550                                 goto fail;
1551                         }
1552                         vwdev->wiphy = cfg->wdev->wiphy;
1553                         WL_INFORM(("virtual interface(%s) is created\n", cfg->p2p->vir_ifname));
1554                         vwdev->iftype = type;
1555                         vwdev->netdev = new_ndev;
1556                         new_ndev->ieee80211_ptr = vwdev;
1557                         SET_NETDEV_DEV(new_ndev, wiphy_dev(vwdev->wiphy));
1558                         wl_set_drv_status(cfg, READY, new_ndev);
1559                         cfg->p2p->vif_created = true;
1560                         wl_set_mode_by_netdev(cfg, new_ndev, mode);
1561
1562                         if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev) != BCME_OK) {
1563                                 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev);
1564                                 goto fail;
1565                         }
1566                         wl_alloc_netinfo(cfg, new_ndev, vwdev, mode, pm_mode);
1567                         val = 1;
1568                         /* Disable firmware roaming for P2P interface  */
1569                         wldev_iovar_setint(new_ndev, "roam_off", val);
1570
1571                         if (mode != WL_MODE_AP)
1572                                 wldev_iovar_setint(new_ndev, "buf_key_b4_m4", 1);
1573
1574                         DHD_NV_INFO((" virtual interface(%s) is "
1575                                 "created net attach done\n", cfg->p2p->vir_ifname));
1576 #ifdef CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA
1577                         TEGRA_SYSFS_HISTOGRAM_STAT_INC(ago_start);
1578 #endif
1579                         if (mode == WL_MODE_AP)
1580                                 wl_set_drv_status(cfg, CONNECTED, new_ndev);
1581 #ifdef SUPPORT_AP_POWERSAVE
1582                         if (mode == WL_MODE_AP) {
1583                                 dhd_set_ap_powersave(dhd, 0, TRUE);
1584                         }
1585 #endif
1586                         if (type == NL80211_IFTYPE_P2P_CLIENT)
1587                                 dhd_mode = DHD_FLAG_P2P_GC_MODE;
1588                         else if (type == NL80211_IFTYPE_P2P_GO)
1589                                 dhd_mode = DHD_FLAG_P2P_GO_MODE;
1590                         DNGL_FUNC(dhd_cfg80211_set_p2p_info, (cfg, dhd_mode));
1591                         /* reinitialize completion to clear previous count */
1592 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
1593                         INIT_COMPLETION(cfg->iface_disable);
1594 #else
1595                         init_completion(&cfg->iface_disable);
1596 #endif
1597                         return ndev_to_cfgdev(new_ndev);
1598                 } else {
1599                         wl_clr_p2p_status(cfg, IF_ADDING);
1600                         WL_ERR((" virtual interface(%s) is not created \n", cfg->p2p->vir_ifname));
1601
1602                         WL_ERR(("left timeout : %d\n", timeout));
1603                         WL_ERR(("IF_ADDING status : %d\n", wl_get_p2p_status(cfg, IF_ADDING)));
1604                         WL_ERR(("event valid : %d\n", cfg->if_event_info.valid));
1605
1606                         wl_clr_p2p_status(cfg, GO_NEG_PHASE);
1607                         wl_set_p2p_status(cfg, IF_DELETING);
1608
1609                         err = wl_cfgp2p_ifdel(cfg, &cfg->p2p->int_addr);
1610                         if (err == BCME_OK) {
1611                                 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
1612                                         (wl_get_p2p_status(cfg, IF_DELETING) == false),
1613                                         msecs_to_jiffies(MAX_WAIT_TIME));
1614                                 if (timeout > 0 && !wl_get_p2p_status(cfg, IF_DELETING) &&
1615                                         cfg->if_event_info.valid) {
1616                                         WL_ERR(("IFDEL operation done\n"));
1617                                 } else {
1618                                         WL_ERR(("IFDEL didn't complete properly\n"));
1619                                         err = BCME_ERROR;
1620                                 }
1621                         }
1622                         if (err != BCME_OK) {
1623                                 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
1624
1625                                 WL_ERR(("p2p_ifdel failed, error %d, sent HANG event to %s\n",
1626                                         err, ndev->name));
1627                                 net_os_send_hang_message(ndev);
1628                         }
1629
1630                         memset(cfg->p2p->vir_ifname, '\0', IFNAMSIZ);
1631                         cfg->p2p->vif_created = false;
1632 #ifdef PROP_TXSTATUS_VSDB
1633 if (bcmdhd_prop_txstatus_vsdb) {
1634 #if defined(BCMSDIO)
1635                         dhd_wlfc_get_enable(dhd, &enabled);
1636                 if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
1637                         dhd->op_mode != DHD_FLAG_IBSS_MODE) {
1638                         dhd_wlfc_deinit(dhd);
1639                         cfg->wlfc_on = false;
1640                 }
1641 #endif 
1642 }
1643 #endif /* PROP_TXSTATUS_VSDB */
1644                 }
1645         }
1646
1647 fail:
1648         if (wlif_type == WL_P2P_IF_GO)
1649                 wldev_iovar_setint(primary_ndev, "mpc", 1);
1650         return ERR_PTR(-ENODEV);
1651 }
1652
1653 static s32
1654 wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
1655 {
1656         struct net_device *dev = NULL;
1657         struct ether_addr p2p_mac;
1658         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1659         s32 timeout = -1;
1660         s32 ret = 0;
1661         s32 index = -1;
1662 #ifdef CUSTOM_SET_CPUCORE
1663         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
1664 #endif /* CUSTOM_SET_CPUCORE */
1665         WL_DBG(("Enter\n"));
1666
1667 #ifdef CUSTOM_SET_CPUCORE
1668         dhd->chan_isvht80 &= ~DHD_FLAG_P2P_MODE;
1669         if (!(dhd->chan_isvht80))
1670                 dhd_set_cpucore(dhd, FALSE);
1671 #endif /* CUSTOM_SET_CPUCORE */
1672         if (!cfg)
1673                 return -EINVAL;
1674
1675 #if defined(WL_CFG80211_P2P_DEV_IF)
1676         if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
1677                 return wl_cfgp2p_del_p2p_disc_if(cfgdev, cfg);
1678         }
1679 #endif /* WL_CFG80211_P2P_DEV_IF */
1680         dev = cfgdev_to_wlc_ndev(cfgdev, cfg);
1681
1682 #ifdef WLAIBSS_MCHAN
1683         if (cfgdev == cfg->ibss_cfgdev)
1684                 return bcm_cfg80211_del_ibss_if(wiphy, cfgdev);
1685 #endif /* WLAIBSS_MCHAN */
1686
1687 #ifdef DUAL_STA
1688         if (cfgdev == cfg->bss_cfgdev)
1689                 return wl_cfg80211_del_iface(wiphy, cfgdev);
1690 #endif /* DUAL_STA */
1691
1692         if (wl_cfgp2p_find_idx(cfg, dev, &index) != BCME_OK) {
1693                 WL_ERR(("Find p2p index from ndev(%p) failed\n", dev));
1694                 return BCME_ERROR;
1695         }
1696         if (cfg->p2p_supported) {
1697                 memcpy(p2p_mac.octet, cfg->p2p->int_addr.octet, ETHER_ADDR_LEN);
1698
1699                 /* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases
1700                  */
1701                 WL_DBG(("P2P: GO_NEG_PHASE status cleared "));
1702                 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
1703                 if (cfg->p2p->vif_created) {
1704                         if (wl_get_drv_status(cfg, SCANNING, dev)) {
1705                                 wl_notify_escan_complete(cfg, dev, true, true);
1706                         }
1707                         wldev_iovar_setint(dev, "mpc", 1);
1708                         /* Delete pm_enable_work */
1709                         wl_add_remove_pm_enable_work(cfg, FALSE, WL_HANDLER_DEL);
1710
1711                         /* for GC */
1712                         if (wl_get_drv_status(cfg, DISCONNECTING, dev) &&
1713                                 (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_AP)) {
1714                                 WL_ERR(("Wait for Link Down event for GC !\n"));
1715                                 wait_for_completion_timeout
1716                                         (&cfg->iface_disable, msecs_to_jiffies(500));
1717                         }
1718
1719                         memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
1720                         wl_set_p2p_status(cfg, IF_DELETING);
1721                         DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (cfg));
1722
1723                         /* for GO */
1724                         if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
1725                                 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
1726                                 /* disable interface before bsscfg free */
1727                                 ret = wl_cfgp2p_ifdisable(cfg, &p2p_mac);
1728                                 /* if fw doesn't support "ifdis",
1729                                    do not wait for link down of ap mode
1730                                  */
1731                                 if (ret == 0) {
1732                                         WL_ERR(("Wait for Link Down event for GO !!!\n"));
1733                                         wait_for_completion_timeout(&cfg->iface_disable,
1734                                                 msecs_to_jiffies(500));
1735                                 } else if (ret != BCME_UNSUPPORTED) {
1736                                         msleep(300);
1737                                 }
1738                         }
1739                         wl_cfgp2p_clear_management_ie(cfg, index);
1740
1741                         if (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_AP)
1742                                 wldev_iovar_setint(dev, "buf_key_b4_m4", 0);
1743
1744                         /* delete interface after link down */
1745                         ret = wl_cfgp2p_ifdel(cfg, &p2p_mac);
1746
1747                         if (ret != BCME_OK) {
1748                                 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
1749
1750                                 WL_ERR(("p2p_ifdel failed, error %d, sent HANG event to %s\n",
1751                                         ret, ndev->name));
1752                                 #if defined(BCMDONGLEHOST) && defined(OEM_ANDROID)
1753                                 net_os_send_hang_message(ndev);
1754                                 #endif 
1755                         } else {
1756                                 /* Wait for IF_DEL operation to be finished */
1757                                 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
1758                                         (wl_get_p2p_status(cfg, IF_DELETING) == false),
1759                                         msecs_to_jiffies(MAX_WAIT_TIME));
1760                                 if (timeout > 0 && !wl_get_p2p_status(cfg, IF_DELETING) &&
1761                                         cfg->if_event_info.valid) {
1762
1763                                         WL_DBG(("IFDEL operation done\n"));
1764                                         wl_cfg80211_handle_ifdel(cfg, &cfg->if_event_info, dev);
1765                                 } else {
1766                                         WL_ERR(("IFDEL didn't complete properly\n"));
1767                                 }
1768                         }
1769
1770                         ret = dhd_del_monitor(dev);
1771                         if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
1772                                 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_CANCEL((dhd_pub_t *)(cfg->pub));
1773                         }
1774                 }
1775         }
1776         return ret;
1777 }
1778
1779 static s32
1780 wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
1781         enum nl80211_iftype type, u32 *flags,
1782         struct vif_params *params)
1783 {
1784         s32 ap = 0;
1785         s32 infra = 0;
1786         s32 ibss = 0;
1787         s32 wlif_type;
1788         s32 mode = 0;
1789         s32 err = BCME_OK;
1790         chanspec_t chspec;
1791         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1792         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
1793
1794         WL_DBG(("Enter type %d\n", type));
1795
1796         if (!cfg)
1797                 return -EINVAL;
1798         switch (type) {
1799         case NL80211_IFTYPE_MONITOR:
1800         case NL80211_IFTYPE_WDS:
1801         case NL80211_IFTYPE_MESH_POINT:
1802                 ap = 1;
1803                 WL_ERR(("type (%d) : currently we do not support this type\n",
1804                         type));
1805                 break;
1806         case NL80211_IFTYPE_ADHOC:
1807                 mode = WL_MODE_IBSS;
1808                 ibss = 1;
1809                 break;
1810         case NL80211_IFTYPE_STATION:
1811         case NL80211_IFTYPE_P2P_CLIENT:
1812                 mode = WL_MODE_BSS;
1813                 infra = 1;
1814                 break;
1815         case NL80211_IFTYPE_AP:
1816         case NL80211_IFTYPE_AP_VLAN:
1817         case NL80211_IFTYPE_P2P_GO:
1818                 mode = WL_MODE_AP;
1819                 ap = 1;
1820                 break;
1821         default:
1822                 return -EINVAL;
1823         }
1824         if (!dhd)
1825                 return -EINVAL;
1826         if (ap) {
1827                 wl_set_mode_by_netdev(cfg, ndev, mode);
1828                 if (cfg->p2p_supported && cfg->p2p->vif_created) {
1829                         WL_DBG(("p2p_vif_created (%d) p2p_on (%d)\n", cfg->p2p->vif_created,
1830                         p2p_on(cfg)));
1831                         wldev_iovar_setint(ndev, "mpc", 0);
1832                         wl_notify_escan_complete(cfg, ndev, true, true);
1833
1834                         /* In concurrency case, STA may be already associated in a particular
1835                          * channel. so retrieve the current channel of primary interface and
1836                          * then start the virtual interface on that.
1837                          */
1838                         chspec = wl_cfg80211_get_shared_freq(wiphy);
1839
1840                         wlif_type = WL_P2P_IF_GO;
1841                         WL_ERR(("%s : ap (%d), infra (%d), iftype: (%d)\n",
1842                                 ndev->name, ap, infra, type));
1843                         wl_set_p2p_status(cfg, IF_CHANGING);
1844                         wl_clr_p2p_status(cfg, IF_CHANGED);
1845                         wl_cfgp2p_ifchange(cfg, &cfg->p2p->int_addr, htod32(wlif_type), chspec);
1846                         wait_event_interruptible_timeout(cfg->netif_change_event,
1847                                 (wl_get_p2p_status(cfg, IF_CHANGED) == true),
1848                                 msecs_to_jiffies(MAX_WAIT_TIME));
1849                         wl_set_mode_by_netdev(cfg, ndev, mode);
1850                         dhd->op_mode &= ~DHD_FLAG_P2P_GC_MODE;
1851                         dhd->op_mode |= DHD_FLAG_P2P_GO_MODE;
1852                         wl_clr_p2p_status(cfg, IF_CHANGING);
1853                         wl_clr_p2p_status(cfg, IF_CHANGED);
1854                         if (mode == WL_MODE_AP)
1855                                 wl_set_drv_status(cfg, CONNECTED, ndev);
1856 #ifdef SUPPORT_AP_POWERSAVE
1857                         dhd_set_ap_powersave(dhd, 0, TRUE);
1858 #endif
1859                 } else if (ndev == bcmcfg_to_prmry_ndev(cfg) &&
1860                         !wl_get_drv_status(cfg, AP_CREATED, ndev)) {
1861                         wl_set_drv_status(cfg, AP_CREATING, ndev);
1862                         if (!cfg->ap_info &&
1863                                 !(cfg->ap_info = kzalloc(sizeof(struct ap_info), GFP_KERNEL))) {
1864                                 WL_ERR(("struct ap_saved_ie allocation failed\n"));
1865                                 return -ENOMEM;
1866                         }
1867                 } else {
1868                         WL_ERR(("Cannot change the interface for GO or SOFTAP\n"));
1869                         return -EINVAL;
1870                 }
1871         } else {
1872                 WL_DBG(("Change_virtual_iface for transition from GO/AP to client/STA"));
1873 #ifdef SUPPORT_AP_POWERSAVE
1874                 dhd_set_ap_powersave(dhd, 0, FALSE);
1875 #endif
1876 #ifdef  P2PONEINT
1877                 wl_set_mode_by_netdev(cfg, ndev, mode);
1878                 if (cfg->p2p_supported && cfg->p2p->vif_created) {
1879                         WL_DBG(("p2p_vif_created (%d) p2p_on (%d)\n", cfg->p2p->vif_created,
1880                                 p2p_on(cfg)));
1881                         wldev_iovar_setint(ndev, "mpc", 0);
1882                         wl_notify_escan_complete(cfg, ndev, true, true);
1883
1884                         /* In concurrency case, STA may be already associated in a particular
1885                          * channel. so retrieve the current channel of primary interface and
1886                          * then start the virtual interface on that.
1887                          */
1888                         chspec = wl_cfg80211_get_shared_freq(wiphy);
1889
1890                         wlif_type = WL_P2P_IF_CLIENT;
1891                         WL_ERR(("%s : ap (%d), infra (%d), iftype: (%d) chspec 0x%x \n",
1892                                 ndev->name, ap, infra, type, chspec));
1893                         wl_set_p2p_status(cfg, IF_CHANGING);
1894                         wl_clr_p2p_status(cfg, IF_CHANGED);
1895                         wl_cfgp2p_ifchange(cfg, &cfg->p2p->int_addr, htod32(wlif_type), chspec);
1896                         wait_event_interruptible_timeout(cfg->netif_change_event,
1897                                 (wl_get_p2p_status(cfg, IF_CHANGED) == true),
1898                                 msecs_to_jiffies(MAX_WAIT_TIME));
1899                         wl_set_mode_by_netdev(cfg, ndev, mode);
1900                         dhd->op_mode |= DHD_FLAG_P2P_GC_MODE;
1901                         dhd->op_mode &= ~DHD_FLAG_P2P_GO_MODE;
1902                         wl_clr_p2p_status(cfg, IF_CHANGING);
1903                         wl_clr_p2p_status(cfg, IF_CHANGED);
1904
1905 #define INIT_IE(IE_TYPE, BSS_TYPE)      \
1906                 do {                            \
1907                 memset(wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie, 0, \
1908                 sizeof(wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie)); \
1909                 wl_to_p2p_bss_saved_ie(cfg, BSS_TYPE).p2p_ ## IE_TYPE ## _ie_len = 0; \
1910                 } while (0);
1911
1912                         INIT_IE(probe_req, P2PAPI_BSSCFG_CONNECTION);
1913                         INIT_IE(probe_res, P2PAPI_BSSCFG_CONNECTION);
1914                         INIT_IE(assoc_req, P2PAPI_BSSCFG_CONNECTION);
1915                         INIT_IE(assoc_res, P2PAPI_BSSCFG_CONNECTION);
1916                         INIT_IE(beacon,    P2PAPI_BSSCFG_CONNECTION);
1917                 }
1918 #endif /* P2PONEINT */
1919         }
1920
1921         if (ibss) {
1922                 infra = 0;
1923                 wl_set_mode_by_netdev(cfg, ndev, mode);
1924                 err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(s32), true);
1925                 if (err < 0) {
1926                         WL_ERR(("SET Adhoc error %d\n", err));
1927                         return -EINVAL;
1928                 }
1929         }
1930
1931         ndev->ieee80211_ptr->iftype = type;
1932         return 0;
1933 }
1934
1935 s32
1936 wl_cfg80211_notify_ifadd(int ifidx, char *name, uint8 *mac, uint8 bssidx)
1937 {
1938         bool ifadd_expected = FALSE;
1939         struct bcm_cfg80211 *cfg = g_bcm_cfg;
1940
1941         /* P2P may send WLC_E_IF_ADD and/or WLC_E_IF_CHANGE during IF updating ("p2p_ifupd")
1942          * redirect the IF_ADD event to ifchange as it is not a real "new" interface
1943          */
1944         if (wl_get_p2p_status(cfg, IF_CHANGING))
1945                 return wl_cfg80211_notify_ifchange(ifidx, name, mac, bssidx);
1946
1947         /* Okay, we are expecting IF_ADD (as IF_ADDING is true) */
1948         if (wl_get_p2p_status(cfg, IF_ADDING)) {
1949                 ifadd_expected = TRUE;
1950                 wl_clr_p2p_status(cfg, IF_ADDING);
1951         } else if (cfg->bss_pending_op) {
1952                 ifadd_expected = TRUE;
1953                 cfg->bss_pending_op = FALSE;
1954         }
1955
1956         if (ifadd_expected) {
1957                 wl_if_event_info *if_event_info = &cfg->if_event_info;
1958
1959                 if_event_info->valid = TRUE;
1960                 if_event_info->ifidx = ifidx;
1961                 if_event_info->bssidx = bssidx;
1962                 strncpy(if_event_info->name, name, IFNAMSIZ);
1963                 if_event_info->name[IFNAMSIZ] = '\0';
1964                 if (mac)
1965                         memcpy(if_event_info->mac, mac, ETHER_ADDR_LEN);
1966                 wake_up_interruptible(&cfg->netif_change_event);
1967                 return BCME_OK;
1968         }
1969
1970         return BCME_ERROR;
1971 }
1972
1973 s32
1974 wl_cfg80211_notify_ifdel(int ifidx, char *name, uint8 *mac, uint8 bssidx)
1975 {
1976         bool ifdel_expected = FALSE;
1977         struct bcm_cfg80211 *cfg = g_bcm_cfg;
1978         wl_if_event_info *if_event_info = &cfg->if_event_info;
1979         dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
1980
1981
1982         if (wl_get_p2p_status(cfg, IF_DELETING)) {
1983                 if_event_info->valid = TRUE;
1984                 ifdel_expected = TRUE;
1985                 dhd_p2p_ifdel(dhd,ifidx);
1986                 wl_clr_p2p_status(cfg, IF_DELETING);
1987         } else if (cfg->bss_pending_op) {
1988                 ifdel_expected = TRUE;
1989                 cfg->bss_pending_op = FALSE;
1990                 if_event_info->valid = TRUE;
1991         }
1992
1993         if (ifdel_expected) {
1994                 if_event_info->ifidx = ifidx;
1995                 if_event_info->bssidx = bssidx;
1996                 wake_up_interruptible(&cfg->netif_change_event);
1997                 return BCME_OK;
1998         }
1999
2000         return BCME_ERROR;
2001 }
2002
2003 s32
2004 wl_cfg80211_notify_ifchange(int ifidx, char *name, uint8 *mac, uint8 bssidx)
2005 {
2006         struct bcm_cfg80211 *cfg = g_bcm_cfg;
2007
2008         if (wl_get_p2p_status(cfg, IF_CHANGING)) {
2009                 wl_set_p2p_status(cfg, IF_CHANGED);
2010                 wake_up_interruptible(&cfg->netif_change_event);
2011                 return BCME_OK;
2012         }
2013
2014         return BCME_ERROR;
2015 }
2016
2017 static s32 wl_cfg80211_handle_ifdel(struct bcm_cfg80211 *cfg, wl_if_event_info *if_event_info,
2018         struct net_device* ndev)
2019 {
2020         s32 type = -1;
2021         s32 bssidx = -1;
2022 #ifdef PROP_TXSTATUS_VSDB
2023 #if defined(BCMSDIO)
2024         dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
2025         bool enabled;
2026 #endif 
2027 #endif /* PROP_TXSTATUS_VSDB */
2028
2029         bssidx = if_event_info->bssidx;
2030         if (bssidx != wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION)) {
2031                 WL_ERR(("got IF_DEL for if %d, not owned by cfg driver\n", bssidx));
2032                 return BCME_ERROR;
2033         }
2034
2035         if (p2p_is_on(cfg) && cfg->p2p->vif_created) {
2036
2037                 if (cfg->scan_request && (cfg->escan_info.ndev == ndev)) {
2038                         /* Abort any pending scan requests */
2039                         cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
2040                         WL_DBG(("ESCAN COMPLETED\n"));
2041                         wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, false);
2042                 }
2043
2044                 memset(cfg->p2p->vir_ifname, '\0', IFNAMSIZ);
2045                 if (wl_cfgp2p_find_type(cfg, bssidx, &type) != BCME_OK) {
2046                         WL_ERR(("Find p2p type from bssidx(%d) failed\n", bssidx));
2047                         return BCME_ERROR;
2048                 }
2049                 wl_clr_drv_status(cfg, CONNECTED, wl_to_p2p_bss_ndev(cfg, type));
2050                 wl_to_p2p_bss_ndev(cfg, type) = NULL;
2051                 wl_to_p2p_bss_bssidx(cfg, type) = WL_INVALID;
2052                 cfg->p2p->vif_created = false;
2053
2054 #ifdef PROP_TXSTATUS_VSDB
2055 if (bcmdhd_prop_txstatus_vsdb) {
2056 #if defined(BCMSDIO)
2057                 dhd_wlfc_get_enable(dhd, &enabled);
2058                 if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
2059                         dhd->op_mode != DHD_FLAG_IBSS_MODE) {
2060                         dhd_wlfc_deinit(dhd);
2061                         cfg->wlfc_on = false;
2062                 }
2063 #endif 
2064 }
2065 #endif /* PROP_TXSTATUS_VSDB */
2066         }
2067
2068         wl_cfg80211_remove_p2p_if(cfg, if_event_info->ifidx, ndev);
2069         return BCME_OK;
2070 }
2071
2072 /* Find listen channel */
2073 static s32 wl_find_listen_channel(struct bcm_cfg80211 *cfg,
2074         const u8 *ie, u32 ie_len)
2075 {
2076         wifi_p2p_ie_t *p2p_ie;
2077         u8 *end, *pos;
2078         s32 listen_channel;
2079
2080         pos = (u8 *)ie;
2081         p2p_ie = wl_cfgp2p_find_p2pie(pos, ie_len);
2082
2083         if (p2p_ie == NULL)
2084                 return 0;
2085
2086         pos = p2p_ie->subelts;
2087         end = p2p_ie->subelts + (p2p_ie->len - 4);
2088
2089         CFGP2P_DBG((" found p2p ie ! lenth %d \n",
2090                 p2p_ie->len));
2091
2092         while (pos < end) {
2093                 uint16 attr_len;
2094                 if (pos + 2 >= end) {
2095                         CFGP2P_DBG((" -- Invalid P2P attribute"));
2096                         return 0;
2097                 }
2098                 attr_len = ((uint16) (((pos + 1)[1] << 8) | (pos + 1)[0]));
2099
2100                 if (pos + 3 + attr_len > end) {
2101                         CFGP2P_DBG(("P2P: Attribute underflow "
2102                                    "(len=%u left=%d)",
2103                                    attr_len, (int) (end - pos - 3)));
2104                         return 0;
2105                 }
2106
2107                 /* if Listen Channel att id is 6 and the vailue is valid,
2108                  * return the listen channel
2109                  */
2110                 if (pos[0] == 6) {
2111                         /* listen channel subel length format
2112                          * 1(id) + 2(len) + 3(country) + 1(op. class) + 1(chan num)
2113                          */
2114                         listen_channel = pos[1 + 2 + 3 + 1];
2115
2116                         if (listen_channel == SOCIAL_CHAN_1 ||
2117                                 listen_channel == SOCIAL_CHAN_2 ||
2118                                 listen_channel == SOCIAL_CHAN_3) {
2119                                 CFGP2P_DBG((" Found my Listen Channel %d \n", listen_channel));
2120                                 return listen_channel;
2121                         }
2122                 }
2123                 pos += 3 + attr_len;
2124         }
2125         return 0;
2126 }
2127
2128 static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_request *request)
2129 {
2130         u32 n_ssids;
2131         u32 n_channels;
2132         u16 channel;
2133         chanspec_t chanspec;
2134         s32 i = 0, j = 0, offset;
2135         char *ptr;
2136         wlc_ssid_t ssid;
2137         struct bcm_cfg80211 *cfg = g_bcm_cfg;
2138
2139         memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
2140         params->bss_type = DOT11_BSSTYPE_ANY;
2141         params->scan_type = 0;
2142         params->nprobes = -1;
2143         params->active_time = -1;
2144         params->passive_time = -1;
2145         params->home_time = -1;
2146         params->channel_num = 0;
2147         memset(&params->ssid, 0, sizeof(wlc_ssid_t));
2148 #ifdef CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA
2149         TEGRA_SCAN_PREPARE(params, request)
2150 #endif
2151
2152         WL_SCAN(("Preparing Scan request\n"));
2153         WL_SCAN(("nprobes=%d\n", params->nprobes));
2154         WL_SCAN(("active_time=%d\n", params->active_time));
2155         WL_SCAN(("passive_time=%d\n", params->passive_time));
2156         WL_SCAN(("home_time=%d\n", params->home_time));
2157         WL_SCAN(("scan_type=%d\n", params->scan_type));
2158
2159         params->nprobes = htod32(params->nprobes);
2160         params->active_time = htod32(params->active_time);
2161         params->passive_time = htod32(params->passive_time);
2162         params->home_time = htod32(params->home_time);
2163
2164         /* if request is null just exit so it will be all channel broadcast scan */
2165         if (!request)
2166                 return;
2167
2168         n_ssids = request->n_ssids;
2169         n_channels = request->n_channels;
2170
2171         /* Copy channel array if applicable */
2172         WL_SCAN(("### List of channelspecs to scan ###\n"));
2173         if (n_channels > 0) {
2174                 for (i = 0; i < n_channels; i++) {
2175                         chanspec = 0;
2176                         channel = ieee80211_frequency_to_channel(request->channels[i]->center_freq);
2177                         /* SKIP DFS channels for Secondary interface */
2178                         if ((cfg->escan_info.ndev != bcmcfg_to_prmry_ndev(cfg)) &&
2179                                 (request->channels[i]->flags &
2180 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
2181                                 (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN)))
2182 #else
2183                                 (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR)))
2184 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) */
2185                                 continue;
2186
2187                         if (request->channels[i]->band == IEEE80211_BAND_2GHZ) {
2188                                 chanspec |= WL_CHANSPEC_BAND_2G;
2189                         } else {
2190                                 chanspec |= WL_CHANSPEC_BAND_5G;
2191                         }
2192
2193                         chanspec |= WL_CHANSPEC_BW_20;
2194                         chanspec |= WL_CHANSPEC_CTL_SB_NONE;
2195
2196                         params->channel_list[j] = channel;
2197                         params->channel_list[j] &= WL_CHANSPEC_CHAN_MASK;
2198                         params->channel_list[j] |= chanspec;
2199                         WL_SCAN(("Chan : %d, Channel spec: %x \n",
2200                                 channel, params->channel_list[j]));
2201                         params->channel_list[j] = wl_chspec_host_to_driver(params->channel_list[j]);
2202                         j++;
2203                 }
2204         } else {
2205                 WL_SCAN(("Scanning all channels\n"));
2206         }
2207         n_channels = j;
2208         /* Copy ssid array if applicable */
2209         WL_SCAN(("### List of SSIDs to scan ###\n"));
2210         if (n_ssids > 0) {
2211                 offset = offsetof(wl_scan_params_t, channel_list) + n_channels * sizeof(u16);
2212                 offset = roundup(offset, sizeof(u32));
2213                 ptr = (char*)params + offset;
2214                 for (i = 0; i < n_ssids; i++) {
2215                         memset(&ssid, 0, sizeof(wlc_ssid_t));
2216                         ssid.SSID_len = MIN((int)request->ssids[i].ssid_len, DOT11_MAX_SSID_LEN);
2217                         memcpy(ssid.SSID, request->ssids[i].ssid, ssid.SSID_len);
2218                         if (!ssid.SSID_len)
2219                                 WL_SCAN(("%d: Broadcast scan\n", i));
2220                         else
2221                                 WL_SCAN(("%d: scan  for  %s size =%d\n", i,
2222                                 ssid.SSID, ssid.SSID_len));
2223                         memcpy(ptr, &ssid, sizeof(wlc_ssid_t));
2224                         ptr += sizeof(wlc_ssid_t);
2225                 }
2226         } else {
2227                 WL_SCAN(("Broadcast scan\n"));
2228         }
2229         /* Adding mask to channel numbers */
2230         params->channel_num =
2231                 htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) |
2232                        (n_channels & WL_SCAN_PARAMS_COUNT_MASK));
2233
2234 #ifdef CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA
2235         /* skip original code for single channel scan parameter override if
2236          * processing scan request from one of the scan work(s)
2237          * - the scan request in the scan work(s) has specific scan parameters
2238          *   which should not be overridden
2239          */
2240         TEGRA_SCAN_WORK_ACTIVE_CHECK(request,
2241                 goto skip_single_channel_scan_parameter_override)
2242 #endif
2243         if (n_channels == 1) {
2244                 params->active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
2245                 params->nprobes = htod32(params->active_time / WL_SCAN_JOIN_PROBE_INTERVAL_MS);
2246         }
2247 #ifdef CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA
2248 skip_single_channel_scan_parameter_override:
2249         ;
2250 #endif
2251 }
2252
2253 static s32
2254 wl_get_valid_channels(struct net_device *ndev, u8 *valid_chan_list, s32 size)
2255 {
2256         wl_uint32_list_t *list;
2257         s32 err = BCME_OK;
2258         if (valid_chan_list == NULL || size <= 0)
2259                 return -ENOMEM;
2260
2261         memset(valid_chan_list, 0, size);
2262         list = (wl_uint32_list_t *)(void *) valid_chan_list;
2263         list->count = htod32(WL_NUMCHANNELS);
2264         err = wldev_ioctl(ndev, WLC_GET_VALID_CHANNELS, valid_chan_list, size, false);
2265         if (err != 0) {
2266                 WL_ERR(("get channels failed with %d\n", err));
2267         }
2268
2269         return err;
2270 }
2271
2272 #if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME)
2273 #define FIRST_SCAN_ACTIVE_DWELL_TIME_MS 40
2274 bool g_first_broadcast_scan = TRUE;
2275 #endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */
2276
2277 static s32
2278 wl_run_escan(struct bcm_cfg80211 *cfg, struct net_device *ndev,
2279         struct cfg80211_scan_request *request, uint16 action)
2280 {
2281         s32 err = BCME_OK;
2282         u32 n_channels;
2283         u32 n_ssids;
2284         s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params));
2285         wl_escan_params_t *params = NULL;
2286         u8 chan_buf[sizeof(u32)*(WL_NUMCHANNELS + 1)];
2287         u32 num_chans = 0;
2288         s32 channel;
2289         u32 n_valid_chan;
2290         s32 search_state = WL_P2P_DISC_ST_SCAN;
2291         u32 i, j, n_nodfs = 0;
2292         u16 *default_chan_list = NULL;
2293         wl_uint32_list_t *list;
2294         struct net_device *dev = NULL;
2295 #if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME)
2296         bool is_first_init_2g_scan = false;
2297 #endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */
2298         p2p_scan_purpose_t      p2p_scan_purpose = P2P_SCAN_PURPOSE_MIN;
2299
2300         WL_DBG(("Enter \n"));
2301
2302         /* scan request can come with empty request : perform all default scan */
2303         if (!cfg) {
2304                 err = -EINVAL;
2305                 goto exit;
2306         }
2307         if (!cfg->p2p_supported || !p2p_scan(cfg)) {
2308                 /* LEGACY SCAN TRIGGER */
2309                 WL_SCAN((" LEGACY E-SCAN START\n"));
2310
2311 #if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME)
2312                 if (!request) {
2313                         err = -EINVAL;
2314                         goto exit;
2315                 }
2316                 if (ndev == bcmcfg_to_prmry_ndev(cfg) && g_first_broadcast_scan == true) {
2317 #ifdef USE_INITIAL_2G_SCAN
2318                         struct ieee80211_channel tmp_channel_list[CH_MAX_2G_CHANNEL];
2319                         /* allow one 5G channel to add previous connected channel in 5G */
2320                         bool allow_one_5g_channel = TRUE;
2321                         j = 0;
2322                         for (i = 0; i < request->n_channels; i++) {
2323                                 int tmp_chan = ieee80211_frequency_to_channel
2324                                         (request->channels[i]->center_freq);
2325                                 if (tmp_chan > CH_MAX_2G_CHANNEL) {
2326                                         if (allow_one_5g_channel)
2327                                                 allow_one_5g_channel = FALSE;
2328                                         else
2329                                                 continue;
2330                                 }
2331                                 if (j > CH_MAX_2G_CHANNEL) {
2332                                         WL_ERR(("Index %d exceeds max 2.4GHz channels %d"
2333                                                 " and previous 5G connected channel\n",
2334                                                 j, CH_MAX_2G_CHANNEL));
2335                                         break;
2336                                 }
2337                                 bcopy(request->channels[i], &tmp_channel_list[j],
2338                                         sizeof(struct ieee80211_channel));
2339                                 WL_SCAN(("channel of request->channels[%d]=%d\n", i, tmp_chan));
2340                                 j++;
2341                         }
2342                         if ((j > 0) && (j <= CH_MAX_2G_CHANNEL)) {
2343                                 for (i = 0; i < j; i++)
2344                                         bcopy(&tmp_channel_list[i], request->channels[i],
2345                                                 sizeof(struct ieee80211_channel));
2346
2347                                 request->n_channels = j;
2348                                 is_first_init_2g_scan = true;
2349                         }
2350                         else
2351                                 WL_ERR(("Invalid number of 2.4GHz channels %d\n", j));
2352
2353                         WL_SCAN(("request->n_channels=%d\n", request->n_channels));
2354 #else /* USE_INITIAL_SHORT_DWELL_TIME */
2355                         is_first_init_2g_scan = true;
2356 #endif /* USE_INITIAL_2G_SCAN */
2357                         g_first_broadcast_scan = false;
2358                 }
2359 #endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */
2360
2361                 /* if scan request is not empty parse scan request paramters */
2362                 if (request != NULL) {
2363                         n_channels = request->n_channels;
2364                         n_ssids = request->n_ssids;
2365                         if (n_channels % 2)
2366                                 /* If n_channels is odd, add a padd of u16 */
2367                                 params_size += sizeof(u16) * (n_channels + 1);
2368                         else
2369                                 params_size += sizeof(u16) * n_channels;
2370
2371                         /* Allocate space for populating ssids in wl_escan_params_t struct */
2372                         params_size += sizeof(struct wlc_ssid) * n_ssids;
2373                 }
2374                 params = (wl_escan_params_t *) kzalloc(params_size, GFP_KERNEL);
2375                 if (params == NULL) {
2376                         err = -ENOMEM;
2377                         goto exit;
2378                 }
2379                 wl_scan_prep(&params->params, request);
2380
2381 #if defined(USE_INITIAL_2G_SCAN) || defined(USE_INITIAL_SHORT_DWELL_TIME)
2382                 /* Override active_time to reduce scan time if it's first bradcast scan. */
2383                 if (is_first_init_2g_scan)
2384                         params->params.active_time = FIRST_SCAN_ACTIVE_DWELL_TIME_MS;
2385 #endif /* USE_INITIAL_2G_SCAN || USE_INITIAL_SHORT_DWELL_TIME */
2386
2387                 params->version = htod32(ESCAN_REQ_VERSION);
2388                 params->action =  htod16(action);
2389                 wl_escan_set_sync_id(params->sync_id, cfg);
2390                 wl_escan_set_type(cfg, WL_SCANTYPE_LEGACY);
2391                 if (params_size + sizeof("escan") >= WLC_IOCTL_MEDLEN) {
2392                         WL_ERR(("ioctl buffer length not sufficient\n"));
2393                         kfree(params);
2394                         err = -ENOMEM;
2395                         goto exit;
2396                 }
2397                 err = wldev_iovar_setbuf(ndev, "escan", params, params_size,
2398                         cfg->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
2399                 if (unlikely(err)) {
2400                         if (err == BCME_EPERM)
2401                                 /* Scan Not permitted at this point of time */
2402                                 WL_DBG((" Escan not permitted at this time (%d)\n", err));
2403                         else
2404                                 WL_ERR((" Escan set error (%d)\n", err));
2405                 }
2406                 kfree(params);
2407         }
2408         else if (p2p_is_on(cfg) && p2p_scan(cfg)) {
2409                 /* P2P SCAN TRIGGER */
2410                 s32 _freq = 0;
2411                 n_nodfs = 0;
2412                 if (request && request->n_channels) {
2413                         num_chans = request->n_channels;
2414                         WL_SCAN((" chann number : %d\n", num_chans));
2415                         default_chan_list = kzalloc(num_chans * sizeof(*default_chan_list),
2416                                 GFP_KERNEL);
2417                         if (default_chan_list == NULL) {
2418                                 WL_ERR(("channel list allocation failed \n"));
2419                                 err = -ENOMEM;
2420                                 goto exit;
2421                         }
2422                         if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) {
2423                                 list = (wl_uint32_list_t *) chan_buf;
2424                                 n_valid_chan = dtoh32(list->count);
2425                                 for (i = 0; i < num_chans; i++)
2426                                 {
2427                                         _freq = request->channels[i]->center_freq;
2428                                         channel = ieee80211_frequency_to_channel(_freq);
2429
2430                                         /* ignore DFS channels */
2431                                         if (request->channels[i]->flags &
2432 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2433                                                 (IEEE80211_CHAN_NO_IR
2434                                                 | IEEE80211_CHAN_RADAR))
2435 #else
2436                                                 (IEEE80211_CHAN_RADAR
2437                                                 | IEEE80211_CHAN_PASSIVE_SCAN))
2438 #endif
2439                                                 continue;
2440
2441                                         for (j = 0; j < n_valid_chan; j++) {
2442                                                 /* allows only supported channel on
2443                                                 *  current reguatory
2444                                                 */
2445                                                 if (channel == (dtoh32(list->element[j])))
2446                                                         default_chan_list[n_nodfs++] =
2447                                                                 channel;
2448                                         }
2449
2450                                 }
2451                         }
2452                         if (num_chans == SOCIAL_CHAN_CNT && (
2453                                                 (default_chan_list[0] == SOCIAL_CHAN_1) &&
2454                                                 (default_chan_list[1] == SOCIAL_CHAN_2) &&
2455                                                 (default_chan_list[2] == SOCIAL_CHAN_3))) {
2456                                 /* SOCIAL CHANNELS 1, 6, 11 */
2457                                 search_state = WL_P2P_DISC_ST_SEARCH;
2458                                 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2459                                 WL_INFORM(("P2P SEARCH PHASE START \n"));
2460                         } else if ((dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION)) &&
2461                                 (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP)) {
2462                                 /* If you are already a GO, then do SEARCH only */
2463                                 WL_INFORM(("Already a GO. Do SEARCH Only"));
2464                                 search_state = WL_P2P_DISC_ST_SEARCH;
2465                                 num_chans = n_nodfs;
2466                                 p2p_scan_purpose = P2P_SCAN_NORMAL;
2467
2468                         } else if (num_chans == 1) {
2469                                 p2p_scan_purpose = P2P_SCAN_CONNECT_TRY;
2470                         } else if (num_chans == SOCIAL_CHAN_CNT + 1) {
2471                         /* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by
2472                          * the supplicant
2473                          */
2474                                 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2475                         } else {
2476                                 WL_INFORM(("P2P SCAN STATE START \n"));
2477                                 num_chans = n_nodfs;
2478                                 p2p_scan_purpose = P2P_SCAN_NORMAL;
2479                         }
2480                 } else {
2481                         err = -EINVAL;
2482                         goto exit;
2483                 }
2484                 err = wl_cfgp2p_escan(cfg, ndev, cfg->active_scan, num_chans, default_chan_list,
2485                         search_state, action,
2486                         wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE), NULL,
2487                         p2p_scan_purpose);
2488
2489                 if (!err)
2490                         cfg->p2p->search_state = search_state;
2491
2492                 kfree(default_chan_list);
2493         }
2494 exit:
2495         if (unlikely(err)) {
2496                 /* Don't print Error incase of Scan suppress */
2497                 if ((err == BCME_EPERM) && cfg->scan_suppressed)
2498                         WL_DBG(("Escan failed: Scan Suppressed \n"));
2499                 else
2500                         WL_ERR(("error (%d)\n", err));
2501         }
2502         return err;
2503 }
2504
2505
2506 static s32
2507 wl_do_escan(struct bcm_cfg80211 *cfg, struct wiphy *wiphy, struct net_device *ndev,
2508         struct cfg80211_scan_request *request)
2509 {
2510         s32 err = BCME_OK;
2511         s32 passive_scan;
2512         s32 passive_scan_time;
2513         s32 passive_scan_time_org;
2514         wl_scan_results_t *results;
2515         WL_SCAN(("Enter \n"));
2516         mutex_lock(&cfg->usr_sync);
2517
2518         results = wl_escan_get_buf(cfg, FALSE);
2519         results->version = 0;
2520         results->count = 0;
2521         results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
2522
2523         cfg->escan_info.ndev = ndev;
2524         cfg->escan_info.wiphy = wiphy;
2525         cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
2526         passive_scan = cfg->active_scan ? 0 : 1;
2527         err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
2528                 &passive_scan, sizeof(passive_scan), true);
2529         if (unlikely(err)) {
2530                 WL_ERR(("error (%d)\n", err));
2531                 goto exit;
2532         }
2533
2534         if (passive_channel_skip) {
2535
2536                 err = wldev_ioctl(ndev, WLC_GET_SCAN_PASSIVE_TIME,
2537                         &passive_scan_time_org, sizeof(passive_scan_time_org), false);
2538                 if (unlikely(err)) {
2539                         WL_ERR(("== error (%d)\n", err));
2540                         goto exit;
2541                 }
2542
2543                 WL_SCAN(("PASSIVE SCAN time : %d \n", passive_scan_time_org));
2544
2545                 passive_scan_time = 0;
2546                 err = wldev_ioctl(ndev, WLC_SET_SCAN_PASSIVE_TIME,
2547                         &passive_scan_time, sizeof(passive_scan_time), true);
2548                 if (unlikely(err)) {
2549                         WL_ERR(("== error (%d)\n", err));
2550                         goto exit;
2551                 }
2552
2553                 WL_SCAN(("PASSIVE SCAN SKIPED!! (passive_channel_skip:%d) \n",
2554                         passive_channel_skip));
2555         }
2556
2557         TEGRA_SYSFS_HISTOGRAM_SCAN_REQUEST(ndev, request, sizeof(*request))
2558         err = wl_run_escan(cfg, ndev, request, WL_SCAN_ACTION_START);
2559
2560         if (passive_channel_skip) {
2561                 err = wldev_ioctl(ndev, WLC_SET_SCAN_PASSIVE_TIME,
2562                         &passive_scan_time_org, sizeof(passive_scan_time_org), true);
2563                 if (unlikely(err)) {
2564                         WL_ERR(("== error (%d)\n", err));
2565                         goto exit;
2566                 }
2567
2568                 WL_SCAN(("PASSIVE SCAN RECOVERED!! (passive_scan_time_org:%d) \n",
2569                         passive_scan_time_org));
2570         }
2571
2572 exit:
2573         mutex_unlock(&cfg->usr_sync);
2574         return err;
2575 }
2576
2577 static s32
2578 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
2579         struct cfg80211_scan_request *request,
2580         struct cfg80211_ssid *this_ssid)
2581 {
2582         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2583         struct cfg80211_ssid *ssids;
2584         struct ether_addr primary_mac;
2585         bool p2p_ssid;
2586 #ifdef WL11U
2587         bcm_tlv_t *interworking_ie;
2588 #endif
2589         s32 err = 0;
2590         s32 bssidx = -1;
2591         s32 i;
2592
2593         unsigned long flags;
2594         static s32 busy_count = 0;
2595 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
2596         struct net_device *remain_on_channel_ndev = NULL;
2597 #endif
2598
2599         dhd_pub_t *dhd;
2600
2601         dhd = (dhd_pub_t *)(cfg->pub);
2602         /*
2603          * Hostapd triggers scan before starting automatic channel selection
2604          * also Dump stats IOVAR scans each channel hence returning from here.
2605          */
2606         if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
2607 #ifdef WL_SUPPORT_ACS
2608                 WL_INFORM(("Scan Command at SoftAP mode\n"));
2609                 return 0;
2610 #else
2611                 WL_ERR(("Invalid Scan Command at SoftAP mode\n"));
2612                 return -EINVAL;
2613 #endif /* WL_SUPPORT_ACS */
2614         }
2615
2616         ndev = ndev_to_wlc_ndev(ndev, cfg);
2617
2618         if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg)) {
2619                 WL_ERR(("Sending Action Frames. Try it again.\n"));
2620                 return -EAGAIN;
2621         }
2622
2623         WL_DBG(("Enter wiphy (%p)\n", wiphy));
2624         if (wl_get_drv_status_all(cfg, SCANNING)) {
2625                 if (cfg->scan_request == NULL) {
2626                         wl_clr_drv_status_all(cfg, SCANNING);
2627                         WL_DBG(("<<<<<<<<<<<Force Clear Scanning Status>>>>>>>>>>>\n"));
2628                 } else {
2629                         WL_ERR(("Scanning already\n"));
2630                         return -EAGAIN;
2631                 }
2632         }
2633         if (wl_get_drv_status(cfg, SCAN_ABORTING, ndev)) {
2634                 WL_ERR(("Scanning being aborted\n"));
2635                 return -EAGAIN;
2636         }
2637         if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) {
2638                 WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n"));
2639                 return -EOPNOTSUPP;
2640         }
2641 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
2642         remain_on_channel_ndev = wl_cfg80211_get_remain_on_channel_ndev(cfg);
2643         if (remain_on_channel_ndev) {
2644                 WL_DBG(("Remain_on_channel bit is set, somehow it didn't get cleared\n"));
2645                 wl_notify_escan_complete(cfg, remain_on_channel_ndev, true, true);
2646         }
2647 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
2648
2649
2650         /* Arm scan timeout timer */
2651         mod_timer(&cfg->scan_timeout, jiffies + msecs_to_jiffies(WL_SCAN_TIMER_INTERVAL_MS));
2652         if (request) {          /* scan bss */
2653                 ssids = request->ssids;
2654                 p2p_ssid = false;
2655                 for (i = 0; i < request->n_ssids; i++) {
2656                         if (ssids[i].ssid_len &&
2657                                 IS_P2P_SSID(ssids[i].ssid, ssids[i].ssid_len)) {
2658                                 p2p_ssid = true;
2659                                 break;
2660                         }
2661                 }
2662                 if (p2p_ssid) {
2663                         if (cfg->p2p_supported) {
2664                                 /* p2p scan trigger */
2665                                 if (p2p_on(cfg) == false) {
2666                                         /* p2p on at the first time */
2667                                         p2p_on(cfg) = true;
2668                                         wl_cfgp2p_set_firm_p2p(cfg);
2669                                         get_primary_mac(cfg, &primary_mac);
2670                                         wl_cfgp2p_generate_bss_mac(&primary_mac,
2671                                                 &cfg->p2p->dev_addr, &cfg->p2p->int_addr);
2672 #if defined(P2P_IE_MISSING_FIX)
2673                                         cfg->p2p_prb_noti = false;
2674 #endif
2675                                 }
2676                                 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
2677                                 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
2678                                 p2p_scan(cfg) = true;
2679                         }
2680                 } else {
2681                         /* legacy scan trigger
2682                          * So, we have to disable p2p discovery if p2p discovery is on
2683                          */
2684                         if (cfg->p2p_supported) {
2685                                 p2p_scan(cfg) = false;
2686                                 /* If Netdevice is not equals to primary and p2p is on
2687                                 *  , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
2688                                 */
2689
2690                                 if (p2p_scan(cfg) == false) {
2691                                         if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
2692                                                 err = wl_cfgp2p_discover_enable_search(cfg,
2693                                                 false);
2694                                                 if (unlikely(err)) {
2695                                                         goto scan_out;
2696                                                 }
2697
2698                                         }
2699                                 }
2700                         }
2701                         if (!cfg->p2p_supported || !p2p_scan(cfg)) {
2702
2703                                 if (wl_cfgp2p_find_idx(cfg, ndev, &bssidx) != BCME_OK) {
2704                                         WL_ERR(("Find p2p index from ndev(%p) failed\n",
2705                                                 ndev));
2706                                         err = BCME_ERROR;
2707                                         goto scan_out;
2708                                 }
2709 #ifdef WL11U
2710 if (bcmdhd_wl11u) {
2711                                 if ((interworking_ie = wl_cfg80211_find_interworking_ie(
2712                                         (u8 *)request->ie, request->ie_len)) != NULL) {
2713                                         err = wl_cfg80211_add_iw_ie(cfg, ndev, bssidx,
2714                                                VNDR_IE_CUSTOM_FLAG, interworking_ie->id,
2715                                                interworking_ie->data, interworking_ie->len);
2716
2717                                         if (unlikely(err)) {
2718                                                 goto scan_out;
2719                                         }
2720                                 } else if (cfg->iw_ie_len != 0) {
2721                                 /* we have to clear IW IE and disable gratuitous APR */
2722                                         wl_cfg80211_add_iw_ie(cfg, ndev, bssidx,
2723                                                 VNDR_IE_CUSTOM_FLAG,
2724                                                 DOT11_MNG_INTERWORKING_ID,
2725                                                 0, 0);
2726
2727                                         wldev_iovar_setint_bsscfg(ndev, "grat_arp", 0,
2728                                                 bssidx);
2729                                         cfg->wl11u = FALSE;
2730                                         cfg->iw_ie_len = 0;
2731                                         memset(cfg->iw_ie, 0, IW_IES_MAX_BUF_LEN);
2732                                         /* we don't care about error */
2733                                 }
2734 }
2735 #endif /* WL11U */
2736                                 err = wl_cfgp2p_set_management_ie(cfg, ndev, bssidx,
2737                                         VNDR_IE_PRBREQ_FLAG, (u8 *)request->ie,
2738                                         request->ie_len);
2739
2740                                 if (unlikely(err)) {
2741                                         goto scan_out;
2742                                 }
2743
2744                         }
2745                 }
2746         } else {                /* scan in ibss */
2747                 ssids = this_ssid;
2748         }
2749
2750         if (request && !p2p_scan(cfg)) {
2751                 WL_TRACE_HW4(("START SCAN\n"));
2752         }
2753
2754         cfg->scan_request = request;
2755         wl_set_drv_status(cfg, SCANNING, ndev);
2756
2757         if (cfg->p2p_supported) {
2758                 if (p2p_on(cfg) && p2p_scan(cfg)) {
2759
2760                         /* find my listen channel */
2761                         cfg->afx_hdl->my_listen_chan =
2762                                 wl_find_listen_channel(cfg, request->ie,
2763                                 request->ie_len);
2764                         err = wl_cfgp2p_enable_discovery(cfg, ndev,
2765                         request->ie, request->ie_len);
2766
2767                         if (unlikely(err)) {
2768                                 goto scan_out;
2769                         }
2770                 }
2771         }
2772         err = wl_do_escan(cfg, wiphy, ndev, request);
2773         if (likely(!err))
2774                 goto scan_success;
2775         else
2776                 goto scan_out;
2777
2778 scan_success:
2779         busy_count = 0;
2780
2781         return 0;
2782
2783 scan_out:
2784         if (err == BCME_BUSY || err == BCME_NOTREADY) {
2785                 WL_ERR(("Scan err = (%d), busy?%d", err, -EBUSY));
2786                 err = -EBUSY;
2787         }
2788
2789 #define SCAN_EBUSY_RETRY_LIMIT 1
2790         if (err == -EBUSY) {
2791                 if (busy_count++ > SCAN_EBUSY_RETRY_LIMIT) {
2792                         struct ether_addr bssid;
2793                         s32 ret = 0;
2794                         busy_count = 0;
2795                         WL_ERR(("Unusual continuous EBUSY error, %d %d %d %d %d %d %d %d %d\n",
2796                                 wl_get_drv_status(cfg, SCANNING, ndev),
2797                                 wl_get_drv_status(cfg, SCAN_ABORTING, ndev),
2798                                 wl_get_drv_status(cfg, CONNECTING, ndev),
2799                                 wl_get_drv_status(cfg, CONNECTED, ndev),
2800                                 wl_get_drv_status(cfg, DISCONNECTING, ndev),
2801                                 wl_get_drv_status(cfg, AP_CREATING, ndev),
2802                                 wl_get_drv_status(cfg, AP_CREATED, ndev),
2803                                 wl_get_drv_status(cfg, SENDING_ACT_FRM, ndev),
2804                                 wl_get_drv_status(cfg, SENDING_ACT_FRM, ndev)));
2805
2806                         bzero(&bssid, sizeof(bssid));
2807                         if ((ret = wldev_ioctl(ndev, WLC_GET_BSSID,
2808                                 &bssid, ETHER_ADDR_LEN, false)) == 0)
2809                                 WL_ERR(("FW is connected with " MACDBG "/n",
2810                                         MAC2STRDBG(bssid.octet)));
2811                         else
2812                                 WL_ERR(("GET BSSID failed with %d\n", ret));
2813
2814                         wl_cfg80211_scan_abort(cfg);
2815
2816                 }
2817         } else {
2818                 busy_count = 0;
2819         }
2820
2821         wl_clr_drv_status(cfg, SCANNING, ndev);
2822         if (timer_pending(&cfg->scan_timeout))
2823                 del_timer_sync(&cfg->scan_timeout);
2824         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
2825 #ifdef CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA
2826         TEGRA_SCAN_DONE(cfg->scan_request, true)
2827         skip_cfg80211_scan_done: ;
2828 #endif
2829         cfg->scan_request = NULL;
2830         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
2831
2832         return err;
2833 }
2834
2835 #if defined(WL_CFG80211_P2P_DEV_IF)
2836 static s32
2837 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
2838 #else
2839 static s32
2840 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
2841         struct cfg80211_scan_request *request)
2842 #endif /* WL_CFG80211_P2P_DEV_IF */
2843 {
2844         s32 err = 0;
2845         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2846 #if defined(WL_CFG80211_P2P_DEV_IF)
2847         struct net_device *ndev = wdev_to_wlc_ndev(request->wdev, cfg);
2848 #endif /* WL_CFG80211_P2P_DEV_IF */
2849
2850         WL_DBG(("Enter \n"));
2851         RETURN_EIO_IF_NOT_UP(cfg);
2852
2853 #ifdef P2PONEINT
2854         ndev = bcmcfg_to_prmry_ndev(cfg);
2855         WL_DBG(("scan use  [dev name %s ] \n", ndev->name));
2856 #endif
2857
2858 #ifdef CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA
2859         {
2860                 int status = wifi_scan_request(wl_cfg80211_scan,
2861                         wiphy, ndev, request);
2862                 if (status > 0) {
2863                         WIFI_SCAN_DEBUG("%s: substituted wifi scan policy"
2864                                 " with %d rule(s)\n",
2865                                 __func__, status);
2866                         return (0);
2867                 } else if (status < 0) {
2868                         WIFI_SCAN_DEBUG("%s: wifi scan policy active\n",
2869                                 __func__);
2870                         return (status);
2871                 }
2872                 /* continue scan request if status is 0 */
2873         }
2874 #endif
2875
2876         err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
2877         if (unlikely(err)) {
2878                 if ((err == BCME_EPERM) && cfg->scan_suppressed)
2879                         WL_DBG(("scan not permitted at this time (%d)\n", err));
2880                 else
2881                         WL_ERR(("scan error (%d)\n", err));
2882                 return err;
2883         }
2884
2885         return err;
2886 }
2887
2888 static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
2889 {
2890         s32 err = 0;
2891
2892         err = wldev_iovar_setint(dev, "rtsthresh", rts_threshold);
2893         if (unlikely(err)) {
2894                 WL_ERR(("Error (%d)\n", err));
2895                 return err;
2896         }
2897         return err;
2898 }
2899
2900 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
2901 {
2902         s32 err = 0;
2903
2904         err = wldev_iovar_setint_bsscfg(dev, "fragthresh", frag_threshold, 0);
2905         if (unlikely(err)) {
2906                 WL_ERR(("Error (%d)\n", err));
2907                 return err;
2908         }
2909         return err;
2910 }
2911
2912 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
2913 {
2914         s32 err = 0;
2915         u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
2916
2917         retry = htod32(retry);
2918         err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), true);
2919         if (unlikely(err)) {
2920                 WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
2921                 return err;
2922         }
2923         return err;
2924 }
2925
2926 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
2927 {
2928         struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy);
2929         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
2930         s32 err = 0;
2931
2932         RETURN_EIO_IF_NOT_UP(cfg);
2933         WL_DBG(("Enter\n"));
2934         if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
2935                 (cfg->conf->rts_threshold != wiphy->rts_threshold)) {
2936                 cfg->conf->rts_threshold = wiphy->rts_threshold;
2937                 err = wl_set_rts(ndev, cfg->conf->rts_threshold);
2938                 if (!err)
2939                         return err;
2940         }
2941         if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
2942                 (cfg->conf->frag_threshold != wiphy->frag_threshold)) {
2943                 cfg->conf->frag_threshold = wiphy->frag_threshold;
2944                 err = wl_set_frag(ndev, cfg->conf->frag_threshold);
2945                 if (!err)
2946                         return err;
2947         }
2948         if (changed & WIPHY_PARAM_RETRY_LONG &&
2949                 (cfg->conf->retry_long != wiphy->retry_long)) {
2950                 cfg->conf->retry_long = wiphy->retry_long;
2951                 err = wl_set_retry(ndev, cfg->conf->retry_long, true);
2952                 if (!err)
2953                         return err;
2954         }
2955         if (changed & WIPHY_PARAM_RETRY_SHORT &&
2956                 (cfg->conf->retry_short != wiphy->retry_short)) {
2957                 cfg->conf->retry_short = wiphy->retry_short;
2958                 err = wl_set_retry(ndev, cfg->conf->retry_short, false);
2959                 if (!err) {
2960                         return err;
2961                 }
2962         }
2963
2964         return err;
2965 }
2966 static chanspec_t
2967 channel_to_chanspec(struct wiphy *wiphy, struct net_device *dev, u32 channel, u32 bw_cap)
2968 {
2969         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2970         u8 *buf = NULL;
2971         wl_uint32_list_t *list;
2972         int err = BCME_OK;
2973         chanspec_t c = 0, ret_c = 0;
2974         int bw = 0, tmp_bw = 0;
2975         int i;
2976         u32 tmp_c;
2977         u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
2978 #define LOCAL_BUF_SIZE  1024
2979         buf = (u8 *) kzalloc(LOCAL_BUF_SIZE, kflags);
2980         if (!buf) {
2981                 WL_ERR(("buf memory alloc failed\n"));
2982                 goto exit;
2983         }
2984         list = (wl_uint32_list_t *)(void *)buf;
2985         list->count = htod32(WL_NUMCHANSPECS);
2986         err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
2987                 0, buf, LOCAL_BUF_SIZE, 0, &cfg->ioctl_buf_sync);
2988         if (err != BCME_OK) {
2989                 WL_ERR(("get chanspecs failed with %d\n", err));
2990                 goto exit;
2991         }
2992         for (i = 0; i < dtoh32(list->count); i++) {
2993                 c = dtoh32(list->element[i]);
2994                 if (channel <= CH_MAX_2G_CHANNEL) {
2995                         if (!CHSPEC_IS20(c))
2996                                 continue;
2997                         if (channel == CHSPEC_CHANNEL(c)) {
2998                                 ret_c = c;
2999                                 bw = 20;
3000                                 goto exit;
3001                         }
3002                 }
3003                 tmp_c = wf_chspec_ctlchan(c);
3004                 tmp_bw = bw2cap[CHSPEC_BW(c) >> WL_CHANSPEC_BW_SHIFT];
3005                 if (tmp_c != channel)
3006                         continue;
3007
3008                 if ((tmp_bw > bw) && (tmp_bw <= bw_cap)) {
3009                         bw = tmp_bw;
3010                         ret_c = c;
3011                         if (bw == bw_cap)
3012                                 goto exit;
3013                 }
3014         }
3015 exit:
3016         if (buf)
3017                 kfree(buf);
3018 #undef LOCAL_BUF_SIZE
3019         WL_INFORM(("return chanspec %x %d\n", ret_c, bw));
3020         return ret_c;
3021 }
3022
3023 void
3024 wl_cfg80211_ibss_vsie_set_buffer(vndr_ie_setbuf_t *ibss_vsie, int ibss_vsie_len)
3025 {
3026         struct bcm_cfg80211 *cfg = g_bcm_cfg;
3027
3028         if (cfg != NULL && ibss_vsie != NULL) {
3029                 if (cfg->ibss_vsie != NULL) {
3030                         kfree(cfg->ibss_vsie);
3031                 }
3032                 cfg->ibss_vsie = ibss_vsie;
3033                 cfg->ibss_vsie_len = ibss_vsie_len;
3034         }
3035 }
3036
3037 static void
3038 wl_cfg80211_ibss_vsie_free(struct bcm_cfg80211 *cfg)
3039 {
3040         /* free & initiralize VSIE (Vendor Specific IE) */
3041         if (cfg->ibss_vsie != NULL) {
3042                 kfree(cfg->ibss_vsie);
3043                 cfg->ibss_vsie = NULL;
3044                 cfg->ibss_vsie_len = 0;
3045         }
3046 }
3047
3048 s32
3049 wl_cfg80211_ibss_vsie_delete(struct net_device *dev)
3050 {
3051         struct bcm_cfg80211 *cfg = g_bcm_cfg;
3052         char *ioctl_buf = NULL;
3053         s32 ret = BCME_OK;
3054
3055         if (cfg != NULL && cfg->ibss_vsie != NULL) {
3056                 ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
3057                 if (!ioctl_buf) {
3058                         WL_ERR(("ioctl memory alloc failed\n"));
3059                         return -ENOMEM;
3060                 }
3061
3062                 /* change the command from "add" to "del" */
3063                 strncpy(cfg->ibss_vsie->cmd, "del", VNDR_IE_CMD_LEN - 1);
3064                 cfg->ibss_vsie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
3065
3066                 ret = wldev_iovar_setbuf(dev, "ie",
3067                         cfg->ibss_vsie, cfg->ibss_vsie_len,
3068                         ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
3069                 WL_ERR(("ret=%d\n", ret));
3070
3071                 if (ret == BCME_OK) {
3072                         /* free & initiralize VSIE */
3073                         kfree(cfg->ibss_vsie);
3074                         cfg->ibss_vsie = NULL;
3075                         cfg->ibss_vsie_len = 0;
3076                 }
3077
3078                 if (ioctl_buf) {
3079                         kfree(ioctl_buf);
3080                 }
3081         }
3082
3083         return ret;
3084 }
3085
3086 #ifdef WLAIBSS_MCHAN
3087 static bcm_struct_cfgdev*
3088 bcm_cfg80211_add_ibss_if(struct wiphy *wiphy, char *name)
3089 {
3090         int err = 0;
3091         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3092         struct wireless_dev* wdev = NULL;
3093         struct net_device *new_ndev = NULL;
3094         struct net_device *primary_ndev = NULL;
3095         s32 timeout;
3096         wl_aibss_if_t aibss_if;
3097         wl_if_event_info *event = NULL;
3098
3099         if (cfg->ibss_cfgdev != NULL) {
3100                 WL_ERR(("IBSS interface %s already exists\n", name));
3101                 return NULL;
3102         }
3103
3104         WL_ERR(("Try to create IBSS interface %s\n", name));
3105         primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3106         /* generate a new MAC address for the IBSS interface */
3107         get_primary_mac(cfg, &cfg->ibss_if_addr);
3108         cfg->ibss_if_addr.octet[4] ^= 0x40;
3109         memset(&aibss_if, sizeof(aibss_if), 0);
3110         memcpy(&aibss_if.addr, &cfg->ibss_if_addr, sizeof(aibss_if.addr));
3111         aibss_if.chspec = 0;
3112         aibss_if.len = sizeof(aibss_if);
3113
3114         cfg->bss_pending_op = TRUE;
3115         memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
3116         err = wldev_iovar_setbuf(primary_ndev, "aibss_ifadd", &aibss_if,
3117                 sizeof(aibss_if), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, NULL);
3118         if (err) {
3119                 WL_ERR(("IOVAR aibss_ifadd failed with error %d\n", err));
3120                 goto fail;
3121         }
3122         timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
3123                 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
3124         if (timeout <= 0 || cfg->bss_pending_op)
3125                 goto fail;
3126
3127         event = &cfg->if_event_info;
3128         strncpy(event->name, name, IFNAMSIZ - 1);
3129         /* By calling wl_cfg80211_allocate_if (dhd_allocate_if eventually) we give the control
3130          * over this net_device interface to dhd_linux, hence the interface is managed by dhd_liux
3131          * and will be freed by dhd_detach unless it gets unregistered before that. The
3132          * wireless_dev instance new_ndev->ieee80211_ptr associated with this net_device will
3133          * be freed by wl_dealloc_netinfo
3134          */
3135         new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx, event->name,
3136                 event->mac, event->bssidx);
3137         if (new_ndev == NULL)
3138                 goto fail;
3139         wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
3140         if (wdev == NULL)
3141                 goto fail;
3142         wdev->wiphy = wiphy;
3143         wdev->iftype = NL80211_IFTYPE_ADHOC;
3144         wdev->netdev = new_ndev;
3145         new_ndev->ieee80211_ptr = wdev;
3146         SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy));
3147
3148         /* rtnl lock must have been acquired, if this is not the case, wl_cfg80211_register_if
3149         * needs to be modified to take one parameter (bool need_rtnl_lock)
3150          */
3151         ASSERT_RTNL();
3152         if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev) != BCME_OK)
3153                 goto fail;
3154
3155         wl_alloc_netinfo(cfg, new_ndev, wdev, WL_MODE_IBSS, PM_ENABLE);
3156         cfg->ibss_cfgdev = ndev_to_cfgdev(new_ndev);
3157         WL_ERR(("IBSS interface %s created\n", new_ndev->name));
3158         return cfg->ibss_cfgdev;
3159
3160 fail:
3161         WL_ERR(("failed to create IBSS interface %s \n", name));
3162         cfg->bss_pending_op = FALSE;
3163         if (new_ndev)
3164                 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev);
3165         if (wdev)
3166                 kfree(wdev);
3167         return NULL;
3168 }
3169
3170 static s32
3171 bcm_cfg80211_del_ibss_if(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
3172 {
3173         int err = 0;
3174         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3175         struct net_device *ndev = NULL;
3176         struct net_device *primary_ndev = NULL;
3177         s32 timeout;
3178
3179         if (!cfgdev || cfg->ibss_cfgdev != cfgdev || ETHER_ISNULLADDR(&cfg->ibss_if_addr.octet))
3180                 return -EINVAL;
3181         ndev = (struct net_device *)cfgdev_to_ndev(cfg->ibss_cfgdev);
3182         primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3183
3184         cfg->bss_pending_op = TRUE;
3185         memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
3186         err = wldev_iovar_setbuf(primary_ndev, "aibss_ifdel", &cfg->ibss_if_addr,
3187                 sizeof(cfg->ibss_if_addr), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, NULL);
3188         if (err) {
3189                 WL_ERR(("IOVAR aibss_ifdel failed with error %d\n", err));
3190                 goto fail;
3191         }
3192         timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
3193                 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
3194         if (timeout <= 0 || cfg->bss_pending_op) {
3195                 WL_ERR(("timeout in waiting IF_DEL event\n"));
3196                 goto fail;
3197         }
3198
3199         wl_cfg80211_remove_if(cfg, cfg->if_event_info.ifidx, ndev);
3200         cfg->ibss_cfgdev = NULL;
3201         return 0;
3202
3203 fail:
3204         cfg->bss_pending_op = FALSE;
3205         return -1;
3206 }
3207 #endif /* WLAIBSS_MCHAN */
3208
3209 s32
3210 wl_cfg80211_interface_ops(struct bcm_cfg80211 *cfg,
3211         struct net_device *ndev, s32 bsscfg_idx,
3212         enum nl80211_iftype iface_type, s32 del, u8 *addr)
3213 {
3214         wl_interface_create_t iface;
3215         s32 ret;
3216         wl_interface_info_t *info;
3217
3218         bzero(&iface, sizeof(wl_interface_create_t));
3219
3220         iface.ver = WL_INTERFACE_CREATE_VER;
3221
3222         if (iface_type == NL80211_IFTYPE_AP)
3223                 iface.flags = WL_INTERFACE_CREATE_AP;
3224         else
3225                 iface.flags = WL_INTERFACE_CREATE_STA;
3226
3227         if (del) {
3228                 ret = wldev_iovar_setbuf(ndev, "interface_remove",
3229                         NULL, 0, cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
3230         } else {
3231                 if (addr) {
3232                         memcpy(&iface.mac_addr.octet, addr, ETH_ALEN);
3233                         iface.flags |= WL_INTERFACE_MAC_USE;
3234                 }
3235                 ret = wldev_iovar_getbuf(ndev, "interface_create",
3236                         &iface, sizeof(wl_interface_create_t),
3237                         cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
3238                 if (ret == 0) {
3239                         /* success */
3240                         info = (wl_interface_info_t *)cfg->ioctl_buf;
3241                         WL_DBG(("wl interface create success!! bssidx:%d \n",
3242                                 info->bsscfgidx));
3243                         ret = info->bsscfgidx;
3244                 }
3245         }
3246
3247         if (ret < 0)
3248                 WL_ERR(("Interface %s failed!! ret %d\n",
3249                         del ? "remove" : "create", ret));
3250
3251         return ret;
3252 }
3253
3254 #if defined(DUAL_STA) || defined(DUAL_STA_STATIC_IF)
3255 s32
3256 wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg,
3257         struct net_device *ndev, s32 bsscfg_idx,
3258         enum nl80211_iftype iface_type, s32 del, u8 *addr)
3259 {
3260         s32 ret = BCME_OK;
3261         s32 val = 0;
3262
3263         struct {
3264                 s32 cfg;
3265                 s32 val;
3266                 struct ether_addr ea;
3267         } bss_setbuf;
3268
3269         WL_INFORM(("iface_type:%d del:%d \n", iface_type, del));
3270
3271         bzero(&bss_setbuf, sizeof(bss_setbuf));
3272
3273         /* AP=3, STA=2, up=1, down=0, val=-1 */
3274         if (del) {
3275                 val = -1;
3276         } else if (iface_type == NL80211_IFTYPE_AP) {
3277                 /* AP Interface */
3278                 WL_DBG(("Adding AP Interface \n"));
3279                 val = 3;
3280         } else if (iface_type == NL80211_IFTYPE_STATION) {
3281                 WL_DBG(("Adding STA Interface \n"));
3282                 val = 2;
3283         } else {
3284                 WL_ERR((" add_del_bss NOT supported for IFACE type:0x%x", iface_type));
3285                 return -EINVAL;
3286         }
3287
3288         bss_setbuf.cfg = htod32(bsscfg_idx);
3289         bss_setbuf.val = htod32(val);
3290
3291         if (addr) {
3292                 memcpy(&bss_setbuf.ea.octet, addr, ETH_ALEN);
3293         }
3294
3295         ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
3296                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
3297         if (ret != 0)
3298                 WL_ERR(("'bss %d' failed with %d\n", val, ret));
3299
3300         return ret;
3301 }
3302
3303 /* Create a Generic Network Interface and initialize it depending up on
3304  * the interface type
3305  */
3306 bcm_struct_cfgdev*
3307 wl_cfg80211_create_iface(struct wiphy *wiphy,
3308         enum nl80211_iftype iface_type,
3309         u8 *mac_addr, const char *name)
3310 {
3311         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3312         struct net_device *new_ndev = NULL;
3313         struct net_device *primary_ndev = NULL;
3314         s32 ret = BCME_OK;
3315         s32 bsscfg_idx = 1;
3316         u32 timeout;
3317         wl_if_event_info *event = NULL;
3318         struct wireless_dev *wdev = NULL;
3319         u8 addr[ETH_ALEN];
3320
3321         WL_DBG(("Enter\n"));
3322
3323         if (!name) {
3324                 WL_ERR(("Interface name not provided\n"));
3325                 return NULL;
3326         }
3327
3328         primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3329
3330         if (likely(!mac_addr)) {
3331                 /* Use primary MAC with the locally administered bit for the Secondary STA I/F */
3332                 memcpy(addr, primary_ndev->dev_addr, ETH_ALEN);
3333                 addr[0] |= 0x02;
3334         } else {
3335                 /* Use the application provided mac address (if any) */
3336                 memcpy(addr, mac_addr, ETH_ALEN);
3337         }
3338
3339         if ((iface_type != NL80211_IFTYPE_STATION) && (iface_type != NL80211_IFTYPE_AP)) {
3340                 WL_ERR(("IFACE type:%d not supported. STA "
3341                                         "or AP IFACE is only supported\n", iface_type));
3342                 return NULL;
3343         }
3344
3345         cfg->bss_pending_op = TRUE;
3346         memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
3347
3348         /* De-initialize the p2p discovery interface, if operational */
3349         if (p2p_is_on(cfg)) {
3350                 WL_DBG(("Disabling P2P Discovery Interface \n"));
3351 #ifdef WL_CFG80211_P2P_DEV_IF
3352                 ret = wl_cfg80211_scan_stop(bcmcfg_to_p2p_wdev(cfg));
3353 #else
3354                 ret = wl_cfg80211_scan_stop(cfg->p2p_net);
3355 #endif
3356                 if (unlikely(ret < 0)) {
3357                         CFGP2P_ERR(("P2P scan stop failed, ret=%d\n", ret));
3358                 }
3359
3360                 wl_cfgp2p_disable_discovery(cfg);
3361                 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0;
3362                 p2p_on(cfg) = false;
3363         }
3364
3365         /*
3366          * Intialize the firmware I/F.
3367          */
3368         ret = wl_cfg80211_interface_ops(cfg, primary_ndev, bsscfg_idx,
3369                 NL80211_IFTYPE_STATION, 0, addr);
3370         if (ret == BCME_UNSUPPORTED) {
3371             /* Use bssidx 1 by default */
3372                 if ((ret = wl_cfg80211_add_del_bss(cfg, primary_ndev,
3373                         bsscfg_idx, iface_type, 0, addr)) < 0) {
3374                         return NULL;
3375                 }
3376         } else if (ret < 0) {
3377             WL_ERR(("Interface create failed!! ret:%d \n", ret));
3378             goto fail;
3379         } else {
3380             /* Success */
3381             bsscfg_idx = ret;
3382         }
3383
3384         /*
3385          * Wait till the firmware send a confirmation event back.
3386          */
3387         WL_DBG(("Wait for the FW I/F Event\n"));
3388         timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
3389                 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
3390         if (timeout <= 0 || cfg->bss_pending_op) {
3391                 WL_ERR(("ADD_IF event, didn't come. Return \n"));
3392                 goto fail;
3393         }
3394
3395         /*
3396          * Since FW operation is successful,we can go ahead with the
3397          * the host interface creation.
3398          */
3399         event = &cfg->if_event_info;
3400         strncpy(event->name, name, IFNAMSIZ - 1);
3401         new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx,
3402                 event->name, addr, event->bssidx);
3403         if (!new_ndev) {
3404                 WL_ERR(("I/F allocation failed! \n"));
3405                 goto fail;
3406         } else
3407                 WL_DBG(("I/F allocation succeeded! ifidx:0x%x bssidx:0x%x \n",
3408                  event->ifidx, event->bssidx));
3409
3410         wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
3411         if (!wdev) {
3412                 WL_ERR(("wireless_dev alloc failed! \n"));
3413                 goto fail;
3414         }
3415
3416         wdev->wiphy = wiphy;
3417         wdev->iftype = iface_type;
3418         new_ndev->ieee80211_ptr = wdev;
3419         SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy));
3420
3421         /* RTNL lock must have been acquired. */
3422         ASSERT_RTNL();
3423
3424         /* Set the locally administed mac addr, if not applied already */
3425         if (memcmp(addr, event->mac, ETH_ALEN) != 0) {
3426                 ret = wldev_iovar_setbuf_bsscfg(primary_ndev, "cur_etheraddr", addr, ETH_ALEN,
3427                         cfg->ioctl_buf, WLC_IOCTL_MAXLEN, event->bssidx, &cfg->ioctl_buf_sync);
3428                 if (unlikely(ret)) {
3429                                 WL_ERR(("set cur_etheraddr Error (%d)\n", ret));
3430                                 goto fail;
3431                 }
3432                 memcpy(new_ndev->dev_addr, addr, ETH_ALEN);
3433         }
3434
3435         if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev) != BCME_OK) {
3436                 WL_ERR(("IFACE register failed \n"));
3437                 goto fail;
3438         }
3439
3440         /* Initialize with the station mode params */
3441         wl_alloc_netinfo(cfg, new_ndev, wdev,
3442                 (iface_type == NL80211_IFTYPE_STATION) ?
3443                 WL_MODE_BSS : WL_MODE_AP, PM_ENABLE);
3444         cfg->bss_cfgdev = ndev_to_cfgdev(new_ndev);
3445         cfg->cfgdev_bssidx = event->bssidx;
3446
3447         WL_DBG(("Host Network Interface for Secondary I/F created"));
3448
3449         return cfg->bss_cfgdev;
3450
3451 fail:
3452         cfg->bss_pending_op = FALSE;
3453         if (new_ndev)
3454                 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev);
3455         if (wdev)
3456                 kfree(wdev);
3457
3458         return NULL;
3459 }
3460
3461 s32
3462 wl_cfg80211_del_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
3463 {
3464         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3465         struct net_device *ndev = NULL;
3466         struct net_device *primary_ndev = NULL;
3467         s32 ret = BCME_OK;
3468         s32 bsscfg_idx = 1;
3469         u32 timeout;
3470         u32 ifidx;
3471         enum nl80211_iftype iface_type = NL80211_IFTYPE_STATION;
3472
3473         WL_DBG(("Enter\n"));
3474
3475         if (!cfg->bss_cfgdev)
3476                 return 0;
3477
3478         /* If any scan is going on, abort it */
3479         if (wl_get_drv_status_all(cfg, SCANNING)) {
3480                 WL_DBG(("Scan in progress. Aborting the scan!\n"));
3481                 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
3482         }
3483
3484         ndev = (struct net_device *)cfgdev_to_ndev(cfg->bss_cfgdev);
3485         primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3486
3487         cfg->bss_pending_op = TRUE;
3488         memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
3489
3490         /* Delete the firmware interface */
3491         ret = wl_cfg80211_interface_ops(cfg, ndev, cfg->cfgdev_bssidx,
3492                 NL80211_IFTYPE_STATION, 1, NULL);
3493         if (ret == BCME_UNSUPPORTED) {
3494                 if ((ret = wl_cfg80211_add_del_bss(cfg, ndev,
3495                         bsscfg_idx, iface_type, true, NULL)) < 0) {
3496                         WL_ERR(("DEL bss failed ret:%d \n", ret));
3497                         return ret;
3498                 }
3499         } else if (ret < 0) {
3500             WL_ERR(("Interface DEL failed ret:%d \n", ret));
3501             return ret;
3502         }
3503
3504         timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
3505                 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
3506         if (timeout <= 0 || cfg->bss_pending_op) {
3507                 WL_ERR(("timeout in waiting IF_DEL event\n"));
3508         }
3509         ifidx = dhd_net2idx(((struct dhd_pub *)(cfg->pub))->info, ndev);
3510         wl_cfg80211_remove_if(cfg, ifidx, ndev);
3511         cfg->bss_cfgdev = NULL;
3512         cfg->cfgdev_bssidx = -1;
3513         cfg->bss_pending_op = FALSE;
3514
3515         WL_DBG(("IF_DEL Done.\n"));
3516
3517         return ret;
3518 }
3519 #endif /* defined(DUAL_STA) || defined(DUAL_STA_STATIC_IF) */
3520
3521 static s32
3522 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
3523         struct cfg80211_ibss_params *params)
3524 {
3525         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3526         struct cfg80211_bss *bss;
3527         struct ieee80211_channel *chan;
3528         struct wl_join_params join_params;
3529         int scan_suppress;
3530         struct cfg80211_ssid ssid;
3531         s32 scan_retry = 0;
3532         s32 err = 0;
3533         size_t join_params_size;
3534         chanspec_t chanspec = 0;
3535         u32 param[2] = {0, 0};
3536         u32 bw_cap = 0;
3537
3538         WL_TRACE(("In\n"));
3539         RETURN_EIO_IF_NOT_UP(cfg);
3540         WL_INFORM(("JOIN BSSID:" MACDBG "\n", MAC2STRDBG(params->bssid)));
3541         if (!params->ssid || params->ssid_len <= 0 ||
3542                 params->ssid_len >  DOT11_MAX_SSID_LEN) {
3543                 WL_ERR(("Invalid parameter\n"));
3544                 return -EINVAL;
3545         }
3546 #if defined(WL_CFG80211_P2P_DEV_IF)
3547         chan = params->chandef.chan;
3548 #else
3549         chan = params->channel;
3550 #endif /* WL_CFG80211_P2P_DEV_IF */
3551         if (chan)
3552                 cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
3553         if (wl_get_drv_status(cfg, CONNECTED, dev)) {
3554                 struct wlc_ssid *ssid = (struct wlc_ssid *)wl_read_prof(cfg, dev, WL_PROF_SSID);
3555                 u8 *bssid = (u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID);
3556                 u32 *channel = (u32 *)wl_read_prof(cfg, dev, WL_PROF_CHAN);
3557                 if (!params->bssid || ((memcmp(params->bssid, bssid, ETHER_ADDR_LEN) == 0) &&
3558                         (memcmp(params->ssid, ssid->SSID, ssid->SSID_len) == 0) &&
3559                         (*channel == cfg->channel))) {
3560                         WL_ERR(("Connection already existed to " MACDBG "\n",
3561                                 MAC2STRDBG((u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID))));
3562                         return -EISCONN;
3563                 }
3564                 WL_ERR(("Ignore Previous connecton to %s (" MACDBG ")\n",
3565                         ssid->SSID, MAC2STRDBG(bssid)));
3566         }
3567
3568         /* remove the VSIE */
3569         wl_cfg80211_ibss_vsie_delete(dev);
3570
3571         bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
3572         if (!bss) {
3573                 if (IBSS_INITIAL_SCAN_ALLOWED == TRUE) {
3574                         memcpy(ssid.ssid, params->ssid, params->ssid_len);
3575                         ssid.ssid_len = params->ssid_len;
3576                         do {
3577                                 if (unlikely
3578                                         (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
3579                                          -EBUSY)) {
3580                                         wl_delay(150);
3581                                 } else {
3582                                         break;
3583                                 }
3584                         } while (++scan_retry < WL_SCAN_RETRY_MAX);
3585
3586                         /* rtnl lock code is removed here. don't see why rtnl lock
3587                          * needs to be released.
3588                          */
3589
3590                         /* wait 4 secons till scan done.... */
3591                         schedule_timeout_interruptible(msecs_to_jiffies(4000));
3592
3593                         bss = cfg80211_get_ibss(wiphy, NULL,
3594                                 params->ssid, params->ssid_len);
3595                 }
3596         }
3597         if (bss && ((IBSS_COALESCE_ALLOWED == TRUE) ||
3598                 ((IBSS_COALESCE_ALLOWED == FALSE) && params->bssid &&
3599                 !memcmp(bss->bssid, params->bssid, ETHER_ADDR_LEN)))) {
3600                 cfg->ibss_starter = false;
3601                 WL_DBG(("Found IBSS\n"));
3602         } else {
3603                 cfg->ibss_starter = true;
3604         }
3605         if (chan) {
3606                 if (chan->band == IEEE80211_BAND_5GHZ)
3607                         param[0] = WLC_BAND_5G;
3608                 else if (chan->band == IEEE80211_BAND_2GHZ)
3609                         param[0] = WLC_BAND_2G;
3610                 err = wldev_iovar_getint(dev, "bw_cap", param);
3611                 if (unlikely(err)) {
3612                         WL_ERR(("Get bw_cap Failed (%d)\n", err));
3613                         return err;
3614                 }
3615                 bw_cap = param[0];
3616                 chanspec = channel_to_chanspec(wiphy, dev, cfg->channel, bw_cap);
3617         }
3618         /*
3619          * Join with specific BSSID and cached SSID
3620          * If SSID is zero join based on BSSID only
3621          */
3622         memset(&join_params, 0, sizeof(join_params));
3623         memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
3624                 params->ssid_len);
3625         join_params.ssid.SSID_len = htod32(params->ssid_len);
3626         if (params->bssid) {
3627                 memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
3628                 err = wldev_ioctl(dev, WLC_SET_DESIRED_BSSID, &join_params.params.bssid,
3629                         ETHER_ADDR_LEN, true);
3630                 if (unlikely(err)) {
3631                         WL_ERR(("Error (%d)\n", err));
3632                         return err;
3633                 }
3634         } else
3635                 memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
3636         wldev_iovar_setint(dev, "ibss_coalesce_allowed", IBSS_COALESCE_ALLOWED);
3637
3638         if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
3639                 scan_suppress = TRUE;
3640                 /* Set the SCAN SUPPRESS Flag in the firmware to skip join scan */
3641                 err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS,
3642                         &scan_suppress, sizeof(int), true);
3643                 if (unlikely(err)) {
3644                         WL_ERR(("Scan Suppress Setting Failed (%d)\n", err));
3645                         return err;
3646                 }
3647         }
3648
3649         join_params.params.chanspec_list[0] = chanspec;
3650         join_params.params.chanspec_num = 1;
3651         wldev_iovar_setint(dev, "chanspec", chanspec);
3652         join_params_size = sizeof(join_params);
3653
3654         /* Disable Authentication, IBSS will add key if it required */
3655         wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
3656         wldev_iovar_setint(dev, "wsec", 0);
3657
3658
3659         err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
3660                 join_params_size, true);
3661         if (unlikely(err)) {
3662                 WL_ERR(("Error (%d)\n", err));
3663                 return err;
3664         }
3665
3666         if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
3667                 scan_suppress = FALSE;
3668                 /* Reset the SCAN SUPPRESS Flag */
3669                 err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS,
3670                         &scan_suppress, sizeof(int), true);
3671                 if (unlikely(err)) {
3672                         WL_ERR(("Reset Scan Suppress Flag Failed (%d)\n", err));
3673                         return err;
3674                 }
3675         }
3676         wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
3677         wl_update_prof(cfg, dev, NULL, &cfg->channel, WL_PROF_CHAN);
3678         cfg->rmc_event_seq = 0; /* initialize rmcfail sequence */
3679         return err;
3680 }
3681
3682 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
3683 {
3684         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3685         s32 err = 0;
3686         scb_val_t scbval;
3687         u8 *curbssid;
3688
3689         RETURN_EIO_IF_NOT_UP(cfg);
3690         wl_link_down(cfg);
3691
3692         WL_ERR(("Leave IBSS\n"));
3693         curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
3694         wl_set_drv_status(cfg, DISCONNECTING, dev);
3695         scbval.val = 0;
3696         memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
3697         err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
3698                 sizeof(scb_val_t), true);
3699         if (unlikely(err)) {
3700                 wl_clr_drv_status(cfg, DISCONNECTING, dev);
3701                 WL_ERR(("error(%d)\n", err));
3702                 return err;
3703         }
3704
3705         /* remove the VSIE */
3706         wl_cfg80211_ibss_vsie_delete(dev);
3707
3708         return err;
3709 }
3710
3711 #ifdef MFP
3712 static int wl_cfg80211_get_rsn_capa(bcm_tlv_t *wpa2ie, u8* capa)
3713 {
3714         u16 suite_count;
3715         wpa_suite_mcast_t *mcast;
3716         wpa_suite_ucast_t *ucast;
3717         u16 len;
3718         wpa_suite_auth_key_mgmt_t *mgmt;
3719
3720         if (!wpa2ie)
3721                 return -1;
3722
3723         len = wpa2ie->len;
3724         mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
3725         if ((len -= WPA_SUITE_LEN) <= 0)
3726                 return BCME_BADLEN;
3727         ucast = (wpa_suite_ucast_t *)&mcast[1];
3728         suite_count = ltoh16_ua(&ucast->count);
3729         if ((suite_count > NL80211_MAX_NR_CIPHER_SUITES) ||
3730                 (len -= (WPA_IE_SUITE_COUNT_LEN +
3731                 (WPA_SUITE_LEN * suite_count))) <= 0)
3732                 return BCME_BADLEN;
3733
3734         mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
3735         suite_count = ltoh16_ua(&mgmt->count);
3736
3737         if ((suite_count > NL80211_MAX_NR_CIPHER_SUITES) ||
3738                 (len -= (WPA_IE_SUITE_COUNT_LEN +
3739                 (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
3740                 capa[0] = *(u8 *)&mgmt->list[suite_count];
3741                 capa[1] = *((u8 *)&mgmt->list[suite_count] + 1);
3742         } else
3743                 return BCME_BADLEN;
3744
3745         return 0;
3746 }
3747 #endif /* MFP */
3748
3749 static s32
3750 wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
3751 {
3752         struct bcm_cfg80211 *cfg = g_bcm_cfg;
3753         struct wl_security *sec;
3754         s32 val = 0;
3755         s32 err = 0;
3756         s32 bssidx;
3757         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
3758                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3759                 return BCME_ERROR;
3760         }
3761
3762         if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
3763                 val = WPA_AUTH_PSK |
3764                         WPA_AUTH_UNSPECIFIED;
3765         else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
3766                 val = WPA2_AUTH_PSK|
3767                         WPA2_AUTH_UNSPECIFIED;
3768         else
3769                 val = WPA_AUTH_DISABLED;
3770
3771         if (is_wps_conn(sme))
3772                 val = WPA_AUTH_DISABLED;
3773
3774         WL_DBG(("setting wpa_auth to 0x%0x\n", val));
3775         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
3776         if (unlikely(err)) {
3777                 WL_ERR(("set wpa_auth failed (%d)\n", err));
3778                 return err;
3779         }
3780         sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
3781         sec->wpa_versions = sme->crypto.wpa_versions;
3782         return err;
3783 }
3784
3785
3786 static s32
3787 wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
3788 {
3789         struct bcm_cfg80211 *cfg = g_bcm_cfg;
3790         struct wl_security *sec;
3791         s32 val = 0;
3792         s32 err = 0;
3793         s32 bssidx;
3794         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
3795                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3796                 return BCME_ERROR;
3797         }
3798
3799         switch (sme->auth_type) {
3800         case NL80211_AUTHTYPE_OPEN_SYSTEM:
3801                 val = WL_AUTH_OPEN_SYSTEM;
3802                 WL_DBG(("open system\n"));
3803                 break;
3804         case NL80211_AUTHTYPE_SHARED_KEY:
3805                 val = WL_AUTH_SHARED_KEY;
3806                 WL_DBG(("shared key\n"));
3807                 break;
3808         case NL80211_AUTHTYPE_AUTOMATIC:
3809                 val = WL_AUTH_OPEN_SHARED;
3810                 WL_DBG(("automatic\n"));
3811                 break;
3812         default:
3813                 val = 2;
3814                 WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
3815                 break;
3816         }
3817
3818         err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
3819         if (unlikely(err)) {
3820                 WL_ERR(("set auth failed (%d)\n", err));
3821                 return err;
3822         }
3823         sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
3824         sec->auth_type = sme->auth_type;
3825         return err;
3826 }
3827
3828 static s32
3829 wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
3830 {
3831         struct bcm_cfg80211 *cfg = g_bcm_cfg;
3832         struct wl_security *sec;
3833         s32 pval = 0;
3834         s32 gval = 0;
3835         s32 err = 0;
3836         s32 wsec_val = 0;
3837 #ifdef MFP
3838         s32 mfp = 0;
3839         bcm_tlv_t *wpa2_ie;
3840         u8 rsn_cap[2];
3841 #endif /* MFP */
3842
3843         s32 bssidx;
3844         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
3845                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3846                 return BCME_ERROR;
3847         }
3848
3849         if (sme->crypto.n_ciphers_pairwise) {
3850                 switch (sme->crypto.ciphers_pairwise[0]) {
3851                 case WLAN_CIPHER_SUITE_WEP40:
3852                 case WLAN_CIPHER_SUITE_WEP104:
3853                         pval = WEP_ENABLED;
3854                         break;
3855                 case WLAN_CIPHER_SUITE_TKIP:
3856                         pval = TKIP_ENABLED;
3857                         break;
3858                 case WLAN_CIPHER_SUITE_CCMP:
3859                 case WLAN_CIPHER_SUITE_AES_CMAC:
3860                         pval = AES_ENABLED;
3861                         break;
3862                 default:
3863                         WL_ERR(("invalid cipher pairwise (%d)\n",
3864                                 sme->crypto.ciphers_pairwise[0]));
3865                         return -EINVAL;
3866                 }
3867         }
3868         if (sme->crypto.cipher_group) {
3869                 switch (sme->crypto.cipher_group) {
3870                 case WLAN_CIPHER_SUITE_WEP40:
3871                 case WLAN_CIPHER_SUITE_WEP104:
3872                         gval = WEP_ENABLED;
3873                         break;
3874                 case WLAN_CIPHER_SUITE_TKIP:
3875                         gval = TKIP_ENABLED;
3876                         break;
3877                 case WLAN_CIPHER_SUITE_CCMP:
3878                         gval = AES_ENABLED;
3879                         break;
3880                 case WLAN_CIPHER_SUITE_AES_CMAC:
3881                         gval = AES_ENABLED;
3882                         break;
3883                 default:
3884                         WL_ERR(("invalid cipher group (%d)\n",
3885                                 sme->crypto.cipher_group));
3886                         return -EINVAL;
3887                 }
3888         }
3889
3890         WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
3891
3892         if (is_wps_conn(sme)) {
3893                 if (sme->privacy)
3894                         err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
3895                 else
3896                         /* WPS-2.0 allows no security */
3897                         err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
3898         } else {
3899                         WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC"));
3900                         wsec_val = pval | gval;
3901
3902 #ifdef MFP
3903                         if (pval == AES_ENABLED) {
3904                                 if (((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
3905                                         DOT11_MNG_RSN_ID)) != NULL) &&
3906                                         (wl_cfg80211_get_rsn_capa(wpa2_ie, rsn_cap) == 0)) {
3907
3908                                         if (rsn_cap[0] & RSN_CAP_MFPC) {
3909                                                 /* MFP Capability advertised by supplicant. Check
3910                                                  * whether MFP is supported in the firmware
3911                                                  */
3912                                                 if ((err = wldev_iovar_getint_bsscfg(dev,
3913                                                                 "mfp", &mfp, bssidx)) < 0) {
3914                                                         WL_ERR(("Get MFP failed! "
3915                                                                 "Check MFP support in FW \n"));
3916                                                         return -1;
3917                                                 }
3918
3919                                                 if ((sme->crypto.n_akm_suites == 1) &&
3920                                                         ((sme->crypto.akm_suites[0] ==
3921                                                         WL_AKM_SUITE_MFP_PSK) ||
3922                                                         (sme->crypto.akm_suites[0] ==
3923                                                         WL_AKM_SUITE_MFP_1X))) {
3924                                                         wsec_val |= MFP_SHA256;
3925                                                 } else if (sme->crypto.n_akm_suites > 1) {
3926                                                         WL_ERR(("Multiple AKM Specified \n"));
3927                                                         return -EINVAL;
3928                                                 }
3929
3930                                                 wsec_val |= MFP_CAPABLE;
3931                                                 if (rsn_cap[0] & RSN_CAP_MFPR)
3932                                                         wsec_val |= MFP_REQUIRED;
3933
3934                                                 if (rsn_cap[0] & RSN_CAP_MFPR)
3935                                                         mfp = WL_MFP_REQUIRED;
3936                                                 else
3937                                                         mfp = WL_MFP_CAPABLE;
3938                                                 err = wldev_iovar_setint_bsscfg(dev, "mfp",
3939                                                         mfp, bssidx);
3940                                         }
3941                                 }
3942                         }
3943 #endif /* MFP */
3944                         WL_DBG((" Set WSEC to fW 0x%x \n", wsec_val));
3945                         err = wldev_iovar_setint_bsscfg(dev, "wsec",
3946                                 wsec_val, bssidx);
3947         }
3948         if (unlikely(err)) {
3949                 WL_ERR(("error (%d)\n", err));
3950                 return err;
3951         }
3952
3953         sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
3954         sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
3955         sec->cipher_group = sme->crypto.cipher_group;
3956
3957         return err;
3958 }
3959
3960 static s32
3961 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
3962 {
3963         struct bcm_cfg80211 *cfg = g_bcm_cfg;
3964         struct wl_security *sec;
3965         s32 val = 0;
3966         s32 err = 0;
3967         s32 bssidx;
3968         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
3969                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3970                 return BCME_ERROR;
3971         }
3972
3973         if (sme->crypto.n_akm_suites) {
3974                 err = wldev_iovar_getint(dev, "wpa_auth", &val);
3975                 if (unlikely(err)) {
3976                         WL_ERR(("could not get wpa_auth (%d)\n", err));
3977                         return err;
3978                 }
3979                 if (val & (WPA_AUTH_PSK |
3980                         WPA_AUTH_UNSPECIFIED)) {
3981                         switch (sme->crypto.akm_suites[0]) {
3982                         case WLAN_AKM_SUITE_8021X:
3983                                 val = WPA_AUTH_UNSPECIFIED;
3984                                 break;
3985                         case WLAN_AKM_SUITE_PSK:
3986                                 val = WPA_AUTH_PSK;
3987                                 break;
3988                         default:
3989                                 WL_ERR(("invalid cipher group (%d)\n",
3990                                         sme->crypto.cipher_group));
3991                                 return -EINVAL;
3992                         }
3993                 } else if (val & (WPA2_AUTH_PSK |
3994                         WPA2_AUTH_UNSPECIFIED)) {
3995                         switch (sme->crypto.akm_suites[0]) {
3996                         case WLAN_AKM_SUITE_8021X:
3997                                 val = WPA2_AUTH_UNSPECIFIED;
3998                                 break;
3999 #ifdef MFP
4000                         case WL_AKM_SUITE_MFP_1X:
4001                                 val = WPA2_AUTH_UNSPECIFIED;
4002                                 break;
4003                         case WL_AKM_SUITE_MFP_PSK:
4004                                 val = WPA2_AUTH_PSK;
4005                                 break;
4006 #endif
4007                         case WLAN_AKM_SUITE_PSK:
4008                                 val = WPA2_AUTH_PSK;
4009                                 break;
4010                         default:
4011                                 WL_ERR(("invalid cipher group (%d)\n",
4012                                         sme->crypto.cipher_group));
4013                                 return -EINVAL;
4014                         }
4015                 }
4016                 WL_DBG(("setting wpa_auth to %d\n", val));
4017
4018                 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
4019                 if (unlikely(err)) {
4020                         WL_ERR(("could not set wpa_auth (%d)\n", err));
4021                         return err;
4022                 }
4023         }
4024         sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4025         sec->wpa_auth = sme->crypto.akm_suites[0];
4026
4027         return err;
4028 }
4029
4030 static s32
4031 wl_set_set_sharedkey(struct net_device *dev,
4032         struct cfg80211_connect_params *sme)
4033 {
4034         struct bcm_cfg80211 *cfg = g_bcm_cfg;
4035         struct wl_security *sec;
4036         struct wl_wsec_key key;
4037         s32 val;
4038         s32 err = 0;
4039         s32 bssidx;
4040         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
4041                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4042                 return BCME_ERROR;
4043         }
4044
4045         WL_DBG(("key len (%d)\n", sme->key_len));
4046         if (sme->key_len) {
4047                 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4048                 WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
4049                         sec->wpa_versions, sec->cipher_pairwise));
4050                 if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 |
4051                         NL80211_WPA_VERSION_2)) &&
4052                         (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
4053                 WLAN_CIPHER_SUITE_WEP104)))
4054                 {
4055                         memset(&key, 0, sizeof(key));
4056                         key.len = (u32) sme->key_len;
4057                         key.index = (u32) sme->key_idx;
4058                         if (unlikely(key.len > sizeof(key.data))) {
4059                                 WL_ERR(("Too long key length (%u)\n", key.len));
4060                                 return -EINVAL;
4061                         }
4062                         memcpy(key.data, sme->key, key.len);
4063                         key.flags = WL_PRIMARY_KEY;
4064                         switch (sec->cipher_pairwise) {
4065                         case WLAN_CIPHER_SUITE_WEP40:
4066                                 key.algo = CRYPTO_ALGO_WEP1;
4067                                 break;
4068                         case WLAN_CIPHER_SUITE_WEP104:
4069                                 key.algo = CRYPTO_ALGO_WEP128;
4070                                 break;
4071                         default:
4072                                 WL_ERR(("Invalid algorithm (%d)\n",
4073                                         sme->crypto.ciphers_pairwise[0]));
4074                                 return -EINVAL;
4075                         }
4076                         /* Set the new key/index */
4077                         WL_DBG(("key length (%d) key index (%d) algo (%d)\n",
4078                                 key.len, key.index, key.algo));
4079                         WL_DBG(("key \"%s\"\n", key.data));
4080                         swap_key_from_BE(&key);
4081                         err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
4082                                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4083                         if (unlikely(err)) {
4084                                 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
4085                                 return err;
4086                         }
4087                         if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
4088                                 WL_DBG(("set auth_type to shared key\n"));
4089                                 val = WL_AUTH_SHARED_KEY;       /* shared key */
4090                                 err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
4091                                 if (unlikely(err)) {
4092                                         WL_ERR(("set auth failed (%d)\n", err));
4093                                         return err;
4094                                 }
4095                         }
4096                 }
4097         }
4098         return err;
4099 }
4100
4101 static u8 connect_req_bssid[6];
4102 #if defined(ESCAN_RESULT_PATCH)
4103 static u8 broad_bssid[6];
4104 #endif /* ESCAN_RESULT_PATCH */
4105
4106
4107
4108 #if defined(CUSTOM_SET_CPUCORE) || defined(CONFIG_TCPACK_FASTTX)
4109 static bool wl_get_chan_isvht80(struct net_device *net, dhd_pub_t *dhd)
4110 {
4111         u32 chanspec = 0;
4112         bool isvht80 = 0;
4113
4114         if (wldev_iovar_getint(net, "chanspec", (s32 *)&chanspec) == BCME_OK)
4115                 chanspec = wl_chspec_driver_to_host(chanspec);
4116
4117         isvht80 = chanspec & WL_CHANSPEC_BW_80;
4118         WL_INFO(("%s: chanspec(%x:%d)\n", __FUNCTION__, chanspec, isvht80));
4119
4120         return isvht80;
4121 }
4122 #endif /* CUSTOM_SET_CPUCORE || CONFIG_TCPACK_FASTTX */
4123
4124 static s32
4125 wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
4126         struct cfg80211_connect_params *sme)
4127 {
4128         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4129         struct ieee80211_channel *chan = sme->channel;
4130         wl_extjoin_params_t *ext_join_params;
4131         struct wl_join_params join_params;
4132         size_t join_params_size;
4133 #if defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION)
4134         dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
4135         s32 roam_trigger[2] = {0, 0};
4136 #endif /* ROAM_AP_ENV_DETECTION */
4137         s32 err = 0;
4138         wpa_ie_fixed_t *wpa_ie;
4139         bcm_tlv_t *wpa2_ie;
4140         u8* wpaie  = 0;
4141         u32 wpaie_len = 0;
4142         u32 chan_cnt = 0;
4143         struct ether_addr bssid;
4144         s32 bssidx;
4145         int ret;
4146         int wait_cnt;
4147
4148         WL_DBG(("In\n"));
4149
4150         if (unlikely(!sme->ssid)) {
4151                 WL_ERR(("Invalid ssid\n"));
4152                 return -EOPNOTSUPP;
4153         }
4154
4155         if (unlikely(sme->ssid_len > DOT11_MAX_SSID_LEN)) {
4156                 WL_ERR(("Invalid SSID info: SSID=%s, length=%zd\n",
4157                         sme->ssid, sme->ssid_len));
4158                 return -EINVAL;
4159         }
4160
4161         WL_DBG(("SME IE : len=%zu\n", sme->ie_len));
4162         if (sme->ie != NULL && sme->ie_len > 0 && (wl_dbg_level & WL_DBG_DBG)) {
4163                 prhex(NULL, sme->ie, sme->ie_len);
4164         }
4165
4166         RETURN_EIO_IF_NOT_UP(cfg);
4167
4168         /*
4169          * Cancel ongoing scan to sync up with sme state machine of cfg80211.
4170          */
4171 #if !defined(ESCAN_RESULT_PATCH)
4172         if (cfg->scan_request) {
4173                 wl_notify_escan_complete(cfg, dev, true, true);
4174         }
4175 #endif
4176 #ifdef WL_SCHED_SCAN
4177         if (cfg->sched_scan_req) {
4178                 wl_cfg80211_sched_scan_stop(wiphy, bcmcfg_to_prmry_ndev(cfg));
4179         }
4180 #endif
4181         if (sme->bssid)
4182                 memcpy(connect_req_bssid, sme->bssid, ETHER_ADDR_LEN);
4183         else
4184                 bzero(connect_req_bssid, ETHER_ADDR_LEN);
4185 #if defined(ESCAN_RESULT_PATCH)
4186         bzero(broad_bssid, ETHER_ADDR_LEN);
4187 #endif
4188 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
4189         maxrxpktglom = 0;
4190 #endif
4191         bzero(&bssid, sizeof(bssid));
4192         if (!wl_get_drv_status(cfg, CONNECTED, dev)&&
4193                 (ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false)) == 0) {
4194                 if (!ETHER_ISNULLADDR(&bssid)) {
4195                         scb_val_t scbval;
4196                         wl_set_drv_status(cfg, DISCONNECTING, dev);
4197                         scbval.val = DOT11_RC_DISASSOC_LEAVING;
4198                         memcpy(&scbval.ea, &bssid, ETHER_ADDR_LEN);
4199                         scbval.val = htod32(scbval.val);
4200
4201                         WL_DBG(("drv status CONNECTED is not set, but connected in FW!" MACDBG "/n",
4202                                 MAC2STRDBG(bssid.octet)));
4203                         err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
4204                                 sizeof(scb_val_t), true);
4205                         if (unlikely(err)) {
4206                                 wl_clr_drv_status(cfg, DISCONNECTING, dev);
4207                                 WL_ERR(("error (%d)\n", err));
4208                                 return err;
4209                         }
4210                         wait_cnt = 500/10;
4211                         while (wl_get_drv_status(cfg, DISCONNECTING, dev) && wait_cnt) {
4212                                 WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n",
4213                                         wait_cnt));
4214                                 wait_cnt--;
4215                                 OSL_SLEEP(10);
4216                         }
4217                 } else
4218                         WL_DBG(("Currently not associated!\n"));
4219         } else {
4220                 /* if status is DISCONNECTING, wait for disconnection terminated max 500 ms */
4221                 wait_cnt = 500/10;
4222                 while (wl_get_drv_status(cfg, DISCONNECTING, dev) && wait_cnt) {
4223                         WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n", wait_cnt));
4224                         wait_cnt--;
4225                         OSL_SLEEP(10);
4226                 }
4227         }
4228
4229         /* Clean BSSID */
4230         bzero(&bssid, sizeof(bssid));
4231         if (!wl_get_drv_status(cfg, DISCONNECTING, dev))
4232                 wl_update_prof(cfg, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
4233
4234         if (p2p_is_on(cfg) && (dev != bcmcfg_to_prmry_ndev(cfg))) {
4235                 /* we only allow to connect using virtual interface in case of P2P */
4236                         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
4237                                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4238                                 return BCME_ERROR;
4239                         }
4240                         wl_cfgp2p_set_management_ie(cfg, dev, bssidx,
4241                                 VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
4242         } else if (dev == bcmcfg_to_prmry_ndev(cfg)) {
4243                 /* find the RSN_IE */
4244                 if ((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
4245                         DOT11_MNG_RSN_ID)) != NULL) {
4246                         WL_DBG((" WPA2 IE is found\n"));
4247                 }
4248                 /* find the WPA_IE */
4249                 if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)sme->ie,
4250                         sme->ie_len)) != NULL) {
4251                         WL_DBG((" WPA IE is found\n"));
4252                 }
4253                 if (wpa_ie != NULL || wpa2_ie != NULL) {
4254                         wpaie = (wpa_ie != NULL) ? (u8 *)wpa_ie : (u8 *)wpa2_ie;
4255                         wpaie_len = (wpa_ie != NULL) ? wpa_ie->length : wpa2_ie->len;
4256                         wpaie_len += WPA_RSN_IE_TAG_FIXED_LEN;
4257                         err = wldev_iovar_setbuf(dev, "wpaie", wpaie, wpaie_len,
4258                                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
4259                         if (unlikely(err)) {
4260                                 WL_ERR(("wpaie set error (%d)\n", err));
4261                                 return err;
4262                         }
4263                 } else {
4264                         err = wldev_iovar_setbuf(dev, "wpaie", NULL, 0,
4265                                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
4266                         if (unlikely(err)) {
4267                                 WL_ERR(("wpaie set error (%d)\n", err));
4268                                 return err;
4269                         }
4270                 }
4271
4272                 if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
4273                         WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4274                         return BCME_ERROR;
4275                 }
4276                 err = wl_cfgp2p_set_management_ie(cfg, dev, bssidx,
4277                         VNDR_IE_ASSOCREQ_FLAG, (u8 *)sme->ie, sme->ie_len);
4278                 if (unlikely(err)) {
4279                         return err;
4280                 }
4281         }
4282 #if defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION)
4283         if (dhd->roam_env_detection) {
4284                 bool is_roamtrig_reset = TRUE;
4285                 bool is_roam_env_ok = (wldev_iovar_setint(dev, "roam_env_detection",
4286                         AP_ENV_DETECT_NOT_USED) == BCME_OK);
4287                 if (is_roamtrig_reset && is_roam_env_ok) {
4288                         roam_trigger[0] = WL_AUTO_ROAM_TRIGGER;
4289                         roam_trigger[1] = WLC_BAND_ALL;
4290                 err = wldev_ioctl(dev, WLC_SET_ROAM_TRIGGER, roam_trigger,
4291                         sizeof(roam_trigger), true);
4292                 if (unlikely(err)) {
4293                                 WL_ERR((" failed to restore roam_trigger for auto env"
4294                                         " detection\n"));
4295                         }
4296                 }
4297         }
4298 #endif /* ROAM_ENABLE && ROAM_AP_ENV_DETECTION */
4299         if (chan) {
4300                 cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
4301                 chan_cnt = 1;
4302                 WL_DBG(("channel (%d), center_req (%d), %d channels\n", cfg->channel,
4303                         chan->center_freq, chan_cnt));
4304         } else
4305                 cfg->channel = 0;
4306         WL_DBG(("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len));
4307         WL_DBG(("3. set wapi version \n"));
4308         err = wl_set_wpa_version(dev, sme);
4309         if (unlikely(err)) {
4310                 WL_ERR(("Invalid wpa_version\n"));
4311                 return err;
4312         }
4313                 err = wl_set_auth_type(dev, sme);
4314                 if (unlikely(err)) {
4315                         WL_ERR(("Invalid auth type\n"));
4316                         return err;
4317                 }
4318
4319         err = wl_set_set_cipher(dev, sme);
4320         if (unlikely(err)) {
4321                 WL_ERR(("Invalid ciper\n"));
4322                 return err;
4323         }
4324
4325         err = wl_set_key_mgmt(dev, sme);
4326         if (unlikely(err)) {
4327                 WL_ERR(("Invalid key mgmt\n"));
4328                 return err;
4329         }
4330
4331         err = wl_set_set_sharedkey(dev, sme);
4332         if (unlikely(err)) {
4333                 WL_ERR(("Invalid shared key\n"));
4334                 return err;
4335         }
4336
4337         /*
4338          *  Join with specific BSSID and cached SSID
4339          *  If SSID is zero join based on BSSID only
4340          */
4341         join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE +
4342                 chan_cnt * sizeof(chanspec_t);
4343         ext_join_params =  (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL);
4344         if (ext_join_params == NULL) {
4345                 err = -ENOMEM;
4346                 wl_clr_drv_status(cfg, CONNECTING, dev);
4347                 goto exit;
4348         }
4349         ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len);
4350         memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len);
4351         wl_update_prof(cfg, dev, NULL, &ext_join_params->ssid, WL_PROF_SSID);
4352         ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
4353         /* increate dwell time to receive probe response or detect Beacon
4354         * from target AP at a noisy air only during connect command
4355         */
4356         ext_join_params->scan.active_time = chan_cnt ? WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS : -1;
4357         ext_join_params->scan.passive_time = chan_cnt ? WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS : -1;
4358         /* Set up join scan parameters */
4359         ext_join_params->scan.scan_type = -1;
4360         ext_join_params->scan.nprobes = chan_cnt ?
4361                 (ext_join_params->scan.active_time/WL_SCAN_JOIN_PROBE_INTERVAL_MS) : -1;
4362         ext_join_params->scan.home_time = -1;
4363
4364         if (sme->bssid)
4365                 memcpy(&ext_join_params->assoc.bssid, sme->bssid, ETH_ALEN);
4366         else
4367                 memcpy(&ext_join_params->assoc.bssid, &ether_bcast, ETH_ALEN);
4368         ext_join_params->assoc.chanspec_num = chan_cnt;
4369         if (chan_cnt) {
4370                 u16 channel, band, bw, ctl_sb;
4371                 chanspec_t chspec;
4372                 channel = cfg->channel;
4373                 band = (channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G
4374                         : WL_CHANSPEC_BAND_5G;
4375                 bw = WL_CHANSPEC_BW_20;
4376                 ctl_sb = WL_CHANSPEC_CTL_SB_NONE;
4377                 chspec = (channel | band | bw | ctl_sb);
4378                 ext_join_params->assoc.chanspec_list[0]  &= WL_CHANSPEC_CHAN_MASK;
4379                 ext_join_params->assoc.chanspec_list[0] |= chspec;
4380                 ext_join_params->assoc.chanspec_list[0] =
4381                         wl_chspec_host_to_driver(ext_join_params->assoc.chanspec_list[0]);
4382         }
4383         ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num);
4384         if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
4385                 WL_INFORM(("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID,
4386                         ext_join_params->ssid.SSID_len));
4387         }
4388         wl_set_drv_status(cfg, CONNECTING, dev);
4389
4390         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
4391                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4392                 wl_clr_drv_status(cfg, CONNECTING, dev);
4393                 kfree(ext_join_params);
4394                 return BCME_ERROR;
4395         }
4396         err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size,
4397                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4398
4399         DHD_NV_INFO(("Connectting with " MACDBG " channel (%d) ssid \"%s\", len (%d)\n\n",
4400                 MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)), cfg->channel,
4401                 ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len));
4402
4403         kfree(ext_join_params);
4404         if (err) {
4405                 wl_clr_drv_status(cfg, CONNECTING, dev);
4406                 if (err == BCME_UNSUPPORTED) {
4407                         WL_DBG(("join iovar is not supported\n"));
4408                         goto set_ssid;
4409                 } else {
4410                         WL_ERR(("error (%d)\n", err));
4411                         goto exit;
4412                 }
4413         } else
4414                 goto exit;
4415
4416 set_ssid:
4417         memset(&join_params, 0, sizeof(join_params));
4418         join_params_size = sizeof(join_params.ssid);
4419
4420         join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
4421         memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
4422         join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
4423         wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
4424         if (sme->bssid)
4425                 memcpy(&join_params.params.bssid, sme->bssid, ETH_ALEN);
4426         else
4427                 memcpy(&join_params.params.bssid, &ether_bcast, ETH_ALEN);
4428
4429         wl_ch_to_chanspec(cfg->channel, &join_params, &join_params_size);
4430         WL_DBG(("join_param_size %zu\n", join_params_size));
4431
4432         if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
4433                 WL_INFORM(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
4434                         join_params.ssid.SSID_len));
4435         }
4436         wl_set_drv_status(cfg, CONNECTING, dev);
4437         err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true);
4438         if (err) {
4439                 WL_ERR(("error (%d)\n", err));
4440                 wl_clr_drv_status(cfg, CONNECTING, dev);
4441         }
4442 exit:
4443         return err;
4444 }
4445
4446 static s32
4447 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
4448         u16 reason_code)
4449 {
4450         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4451         scb_val_t scbval;
4452         bool act = false;
4453         s32 err = 0;
4454         u8 *curbssid;
4455 #ifdef CUSTOM_SET_CPUCORE
4456         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
4457 #endif /* CUSTOM_SET_CPUCORE */
4458         DHD_NV_INFO(("Reason %d\n", reason_code));
4459 #ifdef CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA
4460         if (bcmdhd_stat.rssi < -67)
4461                 TEGRA_SYSFS_HISTOGRAM_STAT_INC(disconnect_rssi_low);
4462         else
4463                 TEGRA_SYSFS_HISTOGRAM_STAT_INC(disconnect_rssi_high);
4464 #endif
4465         RETURN_EIO_IF_NOT_UP(cfg);
4466         act = *(bool *) wl_read_prof(cfg, dev, WL_PROF_ACT);
4467         curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
4468 #ifdef ESCAN_RESULT_PATCH
4469         if (wl_get_drv_status(cfg, CONNECTING, dev) && curbssid &&
4470                 (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0)) {
4471                 WL_ERR(("Disconnecting from connecting device: " MACDBG "\n",
4472                         MAC2STRDBG(curbssid)));
4473                 act = true;
4474         }
4475 #endif /* ESCAN_RESULT_PATCH */
4476         if (act || wl_get_drv_status(cfg, CONNECTING, dev)) {
4477                 /*
4478                 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
4479                 */
4480                 /* Let scan aborted by F/W */
4481                 if (cfg->scan_request) {
4482                         wl_notify_escan_complete(cfg, dev, true, true);
4483                 }
4484                 wl_clr_drv_status(cfg, CONNECTING, dev);
4485                 wl_set_drv_status(cfg, DISCONNECTING, dev);
4486                 scbval.val = reason_code;
4487                 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
4488                 scbval.val = htod32(scbval.val);
4489                 err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
4490                         sizeof(scb_val_t), true);
4491                 if (unlikely(err)) {
4492                         wl_clr_drv_status(cfg, DISCONNECTING, dev);
4493                         WL_ERR(("error (%d)\n", err));
4494                         return err;
4495                 }
4496         }
4497 #ifdef CUSTOM_SET_CPUCORE
4498         /* set default cpucore */
4499         if (dev == bcmcfg_to_prmry_ndev(cfg)) {
4500                 dhd->chan_isvht80 &= ~DHD_FLAG_STA_MODE;
4501                 if (!(dhd->chan_isvht80))
4502                         dhd_set_cpucore(dhd, FALSE);
4503         }
4504 #endif /* CUSTOM_SET_CPUCORE */
4505
4506         return err;
4507 }
4508
4509 #if defined(WL_CFG80211_P2P_DEV_IF)
4510 static s32
4511 wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
4512         enum nl80211_tx_power_setting type, s32 mbm)
4513 #else
4514 static s32
4515 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
4516         enum nl80211_tx_power_setting type, s32 dbm)
4517 #endif /* WL_CFG80211_P2P_DEV_IF */
4518 {
4519
4520         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4521         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
4522         s32 err = 0;
4523 #if defined(WL_CFG80211_P2P_DEV_IF)
4524         s32 dbm = MBM_TO_DBM(mbm);
4525 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || \
4526         defined(WL_COMPAT_WIRELESS) || defined(WL_SUPPORT_BACKPORTED_KPATCHES)
4527         dbm = MBM_TO_DBM(dbm);
4528 #endif /* WL_CFG80211_P2P_DEV_IF */
4529
4530         RETURN_EIO_IF_NOT_UP(cfg);
4531         switch (type) {
4532         case NL80211_TX_POWER_AUTOMATIC:
4533                 break;
4534         case NL80211_TX_POWER_LIMITED:
4535                 if (dbm < 0) {
4536                         WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
4537                         return -EINVAL;
4538                 }
4539                 break;
4540         case NL80211_TX_POWER_FIXED:
4541                 if (dbm < 0) {
4542                         WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
4543                         return -EINVAL;
4544                 }
4545                 break;
4546         }
4547
4548         err = wl_set_tx_power(ndev, type, dbm);
4549         if (unlikely(err)) {
4550                 WL_ERR(("error (%d)\n", err));
4551                 return err;
4552         }
4553
4554         cfg->conf->tx_power = dbm;
4555
4556         return err;
4557 }
4558
4559 #if defined(WL_CFG80211_P2P_DEV_IF)
4560 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
4561         struct wireless_dev *wdev, s32 *dbm)
4562 #else
4563 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
4564 #endif /* WL_CFG80211_P2P_DEV_IF */
4565 {
4566         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4567         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
4568         s32 err = 0;
4569
4570         RETURN_EIO_IF_NOT_UP(cfg);
4571         err = wl_get_tx_power(ndev, dbm);
4572         if (unlikely(err))
4573                 WL_ERR(("error (%d)\n", err));
4574
4575         return err;
4576 }
4577
4578 static s32
4579 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
4580         u8 key_idx, bool unicast, bool multicast)
4581 {
4582         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4583         u32 index;
4584         s32 wsec;
4585         s32 err = 0;
4586         s32 bssidx;
4587         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
4588                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4589                 return BCME_ERROR;
4590         }
4591
4592         WL_DBG(("key index (%d)\n", key_idx));
4593         RETURN_EIO_IF_NOT_UP(cfg);
4594         err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
4595         if (unlikely(err)) {
4596                 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
4597                 return err;
4598         }
4599         if (wsec == WEP_ENABLED) {
4600                 /* Just select a new current key */
4601                 index = (u32) key_idx;
4602                 index = htod32(index);
4603                 err = wldev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
4604                         sizeof(index), true);
4605                 if (unlikely(err)) {
4606                         WL_ERR(("error (%d)\n", err));
4607                 }
4608         }
4609         return err;
4610 }
4611
4612 static s32
4613 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
4614         u8 key_idx, const u8 *mac_addr, struct key_params *params)
4615 {
4616         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4617         struct wl_wsec_key key;
4618         s32 err = 0;
4619         s32 bssidx;
4620         s32 mode = wl_get_mode_by_netdev(cfg, dev);
4621         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
4622                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4623                 return BCME_ERROR;
4624         }
4625         memset(&key, 0, sizeof(key));
4626         key.index = (u32) key_idx;
4627
4628         if (!ETHER_ISMULTI(mac_addr))
4629                 memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN);
4630         key.len = (u32) params->key_len;
4631
4632         /* check for key index change */
4633         if (key.len == 0) {
4634                 /* key delete */
4635                 swap_key_from_BE(&key);
4636                 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
4637                         cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4638                 if (unlikely(err)) {
4639                         WL_ERR(("key delete error (%d)\n", err));
4640                         return err;
4641                 }
4642         } else {
4643                 if (key.len > sizeof(key.data)) {
4644                         WL_ERR(("Invalid key length (%d)\n", key.len));
4645                         return -EINVAL;
4646                 }
4647                 WL_DBG(("Setting the key index %d\n", key.index));
4648                 memcpy(key.data, params->key, key.len);
4649
4650                 if ((mode == WL_MODE_BSS) &&
4651                         (params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
4652                         u8 keybuf[8];
4653                         memcpy(keybuf, &key.data[24], sizeof(keybuf));
4654                         memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
4655                         memcpy(&key.data[16], keybuf, sizeof(keybuf));
4656                 }
4657
4658                 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
4659                 if (params->seq && params->seq_len == 6) {
4660                         /* rx iv */
4661                         u8 *ivptr;
4662                         ivptr = (u8 *) params->seq;
4663                         key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
4664                                 (ivptr[3] << 8) | ivptr[2];
4665                         key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
4666                         key.iv_initialized = true;
4667                 }
4668
4669                 switch (params->cipher) {
4670                 case WLAN_CIPHER_SUITE_WEP40:
4671                         key.algo = CRYPTO_ALGO_WEP1;
4672                         WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
4673                         break;
4674                 case WLAN_CIPHER_SUITE_WEP104:
4675                         key.algo = CRYPTO_ALGO_WEP128;
4676                         WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
4677                         break;
4678                 case WLAN_CIPHER_SUITE_TKIP:
4679                         key.algo = CRYPTO_ALGO_TKIP;
4680                         WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
4681                         break;
4682                 case WLAN_CIPHER_SUITE_AES_CMAC:
4683                         key.algo = CRYPTO_ALGO_AES_CCM;
4684                         WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
4685                         break;
4686                 case WLAN_CIPHER_SUITE_CCMP:
4687                         key.algo = CRYPTO_ALGO_AES_CCM;
4688                         WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
4689                         break;
4690                 default:
4691                         WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
4692                         return -EINVAL;
4693                 }
4694                 swap_key_from_BE(&key);
4695                 /* need to guarantee EAPOL 4/4 send out before set key */
4696                 if (mode != WL_MODE_AP)
4697                         dhd_wait_pend8021x(dev);
4698                 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
4699                         cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4700                 if (unlikely(err)) {
4701                         WL_ERR(("WLC_SET_KEY error (%d)\n", err));
4702                         return err;
4703                 }
4704         }
4705         return err;
4706 }
4707
4708 int
4709 wl_cfg80211_enable_roam_offload(struct net_device *dev, int enable)
4710 {
4711         int err;
4712         wl_eventmsg_buf_t ev_buf;
4713
4714         if (dev != bcmcfg_to_prmry_ndev(g_bcm_cfg)) {
4715                 /* roam offload is only for the primary device */
4716                 return -1;
4717         }
4718         err = wldev_iovar_setint(dev, "roam_offload", enable);
4719         if (err)
4720                 return err;
4721
4722         bzero(&ev_buf, sizeof(wl_eventmsg_buf_t));
4723         wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_PSK_SUP, !enable);
4724         wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_REQ_IE, !enable);
4725         wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_RESP_IE, !enable);
4726         wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_REASSOC, !enable);
4727         wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_JOIN, !enable);
4728         wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ROAM, !enable);
4729         err = wl_cfg80211_apply_eventbuffer(dev, g_bcm_cfg, &ev_buf);
4730         if (!err) {
4731                 g_bcm_cfg->roam_offload = enable;
4732         }
4733         return err;
4734 }
4735
4736 static s32
4737 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
4738         u8 key_idx, bool pairwise, const u8 *mac_addr,
4739         struct key_params *params)
4740 {
4741         struct wl_wsec_key key;
4742         s32 val = 0;
4743         s32 wsec = 0;
4744         s32 err = 0;
4745         u8 keybuf[8];
4746         s32 bssidx = 0;
4747         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4748         s32 mode = wl_get_mode_by_netdev(cfg, dev);
4749         WL_DBG(("key index (%d)\n", key_idx));
4750         RETURN_EIO_IF_NOT_UP(cfg);
4751
4752         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
4753                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4754                 return BCME_ERROR;
4755         }
4756
4757         if (mac_addr &&
4758                 ((params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
4759                 (params->cipher != WLAN_CIPHER_SUITE_WEP104))) {
4760                         wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
4761                         goto exit;
4762         }
4763         memset(&key, 0, sizeof(key));
4764
4765         key.len = (u32) params->key_len;
4766         key.index = (u32) key_idx;
4767
4768         if (unlikely(key.len > sizeof(key.data))) {
4769                 WL_ERR(("Too long key length (%u)\n", key.len));
4770                 return -EINVAL;
4771         }
4772         memcpy(key.data, params->key, key.len);
4773
4774         key.flags = WL_PRIMARY_KEY;
4775         switch (params->cipher) {
4776         case WLAN_CIPHER_SUITE_WEP40:
4777                 key.algo = CRYPTO_ALGO_WEP1;
4778                 val = WEP_ENABLED;
4779                 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
4780                 break;
4781         case WLAN_CIPHER_SUITE_WEP104:
4782                 key.algo = CRYPTO_ALGO_WEP128;
4783                 val = WEP_ENABLED;
4784                 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
4785                 break;
4786         case WLAN_CIPHER_SUITE_TKIP:
4787                 key.algo = CRYPTO_ALGO_TKIP;
4788                 val = TKIP_ENABLED;
4789                 /* wpa_supplicant switches the third and fourth quarters of the TKIP key */
4790                 if (mode == WL_MODE_BSS) {
4791                         bcopy(&key.data[24], keybuf, sizeof(keybuf));
4792                         bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
4793                         bcopy(keybuf, &key.data[16], sizeof(keybuf));
4794                 }
4795                 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
4796                 break;
4797         case WLAN_CIPHER_SUITE_AES_CMAC:
4798                 key.algo = CRYPTO_ALGO_AES_CCM;
4799                 val = AES_ENABLED;
4800                 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
4801                 break;
4802         case WLAN_CIPHER_SUITE_CCMP:
4803                 key.algo = CRYPTO_ALGO_AES_CCM;
4804                 val = AES_ENABLED;
4805                 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
4806                 break;
4807         default:
4808                 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
4809                 return -EINVAL;
4810         }
4811
4812         /* Set the new key/index */
4813         if ((mode == WL_MODE_IBSS) && (val & (TKIP_ENABLED | AES_ENABLED))) {
4814                 WL_ERR(("IBSS KEY setted\n"));
4815                 wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_NONE);
4816         }
4817         swap_key_from_BE(&key);
4818         err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), cfg->ioctl_buf,
4819                 WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4820         if (unlikely(err)) {
4821                 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
4822                 return err;
4823         }
4824
4825 exit:
4826         err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
4827         if (unlikely(err)) {
4828                 WL_ERR(("get wsec error (%d)\n", err));
4829                 return err;
4830         }
4831
4832         wsec |= val;
4833         err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
4834         if (unlikely(err)) {
4835                 WL_ERR(("set wsec error (%d)\n", err));
4836                 return err;
4837         }
4838
4839         return err;
4840 }
4841
4842 static s32
4843 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
4844         u8 key_idx, bool pairwise, const u8 *mac_addr)
4845 {
4846         struct wl_wsec_key key;
4847         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4848         s32 err = 0;
4849         s32 bssidx;
4850
4851         if (!cfg)
4852                 return -EINVAL;
4853
4854         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
4855                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4856                 return BCME_ERROR;
4857         }
4858         WL_DBG(("Enter\n"));
4859
4860 #ifndef IEEE80211W
4861         if ((key_idx >= DOT11_MAX_DEFAULT_KEYS) && (key_idx < DOT11_MAX_DEFAULT_KEYS+2))
4862                 return -EINVAL;
4863 #endif
4864
4865         RETURN_EIO_IF_NOT_UP(cfg);
4866         memset(&key, 0, sizeof(key));
4867
4868         key.flags = WL_PRIMARY_KEY;
4869         key.algo = CRYPTO_ALGO_OFF;
4870         key.index = (u32) key_idx;
4871
4872         WL_DBG(("key index (%d)\n", key_idx));
4873         /* Set the new key/index */
4874         swap_key_from_BE(&key);
4875         err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), cfg->ioctl_buf,
4876                 WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4877         if (unlikely(err)) {
4878                 if (err == -EINVAL) {
4879                         if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
4880                                 /* we ignore this key index in this case */
4881                                 WL_DBG(("invalid key index (%d)\n", key_idx));
4882                         }
4883                 } else {
4884                         WL_ERR(("WLC_SET_KEY error (%d)\n", err));
4885                 }
4886                 return err;
4887         }
4888         return err;
4889 }
4890
4891 static s32
4892 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
4893         u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
4894         void (*callback) (void *cookie, struct key_params * params))
4895 {
4896         struct key_params params;
4897         struct wl_wsec_key key;
4898         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4899         struct wl_security *sec;
4900         s32 wsec;
4901         s32 err = 0;
4902         s32 bssidx;
4903         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
4904                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4905                 return BCME_ERROR;
4906         }
4907         WL_DBG(("key index (%d)\n", key_idx));
4908         RETURN_EIO_IF_NOT_UP(cfg);
4909         memset(&key, 0, sizeof(key));
4910         key.index = key_idx;
4911         swap_key_to_BE(&key);
4912         memset(&params, 0, sizeof(params));
4913         params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
4914         memcpy(params.key, key.data, params.key_len);
4915
4916         err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
4917         if (unlikely(err)) {
4918                 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
4919                 return err;
4920         }
4921         switch (WSEC_ENABLED(wsec)) {
4922                 case WEP_ENABLED:
4923                         sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4924                         if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
4925                                 params.cipher = WLAN_CIPHER_SUITE_WEP40;
4926                                 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
4927                         } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
4928                                 params.cipher = WLAN_CIPHER_SUITE_WEP104;
4929                                 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
4930                         }
4931                         break;
4932                 case TKIP_ENABLED:
4933                         params.cipher = WLAN_CIPHER_SUITE_TKIP;
4934                         WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
4935                         break;
4936                 case AES_ENABLED:
4937                         params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
4938                         WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
4939                         break;
4940                 default:
4941                         WL_ERR(("Invalid algo (0x%x)\n", wsec));
4942                         return -EINVAL;
4943         }
4944
4945         callback(cookie, &params);
4946         return err;
4947 }
4948
4949 static s32
4950 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
4951         struct net_device *dev, u8 key_idx)
4952 {
4953 #ifdef MFP
4954         return 0;
4955 #else
4956         WL_INFORM(("Not supported\n"));
4957         return -EOPNOTSUPP;
4958 #endif /* MFP */
4959 }
4960
4961 static s32
4962 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
4963         u8 *mac, struct station_info *sinfo)
4964 {
4965         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4966         scb_val_t scb_val;
4967         s32 rssi;
4968         s32 rate;
4969         s32 err = 0;
4970         sta_info_t *sta;
4971 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
4972         s8 eabuf[ETHER_ADDR_STR_LEN];
4973 #endif
4974         dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
4975         RETURN_EIO_IF_NOT_UP(cfg);
4976         if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
4977                 err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac,
4978                         ETHER_ADDR_LEN, cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
4979                 if (err < 0) {
4980                         WL_ERR(("GET STA INFO failed, %d\n", err));
4981                         return err;
4982                 }
4983                 sinfo->filled = STATION_INFO_INACTIVE_TIME;
4984                 sta = (sta_info_t *)cfg->ioctl_buf;
4985                 sta->len = dtoh16(sta->len);
4986                 sta->cap = dtoh16(sta->cap);
4987                 sta->flags = dtoh32(sta->flags);
4988                 sta->idle = dtoh32(sta->idle);
4989                 sta->in = dtoh32(sta->in);
4990                 sinfo->inactive_time = sta->idle * 1000;
4991 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
4992                 if (sta->flags & WL_STA_ASSOC) {
4993                         sinfo->filled |= STATION_INFO_CONNECTED_TIME;
4994                         sinfo->connected_time = sta->in;
4995                 }
4996                 WL_INFORM(("STA %s : idle time : %d sec, connected time :%d ms\n",
4997                         bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), sinfo->inactive_time,
4998                         sta->idle * 1000));
4999 #endif
5000         } else if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_BSS ||
5001                 wl_get_mode_by_netdev(cfg, dev) == WL_MODE_IBSS) {
5002                 get_pktcnt_t pktcnt;
5003                 u8 *curmacp;
5004
5005                 if (cfg->roam_offload) {
5006                         struct ether_addr bssid;
5007                         err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
5008                         if (err) {
5009                                 WL_ERR(("Failed to get current BSSID\n"));
5010                         } else {
5011                                 if (memcmp(mac, &bssid.octet, ETHER_ADDR_LEN) != 0) {
5012                                         /* roaming is detected */
5013                                         err = wl_cfg80211_delayed_roam(cfg, dev, &bssid);
5014                                         if (err)
5015                                                 WL_ERR(("Failed to handle the delayed roam, "
5016                                                         "err=%d", err));
5017                                         mac = (u8 *)bssid.octet;
5018                                 }
5019                         }
5020                 }
5021                 if (!wl_get_drv_status(cfg, CONNECTED, dev) ||
5022                         (dhd_is_associated(dhd, NULL, &err) == FALSE)) {
5023                         WL_ERR(("NOT assoc\n"));
5024                         if (err == -ERESTARTSYS)
5025                                 return err;
5026                         err = -ENODEV;
5027                         return err;
5028                 }
5029                 curmacp = wl_read_prof(cfg, dev, WL_PROF_BSSID);
5030                 if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
5031                         WL_ERR(("Wrong Mac address: "MACDBG" != "MACDBG"\n",
5032                                 MAC2STRDBG(mac), MAC2STRDBG(curmacp)));
5033                 }
5034
5035                 /* Report the current tx rate */
5036                 err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
5037                 if (err) {
5038                         WL_ERR(("Could not get rate (%d)\n", err));
5039                 } else {
5040 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
5041                         int rxpktglom;
5042 #endif
5043                         rate = dtoh32(rate);
5044                         sinfo->filled |= STATION_INFO_TX_BITRATE;
5045                         sinfo->txrate.legacy = rate * 5;
5046                         WL_DBG(("Rate %d Mbps\n", (rate / 2)));
5047 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
5048                         rxpktglom = ((rate/2) > 150) ? 20 : 10;
5049
5050                         if (maxrxpktglom != rxpktglom) {
5051                                 maxrxpktglom = rxpktglom;
5052                                 WL_DBG(("Rate %d Mbps, update bus:maxtxpktglom=%d\n", (rate/2),
5053                                         maxrxpktglom));
5054                                 err = wldev_iovar_setbuf(dev, "bus:maxtxpktglom",
5055                                         (char*)&maxrxpktglom, 4, cfg->ioctl_buf,
5056                                         WLC_IOCTL_MAXLEN, NULL);
5057                                 if (err < 0) {
5058                                         WL_ERR(("set bus:maxtxpktglom failed, %d\n", err));
5059                                 }
5060                         }
5061 #endif
5062                 }
5063
5064                 memset(&scb_val, 0, sizeof(scb_val));
5065                 scb_val.val = 0;
5066                 err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,
5067                         sizeof(scb_val_t), false);
5068                 if (err) {
5069                         WL_ERR(("Could not get rssi (%d)\n", err));
5070                         goto get_station_err;
5071                 }
5072                 rssi = wl_rssi_offset(dtoh32(scb_val.val));
5073                 sinfo->filled |= STATION_INFO_SIGNAL;
5074                 sinfo->signal = rssi;
5075                 WL_DBG(("RSSI %d dBm\n", rssi));
5076                 err = wldev_ioctl(dev, WLC_GET_PKTCNTS, &pktcnt,
5077                         sizeof(pktcnt), false);
5078                 if (!err) {
5079                         sinfo->filled |= (STATION_INFO_RX_PACKETS |
5080                                 STATION_INFO_RX_DROP_MISC |
5081                                 STATION_INFO_TX_PACKETS |
5082                                 STATION_INFO_TX_FAILED);
5083                         sinfo->rx_packets = pktcnt.rx_good_pkt;
5084                         sinfo->rx_dropped_misc = pktcnt.rx_bad_pkt;
5085                         sinfo->tx_packets = pktcnt.tx_good_pkt;
5086                         sinfo->tx_failed  = pktcnt.tx_bad_pkt;
5087                 }
5088 get_station_err:
5089                 if (err && (err != -ERESTARTSYS)) {
5090                         /* Disconnect due to zero BSSID or error to get RSSI */
5091                         WL_ERR(("force cfg80211_disconnected: %d\n", err));
5092                         wl_clr_drv_status(cfg, CONNECTED, dev);
5093                         cfg80211_disconnected(dev, 0, NULL, 0, GFP_KERNEL);
5094                         wl_link_down(cfg);
5095                 }
5096         }
5097         else {
5098                 WL_ERR(("Invalid device mode %d\n", wl_get_mode_by_netdev(cfg, dev)));
5099         }
5100
5101         return err;
5102 }
5103
5104 static s32
5105 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
5106         bool enabled, s32 timeout)
5107 {
5108         s32 pm;
5109         s32 err = 0;
5110         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5111         struct net_info *_net_info = wl_get_netinfo_by_netdev(cfg, dev);
5112
5113         RETURN_EIO_IF_NOT_UP(cfg);
5114         WL_DBG(("Enter\n"));
5115         if (cfg->p2p_net == dev || _net_info == NULL || cfg->vsdb_mode ||
5116                 !wl_get_drv_status(cfg, CONNECTED, dev)) {
5117                 return err;
5118         }
5119
5120         /* Delete pm_enable_work */
5121         wl_add_remove_pm_enable_work(cfg, FALSE, WL_HANDLER_PEND);
5122
5123         pm = enabled ? PM_FAST : PM_OFF;
5124         if (_net_info->pm_block) {
5125                 WL_ERR(("%s:Do not enable the power save for pm_block %d\n",
5126                         dev->name, _net_info->pm_block));
5127                 pm = PM_OFF;
5128         }
5129         pm = htod32(pm);
5130         WL_DBG(("%s:power save %s\n", dev->name, (pm ? "enabled" : "disabled")));
5131         err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true);
5132         if (unlikely(err)) {
5133                 if (err == -ENODEV)
5134                         WL_DBG(("net_device is not ready yet\n"));
5135                 else
5136                         WL_ERR(("error (%d)\n", err));
5137                 return err;
5138         }
5139         wl_cfg80211_update_power_mode(dev);
5140         return err;
5141 }
5142
5143 void wl_cfg80211_update_power_mode(struct net_device *dev)
5144 {
5145         int err, pm = -1;
5146
5147         err = wldev_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), true);
5148         if (err)
5149                 WL_ERR(("%s:error (%d)\n", __FUNCTION__, err));
5150         else if (pm != -1 && dev->ieee80211_ptr)
5151                 dev->ieee80211_ptr->ps = (pm == PM_OFF) ? false : true;
5152 }
5153
5154 static __used u32 wl_find_msb(u16 bit16)
5155 {
5156         u32 ret = 0;
5157
5158         if (bit16 & 0xff00) {
5159                 ret += 8;
5160                 bit16 >>= 8;
5161         }
5162
5163         if (bit16 & 0xf0) {
5164                 ret += 4;
5165                 bit16 >>= 4;
5166         }
5167
5168         if (bit16 & 0xc) {
5169                 ret += 2;
5170                 bit16 >>= 2;
5171         }
5172
5173         if (bit16 & 2)
5174                 ret += bit16 & 2;
5175         else if (bit16)
5176                 ret += bit16;
5177
5178         return ret;
5179 }
5180
5181 static s32 wl_cfg80211_resume(struct wiphy *wiphy)
5182 {
5183         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5184         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
5185         s32 err = 0;
5186
5187         if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
5188                 WL_INFORM(("device is not ready\n"));
5189                 return 0;
5190         }
5191
5192         return err;
5193 }
5194
5195 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
5196 static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
5197 #else
5198 static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
5199 #endif
5200 {
5201 #ifdef DHD_CLEAR_ON_SUSPEND
5202         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5203         struct net_info *iter, *next;
5204         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
5205         unsigned long flags;
5206         if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
5207                 WL_INFORM(("device is not ready : status (%d)\n",
5208                         (int)cfg->status));
5209                 return 0;
5210         }
5211         for_each_ndev(cfg, iter, next)
5212                 wl_set_drv_status(cfg, SCAN_ABORTING, iter->ndev);
5213         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
5214         if (cfg->scan_request) {
5215 #ifdef CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA
5216                 TEGRA_SCAN_DONE(cfg->scan_request, true)
5217 #endif
5218                 cfg80211_scan_done(cfg->scan_request, true);
5219 #ifdef CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA
5220 skip_cfg80211_scan_done:
5221 #endif
5222                 cfg->scan_request = NULL;
5223         }
5224         for_each_ndev(cfg, iter, next) {
5225                 wl_clr_drv_status(cfg, SCANNING, iter->ndev);
5226                 wl_clr_drv_status(cfg, SCAN_ABORTING, iter->ndev);
5227         }
5228         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
5229         for_each_ndev(cfg, iter, next) {
5230                 if (wl_get_drv_status(cfg, CONNECTING, iter->ndev)) {
5231                         wl_bss_connect_done(cfg, iter->ndev, NULL, NULL, false);
5232                 }
5233         }
5234 #endif /* DHD_CLEAR_ON_SUSPEND */
5235         return 0;
5236 }
5237
5238 static s32
5239 wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
5240         s32 err)
5241 {
5242         int i, j;
5243         struct bcm_cfg80211 *cfg = g_bcm_cfg;
5244         struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
5245
5246         if (!pmk_list) {
5247                 printk("pmk_list is NULL\n");
5248                 return -EINVAL;
5249         }
5250         /* pmk list is supported only for STA interface i.e. primary interface
5251          * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
5252          */
5253         if (primary_dev != dev) {
5254                 WL_INFORM(("Not supporting Flushing pmklist on virtual"
5255                         " interfaces than primary interface\n"));
5256                 return err;
5257         }
5258
5259         WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
5260         for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
5261                 WL_DBG(("PMKID[%d]: %pM =\n", i,
5262                         &pmk_list->pmkids.pmkid[i].BSSID));
5263                 for (j = 0; j < WPA2_PMKID_LEN; j++) {
5264                         WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
5265                 }
5266         }
5267         if (likely(!err)) {
5268                 err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmk_list,
5269                         sizeof(*pmk_list), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
5270         }
5271
5272         return err;
5273 }
5274
5275 static s32
5276 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
5277         struct cfg80211_pmksa *pmksa)
5278 {
5279         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5280         s32 err = 0;
5281         int i;
5282
5283         if (pmksa == NULL) {
5284                 WL_ERR(("pmksa is null\n"));
5285                 return -EINVAL;
5286         }
5287
5288         RETURN_EIO_IF_NOT_UP(cfg);
5289         for (i = 0; i < cfg->pmk_list->pmkids.npmkid; i++)
5290                 if (!memcmp(pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
5291                         ETHER_ADDR_LEN))
5292                         break;
5293         if (i < WL_NUM_PMKIDS_MAX) {
5294                 memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
5295                         ETHER_ADDR_LEN);
5296                 memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
5297                         WPA2_PMKID_LEN);
5298                 if (i == cfg->pmk_list->pmkids.npmkid)
5299                         cfg->pmk_list->pmkids.npmkid++;
5300         } else {
5301                 err = -EINVAL;
5302         }
5303         WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
5304                 &cfg->pmk_list->pmkids.pmkid[cfg->pmk_list->pmkids.npmkid - 1].BSSID));
5305         for (i = 0; i < WPA2_PMKID_LEN; i++) {
5306                 WL_DBG(("%02x\n",
5307                         cfg->pmk_list->pmkids.pmkid[cfg->pmk_list->pmkids.npmkid - 1].
5308                         PMKID[i]));
5309         }
5310
5311         err = wl_update_pmklist(dev, cfg->pmk_list, err);
5312
5313         return err;
5314 }
5315
5316 static s32
5317 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
5318         struct cfg80211_pmksa *pmksa)
5319 {
5320         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5321         struct _pmkid_list pmkid = {0};
5322         s32 err = 0;
5323         int i;
5324
5325         if (pmksa == NULL) {
5326                 WL_ERR(("pmksa is null\n"));
5327                 return -EINVAL;
5328         }
5329
5330         RETURN_EIO_IF_NOT_UP(cfg);
5331         memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
5332         memcpy(pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
5333
5334         WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
5335                 &pmkid.pmkid[0].BSSID));
5336         for (i = 0; i < WPA2_PMKID_LEN; i++) {
5337                 WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
5338         }
5339
5340         for (i = 0; i < cfg->pmk_list->pmkids.npmkid; i++)
5341                 if (!memcmp
5342                     (pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
5343                      ETHER_ADDR_LEN))
5344                         break;
5345
5346         if ((cfg->pmk_list->pmkids.npmkid > 0) &&
5347                 (i < cfg->pmk_list->pmkids.npmkid)) {
5348                 memset(&cfg->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
5349                 for (; i < (cfg->pmk_list->pmkids.npmkid - 1); i++) {
5350                         memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID,
5351                                 &cfg->pmk_list->pmkids.pmkid[i + 1].BSSID,
5352                                 ETHER_ADDR_LEN);
5353                         memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID,
5354                                 &cfg->pmk_list->pmkids.pmkid[i + 1].PMKID,
5355                                 WPA2_PMKID_LEN);
5356                 }
5357                 cfg->pmk_list->pmkids.npmkid--;
5358         } else {
5359                 err = -EINVAL;
5360         }
5361
5362         err = wl_update_pmklist(dev, cfg->pmk_list, err);
5363
5364         return err;
5365
5366 }
5367
5368 static s32
5369 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
5370 {
5371         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5372         s32 err = 0;
5373         RETURN_EIO_IF_NOT_UP(cfg);
5374         memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list));
5375         err = wl_update_pmklist(dev, cfg->pmk_list, err);
5376         return err;
5377
5378 }
5379
5380 static wl_scan_params_t *
5381 wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size)
5382 {
5383         wl_scan_params_t *params;
5384         int params_size;
5385         int num_chans;
5386
5387         *out_params_size = 0;
5388
5389         /* Our scan params only need space for 1 channel and 0 ssids */
5390         params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16);
5391         params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL);
5392         if (params == NULL) {
5393                 WL_ERR(("mem alloc failed (%d bytes)\n", params_size));
5394                 return params;
5395         }
5396         memset(params, 0, params_size);
5397         params->nprobes = nprobes;
5398
5399         num_chans = (channel == 0) ? 0 : 1;
5400
5401         memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
5402         params->bss_type = DOT11_BSSTYPE_ANY;
5403         params->scan_type = DOT11_SCANTYPE_ACTIVE;
5404         params->nprobes = htod32(1);
5405         params->active_time = htod32(-1);
5406         params->passive_time = htod32(-1);
5407         params->home_time = htod32(10);
5408         if (channel == -1)
5409                 params->channel_list[0] = htodchanspec(channel);
5410         else
5411                 params->channel_list[0] = wl_ch_host_to_driver(channel);
5412
5413         /* Our scan params have 1 channel and 0 ssids */
5414         params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
5415                 (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
5416
5417         *out_params_size = params_size; /* rtn size to the caller */
5418         return params;
5419 }
5420
5421 #if defined(WL_CFG80211_P2P_DEV_IF)
5422 static s32
5423 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
5424         struct ieee80211_channel *channel, unsigned int duration, u64 *cookie)
5425 #else
5426 static s32
5427 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
5428         struct ieee80211_channel * channel,
5429         enum nl80211_channel_type channel_type,
5430         unsigned int duration, u64 *cookie)
5431 #endif /* WL_CFG80211_P2P_DEV_IF */
5432 {
5433         s32 target_channel;
5434         u32 id;
5435         s32 err = BCME_OK;
5436         struct ether_addr primary_mac;
5437         struct net_device *ndev = NULL;
5438         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5439
5440         if (!cfg)
5441                 return -EINVAL;
5442
5443         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
5444
5445         WL_DBG(("Enter, channel: %d, duration ms (%d) SCANNING ?? %s \n",
5446                 ieee80211_frequency_to_channel(channel->center_freq),
5447                 duration, (wl_get_drv_status(cfg, SCANNING, ndev)) ? "YES":"NO"));
5448
5449         if (!cfg->p2p) {
5450                 WL_ERR(("cfg->p2p is not initialized\n"));
5451                 err = BCME_ERROR;
5452                 goto exit;
5453         }
5454
5455 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5456         if (wl_get_drv_status_all(cfg, SCANNING)) {
5457                 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
5458         }
5459 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5460
5461         target_channel = ieee80211_frequency_to_channel(channel->center_freq);
5462         memcpy(&cfg->remain_on_chan, channel, sizeof(struct ieee80211_channel));
5463 #if defined(WL_ENABLE_P2P_IF)
5464         cfg->remain_on_chan_type = channel_type;
5465 #endif /* WL_ENABLE_P2P_IF */
5466         id = ++cfg->last_roc_id;
5467         if (id == 0)
5468                 id = ++cfg->last_roc_id;
5469         *cookie = id;
5470
5471 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5472         if (wl_get_drv_status(cfg, SCANNING, ndev)) {
5473                 struct timer_list *_timer;
5474                 WL_DBG(("scan is running. go to fake listen state\n"));
5475
5476                 if (duration > LONG_LISTEN_TIME) {
5477                         wl_cfg80211_scan_abort(cfg);
5478                 } else {
5479                         wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
5480
5481                         if (timer_pending(&cfg->p2p->listen_timer)) {
5482                                 WL_DBG(("cancel current listen timer \n"));
5483                                 del_timer_sync(&cfg->p2p->listen_timer);
5484                         }
5485
5486                         _timer = &cfg->p2p->listen_timer;
5487                         wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
5488
5489                         INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration, 0);
5490
5491                         err = BCME_OK;
5492                         goto exit;
5493                 }
5494         }
5495 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5496
5497 #ifdef WL_CFG80211_SYNC_GON
5498         if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
5499                 /* do not enter listen mode again if we are in listen mode already for next af.
5500                  * remain on channel completion will be returned by waiting next af completion.
5501                  */
5502 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5503                 wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
5504 #else
5505                 wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
5506 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5507                 goto exit;
5508         }
5509 #endif /* WL_CFG80211_SYNC_GON */
5510         if (cfg->p2p && !cfg->p2p->on) {
5511                 /* In case of p2p_listen command, supplicant send remain_on_channel
5512                  * without turning on P2P
5513                  */
5514                 get_primary_mac(cfg, &primary_mac);
5515                 wl_cfgp2p_generate_bss_mac(&primary_mac, &cfg->p2p->dev_addr, &cfg->p2p->int_addr);
5516                 p2p_on(cfg) = true;
5517         }
5518
5519         if (p2p_is_on(cfg)) {
5520                 err = wl_cfgp2p_enable_discovery(cfg, ndev, NULL, 0);
5521                 if (unlikely(err)) {
5522                         goto exit;
5523                 }
5524 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5525                 wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
5526 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5527                 err = wl_cfgp2p_discover_listen(cfg, target_channel, duration);
5528
5529 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5530                 if (err == BCME_OK) {
5531                         wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
5532                 } else {
5533                         /* if failed, firmware may be internal scanning state.
5534                          * so other scan request shall not abort it
5535                          */
5536                         wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
5537                 }
5538 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5539                 /* WAR: set err = ok to prevent cookie mismatch in wpa_supplicant
5540                  * and expire timer will send a completion to the upper layer
5541                  */
5542                 err = BCME_OK;
5543         }
5544
5545 exit:
5546         if (err == BCME_OK) {
5547                 WL_INFORM(("Success\n"));
5548 #if defined(WL_CFG80211_P2P_DEV_IF)
5549                 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
5550                         duration, GFP_KERNEL);
5551 #else
5552                 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
5553                         channel_type, duration, GFP_KERNEL);
5554 #endif /* WL_CFG80211_P2P_DEV_IF */
5555         } else {
5556                 WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err, *cookie));
5557         }
5558         return err;
5559 }
5560
5561 static s32
5562 wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
5563         bcm_struct_cfgdev *cfgdev, u64 cookie)
5564 {
5565         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5566         s32 err = 0;
5567
5568 #ifdef P2PLISTEN_AP_SAMECHN
5569         struct bcm_cfg80211 *cfg = g_bcm_cfg;
5570         struct net_device *dev;
5571 #endif /* P2PLISTEN_AP_SAMECHN */
5572
5573         RETURN_EIO_IF_NOT_UP(cfg);
5574 #if defined(WL_CFG80211_P2P_DEV_IF)
5575         if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
5576                 WL_DBG((" enter ) on P2P dedicated discover interface\n"));
5577         }
5578 #else
5579         WL_DBG((" enter ) netdev_ifidx: %d \n", cfgdev->ifindex));
5580 #endif /* WL_CFG80211_P2P_DEV_IF */
5581
5582 #ifdef P2PLISTEN_AP_SAMECHN
5583         if (cfg && cfg->p2p_resp_apchn_status) {
5584                 dev = bcmcfg_to_prmry_ndev(cfg);
5585                 wl_cfg80211_set_p2p_resp_ap_chn(dev, 0);
5586                 cfg->p2p_resp_apchn_status = false;
5587                 WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
5588         }
5589 #endif /* P2PLISTEN_AP_SAMECHN */
5590
5591         if (cfg->last_roc_id == cookie) {
5592                 wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
5593                         wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
5594         } else {
5595                 WL_ERR(("%s : ignore, request cookie(%llu) is not matched. (cur : %llu)\n",
5596                         __FUNCTION__, cookie, cfg->last_roc_id));
5597         }
5598
5599         return err;
5600 }
5601
5602 static void
5603 wl_cfg80211_afx_handler(struct work_struct *work)
5604 {
5605         struct afx_hdl *afx_instance;
5606         struct bcm_cfg80211 *cfg = g_bcm_cfg;
5607         s32 ret = BCME_OK;
5608
5609         afx_instance = container_of(work, struct afx_hdl, work);
5610         if (afx_instance != NULL && cfg->afx_hdl->is_active) {
5611                 if (cfg->afx_hdl->is_listen && cfg->afx_hdl->my_listen_chan) {
5612                         ret = wl_cfgp2p_discover_listen(cfg, cfg->afx_hdl->my_listen_chan,
5613                                 (100 * (1 + (RANDOM32() % 3)))); /* 100ms ~ 300ms */
5614                 } else {
5615                         ret = wl_cfgp2p_act_frm_search(cfg, cfg->afx_hdl->dev,
5616                                 cfg->afx_hdl->bssidx, cfg->afx_hdl->peer_listen_chan,
5617                                 NULL);
5618                 }
5619                 if (unlikely(ret != BCME_OK)) {
5620                         WL_ERR(("ERROR occurred! returned value is (%d)\n", ret));
5621                         if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL))
5622                                 complete(&cfg->act_frm_scan);
5623                 }
5624         }
5625 }
5626
5627 static s32
5628 wl_cfg80211_af_searching_channel(struct bcm_cfg80211 *cfg, struct net_device *dev)
5629 {
5630         u32 max_retry = WL_CHANNEL_SYNC_RETRY;
5631
5632         if (dev == NULL)
5633                 return -1;
5634
5635         WL_DBG((" enter ) \n"));
5636
5637         wl_set_drv_status(cfg, FINDING_COMMON_CHANNEL, dev);
5638         cfg->afx_hdl->is_active = TRUE;
5639
5640         /* Loop to wait until we find a peer's channel or the
5641          * pending action frame tx is cancelled.
5642          */
5643         while ((cfg->afx_hdl->retry < max_retry) &&
5644                 (cfg->afx_hdl->peer_chan == WL_INVALID)) {
5645                 cfg->afx_hdl->is_listen = FALSE;
5646                 wl_set_drv_status(cfg, SCANNING, dev);
5647                 WL_DBG(("Scheduling the action frame for sending.. retry %d\n",
5648                         cfg->afx_hdl->retry));
5649                 /* search peer on peer's listen channel */
5650           &nbs