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