b04a5146e2fd005861a2ba77bc0667d10f415668
[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 = request->ssids[i].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                 WL_ERR(("Invalid parameter\n"));
3543                 return -EINVAL;
3544         }
3545 #if defined(WL_CFG80211_P2P_DEV_IF)
3546         chan = params->chandef.chan;
3547 #else
3548         chan = params->channel;
3549 #endif /* WL_CFG80211_P2P_DEV_IF */
3550         if (chan)
3551                 cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
3552         if (wl_get_drv_status(cfg, CONNECTED, dev)) {
3553                 struct wlc_ssid *ssid = (struct wlc_ssid *)wl_read_prof(cfg, dev, WL_PROF_SSID);
3554                 u8 *bssid = (u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID);
3555                 u32 *channel = (u32 *)wl_read_prof(cfg, dev, WL_PROF_CHAN);
3556                 if (!params->bssid || ((memcmp(params->bssid, bssid, ETHER_ADDR_LEN) == 0) &&
3557                         (memcmp(params->ssid, ssid->SSID, ssid->SSID_len) == 0) &&
3558                         (*channel == cfg->channel))) {
3559                         WL_ERR(("Connection already existed to " MACDBG "\n",
3560                                 MAC2STRDBG((u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID))));
3561                         return -EISCONN;
3562                 }
3563                 WL_ERR(("Ignore Previous connecton to %s (" MACDBG ")\n",
3564                         ssid->SSID, MAC2STRDBG(bssid)));
3565         }
3566
3567         /* remove the VSIE */
3568         wl_cfg80211_ibss_vsie_delete(dev);
3569
3570         bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
3571         if (!bss) {
3572                 if (IBSS_INITIAL_SCAN_ALLOWED == TRUE) {
3573                         memcpy(ssid.ssid, params->ssid, params->ssid_len);
3574                         ssid.ssid_len = params->ssid_len;
3575                         do {
3576                                 if (unlikely
3577                                         (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
3578                                          -EBUSY)) {
3579                                         wl_delay(150);
3580                                 } else {
3581                                         break;
3582                                 }
3583                         } while (++scan_retry < WL_SCAN_RETRY_MAX);
3584
3585                         /* rtnl lock code is removed here. don't see why rtnl lock
3586                          * needs to be released.
3587                          */
3588
3589                         /* wait 4 secons till scan done.... */
3590                         schedule_timeout_interruptible(msecs_to_jiffies(4000));
3591
3592                         bss = cfg80211_get_ibss(wiphy, NULL,
3593                                 params->ssid, params->ssid_len);
3594                 }
3595         }
3596         if (bss && ((IBSS_COALESCE_ALLOWED == TRUE) ||
3597                 ((IBSS_COALESCE_ALLOWED == FALSE) && params->bssid &&
3598                 !memcmp(bss->bssid, params->bssid, ETHER_ADDR_LEN)))) {
3599                 cfg->ibss_starter = false;
3600                 WL_DBG(("Found IBSS\n"));
3601         } else {
3602                 cfg->ibss_starter = true;
3603         }
3604         if (chan) {
3605                 if (chan->band == IEEE80211_BAND_5GHZ)
3606                         param[0] = WLC_BAND_5G;
3607                 else if (chan->band == IEEE80211_BAND_2GHZ)
3608                         param[0] = WLC_BAND_2G;
3609                 err = wldev_iovar_getint(dev, "bw_cap", param);
3610                 if (unlikely(err)) {
3611                         WL_ERR(("Get bw_cap Failed (%d)\n", err));
3612                         return err;
3613                 }
3614                 bw_cap = param[0];
3615                 chanspec = channel_to_chanspec(wiphy, dev, cfg->channel, bw_cap);
3616         }
3617         /*
3618          * Join with specific BSSID and cached SSID
3619          * If SSID is zero join based on BSSID only
3620          */
3621         memset(&join_params, 0, sizeof(join_params));
3622         memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
3623                 params->ssid_len);
3624         join_params.ssid.SSID_len = htod32(params->ssid_len);
3625         if (params->bssid) {
3626                 memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
3627                 err = wldev_ioctl(dev, WLC_SET_DESIRED_BSSID, &join_params.params.bssid,
3628                         ETHER_ADDR_LEN, true);
3629                 if (unlikely(err)) {
3630                         WL_ERR(("Error (%d)\n", err));
3631                         return err;
3632                 }
3633         } else
3634                 memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
3635         wldev_iovar_setint(dev, "ibss_coalesce_allowed", IBSS_COALESCE_ALLOWED);
3636
3637         if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
3638                 scan_suppress = TRUE;
3639                 /* Set the SCAN SUPPRESS Flag in the firmware to skip join scan */
3640                 err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS,
3641                         &scan_suppress, sizeof(int), true);
3642                 if (unlikely(err)) {
3643                         WL_ERR(("Scan Suppress Setting Failed (%d)\n", err));
3644                         return err;
3645                 }
3646         }
3647
3648         join_params.params.chanspec_list[0] = chanspec;
3649         join_params.params.chanspec_num = 1;
3650         wldev_iovar_setint(dev, "chanspec", chanspec);
3651         join_params_size = sizeof(join_params);
3652
3653         /* Disable Authentication, IBSS will add key if it required */
3654         wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
3655         wldev_iovar_setint(dev, "wsec", 0);
3656
3657
3658         err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
3659                 join_params_size, true);
3660         if (unlikely(err)) {
3661                 WL_ERR(("Error (%d)\n", err));
3662                 return err;
3663         }
3664
3665         if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
3666                 scan_suppress = FALSE;
3667                 /* Reset the SCAN SUPPRESS Flag */
3668                 err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS,
3669                         &scan_suppress, sizeof(int), true);
3670                 if (unlikely(err)) {
3671                         WL_ERR(("Reset Scan Suppress Flag Failed (%d)\n", err));
3672                         return err;
3673                 }
3674         }
3675         wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
3676         wl_update_prof(cfg, dev, NULL, &cfg->channel, WL_PROF_CHAN);
3677         cfg->rmc_event_seq = 0; /* initialize rmcfail sequence */
3678         return err;
3679 }
3680
3681 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
3682 {
3683         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3684         s32 err = 0;
3685         scb_val_t scbval;
3686         u8 *curbssid;
3687
3688         RETURN_EIO_IF_NOT_UP(cfg);
3689         wl_link_down(cfg);
3690
3691         WL_ERR(("Leave IBSS\n"));
3692         curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
3693         wl_set_drv_status(cfg, DISCONNECTING, dev);
3694         scbval.val = 0;
3695         memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
3696         err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
3697                 sizeof(scb_val_t), true);
3698         if (unlikely(err)) {
3699                 wl_clr_drv_status(cfg, DISCONNECTING, dev);
3700                 WL_ERR(("error(%d)\n", err));
3701                 return err;
3702         }
3703
3704         /* remove the VSIE */
3705         wl_cfg80211_ibss_vsie_delete(dev);
3706
3707         return err;
3708 }
3709
3710 #ifdef MFP
3711 static int wl_cfg80211_get_rsn_capa(bcm_tlv_t *wpa2ie, u8* capa)
3712 {
3713         u16 suite_count;
3714         wpa_suite_mcast_t *mcast;
3715         wpa_suite_ucast_t *ucast;
3716         u16 len;
3717         wpa_suite_auth_key_mgmt_t *mgmt;
3718
3719         if (!wpa2ie)
3720                 return -1;
3721
3722         len = wpa2ie->len;
3723         mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
3724         if ((len -= WPA_SUITE_LEN) <= 0)
3725                 return BCME_BADLEN;
3726         ucast = (wpa_suite_ucast_t *)&mcast[1];
3727         suite_count = ltoh16_ua(&ucast->count);
3728         if ((suite_count > NL80211_MAX_NR_CIPHER_SUITES) ||
3729                 (len -= (WPA_IE_SUITE_COUNT_LEN +
3730                 (WPA_SUITE_LEN * suite_count))) <= 0)
3731                 return BCME_BADLEN;
3732
3733         mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
3734         suite_count = ltoh16_ua(&mgmt->count);
3735
3736         if ((suite_count > NL80211_MAX_NR_CIPHER_SUITES) ||
3737                 (len -= (WPA_IE_SUITE_COUNT_LEN +
3738                 (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
3739                 capa[0] = *(u8 *)&mgmt->list[suite_count];
3740                 capa[1] = *((u8 *)&mgmt->list[suite_count] + 1);
3741         } else
3742                 return BCME_BADLEN;
3743
3744         return 0;
3745 }
3746 #endif /* MFP */
3747
3748 static s32
3749 wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
3750 {
3751         struct bcm_cfg80211 *cfg = g_bcm_cfg;
3752         struct wl_security *sec;
3753         s32 val = 0;
3754         s32 err = 0;
3755         s32 bssidx;
3756         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
3757                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3758                 return BCME_ERROR;
3759         }
3760
3761         if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
3762                 val = WPA_AUTH_PSK |
3763                         WPA_AUTH_UNSPECIFIED;
3764         else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
3765                 val = WPA2_AUTH_PSK|
3766                         WPA2_AUTH_UNSPECIFIED;
3767         else
3768                 val = WPA_AUTH_DISABLED;
3769
3770         if (is_wps_conn(sme))
3771                 val = WPA_AUTH_DISABLED;
3772
3773         WL_DBG(("setting wpa_auth to 0x%0x\n", val));
3774         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
3775         if (unlikely(err)) {
3776                 WL_ERR(("set wpa_auth failed (%d)\n", err));
3777                 return err;
3778         }
3779         sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
3780         sec->wpa_versions = sme->crypto.wpa_versions;
3781         return err;
3782 }
3783
3784
3785 static s32
3786 wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
3787 {
3788         struct bcm_cfg80211 *cfg = g_bcm_cfg;
3789         struct wl_security *sec;
3790         s32 val = 0;
3791         s32 err = 0;
3792         s32 bssidx;
3793         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
3794                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3795                 return BCME_ERROR;
3796         }
3797
3798         switch (sme->auth_type) {
3799         case NL80211_AUTHTYPE_OPEN_SYSTEM:
3800                 val = WL_AUTH_OPEN_SYSTEM;
3801                 WL_DBG(("open system\n"));
3802                 break;
3803         case NL80211_AUTHTYPE_SHARED_KEY:
3804                 val = WL_AUTH_SHARED_KEY;
3805                 WL_DBG(("shared key\n"));
3806                 break;
3807         case NL80211_AUTHTYPE_AUTOMATIC:
3808                 val = WL_AUTH_OPEN_SHARED;
3809                 WL_DBG(("automatic\n"));
3810                 break;
3811         default:
3812                 val = 2;
3813                 WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
3814                 break;
3815         }
3816
3817         err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
3818         if (unlikely(err)) {
3819                 WL_ERR(("set auth failed (%d)\n", err));
3820                 return err;
3821         }
3822         sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
3823         sec->auth_type = sme->auth_type;
3824         return err;
3825 }
3826
3827 static s32
3828 wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
3829 {
3830         struct bcm_cfg80211 *cfg = g_bcm_cfg;
3831         struct wl_security *sec;
3832         s32 pval = 0;
3833         s32 gval = 0;
3834         s32 err = 0;
3835         s32 wsec_val = 0;
3836 #ifdef MFP
3837         s32 mfp = 0;
3838         bcm_tlv_t *wpa2_ie;
3839         u8 rsn_cap[2];
3840 #endif /* MFP */
3841
3842         s32 bssidx;
3843         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
3844                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3845                 return BCME_ERROR;
3846         }
3847
3848         if (sme->crypto.n_ciphers_pairwise) {
3849                 switch (sme->crypto.ciphers_pairwise[0]) {
3850                 case WLAN_CIPHER_SUITE_WEP40:
3851                 case WLAN_CIPHER_SUITE_WEP104:
3852                         pval = WEP_ENABLED;
3853                         break;
3854                 case WLAN_CIPHER_SUITE_TKIP:
3855                         pval = TKIP_ENABLED;
3856                         break;
3857                 case WLAN_CIPHER_SUITE_CCMP:
3858                 case WLAN_CIPHER_SUITE_AES_CMAC:
3859                         pval = AES_ENABLED;
3860                         break;
3861                 default:
3862                         WL_ERR(("invalid cipher pairwise (%d)\n",
3863                                 sme->crypto.ciphers_pairwise[0]));
3864                         return -EINVAL;
3865                 }
3866         }
3867         if (sme->crypto.cipher_group) {
3868                 switch (sme->crypto.cipher_group) {
3869                 case WLAN_CIPHER_SUITE_WEP40:
3870                 case WLAN_CIPHER_SUITE_WEP104:
3871                         gval = WEP_ENABLED;
3872                         break;
3873                 case WLAN_CIPHER_SUITE_TKIP:
3874                         gval = TKIP_ENABLED;
3875                         break;
3876                 case WLAN_CIPHER_SUITE_CCMP:
3877                         gval = AES_ENABLED;
3878                         break;
3879                 case WLAN_CIPHER_SUITE_AES_CMAC:
3880                         gval = AES_ENABLED;
3881                         break;
3882                 default:
3883                         WL_ERR(("invalid cipher group (%d)\n",
3884                                 sme->crypto.cipher_group));
3885                         return -EINVAL;
3886                 }
3887         }
3888
3889         WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
3890
3891         if (is_wps_conn(sme)) {
3892                 if (sme->privacy)
3893                         err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
3894                 else
3895                         /* WPS-2.0 allows no security */
3896                         err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
3897         } else {
3898                         WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC"));
3899                         wsec_val = pval | gval;
3900
3901 #ifdef MFP
3902                         if (pval == AES_ENABLED) {
3903                                 if (((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
3904                                         DOT11_MNG_RSN_ID)) != NULL) &&
3905                                         (wl_cfg80211_get_rsn_capa(wpa2_ie, rsn_cap) == 0)) {
3906
3907                                         if (rsn_cap[0] & RSN_CAP_MFPC) {
3908                                                 /* MFP Capability advertised by supplicant. Check
3909                                                  * whether MFP is supported in the firmware
3910                                                  */
3911                                                 if ((err = wldev_iovar_getint_bsscfg(dev,
3912                                                                 "mfp", &mfp, bssidx)) < 0) {
3913                                                         WL_ERR(("Get MFP failed! "
3914                                                                 "Check MFP support in FW \n"));
3915                                                         return -1;
3916                                                 }
3917
3918                                                 if ((sme->crypto.n_akm_suites == 1) &&
3919                                                         ((sme->crypto.akm_suites[0] ==
3920                                                         WL_AKM_SUITE_MFP_PSK) ||
3921                                                         (sme->crypto.akm_suites[0] ==
3922                                                         WL_AKM_SUITE_MFP_1X))) {
3923                                                         wsec_val |= MFP_SHA256;
3924                                                 } else if (sme->crypto.n_akm_suites > 1) {
3925                                                         WL_ERR(("Multiple AKM Specified \n"));
3926                                                         return -EINVAL;
3927                                                 }
3928
3929                                                 wsec_val |= MFP_CAPABLE;
3930                                                 if (rsn_cap[0] & RSN_CAP_MFPR)
3931                                                         wsec_val |= MFP_REQUIRED;
3932
3933                                                 if (rsn_cap[0] & RSN_CAP_MFPR)
3934                                                         mfp = WL_MFP_REQUIRED;
3935                                                 else
3936                                                         mfp = WL_MFP_CAPABLE;
3937                                                 err = wldev_iovar_setint_bsscfg(dev, "mfp",
3938                                                         mfp, bssidx);
3939                                         }
3940                                 }
3941                         }
3942 #endif /* MFP */
3943                         WL_DBG((" Set WSEC to fW 0x%x \n", wsec_val));
3944                         err = wldev_iovar_setint_bsscfg(dev, "wsec",
3945                                 wsec_val, bssidx);
3946         }
3947         if (unlikely(err)) {
3948                 WL_ERR(("error (%d)\n", err));
3949                 return err;
3950         }
3951
3952         sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
3953         sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
3954         sec->cipher_group = sme->crypto.cipher_group;
3955
3956         return err;
3957 }
3958
3959 static s32
3960 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
3961 {
3962         struct bcm_cfg80211 *cfg = g_bcm_cfg;
3963         struct wl_security *sec;
3964         s32 val = 0;
3965         s32 err = 0;
3966         s32 bssidx;
3967         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
3968                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3969                 return BCME_ERROR;
3970         }
3971
3972         if (sme->crypto.n_akm_suites) {
3973                 err = wldev_iovar_getint(dev, "wpa_auth", &val);
3974                 if (unlikely(err)) {
3975                         WL_ERR(("could not get wpa_auth (%d)\n", err));
3976                         return err;
3977                 }
3978                 if (val & (WPA_AUTH_PSK |
3979                         WPA_AUTH_UNSPECIFIED)) {
3980                         switch (sme->crypto.akm_suites[0]) {
3981                         case WLAN_AKM_SUITE_8021X:
3982                                 val = WPA_AUTH_UNSPECIFIED;
3983                                 break;
3984                         case WLAN_AKM_SUITE_PSK:
3985                                 val = WPA_AUTH_PSK;
3986                                 break;
3987                         default:
3988                                 WL_ERR(("invalid cipher group (%d)\n",
3989                                         sme->crypto.cipher_group));
3990                                 return -EINVAL;
3991                         }
3992                 } else if (val & (WPA2_AUTH_PSK |
3993                         WPA2_AUTH_UNSPECIFIED)) {
3994                         switch (sme->crypto.akm_suites[0]) {
3995                         case WLAN_AKM_SUITE_8021X:
3996                                 val = WPA2_AUTH_UNSPECIFIED;
3997                                 break;
3998 #ifdef MFP
3999                         case WL_AKM_SUITE_MFP_1X:
4000                                 val = WPA2_AUTH_UNSPECIFIED;
4001                                 break;
4002                         case WL_AKM_SUITE_MFP_PSK:
4003                                 val = WPA2_AUTH_PSK;
4004                                 break;
4005 #endif
4006                         case WLAN_AKM_SUITE_PSK:
4007                                 val = WPA2_AUTH_PSK;
4008                                 break;
4009                         default:
4010                                 WL_ERR(("invalid cipher group (%d)\n",
4011                                         sme->crypto.cipher_group));
4012                                 return -EINVAL;
4013                         }
4014                 }
4015                 WL_DBG(("setting wpa_auth to %d\n", val));
4016
4017                 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
4018                 if (unlikely(err)) {
4019                         WL_ERR(("could not set wpa_auth (%d)\n", err));
4020                         return err;
4021                 }
4022         }
4023         sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4024         sec->wpa_auth = sme->crypto.akm_suites[0];
4025
4026         return err;
4027 }
4028
4029 static s32
4030 wl_set_set_sharedkey(struct net_device *dev,
4031         struct cfg80211_connect_params *sme)
4032 {
4033         struct bcm_cfg80211 *cfg = g_bcm_cfg;
4034         struct wl_security *sec;
4035         struct wl_wsec_key key;
4036         s32 val;
4037         s32 err = 0;
4038         s32 bssidx;
4039         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
4040                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4041                 return BCME_ERROR;
4042         }
4043
4044         WL_DBG(("key len (%d)\n", sme->key_len));
4045         if (sme->key_len) {
4046                 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4047                 WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
4048                         sec->wpa_versions, sec->cipher_pairwise));
4049                 if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 |
4050                         NL80211_WPA_VERSION_2)) &&
4051                         (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
4052                 WLAN_CIPHER_SUITE_WEP104)))
4053                 {
4054                         memset(&key, 0, sizeof(key));
4055                         key.len = (u32) sme->key_len;
4056                         key.index = (u32) sme->key_idx;
4057                         if (unlikely(key.len > sizeof(key.data))) {
4058                                 WL_ERR(("Too long key length (%u)\n", key.len));
4059                                 return -EINVAL;
4060                         }
4061                         memcpy(key.data, sme->key, key.len);
4062                         key.flags = WL_PRIMARY_KEY;
4063                         switch (sec->cipher_pairwise) {
4064                         case WLAN_CIPHER_SUITE_WEP40:
4065                                 key.algo = CRYPTO_ALGO_WEP1;
4066                                 break;
4067                         case WLAN_CIPHER_SUITE_WEP104:
4068                                 key.algo = CRYPTO_ALGO_WEP128;
4069                                 break;
4070                         default:
4071                                 WL_ERR(("Invalid algorithm (%d)\n",
4072                                         sme->crypto.ciphers_pairwise[0]));
4073                                 return -EINVAL;
4074                         }
4075                         /* Set the new key/index */
4076                         WL_DBG(("key length (%d) key index (%d) algo (%d)\n",
4077                                 key.len, key.index, key.algo));
4078                         WL_DBG(("key \"%s\"\n", key.data));
4079                         swap_key_from_BE(&key);
4080                         err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
4081                                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4082                         if (unlikely(err)) {
4083                                 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
4084                                 return err;
4085                         }
4086                         if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
4087                                 WL_DBG(("set auth_type to shared key\n"));
4088                                 val = WL_AUTH_SHARED_KEY;       /* shared key */
4089                                 err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
4090                                 if (unlikely(err)) {
4091                                         WL_ERR(("set auth failed (%d)\n", err));
4092                                         return err;
4093                                 }
4094                         }
4095                 }
4096         }
4097         return err;
4098 }
4099
4100 static u8 connect_req_bssid[6];
4101 #if defined(ESCAN_RESULT_PATCH)
4102 static u8 broad_bssid[6];
4103 #endif /* ESCAN_RESULT_PATCH */
4104
4105
4106
4107 #if defined(CUSTOM_SET_CPUCORE) || defined(CONFIG_TCPACK_FASTTX)
4108 static bool wl_get_chan_isvht80(struct net_device *net, dhd_pub_t *dhd)
4109 {
4110         u32 chanspec = 0;
4111         bool isvht80 = 0;
4112
4113         if (wldev_iovar_getint(net, "chanspec", (s32 *)&chanspec) == BCME_OK)
4114                 chanspec = wl_chspec_driver_to_host(chanspec);
4115
4116         isvht80 = chanspec & WL_CHANSPEC_BW_80;
4117         WL_INFO(("%s: chanspec(%x:%d)\n", __FUNCTION__, chanspec, isvht80));
4118
4119         return isvht80;
4120 }
4121 #endif /* CUSTOM_SET_CPUCORE || CONFIG_TCPACK_FASTTX */
4122
4123 static s32
4124 wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
4125         struct cfg80211_connect_params *sme)
4126 {
4127         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4128         struct ieee80211_channel *chan = sme->channel;
4129         wl_extjoin_params_t *ext_join_params;
4130         struct wl_join_params join_params;
4131         size_t join_params_size;
4132 #if defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION)
4133         dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
4134         s32 roam_trigger[2] = {0, 0};
4135 #endif /* ROAM_AP_ENV_DETECTION */
4136         s32 err = 0;
4137         wpa_ie_fixed_t *wpa_ie;
4138         bcm_tlv_t *wpa2_ie;
4139         u8* wpaie  = 0;
4140         u32 wpaie_len = 0;
4141         u32 chan_cnt = 0;
4142         struct ether_addr bssid;
4143         s32 bssidx;
4144         int ret;
4145         int wait_cnt;
4146
4147         WL_DBG(("In\n"));
4148
4149         if (unlikely(!sme->ssid)) {
4150                 WL_ERR(("Invalid ssid\n"));
4151                 return -EOPNOTSUPP;
4152         }
4153
4154         if (unlikely(sme->ssid_len > DOT11_MAX_SSID_LEN)) {
4155                 WL_ERR(("Invalid SSID info: SSID=%s, length=%zd\n",
4156                         sme->ssid, sme->ssid_len));
4157                 return -EINVAL;
4158         }
4159
4160         WL_DBG(("SME IE : len=%zu\n", sme->ie_len));
4161         if (sme->ie != NULL && sme->ie_len > 0 && (wl_dbg_level & WL_DBG_DBG)) {
4162                 prhex(NULL, sme->ie, sme->ie_len);
4163         }
4164
4165         RETURN_EIO_IF_NOT_UP(cfg);
4166
4167         /*
4168          * Cancel ongoing scan to sync up with sme state machine of cfg80211.
4169          */
4170 #if !defined(ESCAN_RESULT_PATCH)
4171         if (cfg->scan_request) {
4172                 wl_notify_escan_complete(cfg, dev, true, true);
4173         }
4174 #endif
4175 #ifdef WL_SCHED_SCAN
4176         if (cfg->sched_scan_req) {
4177                 wl_cfg80211_sched_scan_stop(wiphy, bcmcfg_to_prmry_ndev(cfg));
4178         }
4179 #endif
4180         if (sme->bssid)
4181                 memcpy(connect_req_bssid, sme->bssid, ETHER_ADDR_LEN);
4182         else
4183                 bzero(connect_req_bssid, ETHER_ADDR_LEN);
4184 #if defined(ESCAN_RESULT_PATCH)
4185         bzero(broad_bssid, ETHER_ADDR_LEN);
4186 #endif
4187 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
4188         maxrxpktglom = 0;
4189 #endif
4190         bzero(&bssid, sizeof(bssid));
4191         if (!wl_get_drv_status(cfg, CONNECTED, dev)&&
4192                 (ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false)) == 0) {
4193                 if (!ETHER_ISNULLADDR(&bssid)) {
4194                         scb_val_t scbval;
4195                         wl_set_drv_status(cfg, DISCONNECTING, dev);
4196                         scbval.val = DOT11_RC_DISASSOC_LEAVING;
4197                         memcpy(&scbval.ea, &bssid, ETHER_ADDR_LEN);
4198                         scbval.val = htod32(scbval.val);
4199
4200                         WL_DBG(("drv status CONNECTED is not set, but connected in FW!" MACDBG "/n",
4201                                 MAC2STRDBG(bssid.octet)));
4202                         err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
4203                                 sizeof(scb_val_t), true);
4204                         if (unlikely(err)) {
4205                                 wl_clr_drv_status(cfg, DISCONNECTING, dev);
4206                                 WL_ERR(("error (%d)\n", err));
4207                                 return err;
4208                         }
4209                         wait_cnt = 500/10;
4210                         while (wl_get_drv_status(cfg, DISCONNECTING, dev) && wait_cnt) {
4211                                 WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n",
4212                                         wait_cnt));
4213                                 wait_cnt--;
4214                                 OSL_SLEEP(10);
4215                         }
4216                 } else
4217                         WL_DBG(("Currently not associated!\n"));
4218         } else {
4219                 /* if status is DISCONNECTING, wait for disconnection terminated max 500 ms */
4220                 wait_cnt = 500/10;
4221                 while (wl_get_drv_status(cfg, DISCONNECTING, dev) && wait_cnt) {
4222                         WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n", wait_cnt));
4223                         wait_cnt--;
4224                         OSL_SLEEP(10);
4225                 }
4226         }
4227
4228         /* Clean BSSID */
4229         bzero(&bssid, sizeof(bssid));
4230         if (!wl_get_drv_status(cfg, DISCONNECTING, dev))
4231                 wl_update_prof(cfg, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
4232
4233         if (p2p_is_on(cfg) && (dev != bcmcfg_to_prmry_ndev(cfg))) {
4234                 /* we only allow to connect using virtual interface in case of P2P */
4235                         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
4236                                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4237                                 return BCME_ERROR;
4238                         }
4239                         wl_cfgp2p_set_management_ie(cfg, dev, bssidx,
4240                                 VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
4241         } else if (dev == bcmcfg_to_prmry_ndev(cfg)) {
4242                 /* find the RSN_IE */
4243                 if ((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
4244                         DOT11_MNG_RSN_ID)) != NULL) {
4245                         WL_DBG((" WPA2 IE is found\n"));
4246                 }
4247                 /* find the WPA_IE */
4248                 if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)sme->ie,
4249                         sme->ie_len)) != NULL) {
4250                         WL_DBG((" WPA IE is found\n"));
4251                 }
4252                 if (wpa_ie != NULL || wpa2_ie != NULL) {
4253                         wpaie = (wpa_ie != NULL) ? (u8 *)wpa_ie : (u8 *)wpa2_ie;
4254                         wpaie_len = (wpa_ie != NULL) ? wpa_ie->length : wpa2_ie->len;
4255                         wpaie_len += WPA_RSN_IE_TAG_FIXED_LEN;
4256                         err = wldev_iovar_setbuf(dev, "wpaie", wpaie, wpaie_len,
4257                                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
4258                         if (unlikely(err)) {
4259                                 WL_ERR(("wpaie set error (%d)\n", err));
4260                                 return err;
4261                         }
4262                 } else {
4263                         err = wldev_iovar_setbuf(dev, "wpaie", NULL, 0,
4264                                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
4265                         if (unlikely(err)) {
4266                                 WL_ERR(("wpaie set error (%d)\n", err));
4267                                 return err;
4268                         }
4269                 }
4270
4271                 if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
4272                         WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4273                         return BCME_ERROR;
4274                 }
4275                 err = wl_cfgp2p_set_management_ie(cfg, dev, bssidx,
4276                         VNDR_IE_ASSOCREQ_FLAG, (u8 *)sme->ie, sme->ie_len);
4277                 if (unlikely(err)) {
4278                         return err;
4279                 }
4280         }
4281 #if defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION)
4282         if (dhd->roam_env_detection) {
4283                 bool is_roamtrig_reset = TRUE;
4284                 bool is_roam_env_ok = (wldev_iovar_setint(dev, "roam_env_detection",
4285                         AP_ENV_DETECT_NOT_USED) == BCME_OK);
4286                 if (is_roamtrig_reset && is_roam_env_ok) {
4287                         roam_trigger[0] = WL_AUTO_ROAM_TRIGGER;
4288                         roam_trigger[1] = WLC_BAND_ALL;
4289                 err = wldev_ioctl(dev, WLC_SET_ROAM_TRIGGER, roam_trigger,
4290                         sizeof(roam_trigger), true);
4291                 if (unlikely(err)) {
4292                                 WL_ERR((" failed to restore roam_trigger for auto env"
4293                                         " detection\n"));
4294                         }
4295                 }
4296         }
4297 #endif /* ROAM_ENABLE && ROAM_AP_ENV_DETECTION */
4298         if (chan) {
4299                 cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
4300                 chan_cnt = 1;
4301                 WL_DBG(("channel (%d), center_req (%d), %d channels\n", cfg->channel,
4302                         chan->center_freq, chan_cnt));
4303         } else
4304                 cfg->channel = 0;
4305         WL_DBG(("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len));
4306         WL_DBG(("3. set wapi version \n"));
4307         err = wl_set_wpa_version(dev, sme);
4308         if (unlikely(err)) {
4309                 WL_ERR(("Invalid wpa_version\n"));
4310                 return err;
4311         }
4312                 err = wl_set_auth_type(dev, sme);
4313                 if (unlikely(err)) {
4314                         WL_ERR(("Invalid auth type\n"));
4315                         return err;
4316                 }
4317
4318         err = wl_set_set_cipher(dev, sme);
4319         if (unlikely(err)) {
4320                 WL_ERR(("Invalid ciper\n"));
4321                 return err;
4322         }
4323
4324         err = wl_set_key_mgmt(dev, sme);
4325         if (unlikely(err)) {
4326                 WL_ERR(("Invalid key mgmt\n"));
4327                 return err;
4328         }
4329
4330         err = wl_set_set_sharedkey(dev, sme);
4331         if (unlikely(err)) {
4332                 WL_ERR(("Invalid shared key\n"));
4333                 return err;
4334         }
4335
4336         /*
4337          *  Join with specific BSSID and cached SSID
4338          *  If SSID is zero join based on BSSID only
4339          */
4340         join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE +
4341                 chan_cnt * sizeof(chanspec_t);
4342         ext_join_params =  (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL);
4343         if (ext_join_params == NULL) {
4344                 err = -ENOMEM;
4345                 wl_clr_drv_status(cfg, CONNECTING, dev);
4346                 goto exit;
4347         }
4348         ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len);
4349         memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len);
4350         wl_update_prof(cfg, dev, NULL, &ext_join_params->ssid, WL_PROF_SSID);
4351         ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
4352         /* increate dwell time to receive probe response or detect Beacon
4353         * from target AP at a noisy air only during connect command
4354         */
4355         ext_join_params->scan.active_time = chan_cnt ? WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS : -1;
4356         ext_join_params->scan.passive_time = chan_cnt ? WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS : -1;
4357         /* Set up join scan parameters */
4358         ext_join_params->scan.scan_type = -1;
4359         ext_join_params->scan.nprobes = chan_cnt ?
4360                 (ext_join_params->scan.active_time/WL_SCAN_JOIN_PROBE_INTERVAL_MS) : -1;
4361         ext_join_params->scan.home_time = -1;
4362
4363         if (sme->bssid)
4364                 memcpy(&ext_join_params->assoc.bssid, sme->bssid, ETH_ALEN);
4365         else
4366                 memcpy(&ext_join_params->assoc.bssid, &ether_bcast, ETH_ALEN);
4367         ext_join_params->assoc.chanspec_num = chan_cnt;
4368         if (chan_cnt) {
4369                 u16 channel, band, bw, ctl_sb;
4370                 chanspec_t chspec;
4371                 channel = cfg->channel;
4372                 band = (channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G
4373                         : WL_CHANSPEC_BAND_5G;
4374                 bw = WL_CHANSPEC_BW_20;
4375                 ctl_sb = WL_CHANSPEC_CTL_SB_NONE;
4376                 chspec = (channel | band | bw | ctl_sb);
4377                 ext_join_params->assoc.chanspec_list[0]  &= WL_CHANSPEC_CHAN_MASK;
4378                 ext_join_params->assoc.chanspec_list[0] |= chspec;
4379                 ext_join_params->assoc.chanspec_list[0] =
4380                         wl_chspec_host_to_driver(ext_join_params->assoc.chanspec_list[0]);
4381         }
4382         ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num);
4383         if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
4384                 WL_INFORM(("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID,
4385                         ext_join_params->ssid.SSID_len));
4386         }
4387         wl_set_drv_status(cfg, CONNECTING, dev);
4388
4389         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
4390                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4391                 wl_clr_drv_status(cfg, CONNECTING, dev);
4392                 kfree(ext_join_params);
4393                 return BCME_ERROR;
4394         }
4395         err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size,
4396                 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4397
4398         DHD_NV_INFO(("Connectting with " MACDBG " channel (%d) ssid \"%s\", len (%d)\n\n",
4399                 MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)), cfg->channel,
4400                 ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len));
4401
4402         kfree(ext_join_params);
4403         if (err) {
4404                 wl_clr_drv_status(cfg, CONNECTING, dev);
4405                 if (err == BCME_UNSUPPORTED) {
4406                         WL_DBG(("join iovar is not supported\n"));
4407                         goto set_ssid;
4408                 } else {
4409                         WL_ERR(("error (%d)\n", err));
4410                         goto exit;
4411                 }
4412         } else
4413                 goto exit;
4414
4415 set_ssid:
4416         memset(&join_params, 0, sizeof(join_params));
4417         join_params_size = sizeof(join_params.ssid);
4418
4419         join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
4420         memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
4421         join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
4422         wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
4423         if (sme->bssid)
4424                 memcpy(&join_params.params.bssid, sme->bssid, ETH_ALEN);
4425         else
4426                 memcpy(&join_params.params.bssid, &ether_bcast, ETH_ALEN);
4427
4428         wl_ch_to_chanspec(cfg->channel, &join_params, &join_params_size);
4429         WL_DBG(("join_param_size %zu\n", join_params_size));
4430
4431         if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
4432                 WL_INFORM(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
4433                         join_params.ssid.SSID_len));
4434         }
4435         wl_set_drv_status(cfg, CONNECTING, dev);
4436         err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true);
4437         if (err) {
4438                 WL_ERR(("error (%d)\n", err));
4439                 wl_clr_drv_status(cfg, CONNECTING, dev);
4440         }
4441 exit:
4442         return err;
4443 }
4444
4445 static s32
4446 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
4447         u16 reason_code)
4448 {
4449         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4450         scb_val_t scbval;
4451         bool act = false;
4452         s32 err = 0;
4453         u8 *curbssid;
4454 #ifdef CUSTOM_SET_CPUCORE
4455         dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
4456 #endif /* CUSTOM_SET_CPUCORE */
4457         DHD_NV_INFO(("Reason %d\n", reason_code));
4458 #ifdef CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA
4459         if (bcmdhd_stat.rssi < -67)
4460                 TEGRA_SYSFS_HISTOGRAM_STAT_INC(disconnect_rssi_low);
4461         else
4462                 TEGRA_SYSFS_HISTOGRAM_STAT_INC(disconnect_rssi_high);
4463 #endif
4464         RETURN_EIO_IF_NOT_UP(cfg);
4465         act = *(bool *) wl_read_prof(cfg, dev, WL_PROF_ACT);
4466         curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
4467 #ifdef ESCAN_RESULT_PATCH
4468         if (wl_get_drv_status(cfg, CONNECTING, dev) && curbssid &&
4469                 (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0)) {
4470                 WL_ERR(("Disconnecting from connecting device: " MACDBG "\n",
4471                         MAC2STRDBG(curbssid)));
4472                 act = true;
4473         }
4474 #endif /* ESCAN_RESULT_PATCH */
4475         if (act || wl_get_drv_status(cfg, CONNECTING, dev)) {
4476                 /*
4477                 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
4478                 */
4479                 /* Let scan aborted by F/W */
4480                 if (cfg->scan_request) {
4481                         wl_notify_escan_complete(cfg, dev, true, true);
4482                 }
4483                 wl_clr_drv_status(cfg, CONNECTING, dev);
4484                 wl_set_drv_status(cfg, DISCONNECTING, dev);
4485                 scbval.val = reason_code;
4486                 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
4487                 scbval.val = htod32(scbval.val);
4488                 err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
4489                         sizeof(scb_val_t), true);
4490                 if (unlikely(err)) {
4491                         wl_clr_drv_status(cfg, DISCONNECTING, dev);
4492                         WL_ERR(("error (%d)\n", err));
4493                         return err;
4494                 }
4495         }
4496 #ifdef CUSTOM_SET_CPUCORE
4497         /* set default cpucore */
4498         if (dev == bcmcfg_to_prmry_ndev(cfg)) {
4499                 dhd->chan_isvht80 &= ~DHD_FLAG_STA_MODE;
4500                 if (!(dhd->chan_isvht80))
4501                         dhd_set_cpucore(dhd, FALSE);
4502         }
4503 #endif /* CUSTOM_SET_CPUCORE */
4504
4505         return err;
4506 }
4507
4508 #if defined(WL_CFG80211_P2P_DEV_IF)
4509 static s32
4510 wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
4511         enum nl80211_tx_power_setting type, s32 mbm)
4512 #else
4513 static s32
4514 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
4515         enum nl80211_tx_power_setting type, s32 dbm)
4516 #endif /* WL_CFG80211_P2P_DEV_IF */
4517 {
4518
4519         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4520         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
4521         s32 err = 0;
4522 #if defined(WL_CFG80211_P2P_DEV_IF)
4523         s32 dbm = MBM_TO_DBM(mbm);
4524 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || \
4525         defined(WL_COMPAT_WIRELESS) || defined(WL_SUPPORT_BACKPORTED_KPATCHES)
4526         dbm = MBM_TO_DBM(dbm);
4527 #endif /* WL_CFG80211_P2P_DEV_IF */
4528
4529         RETURN_EIO_IF_NOT_UP(cfg);
4530         switch (type) {
4531         case NL80211_TX_POWER_AUTOMATIC:
4532                 break;
4533         case NL80211_TX_POWER_LIMITED:
4534                 if (dbm < 0) {
4535                         WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
4536                         return -EINVAL;
4537                 }
4538                 break;
4539         case NL80211_TX_POWER_FIXED:
4540                 if (dbm < 0) {
4541                         WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
4542                         return -EINVAL;
4543                 }
4544                 break;
4545         }
4546
4547         err = wl_set_tx_power(ndev, type, dbm);
4548         if (unlikely(err)) {
4549                 WL_ERR(("error (%d)\n", err));
4550                 return err;
4551         }
4552
4553         cfg->conf->tx_power = dbm;
4554
4555         return err;
4556 }
4557
4558 #if defined(WL_CFG80211_P2P_DEV_IF)
4559 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
4560         struct wireless_dev *wdev, s32 *dbm)
4561 #else
4562 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
4563 #endif /* WL_CFG80211_P2P_DEV_IF */
4564 {
4565         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4566         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
4567         s32 err = 0;
4568
4569         RETURN_EIO_IF_NOT_UP(cfg);
4570         err = wl_get_tx_power(ndev, dbm);
4571         if (unlikely(err))
4572                 WL_ERR(("error (%d)\n", err));
4573
4574         return err;
4575 }
4576
4577 static s32
4578 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
4579         u8 key_idx, bool unicast, bool multicast)
4580 {
4581         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4582         u32 index;
4583         s32 wsec;
4584         s32 err = 0;
4585         s32 bssidx;
4586         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
4587                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4588                 return BCME_ERROR;
4589         }
4590
4591         WL_DBG(("key index (%d)\n", key_idx));
4592         RETURN_EIO_IF_NOT_UP(cfg);
4593         err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
4594         if (unlikely(err)) {
4595                 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
4596                 return err;
4597         }
4598         if (wsec == WEP_ENABLED) {
4599                 /* Just select a new current key */
4600                 index = (u32) key_idx;
4601                 index = htod32(index);
4602                 err = wldev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
4603                         sizeof(index), true);
4604                 if (unlikely(err)) {
4605                         WL_ERR(("error (%d)\n", err));
4606                 }
4607         }
4608         return err;
4609 }
4610
4611 static s32
4612 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
4613         u8 key_idx, const u8 *mac_addr, struct key_params *params)
4614 {
4615         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4616         struct wl_wsec_key key;
4617         s32 err = 0;
4618         s32 bssidx;
4619         s32 mode = wl_get_mode_by_netdev(cfg, dev);
4620         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
4621                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4622                 return BCME_ERROR;
4623         }
4624         memset(&key, 0, sizeof(key));
4625         key.index = (u32) key_idx;
4626
4627         if (!ETHER_ISMULTI(mac_addr))
4628                 memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN);
4629         key.len = (u32) params->key_len;
4630
4631         /* check for key index change */
4632         if (key.len == 0) {
4633                 /* key delete */
4634                 swap_key_from_BE(&key);
4635                 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
4636                         cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4637                 if (unlikely(err)) {
4638                         WL_ERR(("key delete error (%d)\n", err));
4639                         return err;
4640                 }
4641         } else {
4642                 if (key.len > sizeof(key.data)) {
4643                         WL_ERR(("Invalid key length (%d)\n", key.len));
4644                         return -EINVAL;
4645                 }
4646                 WL_DBG(("Setting the key index %d\n", key.index));
4647                 memcpy(key.data, params->key, key.len);
4648
4649                 if ((mode == WL_MODE_BSS) &&
4650                         (params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
4651                         u8 keybuf[8];
4652                         memcpy(keybuf, &key.data[24], sizeof(keybuf));
4653                         memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
4654                         memcpy(&key.data[16], keybuf, sizeof(keybuf));
4655                 }
4656
4657                 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
4658                 if (params->seq && params->seq_len == 6) {
4659                         /* rx iv */
4660                         u8 *ivptr;
4661                         ivptr = (u8 *) params->seq;
4662                         key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
4663                                 (ivptr[3] << 8) | ivptr[2];
4664                         key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
4665                         key.iv_initialized = true;
4666                 }
4667
4668                 switch (params->cipher) {
4669                 case WLAN_CIPHER_SUITE_WEP40:
4670                         key.algo = CRYPTO_ALGO_WEP1;
4671                         WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
4672                         break;
4673                 case WLAN_CIPHER_SUITE_WEP104:
4674                         key.algo = CRYPTO_ALGO_WEP128;
4675                         WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
4676                         break;
4677                 case WLAN_CIPHER_SUITE_TKIP:
4678                         key.algo = CRYPTO_ALGO_TKIP;
4679                         WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
4680                         break;
4681                 case WLAN_CIPHER_SUITE_AES_CMAC:
4682                         key.algo = CRYPTO_ALGO_AES_CCM;
4683                         WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
4684                         break;
4685                 case WLAN_CIPHER_SUITE_CCMP:
4686                         key.algo = CRYPTO_ALGO_AES_CCM;
4687                         WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
4688                         break;
4689                 default:
4690                         WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
4691                         return -EINVAL;
4692                 }
4693                 swap_key_from_BE(&key);
4694                 /* need to guarantee EAPOL 4/4 send out before set key */
4695                 if (mode != WL_MODE_AP)
4696                         dhd_wait_pend8021x(dev);
4697                 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
4698                         cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4699                 if (unlikely(err)) {
4700                         WL_ERR(("WLC_SET_KEY error (%d)\n", err));
4701                         return err;
4702                 }
4703         }
4704         return err;
4705 }
4706
4707 int
4708 wl_cfg80211_enable_roam_offload(struct net_device *dev, int enable)
4709 {
4710         int err;
4711         wl_eventmsg_buf_t ev_buf;
4712
4713         if (dev != bcmcfg_to_prmry_ndev(g_bcm_cfg)) {
4714                 /* roam offload is only for the primary device */
4715                 return -1;
4716         }
4717         err = wldev_iovar_setint(dev, "roam_offload", enable);
4718         if (err)
4719                 return err;
4720
4721         bzero(&ev_buf, sizeof(wl_eventmsg_buf_t));
4722         wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_PSK_SUP, !enable);
4723         wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_REQ_IE, !enable);
4724         wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_RESP_IE, !enable);
4725         wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_REASSOC, !enable);
4726         wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_JOIN, !enable);
4727         wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ROAM, !enable);
4728         err = wl_cfg80211_apply_eventbuffer(dev, g_bcm_cfg, &ev_buf);
4729         if (!err) {
4730                 g_bcm_cfg->roam_offload = enable;
4731         }
4732         return err;
4733 }
4734
4735 static s32
4736 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
4737         u8 key_idx, bool pairwise, const u8 *mac_addr,
4738         struct key_params *params)
4739 {
4740         struct wl_wsec_key key;
4741         s32 val = 0;
4742         s32 wsec = 0;
4743         s32 err = 0;
4744         u8 keybuf[8];
4745         s32 bssidx = 0;
4746         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4747         s32 mode = wl_get_mode_by_netdev(cfg, dev);
4748         WL_DBG(("key index (%d)\n", key_idx));
4749         RETURN_EIO_IF_NOT_UP(cfg);
4750
4751         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
4752                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4753                 return BCME_ERROR;
4754         }
4755
4756         if (mac_addr &&
4757                 ((params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
4758                 (params->cipher != WLAN_CIPHER_SUITE_WEP104))) {
4759                         wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
4760                         goto exit;
4761         }
4762         memset(&key, 0, sizeof(key));
4763
4764         key.len = (u32) params->key_len;
4765         key.index = (u32) key_idx;
4766
4767         if (unlikely(key.len > sizeof(key.data))) {
4768                 WL_ERR(("Too long key length (%u)\n", key.len));
4769                 return -EINVAL;
4770         }
4771         memcpy(key.data, params->key, key.len);
4772
4773         key.flags = WL_PRIMARY_KEY;
4774         switch (params->cipher) {
4775         case WLAN_CIPHER_SUITE_WEP40:
4776                 key.algo = CRYPTO_ALGO_WEP1;
4777                 val = WEP_ENABLED;
4778                 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
4779                 break;
4780         case WLAN_CIPHER_SUITE_WEP104:
4781                 key.algo = CRYPTO_ALGO_WEP128;
4782                 val = WEP_ENABLED;
4783                 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
4784                 break;
4785         case WLAN_CIPHER_SUITE_TKIP:
4786                 key.algo = CRYPTO_ALGO_TKIP;
4787                 val = TKIP_ENABLED;
4788                 /* wpa_supplicant switches the third and fourth quarters of the TKIP key */
4789                 if (mode == WL_MODE_BSS) {
4790                         bcopy(&key.data[24], keybuf, sizeof(keybuf));
4791                         bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
4792                         bcopy(keybuf, &key.data[16], sizeof(keybuf));
4793                 }
4794                 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
4795                 break;
4796         case WLAN_CIPHER_SUITE_AES_CMAC:
4797                 key.algo = CRYPTO_ALGO_AES_CCM;
4798                 val = AES_ENABLED;
4799                 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
4800                 break;
4801         case WLAN_CIPHER_SUITE_CCMP:
4802                 key.algo = CRYPTO_ALGO_AES_CCM;
4803                 val = AES_ENABLED;
4804                 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
4805                 break;
4806         default:
4807                 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
4808                 return -EINVAL;
4809         }
4810
4811         /* Set the new key/index */
4812         if ((mode == WL_MODE_IBSS) && (val & (TKIP_ENABLED | AES_ENABLED))) {
4813                 WL_ERR(("IBSS KEY setted\n"));
4814                 wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_NONE);
4815         }
4816         swap_key_from_BE(&key);
4817         err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), cfg->ioctl_buf,
4818                 WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4819         if (unlikely(err)) {
4820                 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
4821                 return err;
4822         }
4823
4824 exit:
4825         err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
4826         if (unlikely(err)) {
4827                 WL_ERR(("get wsec error (%d)\n", err));
4828                 return err;
4829         }
4830
4831         wsec |= val;
4832         err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
4833         if (unlikely(err)) {
4834                 WL_ERR(("set wsec error (%d)\n", err));
4835                 return err;
4836         }
4837
4838         return err;
4839 }
4840
4841 static s32
4842 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
4843         u8 key_idx, bool pairwise, const u8 *mac_addr)
4844 {
4845         struct wl_wsec_key key;
4846         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4847         s32 err = 0;
4848         s32 bssidx;
4849
4850         if (!cfg)
4851                 return -EINVAL;
4852
4853         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
4854                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4855                 return BCME_ERROR;
4856         }
4857         WL_DBG(("Enter\n"));
4858
4859 #ifndef IEEE80211W
4860         if ((key_idx >= DOT11_MAX_DEFAULT_KEYS) && (key_idx < DOT11_MAX_DEFAULT_KEYS+2))
4861                 return -EINVAL;
4862 #endif
4863
4864         RETURN_EIO_IF_NOT_UP(cfg);
4865         memset(&key, 0, sizeof(key));
4866
4867         key.flags = WL_PRIMARY_KEY;
4868         key.algo = CRYPTO_ALGO_OFF;
4869         key.index = (u32) key_idx;
4870
4871         WL_DBG(("key index (%d)\n", key_idx));
4872         /* Set the new key/index */
4873         swap_key_from_BE(&key);
4874         err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), cfg->ioctl_buf,
4875                 WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4876         if (unlikely(err)) {
4877                 if (err == -EINVAL) {
4878                         if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
4879                                 /* we ignore this key index in this case */
4880                                 WL_DBG(("invalid key index (%d)\n", key_idx));
4881                         }
4882                 } else {
4883                         WL_ERR(("WLC_SET_KEY error (%d)\n", err));
4884                 }
4885                 return err;
4886         }
4887         return err;
4888 }
4889
4890 static s32
4891 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
4892         u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
4893         void (*callback) (void *cookie, struct key_params * params))
4894 {
4895         struct key_params params;
4896         struct wl_wsec_key key;
4897         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4898         struct wl_security *sec;
4899         s32 wsec;
4900         s32 err = 0;
4901         s32 bssidx;
4902         if (wl_cfgp2p_find_idx(cfg, dev, &bssidx) != BCME_OK) {
4903                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4904                 return BCME_ERROR;
4905         }
4906         WL_DBG(("key index (%d)\n", key_idx));
4907         RETURN_EIO_IF_NOT_UP(cfg);
4908         memset(&key, 0, sizeof(key));
4909         key.index = key_idx;
4910         swap_key_to_BE(&key);
4911         memset(&params, 0, sizeof(params));
4912         params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
4913         memcpy(params.key, key.data, params.key_len);
4914
4915         err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
4916         if (unlikely(err)) {
4917                 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
4918                 return err;
4919         }
4920         switch (WSEC_ENABLED(wsec)) {
4921                 case WEP_ENABLED:
4922                         sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4923                         if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
4924                                 params.cipher = WLAN_CIPHER_SUITE_WEP40;
4925                                 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
4926                         } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
4927                                 params.cipher = WLAN_CIPHER_SUITE_WEP104;
4928                                 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
4929                         }
4930                         break;
4931                 case TKIP_ENABLED:
4932                         params.cipher = WLAN_CIPHER_SUITE_TKIP;
4933                         WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
4934                         break;
4935                 case AES_ENABLED:
4936                         params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
4937                         WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
4938                         break;
4939                 default:
4940                         WL_ERR(("Invalid algo (0x%x)\n", wsec));
4941                         return -EINVAL;
4942         }
4943
4944         callback(cookie, &params);
4945         return err;
4946 }
4947
4948 static s32
4949 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
4950         struct net_device *dev, u8 key_idx)
4951 {
4952 #ifdef MFP
4953         return 0;
4954 #else
4955         WL_INFORM(("Not supported\n"));
4956         return -EOPNOTSUPP;
4957 #endif /* MFP */
4958 }
4959
4960 static s32
4961 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
4962         u8 *mac, struct station_info *sinfo)
4963 {
4964         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4965         scb_val_t scb_val;
4966         s32 rssi;
4967         s32 rate;
4968         s32 err = 0;
4969         sta_info_t *sta;
4970 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
4971         s8 eabuf[ETHER_ADDR_STR_LEN];
4972 #endif
4973         dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
4974         RETURN_EIO_IF_NOT_UP(cfg);
4975         if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
4976                 err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac,
4977                         ETHER_ADDR_LEN, cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
4978                 if (err < 0) {
4979                         WL_ERR(("GET STA INFO failed, %d\n", err));
4980                         return err;
4981                 }
4982                 sinfo->filled = STATION_INFO_INACTIVE_TIME;
4983                 sta = (sta_info_t *)cfg->ioctl_buf;
4984                 sta->len = dtoh16(sta->len);
4985                 sta->cap = dtoh16(sta->cap);
4986                 sta->flags = dtoh32(sta->flags);
4987                 sta->idle = dtoh32(sta->idle);
4988                 sta->in = dtoh32(sta->in);
4989                 sinfo->inactive_time = sta->idle * 1000;
4990 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
4991                 if (sta->flags & WL_STA_ASSOC) {
4992                         sinfo->filled |= STATION_INFO_CONNECTED_TIME;
4993                         sinfo->connected_time = sta->in;
4994                 }
4995                 WL_INFORM(("STA %s : idle time : %d sec, connected time :%d ms\n",
4996                         bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), sinfo->inactive_time,
4997                         sta->idle * 1000));
4998 #endif
4999         } else if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_BSS ||
5000                 wl_get_mode_by_netdev(cfg, dev) == WL_MODE_IBSS) {
5001                 get_pktcnt_t pktcnt;
5002                 u8 *curmacp;
5003
5004                 if (cfg->roam_offload) {
5005                         struct ether_addr bssid;
5006                         err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
5007                         if (err) {
5008                                 WL_ERR(("Failed to get current BSSID\n"));
5009                         } else {
5010                                 if (memcmp(mac, &bssid.octet, ETHER_ADDR_LEN) != 0) {
5011                                         /* roaming is detected */
5012                                         err = wl_cfg80211_delayed_roam(cfg, dev, &bssid);
5013                                         if (err)
5014                                                 WL_ERR(("Failed to handle the delayed roam, "
5015                                                         "err=%d", err));
5016                                         mac = (u8 *)bssid.octet;
5017                                 }
5018                         }
5019                 }
5020                 if (!wl_get_drv_status(cfg, CONNECTED, dev) ||
5021                         (dhd_is_associated(dhd, NULL, &err) == FALSE)) {
5022                         WL_ERR(("NOT assoc\n"));
5023                         if (err == -ERESTARTSYS)
5024                                 return err;
5025                         err = -ENODEV;
5026                         return err;
5027                 }
5028                 curmacp = wl_read_prof(cfg, dev, WL_PROF_BSSID);
5029                 if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
5030                         WL_ERR(("Wrong Mac address: "MACDBG" != "MACDBG"\n",
5031                                 MAC2STRDBG(mac), MAC2STRDBG(curmacp)));
5032                 }
5033
5034                 /* Report the current tx rate */
5035                 err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
5036                 if (err) {
5037                         WL_ERR(("Could not get rate (%d)\n", err));
5038                 } else {
5039 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
5040                         int rxpktglom;
5041 #endif
5042                         rate = dtoh32(rate);
5043                         sinfo->filled |= STATION_INFO_TX_BITRATE;
5044                         sinfo->txrate.legacy = rate * 5;
5045                         WL_DBG(("Rate %d Mbps\n", (rate / 2)));
5046 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
5047                         rxpktglom = ((rate/2) > 150) ? 20 : 10;
5048
5049                         if (maxrxpktglom != rxpktglom) {
5050                                 maxrxpktglom = rxpktglom;
5051                                 WL_DBG(("Rate %d Mbps, update bus:maxtxpktglom=%d\n", (rate/2),
5052                                         maxrxpktglom));
5053                                 err = wldev_iovar_setbuf(dev, "bus:maxtxpktglom",
5054                                         (char*)&maxrxpktglom, 4, cfg->ioctl_buf,
5055                                         WLC_IOCTL_MAXLEN, NULL);
5056                                 if (err < 0) {
5057                                         WL_ERR(("set bus:maxtxpktglom failed, %d\n", err));
5058                                 }
5059                         }
5060 #endif
5061                 }
5062
5063                 memset(&scb_val, 0, sizeof(scb_val));
5064                 scb_val.val = 0;
5065                 err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,
5066                         sizeof(scb_val_t), false);
5067                 if (err) {
5068                         WL_ERR(("Could not get rssi (%d)\n", err));
5069                         goto get_station_err;
5070                 }
5071                 rssi = wl_rssi_offset(dtoh32(scb_val.val));
5072                 sinfo->filled |= STATION_INFO_SIGNAL;
5073                 sinfo->signal = rssi;
5074                 WL_DBG(("RSSI %d dBm\n", rssi));
5075                 err = wldev_ioctl(dev, WLC_GET_PKTCNTS, &pktcnt,
5076                         sizeof(pktcnt), false);
5077                 if (!err) {
5078                         sinfo->filled |= (STATION_INFO_RX_PACKETS |
5079                                 STATION_INFO_RX_DROP_MISC |
5080                                 STATION_INFO_TX_PACKETS |
5081                                 STATION_INFO_TX_FAILED);
5082                         sinfo->rx_packets = pktcnt.rx_good_pkt;
5083                         sinfo->rx_dropped_misc = pktcnt.rx_bad_pkt;
5084                         sinfo->tx_packets = pktcnt.tx_good_pkt;
5085                         sinfo->tx_failed  = pktcnt.tx_bad_pkt;
5086                 }
5087 get_station_err:
5088                 if (err && (err != -ERESTARTSYS)) {
5089                         /* Disconnect due to zero BSSID or error to get RSSI */
5090                         WL_ERR(("force cfg80211_disconnected: %d\n", err));
5091                         wl_clr_drv_status(cfg, CONNECTED, dev);
5092                         cfg80211_disconnected(dev, 0, NULL, 0, GFP_KERNEL);
5093                         wl_link_down(cfg);
5094                 }
5095         }
5096         else {
5097                 WL_ERR(("Invalid device mode %d\n", wl_get_mode_by_netdev(cfg, dev)));
5098         }
5099
5100         return err;
5101 }
5102
5103 static s32
5104 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
5105         bool enabled, s32 timeout)
5106 {
5107         s32 pm;
5108         s32 err = 0;
5109         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5110         struct net_info *_net_info = wl_get_netinfo_by_netdev(cfg, dev);
5111
5112         RETURN_EIO_IF_NOT_UP(cfg);
5113         WL_DBG(("Enter\n"));
5114         if (cfg->p2p_net == dev || _net_info == NULL || cfg->vsdb_mode ||
5115                 !wl_get_drv_status(cfg, CONNECTED, dev)) {
5116                 return err;
5117         }
5118
5119         /* Delete pm_enable_work */
5120         wl_add_remove_pm_enable_work(cfg, FALSE, WL_HANDLER_PEND);
5121
5122         pm = enabled ? PM_FAST : PM_OFF;
5123         if (_net_info->pm_block) {
5124                 WL_ERR(("%s:Do not enable the power save for pm_block %d\n",
5125                         dev->name, _net_info->pm_block));
5126                 pm = PM_OFF;
5127         }
5128         pm = htod32(pm);
5129         WL_DBG(("%s:power save %s\n", dev->name, (pm ? "enabled" : "disabled")));
5130         err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true);
5131         if (unlikely(err)) {
5132                 if (err == -ENODEV)
5133                         WL_DBG(("net_device is not ready yet\n"));
5134                 else
5135                         WL_ERR(("error (%d)\n", err));
5136                 return err;
5137         }
5138         wl_cfg80211_update_power_mode(dev);
5139         return err;
5140 }
5141
5142 void wl_cfg80211_update_power_mode(struct net_device *dev)
5143 {
5144         int err, pm = -1;
5145
5146         err = wldev_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), true);
5147         if (err)
5148                 WL_ERR(("%s:error (%d)\n", __FUNCTION__, err));
5149         else if (pm != -1 && dev->ieee80211_ptr)
5150                 dev->ieee80211_ptr->ps = (pm == PM_OFF) ? false : true;
5151 }
5152
5153 static __used u32 wl_find_msb(u16 bit16)
5154 {
5155         u32 ret = 0;
5156
5157         if (bit16 & 0xff00) {
5158                 ret += 8;
5159                 bit16 >>= 8;
5160         }
5161
5162         if (bit16 & 0xf0) {
5163                 ret += 4;
5164                 bit16 >>= 4;
5165         }
5166
5167         if (bit16 & 0xc) {
5168                 ret += 2;
5169                 bit16 >>= 2;
5170         }
5171
5172         if (bit16 & 2)
5173                 ret += bit16 & 2;
5174         else if (bit16)
5175                 ret += bit16;
5176
5177         return ret;
5178 }
5179
5180 static s32 wl_cfg80211_resume(struct wiphy *wiphy)
5181 {
5182         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5183         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
5184         s32 err = 0;
5185
5186         if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
5187                 WL_INFORM(("device is not ready\n"));
5188                 return 0;
5189         }
5190
5191         return err;
5192 }
5193
5194 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
5195 static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
5196 #else
5197 static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
5198 #endif
5199 {
5200 #ifdef DHD_CLEAR_ON_SUSPEND
5201         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5202         struct net_info *iter, *next;
5203         struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
5204         unsigned long flags;
5205         if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
5206                 WL_INFORM(("device is not ready : status (%d)\n",
5207                         (int)cfg->status));
5208                 return 0;
5209         }
5210         for_each_ndev(cfg, iter, next)
5211                 wl_set_drv_status(cfg, SCAN_ABORTING, iter->ndev);
5212         spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
5213         if (cfg->scan_request) {
5214 #ifdef CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA
5215                 TEGRA_SCAN_DONE(cfg->scan_request, true)
5216 #endif
5217                 cfg80211_scan_done(cfg->scan_request, true);
5218 #ifdef CONFIG_BCMDHD_CUSTOM_SYSFS_TEGRA
5219 skip_cfg80211_scan_done:
5220 #endif
5221                 cfg->scan_request = NULL;
5222         }
5223         for_each_ndev(cfg, iter, next) {
5224                 wl_clr_drv_status(cfg, SCANNING, iter->ndev);
5225                 wl_clr_drv_status(cfg, SCAN_ABORTING, iter->ndev);
5226         }
5227         spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
5228         for_each_ndev(cfg, iter, next) {
5229                 if (wl_get_drv_status(cfg, CONNECTING, iter->ndev)) {
5230                         wl_bss_connect_done(cfg, iter->ndev, NULL, NULL, false);
5231                 }
5232         }
5233 #endif /* DHD_CLEAR_ON_SUSPEND */
5234         return 0;
5235 }
5236
5237 static s32
5238 wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
5239         s32 err)
5240 {
5241         int i, j;
5242         struct bcm_cfg80211 *cfg = g_bcm_cfg;
5243         struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
5244
5245         if (!pmk_list) {
5246                 printk("pmk_list is NULL\n");
5247                 return -EINVAL;
5248         }
5249         /* pmk list is supported only for STA interface i.e. primary interface
5250          * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
5251          */
5252         if (primary_dev != dev) {
5253                 WL_INFORM(("Not supporting Flushing pmklist on virtual"
5254                         " interfaces than primary interface\n"));
5255                 return err;
5256         }
5257
5258         WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
5259         for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
5260                 WL_DBG(("PMKID[%d]: %pM =\n", i,
5261                         &pmk_list->pmkids.pmkid[i].BSSID));
5262                 for (j = 0; j < WPA2_PMKID_LEN; j++) {
5263                         WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
5264                 }
5265         }
5266         if (likely(!err)) {
5267                 err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmk_list,
5268                         sizeof(*pmk_list), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
5269         }
5270
5271         return err;
5272 }
5273
5274 static s32
5275 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
5276         struct cfg80211_pmksa *pmksa)
5277 {
5278         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5279         s32 err = 0;
5280         int i;
5281
5282         if (pmksa == NULL) {
5283                 WL_ERR(("pmksa is null\n"));
5284                 return -EINVAL;
5285         }
5286
5287         RETURN_EIO_IF_NOT_UP(cfg);
5288         for (i = 0; i < cfg->pmk_list->pmkids.npmkid; i++)
5289                 if (!memcmp(pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
5290                         ETHER_ADDR_LEN))
5291                         break;
5292         if (i < WL_NUM_PMKIDS_MAX) {
5293                 memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
5294                         ETHER_ADDR_LEN);
5295                 memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
5296                         WPA2_PMKID_LEN);
5297                 if (i == cfg->pmk_list->pmkids.npmkid)
5298                         cfg->pmk_list->pmkids.npmkid++;
5299         } else {
5300                 err = -EINVAL;
5301         }
5302         WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
5303                 &cfg->pmk_list->pmkids.pmkid[cfg->pmk_list->pmkids.npmkid - 1].BSSID));
5304         for (i = 0; i < WPA2_PMKID_LEN; i++) {
5305                 WL_DBG(("%02x\n",
5306                         cfg->pmk_list->pmkids.pmkid[cfg->pmk_list->pmkids.npmkid - 1].
5307                         PMKID[i]));
5308         }
5309
5310         err = wl_update_pmklist(dev, cfg->pmk_list, err);
5311
5312         return err;
5313 }
5314
5315 static s32
5316 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
5317         struct cfg80211_pmksa *pmksa)
5318 {
5319         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5320         struct _pmkid_list pmkid = {0};
5321         s32 err = 0;
5322         int i;
5323
5324         if (pmksa == NULL) {
5325                 WL_ERR(("pmksa is null\n"));
5326                 return -EINVAL;
5327         }
5328
5329         RETURN_EIO_IF_NOT_UP(cfg);
5330         memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
5331         memcpy(pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
5332
5333         WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
5334                 &pmkid.pmkid[0].BSSID));
5335         for (i = 0; i < WPA2_PMKID_LEN; i++) {
5336                 WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
5337         }
5338
5339         for (i = 0; i < cfg->pmk_list->pmkids.npmkid; i++)
5340                 if (!memcmp
5341                     (pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
5342                      ETHER_ADDR_LEN))
5343                         break;
5344
5345         if ((cfg->pmk_list->pmkids.npmkid > 0) &&
5346                 (i < cfg->pmk_list->pmkids.npmkid)) {
5347                 memset(&cfg->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
5348                 for (; i < (cfg->pmk_list->pmkids.npmkid - 1); i++) {
5349                         memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID,
5350                                 &cfg->pmk_list->pmkids.pmkid[i + 1].BSSID,
5351                                 ETHER_ADDR_LEN);
5352                         memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID,
5353                                 &cfg->pmk_list->pmkids.pmkid[i + 1].PMKID,
5354                                 WPA2_PMKID_LEN);
5355                 }
5356                 cfg->pmk_list->pmkids.npmkid--;
5357         } else {
5358                 err = -EINVAL;
5359         }
5360
5361         err = wl_update_pmklist(dev, cfg->pmk_list, err);
5362
5363         return err;
5364
5365 }
5366
5367 static s32
5368 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
5369 {
5370         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5371         s32 err = 0;
5372         RETURN_EIO_IF_NOT_UP(cfg);
5373         memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list));
5374         err = wl_update_pmklist(dev, cfg->pmk_list, err);
5375         return err;
5376
5377 }
5378
5379 static wl_scan_params_t *
5380 wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size)
5381 {
5382         wl_scan_params_t *params;
5383         int params_size;
5384         int num_chans;
5385
5386         *out_params_size = 0;
5387
5388         /* Our scan params only need space for 1 channel and 0 ssids */
5389         params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16);
5390         params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL);
5391         if (params == NULL) {
5392                 WL_ERR(("mem alloc failed (%d bytes)\n", params_size));
5393                 return params;
5394         }
5395         memset(params, 0, params_size);
5396         params->nprobes = nprobes;
5397
5398         num_chans = (channel == 0) ? 0 : 1;
5399
5400         memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
5401         params->bss_type = DOT11_BSSTYPE_ANY;
5402         params->scan_type = DOT11_SCANTYPE_ACTIVE;
5403         params->nprobes = htod32(1);
5404         params->active_time = htod32(-1);
5405         params->passive_time = htod32(-1);
5406         params->home_time = htod32(10);
5407         if (channel == -1)
5408                 params->channel_list[0] = htodchanspec(channel);
5409         else
5410                 params->channel_list[0] = wl_ch_host_to_driver(channel);
5411
5412         /* Our scan params have 1 channel and 0 ssids */
5413         params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
5414                 (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
5415
5416         *out_params_size = params_size; /* rtn size to the caller */
5417         return params;
5418 }
5419
5420 #if defined(WL_CFG80211_P2P_DEV_IF)
5421 static s32
5422 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
5423         struct ieee80211_channel *channel, unsigned int duration, u64 *cookie)
5424 #else
5425 static s32
5426 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
5427         struct ieee80211_channel * channel,
5428         enum nl80211_channel_type channel_type,
5429         unsigned int duration, u64 *cookie)
5430 #endif /* WL_CFG80211_P2P_DEV_IF */
5431 {
5432         s32 target_channel;
5433         u32 id;
5434         s32 err = BCME_OK;
5435         struct ether_addr primary_mac;
5436         struct net_device *ndev = NULL;
5437         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5438
5439         if (!cfg)
5440                 return -EINVAL;
5441
5442         ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
5443
5444         WL_DBG(("Enter, channel: %d, duration ms (%d) SCANNING ?? %s \n",
5445                 ieee80211_frequency_to_channel(channel->center_freq),
5446                 duration, (wl_get_drv_status(cfg, SCANNING, ndev)) ? "YES":"NO"));
5447
5448         if (!cfg->p2p) {
5449                 WL_ERR(("cfg->p2p is not initialized\n"));
5450                 err = BCME_ERROR;
5451                 goto exit;
5452         }
5453
5454 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5455         if (wl_get_drv_status_all(cfg, SCANNING)) {
5456                 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
5457         }
5458 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5459
5460         target_channel = ieee80211_frequency_to_channel(channel->center_freq);
5461         memcpy(&cfg->remain_on_chan, channel, sizeof(struct ieee80211_channel));
5462 #if defined(WL_ENABLE_P2P_IF)
5463         cfg->remain_on_chan_type = channel_type;
5464 #endif /* WL_ENABLE_P2P_IF */
5465         id = ++cfg->last_roc_id;
5466         if (id == 0)
5467                 id = ++cfg->last_roc_id;
5468         *cookie = id;
5469
5470 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5471         if (wl_get_drv_status(cfg, SCANNING, ndev)) {
5472                 struct timer_list *_timer;
5473                 WL_DBG(("scan is running. go to fake listen state\n"));
5474
5475                 if (duration > LONG_LISTEN_TIME) {
5476                         wl_cfg80211_scan_abort(cfg);
5477                 } else {
5478                         wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
5479
5480                         if (timer_pending(&cfg->p2p->listen_timer)) {
5481                                 WL_DBG(("cancel current listen timer \n"));
5482                                 del_timer_sync(&cfg->p2p->listen_timer);
5483                         }
5484
5485                         _timer = &cfg->p2p->listen_timer;
5486                         wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
5487
5488                         INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration, 0);
5489
5490                         err = BCME_OK;
5491                         goto exit;
5492                 }
5493         }
5494 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5495
5496 #ifdef WL_CFG80211_SYNC_GON
5497         if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
5498                 /* do not enter listen mode again if we are in listen mode already for next af.
5499                  * remain on channel completion will be returned by waiting next af completion.
5500                  */
5501 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5502                 wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
5503 #else
5504                 wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
5505 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5506                 goto exit;
5507         }
5508 #endif /* WL_CFG80211_SYNC_GON */
5509         if (cfg->p2p && !cfg->p2p->on) {
5510                 /* In case of p2p_listen command, supplicant send remain_on_channel
5511                  * without turning on P2P
5512                  */
5513                 get_primary_mac(cfg, &primary_mac);
5514                 wl_cfgp2p_generate_bss_mac(&primary_mac, &cfg->p2p->dev_addr, &cfg->p2p->int_addr);
5515                 p2p_on(cfg) = true;
5516         }
5517
5518         if (p2p_is_on(cfg)) {
5519                 err = wl_cfgp2p_enable_discovery(cfg, ndev, NULL, 0);
5520                 if (unlikely(err)) {
5521                         goto exit;
5522                 }
5523 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5524                 wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
5525 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5526                 err = wl_cfgp2p_discover_listen(cfg, target_channel, duration);
5527
5528 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5529                 if (err == BCME_OK) {
5530                         wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
5531                 } else {
5532                         /* if failed, firmware may be internal scanning state.
5533                          * so other scan request shall not abort it
5534                          */
5535                         wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
5536                 }
5537 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5538                 /* WAR: set err = ok to prevent cookie mismatch in wpa_supplicant
5539                  * and expire timer will send a completion to the upper layer
5540                  */
5541                 err = BCME_OK;
5542         }
5543
5544 exit:
5545         if (err == BCME_OK) {
5546                 WL_INFORM(("Success\n"));
5547 #if defined(WL_CFG80211_P2P_DEV_IF)
5548                 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
5549                         duration, GFP_KERNEL);
5550 #else
5551                 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
5552                         channel_type, duration, GFP_KERNEL);
5553 #endif /* WL_CFG80211_P2P_DEV_IF */
5554         } else {
5555                 WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err, *cookie));
5556         }
5557         return err;
5558 }
5559
5560 static s32
5561 wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
5562         bcm_struct_cfgdev *cfgdev, u64 cookie)
5563 {
5564         struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5565         s32 err = 0;
5566
5567 #ifdef P2PLISTEN_AP_SAMECHN
5568         struct bcm_cfg80211 *cfg = g_bcm_cfg;
5569         struct net_device *dev;
5570 #endif /* P2PLISTEN_AP_SAMECHN */
5571
5572         RETURN_EIO_IF_NOT_UP(cfg);
5573 #if defined(WL_CFG80211_P2P_DEV_IF)
5574         if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
5575                 WL_DBG((" enter ) on P2P dedicated discover interface\n"));
5576         }
5577 #else
5578         WL_DBG((" enter ) netdev_ifidx: %d \n", cfgdev->ifindex));
5579 #endif /* WL_CFG80211_P2P_DEV_IF */
5580
5581 #ifdef P2PLISTEN_AP_SAMECHN
5582         if (cfg && cfg->p2p_resp_apchn_status) {
5583                 dev = bcmcfg_to_prmry_ndev(cfg);
5584                 wl_cfg80211_set_p2p_resp_ap_chn(dev, 0);
5585                 cfg->p2p_resp_apchn_status = false;
5586                 WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
5587         }
5588 #endif /* P2PLISTEN_AP_SAMECHN */
5589
5590         if (cfg->last_roc_id == cookie) {
5591                 wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
5592                         wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
5593         } else {
5594                 WL_ERR(("%s : ignore, request cookie(%llu) is not matched. (cur : %llu)\n",
5595                         __FUNCTION__, cookie, cfg->last_roc_id));
5596         }
5597
5598         return err;
5599 }
5600
5601 static void
5602 wl_cfg80211_afx_handler(struct work_struct *work)
5603 {
5604         struct afx_hdl *afx_instance;
5605         struct bcm_cfg80211 *cfg = g_bcm_cfg;
5606         s32 ret = BCME_OK;
5607
5608         afx_instance = container_of(work, struct afx_hdl, work);
5609         if (afx_instance != NULL && cfg->afx_hdl->is_active) {
5610                 if (cfg->afx_hdl->is_listen && cfg->afx_hdl->my_listen_chan) {
5611                         ret = wl_cfgp2p_discover_listen(cfg, cfg->afx_hdl->my_listen_chan,
5612                                 (100 * (1 + (RANDOM32() % 3)))); /* 100ms ~ 300ms */
5613                 } else {
5614                         ret = wl_cfgp2p_act_frm_search(cfg, cfg->afx_hdl->dev,
5615                                 cfg->afx_hdl->bssidx, cfg->afx_hdl->peer_listen_chan,
5616                                 NULL);
5617                 }
5618                 if (unlikely(ret != BCME_OK)) {
5619                         WL_ERR(("ERROR occurred! returned value is (%d)\n", ret));
5620                         if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL))
5621                                 complete(&cfg->act_frm_scan);
5622                 }
5623         }
5624 }
5625
5626 static s32
5627 wl_cfg80211_af_searching_channel(struct bcm_cfg80211 *cfg, struct net_device *dev)
5628 {
5629         u32 max_retry = WL_CHANNEL_SYNC_RETRY;
5630
5631         if (dev == NULL)
5632                 return -1;
5633
5634         WL_DBG((" enter ) \n"));
5635
5636         wl_set_drv_status(cfg, FINDING_COMMON_CHANNEL, dev);
5637         cfg->afx_hdl->is_active = TRUE;
5638
5639         /* Loop to wait until we find a peer's channel or the
5640          * pending action frame tx is cancelled.
5641          */
5642         while ((cfg->afx_hdl->retry < max_retry) &&
5643                 (cfg->afx_hdl->peer_chan == WL_INVALID)) {
5644                 cfg->afx_hdl->is_listen = FALSE;
5645                 wl_set_drv_status(cfg, SCANNING, dev);
5646                 WL_DBG(("Scheduling the action frame for sending.. retry %d\n",
5647                         cfg->afx_hdl->retry));
5648                 /* search peer on peer's listen channel */
5649                 schedule_work(&cfg->afx_hdl->work);
5650                 wait_for_completion_timeout(&cfg->act_frm_scan,
5651                         msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
5652
5653                 if ((cfg->afx_hdl->peer_chan != WL_INVALID) ||
5654                         !(wl_get_drv_status(cfg, FINDING_COMMON_CHANNEL, dev)))
5655                         break;
5656
5657                 if (cfg->