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