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