]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/blob - drivers/net/wireless/bcmdhd/wl_cfg80211.c
6cfc293c13db51feb27f03457fc54521143e2633
[sojka/nv-tegra/linux-3.10.git] / drivers / net / wireless / bcmdhd / wl_cfg80211.c
1
2 /*
3  * Linux cfg80211 driver
4  *
5  * Copyright (C) 1999-2013, Broadcom Corporation
6  * 
7  *      Unless you and Broadcom execute a separate written software license
8  * agreement governing use of this software, this software is licensed to you
9  * under the terms of the GNU General Public License version 2 (the "GPL"),
10  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
11  * following added to such license:
12  * 
13  *      As a special exception, the copyright holders of this software give you
14  * permission to link this software with independent modules, and to copy and
15  * distribute the resulting executable under terms of your choice, provided that
16  * you also meet, for each linked independent module, the terms and conditions of
17  * the license of that module.  An independent module is a module which is not
18  * derived from this software.  The special exception does not apply to any
19  * modifications of the software.
20  * 
21  *      Notwithstanding the above, under no circumstances may you combine this
22  * software in any way with any other Broadcom software provided under a license
23  * other than the GPL, without Broadcom's express prior written consent.
24  *
25  * $Id: wl_cfg80211.c 432088 2013-10-25 15:02:04Z $
26  */
27 /* */
28 #include <typedefs.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 <dhdioctl.h>
44 #include <wlioctl.h>
45 #include <dhd_cfg80211.h>
46 #ifdef PNO_SUPPORT
47 #include <dhd_pno.h>
48 #endif /* PNO_SUPPORT */
49
50 #include <proto/ethernet.h>
51 #include <linux/kernel.h>
52 #include <linux/kthread.h>
53 #include <linux/netdevice.h>
54 #include <linux/sched.h>
55 #include <linux/etherdevice.h>
56 #include <linux/wireless.h>
57 #include <linux/ieee80211.h>
58 #include <linux/wait.h>
59 #include <net/cfg80211.h>
60 #include <net/rtnetlink.h>
61
62 #include <wlioctl.h>
63 #include <wldev_common.h>
64 #include <wl_cfg80211.h>
65 #include <wl_cfgp2p.h>
66 #include <wl_android.h>
67
68 #ifdef PROP_TXSTATUS
69 #include <dhd_wlfc.h>
70 #endif
71
72
73
74 #define IW_WSEC_ENABLED(wsec)   ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
75
76 static struct device *cfg80211_parent_dev = NULL;
77 struct wl_priv *wlcfg_drv_priv = NULL;
78 u32 wl_dbg_level = WL_DBG_ERR;
79
80 #define MAX_WAIT_TIME 1500
81
82 #ifdef VSDB
83 /* sleep time to keep STA's connecting or connection for continuous af tx or finding a peer */
84 #define DEFAULT_SLEEP_TIME_VSDB         120
85 #define OFF_CHAN_TIME_THRESHOLD_MS      200
86 #define AF_RETRY_DELAY_TIME             40
87
88 /* if sta is connected or connecting, sleep for a while before retry af tx or finding a peer */
89 #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl)   \
90         do {    \
91                 if (wl_get_drv_status(wl, CONNECTED, wl_to_prmry_ndev(wl)) ||   \
92                         wl_get_drv_status(wl, CONNECTING, wl_to_prmry_ndev(wl))) {      \
93                         OSL_SLEEP(DEFAULT_SLEEP_TIME_VSDB);     \
94                 }       \
95         } while (0)
96 #else /* VSDB */
97 /* if not VSDB, do nothing */
98 #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl)
99 #endif /* VSDB */
100
101 #ifdef WL_CFG80211_SYNC_GON
102 #define WL_DRV_STATUS_SENDING_AF_FRM_EXT(wl) \
103         (wl_get_drv_status_all(wl, SENDING_ACT_FRM) || \
104                 wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN))
105 #else
106 #define WL_DRV_STATUS_SENDING_AF_FRM_EXT(wl) wl_get_drv_status_all(wl, SENDING_ACT_FRM)
107 #endif /* WL_CFG80211_SYNC_GON */
108
109 #define WL_CHANSPEC_CTL_SB_NONE WL_CHANSPEC_CTL_SB_LLL
110
111
112 #define DNGL_FUNC(func, parameters) func parameters;
113 #define COEX_DHCP
114
115 #define WLAN_EID_SSID   0
116 #define CH_MIN_5G_CHANNEL 34
117 #define CH_MIN_2G_CHANNEL 1
118
119 /* This is to override regulatory domains defined in cfg80211 module (reg.c)
120  * By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN
121  * and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165).
122  * With respect to these flags, wpa_supplicant doesn't start p2p operations on 5GHz channels.
123  * All the chnages in world regulatory domain are to be done here.
124  */
125 static const struct ieee80211_regdomain brcm_regdom = {
126         .n_reg_rules = 4,
127         .alpha2 =  "99",
128         .reg_rules = {
129                 /* IEEE 802.11b/g, channels 1..11 */
130                 REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
131                 /* If any */
132                 /* IEEE 802.11 channel 14 - Only JP enables
133                  * this and for 802.11b only
134                  */
135                 REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
136                 /* IEEE 802.11a, channel 36..64 */
137                 REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
138                 /* IEEE 802.11a, channel 100..165 */
139                 REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
140 };
141
142 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
143         (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
144 /*
145  * Possible interface combinations supported by driver
146  *
147  * ADHOC Mode     - #ADHOC <= 1 on channels = 1
148  * SoftAP Mode    - #AP <= 1 on channels = 1
149  * STA + P2P Mode - #STA <= 2, #{P2P-GO, P2P-client} <= 1, #P2P-device <= 1
150  *                  on channels = 2
151  */
152 static const struct ieee80211_iface_limit softap_limits[] = {
153         {
154         .max = 1,
155         .types = BIT(NL80211_IFTYPE_AP),
156         },
157 };
158
159 static const struct ieee80211_iface_limit sta_p2p_limits[] = {
160         /*
161          * During P2P-GO removal, P2P-GO is first changed to STA and later only
162          * removed. So setting maximum possible number of STA interfaces as 3 to
163          * accommodate the above behaviour.
164          */
165         {
166 #ifdef WL_ENABLE_P2P_IF
167         .max = 3,
168 #else
169         .max = 2,
170 #endif /* WL_ENABLE_P2P_IF */
171
172         .types = BIT(NL80211_IFTYPE_STATION),
173         },
174         {
175         .max = 2,
176         .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
177         },
178 #if defined(WL_CFG80211_P2P_DEV_IF)
179         {
180         .max = 1,
181         .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
182         },
183 #endif /* WL_CFG80211_P2P_DEV_IF */
184         {
185         .max = 1,
186         .types = BIT(NL80211_IFTYPE_ADHOC),
187         },
188 };
189
190 static const struct ieee80211_iface_combination
191 softap_iface_combinations[] = {
192         {
193         .num_different_channels = 1,
194         .max_interfaces = 1,
195         .limits = softap_limits,
196         .n_limits = ARRAY_SIZE(softap_limits),
197         },
198 };
199
200 static const struct ieee80211_iface_combination
201 sta_p2p_iface_combinations[] = {
202         {
203 #ifdef DHD_ENABLE_MCC
204         .num_different_channels = 2,
205 #else
206         .num_different_channels = 1,
207 #endif
208         .max_interfaces = 3,
209         .limits = sta_p2p_limits,
210         .n_limits = ARRAY_SIZE(sta_p2p_limits),
211         },
212 };
213 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
214
215 /* Data Element Definitions */
216 #define WPS_ID_CONFIG_METHODS     0x1008
217 #define WPS_ID_REQ_TYPE           0x103A
218 #define WPS_ID_DEVICE_NAME        0x1011
219 #define WPS_ID_VERSION            0x104A
220 #define WPS_ID_DEVICE_PWD_ID      0x1012
221 #define WPS_ID_REQ_DEV_TYPE       0x106A
222 #define WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS 0x1053
223 #define WPS_ID_PRIM_DEV_TYPE      0x1054
224
225 /* Device Password ID */
226 #define DEV_PW_DEFAULT 0x0000
227 #define DEV_PW_USER_SPECIFIED 0x0001,
228 #define DEV_PW_MACHINE_SPECIFIED 0x0002
229 #define DEV_PW_REKEY 0x0003
230 #define DEV_PW_PUSHBUTTON 0x0004
231 #define DEV_PW_REGISTRAR_SPECIFIED 0x0005
232
233 /* Config Methods */
234 #define WPS_CONFIG_USBA 0x0001
235 #define WPS_CONFIG_ETHERNET 0x0002
236 #define WPS_CONFIG_LABEL 0x0004
237 #define WPS_CONFIG_DISPLAY 0x0008
238 #define WPS_CONFIG_EXT_NFC_TOKEN 0x0010
239 #define WPS_CONFIG_INT_NFC_TOKEN 0x0020
240 #define WPS_CONFIG_NFC_INTERFACE 0x0040
241 #define WPS_CONFIG_PUSHBUTTON 0x0080
242 #define WPS_CONFIG_KEYPAD 0x0100
243 #define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280
244 #define WPS_CONFIG_PHY_PUSHBUTTON 0x0480
245 #define WPS_CONFIG_VIRT_DISPLAY 0x2008
246 #define WPS_CONFIG_PHY_DISPLAY 0x4008
247
248 #define PM_BLOCK 1
249 #define PM_ENABLE 0
250
251
252
253 #ifndef IBSS_COALESCE_ALLOWED
254 #define IBSS_COALESCE_ALLOWED   0
255 #endif
256
257 #ifndef IBSS_INITIAL_SCAN_ALLOWED
258 #define IBSS_INITIAL_SCAN_ALLOWED       0
259 #endif
260 /*
261  * cfg80211_ops api/callback list
262  */
263 static s32 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
264         const struct ether_addr *sa, const struct ether_addr *bssid,
265         u8 **pheader, u32 *body_len, u8 *pbody);
266 static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
267         struct cfg80211_scan_request *request,
268         struct cfg80211_ssid *this_ssid);
269 #if defined(WL_CFG80211_P2P_DEV_IF)
270 static s32
271 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request);
272 #else
273 static s32
274 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
275         struct cfg80211_scan_request *request);
276 #endif /* WL_CFG80211_P2P_DEV_IF */
277 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
278 static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
279         struct cfg80211_ibss_params *params);
280 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy,
281         struct net_device *dev);
282 static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
283         struct net_device *dev, u8 *mac,
284         struct station_info *sinfo);
285 static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
286         struct net_device *dev, bool enabled,
287         s32 timeout);
288 static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
289         struct cfg80211_connect_params *sme);
290 static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
291         u16 reason_code);
292 #if defined(WL_CFG80211_P2P_DEV_IF)
293 static s32
294 wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
295         enum nl80211_tx_power_setting type, s32 mbm);
296 #else
297 static s32
298 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
299         enum nl80211_tx_power_setting type, s32 dbm);
300 #endif /* WL_CFG80211_P2P_DEV_IF */
301 #if defined(WL_CFG80211_P2P_DEV_IF)
302 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
303         struct wireless_dev *wdev, s32 *dbm);
304 #else
305 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
306 #endif /* WL_CFG80211_P2P_DEV_IF */
307 static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
308         struct net_device *dev,
309         u8 key_idx, bool unicast, bool multicast);
310 static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
311         u8 key_idx, bool pairwise, const u8 *mac_addr,
312         struct key_params *params);
313 static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
314         u8 key_idx, bool pairwise, const u8 *mac_addr);
315 static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
316         u8 key_idx, bool pairwise, const u8 *mac_addr,
317         void *cookie, void (*callback) (void *cookie,
318         struct key_params *params));
319 static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
320         struct net_device *dev, u8 key_idx);
321 static s32 wl_cfg80211_resume(struct wiphy *wiphy);
322 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
323         2, 0))
324 static s32 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
325         bcm_struct_cfgdev *cfgdev, u64 cookie);
326 static s32 wl_cfg80211_del_station(struct wiphy *wiphy,
327         struct net_device *ndev, u8* mac_addr);
328 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
329 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || 0
330 static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
331 #else
332 static s32 wl_cfg80211_suspend(struct wiphy *wiphy);
333 #endif
334 static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
335         struct cfg80211_pmksa *pmksa);
336 static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
337         struct cfg80211_pmksa *pmksa);
338 static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
339         struct net_device *dev);
340 static void wl_cfg80211_scan_abort(struct wl_priv *wl);
341 static s32 wl_notify_escan_complete(struct wl_priv *wl,
342         struct net_device *ndev, bool aborted, bool fw_abort);
343 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || 0
344 static s32 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
345         u8 *peer, enum nl80211_tdls_operation oper);
346 #endif 
347
348 /*
349  * event & event Q handlers for cfg80211 interfaces
350  */
351 static s32 wl_create_event_handler(struct wl_priv *wl);
352 static void wl_destroy_event_handler(struct wl_priv *wl);
353 static s32 wl_event_handler(void *data);
354 static void wl_init_eq(struct wl_priv *wl);
355 static void wl_flush_eq(struct wl_priv *wl);
356 static unsigned long wl_lock_eq(struct wl_priv *wl);
357 static void wl_unlock_eq(struct wl_priv *wl, unsigned long flags);
358 static void wl_init_eq_lock(struct wl_priv *wl);
359 static void wl_init_event_handler(struct wl_priv *wl);
360 static struct wl_event_q *wl_deq_event(struct wl_priv *wl);
361 static s32 wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 type,
362         const wl_event_msg_t *msg, void *data);
363 static void wl_put_event(struct wl_event_q *e);
364 static void wl_wakeup_event(struct wl_priv *wl);
365 static s32 wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev,
366         const wl_event_msg_t *e, void *data);
367 static s32 wl_notify_connect_status(struct wl_priv *wl,
368         bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
369 static s32 wl_notify_roaming_status(struct wl_priv *wl,
370         bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
371 static s32 wl_notify_scan_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
372         const wl_event_msg_t *e, void *data);
373 static s32 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
374         const wl_event_msg_t *e, void *data, bool completed);
375 static s32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
376         const wl_event_msg_t *e, void *data);
377 static s32 wl_notify_mic_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
378         const wl_event_msg_t *e, void *data);
379 #ifdef WL_SCHED_SCAN
380 static s32
381 wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev,
382         const wl_event_msg_t *e, void *data);
383 #endif /* WL_SCHED_SCAN */
384 #ifdef PNO_SUPPORT
385 static s32 wl_notify_pfn_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
386         const wl_event_msg_t *e, void *data);
387 #endif /* PNO_SUPPORT */
388 static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info,
389         enum wl_status state, bool set);
390
391 #ifdef WLTDLS
392 static s32 wl_tdls_event_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
393         const wl_event_msg_t *e, void *data);
394 #endif /* WLTDLS */
395 #ifdef BCMCCX_S69
396 static s32 wl_ccx_s69_response(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
397         const wl_event_msg_t *e, void *data);
398 #endif
399 /*
400  * register/deregister parent device
401  */
402 static void wl_cfg80211_clear_parent_dev(void);
403
404 /*
405  * ioctl utilites
406  */
407
408 /*
409  * cfg80211 set_wiphy_params utilities
410  */
411 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold);
412 static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold);
413 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
414
415 /*
416  * wl profile utilities
417  */
418 static s32 wl_update_prof(struct wl_priv *wl, struct net_device *ndev,
419         const wl_event_msg_t *e, void *data, s32 item);
420 static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item);
421 static void wl_init_prof(struct wl_priv *wl, struct net_device *ndev);
422
423 /*
424  * cfg80211 connect utilites
425  */
426 static s32 wl_set_wpa_version(struct net_device *dev,
427         struct cfg80211_connect_params *sme);
428 static s32 wl_set_auth_type(struct net_device *dev,
429         struct cfg80211_connect_params *sme);
430 static s32 wl_set_set_cipher(struct net_device *dev,
431         struct cfg80211_connect_params *sme);
432 static s32 wl_set_key_mgmt(struct net_device *dev,
433         struct cfg80211_connect_params *sme);
434 static s32 wl_set_set_sharedkey(struct net_device *dev,
435         struct cfg80211_connect_params *sme);
436 static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev);
437 static void wl_ch_to_chanspec(int ch,
438         struct wl_join_params *join_params, size_t *join_params_size);
439
440 /*
441  * information element utilities
442  */
443 static void wl_rst_ie(struct wl_priv *wl);
444 static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v);
445 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size);
446 static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size);
447 static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size);
448 static u32 wl_get_ielen(struct wl_priv *wl);
449
450
451 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev, void *data);
452 static void wl_free_wdev(struct wl_priv *wl);
453 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
454 static int
455 wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
456 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
457
458 static s32 wl_inform_bss(struct wl_priv *wl);
459 static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi);
460 static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev);
461 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy);
462 s32 wl_cfg80211_channel_to_freq(u32 channel);
463
464
465 static void wl_cfg80211_work_handler(struct work_struct *work);
466 static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
467         u8 key_idx, const u8 *mac_addr,
468         struct key_params *params);
469 /*
470  * key indianess swap utilities
471  */
472 static void swap_key_from_BE(struct wl_wsec_key *key);
473 static void swap_key_to_BE(struct wl_wsec_key *key);
474
475 /*
476  * wl_priv memory init/deinit utilities
477  */
478 static s32 wl_init_priv_mem(struct wl_priv *wl);
479 static void wl_deinit_priv_mem(struct wl_priv *wl);
480
481 static void wl_delay(u32 ms);
482
483 /*
484  * ibss mode utilities
485  */
486 static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev);
487 static __used bool wl_is_ibssstarter(struct wl_priv *wl);
488
489 /*
490  * link up/down , default configuration utilities
491  */
492 static s32 __wl_cfg80211_up(struct wl_priv *wl);
493 static s32 __wl_cfg80211_down(struct wl_priv *wl);
494 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e);
495 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev);
496 static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e);
497 static void wl_link_up(struct wl_priv *wl);
498 static void wl_link_down(struct wl_priv *wl);
499 static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype);
500 static void wl_init_conf(struct wl_conf *conf);
501
502 /*
503  * iscan handler
504  */
505 static void wl_iscan_timer(unsigned long data);
506 static void wl_term_iscan(struct wl_priv *wl);
507 static s32 wl_init_scan(struct wl_priv *wl);
508 static s32 wl_iscan_thread(void *data);
509 static s32 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request,
510         u16 action);
511 static s32 wl_do_iscan(struct wl_priv *wl,  struct cfg80211_scan_request *request);
512 static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan);
513 static s32 wl_invoke_iscan(struct wl_priv *wl);
514 static s32 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
515         struct wl_scan_results **bss_list);
516 static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted);
517 static void wl_init_iscan_handler(struct wl_iscan_ctrl *iscan);
518 static s32 wl_iscan_done(struct wl_priv *wl);
519 static s32 wl_iscan_pending(struct wl_priv *wl);
520 static s32 wl_iscan_inprogress(struct wl_priv *wl);
521 static s32 wl_iscan_aborted(struct wl_priv *wl);
522
523 /*
524  * find most significant bit set
525  */
526 static __used u32 wl_find_msb(u16 bit16);
527
528 /*
529  * rfkill support
530  */
531 static int wl_setup_rfkill(struct wl_priv *wl, bool setup);
532 static int wl_rfkill_set(void *data, bool blocked);
533 #ifdef DEBUGFS_CFG80211
534 static s32 wl_setup_debugfs(struct wl_priv *wl);
535 static s32 wl_free_debugfs(struct wl_priv *wl);
536 #endif
537
538 static wl_scan_params_t *wl_cfg80211_scan_alloc_params(int channel,
539         int nprobes, int *out_params_size);
540 static bool check_dev_role_integrity(struct wl_priv *wl, u32 dev_role);
541
542 /*
543  * Some external functions, TODO: move them to dhd_linux.h
544  */
545 int dhd_add_monitor(char *name, struct net_device **new_ndev);
546 int dhd_del_monitor(struct net_device *ndev);
547 int dhd_monitor_init(void *dhd_pub);
548 int dhd_monitor_uninit(void);
549 int dhd_start_xmit(struct sk_buff *skb, struct net_device *net);
550
551
552
553 #define RETURN_EIO_IF_NOT_UP(wlpriv)                                            \
554 do {                                                                    \
555         struct net_device *checkSysUpNDev = wl_to_prmry_ndev(wlpriv);           \
556         if (unlikely(!wl_get_drv_status(wlpriv, READY, checkSysUpNDev))) {      \
557                 WL_INFO(("device is not ready\n"));                     \
558                 return -EIO;                                            \
559         }                                                               \
560 } while (0)
561
562 #ifdef RSSI_OFFSET
563 static s32 wl_rssi_offset(s32 rssi)
564 {
565         rssi += RSSI_OFFSET;
566         if (rssi > 0)
567                 rssi = 0;
568         return rssi;
569 }
570 #else
571 #define wl_rssi_offset(x)       x
572 #endif
573
574 #define IS_WPA_AKM(akm) ((akm) == RSN_AKM_NONE ||                       \
575                                  (akm) == RSN_AKM_UNSPECIFIED ||        \
576                                  (akm) == RSN_AKM_PSK)
577
578
579 extern int dhd_wait_pend8021x(struct net_device *dev);
580 #ifdef PROP_TXSTATUS_VSDB
581 extern int disable_proptx;
582 extern int dhd_wlfc_init(dhd_pub_t *dhd);
583 extern void dhd_wlfc_deinit(dhd_pub_t *dhd);
584 #endif /* PROP_TXSTATUS_VSDB */
585
586 #if (WL_DBG_LEVEL > 0)
587 #define WL_DBG_ESTR_MAX 50
588 static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = {
589         "SET_SSID", "JOIN", "START", "AUTH", "AUTH_IND",
590         "DEAUTH", "DEAUTH_IND", "ASSOC", "ASSOC_IND", "REASSOC",
591         "REASSOC_IND", "DISASSOC", "DISASSOC_IND", "QUIET_START", "QUIET_END",
592         "BEACON_RX", "LINK", "MIC_ERROR", "NDIS_LINK", "ROAM",
593         "TXFAIL", "PMKID_CACHE", "RETROGRADE_TSF", "PRUNE", "AUTOAUTH",
594         "EAPOL_MSG", "SCAN_COMPLETE", "ADDTS_IND", "DELTS_IND", "BCNSENT_IND",
595         "BCNRX_MSG", "BCNLOST_MSG", "ROAM_PREP", "PFN_NET_FOUND",
596         "PFN_NET_LOST",
597         "RESET_COMPLETE", "JOIN_START", "ROAM_START", "ASSOC_START",
598         "IBSS_ASSOC",
599         "RADIO", "PSM_WATCHDOG", "WLC_E_CCX_ASSOC_START", "WLC_E_CCX_ASSOC_ABORT",
600         "PROBREQ_MSG",
601         "SCAN_CONFIRM_IND", "PSK_SUP", "COUNTRY_CODE_CHANGED",
602         "EXCEEDED_MEDIUM_TIME", "ICV_ERROR",
603         "UNICAST_DECODE_ERROR", "MULTICAST_DECODE_ERROR", "TRACE",
604         "WLC_E_BTA_HCI_EVENT", "IF", "WLC_E_P2P_DISC_LISTEN_COMPLETE",
605         "RSSI", "PFN_SCAN_COMPLETE", "WLC_E_EXTLOG_MSG",
606         "ACTION_FRAME", "ACTION_FRAME_COMPLETE", "WLC_E_PRE_ASSOC_IND",
607         "WLC_E_PRE_REASSOC_IND", "WLC_E_CHANNEL_ADOPTED", "WLC_E_AP_STARTED",
608         "WLC_E_DFS_AP_STOP", "WLC_E_DFS_AP_RESUME", "WLC_E_WAI_STA_EVENT",
609         "WLC_E_WAI_MSG", "WLC_E_ESCAN_RESULT", "WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE",
610         "WLC_E_PROBRESP_MSG", "WLC_E_P2P_PROBREQ_MSG", "WLC_E_DCS_REQUEST", "WLC_E_FIFO_CREDIT_MAP",
611         "WLC_E_ACTION_FRAME_RX", "WLC_E_WAKE_EVENT", "WLC_E_RM_COMPLETE"
612 };
613 #endif                          /* WL_DBG_LEVEL */
614
615 #define CHAN2G(_channel, _freq, _flags) {                       \
616         .band                   = IEEE80211_BAND_2GHZ,          \
617         .center_freq            = (_freq),                      \
618         .hw_value               = (_channel),                   \
619         .flags                  = (_flags),                     \
620         .max_antenna_gain       = 0,                            \
621         .max_power              = 30,                           \
622 }
623
624 #define CHAN5G(_channel, _flags) {                              \
625         .band                   = IEEE80211_BAND_5GHZ,          \
626         .center_freq            = 5000 + (5 * (_channel)),      \
627         .hw_value               = (_channel),                   \
628         .flags                  = (_flags),                     \
629         .max_antenna_gain       = 0,                            \
630         .max_power              = 30,                           \
631 }
632
633 #define RATE_TO_BASE100KBPS(rate)   (((rate) * 10) / 2)
634 #define RATETAB_ENT(_rateid, _flags) \
635         {                                                               \
636                 .bitrate        = RATE_TO_BASE100KBPS(_rateid),     \
637                 .hw_value       = (_rateid),                        \
638                 .flags    = (_flags),                        \
639         }
640
641 static struct ieee80211_rate __wl_rates[] = {
642         RATETAB_ENT(DOT11_RATE_1M, 0),
643         RATETAB_ENT(DOT11_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
644         RATETAB_ENT(DOT11_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
645         RATETAB_ENT(DOT11_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
646         RATETAB_ENT(DOT11_RATE_6M, 0),
647         RATETAB_ENT(DOT11_RATE_9M, 0),
648         RATETAB_ENT(DOT11_RATE_12M, 0),
649         RATETAB_ENT(DOT11_RATE_18M, 0),
650         RATETAB_ENT(DOT11_RATE_24M, 0),
651         RATETAB_ENT(DOT11_RATE_36M, 0),
652         RATETAB_ENT(DOT11_RATE_48M, 0),
653         RATETAB_ENT(DOT11_RATE_54M, 0)
654 };
655
656 #define wl_a_rates              (__wl_rates + 4)
657 #define wl_a_rates_size 8
658 #define wl_g_rates              (__wl_rates + 0)
659 #define wl_g_rates_size 12
660
661 static struct ieee80211_channel __wl_2ghz_channels[] = {
662         CHAN2G(1, 2412, 0),
663         CHAN2G(2, 2417, 0),
664         CHAN2G(3, 2422, 0),
665         CHAN2G(4, 2427, 0),
666         CHAN2G(5, 2432, 0),
667         CHAN2G(6, 2437, 0),
668         CHAN2G(7, 2442, 0),
669         CHAN2G(8, 2447, 0),
670         CHAN2G(9, 2452, 0),
671         CHAN2G(10, 2457, 0),
672         CHAN2G(11, 2462, 0),
673         CHAN2G(12, 2467, 0),
674         CHAN2G(13, 2472, 0),
675         CHAN2G(14, 2484, 0)
676 };
677
678 static struct ieee80211_channel __wl_5ghz_a_channels[] = {
679         CHAN5G(34, 0), CHAN5G(36, 0),
680         CHAN5G(38, 0), CHAN5G(40, 0),
681         CHAN5G(42, 0), CHAN5G(44, 0),
682         CHAN5G(46, 0), CHAN5G(48, 0),
683         CHAN5G(52, 0), CHAN5G(56, 0),
684         CHAN5G(60, 0), CHAN5G(64, 0),
685         CHAN5G(100, 0), CHAN5G(104, 0),
686         CHAN5G(108, 0), CHAN5G(112, 0),
687         CHAN5G(116, 0), CHAN5G(120, 0),
688         CHAN5G(124, 0), CHAN5G(128, 0),
689         CHAN5G(132, 0), CHAN5G(136, 0),
690         CHAN5G(140, 0), CHAN5G(149, 0),
691         CHAN5G(153, 0), CHAN5G(157, 0),
692         CHAN5G(161, 0), CHAN5G(165, 0)
693 };
694
695 static struct ieee80211_supported_band __wl_band_2ghz = {
696         .band = IEEE80211_BAND_2GHZ,
697         .channels = __wl_2ghz_channels,
698         .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
699         .bitrates = wl_g_rates,
700         .n_bitrates = wl_g_rates_size
701 };
702
703 static struct ieee80211_supported_band __wl_band_5ghz_a = {
704         .band = IEEE80211_BAND_5GHZ,
705         .channels = __wl_5ghz_a_channels,
706         .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
707         .bitrates = wl_a_rates,
708         .n_bitrates = wl_a_rates_size
709 };
710
711 static const u32 __wl_cipher_suites[] = {
712         WLAN_CIPHER_SUITE_WEP40,
713         WLAN_CIPHER_SUITE_WEP104,
714         WLAN_CIPHER_SUITE_TKIP,
715         WLAN_CIPHER_SUITE_CCMP,
716         WLAN_CIPHER_SUITE_AES_CMAC,
717 };
718
719
720 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
721 static int maxrxpktglom = 0;
722 #endif
723
724 /* IOCtl version read from targeted driver */
725 static int ioctl_version;
726 #ifdef DEBUGFS_CFG80211
727 #define S_SUBLOGLEVEL 20
728 static const struct {
729         u32 log_level;
730         char *sublogname;
731 } sublogname_map[] = {
732         {WL_DBG_ERR, "ERR"},
733         {WL_DBG_INFO, "INFO"},
734         {WL_DBG_DBG, "DBG"},
735         {WL_DBG_SCAN, "SCAN"},
736         {WL_DBG_TRACE, "TRACE"},
737         {WL_DBG_P2P_ACTION, "P2PACTION"}
738 };
739 #endif
740
741
742 static void wl_add_remove_pm_enable_work(struct wl_priv *wl, bool add_remove,
743         enum wl_handler_del_type type)
744 {
745         if (wl->pm_enable_work_on) {
746                 if (add_remove) {
747                         schedule_delayed_work(&wl->pm_enable_work,
748                                 msecs_to_jiffies(WL_PM_ENABLE_TIMEOUT));
749                 } else {
750                         cancel_delayed_work_sync(&wl->pm_enable_work);
751                         switch (type) {
752                                 case WL_HANDLER_MAINTAIN:
753                                         schedule_delayed_work(&wl->pm_enable_work,
754                                                 msecs_to_jiffies(WL_PM_ENABLE_TIMEOUT));
755                                         break;
756                                 case WL_HANDLER_PEND:
757                                         schedule_delayed_work(&wl->pm_enable_work,
758                                                 msecs_to_jiffies(WL_PM_ENABLE_TIMEOUT*2));
759                                         break;
760                                 case WL_HANDLER_DEL:
761                                 default:
762                                         wl->pm_enable_work_on = false;
763                                         break;
764                         }
765                 }
766         }
767 }
768
769 /* Return a new chanspec given a legacy chanspec
770  * Returns INVCHANSPEC on error
771  */
772 static chanspec_t
773 wl_chspec_from_legacy(chanspec_t legacy_chspec)
774 {
775         chanspec_t chspec;
776
777         /* get the channel number */
778         chspec = LCHSPEC_CHANNEL(legacy_chspec);
779
780         /* convert the band */
781         if (LCHSPEC_IS2G(legacy_chspec)) {
782                 chspec |= WL_CHANSPEC_BAND_2G;
783         } else {
784                 chspec |= WL_CHANSPEC_BAND_5G;
785         }
786
787         /* convert the bw and sideband */
788         if (LCHSPEC_IS20(legacy_chspec)) {
789                 chspec |= WL_CHANSPEC_BW_20;
790         } else {
791                 chspec |= WL_CHANSPEC_BW_40;
792                 if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
793                         chspec |= WL_CHANSPEC_CTL_SB_L;
794                 } else {
795                         chspec |= WL_CHANSPEC_CTL_SB_U;
796                 }
797         }
798
799         if (wf_chspec_malformed(chspec)) {
800                 WL_ERR(("wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
801                         chspec));
802                 return INVCHANSPEC;
803         }
804
805         return chspec;
806 }
807
808 /* Return a legacy chanspec given a new chanspec
809  * Returns INVCHANSPEC on error
810  */
811 static chanspec_t
812 wl_chspec_to_legacy(chanspec_t chspec)
813 {
814         chanspec_t lchspec;
815
816         if (wf_chspec_malformed(chspec)) {
817                 WL_ERR(("wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n",
818                         chspec));
819                 return INVCHANSPEC;
820         }
821
822         /* get the channel number */
823         lchspec = CHSPEC_CHANNEL(chspec);
824
825         /* convert the band */
826         if (CHSPEC_IS2G(chspec)) {
827                 lchspec |= WL_LCHANSPEC_BAND_2G;
828         } else {
829                 lchspec |= WL_LCHANSPEC_BAND_5G;
830         }
831
832         /* convert the bw and sideband */
833         if (CHSPEC_IS20(chspec)) {
834                 lchspec |= WL_LCHANSPEC_BW_20;
835                 lchspec |= WL_LCHANSPEC_CTL_SB_NONE;
836         } else if (CHSPEC_IS40(chspec)) {
837                 lchspec |= WL_LCHANSPEC_BW_40;
838                 if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_L) {
839                         lchspec |= WL_LCHANSPEC_CTL_SB_LOWER;
840                 } else {
841                         lchspec |= WL_LCHANSPEC_CTL_SB_UPPER;
842                 }
843         } else {
844                 /* cannot express the bandwidth */
845                 char chanbuf[CHANSPEC_STR_LEN];
846                 WL_ERR((
847                         "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) "
848                         "to pre-11ac format\n",
849                         wf_chspec_ntoa(chspec, chanbuf), chspec));
850                 return INVCHANSPEC;
851         }
852
853         return lchspec;
854 }
855
856 /* given a chanspec value, do the endian and chanspec version conversion to
857  * a chanspec_t value
858  * Returns INVCHANSPEC on error
859  */
860 static chanspec_t
861 wl_chspec_host_to_driver(chanspec_t chanspec)
862 {
863         if (ioctl_version == 1) {
864                 chanspec = wl_chspec_to_legacy(chanspec);
865                 if (chanspec == INVCHANSPEC) {
866                         return chanspec;
867                 }
868         }
869         chanspec = htodchanspec(chanspec);
870
871         return chanspec;
872 }
873
874 /* given a channel value, do the endian and chanspec version conversion to
875  * a chanspec_t value
876  * Returns INVCHANSPEC on error
877  */
878 chanspec_t
879 wl_ch_host_to_driver(u16 channel)
880 {
881
882         chanspec_t chanspec;
883
884         chanspec = channel & WL_CHANSPEC_CHAN_MASK;
885
886         if (channel <= CH_MAX_2G_CHANNEL)
887                 chanspec |= WL_CHANSPEC_BAND_2G;
888         else
889                 chanspec |= WL_CHANSPEC_BAND_5G;
890
891         chanspec |= WL_CHANSPEC_BW_20;
892         chanspec |= WL_CHANSPEC_CTL_SB_NONE;
893
894         return wl_chspec_host_to_driver(chanspec);
895 }
896
897 /* given a chanspec value from the driver, do the endian and chanspec version conversion to
898  * a chanspec_t value
899  * Returns INVCHANSPEC on error
900  */
901 static chanspec_t
902 wl_chspec_driver_to_host(chanspec_t chanspec)
903 {
904         chanspec = dtohchanspec(chanspec);
905         if (ioctl_version == 1) {
906                 chanspec = wl_chspec_from_legacy(chanspec);
907         }
908
909         return chanspec;
910 }
911
912 /* There isn't a lot of sense in it, but you can transmit anything you like */
913 static const struct ieee80211_txrx_stypes
914 wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
915         [NL80211_IFTYPE_ADHOC] = {
916                 .tx = 0xffff,
917                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
918         },
919         [NL80211_IFTYPE_STATION] = {
920                 .tx = 0xffff,
921                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
922                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
923         },
924         [NL80211_IFTYPE_AP] = {
925                 .tx = 0xffff,
926                 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
927                 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
928                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
929                 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
930                 BIT(IEEE80211_STYPE_AUTH >> 4) |
931                 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
932                 BIT(IEEE80211_STYPE_ACTION >> 4)
933         },
934         [NL80211_IFTYPE_AP_VLAN] = {
935                 /* copy AP */
936                 .tx = 0xffff,
937                 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
938                 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
939                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
940                 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
941                 BIT(IEEE80211_STYPE_AUTH >> 4) |
942                 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
943                 BIT(IEEE80211_STYPE_ACTION >> 4)
944         },
945         [NL80211_IFTYPE_P2P_CLIENT] = {
946                 .tx = 0xffff,
947                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
948                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
949         },
950         [NL80211_IFTYPE_P2P_GO] = {
951                 .tx = 0xffff,
952                 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
953                 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
954                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
955                 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
956                 BIT(IEEE80211_STYPE_AUTH >> 4) |
957                 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
958                 BIT(IEEE80211_STYPE_ACTION >> 4)
959         },
960 #if defined(WL_CFG80211_P2P_DEV_IF)
961         [NL80211_IFTYPE_P2P_DEVICE] = {
962                 .tx = 0xffff,
963                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
964                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
965         },
966 #endif /* WL_CFG80211_P2P_DEV_IF */
967 };
968
969 static void swap_key_from_BE(struct wl_wsec_key *key)
970 {
971         key->index = htod32(key->index);
972         key->len = htod32(key->len);
973         key->algo = htod32(key->algo);
974         key->flags = htod32(key->flags);
975         key->rxiv.hi = htod32(key->rxiv.hi);
976         key->rxiv.lo = htod16(key->rxiv.lo);
977         key->iv_initialized = htod32(key->iv_initialized);
978 }
979
980 static void swap_key_to_BE(struct wl_wsec_key *key)
981 {
982         key->index = dtoh32(key->index);
983         key->len = dtoh32(key->len);
984         key->algo = dtoh32(key->algo);
985         key->flags = dtoh32(key->flags);
986         key->rxiv.hi = dtoh32(key->rxiv.hi);
987         key->rxiv.lo = dtoh16(key->rxiv.lo);
988         key->iv_initialized = dtoh32(key->iv_initialized);
989 }
990
991 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !0
992 /* For debug: Dump the contents of the encoded wps ie buffe */
993 static void
994 wl_validate_wps_ie(char *wps_ie, s32 wps_ie_len, bool *pbc)
995 {
996         #define WPS_IE_FIXED_LEN 6
997         u16 len;
998         u8 *subel = NULL;
999         u16 subelt_id;
1000         u16 subelt_len;
1001         u16 val;
1002         u8 *valptr = (uint8*) &val;
1003         if (wps_ie == NULL || wps_ie_len < WPS_IE_FIXED_LEN) {
1004                 WL_ERR(("invalid argument : NULL\n"));
1005                 return;
1006         }
1007         len = (u16)wps_ie[TLV_LEN_OFF];
1008
1009         if (len > wps_ie_len) {
1010                 WL_ERR(("invalid length len %d, wps ie len %d\n", len, wps_ie_len));
1011                 return;
1012         }
1013         WL_DBG(("wps_ie len=%d\n", len));
1014         len -= 4;       /* for the WPS IE's OUI, oui_type fields */
1015         subel = wps_ie + WPS_IE_FIXED_LEN;
1016         while (len >= 4) {              /* must have attr id, attr len fields */
1017                 valptr[0] = *subel++;
1018                 valptr[1] = *subel++;
1019                 subelt_id = HTON16(val);
1020
1021                 valptr[0] = *subel++;
1022                 valptr[1] = *subel++;
1023                 subelt_len = HTON16(val);
1024
1025                 len -= 4;                       /* for the attr id, attr len fields */
1026                 len -= subelt_len;      /* for the remaining fields in this attribute */
1027                 WL_DBG((" subel=%p, subelt_id=0x%x subelt_len=%u\n",
1028                         subel, subelt_id, subelt_len));
1029
1030                 if (subelt_id == WPS_ID_VERSION) {
1031                         WL_DBG(("  attr WPS_ID_VERSION: %u\n", *subel));
1032                 } else if (subelt_id == WPS_ID_REQ_TYPE) {
1033                         WL_DBG(("  attr WPS_ID_REQ_TYPE: %u\n", *subel));
1034                 } else if (subelt_id == WPS_ID_CONFIG_METHODS) {
1035                         valptr[0] = *subel;
1036                         valptr[1] = *(subel + 1);
1037                         WL_DBG(("  attr WPS_ID_CONFIG_METHODS: %x\n", HTON16(val)));
1038                 } else if (subelt_id == WPS_ID_DEVICE_NAME) {
1039                         char devname[100];
1040                         memcpy(devname, subel, subelt_len);
1041                         devname[subelt_len] = '\0';
1042                         WL_DBG(("  attr WPS_ID_DEVICE_NAME: %s (len %u)\n",
1043                                 devname, subelt_len));
1044                 } else if (subelt_id == WPS_ID_DEVICE_PWD_ID) {
1045                         valptr[0] = *subel;
1046                         valptr[1] = *(subel + 1);
1047                         WL_DBG(("  attr WPS_ID_DEVICE_PWD_ID: %u\n", HTON16(val)));
1048                         *pbc = (HTON16(val) == DEV_PW_PUSHBUTTON) ? true : false;
1049                 } else if (subelt_id == WPS_ID_PRIM_DEV_TYPE) {
1050                         valptr[0] = *subel;
1051                         valptr[1] = *(subel + 1);
1052                         WL_DBG(("  attr WPS_ID_PRIM_DEV_TYPE: cat=%u \n", HTON16(val)));
1053                         valptr[0] = *(subel + 6);
1054                         valptr[1] = *(subel + 7);
1055                         WL_DBG(("  attr WPS_ID_PRIM_DEV_TYPE: subcat=%u\n", HTON16(val)));
1056                 } else if (subelt_id == WPS_ID_REQ_DEV_TYPE) {
1057                         valptr[0] = *subel;
1058                         valptr[1] = *(subel + 1);
1059                         WL_DBG(("  attr WPS_ID_REQ_DEV_TYPE: cat=%u\n", HTON16(val)));
1060                         valptr[0] = *(subel + 6);
1061                         valptr[1] = *(subel + 7);
1062                         WL_DBG(("  attr WPS_ID_REQ_DEV_TYPE: subcat=%u\n", HTON16(val)));
1063                 } else if (subelt_id == WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS) {
1064                         valptr[0] = *subel;
1065                         valptr[1] = *(subel + 1);
1066                         WL_DBG(("  attr WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS"
1067                                 ": cat=%u\n", HTON16(val)));
1068                 } else {
1069                         WL_DBG(("  unknown attr 0x%x\n", subelt_id));
1070                 }
1071
1072                 subel += subelt_len;
1073         }
1074 }
1075 #endif 
1076
1077 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
1078 {
1079         chanspec_t chspec;
1080         int err = 0;
1081         struct wl_priv *wl = wiphy_priv(wiphy);
1082         struct net_device *dev = wl_to_prmry_ndev(wl);
1083         struct ether_addr bssid;
1084         struct wl_bss_info *bss = NULL;
1085
1086         if ((err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), false))) {
1087                 /* STA interface is not associated. So start the new interface on a temp
1088                  * channel . Later proper channel will be applied by the above framework
1089                  * via set_channel (cfg80211 API).
1090                  */
1091                 WL_DBG(("Not associated. Return a temp channel. \n"));
1092                 return wl_ch_host_to_driver(WL_P2P_TEMP_CHAN);
1093         }
1094
1095
1096         *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
1097         if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, wl->extra_buf,
1098                 WL_EXTRA_BUF_MAX, false))) {
1099                         WL_ERR(("Failed to get associated bss info, use temp channel \n"));
1100                         chspec = wl_ch_host_to_driver(WL_P2P_TEMP_CHAN);
1101         }
1102         else {
1103                         bss = (struct wl_bss_info *) (wl->extra_buf + 4);
1104                         chspec =  bss->chanspec;
1105
1106                         WL_DBG(("Valid BSS Found. chanspec:%d \n", chspec));
1107         }
1108         return chspec;
1109 }
1110
1111 static bcm_struct_cfgdev *
1112 wl_cfg80211_add_monitor_if(char *name)
1113 {
1114 #if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)
1115         WL_INFO(("wl_cfg80211_add_monitor_if: No more support monitor interface\n"));
1116         return ERR_PTR(-EOPNOTSUPP);
1117 #else
1118         struct net_device* ndev = NULL;
1119
1120         dhd_add_monitor(name, &ndev);
1121         WL_INFO(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev));
1122         return ndev_to_cfgdev(ndev);
1123 #endif /* WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF */
1124 }
1125
1126 static bcm_struct_cfgdev *
1127 wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
1128 #if defined(WL_CFG80211_P2P_DEV_IF)
1129         const char *name,
1130 #else
1131         char *name,
1132 #endif /* WL_CFG80211_P2P_DEV_IF */
1133         enum nl80211_iftype type, u32 *flags,
1134         struct vif_params *params)
1135 {
1136         s32 err;
1137         s32 timeout = -1;
1138         s32 wlif_type = -1;
1139         s32 mode = 0;
1140         s32 val = 0;
1141         s32 dhd_mode = 0;
1142         chanspec_t chspec;
1143         struct wl_priv *wl = wiphy_priv(wiphy);
1144         struct net_device *_ndev;
1145         struct ether_addr primary_mac;
1146         int (*net_attach)(void *dhdp, int ifidx);
1147         bool rollback_lock = false;
1148 #ifdef PROP_TXSTATUS_VSDB
1149         s32 up = 1;
1150         dhd_pub_t *dhd;
1151 #endif /* PROP_TXSTATUS_VSDB */
1152
1153         if (!wl)
1154                 return ERR_PTR(-EINVAL);
1155
1156 #ifdef PROP_TXSTATUS_VSDB
1157         dhd = (dhd_pub_t *)(wl->pub);
1158 #endif /* PROP_TXSTATUS_VSDB */
1159
1160         /* Use primary I/F for sending cmds down to firmware */
1161         _ndev = wl_to_prmry_ndev(wl);
1162
1163         if (wl_get_drv_status(wl, CONNECTING, _ndev)) {
1164                 WL_ERR(("Already AP connection going on\n"));
1165                 return -EBUSY;
1166         }
1167
1168         WL_DBG(("if name: %s, type: %d\n", name, type));
1169         switch (type) {
1170         case NL80211_IFTYPE_ADHOC:
1171         case NL80211_IFTYPE_AP_VLAN:
1172         case NL80211_IFTYPE_WDS:
1173         case NL80211_IFTYPE_MESH_POINT:
1174                 WL_ERR(("Unsupported interface type\n"));
1175                 mode = WL_MODE_IBSS;
1176                 return NULL;
1177         case NL80211_IFTYPE_MONITOR:
1178                 return wl_cfg80211_add_monitor_if((char *)name);
1179 #if defined(WL_CFG80211_P2P_DEV_IF)
1180         case NL80211_IFTYPE_P2P_DEVICE:
1181                 return wl_cfgp2p_add_p2p_disc_if();
1182 #endif /* WL_CFG80211_P2P_DEV_IF */
1183         case NL80211_IFTYPE_P2P_CLIENT:
1184         case NL80211_IFTYPE_STATION:
1185                 wlif_type = WL_P2P_IF_CLIENT;
1186                 mode = WL_MODE_BSS;
1187                 break;
1188         case NL80211_IFTYPE_P2P_GO:
1189         case NL80211_IFTYPE_AP:
1190                 wlif_type = WL_P2P_IF_GO;
1191                 mode = WL_MODE_AP;
1192                 break;
1193         default:
1194                 WL_ERR(("Unsupported interface type\n"));
1195                 return NULL;
1196                 break;
1197         }
1198
1199         if (!name) {
1200                 WL_ERR(("name is NULL\n"));
1201                 return NULL;
1202         }
1203         if (wl->p2p_supported && (wlif_type != -1)) {
1204                 ASSERT(wl->p2p); /* ensure expectation of p2p initialization */
1205                 if (wl_get_p2p_status(wl, IF_DELETING)) {
1206                         /* wait till IF_DEL is complete
1207                          * release the lock for the unregister to proceed
1208                          */
1209                         if (rtnl_is_locked()) {
1210                                 rtnl_unlock();
1211                                 rollback_lock = true;
1212                         }
1213                         WL_INFO(("Released the lock and wait till IF_DEL is complete\n"));
1214                         timeout = wait_event_interruptible_timeout(wl->netif_change_event,
1215                                 (wl_get_p2p_status(wl, IF_DELETING) == false),
1216                                 msecs_to_jiffies(MAX_WAIT_TIME));
1217
1218                         /* put back the rtnl_lock again */
1219                         if (rollback_lock) {
1220                                 rtnl_lock();
1221                                 rollback_lock = false;
1222                         }
1223                         if (timeout > 0) {
1224                                 WL_ERR(("IF DEL is Success\n"));
1225
1226                         } else {
1227                                 WL_ERR(("timeount < 0, return -EAGAIN\n"));
1228                                 return ERR_PTR(-EAGAIN);
1229                         }
1230                         /* It should be now be safe to put this check here since we are sure
1231                          * by now netdev_notifier (unregister) would have been called
1232                          */
1233                         if (wl->iface_cnt == IFACE_MAX_CNT)
1234                                 return ERR_PTR(-ENOMEM);
1235                 }
1236
1237 #ifdef PROP_TXSTATUS_VSDB
1238                 if (!dhd)
1239                         return ERR_PTR(-ENODEV);
1240 #endif /* PROP_TXSTATUS_VSDB */
1241                 if (!wl->p2p)
1242                         return ERR_PTR(-ENODEV);
1243
1244                 if (wl->p2p && !wl->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
1245                         p2p_on(wl) = true;
1246                         wl_cfgp2p_set_firm_p2p(wl);
1247                         wl_cfgp2p_init_discovery(wl);
1248                         get_primary_mac(wl, &primary_mac);
1249                         wl_cfgp2p_generate_bss_mac(&primary_mac,
1250                                 &wl->p2p->dev_addr, &wl->p2p->int_addr);
1251                 }
1252
1253                 memset(wl->p2p->vir_ifname, 0, IFNAMSIZ);
1254                 strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1);
1255
1256                 wl_cfg80211_scan_abort(wl);
1257 #ifdef PROP_TXSTATUS_VSDB
1258                 if (dhd->op_mode != DHD_FLAG_IBSS_MODE && !wl->wlfc_on && !disable_proptx) {
1259                         dhd->wlfc_enabled = true;
1260                         dhd_wlfc_init(dhd);
1261                         err = wldev_ioctl(_ndev, WLC_UP, &up, sizeof(s32), true);
1262                         if (err < 0)
1263                                 WL_ERR(("WLC_UP return err:%d\n", err));
1264                         wl->wlfc_on = true;
1265                 }
1266 #endif /* PROP_TXSTATUS_VSDB */
1267
1268                 /* In concurrency case, STA may be already associated in a particular channel.
1269                  * so retrieve the current channel of primary interface and then start the virtual
1270                  * interface on that.
1271                  */
1272                  chspec = wl_cfg80211_get_shared_freq(wiphy);
1273
1274                 /* For P2P mode, use P2P-specific driver features to create the
1275                  * bss: "wl p2p_ifadd"
1276                  */
1277                 wl_set_p2p_status(wl, IF_ADD);
1278                 if (wlif_type == WL_P2P_IF_GO)
1279                         wldev_iovar_setint(_ndev, "mpc", 0);
1280                 err = wl_cfgp2p_ifadd(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec);
1281
1282                 if (unlikely(err)) {
1283                         WL_ERR((" virtual iface add failed (%d) \n", err));
1284                         return ERR_PTR(-ENOMEM);
1285                 }
1286
1287                 timeout = wait_event_interruptible_timeout(wl->netif_change_event,
1288                         (wl_get_p2p_status(wl, IF_ADD) == false),
1289                         msecs_to_jiffies(MAX_WAIT_TIME));
1290                 if (timeout > 0 && (!wl_get_p2p_status(wl, IF_ADD))) {
1291
1292                         struct wireless_dev *vwdev;
1293                         vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL);
1294                         if (unlikely(!vwdev)) {
1295                                 WL_ERR(("Could not allocate wireless device\n"));
1296                                 return ERR_PTR(-ENOMEM);
1297                         }
1298                         vwdev->wiphy = wl->wdev->wiphy;
1299                         WL_INFO((" virtual interface(%s) is created memalloc done \n",
1300                                 wl->p2p->vir_ifname));
1301                         vwdev->iftype = type;
1302                         _ndev =  wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
1303                         _ndev->ieee80211_ptr = vwdev;
1304 #ifndef CONFIG_BCMDHD_DISABLE_P2P_SYSFS_DEVICE_NODE
1305                         SET_NETDEV_DEV(_ndev, wiphy_dev(vwdev->wiphy));
1306 #endif
1307                         vwdev->netdev = _ndev;
1308                         wl_set_drv_status(wl, READY, _ndev);
1309                         wl->p2p->vif_created = true;
1310                         wl_set_mode_by_netdev(wl, _ndev, mode);
1311                         net_attach =  wl_to_p2p_bss_private(wl, P2PAPI_BSSCFG_CONNECTION);
1312                         if (net_attach && !net_attach(wl->pub, _ndev->ifindex)) {
1313                                 wl_alloc_netinfo(wl, _ndev, vwdev, mode, PM_ENABLE);
1314                                 val = 1;
1315                                 /* Disable firmware roaming for P2P interface  */
1316                                 wldev_iovar_setint(_ndev, "roam_off", val);
1317
1318                                 if (mode != WL_MODE_AP)
1319                                         wldev_iovar_setint(_ndev, "buf_key_b4_m4", 1);
1320
1321                                 WL_ERR((" virtual interface(%s) is "
1322                                         "created net attach done\n", wl->p2p->vir_ifname));
1323                                 if (mode == WL_MODE_AP)
1324                                         wl_set_drv_status(wl, CONNECTED, _ndev);
1325                                 if (type == NL80211_IFTYPE_P2P_CLIENT)
1326                                         dhd_mode = DHD_FLAG_P2P_GC_MODE;
1327                                 else if (type == NL80211_IFTYPE_P2P_GO)
1328                                         dhd_mode = DHD_FLAG_P2P_GO_MODE;
1329                                 DNGL_FUNC(dhd_cfg80211_set_p2p_info, (wl, dhd_mode));
1330 #ifdef PROP_TXSTATUS_VSDB
1331                                 if (dhd->op_mode != DHD_FLAG_IBSS_MODE && dhd->plat_enable)
1332                                         dhd->plat_enable((void *)dhd);
1333 #endif /* PROP_TXSTATUS_VSDB */
1334                                 /* reinitialize completion to clear previous count */
1335                                 INIT_COMPLETION(wl->iface_disable);
1336                         } else {
1337                                 goto fail;
1338                         }
1339                         return ndev_to_cfgdev(_ndev);
1340                 } else {
1341                         wl_clr_p2p_status(wl, IF_ADD);
1342                         WL_ERR((" virtual interface(%s) is not created \n", wl->p2p->vir_ifname));
1343                         memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ);
1344                         wl->p2p->vif_created = false;
1345 #ifdef PROP_TXSTATUS_VSDB
1346                 if (dhd->op_mode != DHD_FLAG_IBSS_MODE && dhd->wlfc_enabled && wl->wlfc_on) {
1347                         dhd->wlfc_enabled = false;
1348                         dhd_wlfc_deinit(dhd);
1349                         if (dhd->plat_deinit)
1350                                 dhd->plat_deinit((void *)dhd);
1351                         wl->wlfc_on = false;
1352                 }
1353 #endif /* PROP_TXSTATUS_VSDB */
1354                 }
1355         }
1356 fail:
1357         if (wlif_type == WL_P2P_IF_GO)
1358                 wldev_iovar_setint(_ndev, "mpc", 1);
1359         return ERR_PTR(-ENODEV);
1360 }
1361
1362 static s32
1363 wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
1364 {
1365         struct net_device *dev = NULL;
1366         struct ether_addr p2p_mac;
1367         struct wl_priv *wl = wiphy_priv(wiphy);
1368         s32 timeout = -1;
1369         s32 ret = 0;
1370         s32 index = -1;
1371         WL_DBG(("Enter\n"));
1372
1373         if (!wl)
1374                 return ERR_PTR(-EINVAL);
1375
1376 #if defined(WL_CFG80211_P2P_DEV_IF)
1377         if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
1378                 return wl_cfgp2p_del_p2p_disc_if(cfgdev);
1379         }
1380 #endif /* WL_CFG80211_P2P_DEV_IF */
1381         dev = cfgdev_to_wlc_ndev(cfgdev, wl);
1382
1383         if (wl_cfgp2p_find_idx(wl, dev, &index) != BCME_OK) {
1384                 WL_ERR(("Find p2p index from ndev(%p) failed\n", dev));
1385                 return BCME_ERROR;
1386         }
1387         if (wl->p2p_supported) {
1388                 memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN);
1389
1390                 /* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases
1391                  */
1392                 WL_DBG(("P2P: GO_NEG_PHASE status cleared "));
1393                 wl_clr_p2p_status(wl, GO_NEG_PHASE);
1394                 if (wl->p2p->vif_created) {
1395                         if (wl_get_drv_status(wl, SCANNING, dev)) {
1396                                 wl_notify_escan_complete(wl, dev, true, true);
1397                         }
1398                         wldev_iovar_setint(dev, "mpc", 1);
1399                         /* Delete pm_enable_work */
1400                         wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_DEL);
1401
1402                         /* for GC */
1403                         if (wl_get_drv_status(wl, DISCONNECTING, dev) &&
1404                                 (wl_get_mode_by_netdev(wl, dev) != WL_MODE_AP)) {
1405                                 WL_ERR(("Wait for Link Down event for GC !\n"));
1406                                 wait_for_completion_timeout
1407                                         (&wl->iface_disable, msecs_to_jiffies(500));
1408                         }
1409                         wl_set_p2p_status(wl, IF_DELETING);
1410                         DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (wl));
1411
1412                         /* for GO */
1413                         if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) {
1414                                 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
1415                                 /* disable interface before bsscfg free */
1416                                 ret = wl_cfgp2p_ifdisable(wl, &p2p_mac);
1417                                 /* if fw doesn't support "ifdis",
1418                                    do not wait for link down of ap mode
1419                                  */
1420                                 if (ret == 0) {
1421                                         WL_ERR(("Wait for Link Down event for GO !!!\n"));
1422                                         wait_for_completion_timeout(&wl->iface_disable,
1423                                                 msecs_to_jiffies(500));
1424                                 } else if (ret != BCME_UNSUPPORTED) {
1425                                         msleep(300);
1426                                 }
1427                         }
1428                         wl_cfgp2p_clear_management_ie(wl, index);
1429
1430                         if (wl_get_mode_by_netdev(wl, dev) != WL_MODE_AP)
1431                                 wldev_iovar_setint(dev, "buf_key_b4_m4", 0);
1432
1433                         /* delete interface after link down */
1434                         ret = wl_cfgp2p_ifdel(wl, &p2p_mac);
1435                         /* Firmware could not delete the interface so we will not get WLC_E_IF
1436                         * event for cleaning the dhd virtual nw interace
1437                         * So lets do it here. Failures from fw will ensure the application to do
1438                         * ifconfig <inter> down and up sequnce, which will reload the fw
1439                         * however we should cleanup the linux network virtual interfaces
1440                         */
1441                         /* Request framework to RESET and clean up */
1442                         if (ret) {
1443                                 struct net_device *ndev = wl_to_prmry_ndev(wl);
1444                                 WL_ERR(("Firmware returned an error (%d) from p2p_ifdel"
1445                                         "HANG Notification sent to %s\n", ret, ndev->name));
1446                                 net_os_send_hang_message(ndev);
1447                         }
1448                         /* Wait for IF_DEL operation to be finished in firmware */
1449                         timeout = wait_event_interruptible_timeout(wl->netif_change_event,
1450                                 (wl->p2p->vif_created == false),
1451                                 msecs_to_jiffies(MAX_WAIT_TIME));
1452                         if (timeout > 0 && (wl->p2p->vif_created == false)) {
1453                                 WL_DBG(("IFDEL operation done\n"));
1454                         } else {
1455                                 WL_ERR(("IFDEL didn't complete properly\n"));
1456                         }
1457                         ret = dhd_del_monitor(dev);
1458                 }
1459         }
1460         return ret;
1461 }
1462
1463 static s32
1464 wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
1465         enum nl80211_iftype type, u32 *flags,
1466         struct vif_params *params)
1467 {
1468         s32 ap = 0;
1469         s32 infra = 0;
1470         s32 ibss = 0;
1471         s32 wlif_type;
1472         s32 mode = 0;
1473         s32 err = BCME_OK;
1474         chanspec_t chspec;
1475         struct wl_priv *wl = wiphy_priv(wiphy);
1476         dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
1477         WL_DBG(("Enter type %d\n", type));
1478
1479         if (!wl)
1480                 return ERR_PTR(-EINVAL);
1481         switch (type) {
1482         case NL80211_IFTYPE_MONITOR:
1483         case NL80211_IFTYPE_WDS:
1484         case NL80211_IFTYPE_MESH_POINT:
1485                 ap = 1;
1486                 WL_ERR(("type (%d) : currently we do not support this type\n",
1487                         type));
1488                 break;
1489         case NL80211_IFTYPE_ADHOC:
1490                 mode = WL_MODE_IBSS;
1491                 ibss = 1;
1492                 break;
1493         case NL80211_IFTYPE_STATION:
1494         case NL80211_IFTYPE_P2P_CLIENT:
1495                 mode = WL_MODE_BSS;
1496                 infra = 1;
1497                 break;
1498         case NL80211_IFTYPE_AP:
1499         case NL80211_IFTYPE_AP_VLAN:
1500         case NL80211_IFTYPE_P2P_GO:
1501                 mode = WL_MODE_AP;
1502                 ap = 1;
1503                 break;
1504         default:
1505                 return -EINVAL;
1506         }
1507         if (!dhd)
1508                 return -EINVAL;
1509         if (ap) {
1510                 wl_set_mode_by_netdev(wl, ndev, mode);
1511                 if (wl->p2p_supported && wl->p2p->vif_created) {
1512                         WL_DBG(("p2p_vif_created (%d) p2p_on (%d)\n", wl->p2p->vif_created,
1513                         p2p_on(wl)));
1514                         wldev_iovar_setint(ndev, "mpc", 0);
1515                         wl_notify_escan_complete(wl, ndev, true, true);
1516
1517                         /* In concurrency case, STA may be already associated in a particular
1518                          * channel. so retrieve the current channel of primary interface and
1519                          * then start the virtual interface on that.
1520                          */
1521                         chspec = wl_cfg80211_get_shared_freq(wiphy);
1522
1523                         wlif_type = WL_P2P_IF_GO;
1524                         WL_ERR(("%s : ap (%d), infra (%d), iftype: (%d)\n",
1525                                 ndev->name, ap, infra, type));
1526                         wl_set_p2p_status(wl, IF_CHANGING);
1527                         wl_clr_p2p_status(wl, IF_CHANGED);
1528                         wl_cfgp2p_ifchange(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec);
1529                         wait_event_interruptible_timeout(wl->netif_change_event,
1530                                 (wl_get_p2p_status(wl, IF_CHANGED) == true),
1531                                 msecs_to_jiffies(MAX_WAIT_TIME));
1532                         wl_set_mode_by_netdev(wl, ndev, mode);
1533                         dhd->op_mode &= ~DHD_FLAG_P2P_GC_MODE;
1534                         dhd->op_mode |= DHD_FLAG_P2P_GO_MODE;
1535                         wl_clr_p2p_status(wl, IF_CHANGING);
1536                         wl_clr_p2p_status(wl, IF_CHANGED);
1537                         if (mode == WL_MODE_AP)
1538                                 wl_set_drv_status(wl, CONNECTED, ndev);
1539                 } else if (ndev == wl_to_prmry_ndev(wl) &&
1540                         !wl_get_drv_status(wl, AP_CREATED, ndev)) {
1541                         wl_set_drv_status(wl, AP_CREATING, ndev);
1542                         if (!wl->ap_info &&
1543                                 !(wl->ap_info = kzalloc(sizeof(struct ap_info), GFP_KERNEL))) {
1544                                 WL_ERR(("struct ap_saved_ie allocation failed\n"));
1545                                 return -ENOMEM;
1546                         }
1547                 } else {
1548                         WL_ERR(("Cannot change the interface for GO or SOFTAP\n"));
1549                         return -EINVAL;
1550                 }
1551         } else {
1552                 WL_DBG(("Change_virtual_iface for transition from GO/AP to client/STA"));
1553         }
1554
1555         if (ibss) {
1556                 infra = 0;
1557                 wl_set_mode_by_netdev(wl, ndev, mode);
1558                 err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(s32), true);
1559                 if (err < 0) {
1560                         WL_ERR(("SET Adhoc error %d\n", err));
1561                         return -EINVAL;
1562         }
1563         }
1564
1565         ndev->ieee80211_ptr->iftype = type;
1566         return 0;
1567 }
1568
1569 s32
1570 wl_cfg80211_notify_ifadd(struct net_device *ndev, s32 idx, s32 bssidx,
1571         void* _net_attach)
1572 {
1573         struct wl_priv *wl = wlcfg_drv_priv;
1574         s32 ret = BCME_OK;
1575         WL_DBG(("Enter"));
1576         if (!ndev) {
1577                 WL_ERR(("net is NULL\n"));
1578                 return 0;
1579         }
1580         if (wl->p2p_supported && wl_get_p2p_status(wl, IF_ADD)) {
1581                 WL_DBG(("IF_ADD event called from dongle, old interface name: %s,"
1582                         "new name: %s\n", ndev->name, wl->p2p->vir_ifname));
1583                 /* Assign the net device to CONNECT BSSCFG */
1584                 strncpy(ndev->name, wl->p2p->vir_ifname, IFNAMSIZ - 1);
1585                 wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = ndev;
1586                 wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = bssidx;
1587                 wl_to_p2p_bss_private(wl, P2PAPI_BSSCFG_CONNECTION) = _net_attach;
1588                 ndev->ifindex = idx;
1589                 wl_clr_p2p_status(wl, IF_ADD);
1590
1591                 wake_up_interruptible(&wl->netif_change_event);
1592         } else {
1593                 ret = BCME_NOTREADY;
1594         }
1595         return ret;
1596 }
1597
1598 s32
1599 wl_cfg80211_notify_ifdel(void)
1600 {
1601         struct wl_priv *wl = wlcfg_drv_priv;
1602
1603         WL_DBG(("Enter \n"));
1604         wl_clr_p2p_status(wl, IF_DELETING);
1605         wake_up_interruptible(&wl->netif_change_event);
1606         return 0;
1607 }
1608
1609 s32
1610 wl_cfg80211_ifdel_ops(struct net_device *ndev)
1611 {
1612         struct wl_priv *wl = wlcfg_drv_priv;
1613         bool rollback_lock = false;
1614         s32 type = -1;
1615         s32 bssidx = -1;
1616
1617 #ifdef PROP_TXSTATUS_VSDB
1618         dhd_pub_t *dhd =  (dhd_pub_t *)(wl->pub);
1619 #endif /* PROP_TXSTATUS_VSDB */
1620         if (!ndev || (strlen(ndev->name) == 0)) {
1621                 WL_ERR(("net is NULL\n"));
1622                 return 0;
1623         }
1624
1625         if (p2p_is_on(wl) && wl->p2p->vif_created &&
1626                 wl_get_p2p_status(wl, IF_DELETING)) {
1627                 if (wl->scan_request &&
1628                         (wl->escan_info.ndev == ndev)) {
1629                         /* Abort any pending scan requests */
1630                         wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
1631                         if (!rtnl_is_locked()) {
1632                                 rtnl_lock();
1633                                 rollback_lock = true;
1634                         }
1635                         WL_DBG(("ESCAN COMPLETED\n"));
1636                         wl_notify_escan_complete(wl, ndev, true, false);
1637                         if (rollback_lock)
1638                                 rtnl_unlock();
1639                 }
1640                 WL_ERR(("IF_DEL event called from dongle, net %p, vif name: %s\n",
1641                         ndev, wl->p2p->vir_ifname));
1642
1643                 memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ);
1644                 if (wl_cfgp2p_find_idx(wl, ndev, &bssidx) != BCME_OK) {
1645                         WL_ERR(("Find p2p bssidx from ndev(%p) failed\n", ndev));
1646                         return BCME_ERROR;
1647                 }
1648                 if (wl_cfgp2p_find_type(wl, bssidx, &type) != BCME_OK) {
1649                         WL_ERR(("Find p2p type from bssidx(%d) failed\n", bssidx));
1650                         return BCME_ERROR;
1651                 }
1652                 wl_to_p2p_bss_ndev(wl, type) = NULL;
1653                 wl_to_p2p_bss_bssidx(wl, type) = WL_INVALID;
1654                 wl->p2p->vif_created = false;
1655
1656                 WL_DBG(("type : %d\n", type));
1657 #ifdef PROP_TXSTATUS_VSDB
1658                 if (dhd->op_mode != DHD_FLAG_IBSS_MODE && dhd->wlfc_enabled && wl->wlfc_on) {
1659                         dhd->wlfc_enabled = false;
1660                         dhd_wlfc_deinit(dhd);
1661                         if (dhd->plat_deinit)
1662                                 dhd->plat_deinit((void *)dhd);
1663                         wl->wlfc_on = false;
1664                 }
1665 #endif /* PROP_TXSTATUS_VSDB */
1666                 wl_clr_drv_status(wl, CONNECTED, ndev);
1667         }
1668         /* Wake up any waiting thread */
1669         wake_up_interruptible(&wl->netif_change_event);
1670
1671         return 0;
1672 }
1673
1674 s32
1675 wl_cfg80211_is_progress_ifadd(void)
1676 {
1677         s32 is_progress = 0;
1678         struct wl_priv *wl = wlcfg_drv_priv;
1679         if (wl_get_p2p_status(wl, IF_ADD))
1680                 is_progress = 1;
1681         return is_progress;
1682 }
1683
1684 s32
1685 wl_cfg80211_is_progress_ifchange(void)
1686 {
1687         s32 is_progress = 0;
1688         struct wl_priv *wl = wlcfg_drv_priv;
1689         if (wl_get_p2p_status(wl, IF_CHANGING))
1690                 is_progress = 1;
1691         return is_progress;
1692 }
1693
1694
1695 s32
1696 wl_cfg80211_notify_ifchange(void)
1697 {
1698         struct wl_priv *wl = wlcfg_drv_priv;
1699         if (wl_get_p2p_status(wl, IF_CHANGING)) {
1700                 wl_set_p2p_status(wl, IF_CHANGED);
1701                 wake_up_interruptible(&wl->netif_change_event);
1702         }
1703         return 0;
1704 }
1705
1706 /* Find listen channel */
1707 static s32 wl_find_listen_channel(struct wl_priv *wl,
1708         const u8 *ie, u32 ie_len)
1709 {
1710         wifi_p2p_ie_t *p2p_ie;
1711         u8 *end, *pos;
1712         s32 listen_channel;
1713
1714         pos = (u8 *)ie;
1715         p2p_ie = wl_cfgp2p_find_p2pie(pos, ie_len);
1716
1717         if (p2p_ie == NULL)
1718                 return 0;
1719
1720         pos = p2p_ie->subelts;
1721         end = p2p_ie->subelts + (p2p_ie->len - 4);
1722
1723         CFGP2P_DBG((" found p2p ie ! lenth %d \n",
1724                 p2p_ie->len));
1725
1726         while (pos < end) {
1727                 uint16 attr_len;
1728                 if (pos + 2 >= end) {
1729                         CFGP2P_DBG((" -- Invalid P2P attribute"));
1730                         return 0;
1731                 }
1732                 attr_len = ((uint16) (((pos + 1)[1] << 8) | (pos + 1)[0]));
1733
1734                 if (pos + 3 + attr_len > end) {
1735                         CFGP2P_DBG(("P2P: Attribute underflow "
1736                                    "(len=%u left=%d)",
1737                                    attr_len, (int) (end - pos - 3)));
1738                         return 0;
1739                 }
1740
1741                 /* if Listen Channel att id is 6 and the vailue is valid,
1742                  * return the listen channel
1743                  */
1744                 if (pos[0] == 6) {
1745                         /* listen channel subel length format
1746                          * 1(id) + 2(len) + 3(country) + 1(op. class) + 1(chan num)
1747                          */
1748                         listen_channel = pos[1 + 2 + 3 + 1];
1749
1750                         if (listen_channel == SOCIAL_CHAN_1 ||
1751                                 listen_channel == SOCIAL_CHAN_2 ||
1752                                 listen_channel == SOCIAL_CHAN_3) {
1753                                 CFGP2P_DBG((" Found my Listen Channel %d \n", listen_channel));
1754                                 return listen_channel;
1755                         }
1756                 }
1757                 pos += 3 + attr_len;
1758         }
1759         return 0;
1760 }
1761
1762 static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_request *request)
1763 {
1764         u32 n_ssids;
1765         u32 n_channels;
1766         u16 channel;
1767         chanspec_t chanspec;
1768         s32 i = 0, j = 0, offset;
1769         char *ptr;
1770         wlc_ssid_t ssid;
1771         struct wl_priv *wl = wlcfg_drv_priv;
1772
1773         memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
1774         params->bss_type = DOT11_BSSTYPE_ANY;
1775         params->scan_type = 0;
1776         params->nprobes = -1;
1777         params->active_time = -1;
1778         params->passive_time = -1;
1779         params->home_time = -1;
1780         params->channel_num = 0;
1781         memset(&params->ssid, 0, sizeof(wlc_ssid_t));
1782
1783         WL_SCAN(("Preparing Scan request\n"));
1784         WL_SCAN(("nprobes=%d\n", params->nprobes));
1785         WL_SCAN(("active_time=%d\n", params->active_time));
1786         WL_SCAN(("passive_time=%d\n", params->passive_time));
1787         WL_SCAN(("home_time=%d\n", params->home_time));
1788         WL_SCAN(("scan_type=%d\n", params->scan_type));
1789
1790         params->nprobes = htod32(params->nprobes);
1791         params->active_time = htod32(params->active_time);
1792         params->passive_time = htod32(params->passive_time);
1793         params->home_time = htod32(params->home_time);
1794
1795         /* if request is null just exit so it will be all channel broadcast scan */
1796         if (!request)
1797                 return;
1798
1799         n_ssids = request->n_ssids;
1800         n_channels = request->n_channels;
1801
1802         /* Copy channel array if applicable */
1803         WL_SCAN(("### List of channelspecs to scan ###\n"));
1804         if (n_channels > 0) {
1805                 for (i = 0; i < n_channels; i++) {
1806                         chanspec = 0;
1807                         channel = ieee80211_frequency_to_channel(request->channels[i]->center_freq);
1808                         /* SKIP DFS channels for Secondary interface */
1809                         if ((wl->escan_info.ndev != wl_to_prmry_ndev(wl)) &&
1810                                 (request->channels[i]->flags &
1811                                 (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN)))
1812                                 continue;
1813
1814                         if (request->channels[i]->band == IEEE80211_BAND_2GHZ) {
1815                                 chanspec |= WL_CHANSPEC_BAND_2G;
1816                         } else {
1817                                 chanspec |= WL_CHANSPEC_BAND_5G;
1818                         }
1819
1820                         chanspec |= WL_CHANSPEC_BW_20;
1821                         chanspec |= WL_CHANSPEC_CTL_SB_NONE;
1822
1823                         params->channel_list[j] = channel;
1824                         params->channel_list[j] &= WL_CHANSPEC_CHAN_MASK;
1825                         params->channel_list[j] |= chanspec;
1826                         WL_SCAN(("Chan : %d, Channel spec: %x \n",
1827                                 channel, params->channel_list[j]));
1828                         params->channel_list[j] = wl_chspec_host_to_driver(params->channel_list[j]);
1829                         j++;
1830                 }
1831         } else {
1832                 WL_SCAN(("Scanning all channels\n"));
1833         }
1834         n_channels = j;
1835         /* Copy ssid array if applicable */
1836         WL_SCAN(("### List of SSIDs to scan ###\n"));
1837         if (n_ssids > 0) {
1838                 offset = offsetof(wl_scan_params_t, channel_list) + n_channels * sizeof(u16);
1839                 offset = roundup(offset, sizeof(u32));
1840                 ptr = (char*)params + offset;
1841                 for (i = 0; i < n_ssids; i++) {
1842                         memset(&ssid, 0, sizeof(wlc_ssid_t));
1843                         ssid.SSID_len = request->ssids[i].ssid_len;
1844                         memcpy(ssid.SSID, request->ssids[i].ssid, ssid.SSID_len);
1845                         if (!ssid.SSID_len)
1846                                 WL_SCAN(("%d: Broadcast scan\n", i));
1847                         else
1848                                 WL_SCAN(("%d: scan  for  %s size =%d\n", i,
1849                                 ssid.SSID, ssid.SSID_len));
1850                         memcpy(ptr, &ssid, sizeof(wlc_ssid_t));
1851                         ptr += sizeof(wlc_ssid_t);
1852                 }
1853         } else {
1854                 WL_SCAN(("Broadcast scan\n"));
1855         }
1856         /* Adding mask to channel numbers */
1857         params->channel_num =
1858                 htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) |
1859                        (n_channels & WL_SCAN_PARAMS_COUNT_MASK));
1860
1861         if (n_channels == 1) {
1862                 params->active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
1863                 params->nprobes = htod32(params->active_time / WL_SCAN_JOIN_PROBE_INTERVAL_MS);
1864         }
1865 }
1866
1867 static s32
1868 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request, u16 action)
1869 {
1870         u32 n_channels;
1871         u32 n_ssids;
1872         s32 params_size =
1873             (WL_SCAN_PARAMS_FIXED_SIZE + offsetof(wl_iscan_params_t, params));
1874         struct wl_iscan_params *params = NULL;
1875         s32 err = 0;
1876
1877         if (request != NULL) {
1878                 n_channels = request->n_channels;
1879                 n_ssids = request->n_ssids;
1880                 /* Allocate space for populating ssids in wl_iscan_params struct */
1881                 if (n_channels % 2)
1882                         /* If n_channels is odd, add a padd of u16 */
1883                         params_size += sizeof(u16) * (n_channels + 1);
1884                 else
1885                         params_size += sizeof(u16) * n_channels;
1886
1887                 /* Allocate space for populating ssids in wl_iscan_params struct */
1888                 params_size += sizeof(struct wlc_ssid) * n_ssids;
1889         }
1890         params = (struct wl_iscan_params *)kzalloc(params_size, GFP_KERNEL);
1891         if (!params) {
1892                 err = -ENOMEM;
1893                 goto done;
1894         }
1895         wl_scan_prep(&params->params, request);
1896
1897         params->version = htod32(ISCAN_REQ_VERSION);
1898         params->action = htod16(action);
1899         params->scan_duration = htod16(0);
1900
1901         if (params_size + sizeof("iscan") >= WLC_IOCTL_MEDLEN) {
1902                 WL_ERR(("ioctl buffer length is not sufficient\n"));
1903                 err = -ENOMEM;
1904                 goto done;
1905         }
1906         err = wldev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
1907                 iscan->ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
1908         if (unlikely(err)) {
1909                 if (err == -EBUSY) {
1910                         WL_ERR(("system busy : iscan canceled\n"));
1911                 } else {
1912                         WL_ERR(("error (%d)\n", err));
1913                 }
1914         }
1915
1916 done:
1917         if (params)
1918                 kfree(params);
1919         return err;
1920 }
1921
1922 static s32 wl_do_iscan(struct wl_priv *wl, struct cfg80211_scan_request *request)
1923 {
1924         struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
1925         struct net_device *ndev = wl_to_prmry_ndev(wl);
1926         s32 passive_scan;
1927         s32 err = 0;
1928
1929         iscan->state = WL_ISCAN_STATE_SCANING;
1930
1931         passive_scan = wl->active_scan ? 0 : 1;
1932         err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
1933                 &passive_scan, sizeof(passive_scan), true);
1934         if (unlikely(err)) {
1935                 WL_DBG(("error (%d)\n", err));
1936                 return err;
1937         }
1938         wl->iscan_kickstart = true;
1939         wl_run_iscan(iscan, request, WL_SCAN_ACTION_START);
1940         mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms));
1941         iscan->timer_on = 1;
1942
1943         return err;
1944 }
1945 static s32
1946 wl_get_valid_channels(struct net_device *ndev, u8 *valid_chan_list, s32 size)
1947 {
1948         wl_uint32_list_t *list;
1949         s32 err = BCME_OK;
1950         if (valid_chan_list == NULL || size <= 0)
1951                 return -ENOMEM;
1952
1953         memset(valid_chan_list, 0, size);
1954         list = (wl_uint32_list_t *)(void *) valid_chan_list;
1955         list->count = htod32(WL_NUMCHANNELS);
1956         err = wldev_ioctl(ndev, WLC_GET_VALID_CHANNELS, valid_chan_list, size, false);
1957         if (err != 0) {
1958                 WL_ERR(("get channels failed with %d\n", err));
1959         }
1960
1961         return err;
1962 }
1963
1964 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
1965 #define FIRST_SCAN_ACTIVE_DWELL_TIME_MS 40
1966 static bool
1967 g_first_broadcast_scan = TRUE;
1968 #endif 
1969
1970 static s32
1971 wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
1972         struct cfg80211_scan_request *request, uint16 action)
1973 {
1974         s32 err = BCME_OK;
1975         u32 n_channels;
1976         u32 n_ssids;
1977         s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params));
1978         wl_escan_params_t *params = NULL;
1979         u8 chan_buf[sizeof(u32)*(WL_NUMCHANNELS + 1)];
1980         u32 num_chans = 0;
1981         s32 channel;
1982         s32 n_valid_chan;
1983         s32 search_state = WL_P2P_DISC_ST_SCAN;
1984         u32 i, j, n_nodfs = 0;
1985         u16 *default_chan_list = NULL;
1986         wl_uint32_list_t *list;
1987         struct net_device *dev = NULL;
1988 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
1989         bool is_first_init_2g_scan = false;
1990 #endif 
1991         p2p_scan_purpose_t      p2p_scan_purpose = P2P_SCAN_PURPOSE_MIN;
1992
1993         WL_DBG(("Enter \n"));
1994
1995         /* scan request can come with empty request : perform all default scan */
1996         if (!wl) {
1997                 err = -EINVAL;
1998                 goto exit;
1999         }
2000         if (!wl->p2p_supported || !p2p_scan(wl)) {
2001                 /* LEGACY SCAN TRIGGER */
2002                 WL_SCAN((" LEGACY E-SCAN START\n"));
2003
2004 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2005                 if (!request) {
2006                         err = -EINVAL;
2007                         goto exit;
2008                 }
2009                 if (ndev == wl_to_prmry_ndev(wl) && g_first_broadcast_scan == true) {
2010                         is_first_init_2g_scan = true;
2011                         g_first_broadcast_scan = false;
2012                 }
2013 #endif 
2014
2015                 /* if scan request is not empty parse scan request paramters */
2016                 if (request != NULL) {
2017                         n_channels = request->n_channels;
2018                         n_ssids = request->n_ssids;
2019                         /* Allocate space for populating ssids in wl_iscan_params struct */
2020                         if (n_channels % 2)
2021                                 /* If n_channels is odd, add a padd of u16 */
2022                                 params_size += sizeof(u16) * (n_channels + 1);
2023                         else
2024                                 params_size += sizeof(u16) * n_channels;
2025
2026                         /* Allocate space for populating ssids in wl_iscan_params struct */
2027                         params_size += sizeof(struct wlc_ssid) * n_ssids;
2028                 }
2029                 params = (wl_escan_params_t *) kzalloc(params_size, GFP_KERNEL);
2030                 if (params == NULL) {
2031                         err = -ENOMEM;
2032                         goto exit;
2033                 }
2034                 wl_scan_prep(&params->params, request);
2035
2036 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2037                 /* Override active_time to reduce scan time if it's first bradcast scan. */
2038                 if (is_first_init_2g_scan)
2039                         params->params.active_time = FIRST_SCAN_ACTIVE_DWELL_TIME_MS;
2040 #endif 
2041
2042                 params->version = htod32(ESCAN_REQ_VERSION);
2043                 params->action =  htod16(action);
2044                 wl_escan_set_sync_id(params->sync_id, wl);
2045                 if (params_size + sizeof("escan") >= WLC_IOCTL_MEDLEN) {
2046                         WL_ERR(("ioctl buffer length not sufficient\n"));
2047                         kfree(params);
2048                         err = -ENOMEM;
2049                         goto exit;
2050                 }
2051                 err = wldev_iovar_setbuf(ndev, "escan", params, params_size,
2052                         wl->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
2053                 if (unlikely(err)) {
2054                         if (err == BCME_EPERM)
2055                                 /* Scan Not permitted at this point of time */
2056                                 WL_DBG((" Escan not permitted at this time (%d)\n", err));
2057                         else
2058                                 WL_ERR((" Escan set error (%d)\n", err));
2059                 }
2060                 kfree(params);
2061         }
2062         else if (p2p_is_on(wl) && p2p_scan(wl)) {
2063                 /* P2P SCAN TRIGGER */
2064                 s32 _freq = 0;
2065                 n_nodfs = 0;
2066                 if (request && request->n_channels) {
2067                         num_chans = request->n_channels;
2068                         WL_SCAN((" chann number : %d\n", num_chans));
2069                         default_chan_list = kzalloc(num_chans * sizeof(*default_chan_list),
2070                                 GFP_KERNEL);
2071                         if (default_chan_list == NULL) {
2072                                 WL_ERR(("channel list allocation failed \n"));
2073                                 err = -ENOMEM;
2074                                 goto exit;
2075                         }
2076                         if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) {
2077                                 list = (wl_uint32_list_t *) chan_buf;
2078                                 n_valid_chan = dtoh32(list->count);
2079                                 for (i = 0; i < num_chans; i++)
2080                                 {
2081                                         _freq = request->channels[i]->center_freq;
2082                                         channel = ieee80211_frequency_to_channel(_freq);
2083
2084                                         /* ignore DFS channels */
2085                                         if (request->channels[i]->flags &
2086                                                 (IEEE80211_CHAN_RADAR
2087                                                 | IEEE80211_CHAN_PASSIVE_SCAN))
2088                                                 continue;
2089
2090                                         for (j = 0; j < n_valid_chan; j++) {
2091                                                 /* allows only supported channel on
2092                                                 *  current reguatory
2093                                                 */
2094                                                 if (channel == (dtoh32(list->element[j])))
2095                                                         default_chan_list[n_nodfs++] =
2096                                                                 channel;
2097                                         }
2098
2099                                 }
2100                         }
2101                         if (num_chans == SOCIAL_CHAN_CNT && (
2102                                                 (default_chan_list[0] == SOCIAL_CHAN_1) &&
2103                                                 (default_chan_list[1] == SOCIAL_CHAN_2) &&
2104                                                 (default_chan_list[2] == SOCIAL_CHAN_3))) {
2105                                 /* SOCIAL CHANNELS 1, 6, 11 */
2106                                 search_state = WL_P2P_DISC_ST_SEARCH;
2107                                 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2108                                 WL_INFO(("P2P SEARCH PHASE START \n"));
2109                         } else if ((dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION)) &&
2110                                 (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP)) {
2111                                 /* If you are already a GO, then do SEARCH only */
2112                                 WL_INFO(("Already a GO. Do SEARCH Only"));
2113                                 search_state = WL_P2P_DISC_ST_SEARCH;
2114                                 num_chans = n_nodfs;
2115                                 p2p_scan_purpose = P2P_SCAN_NORMAL;
2116
2117                         } else if (num_chans == 1) {
2118                                 p2p_scan_purpose = P2P_SCAN_CONNECT_TRY;
2119                         } else if (num_chans == SOCIAL_CHAN_CNT + 1) {
2120                         /* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by
2121                          * the supplicant
2122                          */
2123                                 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2124                         } else {
2125                                 WL_INFO(("P2P SCAN STATE START \n"));
2126                                 num_chans = n_nodfs;
2127                                 p2p_scan_purpose = P2P_SCAN_NORMAL;
2128                         }
2129                 } else {
2130                         err = -EINVAL;
2131                         goto exit;
2132                 }
2133                 err = wl_cfgp2p_escan(wl, ndev, wl->active_scan, num_chans, default_chan_list,
2134                         search_state, action,
2135                         wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE), NULL,
2136                         p2p_scan_purpose);
2137
2138                 if (!err)
2139                         wl->p2p->search_state = search_state;
2140
2141                 kfree(default_chan_list);
2142         }
2143 exit:
2144         if (unlikely(err)) {
2145                 /* Don't print Error incase of Scan suppress */
2146                 if ((err == BCME_EPERM) && wl->scan_suppressed)
2147                         WL_DBG(("Escan failed: Scan Suppressed \n"));
2148                 else
2149                         WL_ERR(("error (%d)\n", err));
2150         }
2151         return err;
2152 }
2153
2154
2155 static s32
2156 wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev,
2157         struct cfg80211_scan_request *request)
2158 {
2159         s32 err = BCME_OK;
2160         s32 passive_scan;
2161         wl_scan_results_t *results;
2162         WL_SCAN(("Enter \n"));
2163         mutex_lock(&wl->usr_sync);
2164
2165         results = wl_escan_get_buf(wl, FALSE);
2166         results->version = 0;
2167         results->count = 0;
2168         results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
2169
2170         wl->escan_info.ndev = ndev;
2171         wl->escan_info.wiphy = wiphy;
2172         wl->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
2173         passive_scan = wl->active_scan ? 0 : 1;
2174         err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
2175                 &passive_scan, sizeof(passive_scan), true);
2176         if (unlikely(err)) {
2177                 WL_ERR(("error (%d)\n", err));
2178                 goto exit;
2179         }
2180
2181         err = wl_run_escan(wl, ndev, request, WL_SCAN_ACTION_START);
2182 exit:
2183         mutex_unlock(&wl->usr_sync);
2184         return err;
2185 }
2186
2187 static s32
2188 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
2189         struct cfg80211_scan_request *request,
2190         struct cfg80211_ssid *this_ssid)
2191 {
2192         struct wl_priv *wl = wiphy_priv(wiphy);
2193         struct cfg80211_ssid *ssids;
2194         struct wl_scan_req *sr = wl_to_sr(wl);
2195         struct ether_addr primary_mac;
2196         s32 passive_scan;
2197         bool iscan_req;
2198         bool escan_req = false;
2199         bool p2p_ssid;
2200         s32 err = 0;
2201         s32 bssidx = -1;
2202         s32 i;
2203
2204         unsigned long flags;
2205         static s32 busy_count = 0;
2206
2207         dhd_pub_t *dhd;
2208
2209         dhd = (dhd_pub_t *)(wl->pub);
2210         if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
2211                 WL_ERR(("Invalid Scan Command at SoftAP mode\n"));
2212                 return -EINVAL;
2213         }
2214
2215         ndev = ndev_to_wlc_ndev(ndev, wl);
2216
2217         if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(wl)) {
2218                 WL_ERR(("Sending Action Frames. Try it again.\n"));
2219                 return -EAGAIN;
2220         }
2221
2222         WL_DBG(("Enter wiphy (%p)\n", wiphy));
2223         if (wl_get_drv_status_all(wl, SCANNING)) {
2224                 if (wl->scan_request == NULL) {
2225                         wl_clr_drv_status_all(wl, SCANNING);
2226                         WL_DBG(("<<<<<<<<<<<Force Clear Scanning Status>>>>>>>>>>>\n"));
2227                 } else {
2228                         WL_ERR(("Scanning already\n"));
2229                         return -EAGAIN;
2230                 }
2231         }
2232         if (wl_get_drv_status(wl, SCAN_ABORTING, ndev)) {
2233                 WL_ERR(("Scanning being aborted\n"));
2234                 return -EAGAIN;
2235         }
2236         if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) {
2237                 WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n"));
2238                 return -EOPNOTSUPP;
2239         }
2240 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
2241         if (wl_get_drv_status_all(wl, REMAINING_ON_CHANNEL)) {
2242                 WL_DBG(("Remain_on_channel bit is set, somehow it didn't get cleared\n"));
2243                 wl_notify_escan_complete(wl, ndev, true, true);
2244         }
2245 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
2246
2247
2248         /* Arm scan timeout timer */
2249         mod_timer(&wl->scan_timeout, jiffies + msecs_to_jiffies(WL_SCAN_TIMER_INTERVAL_MS));
2250         iscan_req = false;
2251         if (request) {          /* scan bss */
2252                 ssids = request->ssids;
2253                 if (wl->iscan_on && (!ssids || !ssids->ssid_len || request->n_ssids != 1)) {
2254                         iscan_req = true;
2255                 } else if (wl->escan_on) {
2256                         escan_req = true;
2257                         p2p_ssid = false;
2258                         for (i = 0; i < request->n_ssids; i++) {
2259                                 if (ssids[i].ssid_len &&
2260                                         IS_P2P_SSID(ssids[i].ssid, ssids[i].ssid_len)) {
2261                                         p2p_ssid = true;
2262                                         break;
2263                                 }
2264                         }
2265                         if (p2p_ssid) {
2266                                 if (wl->p2p_supported) {
2267                                         /* p2p scan trigger */
2268                                         if (p2p_on(wl) == false) {
2269                                                 /* p2p on at the first time */
2270                                                 p2p_on(wl) = true;
2271                                                 wl_cfgp2p_set_firm_p2p(wl);
2272                                                 get_primary_mac(wl, &primary_mac);
2273                                                 wl_cfgp2p_generate_bss_mac(&primary_mac,
2274                                                         &wl->p2p->dev_addr, &wl->p2p->int_addr);
2275                                         }
2276                                         wl_clr_p2p_status(wl, GO_NEG_PHASE);
2277                                         WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
2278                                         p2p_scan(wl) = true;
2279                                 }
2280                         } else {
2281                                 /* legacy scan trigger
2282                                  * So, we have to disable p2p discovery if p2p discovery is on
2283                                  */
2284                                 if (wl->p2p_supported) {
2285                                         p2p_scan(wl) = false;
2286                                         /* If Netdevice is not equals to primary and p2p is on
2287                                         *  , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
2288                                         */
2289
2290                                         if (p2p_scan(wl) == false) {
2291                                                 if (wl_get_p2p_status(wl, DISCOVERY_ON)) {
2292                                                         err = wl_cfgp2p_discover_enable_search(wl,
2293                                                         false);
2294                                                         if (unlikely(err)) {
2295                                                                 goto scan_out;
2296                                                         }
2297
2298                                                 }
2299                                         }
2300                                 }
2301                                 if (!wl->p2p_supported || !p2p_scan(wl)) {
2302
2303                                         if (wl_cfgp2p_find_idx(wl, ndev, &bssidx) != BCME_OK) {
2304                                                 WL_ERR(("Find p2p index from ndev(%p) failed\n",
2305                                                         ndev));
2306                                                 err = BCME_ERROR;
2307                                                 goto scan_out;
2308                                         }
2309                                         err = wl_cfgp2p_set_management_ie(wl, ndev, bssidx,
2310                                                 VNDR_IE_PRBREQ_FLAG, (u8 *)request->ie,
2311                                                 request->ie_len);
2312
2313                                         if (unlikely(err)) {
2314                                                 goto scan_out;
2315                                         }
2316
2317                                 }
2318                         }
2319                 }
2320         } else {                /* scan in ibss */
2321                 /* we don't do iscan in ibss */
2322                 ssids = this_ssid;
2323         }
2324         if (request && !p2p_scan(wl))
2325                 WL_TRACE_HW4(("START SCAN\n"));
2326         wl->scan_request = request;
2327         wl_set_drv_status(wl, SCANNING, ndev);
2328         if (iscan_req) {
2329                 err = wl_do_iscan(wl, request);
2330                 if (likely(!err))
2331                         goto scan_success;
2332                 else
2333                         goto scan_out;
2334         } else if (escan_req) {
2335                 if (wl->p2p_supported) {
2336                         if (p2p_on(wl) && p2p_scan(wl)) {
2337
2338                                 /* find my listen channel */
2339                                 wl->afx_hdl->my_listen_chan =
2340                                         wl_find_listen_channel(wl, request->ie,
2341                                         request->ie_len);
2342                                 err = wl_cfgp2p_enable_discovery(wl, ndev,
2343                                 request->ie, request->ie_len);
2344
2345                                 if (unlikely(err)) {
2346                                         goto scan_out;
2347                                 }
2348                         }
2349                 }
2350                 err = wl_do_escan(wl, wiphy, ndev, request);
2351                 if (likely(!err))
2352                         goto scan_success;
2353                 else
2354                         goto scan_out;
2355
2356
2357         } else {
2358                 memset(&sr->ssid, 0, sizeof(sr->ssid));
2359                 sr->ssid.SSID_len =
2360                         min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len);
2361                 if (sr->ssid.SSID_len) {
2362                         memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len);
2363                         sr->ssid.SSID_len = htod32(sr->ssid.SSID_len);
2364                         WL_SCAN(("Specific scan ssid=\"%s\" len=%d\n",
2365                                 sr->ssid.SSID, sr->ssid.SSID_len));
2366                 } else {
2367                         WL_SCAN(("Broadcast scan\n"));
2368                 }
2369                 WL_SCAN(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len));
2370                 passive_scan = wl->active_scan ? 0 : 1;
2371                 err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
2372                         &passive_scan, sizeof(passive_scan), true);
2373                 if (unlikely(err)) {
2374                         WL_SCAN(("WLC_SET_PASSIVE_SCAN error (%d)\n", err));
2375                         goto scan_out;
2376                 }
2377                 err = wldev_ioctl(ndev, WLC_SCAN, &sr->ssid,
2378                         sizeof(sr->ssid), false);
2379                 if (err) {
2380                         if (err == -EBUSY) {
2381                                 WL_ERR(("system busy : scan for \"%s\" "
2382                                         "canceled\n", sr->ssid.SSID));
2383                         } else {
2384                                 WL_ERR(("WLC_SCAN error (%d)\n", err));
2385                         }
2386                         goto scan_out;
2387                 }
2388         }
2389
2390 scan_success:
2391         busy_count = 0;
2392
2393         return 0;
2394
2395 scan_out:
2396         if (err == BCME_BUSY || err == BCME_NOTREADY) {
2397                 WL_ERR(("Scan err = (%d), busy?%d", err, -EBUSY));
2398                 err = -EBUSY;
2399         }
2400
2401 #define SCAN_EBUSY_RETRY_LIMIT 10
2402         if (err == -EBUSY) {
2403                 if (busy_count++ > SCAN_EBUSY_RETRY_LIMIT) {
2404                         struct ether_addr bssid;
2405                         s32 ret = 0;
2406                         busy_count = 0;
2407                         WL_ERR(("Unusual continuous EBUSY error, %d %d %d %d %d %d %d %d %d\n",
2408                                 wl_get_drv_status(wl, SCANNING, ndev),
2409                                 wl_get_drv_status(wl, SCAN_ABORTING, ndev),
2410                                 wl_get_drv_status(wl, CONNECTING, ndev),
2411                                 wl_get_drv_status(wl, CONNECTED, ndev),
2412                                 wl_get_drv_status(wl, DISCONNECTING, ndev),
2413                                 wl_get_drv_status(wl, AP_CREATING, ndev),
2414                                 wl_get_drv_status(wl, AP_CREATED, ndev),
2415                                 wl_get_drv_status(wl, SENDING_ACT_FRM, ndev),
2416                                 wl_get_drv_status(wl, SENDING_ACT_FRM, ndev)));
2417
2418                         bzero(&bssid, sizeof(bssid));
2419                         if ((ret = wldev_ioctl(ndev, WLC_GET_BSSID,
2420                                 &bssid, ETHER_ADDR_LEN, false)) == 0)
2421                                 WL_ERR(("FW is connected with " MACDBG "/n",
2422                                         MAC2STRDBG(bssid.octet)));
2423                         else
2424                                 WL_ERR(("GET BSSID failed with %d\n", ret));
2425
2426                         wl_cfg80211_scan_abort(wl);
2427                 }
2428         } else {
2429                 busy_count = 0;
2430         }
2431
2432         wl_clr_drv_status(wl, SCANNING, ndev);
2433         if (timer_pending(&wl->scan_timeout))
2434                 del_timer_sync(&wl->scan_timeout);
2435         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
2436         wl->scan_request = NULL;
2437         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
2438
2439         return err;
2440 }
2441
2442 #if defined(WL_CFG80211_P2P_DEV_IF)
2443 static s32
2444 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
2445 #else
2446 static s32
2447 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
2448         struct cfg80211_scan_request *request)
2449 #endif /* WL_CFG80211_P2P_DEV_IF */
2450 {
2451         s32 err = 0;
2452         struct wl_priv *wl = wiphy_priv(wiphy);
2453 #if defined(WL_CFG80211_P2P_DEV_IF)
2454         struct net_device *ndev = wdev_to_wlc_ndev(request->wdev, wl);
2455 #endif /* WL_CFG80211_P2P_DEV_IF */
2456
2457         WL_DBG(("Enter \n"));
2458         RETURN_EIO_IF_NOT_UP(wl);
2459
2460         err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
2461         if (unlikely(err)) {
2462                 if ((err == BCME_EPERM) && wl->scan_suppressed)
2463                         WL_DBG(("scan not permitted at this time (%d)\n", err));
2464                 else
2465                         WL_ERR(("scan error (%d)\n", err));
2466                 return err;
2467         }
2468
2469         return err;
2470 }
2471
2472 static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
2473 {
2474         s32 err = 0;
2475
2476         err = wldev_iovar_setint(dev, "rtsthresh", rts_threshold);
2477         if (unlikely(err)) {
2478                 WL_ERR(("Error (%d)\n", err));
2479                 return err;
2480         }
2481         return err;
2482 }
2483
2484 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
2485 {
2486         s32 err = 0;
2487
2488         err = wldev_iovar_setint_bsscfg(dev, "fragthresh", frag_threshold, 0);
2489         if (unlikely(err)) {
2490                 WL_ERR(("Error (%d)\n", err));
2491                 return err;
2492         }
2493         return err;
2494 }
2495
2496 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
2497 {
2498         s32 err = 0;
2499         u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
2500
2501         retry = htod32(retry);
2502         err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), true);
2503         if (unlikely(err)) {
2504                 WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
2505                 return err;
2506         }
2507         return err;
2508 }
2509
2510 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
2511 {
2512         struct wl_priv *wl = (struct wl_priv *)wiphy_priv(wiphy);
2513         struct net_device *ndev = wl_to_prmry_ndev(wl);
2514         s32 err = 0;
2515
2516         RETURN_EIO_IF_NOT_UP(wl);
2517         WL_DBG(("Enter\n"));
2518         if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
2519                 (wl->conf->rts_threshold != wiphy->rts_threshold)) {
2520                 wl->conf->rts_threshold = wiphy->rts_threshold;
2521                 err = wl_set_rts(ndev, wl->conf->rts_threshold);
2522                 if (!err)
2523                         return err;
2524         }
2525         if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
2526                 (wl->conf->frag_threshold != wiphy->frag_threshold)) {
2527                 wl->conf->frag_threshold = wiphy->frag_threshold;
2528                 err = wl_set_frag(ndev, wl->conf->frag_threshold);
2529                 if (!err)
2530                         return err;
2531         }
2532         if (changed & WIPHY_PARAM_RETRY_LONG &&
2533                 (wl->conf->retry_long != wiphy->retry_long)) {
2534                 wl->conf->retry_long = wiphy->retry_long;
2535                 err = wl_set_retry(ndev, wl->conf->retry_long, true);
2536                 if (!err)
2537                         return err;
2538         }
2539         if (changed & WIPHY_PARAM_RETRY_SHORT &&
2540                 (wl->conf->retry_short != wiphy->retry_short)) {
2541                 wl->conf->retry_short = wiphy->retry_short;
2542                 err = wl_set_retry(ndev, wl->conf->retry_short, false);
2543                 if (!err) {
2544                         return err;
2545                 }
2546         }
2547
2548         return err;
2549 }
2550 static chanspec_t
2551 channel_to_chanspec(struct wiphy *wiphy, struct net_device *dev, u32 channel, u32 bw_cap)
2552 {
2553         struct wl_priv *wl = wiphy_priv(wiphy);
2554         u8 *buf = NULL;
2555         wl_uint32_list_t *list;
2556         int err = BCME_OK;
2557         chanspec_t c = 0, ret_c = 0;
2558         int bw = 0, tmp_bw = 0;
2559         int i;
2560         u32 tmp_c, sb;
2561         u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
2562 #define LOCAL_BUF_SIZE  1024
2563         buf = (u8 *) kzalloc(LOCAL_BUF_SIZE, kflags);
2564         if (!buf) {
2565                 WL_ERR(("buf memory alloc failed\n"));
2566                 goto exit;
2567         }
2568         list = (wl_uint32_list_t *)(void *)buf;
2569         list->count = htod32(WL_NUMCHANSPECS);
2570         err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
2571                 0, buf, LOCAL_BUF_SIZE, 0, &wl->ioctl_buf_sync);
2572         if (err != BCME_OK) {
2573                 WL_ERR(("get chanspecs failed with %d\n", err));
2574                 goto exit;
2575         }
2576         for (i = 0; i < dtoh32(list->count); i++) {
2577                 c = dtoh32(list->element[i]);
2578                 if (channel <= CH_MAX_2G_CHANNEL) {
2579                         if (!CHSPEC_IS20(c))
2580                                 continue;
2581                         if (channel == CHSPEC_CHANNEL(c)) {
2582                                 ret_c = c;
2583                                 bw = 20;
2584                                 goto exit;
2585                         }
2586                 }
2587                 if (CHSPEC_IS20(c)) {
2588                         tmp_c = CHSPEC_CHANNEL(c);
2589                         tmp_bw = WLC_BW_CAP_20MHZ;
2590                 }
2591                 else if (CHSPEC_IS40(c)) {
2592                         tmp_c = CHSPEC_CHANNEL(c);
2593                         if (CHSPEC_SB_UPPER(c)) {
2594                                 tmp_c += CH_10MHZ_APART;
2595                         } else {
2596                                 tmp_c -= CH_10MHZ_APART;
2597                         }
2598                         tmp_bw = WLC_BW_CAP_40MHZ;
2599                 }
2600                 else {
2601                         tmp_c = CHSPEC_CHANNEL(c);
2602                         sb = c & WL_CHANSPEC_CTL_SB_MASK;
2603                         if (sb == WL_CHANSPEC_CTL_SB_LL) {
2604                                 tmp_c -= (CH_10MHZ_APART + CH_20MHZ_APART);
2605                         } else if (sb == WL_CHANSPEC_CTL_SB_LU) {
2606                                 tmp_c -= CH_10MHZ_APART;
2607                         } else if (sb == WL_CHANSPEC_CTL_SB_UL) {
2608                                 tmp_c += CH_10MHZ_APART;
2609                         } else {
2610                                 /* WL_CHANSPEC_CTL_SB_UU */
2611                                 tmp_c += (CH_10MHZ_APART + CH_20MHZ_APART);
2612                         }
2613                         tmp_bw = WLC_BW_CAP_80MHZ;
2614                 }
2615                 if (tmp_c != channel)
2616                         continue;
2617
2618                 if ((tmp_bw > bw) && (tmp_bw <= bw_cap)) {
2619                         bw = tmp_bw;
2620                         ret_c = c;
2621                         if (bw == bw_cap)
2622                                 goto exit;
2623                 }
2624         }
2625 exit:
2626         if (buf)
2627                 kfree(buf);
2628 #undef LOCAL_BUF_SIZE
2629         WL_INFO(("return chanspec %x %d\n", ret_c, bw));
2630         return ret_c;
2631 }
2632
2633 void
2634 wl_cfg80211_ibss_vsie_set_buffer(vndr_ie_setbuf_t *ibss_vsie, int ibss_vsie_len)
2635 {
2636         struct wl_priv *wl = wlcfg_drv_priv;
2637
2638         if (wl != NULL && ibss_vsie != NULL) {
2639                 if (wl->ibss_vsie != NULL) {
2640                         kfree(wl->ibss_vsie);
2641                 }
2642                 wl->ibss_vsie = ibss_vsie;
2643                 wl->ibss_vsie_len = ibss_vsie_len;
2644         }
2645 }
2646
2647 static void
2648 wl_cfg80211_ibss_vsie_free(struct wl_priv *wl)
2649 {
2650         /* free & initiralize VSIE (Vendor Specific IE) */
2651         if (wl->ibss_vsie != NULL) {
2652                 kfree(wl->ibss_vsie);
2653                 wl->ibss_vsie = NULL;
2654                 wl->ibss_vsie_len = 0;
2655         }
2656 }
2657
2658 s32
2659 wl_cfg80211_ibss_vsie_delete(struct net_device *dev)
2660 {
2661         struct wl_priv *wl = wlcfg_drv_priv;
2662         char *ioctl_buf = NULL;
2663         s32 ret = BCME_OK;
2664
2665         if (wl != NULL && wl->ibss_vsie != NULL) {
2666                 ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
2667                 if (!ioctl_buf) {
2668                         WL_ERR(("ioctl memory alloc failed\n"));
2669                         return -ENOMEM;
2670                 }
2671
2672                 /* change the command from "add" to "del" */
2673                 strncpy(wl->ibss_vsie->cmd, "del", VNDR_IE_CMD_LEN - 1);
2674                 wl->ibss_vsie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
2675
2676                 ret = wldev_iovar_setbuf(dev, "ie",
2677                         wl->ibss_vsie, wl->ibss_vsie_len,
2678                         ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
2679                 WL_ERR(("ret=%d\n", ret));
2680
2681                 if (ret == BCME_OK) {
2682                         /* free & initiralize VSIE */
2683                         kfree(wl->ibss_vsie);
2684                         wl->ibss_vsie = NULL;
2685                         wl->ibss_vsie_len = 0;
2686                 }
2687
2688                 if (ioctl_buf) {
2689                         kfree(ioctl_buf);
2690                 }
2691         }
2692
2693         return ret;
2694 }
2695
2696 static s32
2697 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
2698         struct cfg80211_ibss_params *params)
2699 {
2700         struct wl_priv *wl = wiphy_priv(wiphy);
2701         struct cfg80211_bss *bss;
2702         struct ieee80211_channel *chan;
2703         struct wl_join_params join_params;
2704         struct cfg80211_ssid ssid;
2705         s32 scan_retry = 0;
2706         s32 err = 0;
2707         int scan_suppress = 1;
2708         size_t join_params_size;
2709         chanspec_t chanspec = 0;
2710         u32 param[2] = {0, 0};
2711         u32 bw_cap = 0;
2712
2713         WL_TRACE(("In\n"));
2714         RETURN_EIO_IF_NOT_UP(wl);
2715         WL_INFO(("JOIN BSSID:" MACDBG "\n", MAC2STRDBG(params->bssid)));
2716         if (!params->ssid || params->ssid_len <= 0) {
2717                 WL_ERR(("Invalid parameter\n"));
2718                 return -EINVAL;
2719         }
2720
2721 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
2722         chan = params->chandef.chan;
2723 #else
2724         chan = params->channel;
2725 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) */
2726         if (chan)
2727                 wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
2728         if (wl_get_drv_status(wl, CONNECTED, dev)) {
2729                 struct wlc_ssid *ssid = (struct wlc_ssid *)wl_read_prof(wl, dev, WL_PROF_SSID);
2730                 u8 *bssid = (u8 *)wl_read_prof(wl, dev, WL_PROF_BSSID);
2731                 u32 *channel = (u32 *)wl_read_prof(wl, dev, WL_PROF_CHAN);
2732                 if (!params->bssid || ((memcmp(params->bssid, bssid, ETHER_ADDR_LEN) == 0) &&
2733                         (memcmp(params->ssid, ssid->SSID, ssid->SSID_len) == 0) &&
2734                         (*channel == wl->channel))) {
2735                         WL_ERR(("Connection already existed to " MACDBG "\n",
2736                                 MAC2STRDBG((u8 *)wl_read_prof(wl, dev, WL_PROF_BSSID))));
2737                         return -EISCONN;
2738                 }
2739                 WL_ERR(("Ignore Previous connecton to %s (" MACDBG ")\n",
2740                         ssid->SSID, MAC2STRDBG(bssid)));
2741         }
2742
2743         /* remove the VSIE */
2744         wl_cfg80211_ibss_vsie_delete(dev);
2745
2746         bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
2747         if (!bss) {
2748                 if (IBSS_INITIAL_SCAN_ALLOWED == TRUE) {
2749                         memcpy(ssid.ssid, params->ssid, params->ssid_len);
2750                         ssid.ssid_len = params->ssid_len;
2751                         do {
2752                                 if (unlikely
2753                                         (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
2754                                          -EBUSY)) {
2755                                         wl_delay(150);
2756                                 } else {
2757                                         break;
2758                                 }
2759                         } while (++scan_retry < WL_SCAN_RETRY_MAX);
2760
2761                         /* wait 4 secons till scan done.... */
2762                         schedule_timeout_interruptible(msecs_to_jiffies(4000));
2763                         bss = cfg80211_get_ibss(wiphy, NULL,
2764                                 params->ssid, params->ssid_len);
2765                 }
2766         }
2767         if (bss && ((IBSS_COALESCE_ALLOWED == TRUE) ||
2768                 ((IBSS_COALESCE_ALLOWED == FALSE) && params->bssid &&
2769                 !memcmp(bss->bssid, params->bssid, ETHER_ADDR_LEN)))) {
2770                 wl->ibss_starter = false;
2771                 WL_DBG(("Found IBSS\n"));
2772         } else {
2773                 wl->ibss_starter = true;
2774         }
2775         if (chan) {
2776                 if (chan->band == IEEE80211_BAND_5GHZ)
2777                         param[0] = WLC_BAND_5G;
2778                 else if (chan->band == IEEE80211_BAND_2GHZ)
2779                         param[0] = WLC_BAND_2G;
2780                 err = wldev_iovar_getint(dev, "bw_cap", param);
2781                 if (unlikely(err)) {
2782                         WL_ERR(("Get bw_cap Failed (%d)\n", err));
2783                         return err;
2784                 }
2785                 bw_cap = param[0];
2786                 chanspec = channel_to_chanspec(wiphy, dev, wl->channel, bw_cap);
2787         }
2788         /*
2789          * Join with specific BSSID and cached SSID
2790          * If SSID is zero join based on BSSID only
2791          */
2792         memset(&join_params, 0, sizeof(join_params));
2793         memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
2794                 params->ssid_len);
2795         join_params.ssid.SSID_len = htod32(params->ssid_len);
2796         if (params->bssid) {
2797                 memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
2798                 err = wldev_ioctl(dev, WLC_SET_DESIRED_BSSID, &join_params.params.bssid,
2799                         ETHER_ADDR_LEN, true);
2800                 if (unlikely(err)) {
2801                         WL_ERR(("Error (%d)\n", err));
2802                         return err;
2803                 }
2804         } else
2805                 memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
2806
2807         wldev_iovar_setint(dev, "ibss_coalesce_allowed", IBSS_COALESCE_ALLOWED);
2808
2809         if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
2810                 scan_suppress = TRUE;
2811                 /* Set the SCAN SUPRESS Flag in the firmware to skip join scan */
2812                 err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS, &scan_suppress, sizeof(int), true);
2813                 if (unlikely(err)) {
2814                         WL_ERR(("Scan Supress Setting failed(%d)\n", err));
2815                         return err;
2816                 }
2817         }
2818
2819         join_params.params.chanspec_list[0] = chanspec;
2820         join_params.params.chanspec_num = 1;
2821         wldev_iovar_setint(dev, "chanspec", chanspec);
2822         join_params_size = sizeof(join_params);
2823
2824         /* Disable Authentication, IBSS will add key if it required */
2825         wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
2826         wldev_iovar_setint(dev, "wsec", 0);
2827
2828         err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
2829                 join_params_size, true);
2830         if (unlikely(err)) {
2831                 WL_ERR(("Error (%d)\n", err));
2832                 return err;
2833         }
2834
2835         if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
2836                 scan_suppress = FALSE;
2837                 /* Restore the SCAN SUPPRESS Falg */
2838                 err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS,
2839                         &scan_suppress, sizeof(int), true);
2840                 if (unlikely(err)) {
2841                         WL_ERR(("Reset SCAN Suppress Flag failed (%d)\n", err));
2842                 return err;
2843                 }
2844         }
2845         wl_update_prof(wl, dev, NULL, &join_params.ssid, WL_PROF_SSID);
2846         wl_update_prof(wl, dev, NULL, &wl->channel, WL_PROF_CHAN);
2847         return err;
2848 }
2849
2850 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
2851 {
2852         struct wl_priv *wl = wiphy_priv(wiphy);
2853         s32 err = 0;
2854         scb_val_t scbval;
2855         u8 *curbssid;
2856
2857         RETURN_EIO_IF_NOT_UP(wl);
2858         wl_link_down(wl);
2859         WL_ERR(("Leave IBSS\n"));
2860         curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID);
2861         wl_set_drv_status(wl, DISCONNECTING, dev);
2862         scbval.val = 0;
2863         memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
2864         err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
2865                 sizeof(scb_val_t), true);
2866         if (unlikely(err)) {
2867                 wl_clr_drv_status(wl, DISCONNECTING, dev);
2868                 WL_ERR(("error(%d)\n", err));
2869                 return err;
2870         }
2871
2872         /* remove the VSIE */
2873         wl_cfg80211_ibss_vsie_delete(dev);
2874
2875         return err;
2876 }
2877
2878
2879 static s32
2880 wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
2881 {
2882         struct wl_priv *wl = wlcfg_drv_priv;
2883         struct wl_security *sec;
2884         s32 val = 0;
2885         s32 err = 0;
2886         s32 bssidx;
2887         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
2888                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
2889                 return BCME_ERROR;
2890         }
2891
2892         if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
2893                 val = WPA_AUTH_PSK |
2894                         WPA_AUTH_UNSPECIFIED;
2895         else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
2896                 val = WPA2_AUTH_PSK|
2897                         WPA2_AUTH_UNSPECIFIED;
2898         else
2899                 val = WPA_AUTH_DISABLED;
2900
2901         if (is_wps_conn(sme))
2902                 val = WPA_AUTH_DISABLED;
2903
2904         WL_DBG(("setting wpa_auth to 0x%0x\n", val));
2905         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
2906         if (unlikely(err)) {
2907                 WL_ERR(("set wpa_auth failed (%d)\n", err));
2908                 return err;
2909         }
2910         sec = wl_read_prof(wl, dev, WL_PROF_SEC);
2911         sec->wpa_versions = sme->crypto.wpa_versions;
2912         return err;
2913 }
2914
2915
2916 static s32
2917 wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
2918 {
2919         struct wl_priv *wl = wlcfg_drv_priv;
2920         struct wl_security *sec;
2921         s32 val = 0;
2922         s32 err = 0;
2923         s32 bssidx;
2924         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
2925                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
2926                 return BCME_ERROR;
2927         }
2928
2929         switch (sme->auth_type) {
2930         case NL80211_AUTHTYPE_OPEN_SYSTEM:
2931                 val = WL_AUTH_OPEN_SYSTEM;
2932                 WL_DBG(("open system\n"));
2933                 break;
2934         case NL80211_AUTHTYPE_SHARED_KEY:
2935                 val = WL_AUTH_SHARED_KEY;
2936                 WL_DBG(("shared key\n"));
2937                 break;
2938         case NL80211_AUTHTYPE_AUTOMATIC:
2939                 val = WL_AUTH_OPEN_SHARED;
2940                 WL_DBG(("automatic\n"));
2941                 break;
2942         default:
2943                 val = 2;
2944                 WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
2945                 break;
2946         }
2947
2948         err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
2949         if (unlikely(err)) {
2950                 WL_ERR(("set auth failed (%d)\n", err));
2951                 return err;
2952         }
2953         sec = wl_read_prof(wl, dev, WL_PROF_SEC);
2954         sec->auth_type = sme->auth_type;
2955         return err;
2956 }
2957
2958 static s32
2959 wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
2960 {
2961         struct wl_priv *wl = wlcfg_drv_priv;
2962         struct wl_security *sec;
2963         s32 pval = 0;
2964         s32 gval = 0;
2965         s32 err = 0;
2966         s32 wsec_val = 0;
2967
2968         s32 bssidx;
2969         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
2970                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
2971                 return BCME_ERROR;
2972         }
2973
2974         if (sme->crypto.n_ciphers_pairwise) {
2975                 switch (sme->crypto.ciphers_pairwise[0]) {
2976                 case WLAN_CIPHER_SUITE_WEP40:
2977                 case WLAN_CIPHER_SUITE_WEP104:
2978                         pval = WEP_ENABLED;
2979                         break;
2980                 case WLAN_CIPHER_SUITE_TKIP:
2981                         pval = TKIP_ENABLED;
2982                         break;
2983                 case WLAN_CIPHER_SUITE_CCMP:
2984                 case WLAN_CIPHER_SUITE_AES_CMAC:
2985                         pval = AES_ENABLED;
2986                         break;
2987                 default:
2988                         WL_ERR(("invalid cipher pairwise (%d)\n",
2989                                 sme->crypto.ciphers_pairwise[0]));
2990                         return -EINVAL;
2991                 }
2992         }
2993         if (sme->crypto.cipher_group) {
2994                 switch (sme->crypto.cipher_group) {
2995                 case WLAN_CIPHER_SUITE_WEP40:
2996                 case WLAN_CIPHER_SUITE_WEP104:
2997                         gval = WEP_ENABLED;
2998                         break;
2999                 case WLAN_CIPHER_SUITE_TKIP:
3000                         gval = TKIP_ENABLED;
3001                         break;
3002                 case WLAN_CIPHER_SUITE_CCMP:
3003                         gval = AES_ENABLED;
3004                         break;
3005                 case WLAN_CIPHER_SUITE_AES_CMAC:
3006                         gval = AES_ENABLED;
3007                         break;
3008                 default:
3009                         WL_ERR(("invalid cipher group (%d)\n",
3010                                 sme->crypto.cipher_group));
3011                         return -EINVAL;
3012                 }
3013         }
3014
3015         WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
3016
3017         if (is_wps_conn(sme)) {
3018                 if (sme->privacy)
3019                         err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
3020                 else
3021                         /* WPS-2.0 allows no security */
3022                         err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
3023         } else {
3024                         WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC"));
3025                         wsec_val = pval | gval;
3026
3027                         WL_DBG((" Set WSEC to fW 0x%x \n", wsec_val));
3028                         err = wldev_iovar_setint_bsscfg(dev, "wsec",
3029                                 wsec_val, bssidx);
3030         }
3031         if (unlikely(err)) {
3032                 WL_ERR(("error (%d)\n", err));
3033                 return err;
3034         }
3035
3036         sec = wl_read_prof(wl, dev, WL_PROF_SEC);
3037         sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
3038         sec->cipher_group = sme->crypto.cipher_group;
3039
3040         return err;
3041 }
3042
3043 static s32
3044 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
3045 {
3046         struct wl_priv *wl = wlcfg_drv_priv;
3047         struct wl_security *sec;
3048         s32 val = 0;
3049         s32 err = 0;
3050         s32 bssidx;
3051         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3052                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3053                 return BCME_ERROR;
3054         }
3055
3056         if (sme->crypto.n_akm_suites) {
3057                 err = wldev_iovar_getint(dev, "wpa_auth", &val);
3058                 if (unlikely(err)) {
3059                         WL_ERR(("could not get wpa_auth (%d)\n", err));
3060                         return err;
3061                 }
3062                 if (val & (WPA_AUTH_PSK |
3063                         WPA_AUTH_UNSPECIFIED)) {
3064                         switch (sme->crypto.akm_suites[0]) {
3065                         case WLAN_AKM_SUITE_8021X:
3066                                 val = WPA_AUTH_UNSPECIFIED;
3067                                 break;
3068                         case WLAN_AKM_SUITE_PSK:
3069                                 val = WPA_AUTH_PSK;
3070                                 break;
3071                         default:
3072                                 WL_ERR(("invalid cipher group (%d)\n",
3073                                         sme->crypto.cipher_group));
3074                                 return -EINVAL;
3075                         }
3076                 } else if (val & (WPA2_AUTH_PSK |
3077                         WPA2_AUTH_UNSPECIFIED)) {
3078                         switch (sme->crypto.akm_suites[0]) {
3079                         case WLAN_AKM_SUITE_8021X:
3080                                 val = WPA2_AUTH_UNSPECIFIED;
3081                                 break;
3082                         case WLAN_AKM_SUITE_PSK:
3083                                 val = WPA2_AUTH_PSK;
3084                                 break;
3085                         default:
3086                                 WL_ERR(("invalid cipher group (%d)\n",
3087                                         sme->crypto.cipher_group));
3088                                 return -EINVAL;
3089                         }
3090                 }
3091                 WL_DBG(("setting wpa_auth to %d\n", val));
3092
3093
3094                 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
3095                 if (unlikely(err)) {
3096                         WL_ERR(("could not set wpa_auth (%d)\n", err));
3097                         return err;
3098                 }
3099         }
3100         sec = wl_read_prof(wl, dev, WL_PROF_SEC);
3101         sec->wpa_auth = sme->crypto.akm_suites[0];
3102
3103         return err;
3104 }
3105
3106 static s32
3107 wl_set_set_sharedkey(struct net_device *dev,
3108         struct cfg80211_connect_params *sme)
3109 {
3110         struct wl_priv *wl = wlcfg_drv_priv;
3111         struct wl_security *sec;
3112         struct wl_wsec_key key;
3113         s32 val;
3114         s32 err = 0;
3115         s32 bssidx;
3116         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3117                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3118                 return BCME_ERROR;
3119         }
3120
3121         WL_DBG(("key len (%d)\n", sme->key_len));
3122         if (sme->key_len) {
3123                 sec = wl_read_prof(wl, dev, WL_PROF_SEC);
3124                 WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
3125                         sec->wpa_versions, sec->cipher_pairwise));
3126                 if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 |
3127                         NL80211_WPA_VERSION_2)) &&
3128                         (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
3129                 WLAN_CIPHER_SUITE_WEP104)))
3130                 {
3131                         memset(&key, 0, sizeof(key));
3132                         key.len = (u32) sme->key_len;
3133                         key.index = (u32) sme->key_idx;
3134                         if (unlikely(key.len > sizeof(key.data))) {
3135                                 WL_ERR(("Too long key length (%u)\n", key.len));
3136                                 return -EINVAL;
3137                         }
3138                         memcpy(key.data, sme->key, key.len);
3139                         key.flags = WL_PRIMARY_KEY;
3140                         switch (sec->cipher_pairwise) {
3141                         case WLAN_CIPHER_SUITE_WEP40:
3142                                 key.algo = CRYPTO_ALGO_WEP1;
3143                                 break;
3144                         case WLAN_CIPHER_SUITE_WEP104:
3145                                 key.algo = CRYPTO_ALGO_WEP128;
3146                                 break;
3147                         default:
3148                                 WL_ERR(("Invalid algorithm (%d)\n",
3149                                         sme->crypto.ciphers_pairwise[0]));
3150                                 return -EINVAL;
3151                         }
3152                         /* Set the new key/index */
3153                         WL_DBG(("key length (%d) key index (%d) algo (%d)\n",
3154                                 key.len, key.index, key.algo));
3155                         WL_DBG(("key \"%s\"\n", key.data));
3156                         swap_key_from_BE(&key);
3157                         err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
3158                                 wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3159                         if (unlikely(err)) {
3160                                 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
3161                                 return err;
3162                         }
3163                         if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
3164                                 WL_DBG(("set auth_type to shared key\n"));
3165                                 val = WL_AUTH_SHARED_KEY;       /* shared key */
3166                                 err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
3167                                 if (unlikely(err)) {
3168                                         WL_ERR(("set auth failed (%d)\n", err));
3169                                         return err;
3170                                 }
3171                         }
3172                 }
3173         }
3174         return err;
3175 }
3176
3177 #if defined(ESCAN_RESULT_PATCH)
3178 static u8 connect_req_bssid[6];
3179 static u8 broad_bssid[6];
3180 #endif /* ESCAN_RESULT_PATCH */
3181
3182
3183
3184 static s32
3185 wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
3186         struct cfg80211_connect_params *sme)
3187 {
3188         struct wl_priv *wl = wiphy_priv(wiphy);
3189         struct ieee80211_channel *chan = sme->channel;
3190         wl_extjoin_params_t *ext_join_params;
3191         struct wl_join_params join_params;
3192         size_t join_params_size;
3193         s32 err = 0;
3194         wpa_ie_fixed_t *wpa_ie;
3195         bcm_tlv_t *wpa2_ie;
3196         u8* wpaie  = 0;
3197         u32 wpaie_len = 0;
3198         u32 chan_cnt = 0;
3199         struct ether_addr bssid;
3200         s32 bssidx;
3201         int ret;
3202         int wait_cnt;
3203
3204         WL_DBG(("In\n"));
3205
3206         if (unlikely(!sme->ssid)) {
3207                 WL_ERR(("Invalid ssid\n"));
3208                 return -EOPNOTSUPP;
3209         }
3210
3211         if (unlikely(sme->ssid_len > DOT11_MAX_SSID_LEN)) {
3212                 WL_ERR(("Invalid SSID info: SSID=%s, length=%d\n",
3213                         sme->ssid, sme->ssid_len));
3214                 return -EINVAL;
3215         }
3216
3217         RETURN_EIO_IF_NOT_UP(wl);
3218
3219         /*
3220          * Cancel ongoing scan to sync up with sme state machine of cfg80211.
3221          */
3222 #if !defined(ESCAN_RESULT_PATCH)
3223         if (wl->scan_request) {
3224                 wl_notify_escan_complete(wl, dev, true, true);
3225         }
3226 #endif
3227 #if defined(ESCAN_RESULT_PATCH)
3228         if (sme->bssid)
3229                 memcpy(connect_req_bssid, sme->bssid, ETHER_ADDR_LEN);
3230         else
3231                 bzero(connect_req_bssid, ETHER_ADDR_LEN);
3232         bzero(broad_bssid, ETHER_ADDR_LEN);
3233 #endif
3234 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
3235         maxrxpktglom = 0;
3236 #endif
3237         bzero(&bssid, sizeof(bssid));
3238         if (!wl_get_drv_status(wl, CONNECTED, dev)&&
3239                 (ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false)) == 0) {
3240                 if (!ETHER_ISNULLADDR(&bssid)) {
3241                         scb_val_t scbval;
3242                         wl_set_drv_status(wl, DISCONNECTING, dev);
3243                         scbval.val = DOT11_RC_DISASSOC_LEAVING;
3244                         memcpy(&scbval.ea, &bssid, ETHER_ADDR_LEN);
3245                         scbval.val = htod32(scbval.val);
3246
3247                         WL_DBG(("drv status CONNECTED is not set, but connected in FW!" MACDBG "/n",
3248                                 MAC2STRDBG(bssid.octet)));
3249                         err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
3250                                 sizeof(scb_val_t), true);
3251                         if (unlikely(err)) {
3252                                 wl_clr_drv_status(wl, DISCONNECTING, dev);
3253                                 WL_ERR(("error (%d)\n", err));
3254                                 return err;
3255                         }
3256                         wait_cnt = 500/10;
3257                         while (wl_get_drv_status(wl, DISCONNECTING, dev) && wait_cnt) {
3258                                 WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n",
3259                                         wait_cnt));
3260                                 wait_cnt--;
3261                                 OSL_SLEEP(10);
3262                         }
3263                 } else
3264                         WL_DBG(("Currently not associated!\n"));
3265         } else {
3266                 /* if status is DISCONNECTING, wait for disconnection terminated max 500 ms */
3267                 wait_cnt = 500/10;
3268                 while (wl_get_drv_status(wl, DISCONNECTING, dev) && wait_cnt) {
3269                         WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n", wait_cnt));
3270                         wait_cnt--;
3271                         OSL_SLEEP(10);
3272                 }
3273         }
3274
3275         /* Clean BSSID */
3276         bzero(&bssid, sizeof(bssid));
3277         if (!wl_get_drv_status(wl, DISCONNECTING, dev))
3278                 wl_update_prof(wl, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
3279
3280         if (p2p_is_on(wl) && (dev != wl_to_prmry_ndev(wl))) {
3281                 /* we only allow to connect using virtual interface in case of P2P */
3282                         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3283                                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3284                                 return BCME_ERROR;
3285                         }
3286                         wl_cfgp2p_set_management_ie(wl, dev, bssidx,
3287                                 VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
3288         } else if (dev == wl_to_prmry_ndev(wl)) {
3289                 /* find the RSN_IE */
3290                 if ((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
3291                         DOT11_MNG_RSN_ID)) != NULL) {
3292                         WL_DBG((" WPA2 IE is found\n"));
3293                 }
3294                 /* find the WPA_IE */
3295                 if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)sme->ie,
3296                         sme->ie_len)) != NULL) {
3297                         WL_DBG((" WPA IE is found\n"));
3298                 }
3299                 if (wpa_ie != NULL || wpa2_ie != NULL) {
3300                         wpaie = (wpa_ie != NULL) ? (u8 *)wpa_ie : (u8 *)wpa2_ie;
3301                         wpaie_len = (wpa_ie != NULL) ? wpa_ie->length : wpa2_ie->len;
3302                         wpaie_len += WPA_RSN_IE_TAG_FIXED_LEN;
3303                         wldev_iovar_setbuf(dev, "wpaie", wpaie, wpaie_len,
3304                                 wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
3305                 } else {
3306                         wldev_iovar_setbuf(dev, "wpaie", NULL, 0,
3307                                 wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
3308                 }
3309
3310                 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3311                         WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3312                         return BCME_ERROR;
3313                 }
3314                 err = wl_cfgp2p_set_management_ie(wl, dev, bssidx,
3315                         VNDR_IE_ASSOCREQ_FLAG, (u8 *)sme->ie, sme->ie_len);
3316                 if (unlikely(err)) {
3317                         return err;
3318                 }
3319         }
3320         if (chan) {
3321                 wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
3322                 chan_cnt = 1;
3323                 WL_DBG(("channel (%d), center_req (%d), %d channels\n", wl->channel,
3324                         chan->center_freq, chan_cnt));
3325         } else
3326                 wl->channel = 0;
3327         WL_DBG(("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len));
3328         WL_DBG(("3. set wapi version \n"));
3329         err = wl_set_wpa_version(dev, sme);
3330         if (unlikely(err)) {
3331                 WL_ERR(("Invalid wpa_version\n"));
3332                 return err;
3333         }
3334                 err = wl_set_auth_type(dev, sme);
3335                 if (unlikely(err)) {
3336                         WL_ERR(("Invalid auth type\n"));
3337                         return err;
3338                 }
3339
3340         err = wl_set_set_cipher(dev, sme);
3341         if (unlikely(err)) {
3342                 WL_ERR(("Invalid ciper\n"));
3343                 return err;
3344         }
3345
3346         err = wl_set_key_mgmt(dev, sme);
3347         if (unlikely(err)) {
3348                 WL_ERR(("Invalid key mgmt\n"));
3349                 return err;
3350         }
3351
3352         err = wl_set_set_sharedkey(dev, sme);
3353         if (unlikely(err)) {
3354                 WL_ERR(("Invalid shared key\n"));
3355                 return err;
3356         }
3357
3358         /*
3359          *  Join with specific BSSID and cached SSID
3360          *  If SSID is zero join based on BSSID only
3361          */
3362         join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE +
3363                 chan_cnt * sizeof(chanspec_t);
3364         ext_join_params =  (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL);
3365         if (ext_join_params == NULL) {
3366                 err = -ENOMEM;
3367                 wl_clr_drv_status(wl, CONNECTING, dev);
3368                 goto exit;
3369         }
3370         ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len);
3371         memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len);
3372         wl_update_prof(wl, dev, NULL, &ext_join_params->ssid, WL_PROF_SSID);
3373         ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
3374         /* increate dwell time to receive probe response or detect Beacon
3375         * from target AP at a noisy air only when channel info is provided in connect command
3376         */
3377         ext_join_params->scan.active_time = chan_cnt ? WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS : -1;
3378         ext_join_params->scan.passive_time = chan_cnt ? WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS : -1;
3379         /* Set up join scan parameters */
3380         ext_join_params->scan.scan_type = -1;
3381         ext_join_params->scan.nprobes = chan_cnt ?
3382                 (ext_join_params->scan.active_time/WL_SCAN_JOIN_PROBE_INTERVAL_MS) : -1;
3383         ext_join_params->scan.home_time = -1;
3384
3385         if (sme->bssid)
3386                 memcpy(&ext_join_params->assoc.bssid, sme->bssid, ETH_ALEN);
3387         else
3388                 memcpy(&ext_join_params->assoc.bssid, &ether_bcast, ETH_ALEN);
3389         ext_join_params->assoc.chanspec_num = chan_cnt;
3390         if (chan_cnt) {
3391                 u16 channel, band, bw, ctl_sb;
3392                 chanspec_t chspec;
3393                 channel = wl->channel;
3394                 band = (channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G
3395                         : WL_CHANSPEC_BAND_5G;
3396                 bw = WL_CHANSPEC_BW_20;
3397                 ctl_sb = WL_CHANSPEC_CTL_SB_NONE;
3398                 chspec = (channel | band | bw | ctl_sb);
3399                 ext_join_params->assoc.chanspec_list[0]  &= WL_CHANSPEC_CHAN_MASK;
3400                 ext_join_params->assoc.chanspec_list[0] |= chspec;
3401                 ext_join_params->assoc.chanspec_list[0] =
3402                         wl_chspec_host_to_driver(ext_join_params->assoc.chanspec_list[0]);
3403         }
3404         ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num);
3405         if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
3406                 WL_INFO(("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID,
3407                         ext_join_params->ssid.SSID_len));
3408         }
3409         wl_set_drv_status(wl, CONNECTING, dev);
3410
3411         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3412                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3413                 return BCME_ERROR;
3414         }
3415         err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size,
3416                 wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3417
3418         WL_ERR(("Connectting with" MACDBG " channel (%d) ssid \"%s\", len (%d)\n\n",
3419                 MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)), wl->channel,
3420                 ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len));
3421
3422         kfree(ext_join_params);
3423         if (err) {
3424                 wl_clr_drv_status(wl, CONNECTING, dev);
3425                 if (err == BCME_UNSUPPORTED) {
3426                         WL_DBG(("join iovar is not supported\n"));
3427                         goto set_ssid;
3428                 } else
3429                         WL_ERR(("error (%d)\n", err));
3430         } else
3431                 goto exit;
3432
3433 set_ssid:
3434         memset(&join_params, 0, sizeof(join_params));
3435         join_params_size = sizeof(join_params.ssid);
3436
3437         join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
3438         memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
3439         join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
3440         wl_update_prof(wl, dev, NULL, &join_params.ssid, WL_PROF_SSID);
3441         if (sme->bssid)
3442                 memcpy(&join_params.params.bssid, sme->bssid, ETH_ALEN);
3443         else
3444                 memcpy(&join_params.params.bssid, &ether_bcast, ETH_ALEN);
3445
3446         wl_ch_to_chanspec(wl->channel, &join_params, &join_params_size);
3447         WL_DBG(("join_param_size %zu\n", join_params_size));
3448
3449         if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
3450                 WL_INFO(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
3451                         join_params.ssid.SSID_len));
3452         }
3453         wl_set_drv_status(wl, CONNECTING, dev);
3454         err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true);
3455         if (err) {
3456                 WL_ERR(("error (%d)\n", err));
3457                 wl_clr_drv_status(wl, CONNECTING, dev);
3458         }
3459 exit:
3460         return err;
3461 }
3462
3463 static s32
3464 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
3465         u16 reason_code)
3466 {
3467         struct wl_priv *wl = wiphy_priv(wiphy);
3468         scb_val_t scbval;
3469         bool act = false;
3470         s32 err = 0;
3471         u8 *curbssid;
3472         WL_ERR(("Reason %d\n", reason_code));
3473         RETURN_EIO_IF_NOT_UP(wl);
3474         act = *(bool *) wl_read_prof(wl, dev, WL_PROF_ACT);
3475         curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID);
3476         if (act) {
3477                 /*
3478                 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
3479                 */
3480 #if !defined(ESCAN_RESULT_PATCH)
3481                 /* Let scan aborted by F/W */
3482                 if (wl->scan_request) {
3483                         wl_notify_escan_complete(wl, dev, true, true);
3484                 }
3485 #endif /* ESCAN_RESULT_PATCH */
3486                 wl_set_drv_status(wl, DISCONNECTING, dev);
3487                 scbval.val = reason_code;
3488                 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
3489                 scbval.val = htod32(scbval.val);
3490                 err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
3491                         sizeof(scb_val_t), true);
3492                 if (unlikely(err)) {
3493                         wl_clr_drv_status(wl, DISCONNECTING, dev);
3494                         WL_ERR(("error (%d)\n", err));
3495                         return err;
3496                 }
3497         }
3498
3499         return err;
3500 }
3501
3502 #if defined(WL_CFG80211_P2P_DEV_IF)
3503 static s32
3504 wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
3505         enum nl80211_tx_power_setting type, s32 mbm)
3506 #else
3507 static s32
3508 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
3509         enum nl80211_tx_power_setting type, s32 dbm)
3510 #endif /* WL_CFG80211_P2P_DEV_IF */
3511 {
3512
3513         struct wl_priv *wl = wiphy_priv(wiphy);
3514         struct net_device *ndev = wl_to_prmry_ndev(wl);
3515         u16 txpwrmw;
3516         s32 err = 0;
3517         s32 disable = 0;
3518         s32 txpwrqdbm;
3519 #if defined(WL_CFG80211_P2P_DEV_IF)
3520         s32 dbm = MBM_TO_DBM(mbm);
3521 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || \
3522         defined(WL_COMPAT_WIRELESS) || defined(WL_SUPPORT_BACKPORTED_KPATCHES)
3523         dbm = MBM_TO_DBM(dbm);
3524 #endif /* WL_CFG80211_P2P_DEV_IF */
3525
3526         RETURN_EIO_IF_NOT_UP(wl);
3527         switch (type) {
3528         case NL80211_TX_POWER_AUTOMATIC:
3529                 break;
3530         case NL80211_TX_POWER_LIMITED:
3531                 if (dbm < 0) {
3532                         WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
3533                         return -EINVAL;
3534                 }
3535                 break;
3536         case NL80211_TX_POWER_FIXED:
3537                 if (dbm < 0) {
3538                         WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
3539                         return -EINVAL;
3540                 }
3541                 break;
3542         }
3543         /* Make sure radio is off or on as far as software is concerned */
3544         disable = WL_RADIO_SW_DISABLE << 16;
3545         disable = htod32(disable);
3546         err = wldev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable), true);
3547         if (unlikely(err)) {
3548                 WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
3549                 return err;
3550         }
3551
3552         if (dbm > 0xffff)
3553                 txpwrmw = 0xffff;
3554         else
3555                 txpwrmw = (u16) dbm;
3556         txpwrqdbm = (s32)bcm_mw_to_qdbm(txpwrmw);
3557 #ifdef SUPPORT_WL_TXPOWER
3558         if (type == NL80211_TX_POWER_AUTOMATIC)
3559                 txpwrqdbm = 127;
3560         else
3561                 txpwrqdbm |= WL_TXPWR_OVERRIDE;
3562 #endif /* SUPPORT_WL_TXPOWER */
3563         err = wldev_iovar_setint(ndev, "qtxpower", txpwrqdbm);
3564         if (unlikely(err)) {
3565                 WL_ERR(("qtxpower error (%d)\n", err));
3566                 return err;
3567         }
3568         wl->conf->tx_power = dbm;
3569
3570         return err;
3571 }
3572
3573 #if defined(WL_CFG80211_P2P_DEV_IF)
3574 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
3575         struct wireless_dev *wdev, s32 *dbm)
3576 #else
3577 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
3578 #endif /* WL_CFG80211_P2P_DEV_IF */
3579 {
3580         struct wl_priv *wl = wiphy_priv(wiphy);
3581         struct net_device *ndev = wl_to_prmry_ndev(wl);
3582         s32 txpwrdbm;
3583         u8 result;
3584         s32 err = 0;
3585
3586         RETURN_EIO_IF_NOT_UP(wl);
3587         err = wldev_iovar_getint(ndev, "qtxpower", &txpwrdbm);
3588         if (unlikely(err)) {
3589                 WL_ERR(("error (%d)\n", err));
3590                 return err;
3591         }
3592         result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
3593         *dbm = (s32) bcm_qdbm_to_mw(result);
3594
3595         return err;
3596 }
3597
3598 static s32
3599 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
3600         u8 key_idx, bool unicast, bool multicast)
3601 {
3602         struct wl_priv *wl = wiphy_priv(wiphy);
3603         u32 index;
3604         s32 wsec;
3605         s32 err = 0;
3606         s32 bssidx;
3607         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3608                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3609                 return BCME_ERROR;
3610         }
3611
3612         WL_DBG(("key index (%d)\n", key_idx));
3613         RETURN_EIO_IF_NOT_UP(wl);
3614         err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
3615         if (unlikely(err)) {
3616                 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
3617                 return err;
3618         }
3619         /* fix IOT issue with Apple Airport */
3620         if (wsec == WEP_ENABLED) {
3621                 /* Just select a new current key */
3622                 index = (u32) key_idx;
3623                 index = htod32(index);
3624                 err = wldev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
3625                         sizeof(index), true);
3626                 if (unlikely(err)) {
3627                         WL_ERR(("error (%d)\n", err));
3628                 }
3629         }
3630         return err;
3631 }
3632
3633 static s32
3634 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
3635         u8 key_idx, const u8 *mac_addr, struct key_params *params)
3636 {
3637         struct wl_priv *wl = wiphy_priv(wiphy);
3638         struct wl_wsec_key key;
3639         s32 err = 0;
3640         s32 bssidx;
3641         s32 mode = wl_get_mode_by_netdev(wl, dev);
3642         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3643                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3644                 return BCME_ERROR;
3645         }
3646         memset(&key, 0, sizeof(key));
3647         key.index = (u32) key_idx;
3648
3649         if (!ETHER_ISMULTI(mac_addr))
3650                 memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN);
3651         key.len = (u32) params->key_len;
3652
3653         /* check for key index change */
3654         if (key.len == 0) {
3655                 /* key delete */
3656                 swap_key_from_BE(&key);
3657                 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
3658                         wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3659                 if (unlikely(err)) {
3660                         WL_ERR(("key delete error (%d)\n", err));
3661                         return err;
3662                 }
3663         } else {
3664                 if (key.len > sizeof(key.data)) {
3665                         WL_ERR(("Invalid key length (%d)\n", key.len));
3666                         return -EINVAL;
3667                 }
3668                 WL_DBG(("Setting the key index %d\n", key.index));
3669                 memcpy(key.data, params->key, key.len);
3670
3671                 if ((mode == WL_MODE_BSS) &&
3672                         (params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
3673                         u8 keybuf[8];
3674                         memcpy(keybuf, &key.data[24], sizeof(keybuf));
3675                         memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
3676                         memcpy(&key.data[16], keybuf, sizeof(keybuf));
3677                 }
3678
3679                 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
3680                 if (params->seq && params->seq_len == 6) {
3681                         /* rx iv */
3682                         u8 *ivptr;
3683                         ivptr = (u8 *) params->seq;
3684                         key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
3685                                 (ivptr[3] << 8) | ivptr[2];
3686                         key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
3687                         key.iv_initialized = true;
3688                 }
3689
3690                 switch (params->cipher) {
3691                 case WLAN_CIPHER_SUITE_WEP40:
3692                         key.algo = CRYPTO_ALGO_WEP1;
3693                         WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
3694                         break;
3695                 case WLAN_CIPHER_SUITE_WEP104:
3696                         key.algo = CRYPTO_ALGO_WEP128;
3697                         WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
3698                         break;
3699                 case WLAN_CIPHER_SUITE_TKIP:
3700                         key.algo = CRYPTO_ALGO_TKIP;
3701                         WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
3702                         break;
3703                 case WLAN_CIPHER_SUITE_AES_CMAC:
3704                         key.algo = CRYPTO_ALGO_AES_CCM;
3705                         WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
3706                         break;
3707                 case WLAN_CIPHER_SUITE_CCMP:
3708                         key.algo = CRYPTO_ALGO_AES_CCM;
3709                         WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
3710                         break;
3711                 default:
3712                         WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
3713                         return -EINVAL;
3714                 }
3715                 swap_key_from_BE(&key);
3716                 /* need to guarantee EAPOL 4/4 send out before set key */
3717                 if (mode != WL_MODE_AP)
3718                         dhd_wait_pend8021x(dev);
3719                 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
3720                         wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3721                 if (unlikely(err)) {
3722                         WL_ERR(("WLC_SET_KEY error (%d)\n", err));
3723                         return err;
3724                 }
3725         }
3726         return err;
3727 }
3728
3729 static s32
3730 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
3731         u8 key_idx, bool pairwise, const u8 *mac_addr,
3732         struct key_params *params)
3733 {
3734         struct wl_wsec_key key;
3735         s32 val = 0;
3736         s32 wsec = 0;
3737         s32 err = 0;
3738         u8 keybuf[8];
3739         s32 bssidx = 0;
3740         struct wl_priv *wl = wiphy_priv(wiphy);
3741         s32 mode = wl_get_mode_by_netdev(wl, dev);
3742         WL_DBG(("key index (%d)\n", key_idx));
3743         RETURN_EIO_IF_NOT_UP(wl);
3744
3745         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3746                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3747                 return BCME_ERROR;
3748         }
3749
3750         if (mac_addr &&
3751                 ((params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
3752                 (params->cipher != WLAN_CIPHER_SUITE_WEP104))) {
3753                         wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
3754                         goto exit;
3755         }
3756         memset(&key, 0, sizeof(key));
3757
3758         key.len = (u32) params->key_len;
3759         key.index = (u32) key_idx;
3760
3761         if (unlikely(key.len > sizeof(key.data))) {
3762                 WL_ERR(("Too long key length (%u)\n", key.len));
3763                 return -EINVAL;
3764         }
3765         memcpy(key.data, params->key, key.len);
3766
3767         key.flags = WL_PRIMARY_KEY;
3768         switch (params->cipher) {
3769         case WLAN_CIPHER_SUITE_WEP40:
3770                 key.algo = CRYPTO_ALGO_WEP1;
3771                 val = WEP_ENABLED;
3772                 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
3773                 break;
3774         case WLAN_CIPHER_SUITE_WEP104:
3775                 key.algo = CRYPTO_ALGO_WEP128;
3776                 val = WEP_ENABLED;
3777                 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
3778                 break;
3779         case WLAN_CIPHER_SUITE_TKIP:
3780                 key.algo = CRYPTO_ALGO_TKIP;
3781                 val = TKIP_ENABLED;
3782                 /* wpa_supplicant switches the third and fourth quarters of the TKIP key */
3783                 if (mode == WL_MODE_BSS) {
3784                         bcopy(&key.data[24], keybuf, sizeof(keybuf));
3785                         bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
3786                         bcopy(keybuf, &key.data[16], sizeof(keybuf));
3787                 }
3788                 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
3789                 break;
3790         case WLAN_CIPHER_SUITE_AES_CMAC:
3791                 key.algo = CRYPTO_ALGO_AES_CCM;
3792                 val = AES_ENABLED;
3793                 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
3794                 break;
3795         case WLAN_CIPHER_SUITE_CCMP:
3796                 key.algo = CRYPTO_ALGO_AES_CCM;
3797                 val = AES_ENABLED;
3798                 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
3799                 break;
3800         default:
3801                 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
3802                 return -EINVAL;
3803         }
3804
3805         /* Set the new key/index */
3806         if ((mode == WL_MODE_IBSS) && (val & (TKIP_ENABLED | AES_ENABLED))) {
3807                 WL_ERR(("IBSS KEY setted\n"));
3808                 wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_NONE);
3809         }
3810         swap_key_from_BE(&key);
3811         err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), wl->ioctl_buf,
3812                 WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3813         if (unlikely(err)) {
3814                 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
3815                 return err;
3816         }
3817
3818 exit:
3819         err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
3820         if (unlikely(err)) {
3821                 WL_ERR(("get wsec error (%d)\n", err));
3822                 return err;
3823         }
3824
3825         wsec |= val;
3826         err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
3827         if (unlikely(err)) {
3828                 WL_ERR(("set wsec error (%d)\n", err));
3829                 return err;
3830         }
3831
3832         return err;
3833 }
3834
3835 static s32
3836 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
3837         u8 key_idx, bool pairwise, const u8 *mac_addr)
3838 {
3839         struct wl_wsec_key key;
3840         struct wl_priv *wl = wiphy_priv(wiphy);
3841         s32 err = 0;
3842         s32 bssidx;
3843
3844         if (!wl)
3845                 return ERR_PTR(-EINVAL);
3846
3847         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3848                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3849                 return BCME_ERROR;
3850         }
3851         WL_DBG(("Enter\n"));
3852
3853 #ifndef IEEE80211W
3854         if ((key_idx >= DOT11_MAX_DEFAULT_KEYS) && (key_idx < DOT11_MAX_DEFAULT_KEYS+2))
3855                 return -EINVAL;
3856 #endif
3857
3858         RETURN_EIO_IF_NOT_UP(wl);
3859         memset(&key, 0, sizeof(key));
3860
3861         key.flags = WL_PRIMARY_KEY;
3862         key.algo = CRYPTO_ALGO_OFF;
3863         key.index = (u32) key_idx;
3864
3865         WL_DBG(("key index (%d)\n", key_idx));
3866         /* Set the new key/index */
3867         swap_key_from_BE(&key);
3868         err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), wl->ioctl_buf,
3869                 WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3870         if (unlikely(err)) {
3871                 if (err == -EINVAL) {
3872                         if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
3873                                 /* we ignore this key index in this case */
3874                                 WL_DBG(("invalid key index (%d)\n", key_idx));
3875                         }
3876                 } else {
3877                         WL_ERR(("WLC_SET_KEY error (%d)\n", err));
3878                 }
3879                 return err;
3880         }
3881         return err;
3882 }
3883
3884 static s32
3885 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
3886         u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
3887         void (*callback) (void *cookie, struct key_params * params))
3888 {
3889         struct key_params params;
3890         struct wl_wsec_key key;
3891         struct wl_priv *wl = wiphy_priv(wiphy);
3892         struct wl_security *sec;
3893         s32 wsec;
3894         s32 err = 0;
3895         s32 bssidx;
3896         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3897                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3898                 return BCME_ERROR;
3899         }
3900         WL_DBG(("key index (%d)\n", key_idx));
3901         RETURN_EIO_IF_NOT_UP(wl);
3902         memset(&key, 0, sizeof(key));
3903         key.index = key_idx;
3904         swap_key_to_BE(&key);
3905         memset(&params, 0, sizeof(params));
3906         params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
3907         memcpy(params.key, key.data, params.key_len);
3908
3909         err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
3910         if (unlikely(err)) {
3911                 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
3912                 return err;
3913         }
3914         switch (wsec & ~SES_OW_ENABLED) {
3915                 case WEP_ENABLED:
3916                         sec = wl_read_prof(wl, dev, WL_PROF_SEC);
3917                         if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
3918                                 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3919                                 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
3920                         } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
3921                                 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3922                                 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
3923                         }
3924                         break;
3925                 case TKIP_ENABLED:
3926                         params.cipher = WLAN_CIPHER_SUITE_TKIP;
3927                         WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
3928                         break;
3929                 case AES_ENABLED:
3930                         params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3931                         WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
3932                         break;
3933                 default:
3934                         WL_ERR(("Invalid algo (0x%x)\n", wsec));
3935                         return -EINVAL;
3936         }
3937
3938         callback(cookie, &params);
3939         return err;
3940 }
3941
3942 static s32
3943 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
3944         struct net_device *dev, u8 key_idx)
3945 {
3946         WL_INFO(("Not supported\n"));
3947         return -EOPNOTSUPP;
3948 }
3949
3950 static s32
3951 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
3952         u8 *mac, struct station_info *sinfo)
3953 {
3954         struct wl_priv *wl = wiphy_priv(wiphy);
3955         scb_val_t scb_val;
3956         s32 rssi;
3957         s32 rate;
3958         s32 err = 0;
3959         sta_info_t *sta;
3960 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) || 0
3961         s8 eabuf[ETHER_ADDR_STR_LEN];
3962 #endif
3963         dhd_pub_t *dhd =  (dhd_pub_t *)(wl->pub);
3964         RETURN_EIO_IF_NOT_UP(wl);
3965         if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) {
3966                 err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac,
3967                         ETHER_ADDR_LEN, wl->ioctl_buf, WLC_IOCTL_SMLEN, &wl->ioctl_buf_sync);
3968                 if (err < 0) {
3969                         WL_ERR(("GET STA INFO failed, %d\n", err));
3970                         return err;
3971                 }
3972                 sinfo->filled = STATION_INFO_INACTIVE_TIME;
3973                 sta = (sta_info_t *)wl->ioctl_buf;
3974                 sta->len = dtoh16(sta->len);
3975                 sta->cap = dtoh16(sta->cap);
3976                 sta->flags = dtoh32(sta->flags);
3977                 sta->idle = dtoh32(sta->idle);
3978                 sta->in = dtoh32(sta->in);
3979                 sinfo->inactive_time = sta->idle * 1000;
3980 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) || 0
3981                 if (sta->flags & WL_STA_ASSOC) {
3982                         sinfo->filled |= STATION_INFO_CONNECTED_TIME;
3983                         sinfo->connected_time = sta->in;
3984                 }
3985                 WL_INFO(("STA %s : idle time : %d sec, connected time :%d ms\n",
3986                         bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), sinfo->inactive_time,
3987                         sta->idle * 1000));
3988 #endif
3989         } else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_BSS ||
3990                 wl_get_mode_by_netdev(wl, dev) == WL_MODE_IBSS) {
3991                 get_pktcnt_t pktcnt;
3992                 u8 *curmacp = wl_read_prof(wl, dev, WL_PROF_BSSID);
3993                 if (!wl_get_drv_status(wl, CONNECTED, dev) ||
3994                         (dhd_is_associated(dhd, NULL, &err) == FALSE)) {
3995                         WL_ERR(("NOT assoc\n"));
3996                         if (err == -ERESTARTSYS)
3997                                 return err;
3998                         err = -ENODEV;
3999                         return err;
4000                 }
4001                 if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
4002                         WL_ERR(("Wrong Mac address: "MACDBG" != "MACDBG"\n",
4003                                 MAC2STRDBG(mac), MAC2STRDBG(curmacp)));
4004                 }
4005
4006                 /* Report the current tx rate */
4007                 err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
4008                 if (err) {
4009                         WL_ERR(("Could not get rate (%d)\n", err));
4010                 } else {
4011 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
4012                         int rxpktglom;
4013 #endif
4014                         rate = dtoh32(rate);
4015                         sinfo->filled |= STATION_INFO_TX_BITRATE;
4016                         sinfo->txrate.legacy = rate * 5;
4017                         WL_DBG(("Rate %d Mbps\n", (rate / 2)));
4018 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
4019                         rxpktglom = ((rate/2) > 150) ? 20 : 10;
4020
4021                         if (maxrxpktglom != rxpktglom) {
4022                                 maxrxpktglom = rxpktglom;
4023                                 WL_DBG(("Rate %d Mbps, update bus:maxtxpktglom=%d\n", (rate/2),
4024                                         maxrxpktglom));
4025                                 err = wldev_iovar_setbuf(dev, "bus:maxtxpktglom",
4026                                         (char*)&maxrxpktglom, 4, wl->ioctl_buf,
4027                                         WLC_IOCTL_MAXLEN, NULL);
4028                                 if (err < 0) {
4029                                         WL_ERR(("set bus:maxtxpktglom failed, %d\n", err));
4030                                 }
4031                         }
4032 #endif
4033                 }
4034
4035                 memset(&scb_val, 0, sizeof(scb_val));
4036                 scb_val.val = 0;
4037                 err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,
4038                         sizeof(scb_val_t), false);
4039                 if (err) {
4040                         WL_ERR(("Could not get rssi (%d)\n", err));
4041                         goto get_station_err;
4042                 }
4043                 rssi = wl_rssi_offset(dtoh32(scb_val.val));
4044                 sinfo->filled |= STATION_INFO_SIGNAL;
4045                 sinfo->signal = rssi;
4046                 WL_DBG(("RSSI %d dBm\n", rssi));
4047                 err = wldev_ioctl(dev, WLC_GET_PKTCNTS, &pktcnt,
4048                         sizeof(pktcnt), false);
4049                 if (!err) {
4050                         sinfo->filled |= (STATION_INFO_RX_PACKETS |
4051                                 STATION_INFO_RX_DROP_MISC |
4052                                 STATION_INFO_TX_PACKETS |
4053                                 STATION_INFO_TX_FAILED);
4054                         sinfo->rx_packets = pktcnt.rx_good_pkt;
4055                         sinfo->rx_dropped_misc = pktcnt.rx_bad_pkt;
4056                         sinfo->tx_packets = pktcnt.tx_good_pkt;
4057                         sinfo->tx_failed  = pktcnt.tx_bad_pkt;
4058                 }
4059 get_station_err:
4060                 if (err && (err != -ERESTARTSYS)) {
4061                         /* Disconnect due to zero BSSID or error to get RSSI */
4062                         WL_ERR(("force cfg80211_disconnected: %d\n", err));
4063                         wl_clr_drv_status(wl, CONNECTED, dev);
4064                         cfg80211_disconnected(dev, 0, NULL, 0, GFP_KERNEL);
4065                         wl_link_down(wl);
4066                 }
4067         }
4068         else {
4069                 WL_ERR(("Invalid device mode %d\n", wl_get_mode_by_netdev(wl, dev)));
4070         }
4071
4072         return err;
4073 }
4074
4075 /* Function to update sta power save mode for Kernel wifi stack */
4076 int wl_cfg80211_update_power_mode(struct net_device *dev)
4077 {
4078         int pm = -1;
4079         int err;
4080
4081         err = wldev_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), false);
4082         if (err || (pm == -1)) {
4083                 WL_ERR(("error (%d)\n", err));
4084         } else {
4085                 pm = (pm == PM_OFF) ? false : true;
4086                 WL_DBG(("%s: %d\n", __func__, pm));
4087                 if (dev->ieee80211_ptr)
4088                         dev->ieee80211_ptr->ps = pm;
4089         }
4090         return err;
4091 }
4092
4093 static s32
4094 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
4095         bool enabled, s32 timeout)
4096 {
4097         s32 pm;
4098         s32 err = 0;
4099         struct wl_priv *wl = wiphy_priv(wiphy);
4100         struct net_info *_net_info = wl_get_netinfo_by_netdev(wl, dev);
4101 #if !defined(SUPPORT_PM2_ONLY)
4102         dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
4103 #endif /* (OEM_ANDROID) */
4104         RETURN_EIO_IF_NOT_UP(wl);
4105         WL_DBG(("Enter\n"));
4106 #if defined(WL_ENABLE_P2P_IF)
4107         if (wl->p2p_net == dev || _net_info == NULL || wl->vsdb_mode ||
4108                 !wl_get_drv_status(wl, CONNECTED, dev)) {
4109 #else
4110         if (_net_info == NULL || wl->vsdb_mode ||
4111                 !wl_get_drv_status(wl, CONNECTED, dev)) {
4112 #endif /* WL_ENABLE_P2P_IF */
4113                 return err;
4114         }
4115         WL_DBG(("%s: Enter power save enabled %d\n", dev->name, enabled));
4116
4117         /* Delete pm_enable_work */
4118                 wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_PEND);
4119
4120 #if !defined(SUPPORT_PM2_ONLY)
4121         /* android has special hooks to change pm when kernel suspended */
4122         pm = enabled ? ((dhd->in_suspend) ? PM_MAX : PM_FAST) : PM_OFF;
4123 #else
4124         pm = enabled ? PM_FAST : PM_OFF;
4125 #endif /* SUPPORT_PM2_ONLY */
4126         if (_net_info->pm_block) {
4127                 WL_ERR(("%s:Do not enable the power save for pm_block %d\n",
4128                         dev->name, _net_info->pm_block));
4129                 pm = PM_OFF;
4130         }
4131         pm = htod32(pm);
4132         WL_DBG(("%s:power save %s\n", dev->name, (pm ? "enabled" : "disabled")));
4133         err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true);
4134         if (unlikely(err)) {
4135                 if (err == -ENODEV)
4136                         WL_DBG(("net_device is not ready yet\n"));
4137                 else
4138                         WL_ERR(("error (%d)\n", err));
4139                 return err;
4140         }
4141         return err;
4142 }
4143
4144 static __used u32 wl_find_msb(u16 bit16)
4145 {
4146         u32 ret = 0;
4147
4148         if (bit16 & 0xff00) {
4149                 ret += 8;
4150                 bit16 >>= 8;
4151         }
4152
4153         if (bit16 & 0xf0) {
4154                 ret += 4;
4155                 bit16 >>= 4;
4156         }
4157
4158         if (bit16 & 0xc) {
4159                 ret += 2;
4160                 bit16 >>= 2;
4161         }
4162
4163         if (bit16 & 2)
4164                 ret += bit16 & 2;
4165         else if (bit16)
4166                 ret += bit16;
4167
4168         return ret;
4169 }
4170
4171 static s32 wl_cfg80211_resume(struct wiphy *wiphy)
4172 {
4173         struct wl_priv *wl = wiphy_priv(wiphy);
4174         struct net_device *ndev = wl_to_prmry_ndev(wl);
4175         s32 err = 0;
4176
4177         if (unlikely(!wl_get_drv_status(wl, READY, ndev))) {
4178                 WL_INFO(("device is not ready\n"));
4179                 return 0;
4180         }
4181
4182         wl_invoke_iscan(wl);
4183
4184         return err;
4185 }
4186
4187 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || 0
4188 static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
4189 #else
4190 static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
4191 #endif
4192 {
4193 #ifdef DHD_CLEAR_ON_SUSPEND
4194         struct wl_priv *wl = wiphy_priv(wiphy);
4195         struct net_info *iter, *next;
4196         struct net_device *ndev = wl_to_prmry_ndev(wl);
4197         unsigned long flags;
4198         if (unlikely(!wl_get_drv_status(wl, READY, ndev))) {
4199                 WL_INFO(("device is not ready : status (%d)\n",
4200                         (int)wl->status));
4201                 return 0;
4202         }
4203         for_each_ndev(wl, iter, next)
4204                 wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev);
4205         wl_term_iscan(wl);
4206         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
4207         if (wl->scan_request) {
4208                 cfg80211_scan_done(wl->scan_request, true);
4209                 wl->scan_request = NULL;
4210         }
4211         for_each_ndev(wl, iter, next) {
4212                 wl_clr_drv_status(wl, SCANNING, iter->ndev);
4213                 wl_clr_drv_status(wl, SCAN_ABORTING, iter->ndev);
4214         }
4215         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
4216         for_each_ndev(wl, iter, next) {
4217                 if (wl_get_drv_status(wl, CONNECTING, iter->ndev)) {
4218                         wl_bss_connect_done(wl, iter->ndev, NULL, NULL, false);
4219                 }
4220         }
4221 #endif /* DHD_CLEAR_ON_SUSPEND */
4222         return 0;
4223 }
4224
4225 static s32
4226 wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
4227         s32 err)
4228 {
4229         int i, j;
4230         struct wl_priv *wl = wlcfg_drv_priv;
4231         struct net_device *primary_dev = wl_to_prmry_ndev(wl);
4232
4233         if (!pmk_list) {
4234                 printk("pmk_list is NULL\n");
4235                 return -EINVAL;
4236         }
4237         /* pmk list is supported only for STA interface i.e. primary interface
4238          * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
4239          */
4240         if (primary_dev != dev) {
4241                 WL_INFO(("Not supporting Flushing pmklist on virtual"
4242                         " interfaces than primary interface\n"));
4243                 return err;
4244         }
4245
4246         WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
4247         for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
4248                 WL_DBG(("PMKID[%d]: %pM =\n", i,
4249                         &pmk_list->pmkids.pmkid[i].BSSID));
4250                 for (j = 0; j < WPA2_PMKID_LEN; j++) {
4251                         WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
4252                 }
4253         }
4254         if (likely(!err)) {
4255                 err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmk_list,
4256                         sizeof(*pmk_list), wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
4257         }
4258
4259         return err;
4260 }
4261
4262 static s32
4263 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
4264         struct cfg80211_pmksa *pmksa)
4265 {
4266         struct wl_priv *wl = wiphy_priv(wiphy);
4267         s32 err = 0;
4268         int i;
4269
4270         RETURN_EIO_IF_NOT_UP(wl);
4271         for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
4272                 if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
4273                         ETHER_ADDR_LEN))
4274                         break;
4275         if (i < WL_NUM_PMKIDS_MAX) {
4276                 memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
4277                         ETHER_ADDR_LEN);
4278                 memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
4279                         WPA2_PMKID_LEN);
4280                 if (i == wl->pmk_list->pmkids.npmkid)
4281                         wl->pmk_list->pmkids.npmkid++;
4282         } else {
4283                 err = -EINVAL;
4284         }
4285         WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
4286                 &wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid - 1].BSSID));
4287         for (i = 0; i < WPA2_PMKID_LEN; i++) {
4288                 WL_DBG(("%02x\n",
4289                         wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid - 1].
4290                         PMKID[i]));
4291         }
4292
4293         err = wl_update_pmklist(dev, wl->pmk_list, err);
4294
4295         return err;
4296 }
4297
4298 static s32
4299 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
4300         struct cfg80211_pmksa *pmksa)
4301 {
4302         struct wl_priv *wl = wiphy_priv(wiphy);
4303         struct _pmkid_list pmkid = {0};
4304         s32 err = 0;
4305         int i;
4306
4307         RETURN_EIO_IF_NOT_UP(wl);
4308         memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
4309         memcpy(pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
4310
4311         WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
4312                 &pmkid.pmkid[0].BSSID));
4313         for (i = 0; i < WPA2_PMKID_LEN; i++) {
4314                 WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
4315         }
4316
4317         for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
4318                 if (!memcmp
4319                     (pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
4320                      ETHER_ADDR_LEN))
4321                         break;
4322
4323         if ((wl->pmk_list->pmkids.npmkid > 0) &&
4324                 (i < wl->pmk_list->pmkids.npmkid)) {
4325                 memset(&wl->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
4326                 for (; i < (wl->pmk_list->pmkids.npmkid - 1); i++) {
4327                         memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID,
4328                                 &wl->pmk_list->pmkids.pmkid[i + 1].BSSID,
4329                                 ETHER_ADDR_LEN);
4330                         memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID,
4331                                 &wl->pmk_list->pmkids.pmkid[i + 1].PMKID,
4332                                 WPA2_PMKID_LEN);
4333                 }
4334                 wl->pmk_list->pmkids.npmkid--;
4335         } else {
4336                 err = -EINVAL;
4337         }
4338
4339         err = wl_update_pmklist(dev, wl->pmk_list, err);
4340
4341         return err;
4342
4343 }
4344
4345 static s32
4346 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
4347 {
4348         struct wl_priv *wl = wiphy_priv(wiphy);
4349         s32 err = 0;
4350         RETURN_EIO_IF_NOT_UP(wl);
4351         memset(wl->pmk_list, 0, sizeof(*wl->pmk_list));
4352         err = wl_update_pmklist(dev, wl->pmk_list, err);
4353         return err;
4354
4355 }
4356
4357 static wl_scan_params_t *
4358 wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size)
4359 {
4360         wl_scan_params_t *params;
4361         int params_size;
4362         int num_chans;
4363
4364         *out_params_size = 0;
4365
4366         /* Our scan params only need space for 1 channel and 0 ssids */
4367         params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16);
4368         params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL);
4369         if (params == NULL) {
4370                 WL_ERR(("mem alloc failed (%d bytes)\n", params_size));
4371                 return params;
4372         }
4373         memset(params, 0, params_size);
4374         params->nprobes = nprobes;
4375
4376         num_chans = (channel == 0) ? 0 : 1;
4377
4378         memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
4379         params->bss_type = DOT11_BSSTYPE_ANY;
4380         params->scan_type = DOT11_SCANTYPE_ACTIVE;
4381         params->nprobes = htod32(1);
4382         params->active_time = htod32(-1);
4383         params->passive_time = htod32(-1);
4384         params->home_time = htod32(10);
4385         if (channel == -1)
4386                 params->channel_list[0] = htodchanspec(channel);
4387         else
4388                 params->channel_list[0] = wl_ch_host_to_driver(channel);
4389
4390         /* Our scan params have 1 channel and 0 ssids */
4391         params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
4392                 (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
4393
4394         *out_params_size = params_size; /* rtn size to the caller */
4395         return params;
4396 }
4397
4398 #if defined(WL_CFG80211_P2P_DEV_IF)
4399 static s32
4400 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
4401         struct ieee80211_channel *channel, unsigned int duration, u64 *cookie)
4402 #else
4403 static s32
4404 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
4405         struct ieee80211_channel * channel,
4406         enum nl80211_channel_type channel_type,
4407         unsigned int duration, u64 *cookie)
4408 #endif /* WL_CFG80211_P2P_DEV_IF */
4409 {
4410         s32 target_channel;
4411         u32 id;
4412         s32 err = BCME_OK;
4413         struct ether_addr primary_mac;
4414         struct net_device *ndev = NULL;
4415         struct wl_priv *wl = wiphy_priv(wiphy);
4416
4417         if (!wl)
4418                 return ERR_PTR(-EINVAL);
4419
4420         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
4421
4422         WL_DBG(("Enter, channel: %d, duration ms (%d) SCANNING ?? %s \n",
4423                 ieee80211_frequency_to_channel(channel->center_freq),
4424                 duration, (wl_get_drv_status(wl, SCANNING, ndev)) ? "YES":"NO"));
4425
4426         if (!wl->p2p) {
4427                 WL_ERR(("wl->p2p is not initialized\n"));
4428                 err = BCME_ERROR;
4429                 goto exit;
4430         }
4431
4432 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4433         if (wl_get_drv_status_all(wl, SCANNING)) {
4434                 wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true);
4435         }
4436 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4437
4438         target_channel = ieee80211_frequency_to_channel(channel->center_freq);
4439         memcpy(&wl->remain_on_chan, channel, sizeof(struct ieee80211_channel));
4440 #if defined(WL_ENABLE_P2P_IF)
4441         wl->remain_on_chan_type = channel_type;
4442 #endif /* WL_ENABLE_P2P_IF */
4443         id = ++wl->last_roc_id;
4444         if (id == 0)
4445                 id = ++wl->last_roc_id;
4446         *cookie = id;
4447
4448 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4449         if (wl_get_drv_status(wl, SCANNING, ndev)) {
4450                 struct timer_list *_timer;
4451                 WL_DBG(("scan is running. go to fake listen state\n"));
4452
4453                 wl_set_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev);
4454
4455                 if (timer_pending(&wl->p2p->listen_timer)) {
4456                         WL_DBG(("cancel current listen timer \n"));
4457                         del_timer_sync(&wl->p2p->listen_timer);
4458                 }
4459
4460                 _timer = &wl->p2p->listen_timer;
4461                 wl_clr_p2p_status(wl, LISTEN_EXPIRED);
4462
4463                 INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration, 0);
4464
4465                 err = BCME_OK;
4466                 goto exit;
4467         }
4468 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4469
4470 #ifdef WL_CFG80211_SYNC_GON
4471         if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN)) {
4472                 /* do not enter listen mode again if we are in listen mode already for next af.
4473                  * remain on channel completion will be returned by waiting next af completion.
4474                  */
4475 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4476                 wl_set_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev);
4477 #else
4478                 wl_set_drv_status(wl, REMAINING_ON_CHANNEL, ndev);
4479 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4480                 goto exit;
4481         }
4482 #endif /* WL_CFG80211_SYNC_GON */
4483         if (wl->p2p && !wl->p2p->on) {
4484                 /* In case of p2p_listen command, supplicant send remain_on_channel
4485                  * without turning on P2P
4486                  */
4487                 get_primary_mac(wl, &primary_mac);
4488                 wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr);
4489                 p2p_on(wl) = true;
4490         }
4491
4492         if (p2p_is_on(wl)) {
4493                 err = wl_cfgp2p_enable_discovery(wl, ndev, NULL, 0);
4494                 if (unlikely(err)) {
4495                         goto exit;
4496                 }
4497 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4498                 wl_set_drv_status(wl, REMAINING_ON_CHANNEL, ndev);
4499 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4500                 err = wl_cfgp2p_discover_listen(wl, target_channel, duration);
4501
4502 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4503                 if (err == BCME_OK) {
4504                         wl_set_drv_status(wl, REMAINING_ON_CHANNEL, ndev);
4505                 } else {
4506                         /* if failed, firmware may be internal scanning state.
4507                          * so other scan request shall not abort it
4508                          */
4509                         wl_set_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev);
4510                 }
4511 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4512                 /* WAR: set err = ok to prevent cookie mismatch in wpa_supplicant
4513                  * and expire timer will send a completion to the upper layer
4514                  */
4515                 err = BCME_OK;
4516         }
4517
4518 exit:
4519         if (err == BCME_OK) {
4520                 WL_INFO(("Success\n"));
4521 #if defined(WL_CFG80211_P2P_DEV_IF)
4522                 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
4523                         duration, GFP_KERNEL);
4524 #else
4525                 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
4526                         channel_type, duration, GFP_KERNEL);
4527 #endif /* WL_CFG80211_P2P_DEV_IF */
4528         } else {
4529                 WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err, *cookie));
4530         }
4531         return err;
4532 }
4533
4534 static s32
4535 wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
4536         bcm_struct_cfgdev *cfgdev, u64 cookie)
4537 {
4538         s32 err = 0;
4539
4540 #if defined(WL_CFG80211_P2P_DEV_IF)
4541         if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
4542                 WL_DBG((" enter ) on P2P dedicated discover interface\n"));
4543         }
4544 #else
4545         WL_DBG((" enter ) netdev_ifidx: %d \n", cfgdev->ifindex));
4546 #endif /* WL_CFG80211_P2P_DEV_IF */
4547         return err;
4548 }
4549
4550 static void
4551 wl_cfg80211_afx_handler(struct work_struct *work)
4552 {
4553         struct afx_hdl *afx_instance;
4554         struct wl_priv *wl = wlcfg_drv_priv;
4555         s32 ret = BCME_OK;
4556
4557         afx_instance = container_of(work, struct afx_hdl, work);
4558         if (afx_instance != NULL && wl->afx_hdl->is_active) {
4559                 if (wl->afx_hdl->is_listen && wl->afx_hdl->my_listen_chan) {
4560                         ret = wl_cfgp2p_discover_listen(wl, wl->afx_hdl->my_listen_chan,
4561                                 (100 * (1 + (RANDOM32() % 3)))); /* 100ms ~ 300ms */
4562                 } else {
4563                         ret = wl_cfgp2p_act_frm_search(wl, wl->afx_hdl->dev,
4564                                 wl->afx_hdl->bssidx, wl->afx_hdl->peer_listen_chan,
4565                                 NULL);
4566                 }
4567                 if (unlikely(ret != BCME_OK)) {
4568                         WL_ERR(("ERROR occurred! returned value is (%d)\n", ret));
4569                         if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL))
4570                                 complete(&wl->act_frm_scan);
4571                 }
4572         }
4573 }
4574
4575 static s32
4576 wl_cfg80211_af_searching_channel(struct wl_priv *wl, struct net_device *dev)
4577 {
4578         u32 max_retry = WL_CHANNEL_SYNC_RETRY;
4579
4580         if (dev == NULL)
4581                 return -1;
4582
4583         WL_DBG((" enter ) \n"));
4584
4585         wl_set_drv_status(wl, FINDING_COMMON_CHANNEL, dev);
4586         wl->afx_hdl->is_active = TRUE;
4587
4588         /* Loop to wait until we find a peer's channel or the
4589          * pending action frame tx is cancelled.
4590          */
4591         while ((wl->afx_hdl->retry < max_retry) &&
4592                 (wl->afx_hdl->peer_chan == WL_INVALID)) {
4593                 wl->afx_hdl->is_listen = FALSE;
4594                 wl_set_drv_status(wl, SCANNING, dev);
4595                 WL_DBG(("Scheduling the action frame for sending.. retry %d\n",
4596                         wl->afx_hdl->retry));
4597                 /* search peer on peer's listen channel */
4598                 schedule_work(&wl->afx_hdl->work);
4599                 wait_for_completion_timeout(&wl->act_frm_scan,
4600                         msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
4601
4602                 if ((wl->afx_hdl->peer_chan != WL_INVALID) ||
4603                         !(wl_get_drv_status(wl, FINDING_COMMON_CHANNEL, dev)))
4604                         break;
4605
4606                 if (wl->afx_hdl->my_listen_chan) {
4607                         WL_DBG(("Scheduling Listen peer in my listen channel = %d\n",
4608                                 wl->afx_hdl->my_listen_chan));
4609                         /* listen on my listen channel */
4610                         wl->afx_hdl->is_listen = TRUE;
4611                         schedule_work(&wl->afx_hdl->work);
4612                         wait_for_completion_timeout(&wl->act_frm_scan,
4613                                 msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
4614                 }
4615                 if ((wl->afx_hdl->peer_chan != WL_INVALID) ||
4616                         !(wl_get_drv_status(wl, FINDING_COMMON_CHANNEL, dev)))
4617                         break;
4618
4619                 wl->afx_hdl->retry++;
4620
4621                 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl);
4622         }
4623
4624         wl->afx_hdl->is_active = FALSE;
4625
4626         wl_clr_drv_status(wl, SCANNING, dev);
4627         wl_clr_drv_status(wl, FINDING_COMMON_CHANNEL, dev);
4628
4629         return (wl->afx_hdl->peer_chan);
4630 }
4631
4632 struct p2p_config_af_params {
4633         s32 max_tx_retry;       /* max tx retry count if tx no ack */
4634         /* To make sure to send successfully action frame, we have to turn off mpc
4635          * 0: off, 1: on,  (-1): do nothing
4636          */
4637         s32 mpc_onoff;
4638 #ifdef WL_CFG80211_SYNC_GON
4639         bool extra_listen;
4640 #endif
4641         bool search_channel;    /* 1: search peer's channel to send af */
4642 };
4643
4644 static s32
4645 wl_cfg80211_config_p2p_pub_af_tx(struct wiphy *wiphy,
4646         wl_action_frame_t *action_frame, wl_af_params_t *af_params,
4647         struct p2p_config_af_params *config_af_params)
4648 {
4649         s32 err = BCME_OK;
4650         struct wl_priv *wl = wiphy_priv(wiphy);
4651         wifi_p2p_pub_act_frame_t *act_frm =
4652                 (wifi_p2p_pub_act_frame_t *) (action_frame->data);
4653
4654         /* initialize default value */
4655 #ifdef WL_CFG80211_SYNC_GON
4656         config_af_params->extra_listen = true;
4657 #endif
4658         config_af_params->search_channel = false;
4659         config_af_params->max_tx_retry = WL_AF_TX_MAX_RETRY;
4660         config_af_params->mpc_onoff = -1;
4661         wl->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
4662
4663         switch (act_frm->subtype) {
4664         case P2P_PAF_GON_REQ: {
4665                 WL_DBG(("P2P: GO_NEG_PHASE status set \n"));
4666                 wl_set_p2p_status(wl, GO_NEG_PHASE);
4667
4668                 config_af_params->mpc_onoff = 0;
4669                 config_af_params->search_channel = true;
4670                 wl->next_af_subtype = act_frm->subtype + 1;
4671
4672                 /* increase dwell time to wait for RESP frame */
4673                 af_params->dwell_time = WL_MED_DWELL_TIME;
4674
4675                 break;
4676         }
4677         case P2P_PAF_GON_RSP: {
4678                 wl->next_af_subtype = act_frm->subtype + 1;
4679                 /* increase dwell time to wait for CONF frame */
4680                 af_params->dwell_time = WL_MED_DWELL_TIME + 100;
4681                 break;
4682         }
4683         case P2P_PAF_GON_CONF: {
4684                 /* If we reached till GO Neg confirmation reset the filter */
4685                 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
4686                 wl_clr_p2p_status(wl, GO_NEG_PHASE);
4687
4688                 /* turn on mpc again if go nego is done */
4689                 config_af_params->mpc_onoff = 1;
4690
4691                 /* minimize dwell time */
4692                 af_params->dwell_time = WL_MIN_DWELL_TIME;
4693
4694 #ifdef WL_CFG80211_SYNC_GON
4695                 config_af_params->extra_listen = false;
4696 #endif /* WL_CFG80211_SYNC_GON */
4697                 break;
4698         }
4699         case P2P_PAF_INVITE_REQ: {
4700                 config_af_params->search_channel = true;
4701                 wl->next_af_subtype = act_frm->subtype + 1;
4702
4703                 /* increase dwell time */
4704                 af_params->dwell_time = WL_MED_DWELL_TIME;
4705                 break;
4706         }
4707         case P2P_PAF_INVITE_RSP:
4708                 /* minimize dwell time */
4709                 af_params->dwell_time = WL_MIN_DWELL_TIME;
4710 #ifdef WL_CFG80211_SYNC_GON
4711                 config_af_params->extra_listen = false;
4712 #endif /* WL_CFG80211_SYNC_GON */
4713                 break;
4714         case P2P_PAF_DEVDIS_REQ: {
4715                 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
4716                         action_frame->len)) {
4717                         config_af_params->search_channel = true;
4718                 }
4719
4720                 wl->next_af_subtype = act_frm->subtype + 1;
4721                 /* maximize dwell time to wait for RESP frame */
4722                 af_params->dwell_time = WL_LONG_DWELL_TIME;
4723                 break;
4724         }
4725         case P2P_PAF_DEVDIS_RSP:
4726                 /* minimize dwell time */
4727                 af_params->dwell_time = WL_MIN_DWELL_TIME;
4728 #ifdef WL_CFG80211_SYNC_GON
4729                 config_af_params->extra_listen = false;
4730 #endif /* WL_CFG80211_SYNC_GON */
4731                 break;
4732         case P2P_PAF_PROVDIS_REQ: {
4733                 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
4734                         action_frame->len)) {
4735                         config_af_params->search_channel = true;
4736                 }
4737
4738                 config_af_params->mpc_onoff = 0;
4739                 wl->next_af_subtype = act_frm->subtype + 1;
4740                 /* increase dwell time to wait for RESP frame */
4741                 af_params->dwell_time = WL_MED_DWELL_TIME;
4742                 break;
4743         }
4744         case P2P_PAF_PROVDIS_RSP: {
4745                 wl->next_af_subtype = P2P_PAF_GON_REQ;
4746                 af_params->dwell_time = WL_MIN_DWELL_TIME;
4747 #ifdef WL_CFG80211_SYNC_GON
4748                 config_af_params->extra_listen = false;
4749 #endif /* WL_CFG80211_SYNC_GON */
4750                 break;
4751         }
4752         default:
4753                 WL_DBG(("Unknown p2p pub act frame subtype: %d\n",
4754                         act_frm->subtype));
4755                 err = BCME_BADARG;
4756         }
4757         return err;
4758 }
4759
4760
4761
4762 static bool
4763 wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev,
4764         bcm_struct_cfgdev *cfgdev, wl_af_params_t *af_params,
4765         wl_action_frame_t *action_frame, u16 action_frame_len, s32 bssidx)
4766 {
4767         struct wl_priv *wl = wiphy_priv(wiphy);
4768         bool ack = false;
4769         u8 category, action;
4770         s32 tx_retry;
4771         struct p2p_config_af_params config_af_params;
4772 #ifdef VSDB
4773         ulong off_chan_started_jiffies = 0;
4774 #endif
4775         dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
4776
4777
4778         category = action_frame->data[DOT11_ACTION_CAT_OFF];
4779         action = action_frame->data[DOT11_ACTION_ACT_OFF];
4780
4781         /* initialize variables */
4782         tx_retry = 0;
4783         wl->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
4784         config_af_params.max_tx_retry = WL_AF_TX_MAX_RETRY;
4785         config_af_params.mpc_onoff = -1;
4786         config_af_params.search_channel = false;
4787 #ifdef WL_CFG80211_SYNC_GON
4788         config_af_params.extra_listen = false;
4789 #endif
4790
4791         /* config parameters */
4792         /* Public Action Frame Process - DOT11_ACTION_CAT_PUBLIC */
4793         if (category == DOT11_ACTION_CAT_PUBLIC) {
4794                 if ((action == P2P_PUB_AF_ACTION) &&
4795                         (action_frame_len >= sizeof(wifi_p2p_pub_act_frame_t))) {
4796                         /* p2p public action frame process */
4797                         if (BCME_OK != wl_cfg80211_config_p2p_pub_af_tx(wiphy,
4798                                 action_frame, af_params, &config_af_params)) {
4799                                 WL_DBG(("Unknown subtype.\n"));
4800                         }
4801
4802                 } else if (action_frame_len >= sizeof(wifi_p2psd_gas_pub_act_frame_t)) {
4803                         /* service discovery process */
4804                         if (action == P2PSD_ACTION_ID_GAS_IREQ ||
4805                                 action == P2PSD_ACTION_ID_GAS_CREQ) {
4806                                 /* configure service discovery query frame */
4807
4808                                 config_af_params.search_channel = true;
4809
4810                                 /* save next af suptype to cancel remained dwell time */
4811                                 wl->next_af_subtype = action + 1;
4812
4813                                 af_params->dwell_time = WL_MED_DWELL_TIME;
4814                         } else if (action == P2PSD_ACTION_ID_GAS_IRESP ||
4815                                 action == P2PSD_ACTION_ID_GAS_CRESP) {
4816                                 /* configure service discovery response frame */
4817                                 af_params->dwell_time = WL_MIN_DWELL_TIME;
4818                         } else {
4819                                 WL_DBG(("Unknown action type: %d\n", action));
4820                         }
4821                 } else {
4822                         WL_DBG(("Unknown Frame: category 0x%x, action 0x%x, length %d\n",
4823                                 category, action, action_frame_len));
4824         }
4825         } else if (category == P2P_AF_CATEGORY) {
4826                 /* do not configure anything. it will be sent with a default configuration */
4827         } else {
4828                 WL_DBG(("Unknown Frame: category 0x%x, action 0x%x\n",
4829                         category, action));
4830                 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
4831                         wl_clr_drv_status(wl, SENDING_ACT_FRM, dev);
4832                         return false;
4833                 }
4834         }
4835
4836         /* To make sure to send successfully action frame, we have to turn off mpc */
4837         if (config_af_params.mpc_onoff == 0) {
4838                 wldev_iovar_setint(dev, "mpc", 0);
4839         }
4840
4841         /* validate channel and p2p ies */
4842         if (config_af_params.search_channel && IS_P2P_SOCIAL(af_params->channel) &&
4843                 wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len) {
4844                 config_af_params.search_channel = true;
4845         } else {
4846                 config_af_params.search_channel = false;
4847         }
4848
4849 #ifdef VSDB
4850         /* if connecting on primary iface, sleep for a while before sending af tx for VSDB */
4851         if (wl_get_drv_status(wl, CONNECTING, wl_to_prmry_ndev(wl))) {
4852                 OSL_SLEEP(50);
4853         }
4854 #endif
4855
4856         /* if scan is ongoing, abort current scan. */
4857         if (wl_get_drv_status_all(wl, SCANNING)) {
4858                 wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true);
4859         }
4860
4861
4862         /* set status and destination address before sending af */
4863         if (wl->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
4864                 /* set this status to cancel the remained dwell time in rx process */
4865                 wl_set_drv_status(wl, WAITING_NEXT_ACT_FRM, dev);
4866         }
4867         wl_set_drv_status(wl, SENDING_ACT_FRM, dev);
4868         memcpy(wl->afx_hdl->tx_dst_addr.octet,
4869                 af_params->action_frame.da.octet,
4870                 sizeof(wl->afx_hdl->tx_dst_addr.octet));
4871
4872         /* save af_params for rx process */
4873         wl->afx_hdl->pending_tx_act_frm = af_params;
4874
4875         /* search peer's channel */
4876         if (config_af_params.search_channel) {
4877                 /* initialize afx_hdl */
4878                 if (wl_cfgp2p_find_idx(wl, dev, &wl->afx_hdl->bssidx) != BCME_OK) {
4879                         WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4880                         goto exit;
4881                 }
4882                 wl->afx_hdl->dev = dev;
4883                 wl->afx_hdl->retry = 0;
4884                 wl->afx_hdl->peer_chan = WL_INVALID;
4885
4886                 if (wl_cfg80211_af_searching_channel(wl, dev) == WL_INVALID) {
4887                         WL_ERR(("couldn't find peer's channel.\n"));
4888                         wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len,
4889                                 af_params->channel);
4890                         goto exit;
4891                 }
4892
4893                 wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
4894                 /*
4895                  * Abort scan even for VSDB scenarios. Scan gets aborted in firmware
4896                  * but after the check of piggyback algorithm.
4897                  * To take care of current piggback algo, lets abort the scan here itself.
4898                  */
4899                 wl_notify_escan_complete(wl, dev, true, true);
4900                 /* Suspend P2P discovery's search-listen to prevent it from
4901                  * starting a scan or changing the channel.
4902                  */
4903                 wl_cfgp2p_discover_enable_search(wl, false);
4904
4905                 /* update channel */
4906                 af_params->channel = wl->afx_hdl->peer_chan;
4907         }
4908
4909 #ifdef VSDB
4910         off_chan_started_jiffies = jiffies;
4911 #endif /* VSDB */
4912
4913         wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len, af_params->channel);
4914
4915         /* Now send a tx action frame */
4916         ack = wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx) ? false : true;
4917
4918         /* if failed, retry it. tx_retry_max value is configure by .... */
4919         while ((ack == false) && (tx_retry++ < config_af_params.max_tx_retry)) {
4920 #ifdef VSDB
4921                 if (af_params->channel) {
4922                         if (jiffies_to_msecs(jiffies - off_chan_started_jiffies) >
4923                                 OFF_CHAN_TIME_THRESHOLD_MS) {
4924                                 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl);
4925                                 off_chan_started_jiffies = jiffies;
4926                         } else
4927                                 OSL_SLEEP(AF_RETRY_DELAY_TIME);
4928                 }
4929 #endif /* VSDB */
4930                 ack = wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx) ?
4931                         false : true;
4932         }
4933         if (ack == false) {
4934                 WL_ERR(("Failed to send Action Frame(retry %d)\n", tx_retry));
4935         }
4936 exit:
4937         /* Clear SENDING_ACT_FRM after all sending af is done */
4938         wl_clr_drv_status(wl, SENDING_ACT_FRM, dev);
4939
4940 #ifdef WL_CFG80211_SYNC_GON
4941         /* WAR: sometimes dongle does not keep the dwell time of 'actframe'.
4942          * if we coundn't get the next action response frame and dongle does not keep
4943          * the dwell time, go to listen state again to get next action response frame.
4944          */
4945         if (ack && config_af_params.extra_listen &&
4946                 wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM) &&
4947                 wl->af_sent_channel == wl->afx_hdl->my_listen_chan) {
4948                 s32 extar_listen_time;
4949
4950                 extar_listen_time = af_params->dwell_time -
4951                         jiffies_to_msecs(jiffies - wl->af_tx_sent_jiffies);
4952
4953                 if (extar_listen_time > 50) {
4954                         wl_set_drv_status(wl, WAITING_NEXT_ACT_FRM_LISTEN, dev);
4955                         WL_DBG(("Wait more time! actual af time:%d,"
4956                                 "calculated extar listen:%d\n",
4957                                 af_params->dwell_time, extar_listen_time));
4958                         if (wl_cfgp2p_discover_listen(wl, wl->af_sent_channel,
4959                                 extar_listen_time + 100) == BCME_OK) {
4960                                 wait_for_completion_timeout(&wl->wait_next_af,
4961                                         msecs_to_jiffies(extar_listen_time + 100 + 300));
4962                         }
4963                         wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM_LISTEN, dev);
4964                 }
4965         }
4966 #endif /* WL_CFG80211_SYNC_GON */
4967         wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, dev);
4968
4969         if (wl->afx_hdl->pending_tx_act_frm)
4970                 wl->afx_hdl->pending_tx_act_frm = NULL;
4971
4972         WL_INFO(("-- sending Action Frame is %s, listen chan: %d\n",
4973                 (ack) ? "Succeeded!!":"Failed!!", wl->afx_hdl->my_listen_chan));
4974
4975
4976         /* if all done, turn mpc on again */
4977         if (config_af_params.mpc_onoff == 1) {
4978                 wldev_iovar_setint(dev, "mpc", 1);
4979         }
4980
4981         return ack;
4982 }
4983
4984 #define MAX_NUM_OF_ASSOCIATED_DEV       64
4985 #if defined(WL_CFG80211_P2P_DEV_IF)
4986 static s32
4987 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
4988         struct ieee80211_channel *channel, bool offchan,
4989         unsigned int wait, const u8* buf, size_t len, bool no_cck,
4990         bool dont_wait_for_ack, u64 *cookie)
4991 #else
4992 static s32
4993 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
4994         struct ieee80211_channel *channel, bool offchan,
4995         enum nl80211_channel_type channel_type,
4996         bool channel_type_valid, unsigned int wait,
4997         const u8* buf, size_t len,
4998 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) || 0
4999         bool no_cck,
5000 #endif
5001 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || 0
5002         bool dont_wait_for_ack,
5003 #endif
5004         u64 *cookie)
5005 #endif /* WL_CFG80211_P2P_DEV_IF */
5006 {
5007         wl_action_frame_t *action_frame;
5008         wl_af_params_t *af_params;
5009         scb_val_t scb_val;
5010         const struct ieee80211_mgmt *mgmt;
5011         struct wl_priv *wl = wiphy_priv(wiphy);
5012         struct net_device *dev = NULL;
5013         s32 err = BCME_OK;
5014         s32 bssidx = 0;
5015         u32 id;
5016         bool ack = false;
5017         s8 eabuf[ETHER_ADDR_STR_LEN];
5018
5019         WL_DBG(("Enter \n"));
5020
5021         if (!wl)
5022                 return ERR_PTR(-EINVAL);
5023         dev = cfgdev_to_wlc_ndev(cfgdev, wl);
5024
5025         /* find bssidx based on dev */
5026         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
5027                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
5028                 return BCME_ERROR;
5029         }
5030         if (p2p_is_on(wl)) {
5031                 /* Suspend P2P discovery search-listen to prevent it from changing the
5032                  * channel.
5033                  */
5034                 if ((err = wl_cfgp2p_discover_enable_search(wl, false)) < 0) {
5035                         WL_ERR(("Can not disable discovery mode\n"));
5036                         return -EFAULT;
5037                 }
5038         }
5039         *cookie = 0;
5040         id = wl->send_action_id++;
5041         if (id == 0)
5042                 id = wl->send_action_id++;
5043         *cookie = id;
5044         mgmt = (const struct ieee80211_mgmt *)buf;
5045         if (ieee80211_is_mgmt(mgmt->frame_control)) {
5046                 if (ieee80211_is_probe_resp(mgmt->frame_control)) {
5047                         s32 ie_offset =  DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
5048                         s32 ie_len = len - ie_offset;
5049                         if (dev == wl_to_prmry_ndev(wl))
5050                                 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
5051                                 wl_cfgp2p_set_management_ie(wl, dev, bssidx,
5052                                 VNDR_IE_PRBRSP_FLAG, (u8 *)(buf + ie_offset), ie_len);
5053                         cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
5054                         goto exit;
5055                 } else if (ieee80211_is_disassoc(mgmt->frame_control) ||
5056                         ieee80211_is_deauth(mgmt->frame_control)) {
5057                         char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
5058                                 sizeof(struct ether_addr) + sizeof(uint)] = {0};
5059                         int num_associated = 0;
5060                         struct maclist *assoc_maclist = (struct maclist *)mac_buf;
5061                         if (!bcmp((const uint8 *)BSSID_BROADCAST,
5062                                 (const struct ether_addr *)mgmt->da, ETHER_ADDR_LEN)) {
5063                                 assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
5064                                 err = wldev_ioctl(dev, WLC_GET_ASSOCLIST,
5065                                         assoc_maclist, sizeof(mac_buf), false);
5066                                 if (err < 0)
5067                                         WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
5068                                 else
5069                                         num_associated = assoc_maclist->count;
5070                         }
5071                         memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN);
5072                         scb_val.val = mgmt->u.disassoc.reason_code;
5073                         err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
5074                                 sizeof(scb_val_t), true);
5075                         if (err < 0)
5076                                 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON error %d\n", err));
5077                         WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
5078                                 bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf),
5079                                 scb_val.val));
5080
5081                         if (num_associated > 0 && ETHER_ISBCAST(mgmt->da))
5082                                 wl_delay(400);
5083
5084                         cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
5085                         goto exit;
5086
5087                 } else if (ieee80211_is_action(mgmt->frame_control)) {
5088                         /* Abort the dwell time of any previous off-channel
5089                         * action frame that may be still in effect.  Sending
5090                         * off-channel action frames relies on the driver's
5091                         * scan engine.  If a previous off-channel action frame
5092                         * tx is still in progress (including the dwell time),
5093                         * then this new action frame will not be sent out.
5094                         */
5095 /* Do not abort scan for VSDB. Scan will be aborted in firmware if necessary.
5096  * And previous off-channel action frame must be ended before new af tx.
5097  */
5098 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5099                         wl_notify_escan_complete(wl, dev, true, true);
5100 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5101                 }
5102
5103         } else {
5104                 WL_ERR(("Driver only allows MGMT packet type\n"));
5105                 goto exit;
5106         }
5107
5108         af_params = (wl_af_params_t *) kzalloc(WL_WIFI_AF_PARAMS_SIZE, GFP_KERNEL);
5109
5110         if (af_params == NULL)
5111         {
5112                 WL_ERR(("unable to allocate frame\n"));
5113                 return -ENOMEM;
5114         }
5115
5116         action_frame = &af_params->action_frame;
5117
5118         /* Add the packet Id */
5119         action_frame->packetId = *cookie;
5120         WL_DBG(("action frame %d\n", action_frame->packetId));
5121         /* Add BSSID */
5122         memcpy(&action_frame->da, &mgmt->da[0], ETHER_ADDR_LEN);
5123         memcpy(&af_params->BSSID, &mgmt->bssid[0], ETHER_ADDR_LEN);
5124
5125         /* Add the length exepted for 802.11 header  */
5126         action_frame->len = len - DOT11_MGMT_HDR_LEN;
5127         WL_DBG(("action_frame->len: %d\n", action_frame->len));
5128
5129         /* Add the channel */
5130         af_params->channel =
5131                 ieee80211_frequency_to_channel(channel->center_freq);
5132
5133         /* Save listen_chan for searching common channel */
5134         wl->afx_hdl->peer_listen_chan = af_params->channel;
5135         WL_DBG(("channel from upper layer %d\n", wl->afx_hdl->peer_listen_chan));
5136
5137         /* Add the default dwell time
5138          * Dwell time to stay off-channel to wait for a response action frame
5139          * after transmitting an GO Negotiation action frame
5140          */
5141         af_params->dwell_time = WL_DWELL_TIME;
5142
5143         memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len);
5144
5145         ack = wl_cfg80211_send_action_frame(wiphy, dev, cfgdev, af_params,
5146                 action_frame, action_frame->len, bssidx);
5147         cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, ack, GFP_KERNEL);
5148
5149         kfree(af_params);
5150 exit:
5151         return err;
5152 }
5153
5154
5155 static void
5156 wl_cfg80211_mgmt_frame_register(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
5157         u16 frame_type, bool reg)
5158 {
5159
5160         WL_DBG(("frame_type: %x, reg: %d\n", frame_type, reg));
5161
5162         if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
5163                 return;
5164
5165         return;
5166 }
5167
5168
5169 static s32
5170 wl_cfg80211_change_bss(struct wiphy *wiphy,
5171         struct net_device *dev,
5172         struct bss_parameters *params)
5173 {
5174         if (params->use_cts_prot >= 0) {
5175         }
5176
5177         if (params->use_short_preamble >= 0) {
5178         }
5179
5180         if (params->use_short_slot_time >= 0) {
5181         }
5182
5183         if (params->basic_rates) {
5184         }
5185
5186         if (params->ap_isolate >= 0) {
5187         }
5188
5189         if (params->ht_opmode >= 0) {
5190         }
5191
5192         return 0;
5193 }
5194
5195 static s32
5196 wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
5197         struct ieee80211_channel *chan,
5198         enum nl80211_channel_type channel_type)
5199 {
5200         s32 _chan;
5201         chanspec_t chspec = 0;
5202         chanspec_t fw_chspec = 0;
5203         u32 bw = WL_CHANSPEC_BW_20;
5204
5205         s32 err = BCME_OK;
5206         s32 bw_cap = 0;
5207         struct {
5208                 u32 band;
5209                 u32 bw_cap;
5210         } param = {0, 0};
5211         struct wl_priv *wl = wiphy_priv(wiphy);
5212
5213         if (!wl)
5214                 return ERR_PTR(-EINVAL);
5215         dev = ndev_to_wlc_ndev(dev, wl);
5216         _chan = ieee80211_frequency_to_channel(chan->center_freq);
5217         WL_ERR(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
5218                 dev->ifindex, channel_type, _chan));
5219
5220
5221         if (chan->band == IEEE80211_BAND_5GHZ) {
5222                 param.band = WLC_BAND_5G;
5223                 err = wldev_iovar_getbuf(dev, "bw_cap", &param, sizeof(param),
5224                         wl->ioctl_buf, WLC_IOCTL_SMLEN, &wl->ioctl_buf_sync);
5225                 if (err) {
5226                         if (err != BCME_UNSUPPORTED) {
5227                                 WL_ERR(("bw_cap failed, %d\n", err));
5228                                 return err;
5229                         } else {
5230                                 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
5231                                 if (err) {
5232                                         WL_ERR(("error get mimo_bw_cap (%d)\n", err));
5233                                 }
5234                                 if (bw_cap != WLC_N_BW_20ALL)
5235                                         bw = WL_CHANSPEC_BW_40;
5236                         }
5237                 } else {
5238                         if (WL_BW_CAP_80MHZ(wl->ioctl_buf[0]))
5239                                 bw = WL_CHANSPEC_BW_80;
5240                         else if (WL_BW_CAP_40MHZ(wl->ioctl_buf[0]))
5241                                 bw = WL_CHANSPEC_BW_40;
5242                         else
5243                                 bw = WL_CHANSPEC_BW_20;
5244
5245                 }
5246
5247         } else if (chan->band == IEEE80211_BAND_2GHZ)
5248                 bw = WL_CHANSPEC_BW_20;
5249 set_channel:
5250         chspec = wf_channel2chspec(_chan, bw);
5251         if (wf_chspec_valid(chspec)) {
5252                 fw_chspec = wl_chspec_host_to_driver(chspec);
5253                 if (fw_chspec != INVCHANSPEC) {
5254                         if ((err = wldev_iovar_setint(dev, "chanspec",
5255                                 fw_chspec)) == BCME_BADCHAN) {
5256                                 if (bw == WL_CHANSPEC_BW_80)
5257                                         goto change_bw;
5258                                 err = wldev_ioctl(dev, WLC_SET_CHANNEL,
5259                                         &_chan, sizeof(_chan), true);
5260                                 if (err < 0) {
5261                                         WL_ERR(("WLC_SET_CHANNEL error %d"
5262                                         "chip may not be supporting this channel\n", err));
5263                                 }
5264                         } else if (err) {
5265                                 WL_ERR(("failed to set chanspec error %d\n", err));
5266                         }
5267                 } else {
5268                         WL_ERR(("failed to convert host chanspec to fw chanspec\n"));
5269                         err = BCME_ERROR;
5270                 }
5271         } else {
5272 change_bw:
5273                 if (bw == WL_CHANSPEC_BW_80)
5274                         bw = WL_CHANSPEC_BW_40;
5275                 else if (bw == WL_CHANSPEC_BW_40)
5276                         bw = WL_CHANSPEC_BW_20;
5277                 else
5278                         bw = 0;
5279                 if (bw)
5280                         goto set_channel;
5281                 WL_ERR(("Invalid chanspec 0x%x\n", chspec));
5282                 err = BCME_ERROR;
5283         }
5284         return err;
5285 }
5286
5287 static s32
5288 wl_validate_opensecurity(struct net_device *dev, s32 bssidx)
5289 {
5290         s32 err = BCME_OK;
5291
5292         /* set auth */
5293         err = wldev_iovar_setint_bsscfg(dev, "auth", 0, bssidx);
5294         if (err < 0) {
5295                 WL_ERR(("auth error %d\n", err));
5296                 return BCME_ERROR;
5297         }
5298         /* set wsec */
5299         err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
5300         if (err < 0) {
5301                 WL_ERR(("wsec error %d\n", err));
5302                 return BCME_ERROR;
5303         }
5304         /* set upper-layer auth */
5305         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", WPA_AUTH_NONE, bssidx);
5306         if (err < 0) {
5307                 WL_ERR(("wpa_auth error %d\n", err));
5308                 return BCME_ERROR;
5309         }
5310
5311         return 0;
5312 }
5313
5314 static s32
5315 wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
5316 {
5317         s32 len = 0;
5318         s32 err = BCME_OK;
5319         u16 auth = 0; /* d11 open authentication */
5320         u32 wsec;
5321         u32 pval = 0;
5322         u32 gval = 0;
5323         u32 wpa_auth = 0;
5324         wpa_suite_mcast_t *mcast;
5325         wpa_suite_ucast_t *ucast;
5326         wpa_suite_auth_key_mgmt_t *mgmt;
5327
5328         u16 suite_count;
5329         u8 rsn_cap[2];
5330         u32 wme_bss_disable;
5331
5332         if (wpa2ie == NULL)
5333                 goto exit;
5334
5335         WL_DBG(("Enter \n"));
5336         len =  wpa2ie->len;
5337         /* check the mcast cipher */
5338         mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
5339         switch (mcast->type) {
5340                 case WPA_CIPHER_NONE:
5341                         gval = 0;
5342                         break;
5343                 case WPA_CIPHER_WEP_40:
5344                 case WPA_CIPHER_WEP_104:
5345                         gval = WEP_ENABLED;
5346                         break;
5347                 case WPA_CIPHER_TKIP:
5348                         gval = TKIP_ENABLED;
5349                         break;
5350                 case WPA_CIPHER_AES_CCM:
5351                         gval = AES_ENABLED;
5352                         break;
5353                 default:
5354                         WL_ERR(("No Security Info\n"));
5355                         break;
5356         }
5357         if ((len -= WPA_SUITE_LEN) <= 0)
5358                 return BCME_BADLEN;
5359
5360         /* check the unicast cipher */
5361         ucast = (wpa_suite_ucast_t *)&mcast[1];
5362         suite_count = ltoh16_ua(&ucast->count);
5363         switch (ucast->list[0].type) {
5364                 case WPA_CIPHER_NONE:
5365                         pval = 0;
5366                         break;
5367                 case WPA_CIPHER_WEP_40:
5368                 case WPA_CIPHER_WEP_104:
5369                         pval = WEP_ENABLED;
5370                         break;
5371                 case WPA_CIPHER_TKIP:
5372                         pval = TKIP_ENABLED;
5373                         break;
5374                 case WPA_CIPHER_AES_CCM:
5375                         pval = AES_ENABLED;
5376                         break;
5377                 default:
5378                         WL_ERR(("No Security Info\n"));
5379         }
5380         if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
5381                 return BCME_BADLEN;
5382
5383         /* FOR WPS , set SEC_OW_ENABLED */
5384         wsec = (pval | gval | SES_OW_ENABLED);
5385         /* check the AKM */
5386         mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
5387         suite_count = ltoh16_ua(&mgmt->count);
5388         switch (mgmt->list[0].type) {
5389                 case RSN_AKM_NONE:
5390                         wpa_auth = WPA_AUTH_NONE;
5391                         break;
5392                 case RSN_AKM_UNSPECIFIED:
5393                         wpa_auth = WPA2_AUTH_UNSPECIFIED;
5394                         break;
5395                 case RSN_AKM_PSK:
5396                         wpa_auth = WPA2_AUTH_PSK;
5397                         break;
5398                 default:
5399                         WL_ERR(("No Key Mgmt Info\n"));
5400         }
5401
5402         if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
5403                 rsn_cap[0] = *(u8 *)&mgmt->list[suite_count];
5404                 rsn_cap[1] = *((u8 *)&mgmt->list[suite_count] + 1);
5405
5406                 if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
5407                         wme_bss_disable = 0;
5408                 } else {
5409                         wme_bss_disable = 1;
5410                 }
5411
5412                 /* set wme_bss_disable to sync RSN Capabilities */
5413                 err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
5414                 if (err < 0) {
5415                         WL_ERR(("wme_bss_disable error %d\n", err));
5416                         return BCME_ERROR;
5417                 }
5418         } else {
5419                 WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
5420         }
5421
5422         /* set auth */
5423         err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
5424         if (err < 0) {
5425                 WL_ERR(("auth error %d\n", err));
5426                 return BCME_ERROR;
5427         }
5428         /* set wsec */
5429         err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
5430         if (err < 0) {
5431                 WL_ERR(("wsec error %d\n", err));
5432                 return BCME_ERROR;
5433         }
5434         /* set upper-layer auth */
5435         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
5436         if (err < 0) {
5437                 WL_ERR(("wpa_auth error %d\n", err));
5438                 return BCME_ERROR;
5439         }
5440 exit:
5441         return 0;
5442 }
5443
5444 static s32
5445 wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx)
5446 {
5447         wpa_suite_mcast_t *mcast;
5448         wpa_suite_ucast_t *ucast;
5449         wpa_suite_auth_key_mgmt_t *mgmt;
5450         u16 auth = 0; /* d11 open authentication */
5451         u16 count;
5452         s32 err = BCME_OK;
5453         s32 len = 0;
5454         u32 i;
5455         u32 wsec;
5456         u32 pval = 0;
5457         u32 gval = 0;
5458         u32 wpa_auth = 0;
5459         u32 tmp = 0;
5460
5461         if (wpaie == NULL)
5462                 goto exit;
5463         WL_DBG(("Enter \n"));
5464         len = wpaie->length;    /* value length */
5465         len -= WPA_IE_TAG_FIXED_LEN;
5466         /* check for multicast cipher suite */
5467         if (len < WPA_SUITE_LEN) {
5468                 WL_INFO(("no multicast cipher suite\n"));
5469                 goto exit;
5470         }
5471
5472         /* pick up multicast cipher */
5473         mcast = (wpa_suite_mcast_t *)&wpaie[1];
5474         len -= WPA_SUITE_LEN;
5475         if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
5476                 if (IS_WPA_CIPHER(mcast->type)) {
5477                         tmp = 0;
5478                         switch (mcast->type) {
5479                                 case WPA_CIPHER_NONE:
5480                                         tmp = 0;
5481                                         break;
5482                                 case WPA_CIPHER_WEP_40:
5483                                 case WPA_CIPHER_WEP_104:
5484                                         tmp = WEP_ENABLED;
5485                                         break;
5486                                 case WPA_CIPHER_TKIP:
5487                                         tmp = TKIP_ENABLED;
5488                                         break;
5489                                 case WPA_CIPHER_AES_CCM:
5490                                         tmp = AES_ENABLED;
5491                                         break;
5492                                 default:
5493                                         WL_ERR(("No Security Info\n"));
5494                         }
5495                         gval |= tmp;
5496                 }
5497         }
5498         /* Check for unicast suite(s) */
5499         if (len < WPA_IE_SUITE_COUNT_LEN) {
5500                 WL_INFO(("no unicast suite\n"));
5501                 goto exit;
5502         }
5503         /* walk thru unicast cipher list and pick up what we recognize */
5504         ucast = (wpa_suite_ucast_t *)&mcast[1];
5505         count = ltoh16_ua(&ucast->count);
5506         len -= WPA_IE_SUITE_COUNT_LEN;
5507         for (i = 0; i < count && len >= WPA_SUITE_LEN;
5508                 i++, len -= WPA_SUITE_LEN) {
5509                 if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
5510                         if (IS_WPA_CIPHER(ucast->list[i].type)) {
5511                                 tmp = 0;
5512                                 switch (ucast->list[i].type) {
5513                                         case WPA_CIPHER_NONE:
5514                                                 tmp = 0;
5515                                                 break;
5516                                         case WPA_CIPHER_WEP_40:
5517                                         case WPA_CIPHER_WEP_104:
5518                                                 tmp = WEP_ENABLED;
5519                                                 break;
5520                                         case WPA_CIPHER_TKIP:
5521                                                 tmp = TKIP_ENABLED;
5522                                                 break;
5523                                         case WPA_CIPHER_AES_CCM:
5524                                                 tmp = AES_ENABLED;
5525                                                 break;
5526                                         default:
5527                                                 WL_ERR(("No Security Info\n"));
5528                                 }
5529                                 pval |= tmp;
5530                         }
5531                 }
5532         }
5533         len -= (count - i) * WPA_SUITE_LEN;
5534         /* Check for auth key management suite(s) */
5535         if (len < WPA_IE_SUITE_COUNT_LEN) {
5536                 WL_INFO((" no auth key mgmt suite\n"));
5537                 goto exit;
5538         }
5539         /* walk thru auth management suite list and pick up what we recognize */
5540         mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
5541         count = ltoh16_ua(&mgmt->count);
5542         len -= WPA_IE_SUITE_COUNT_LEN;
5543         for (i = 0; i < count && len >= WPA_SUITE_LEN;
5544                 i++, len -= WPA_SUITE_LEN) {
5545                 if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
5546                         if (IS_WPA_AKM(mgmt->list[i].type)) {
5547                                 tmp = 0;
5548                                 switch (mgmt->list[i].type) {
5549                                         case RSN_AKM_NONE:
5550                                                 tmp = WPA_AUTH_NONE;
5551                                                 break;
5552                                         case RSN_AKM_UNSPECIFIED:
5553                                                 tmp = WPA_AUTH_UNSPECIFIED;
5554                                                 break;
5555                                         case RSN_AKM_PSK:
5556                                                 tmp = WPA_AUTH_PSK;
5557                                                 break;
5558                                         default:
5559                                                 WL_ERR(("No Key Mgmt Info\n"));
5560                                 }
5561                                 wpa_auth |= tmp;
5562                         }
5563                 }
5564
5565         }
5566         /* FOR WPS , set SEC_OW_ENABLED */
5567         wsec = (pval | gval | SES_OW_ENABLED);
5568         /* set auth */
5569         err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
5570         if (err < 0) {
5571                 WL_ERR(("auth error %d\n", err));
5572                 return BCME_ERROR;
5573         }
5574         /* set wsec */
5575         err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
5576         if (err < 0) {
5577                 WL_ERR(("wsec error %d\n", err));
5578                 return BCME_ERROR;
5579         }
5580         /* set upper-layer auth */
5581         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
5582         if (err < 0) {
5583                 WL_ERR(("wpa_auth error %d\n", err));
5584                 return BCME_ERROR;
5585         }
5586 exit:
5587         return 0;
5588 }
5589
5590 static s32
5591 wl_cfg80211_bcn_validate_sec(
5592         struct net_device *dev,
5593         struct parsed_ies *ies,
5594         u32 dev_role,
5595         s32 bssidx)
5596 {
5597         struct wl_priv *wl = wlcfg_drv_priv;
5598
5599         if (dev_role == NL80211_IFTYPE_P2P_GO && (ies->wpa2_ie)) {
5600                 /* For P2P GO, the sec type is WPA2-PSK */
5601                 WL_DBG(("P2P GO: validating wpa2_ie"));
5602                 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0)
5603                         return BCME_ERROR;
5604
5605         } else if (dev_role == NL80211_IFTYPE_AP) {
5606
5607                 WL_DBG(("SoftAP: validating security"));
5608                 /* If wpa2_ie or wpa_ie is present validate it */
5609                 if ((ies->wpa2_ie || ies->wpa_ie) &&
5610                         ((wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0 ||
5611                         wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0))) {
5612                         wl->ap_info->security_mode = false;
5613                         return BCME_ERROR;
5614                 }
5615
5616                 wl->ap_info->security_mode = true;
5617                 if (wl->ap_info->rsn_ie) {
5618                         kfree(wl->ap_info->rsn_ie);
5619                         wl->ap_info->rsn_ie = NULL;
5620                 }
5621                 if (wl->ap_info->wpa_ie) {
5622                         kfree(wl->ap_info->wpa_ie);
5623                         wl->ap_info->wpa_ie = NULL;
5624                 }
5625                 if (wl->ap_info->wps_ie) {
5626                         kfree(wl->ap_info->wps_ie);
5627                         wl->ap_info->wps_ie = NULL;
5628                 }
5629                 if (ies->wpa_ie != NULL) {
5630                         /* WPAIE */
5631                         wl->ap_info->rsn_ie = NULL;
5632                         wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie,
5633                                 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
5634                                 GFP_KERNEL);
5635                 } else if (ies->wpa2_ie != NULL) {
5636                         /* RSNIE */
5637                         wl->ap_info->wpa_ie = NULL;
5638                         wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie,
5639                                 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
5640                                 GFP_KERNEL);
5641                 }
5642
5643                 if (!ies->wpa2_ie && !ies->wpa_ie) {
5644                         wl_validate_opensecurity(dev, bssidx);
5645                         wl->ap_info->security_mode = false;
5646                 }
5647
5648                 if (ies->wps_ie) {
5649                         wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
5650                 }
5651         }
5652
5653         return 0;
5654
5655 }
5656
5657 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
5658 static s32 wl_cfg80211_bcn_set_params(
5659         struct cfg80211_ap_settings *info,
5660         struct net_device *dev,
5661         u32 dev_role, s32 bssidx)
5662 {
5663         struct wl_priv *wl = wlcfg_drv_priv;
5664         s32 err = BCME_OK;
5665
5666         WL_DBG(("interval (%d) \ndtim_period (%d) \n",
5667                 info->beacon_interval, info->dtim_period));
5668
5669         if (info->beacon_interval) {
5670                 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
5671                         &info->beacon_interval, sizeof(s32), true)) < 0) {
5672                         WL_ERR(("Beacon Interval Set Error, %d\n", err));
5673                         return err;
5674                 }
5675         }
5676
5677         if (info->dtim_period) {
5678                 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
5679                         &info->dtim_period, sizeof(s32), true)) < 0) {
5680                         WL_ERR(("DTIM Interval Set Error, %d\n", err));
5681                         return err;
5682                 }
5683         }
5684
5685         if ((info->ssid) && (info->ssid_len > 0) &&
5686                 (info->ssid_len <= 32)) {
5687                 WL_DBG(("SSID (%s) len:%d \n", info->ssid, info->ssid_len));
5688                 if (dev_role == NL80211_IFTYPE_AP) {
5689                         /* Store the hostapd SSID */
5690                         memset(wl->hostapd_ssid.SSID, 0x00, 32);
5691                         memcpy(wl->hostapd_ssid.SSID, info->ssid, info->ssid_len);
5692                         wl->hostapd_ssid.SSID_len = info->ssid_len;
5693                 } else {
5694                                 /* P2P GO */
5695                         memset(wl->p2p->ssid.SSID, 0x00, 32);
5696                         memcpy(wl->p2p->ssid.SSID, info->ssid, info->ssid_len);
5697                         wl->p2p->ssid.SSID_len = info->ssid_len;
5698                 }
5699         }
5700
5701         if (info->hidden_ssid) {
5702                 if ((err = wldev_iovar_setint(dev, "closednet", 1)) < 0)
5703                         WL_ERR(("failed to set hidden : %d\n", err));
5704                 WL_DBG(("hidden_ssid_enum_val: %d \n", info->hidden_ssid));
5705         }
5706
5707         return err;
5708 }
5709 #endif 
5710
5711 static s32
5712 wl_cfg80211_parse_ies(u8 *ptr, u32 len, struct parsed_ies *ies)
5713 {
5714         s32 err = BCME_OK;
5715
5716         memset(ies, 0, sizeof(struct parsed_ies));
5717
5718         /* find the WPSIE */
5719         if ((ies->wps_ie = wl_cfgp2p_find_wpsie(ptr, len)) != NULL) {
5720                 WL_DBG(("WPSIE in beacon \n"));
5721                 ies->wps_ie_len = ies->wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
5722         } else {
5723                 WL_ERR(("No WPSIE in beacon \n"));
5724         }
5725
5726         /* find the RSN_IE */
5727         if ((ies->wpa2_ie = bcm_parse_tlvs(ptr, len,
5728                 DOT11_MNG_RSN_ID)) != NULL) {
5729                 WL_DBG((" WPA2 IE found\n"));
5730                 ies->wpa2_ie_len = ies->wpa2_ie->len;
5731         }
5732
5733         /* find the WPA_IE */
5734         if ((ies->wpa_ie = wl_cfgp2p_find_wpaie(ptr, len)) != NULL) {
5735                 WL_DBG((" WPA found\n"));
5736                 ies->wpa_ie_len = ies->wpa_ie->length;
5737         }
5738
5739         return err;
5740
5741 }
5742
5743 static s32
5744 wl_cfg80211_bcn_bringup_ap(
5745         struct net_device *dev,
5746         struct parsed_ies *ies,
5747         u32 dev_role, s32 bssidx)
5748 {
5749         struct wl_priv *wl = wlcfg_drv_priv;
5750         struct wl_join_params join_params;
5751         bool is_bssup = false;
5752         s32 infra = 1;
5753         s32 join_params_size = 0;
5754         s32 ap = 1;
5755 #ifdef DISABLE_11H_SOFTAP
5756         s32 spect = 0;
5757 #endif /* DISABLE_11H_SOFTAP */
5758         s32 err = BCME_OK;
5759
5760         WL_DBG(("Enter dev_role: %d\n", dev_role));
5761
5762         /* Common code for SoftAP and P2P GO */
5763         wldev_iovar_setint(dev, "mpc", 0);
5764
5765         if (dev_role == NL80211_IFTYPE_P2P_GO) {
5766                 is_bssup = wl_cfgp2p_bss_isup(dev, bssidx);
5767                 if (!is_bssup && (ies->wpa2_ie != NULL)) {
5768
5769                         err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
5770                         if (err < 0) {
5771                                 WL_ERR(("SET INFRA error %d\n", err));
5772                                 goto exit;
5773                         }
5774
5775                         err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &wl->p2p->ssid,
5776                                 sizeof(wl->p2p->ssid), wl->ioctl_buf, WLC_IOCTL_MAXLEN,
5777                                 bssidx, &wl->ioctl_buf_sync);
5778                         if (err < 0) {
5779                                 WL_ERR(("GO SSID setting error %d\n", err));
5780                                 goto exit;
5781                         }
5782
5783                         /* Do abort scan before creating GO */
5784                         wl_cfg80211_scan_abort(wl);
5785
5786                         if ((err = wl_cfgp2p_bss(wl, dev, bssidx, 1)) < 0) {
5787                                 WL_ERR(("GO Bring up error %d\n", err));
5788                                 goto exit;
5789                         }
5790                 } else
5791                         WL_DBG(("Bss is already up\n"));
5792         } else if ((dev_role == NL80211_IFTYPE_AP) &&
5793                 (wl_get_drv_status(wl, AP_CREATING, dev))) {
5794                 /* Device role SoftAP */
5795                 err = wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), true);
5796                 if (err < 0) {
5797                         WL_ERR(("WLC_DOWN error %d\n", err));
5798                         goto exit;
5799                 }
5800                 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
5801                 if (err < 0) {
5802                         WL_ERR(("SET INFRA error %d\n", err));
5803                         goto exit;
5804                 }
5805                 if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
5806                         WL_ERR(("setting AP mode failed %d \n", err));
5807                         goto exit;
5808                 }
5809 #ifdef DISABLE_11H_SOFTAP
5810                 err = wldev_ioctl(dev, WLC_SET_SPECT_MANAGMENT,
5811                         &spect, sizeof(s32), true);
5812                 if (err < 0) {
5813                         WL_ERR(("SET SPECT_MANAGMENT error %d\n", err));
5814                         goto exit;
5815                 }
5816 #endif /* DISABLE_11H_SOFTAP */
5817
5818                 err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
5819                 if (unlikely(err)) {
5820                         WL_ERR(("WLC_UP error (%d)\n", err));
5821                         goto exit;
5822                 }
5823
5824                 memset(&join_params, 0, sizeof(join_params));
5825                 /* join parameters starts with ssid */
5826                 join_params_size = sizeof(join_params.ssid);
5827                 memcpy(join_params.ssid.SSID, wl->hostapd_ssid.SSID,
5828                         wl->hostapd_ssid.SSID_len);
5829                 join_params.ssid.SSID_len = htod32(wl->hostapd_ssid.SSID_len);
5830
5831                 /* create softap */
5832                 if ((err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
5833                         join_params_size, true)) == 0) {
5834                         WL_DBG(("SoftAP set SSID (%s) success\n", join_params.ssid.SSID));
5835                         wl_clr_drv_status(wl, AP_CREATING, dev);
5836                         wl_set_drv_status(wl, AP_CREATED, dev);
5837                 }
5838         }
5839
5840
5841 exit:
5842         return err;
5843 }
5844
5845 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
5846 s32
5847 wl_cfg80211_parse_ap_ies(
5848         struct net_device *dev,
5849         struct cfg80211_beacon_data *info,
5850         struct parsed_ies *ies)
5851 {
5852         struct parsed_ies prb_ies;
5853         struct wl_priv *wl = wlcfg_drv_priv;
5854         dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
5855         u8 *vndr = NULL;
5856         u32 vndr_ie_len = 0;
5857         s32 err = BCME_OK;
5858
5859         /* Parse Beacon IEs */
5860         if (wl_cfg80211_parse_ies((u8 *)info->tail,
5861                 info->tail_len, ies) < 0) {
5862                 WL_ERR(("Beacon get IEs failed \n"));
5863                 err = -EINVAL;
5864                 goto fail;
5865         }
5866
5867         vndr = (u8 *)info->proberesp_ies;
5868         vndr_ie_len = info->proberesp_ies_len;
5869
5870         if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
5871                 /* SoftAP mode */
5872                 struct ieee80211_mgmt *mgmt;
5873                 mgmt = (struct ieee80211_mgmt *)info->probe_resp;
5874                 if (mgmt != NULL) {
5875                         vndr = (u8 *)&mgmt->u.probe_resp.variable;
5876                         vndr_ie_len = info->probe_resp_len -
5877                                 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
5878                 }
5879         }
5880
5881         /* Parse Probe Response IEs */
5882         if (wl_cfg80211_parse_ies(vndr, vndr_ie_len, &prb_ies) < 0) {
5883                 WL_ERR(("PROBE RESP get IEs failed \n"));
5884                 err = -EINVAL;
5885         }
5886
5887 fail:
5888
5889         return err;
5890 }
5891
5892 s32
5893 wl_cfg80211_set_ies(
5894         struct net_device *dev,
5895         struct cfg80211_beacon_data *info,
5896         s32 bssidx)
5897 {
5898         struct wl_priv *wl = wlcfg_drv_priv;
5899         dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
5900         u8 *vndr = NULL;
5901         u32 vndr_ie_len = 0;
5902         s32 err = BCME_OK;
5903
5904         /* Set Beacon IEs to FW */
5905         if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx,
5906                 VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
5907                 info->tail_len)) < 0) {
5908                 WL_ERR(("Set Beacon IE Failed \n"));
5909         } else {
5910                 WL_DBG(("Applied Vndr IEs for Beacon \n"));
5911         }
5912
5913         vndr = (u8 *)info->proberesp_ies;
5914         vndr_ie_len = info->proberesp_ies_len;
5915
5916         if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
5917                 /* SoftAP mode */
5918                 struct ieee80211_mgmt *mgmt;
5919                 mgmt = (struct ieee80211_mgmt *)info->probe_resp;
5920                 if (mgmt != NULL) {
5921                         vndr = (u8 *)&mgmt->u.probe_resp.variable;
5922                         vndr_ie_len = info->probe_resp_len -
5923                                 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
5924                 }
5925         }
5926
5927         /* Set Probe Response IEs to FW */
5928         if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx,
5929                 VNDR_IE_PRBRSP_FLAG, vndr, vndr_ie_len)) < 0) {
5930                 WL_ERR(("Set Probe Resp IE Failed \n"));
5931         } else {
5932                 WL_DBG(("Applied Vndr IEs for Probe Resp \n"));
5933         }
5934
5935         return err;
5936 }
5937 #endif 
5938
5939 static s32 wl_cfg80211_hostapd_sec(
5940         struct net_device *dev,
5941         struct parsed_ies *ies,
5942         s32 bssidx)
5943 {
5944         bool update_bss = 0;
5945         struct wl_priv *wl = wlcfg_drv_priv;
5946
5947
5948         if (ies->wps_ie) {
5949                 if (wl->ap_info->wps_ie &&
5950                         memcmp(wl->ap_info->wps_ie, ies->wps_ie, ies->wps_ie_len)) {
5951                         WL_DBG((" WPS IE is changed\n"));
5952                         kfree(wl->ap_info->wps_ie);
5953                         wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
5954                 } else if (wl->ap_info->wps_ie == NULL) {
5955                         WL_DBG((" WPS IE is added\n"));
5956                         wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
5957                 }
5958                 if ((ies->wpa_ie != NULL || ies->wpa2_ie != NULL)) {
5959                         if (!wl->ap_info->security_mode) {
5960                                 /* change from open mode to security mode */
5961                                 update_bss = true;
5962                                 if (ies->wpa_ie != NULL) {
5963                                         wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie,
5964                                         ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
5965                                         GFP_KERNEL);
5966                                 } else {
5967                                         wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie,
5968                                         ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
5969                                         GFP_KERNEL);
5970                                 }
5971                         } else if (wl->ap_info->wpa_ie) {
5972                                 /* change from WPA2 mode to WPA mode */
5973                                 if (ies->wpa_ie != NULL) {
5974                                         update_bss = true;
5975                                         kfree(wl->ap_info->rsn_ie);
5976                                         wl->ap_info->rsn_ie = NULL;
5977                                         wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie,
5978                                         ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
5979                                         GFP_KERNEL);
5980                                 } else if (memcmp(wl->ap_info->rsn_ie,
5981                                         ies->wpa2_ie, ies->wpa2_ie->len
5982                                         + WPA_RSN_IE_TAG_FIXED_LEN)) {
5983                                         update_bss = true;
5984                                         kfree(wl->ap_info->rsn_ie);
5985                                         wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie,
5986                                         ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
5987                                         GFP_KERNEL);
5988                                         wl->ap_info->wpa_ie = NULL;
5989                                 }
5990                         }
5991                         if (update_bss) {
5992                                 wl->ap_info->security_mode = true;
5993                                 wl_cfgp2p_bss(wl, dev, bssidx, 0);
5994                                 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0 ||
5995                                         wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0) {
5996                                         return BCME_ERROR;
5997                                 }
5998                                 wl_cfgp2p_bss(wl, dev, bssidx, 1);
5999                         }
6000                 }
6001         } else {
6002                 WL_ERR(("No WPSIE in beacon \n"));
6003         }
6004         return 0;
6005 }
6006
6007 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
6008         2, 0))
6009 static s32
6010 wl_cfg80211_del_station(
6011         struct wiphy *wiphy,
6012         struct net_device *ndev,
6013         u8* mac_addr)
6014 {
6015         struct net_device *dev;
6016         struct wl_priv *wl = wiphy_priv(wiphy);
6017         scb_val_t scb_val;
6018         s8 eabuf[ETHER_ADDR_STR_LEN];
6019         int err;
6020         char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
6021                 sizeof(struct ether_addr) + sizeof(uint)] = {0};
6022         struct maclist *assoc_maclist = (struct maclist *)mac_buf;
6023         int num_associated = 0;
6024
6025         WL_DBG(("Entry\n"));
6026         if (mac_addr == NULL) {
6027                 WL_DBG(("mac_addr is NULL ignore it\n"));
6028                 return 0;
6029         }
6030
6031         if (!wl)
6032                 return ERR_PTR(-EINVAL);
6033
6034         dev = ndev_to_wlc_ndev(ndev, wl);
6035
6036         if (p2p_is_on(wl)) {
6037                 /* Suspend P2P discovery search-listen to prevent it from changing the
6038                  * channel.
6039                  */
6040                 if ((wl_cfgp2p_discover_enable_search(wl, false)) < 0) {
6041                         WL_ERR(("Can not disable discovery mode\n"));
6042                         return -EFAULT;
6043                 }
6044         }
6045
6046         assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
6047         err = wldev_ioctl(ndev, WLC_GET_ASSOCLIST,
6048                 assoc_maclist, sizeof(mac_buf), false);
6049         if (err < 0)
6050                 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
6051         else
6052                 num_associated = assoc_maclist->count;
6053
6054         memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN);
6055         scb_val.val = DOT11_RC_DEAUTH_LEAVING;
6056         err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
6057                 sizeof(scb_val_t), true);
6058         if (err < 0)
6059                 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err));
6060         WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
6061                 bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf),
6062                 scb_val.val));
6063
6064         if (num_associated > 0 && ETHER_ISBCAST(mac_addr))
6065                 wl_delay(400);
6066
6067         return 0;
6068 }
6069 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
6070
6071 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
6072 static s32
6073 wl_cfg80211_start_ap(
6074         struct wiphy *wiphy,
6075         struct net_device *dev,
6076         struct cfg80211_ap_settings *info)
6077 {
6078         struct wl_priv *wl = wiphy_priv(wiphy);
6079         s32 err = BCME_OK;
6080         struct parsed_ies ies;
6081         s32 bssidx = 0;
6082         u32 dev_role = 0;
6083
6084         WL_DBG(("Enter \n"));
6085
6086         if (!wl)
6087                 return ERR_PTR(-EINVAL);
6088
6089         if (dev == wl_to_prmry_ndev(wl)) {
6090                 WL_DBG(("Start AP req on primary iface: Softap\n"));
6091                 dev_role = NL80211_IFTYPE_AP;
6092         }
6093 #if defined(WL_ENABLE_P2P_IF)
6094         else if (dev == wl->p2p_net) {
6095                 /* Group Add request on p2p0 */
6096                 WL_DBG(("Start AP req on P2P iface: GO\n"));
6097                 dev = wl_to_prmry_ndev(wl);
6098                 dev_role = NL80211_IFTYPE_P2P_GO;
6099         }
6100 #endif /* WL_ENABLE_P2P_IF */
6101         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6102                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6103                 return BCME_ERROR;
6104         }
6105         if (p2p_is_on(wl) &&
6106                 (bssidx == wl_to_p2p_bss_bssidx(wl,
6107                 P2PAPI_BSSCFG_CONNECTION))) {
6108                 dev_role = NL80211_IFTYPE_P2P_GO;
6109                 WL_DBG(("Start AP req on P2P connection iface\n"));
6110         }
6111
6112         if (!check_dev_role_integrity(wl, dev_role))
6113                 goto fail;
6114
6115 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) && !0)
6116         if ((err = wl_cfg80211_set_channel(wiphy, dev,
6117                 dev->ieee80211_ptr->preset_chandef.chan,
6118                 NL80211_CHAN_HT20) < 0)) {
6119                 WL_ERR(("Set channel failed \n"));
6120                 goto fail;
6121         }
6122 #endif 
6123
6124         if ((err = wl_cfg80211_bcn_set_params(info, dev,
6125                 dev_role, bssidx)) < 0) {
6126                 WL_ERR(("Beacon params set failed \n"));
6127                 goto fail;
6128         }
6129
6130         /* Parse IEs */
6131         if ((err = wl_cfg80211_parse_ap_ies(dev, &info->beacon, &ies)) < 0) {
6132                 WL_ERR(("Set IEs failed \n"));
6133                 goto fail;
6134         }
6135
6136         if ((wl_cfg80211_bcn_validate_sec(dev, &ies,
6137                 dev_role, bssidx)) < 0)
6138         {
6139                 WL_ERR(("Beacon set security failed \n"));
6140                 goto fail;
6141         }
6142
6143         if ((err = wl_cfg80211_bcn_bringup_ap(dev, &ies,
6144                 dev_role, bssidx)) < 0) {
6145                 WL_ERR(("Beacon bring up AP/GO failed \n"));
6146                 goto fail;
6147         }
6148
6149         WL_DBG(("** AP/GO Created **\n"));
6150
6151         /* Set IEs to FW */
6152         if ((err = wl_cfg80211_set_ies(dev, &info->beacon, bssidx)) < 0)
6153                 WL_ERR(("Set IEs failed \n"));
6154
6155 fail:
6156         if (err) {
6157                 WL_ERR(("ADD/SET beacon failed\n"));
6158                 wldev_iovar_setint(dev, "mpc", 1);
6159         }
6160
6161         return err;
6162 }
6163
6164 static s32
6165 wl_cfg80211_stop_ap(
6166         struct wiphy *wiphy,
6167         struct net_device *dev)
6168 {
6169         int err = 0;
6170         u32 dev_role = 0;
6171         int infra = 0;
6172         int ap = 0;
6173         s32 bssidx = 0;
6174         struct wl_priv *wl = wiphy_priv(wiphy);
6175
6176         WL_DBG(("Enter \n"));
6177
6178         if (!wl)
6179                 return ERR_PTR(-EINVAL);
6180
6181         if (dev == wl_to_prmry_ndev(wl)) {
6182                 dev_role = NL80211_IFTYPE_AP;
6183         }
6184 #if defined(WL_ENABLE_P2P_IF)
6185         else if (dev == wl->p2p_net) {
6186                 /* Group Add request on p2p0 */
6187                 dev = wl_to_prmry_ndev(wl);
6188                 dev_role = NL80211_IFTYPE_P2P_GO;
6189         }
6190 #endif /* WL_ENABLE_P2P_IF */
6191         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6192                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6193                 return BCME_ERROR;
6194         }
6195         if (p2p_is_on(wl) &&
6196                 (bssidx == wl_to_p2p_bss_bssidx(wl,
6197                 P2PAPI_BSSCFG_CONNECTION))) {
6198                 dev_role = NL80211_IFTYPE_P2P_GO;
6199         }
6200
6201         if (!check_dev_role_integrity(wl, dev_role))
6202                 goto exit;
6203
6204         if (dev_role == NL80211_IFTYPE_AP) {
6205                 /* SoftAp on primary Interface.
6206                  * Shut down AP and turn on MPC
6207                  */
6208                 if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
6209                         WL_ERR(("setting AP mode failed %d \n", err));
6210                         err = -ENOTSUPP;
6211                         goto exit;
6212                 }
6213                 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
6214                 if (err < 0) {
6215                         WL_ERR(("SET INFRA error %d\n", err));
6216                         err = -ENOTSUPP;
6217                         goto exit;
6218                 }
6219
6220                 err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
6221                 if (unlikely(err)) {
6222                         WL_ERR(("WLC_UP error (%d)\n", err));
6223                         err = -EINVAL;
6224                         goto exit;
6225                 }
6226
6227                 wl_clr_drv_status(wl, AP_CREATED, dev);
6228                 /* Turn on the MPC */
6229                 wldev_iovar_setint(dev, "mpc", 1);
6230                 if (wl->ap_info) {
6231                         kfree(wl->ap_info->wpa_ie);
6232                         kfree(wl->ap_info->rsn_ie);
6233                         kfree(wl->ap_info->wps_ie);
6234                         kfree(wl->ap_info);
6235                         wl->ap_info = NULL;
6236                 }
6237         } else {
6238                 WL_DBG(("Stopping P2P GO \n"));
6239         }
6240
6241 exit:
6242         return err;
6243 }
6244
6245 static s32
6246 wl_cfg80211_change_beacon(
6247         struct wiphy *wiphy,
6248         struct net_device *dev,
6249         struct cfg80211_beacon_data *info)
6250 {
6251         s32 err = BCME_OK;
6252         struct wl_priv *wl = wiphy_priv(wiphy);
6253         struct parsed_ies ies;
6254         u32 dev_role = 0;
6255         s32 bssidx = 0;
6256
6257         WL_DBG(("Enter \n"));
6258
6259         if (!wl)
6260                 return ERR_PTR(-EINVAL);
6261         if (dev == wl_to_prmry_ndev(wl)) {
6262                 dev_role = NL80211_IFTYPE_AP;
6263         }
6264 #if defined(WL_ENABLE_P2P_IF)
6265         else if (dev == wl->p2p_net) {
6266                 /* Group Add request on p2p0 */
6267                 dev = wl_to_prmry_ndev(wl);
6268                 dev_role = NL80211_IFTYPE_P2P_GO;
6269         }
6270 #endif /* WL_ENABLE_P2P_IF */
6271         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6272                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6273                 return BCME_ERROR;
6274         }
6275         if (p2p_is_on(wl) &&
6276                 (bssidx == wl_to_p2p_bss_bssidx(wl,
6277                 P2PAPI_BSSCFG_CONNECTION))) {
6278                 dev_role = NL80211_IFTYPE_P2P_GO;
6279         }
6280
6281         if (!check_dev_role_integrity(wl, dev_role))
6282                 goto fail;
6283
6284         if ((dev_role == NL80211_IFTYPE_P2P_GO) && (wl->p2p_wdev == NULL)) {
6285                 WL_ERR(("P2P already down status!\n"));
6286                 err = BCME_ERROR;
6287                 goto fail;
6288         }
6289
6290         /* Parse IEs */
6291         if ((err = wl_cfg80211_parse_ap_ies(dev, info, &ies)) < 0) {
6292                 WL_ERR(("Parse IEs failed \n"));
6293                 goto fail;
6294         }
6295
6296         /* Set IEs to FW */
6297         if ((err = wl_cfg80211_set_ies(dev, info, bssidx)) < 0) {
6298                 WL_ERR(("Set IEs failed \n"));
6299                 goto fail;
6300         }
6301
6302         if (dev_role == NL80211_IFTYPE_AP) {
6303                 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
6304                         WL_ERR(("Hostapd update sec failed \n"));
6305                         err = -EINVAL;
6306                         goto fail;
6307                 }
6308         }
6309
6310 fail:
6311         return err;
6312 }
6313 #else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) */
6314 static s32
6315 wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
6316         struct beacon_parameters *info)
6317 {
6318         s32 err = BCME_OK;
6319         struct wl_priv *wl = wiphy_priv(wiphy);
6320         s32 ie_offset = 0;
6321         s32 bssidx = 0;
6322         u32 dev_role = NL80211_IFTYPE_AP;
6323         struct parsed_ies ies;
6324         bcm_tlv_t *ssid_ie;
6325         bool pbc = 0;
6326         WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
6327                 info->interval, info->dtim_period, info->head_len, info->tail_len));
6328
6329         if (!wl)
6330                 return ERR_PTR(-EINVAL);
6331
6332         if (dev == wl_to_prmry_ndev(wl)) {
6333                 dev_role = NL80211_IFTYPE_AP;
6334         }
6335 #if defined(WL_ENABLE_P2P_IF)
6336         else if (dev == wl->p2p_net) {
6337                 /* Group Add request on p2p0 */
6338                 dev = wl_to_prmry_ndev(wl);
6339                 dev_role = NL80211_IFTYPE_P2P_GO;
6340         }
6341 #endif /* WL_ENABLE_P2P_IF */
6342         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6343                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6344                 return BCME_ERROR;
6345         }
6346         if (p2p_is_on(wl) &&
6347                 (bssidx == wl_to_p2p_bss_bssidx(wl,
6348                 P2PAPI_BSSCFG_CONNECTION))) {
6349                 dev_role = NL80211_IFTYPE_P2P_GO;
6350         }
6351
6352         if (!check_dev_role_integrity(wl, dev_role))
6353                 goto fail;
6354
6355         if ((dev_role == NL80211_IFTYPE_P2P_GO) && (wl->p2p_wdev == NULL)) {
6356                 WL_ERR(("P2P already down status!\n"));
6357                 err = BCME_ERROR;
6358                 goto fail;
6359         }
6360
6361         ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
6362         /* find the SSID */
6363         if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
6364                 info->head_len - ie_offset,
6365                 DOT11_MNG_SSID_ID)) != NULL) {
6366                 if (dev_role == NL80211_IFTYPE_AP) {
6367                         /* Store the hostapd SSID */
6368                         memset(&wl->hostapd_ssid.SSID[0], 0x00, 32);
6369                         memcpy(&wl->hostapd_ssid.SSID[0], ssid_ie->data, ssid_ie->len);
6370                         wl->hostapd_ssid.SSID_len = ssid_ie->len;
6371                 } else {
6372                                 /* P2P GO */
6373                         memset(&wl->p2p->ssid.SSID[0], 0x00, 32);
6374                         memcpy(wl->p2p->ssid.SSID, ssid_ie->data, ssid_ie->len);
6375                         wl->p2p->ssid.SSID_len = ssid_ie->len;
6376                 }
6377         }
6378
6379         if (wl_cfg80211_parse_ies((u8 *)info->tail,
6380                 info->tail_len, &ies) < 0) {
6381                 WL_ERR(("Beacon get IEs failed \n"));
6382                 err = -EINVAL;
6383                 goto fail;
6384         }
6385
6386         if (wl_cfgp2p_set_management_ie(wl, dev, bssidx,
6387                 VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
6388                 info->tail_len) < 0) {
6389                 WL_ERR(("Beacon set IEs failed \n"));
6390                 goto fail;
6391         } else {
6392                 WL_DBG(("Applied Vndr IEs for Beacon \n"));
6393         }
6394         if (!wl_cfgp2p_bss_isup(dev, bssidx) &&
6395                 (wl_cfg80211_bcn_validate_sec(dev, &ies, dev_role, bssidx) < 0))
6396         {
6397                 WL_ERR(("Beacon set security failed \n"));
6398                 goto fail;
6399         }
6400
6401         /* Set BI and DTIM period */
6402         if (info->interval) {
6403                 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
6404                         &info->interval, sizeof(s32), true)) < 0) {
6405                         WL_ERR(("Beacon Interval Set Error, %d\n", err));
6406                         return err;
6407                 }
6408         }
6409         if (info->dtim_period) {
6410                 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
6411                         &info->dtim_period, sizeof(s32), true)) < 0) {
6412                         WL_ERR(("DTIM Interval Set Error, %d\n", err));
6413                         return err;
6414                 }
6415         }
6416
6417         if (wl_cfg80211_bcn_bringup_ap(dev, &ies, dev_role, bssidx) < 0) {
6418                 WL_ERR(("Beacon bring up AP/GO failed \n"));
6419                 goto fail;
6420         }
6421
6422         if (wl_get_drv_status(wl, AP_CREATED, dev)) {
6423                 /* Soft AP already running. Update changed params */
6424                 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
6425                         WL_ERR(("Hostapd update sec failed \n"));
6426                         err = -EINVAL;
6427                         goto fail;
6428                 }
6429         }
6430
6431         /* Enable Probe Req filter */
6432         if (((dev_role == NL80211_IFTYPE_P2P_GO) ||
6433                 (dev_role == NL80211_IFTYPE_AP)) && (ies.wps_ie != NULL)) {
6434                 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
6435                 if (pbc)
6436                         wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
6437         }
6438
6439         WL_DBG(("** ADD/SET beacon done **\n"));
6440
6441 fail:
6442         if (err) {
6443                 WL_ERR(("ADD/SET beacon failed\n"));
6444                 wldev_iovar_setint(dev, "mpc", 1);
6445         }
6446         return err;
6447
6448 }
6449 #endif 
6450
6451 #ifdef WL_SCHED_SCAN
6452 #define PNO_TIME                30
6453 #define PNO_REPEAT              4
6454 #define PNO_FREQ_EXPO_MAX       2
6455 int wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
6456                              struct net_device *dev,
6457                              struct cfg80211_sched_scan_request *request)
6458 {
6459         ushort pno_time = PNO_TIME;
6460         int pno_repeat = PNO_REPEAT;
6461         int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
6462         wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
6463         struct wl_priv *wl = wiphy_priv(wiphy);
6464         struct cfg80211_ssid *ssid = NULL;
6465         int ssid_count = 0;
6466         int i;
6467         int ret = 0;
6468
6469         WL_DBG(("Enter \n"));
6470
6471         if (!wl)
6472                 return ERR_PTR(-EINVAL);
6473
6474         WL_PNO((">>> SCHED SCAN START\n"));
6475         WL_PNO(("Enter n_match_sets:%d   n_ssids:%d \n",
6476                 request->n_match_sets, request->n_ssids));
6477         WL_PNO(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
6478                 request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max));
6479
6480
6481         if (!request || !request->n_ssids || !request->n_match_sets) {
6482                 WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids));
6483                 return -EINVAL;
6484         }
6485
6486         memset(&ssids_local, 0, sizeof(ssids_local));
6487
6488         if (request->n_match_sets > 0) {
6489                 for (i = 0; i < request->n_match_sets; i++) {
6490                         ssid = &request->match_sets[i].ssid;
6491                         memcpy(ssids_local[i].SSID, ssid->ssid, ssid->ssid_len);
6492                         ssids_local[i].SSID_len = ssid->ssid_len;
6493                         WL_PNO((">>> PNO filter set for ssid (%s) \n", ssid->ssid));
6494                         ssid_count++;
6495                 }
6496         }
6497
6498         if (request->n_ssids > 0) {
6499                 for (i = 0; i < request->n_ssids; i++) {
6500                         /* Active scan req for ssids */
6501                         WL_PNO((">>> Active scan req for ssid (%s) \n", request->ssids[i].ssid));
6502
6503                         /* match_set ssids is a supert set of n_ssid list, so we need
6504                          * not add these set seperately
6505                          */
6506                 }
6507         }
6508
6509         if (ssid_count) {
6510                 if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, request->n_match_sets,
6511                         pno_time, pno_repeat, pno_freq_expo_max, NULL, 0)) < 0) {
6512                         WL_ERR(("PNO setup failed!! ret=%d \n", ret));
6513                         return -EINVAL;
6514                 }
6515                 wl->sched_scan_req = request;
6516         } else {
6517                 return -EINVAL;
6518         }
6519
6520         return 0;
6521 }
6522
6523 int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
6524 {
6525         struct wl_priv *wl = wiphy_priv(wiphy);
6526
6527         WL_DBG(("Enter \n"));
6528
6529         if (!wl)
6530                 return ERR_PTR(-EINVAL);
6531
6532         WL_PNO((">>> SCHED SCAN STOP\n"));
6533
6534         if (dhd_dev_pno_stop_for_ssid(dev) < 0)
6535                 WL_ERR(("PNO Stop for SSID failed"));
6536
6537         if (wl->scan_request && wl->sched_scan_running) {
6538                 WL_PNO((">>> Sched scan running. Aborting it..\n"));
6539                 wl_notify_escan_complete(wl, dev, true, true);
6540         }
6541
6542          wl->sched_scan_req = NULL;
6543          wl->sched_scan_running = FALSE;
6544
6545         return 0;
6546 }
6547 #endif /* WL_SCHED_SCAN */
6548
6549 static struct cfg80211_ops wl_cfg80211_ops = {
6550         .add_virtual_intf = wl_cfg80211_add_virtual_iface,
6551         .del_virtual_intf = wl_cfg80211_del_virtual_iface,
6552         .change_virtual_intf = wl_cfg80211_change_virtual_iface,
6553 #if defined(WL_CFG80211_P2P_DEV_IF)
6554         .start_p2p_device = wl_cfgp2p_start_p2p_device,
6555         .stop_p2p_device = wl_cfgp2p_stop_p2p_device,
6556 #endif /* WL_CFG80211_P2P_DEV_IF */
6557         .scan = wl_cfg80211_scan,
6558         .set_wiphy_params = wl_cfg80211_set_wiphy_params,
6559         .join_ibss = wl_cfg80211_join_ibss,
6560         .leave_ibss = wl_cfg80211_leave_ibss,
6561         .get_station = wl_cfg80211_get_station,
6562         .set_tx_power = wl_cfg80211_set_tx_power,
6563         .get_tx_power = wl_cfg80211_get_tx_power,
6564         .add_key = wl_cfg80211_add_key,
6565         .del_key = wl_cfg80211_del_key,
6566         .get_key = wl_cfg80211_get_key,
6567         .set_default_key = wl_cfg80211_config_default_key,
6568         .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
6569         .set_power_mgmt = wl_cfg80211_set_power_mgmt,
6570         .connect = wl_cfg80211_connect,
6571         .disconnect = wl_cfg80211_disconnect,
6572         .suspend = wl_cfg80211_suspend,
6573         .resume = wl_cfg80211_resume,
6574         .set_pmksa = wl_cfg80211_set_pmksa,
6575         .del_pmksa = wl_cfg80211_del_pmksa,
6576         .flush_pmksa = wl_cfg80211_flush_pmksa,
6577         .remain_on_channel = wl_cfg80211_remain_on_channel,
6578         .cancel_remain_on_channel = wl_cfg80211_cancel_remain_on_channel,
6579         .mgmt_tx = wl_cfg80211_mgmt_tx,
6580         .mgmt_frame_register = wl_cfg80211_mgmt_frame_register,
6581         .change_bss = wl_cfg80211_change_bss,
6582 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) || 0
6583         .set_channel = wl_cfg80211_set_channel,
6584 #endif 
6585 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !0
6586         .set_beacon = wl_cfg80211_add_set_beacon,
6587         .add_beacon = wl_cfg80211_add_set_beacon,
6588 #else
6589         .change_beacon = wl_cfg80211_change_beacon,
6590         .start_ap = wl_cfg80211_start_ap,
6591         .stop_ap = wl_cfg80211_stop_ap,
6592 #endif 
6593 #ifdef WL_SCHED_SCAN
6594         .sched_scan_start = wl_cfg80211_sched_scan_start,
6595         .sched_scan_stop = wl_cfg80211_sched_scan_stop,
6596 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */
6597 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
6598         2, 0))
6599         .del_station = wl_cfg80211_del_station,
6600         .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait,
6601 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */
6602 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || 0
6603         .tdls_oper = wl_cfg80211_tdls_oper
6604 #endif 
6605 };
6606
6607 s32 wl_mode_to_nl80211_iftype(s32 mode)
6608 {
6609         s32 err = 0;
6610
6611         switch (mode) {
6612         case WL_MODE_BSS:
6613                 return NL80211_IFTYPE_STATION;
6614         case WL_MODE_IBSS:
6615                 return NL80211_IFTYPE_ADHOC;
6616         case WL_MODE_AP:
6617                 return NL80211_IFTYPE_AP;
6618         default:
6619                 return NL80211_IFTYPE_UNSPECIFIED;
6620         }
6621
6622         return err;
6623 }
6624
6625 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
6626 /*      Kernel Network Support->Wireless->Regulatory rules database
6627         options should be enabled and regulatory  CRDA regdb table populated in Kernel
6628         for proper country reg notification
6629 */
6630 static int
6631 wl_cfg80211_reg_notifier(
6632         struct wiphy *wiphy,
6633         struct regulatory_request *request)
6634 {
6635         struct wl_priv *wl = (struct wl_priv *)wiphy_priv(wiphy);
6636         int ret = 0;
6637
6638         if (!request || !wl) {
6639                 WL_ERR(("Invalid arg\n"));
6640                 return -EINVAL;
6641         }
6642
6643         WL_DBG(("ccode: %c%c Initiator: %d\n",
6644                 request->alpha2[0], request->alpha2[1], request->initiator));
6645
6646         /* We support only REGDOM_SET_BY_USER as of now */
6647         if ((request->initiator != NL80211_REGDOM_SET_BY_USER) &&
6648                 (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
6649                 WL_ERR(("reg_notifier for intiator:%d not supported : set default\n",
6650                         request->initiator));
6651                 /* in case of no supported country by regdb
6652                      lets driver setup platform default Locale
6653                 */
6654         }
6655
6656         WL_ERR(("Set country code %c%c from %s\n",
6657                 request->alpha2[0], request->alpha2[1],
6658                 ((request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) ? " 11d AP" : "User")));
6659
6660         if ((ret = wldev_set_country(wl_to_prmry_ndev(wl), request->alpha2,
6661                 false, (request->initiator == NL80211_REGDOM_SET_BY_USER ? true : false))) < 0) {
6662                 WL_ERR(("set country Failed :%d\n", ret));
6663         }
6664
6665         return ret;
6666 }
6667 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
6668
6669 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, void *data)
6670 {
6671         s32 err = 0;
6672 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
6673         (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
6674         dhd_pub_t *dhd = (dhd_pub_t *)data;
6675 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
6676
6677         wdev->wiphy =
6678             wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_priv));
6679         if (unlikely(!wdev->wiphy)) {
6680                 WL_ERR(("Couldn not allocate wiphy device\n"));
6681                 err = -ENOMEM;
6682                 return err;
6683         }
6684         set_wiphy_dev(wdev->wiphy, sdiofunc_dev);
6685         wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX;
6686         /* Report  how many SSIDs Driver can support per Scan request */
6687         wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX;
6688         wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
6689 #ifdef WL_SCHED_SCAN
6690         wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT;
6691         wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT;
6692         wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX;
6693         wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
6694 #endif /* WL_SCHED_SCAN */
6695         wdev->wiphy->interface_modes =
6696                 BIT(NL80211_IFTYPE_STATION)
6697                 | BIT(NL80211_IFTYPE_ADHOC)
6698 #if !defined(WL_ENABLE_P2P_IF)
6699                 | BIT(NL80211_IFTYPE_MONITOR)
6700 #endif /* !WL_ENABLE_P2P_IF */
6701 #if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)
6702                 | BIT(NL80211_IFTYPE_P2P_CLIENT)
6703                 | BIT(NL80211_IFTYPE_P2P_GO)
6704 #endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */
6705 #if defined(WL_CFG80211_P2P_DEV_IF)
6706                 | BIT(NL80211_IFTYPE_P2P_DEVICE)
6707 #endif /* WL_CFG80211_P2P_DEV_IF */
6708                 | BIT(NL80211_IFTYPE_AP);
6709
6710 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
6711         (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
6712         if (dhd && dhd->op_mode == DHD_FLAG_HOSTAP_MODE) {
6713                 WL_DBG(("Setting interface combinations for SoftAP mode\n"));
6714                 wdev->wiphy->iface_combinations = softap_iface_combinations;
6715                 wdev->wiphy->n_iface_combinations =
6716                         ARRAY_SIZE(softap_iface_combinations);
6717         } else {
6718                 WL_DBG(("Setting interface combinations for STA+P2P mode\n"));
6719                 wdev->wiphy->iface_combinations = sta_p2p_iface_combinations;
6720                 wdev->wiphy->n_iface_combinations =
6721                         ARRAY_SIZE(sta_p2p_iface_combinations);
6722         }
6723 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
6724
6725         wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
6726
6727         wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
6728         wdev->wiphy->cipher_suites = __wl_cipher_suites;
6729         wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
6730         wdev->wiphy->max_remain_on_channel_duration = 5000;
6731         wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes;
6732 #ifndef WL_POWERSAVE_DISABLED
6733         wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
6734 #else
6735         wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
6736 #endif                          /* !WL_POWERSAVE_DISABLED */
6737         wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK |
6738                 WIPHY_FLAG_4ADDR_AP |
6739 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && !0
6740                 WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS |
6741 #endif
6742                 WIPHY_FLAG_4ADDR_STATION;
6743         /*  If driver advertises FW_ROAM, the supplicant wouldn't
6744          * send the BSSID & Freq in the connect command allowing the
6745          * the driver to choose the AP to connect to. But unless we
6746          * support ROAM_CACHE in firware this will delay the ASSOC as
6747          * as the FW need to do a full scan before attempting to connect
6748          * So that feature will just increase assoc. The better approach
6749          * to let Supplicant to provide channel info and FW letter may roam
6750          * if needed so DON'T advertise that featur eto Supplicant.
6751          */
6752 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
6753 /*      wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; */
6754 #endif
6755 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || 0
6756         wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
6757                 WIPHY_FLAG_OFFCHAN_TX;
6758 #endif
6759 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
6760         4, 0))
6761         /* From 3.4 kernel ownards AP_SME flag can be advertised
6762          * to remove the patch from supplicant
6763          */
6764         wdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
6765 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
6766
6767 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
6768         wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier;
6769 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
6770
6771 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || 0
6772         wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
6773 #endif
6774
6775 #if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
6776         /*
6777          * From linux-3.10 kernel, wowlan packet filter is mandated to avoid the
6778          * disconnection of connected network before suspend. So a dummy wowlan
6779          * filter is configured for kernels linux-3.8 and above.
6780          */
6781         wdev->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
6782 #endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
6783
6784         WL_DBG(("Registering custom regulatory)\n"));
6785         wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
6786         wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom);
6787         /* Now we can register wiphy with cfg80211 module */
6788         err = wiphy_register(wdev->wiphy);
6789         if (unlikely(err < 0)) {
6790                 WL_ERR(("Couldn not register wiphy device (%d)\n", err));
6791                 wiphy_free(wdev->wiphy);
6792         }
6793
6794 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \
6795         KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS)
6796         wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS;
6797 #endif /* ((LINUX_VER >= 3.0) && (LINUX_VER <= 3.3)) && WL_IFACE_COMB_NUM_CHANNELS */
6798
6799         return err;
6800 }
6801
6802 static void wl_free_wdev(struct wl_priv *wl)
6803 {
6804         struct wireless_dev *wdev = wl->wdev;
6805         struct wiphy *wiphy;
6806         if (!wdev) {
6807                 WL_ERR(("wdev is invalid\n"));
6808                 return;
6809         }
6810         wiphy = wdev->wiphy;
6811         wiphy_unregister(wdev->wiphy);
6812         wdev->wiphy->dev.parent = NULL;
6813
6814         wl_delete_all_netinfo(wl);
6815         wiphy_free(wiphy);
6816         /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "wl",
6817          * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
6818          */
6819 }
6820
6821 static s32 wl_inform_bss(struct wl_priv *wl)
6822 {
6823         struct wl_scan_results *bss_list;
6824         struct wl_bss_info *bi = NULL;  /* must be initialized */
6825         s32 err = 0;
6826         s32 i;
6827
6828         bss_list = wl->bss_list;
6829         WL_DBG(("scanned AP count (%d)\n", bss_list->count));
6830         bi = next_bss(bss_list, bi);
6831         for_each_bss(bss_list, bi, i) {
6832                 err = wl_inform_single_bss(wl, bi);
6833                 if (unlikely(err))
6834                         break;
6835         }
6836         return err;
6837 }
6838
6839 static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
6840 {
6841         struct wiphy *wiphy = wl_to_wiphy(wl);
6842         struct ieee80211_mgmt *mgmt;
6843         struct ieee80211_channel *channel;
6844         struct ieee80211_supported_band *band;
6845         struct wl_cfg80211_bss_info *notif_bss_info;
6846         struct wl_scan_req *sr = wl_to_sr(wl);
6847         struct beacon_proberesp *beacon_proberesp;
6848         struct cfg80211_bss *cbss = NULL;
6849         s32 mgmt_type;
6850         s32 signal;
6851         u32 freq;
6852         s32 err = 0;
6853         gfp_t aflags;
6854
6855         if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
6856                 WL_DBG(("Beacon is larger than buffer. Discarding\n"));
6857                 return err;
6858         }
6859         aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
6860         notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt)
6861                 - sizeof(u8) + WL_BSS_INFO_MAX, aflags);
6862         if (unlikely(!notif_bss_info)) {
6863                 WL_ERR(("notif_bss_info alloc failed\n"));
6864                 return -ENOMEM;
6865         }
6866         mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
6867         notif_bss_info->channel =
6868                 bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
6869
6870         if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
6871                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
6872         else
6873                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
6874         if (!band) {
6875                 WL_ERR(("No valid band"));
6876                 kfree(notif_bss_info);
6877                 return -EINVAL;
6878         }
6879         notif_bss_info->rssi = wl_rssi_offset(dtoh16(bi->RSSI));
6880         memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
6881         mgmt_type = wl->active_scan ?
6882                 IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
6883         if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
6884             mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
6885         }
6886         beacon_proberesp = wl->active_scan ?
6887                 (struct beacon_proberesp *)&mgmt->u.probe_resp :
6888                 (struct beacon_proberesp *)&mgmt->u.beacon;
6889         beacon_proberesp->timestamp = 0;
6890         beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
6891         beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
6892         wl_rst_ie(wl);
6893         wl_update_hidden_ap_ie(bi, ((u8 *) bi) + bi->ie_offset, &bi->ie_length);
6894         wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
6895         wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX -
6896                 offsetof(struct wl_cfg80211_bss_info, frame_buf));
6897         notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
6898                 u.beacon.variable) + wl_get_ielen(wl);
6899 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
6900         freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
6901         (void)band->band;
6902 #else
6903         freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band);
6904 #endif
6905         if (freq == 0) {
6906                 WL_ERR(("Invalid channel, fail to chcnage channel to freq\n"));
6907                 kfree(notif_bss_info);
6908                 return -EINVAL;
6909         }
6910         channel = ieee80211_get_channel(wiphy, freq);
6911         if (unlikely(!channel)) {
6912                 WL_ERR(("ieee80211_get_channel error\n"));
6913                 kfree(notif_bss_info);
6914                 return -EINVAL;
6915         }
6916         WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM"
6917                         "mgmt_type %d frame_len %d\n", bi->SSID,
6918                         notif_bss_info->rssi, notif_bss_info->channel,
6919                         mgmt->u.beacon.capab_info, &bi->BSSID, mgmt_type,
6920                         notif_bss_info->frame_len));
6921
6922         signal = notif_bss_info->rssi * 100;
6923         if (!mgmt->u.probe_resp.timestamp) {
6924 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
6925                 struct timespec ts;
6926                 get_monotonic_boottime(&ts);
6927                 mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000)
6928                                 + ts.tv_nsec / 1000;
6929 #else
6930                 struct timeval tv;
6931                 do_gettimeofday(&tv);
6932                 mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec*1000000)
6933                                 + tv.tv_usec;
6934 #endif
6935         }
6936
6937
6938         cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
6939                 le16_to_cpu(notif_bss_info->frame_len), signal, aflags);
6940         if (unlikely(!cbss)) {
6941                 WL_ERR(("cfg80211_inform_bss_frame error\n"));
6942                 kfree(notif_bss_info);
6943                 return -EINVAL;
6944         }
6945
6946 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
6947         cfg80211_put_bss(wiphy, cbss);
6948 #else
6949         cfg80211_put_bss(cbss);
6950 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
6951         kfree(notif_bss_info);
6952         return err;
6953 }
6954
6955 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev)
6956 {
6957         u32 event = ntoh32(e->event_type);
6958         u32 status =  ntoh32(e->status);
6959         u16 flags = ntoh16(e->flags);
6960
6961         WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
6962         if (event == WLC_E_SET_SSID) {
6963                 if (status == WLC_E_STATUS_SUCCESS) {
6964                         if (!wl_is_ibssmode(wl, ndev))
6965                                 return true;
6966                 }
6967         } else if (event == WLC_E_LINK) {
6968                 if (flags & WLC_EVENT_MSG_LINK)
6969                         return true;
6970         }
6971
6972         WL_DBG(("wl_is_linkup false\n"));
6973         return false;
6974 }
6975
6976 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
6977 {
6978         u32 event = ntoh32(e->event_type);
6979         u16 flags = ntoh16(e->flags);
6980
6981         if (event == WLC_E_DEAUTH_IND ||
6982         event == WLC_E_DISASSOC_IND ||
6983         event == WLC_E_DISASSOC ||
6984         event == WLC_E_DEAUTH) {
6985 #if (WL_DBG_LEVEL > 0)
6986         WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
6987 #endif /* (WL_DBG_LEVEL > 0) */
6988                 return true;
6989         } else if (event == WLC_E_LINK) {
6990                 if (!(flags & WLC_EVENT_MSG_LINK)) {
6991 #if (WL_DBG_LEVEL > 0)
6992         WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
6993 #endif /* (WL_DBG_LEVEL > 0) */
6994                         return true;
6995                 }
6996         }
6997
6998         return false;
6999 }
7000
7001 static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e)
7002 {
7003         u32 event = ntoh32(e->event_type);
7004         u32 status = ntoh32(e->status);
7005
7006         if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS)
7007                 return true;
7008         if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS)
7009                 return true;
7010
7011         return false;
7012 }
7013
7014 /* The mainline kernel >= 3.2.0 has support for indicating new/del station
7015  * to AP/P2P GO via events. If this change is backported to kernel for which
7016  * this driver is being built, then define WL_CFG80211_STA_EVENT. You
7017  * should use this new/del sta event mechanism for BRCM supplicant >= 22.
7018  */
7019 static s32
7020 wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev,
7021         const wl_event_msg_t *e, void *data)
7022 {
7023         s32 err = 0;
7024         u32 event = ntoh32(e->event_type);
7025         u32 reason = ntoh32(e->reason);
7026         u32 len = ntoh32(e->datalen);
7027
7028 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) \
7029         && !0
7030         bool isfree = false;
7031         u8 *mgmt_frame;
7032         u8 bsscfgidx = e->bsscfgidx;
7033         s32 freq;
7034         s32 channel;
7035         u8 *body = NULL;
7036         u16 fc = 0;
7037
7038         struct ieee80211_supported_band *band;
7039         struct ether_addr da;
7040         struct ether_addr bssid;
7041         struct wiphy *wiphy = wl_to_wiphy(wl);
7042         channel_info_t ci;
7043 #else
7044         struct station_info sinfo;
7045 #endif 
7046
7047         WL_DBG(("event %d status %d reason %d\n", event, ntoh32(e->status), reason));
7048         /* if link down, bsscfg is disabled. */
7049         if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
7050                 wl_get_p2p_status(wl, IF_DELETING) && (ndev != wl_to_prmry_ndev(wl))) {
7051                 wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
7052                 WL_INFO(("AP mode link down !! \n"));
7053                 complete(&wl->iface_disable);
7054                 return 0;
7055         }
7056
7057 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) \
7058         && !0
7059         WL_DBG(("Enter \n"));
7060         if (!len && (event == WLC_E_DEAUTH)) {
7061                 len = 2; /* reason code field */
7062                 data = &reason;
7063         }
7064         if (len) {
7065                 body = kzalloc(len, GFP_KERNEL);
7066
7067                 if (body == NULL) {
7068                         WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
7069                         return WL_INVALID;
7070                 }
7071         }
7072         memset(&bssid, 0, ETHER_ADDR_LEN);
7073         WL_DBG(("Enter event %d ndev %p\n", event, ndev));
7074         if (wl_get_mode_by_netdev(wl, ndev) == WL_INVALID) {
7075                 kfree(body);
7076                 return WL_INVALID;
7077         }
7078         if (len)
7079                 memcpy(body, data, len);
7080
7081         wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
7082                 NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync);
7083         memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN);
7084         err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
7085         switch (event) {
7086                 case WLC_E_ASSOC_IND:
7087                         fc = FC_ASSOC_REQ;
7088                         break;
7089                 case WLC_E_REASSOC_IND:
7090                         fc = FC_REASSOC_REQ;
7091                         break;
7092                 case WLC_E_DISASSOC_IND:
7093                         fc = FC_DISASSOC;
7094                         WL_ERR(("event %s(%d) status %d reason %d\n",
7095                                 bcmevent_names[event].name, event, ntoh32(e->status), reason));
7096                         break;
7097                 case WLC_E_DEAUTH_IND:
7098                         fc = FC_DISASSOC;
7099                         WL_ERR(("event %s(%d) status %d reason %d\n",
7100                                 bcmevent_names[event].name, event, ntoh32(e->status), reason));
7101                         break;
7102                 case WLC_E_DEAUTH:
7103                         fc = FC_DISASSOC;
7104                         WL_ERR(("event %s(%d) status %d reason %d\n",
7105                                 bcmevent_names[event].name, event, ntoh32(e->status), reason));
7106                         break;
7107                 default:
7108                         fc = 0;
7109                         goto exit;
7110         }
7111         if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) {
7112                 kfree(body);
7113                 return err;
7114         }
7115
7116         channel = dtoh32(ci.hw_channel);
7117         if (channel <= CH_MAX_2G_CHANNEL)
7118                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
7119         else
7120                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
7121         if (!band) {
7122                 WL_ERR(("No valid band"));
7123                 if (body)
7124                         kfree(body);
7125                 return -EINVAL;
7126         }
7127 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
7128         freq = ieee80211_channel_to_frequency(channel);
7129         (void)band->band;
7130 #else
7131         freq = ieee80211_channel_to_frequency(channel, band->band);
7132 #endif
7133
7134         err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
7135                 &mgmt_frame, &len, body);
7136         if (err < 0)
7137                 goto exit;
7138         isfree = true;
7139
7140         if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) {
7141 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
7142                 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
7143 #else
7144                 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
7145 #endif 
7146         } else if (event == WLC_E_DISASSOC_IND) {
7147 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
7148                 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
7149 #else
7150                 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
7151 #endif 
7152         } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
7153 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
7154                 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
7155 #else
7156                 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
7157 #endif 
7158         }
7159
7160 exit:
7161         if (isfree)
7162                 kfree(mgmt_frame);
7163         if (body)
7164                 kfree(body);
7165 #else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
7166         sinfo.filled = 0;
7167         if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
7168                 reason == DOT11_SC_SUCCESS) {
7169                 sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
7170                 if (!data) {
7171                         WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
7172                         return -EINVAL;
7173                 }
7174                 sinfo.assoc_req_ies = data;
7175                 sinfo.assoc_req_ies_len = len;
7176                 cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
7177         } else if (event == WLC_E_DISASSOC_IND) {
7178                 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
7179         } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
7180                 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
7181         }
7182 #endif 
7183         return err;
7184 }
7185
7186 static s32
7187 wl_get_auth_assoc_status(struct wl_priv *wl, struct net_device *ndev,
7188         const wl_event_msg_t *e)
7189 {
7190         u32 reason = ntoh32(e->reason);
7191         u32 event = ntoh32(e->event_type);
7192         struct wl_security *sec = wl_read_prof(wl, ndev, WL_PROF_SEC);
7193         WL_DBG(("event type : %d, reason : %d\n", event, reason));
7194         if (sec) {
7195                 switch (event) {
7196                 case WLC_E_ASSOC:
7197                 case WLC_E_AUTH:
7198                                 sec->auth_assoc_res_status = reason;
7199                 default:
7200                         break;
7201                 }
7202         } else
7203                 WL_ERR(("sec is NULL\n"));
7204         return 0;
7205 }
7206
7207 static s32
7208 wl_notify_connect_status_ibss(struct wl_priv *wl, struct net_device *ndev,
7209         const wl_event_msg_t *e, void *data)
7210 {
7211         s32 err = 0;
7212         u32 event = ntoh32(e->event_type);
7213         u16 flags = ntoh16(e->flags);
7214         u32 status =  ntoh32(e->status);
7215         bool active;
7216
7217         if (event == WLC_E_JOIN) {
7218                 WL_DBG(("joined in IBSS network\n"));
7219         }
7220         if (event == WLC_E_START) {
7221                 WL_DBG(("started IBSS network\n"));
7222         }
7223         if (event == WLC_E_JOIN || event == WLC_E_START ||
7224                 (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
7225                 if (wl_get_drv_status(wl, CONNECTED, ndev)) {
7226                         /* ROAM or Redundant */
7227                         u8 *cur_bssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7228                         if (memcmp(cur_bssid, &e->addr, ETHER_ADDR_LEN) == 0) {
7229                                 WL_DBG(("IBSS connected event from same BSSID("
7230                                         MACDBG "), ignore it\n", MAC2STRDBG(cur_bssid)));
7231                                 return err;
7232                         }
7233                         WL_INFO(("IBSS BSSID is changed from " MACDBG " to " MACDBG "\n",
7234                                 MAC2STRDBG(cur_bssid), MAC2STRDBG((u8 *)&e->addr)));
7235                         wl_get_assoc_ies(wl, ndev);
7236                         wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7237                         wl_update_bss_info(wl, ndev);
7238                         cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL);
7239                 }
7240                 else {
7241                         /* New connection */
7242                         WL_INFO(("IBSS connected to " MACDBG "\n", MAC2STRDBG((u8 *)&e->addr)));
7243                         wl_link_up(wl);
7244                         wl_get_assoc_ies(wl, ndev);
7245                         wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7246                         wl_update_bss_info(wl, ndev);
7247                         cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL);
7248                         wl_set_drv_status(wl, CONNECTED, ndev);
7249                         active = true;
7250                         wl_update_prof(wl, ndev, NULL, (void *)&active, WL_PROF_ACT);
7251                 }
7252         } else if ((event == WLC_E_LINK && !(flags & WLC_EVENT_MSG_LINK)) ||
7253                 event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
7254                 wl_clr_drv_status(wl, CONNECTED, ndev);
7255                 wl_link_down(wl);
7256                 wl_init_prof(wl, ndev);
7257         }
7258         else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
7259                 WL_DBG(("no action - join fail (IBSS mode)\n"));
7260         }
7261         else {
7262                 WL_DBG(("no action (IBSS mode)\n"));
7263         }
7264         return err;
7265 }
7266
7267 static s32
7268 wl_notify_connect_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7269         const wl_event_msg_t *e, void *data)
7270 {
7271         bool act;
7272         struct net_device *ndev = NULL;
7273         s32 err = 0;
7274         u32 event = ntoh32(e->event_type);
7275
7276         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7277
7278         if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) {
7279                 err = wl_notify_connect_status_ap(wl, ndev, e, data);
7280         } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS) {
7281                 err = wl_notify_connect_status_ibss(wl, ndev, e, data);
7282         } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_BSS) {
7283                 WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
7284                         ntoh32(e->event_type), ntoh32(e->status), ndev));
7285                 if (event == WLC_E_ASSOC || event == WLC_E_AUTH) {
7286                         wl_get_auth_assoc_status(wl, ndev, e);
7287                         return 0;
7288                 }
7289                 if (wl_is_linkup(wl, e, ndev)) {
7290                         wl_link_up(wl);
7291                         act = true;
7292                         if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) {
7293                                         printk("wl_bss_connect_done succeeded with " MACDBG "\n",
7294                                                 MAC2STRDBG((u8*)(&e->addr)));
7295                                         wl_bss_connect_done(wl, ndev, e, data, true);
7296                                         WL_DBG(("joined in BSS network \"%s\"\n",
7297                                         ((struct wlc_ssid *)
7298                                          wl_read_prof(wl, ndev, WL_PROF_SSID))->SSID));
7299                         }
7300                         wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT);
7301                         wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7302
7303                 } else if (wl_is_linkdown(wl, e)) {
7304                         if (wl->scan_request) {
7305                                 if (wl->escan_on) {
7306                                         wl_notify_escan_complete(wl, ndev, true, true);
7307                                 } else {
7308                                         del_timer_sync(&wl->scan_timeout);
7309                                         wl_iscan_aborted(wl);
7310                                 }
7311                         }
7312                         if (wl_get_drv_status(wl, CONNECTED, ndev)) {
7313                                 scb_val_t scbval;
7314                                 u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7315                                 s32 reason = 0;
7316                                 if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND)
7317                                         reason = ntoh32(e->reason);
7318                                 /* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */
7319                                 reason = (reason == WLAN_REASON_UNSPECIFIED)? 0 : reason;
7320
7321                                 printk("link down if %s may call cfg80211_disconnected. "
7322                                         "event : %d, reason=%d from " MACDBG "\n",
7323                                         ndev->name, event, ntoh32(e->reason),
7324                                         MAC2STRDBG((u8*)(&e->addr)));
7325                                 if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) {
7326                                         WL_ERR(("BSSID of event is not the connected BSSID"
7327                                                 "(ignore it) cur: " MACDBG " event: " MACDBG"\n",
7328                                                 MAC2STRDBG(curbssid), MAC2STRDBG((u8*)(&e->addr))));
7329                                         return 0;
7330                                 }
7331                                 wl_clr_drv_status(wl, CONNECTED, ndev);
7332                                 if (! wl_get_drv_status(wl, DISCONNECTING, ndev)) {
7333                                         /* To make sure disconnect, explictly send dissassoc
7334                                         *  for BSSID 00:00:00:00:00:00 issue
7335                                         */
7336                                         scbval.val = WLAN_REASON_DEAUTH_LEAVING;
7337
7338                                         memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
7339                                         scbval.val = htod32(scbval.val);
7340                                         err = wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
7341                                                 sizeof(scb_val_t), true);
7342                                         if (err < 0) {
7343                                                 WL_ERR(("WLC_DISASSOC error %d\n", err));
7344                                                 err = 0;
7345                                         }
7346                                         cfg80211_disconnected(ndev, reason, NULL, 0, GFP_KERNEL);
7347                                         wl_link_down(wl);
7348                                         wl_init_prof(wl, ndev);
7349                                 }
7350                         }
7351                         else if (wl_get_drv_status(wl, CONNECTING, ndev)) {
7352
7353                                 printk("link down, during connecting\n");
7354 #ifdef ESCAN_RESULT_PATCH
7355                                 if ((memcmp(connect_req_bssid, broad_bssid, ETHER_ADDR_LEN) == 0) ||
7356                                         (memcmp(&e->addr, broad_bssid, ETHER_ADDR_LEN) == 0) ||
7357                                         (memcmp(&e->addr, connect_req_bssid, ETHER_ADDR_LEN) == 0))
7358                                         /* In case this event comes while associating another AP */
7359 #endif /* ESCAN_RESULT_PATCH */
7360                                         wl_bss_connect_done(wl, ndev, e, data, false);
7361                         }
7362                         wl_clr_drv_status(wl, DISCONNECTING, ndev);
7363
7364                         /* if link down, bsscfg is diabled */
7365                         if (ndev != wl_to_prmry_ndev(wl))
7366                                 complete(&wl->iface_disable);
7367
7368                 } else if (wl_is_nonetwork(wl, e)) {
7369                         printk("connect failed event=%d e->status %d e->reason %d \n",
7370                                 event, (int)ntoh32(e->status), (int)ntoh32(e->reason));
7371                         /* Clean up any pending scan request */
7372                         if (wl->scan_request) {
7373                                 if (wl->escan_on) {
7374                                         wl_notify_escan_complete(wl, ndev, true, true);
7375                                 } else {
7376                                         del_timer_sync(&wl->scan_timeout);
7377                                         wl_iscan_aborted(wl);
7378                                 }
7379                         }
7380                         if (wl_get_drv_status(wl, CONNECTING, ndev))
7381                                 wl_bss_connect_done(wl, ndev, e, data, false);
7382                 } else {
7383                         printk("%s nothing\n", __FUNCTION__);
7384                 }
7385         } else {
7386                 WL_ERR(("Invalid ndev status %d\n", wl_get_mode_by_netdev(wl, ndev)));
7387         }
7388         return err;
7389 }
7390
7391
7392 static s32
7393 wl_notify_roaming_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7394         const wl_event_msg_t *e, void *data)
7395 {
7396         bool act;
7397         struct net_device *ndev = NULL;
7398         s32 err = 0;
7399         u32 event = be32_to_cpu(e->event_type);
7400         u32 status = be32_to_cpu(e->status);
7401
7402         WL_DBG(("Enter \n"));
7403
7404         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7405
7406         if (event == WLC_E_ROAM && status == WLC_E_STATUS_SUCCESS) {
7407                 if (wl_get_drv_status(wl, CONNECTED, ndev))
7408                         wl_bss_roaming_done(wl, ndev, e, data);
7409                 else
7410                         wl_bss_connect_done(wl, ndev, e, data, true);
7411                 act = true;
7412                 wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT);
7413                 wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7414         }
7415         return err;
7416 }
7417
7418 static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev)
7419 {
7420         wl_assoc_info_t assoc_info;
7421         struct wl_connect_info *conn_info = wl_to_conn(wl);
7422         s32 err = 0;
7423
7424         WL_DBG(("Enter \n"));
7425         err = wldev_iovar_getbuf(ndev, "assoc_info", NULL, 0, wl->extra_buf,
7426                 WL_ASSOC_INFO_MAX, NULL);
7427         if (unlikely(err)) {
7428                 WL_ERR(("could not get assoc info (%d)\n", err));
7429                 return err;
7430         }
7431         memcpy(&assoc_info, wl->extra_buf, sizeof(wl_assoc_info_t));
7432         assoc_info.req_len = htod32(assoc_info.req_len);
7433         assoc_info.resp_len = htod32(assoc_info.resp_len);
7434         assoc_info.flags = htod32(assoc_info.flags);
7435         if (conn_info->req_ie_len) {
7436                 conn_info->req_ie_len = 0;
7437                 bzero(conn_info->req_ie, sizeof(conn_info->req_ie));
7438         }
7439         if (conn_info->resp_ie_len) {
7440                 conn_info->resp_ie_len = 0;
7441                 bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie));
7442         }
7443         if (assoc_info.req_len) {
7444                 err = wldev_iovar_getbuf(ndev, "assoc_req_ies", NULL, 0, wl->extra_buf,
7445                         WL_ASSOC_INFO_MAX, NULL);
7446                 if (unlikely(err)) {
7447                         WL_ERR(("could not get assoc req (%d)\n", err));
7448                         return err;
7449                 }
7450                 conn_info->req_ie_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
7451                 if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
7452                         conn_info->req_ie_len -= ETHER_ADDR_LEN;
7453                 }
7454                 if (conn_info->req_ie_len <= MAX_REQ_LINE)
7455                         memcpy(conn_info->req_ie, wl->extra_buf, conn_info->req_ie_len);
7456                 else {
7457                         WL_ERR(("IE size %d above max %d size \n",
7458                                 conn_info->req_ie_len, MAX_REQ_LINE));
7459                         return err;
7460                 }
7461         } else {
7462                 conn_info->req_ie_len = 0;
7463         }
7464         if (assoc_info.resp_len) {
7465                 err = wldev_iovar_getbuf(ndev, "assoc_resp_ies", NULL, 0, wl->extra_buf,
7466                         WL_ASSOC_INFO_MAX, NULL);
7467                 if (unlikely(err)) {
7468                         WL_ERR(("could not get assoc resp (%d)\n", err));
7469                         return err;
7470                 }
7471                 conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp);
7472                 if (conn_info->resp_ie_len <= MAX_REQ_LINE)
7473                         memcpy(conn_info->resp_ie, wl->extra_buf, conn_info->resp_ie_len);
7474                 else {
7475                         WL_ERR(("IE size %d above max %d size \n",
7476                                 conn_info->resp_ie_len, MAX_REQ_LINE));
7477                         return err;
7478                 }
7479         } else {
7480                 conn_info->resp_ie_len = 0;
7481         }
7482         WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
7483                 conn_info->resp_ie_len));
7484
7485         return err;
7486 }
7487
7488 static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
7489         size_t *join_params_size)
7490 {
7491         chanspec_t chanspec = 0;
7492         if (ch != 0) {
7493                 join_params->params.chanspec_num = 1;
7494                 join_params->params.chanspec_list[0] = ch;
7495
7496                 if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
7497                         chanspec |= WL_CHANSPEC_BAND_2G;
7498                 else
7499                         chanspec |= WL_CHANSPEC_BAND_5G;
7500
7501                 chanspec |= WL_CHANSPEC_BW_20;
7502                 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
7503
7504                 *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
7505                         join_params->params.chanspec_num * sizeof(chanspec_t);
7506
7507                 join_params->params.chanspec_list[0]  &= WL_CHANSPEC_CHAN_MASK;
7508                 join_params->params.chanspec_list[0] |= chanspec;
7509                 join_params->params.chanspec_list[0] =
7510                         wl_chspec_host_to_driver(join_params->params.chanspec_list[0]);
7511
7512                 join_params->params.chanspec_num =
7513                         htod32(join_params->params.chanspec_num);
7514                 WL_DBG(("join_params->params.chanspec_list[0]= %X, %d channels\n",
7515                         join_params->params.chanspec_list[0],
7516                         join_params->params.chanspec_num));
7517         }
7518 }
7519
7520 static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev)
7521 {
7522         struct cfg80211_bss *bss;
7523         struct wl_bss_info *bi;
7524         struct wlc_ssid *ssid;
7525         struct bcm_tlv *tim;
7526         s32 beacon_interval;
7527         s32 dtim_period;
7528         size_t ie_len;
7529         u8 *ie;
7530         u8 *curbssid;
7531         s32 err = 0;
7532         struct wiphy *wiphy;
7533
7534         wiphy = wl_to_wiphy(wl);
7535
7536         ssid = (struct wlc_ssid *)wl_read_prof(wl, ndev, WL_PROF_SSID);
7537         curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7538         bss = cfg80211_get_bss(wiphy, NULL, curbssid,
7539                 ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS,
7540                 WLAN_CAPABILITY_ESS);
7541
7542         mutex_lock(&wl->usr_sync);
7543         if (!bss) {
7544                 WL_DBG(("Could not find the AP\n"));
7545                 *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
7546                 err = wldev_ioctl(ndev, WLC_GET_BSS_INFO,
7547                         wl->extra_buf, WL_EXTRA_BUF_MAX, false);
7548                 if (unlikely(err)) {
7549                         WL_ERR(("Could not get bss info %d\n", err));
7550                         goto update_bss_info_out;
7551                 }
7552                 bi = (struct wl_bss_info *)(wl->extra_buf + 4);
7553                 if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) {
7554                         WL_ERR(("Bssid doesn't match\n"));
7555                         err = -EIO;
7556                         goto update_bss_info_out;
7557                 }
7558                 err = wl_inform_single_bss(wl, bi);
7559                 if (unlikely(err))
7560                         goto update_bss_info_out;
7561
7562                 ie = ((u8 *)bi) + bi->ie_offset;
7563                 ie_len = bi->ie_length;
7564                 beacon_interval = cpu_to_le16(bi->beacon_period);
7565         } else {
7566                 WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid));
7567 #if defined(WL_CFG80211_P2P_DEV_IF)
7568                 ie = (u8 *)bss->ies->data;
7569                 ie_len = bss->ies->len;
7570 #else
7571                 ie = bss->information_elements;
7572                 ie_len = bss->len_information_elements;
7573 #endif /* WL_CFG80211_P2P_DEV_IF */
7574                 beacon_interval = bss->beacon_interval;
7575 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
7576                 cfg80211_put_bss(wiphy, bss);
7577 #else
7578                 cfg80211_put_bss(bss);
7579 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
7580         }
7581
7582         tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
7583         if (tim) {
7584                 dtim_period = tim->data[1];
7585         } else {
7586                 /*
7587                 * active scan was done so we could not get dtim
7588                 * information out of probe response.
7589                 * so we speficially query dtim information.
7590                 */
7591                 err = wldev_ioctl(ndev, WLC_GET_DTIMPRD,
7592                         &dtim_period, sizeof(dtim_period), false);
7593                 if (unlikely(err)) {
7594                         WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
7595                         goto update_bss_info_out;
7596                 }
7597         }
7598
7599         wl_update_prof(wl, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT);
7600         wl_update_prof(wl, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
7601
7602 update_bss_info_out:
7603         if (unlikely(err)) {
7604                 WL_ERR(("Failed with error %d\n", err));
7605         }
7606         mutex_unlock(&wl->usr_sync);
7607         return err;
7608 }
7609
7610 static s32
7611 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
7612         const wl_event_msg_t *e, void *data)
7613 {
7614         struct wl_connect_info *conn_info = wl_to_conn(wl);
7615         s32 err = 0;
7616         u8 *curbssid;
7617 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || 0
7618         struct wl_bss_info *bss_info;
7619         struct wiphy *wiphy = wl_to_wiphy(wl);
7620         struct ieee80211_supported_band *band;
7621         struct ieee80211_channel *notify_channel = NULL;
7622         u8 *buf;
7623         u16 channel;
7624         u32 freq;
7625 #endif 
7626
7627         wl_get_assoc_ies(wl, ndev);
7628         wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID);
7629         curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7630         wl_update_bss_info(wl, ndev);
7631         wl_update_pmklist(ndev, wl->pmk_list, err);
7632
7633 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || 0
7634         /* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */
7635         buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
7636         if (!buf)
7637                 goto done;
7638
7639         *(__le32 *)buf = htod32(WL_EXTRA_BUF_MAX);
7640         err = wldev_ioctl(ndev, WLC_GET_BSS_INFO, buf, WL_EXTRA_BUF_MAX, false);
7641         if (err)
7642                 goto done;
7643
7644         bss_info = (struct wl_bss_info *)(buf + 4);
7645         channel = bss_info->ctl_ch ? bss_info->ctl_ch :
7646                 CHSPEC_CHANNEL(wl_chspec_driver_to_host(bss_info->chanspec));
7647         if (channel <= CH_MAX_2G_CHANNEL)
7648                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
7649         else
7650                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
7651         freq = ieee80211_channel_to_frequency(channel, band->band);
7652         notify_channel = ieee80211_get_channel(wiphy, freq);
7653 done:
7654         kfree(buf);
7655 #endif 
7656         printk("wl_bss_roaming_done succeeded to " MACDBG "\n",
7657                 MAC2STRDBG((u8*)(&e->addr)));
7658
7659         if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) {
7660                 WL_DBG(("BSSID Mismatch, so indicate roam to cfg80211\n"));
7661                 cfg80211_roamed(ndev,
7662 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || 0
7663                         notify_channel,
7664 #endif
7665                         curbssid,
7666                         conn_info->req_ie, conn_info->req_ie_len,
7667                         conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
7668         }
7669         WL_DBG(("Report roaming result\n"));
7670
7671         wl_set_drv_status(wl, CONNECTED, ndev);
7672
7673         return err;
7674 }
7675
7676 static s32
7677 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
7678         const wl_event_msg_t *e, void *data, bool completed)
7679 {
7680         struct wl_connect_info *conn_info = wl_to_conn(wl);
7681         struct wl_security *sec = wl_read_prof(wl, ndev, WL_PROF_SEC);
7682         s32 err = 0;
7683         u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7684         if (!sec) {
7685                 WL_ERR(("sec is NULL\n"));
7686                 return -ENODEV;
7687         }
7688         WL_DBG((" enter\n"));
7689 #ifdef ESCAN_RESULT_PATCH
7690         if (wl_get_drv_status(wl, CONNECTED, ndev)) {
7691                 if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) {
7692                         WL_DBG((" Connected event of connected device e=%d s=%d, ignore it\n",
7693                                 ntoh32(e->event_type), ntoh32(e->status)));
7694                         return err;
7695                 }
7696         }
7697         if (memcmp(curbssid, broad_bssid, ETHER_ADDR_LEN) == 0 &&
7698                 memcmp(broad_bssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) {
7699                 WL_DBG(("copy bssid\n"));
7700                 memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN);
7701         }
7702
7703 #else
7704         if (wl->scan_request) {
7705                 wl_notify_escan_complete(wl, ndev, true, true);
7706         }
7707 #endif /* ESCAN_RESULT_PATCH */
7708         if (wl_get_drv_status(wl, CONNECTING, ndev) && (e->event_type == WLC_E_SET_SSID)) {
7709                 wl_cfg80211_scan_abort(wl);
7710                 wl_clr_drv_status(wl, CONNECTING, ndev);
7711                 if (completed) {
7712                         wl_get_assoc_ies(wl, ndev);
7713                         wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID);
7714                         curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7715                         wl_update_bss_info(wl, ndev);
7716                         wl_update_pmklist(ndev, wl->pmk_list, err);
7717                         wl_set_drv_status(wl, CONNECTED, ndev);
7718                         if (ndev != wl_to_prmry_ndev(wl)) {
7719                                 /* reinitialize completion to clear previous count */
7720                                 INIT_COMPLETION(wl->iface_disable);
7721                         }
7722                 }
7723                 cfg80211_connect_result(ndev,
7724                         curbssid,
7725                         conn_info->req_ie,
7726                         conn_info->req_ie_len,
7727                         conn_info->resp_ie,
7728                         conn_info->resp_ie_len,
7729                         completed ? WLAN_STATUS_SUCCESS :
7730                         (sec->auth_assoc_res_status) ?
7731                         sec->auth_assoc_res_status :
7732                         WLAN_STATUS_UNSPECIFIED_FAILURE,
7733                         GFP_KERNEL);
7734                 if (completed)
7735                         WL_INFO(("Report connect result - connection succeeded\n"));
7736                 else
7737                         WL_ERR(("Report connect result - connection failed\n"));
7738         }
7739         return err;
7740 }
7741
7742 static s32
7743 wl_notify_mic_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7744         const wl_event_msg_t *e, void *data)
7745 {
7746         struct net_device *ndev = NULL;
7747         u16 flags = ntoh16(e->flags);
7748         enum nl80211_key_type key_type;
7749
7750         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7751
7752         mutex_lock(&wl->usr_sync);
7753         if (flags & WLC_EVENT_MSG_GROUP)
7754                 key_type = NL80211_KEYTYPE_GROUP;
7755         else
7756                 key_type = NL80211_KEYTYPE_PAIRWISE;
7757
7758         cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
7759                 NULL, GFP_KERNEL);
7760         mutex_unlock(&wl->usr_sync);
7761
7762         return 0;
7763 }
7764
7765 #ifdef PNO_SUPPORT
7766 static s32
7767 wl_notify_pfn_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7768         const wl_event_msg_t *e, void *data)
7769 {
7770         struct net_device *ndev = NULL;
7771
7772         WL_ERR((">>> PNO Event\n"));
7773
7774         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7775
7776 #ifndef WL_SCHED_SCAN
7777         mutex_lock(&wl->usr_sync);
7778         /* TODO: Use cfg80211_sched_scan_results(wiphy); */
7779         cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
7780         mutex_unlock(&wl->usr_sync);
7781 #else
7782         /* If cfg80211 scheduled scan is supported, report the pno results via sched
7783          * scan results
7784          */
7785         wl_notify_sched_scan_results(wl, ndev, e, data);
7786 #endif /* WL_SCHED_SCAN */
7787         return 0;
7788 }
7789 #endif /* PNO_SUPPORT */
7790
7791 static s32
7792 wl_notify_scan_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7793         const wl_event_msg_t *e, void *data)
7794 {
7795         struct channel_info channel_inform;
7796         struct wl_scan_results *bss_list;
7797         struct net_device *ndev = NULL;
7798         u32 len = WL_SCAN_BUF_MAX;
7799         s32 err = 0;
7800         unsigned long flags;
7801
7802         WL_DBG(("Enter \n"));
7803         if (!wl_get_drv_status(wl, SCANNING, ndev)) {
7804                 WL_ERR(("scan is not ready \n"));
7805                 return err;
7806         }
7807         if (wl->iscan_on && wl->iscan_kickstart)
7808                 return wl_wakeup_iscan(wl_to_iscan(wl));
7809
7810         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7811
7812         mutex_lock(&wl->usr_sync);
7813         wl_clr_drv_status(wl, SCANNING, ndev);
7814         err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
7815                 sizeof(channel_inform), false);
7816         if (unlikely(err)) {
7817                 WL_ERR(("scan busy (%d)\n", err));
7818                 goto scan_done_out;
7819         }
7820         channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
7821         if (unlikely(channel_inform.scan_channel)) {
7822
7823                 WL_DBG(("channel_inform.scan_channel (%d)\n",
7824                         channel_inform.scan_channel));
7825         }
7826         wl->bss_list = wl->scan_results;
7827         bss_list = wl->bss_list;
7828         memset(bss_list, 0, len);
7829         bss_list->buflen = htod32(len);
7830         err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, false);
7831         if (unlikely(err) && unlikely(!wl->scan_suppressed)) {
7832                 WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
7833                 err = -EINVAL;
7834                 goto scan_done_out;
7835         }
7836         bss_list->buflen = dtoh32(bss_list->buflen);
7837         bss_list->version = dtoh32(bss_list->version);
7838         bss_list->count = dtoh32(bss_list->count);
7839
7840         err = wl_inform_bss(wl);
7841
7842 scan_done_out:
7843         del_timer_sync(&wl->scan_timeout);
7844         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
7845         if (wl->scan_request) {
7846                 cfg80211_scan_done(wl->scan_request, false);
7847                 wl->scan_request = NULL;
7848         }
7849         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
7850         WL_DBG(("cfg80211_scan_done\n"));
7851         mutex_unlock(&wl->usr_sync);
7852         return err;
7853 }
7854
7855 static s32
7856 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
7857         const struct ether_addr *sa, const struct ether_addr *bssid,
7858         u8 **pheader, u32 *body_len, u8 *pbody)
7859 {
7860         struct dot11_management_header *hdr;
7861         u32 totlen = 0;
7862         s32 err = 0;
7863         u8 *offset;
7864         u32 prebody_len = *body_len;
7865         switch (fc) {
7866                 case FC_ASSOC_REQ:
7867                         /* capability , listen interval */
7868                         totlen = DOT11_ASSOC_REQ_FIXED_LEN;
7869                         *body_len += DOT11_ASSOC_REQ_FIXED_LEN;
7870                         break;
7871
7872                 case FC_REASSOC_REQ:
7873                         /* capability, listen inteval, ap address */
7874                         totlen = DOT11_REASSOC_REQ_FIXED_LEN;
7875                         *body_len += DOT11_REASSOC_REQ_FIXED_LEN;
7876                         break;
7877         }
7878         totlen += DOT11_MGMT_HDR_LEN + prebody_len;
7879         *pheader = kzalloc(totlen, GFP_KERNEL);
7880         if (*pheader == NULL) {
7881                 WL_ERR(("memory alloc failed \n"));
7882                 return -ENOMEM;
7883         }
7884         hdr = (struct dot11_management_header *) (*pheader);
7885         hdr->fc = htol16(fc);
7886         hdr->durid = 0;
7887         hdr->seq = 0;
7888         offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
7889         bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
7890         bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
7891         bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
7892         if ((pbody != NULL) && prebody_len)
7893                 bcopy((const char*)pbody, offset, prebody_len);
7894         *body_len = totlen;
7895         return err;
7896 }
7897
7898
7899 void
7900 wl_stop_wait_next_action_frame(struct wl_priv *wl)
7901 {
7902         if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) {
7903                 if (!(wl_get_p2p_status(wl, ACTION_TX_COMPLETED) ||
7904                         wl_get_p2p_status(wl, ACTION_TX_NOACK)))
7905                         wl_set_p2p_status(wl, ACTION_TX_COMPLETED);
7906
7907                 WL_DBG(("*** Wake UP ** abort actframe iovar\n"));
7908                 /* if channel is not zero, "actfame" uses off channel scan.
7909                  * So abort scan for off channel completion.
7910                  */
7911                 if (wl->af_sent_channel)
7912                         wl_cfg80211_scan_abort(wl);
7913         }
7914 #ifdef WL_CFG80211_SYNC_GON
7915         else if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN)) {
7916                 WL_DBG(("*** Wake UP ** abort listen for next af frame\n"));
7917                 /* So abort scan to cancel listen */
7918                 wl_cfg80211_scan_abort(wl);
7919         }
7920 #endif /* WL_CFG80211_SYNC_GON */
7921 }
7922
7923
7924 int wl_cfg80211_get_ioctl_version(void)
7925 {
7926         return ioctl_version;
7927 }
7928
7929 static s32
7930 wl_notify_rx_mgmt_frame(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7931         const wl_event_msg_t *e, void *data)
7932
7933 {
7934         struct ieee80211_supported_band *band;
7935         struct wiphy *wiphy = wl_to_wiphy(wl);
7936         struct ether_addr da;
7937         struct ether_addr bssid;
7938         bool isfree = false;
7939         s32 err = 0;
7940         s32 freq;
7941         struct net_device *ndev = NULL;
7942         wifi_p2p_pub_act_frame_t *act_frm = NULL;
7943         wifi_p2p_action_frame_t *p2p_act_frm = NULL;
7944         wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
7945         wl_event_rx_frame_data_t *rxframe =
7946                 (wl_event_rx_frame_data_t*)data;
7947         u32 event = ntoh32(e->event_type);
7948         u8 *mgmt_frame;
7949         u8 bsscfgidx = e->bsscfgidx;
7950         u32 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t);
7951         u16 channel = ((ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK));
7952
7953         memset(&bssid, 0, ETHER_ADDR_LEN);
7954
7955         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7956
7957         if (channel <= CH_MAX_2G_CHANNEL)
7958                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
7959         else
7960                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
7961         if (!band) {
7962                 WL_ERR(("No valid band"));
7963                 return -EINVAL;
7964         }
7965 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
7966         freq = ieee80211_channel_to_frequency(channel);
7967         (void)band->band;
7968 #else
7969         freq = ieee80211_channel_to_frequency(channel, band->band);
7970 #endif
7971         if (event == WLC_E_ACTION_FRAME_RX) {
7972                 wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
7973                         NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync);
7974
7975                 err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
7976                 if (err < 0)
7977                          WL_ERR(("WLC_GET_BSSID error %d\n", err));
7978                 memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN);
7979                 err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid,
7980                         &mgmt_frame, &mgmt_frame_len,
7981                         (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1));
7982                 if (err < 0) {
7983                         WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n",
7984                                 mgmt_frame_len, channel, freq));
7985                         goto exit;
7986                 }
7987                 isfree = true;
7988                 if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
7989                         mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
7990                         act_frm = (wifi_p2p_pub_act_frame_t *)
7991                                         (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
7992                 } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
7993                         mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
7994                         p2p_act_frm = (wifi_p2p_action_frame_t *)
7995                                         (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
7996                         (void) p2p_act_frm;
7997                 } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
7998                         mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
7999
8000                         sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)
8001                                         (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
8002                         if (sd_act_frm && wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) {
8003                                 if (wl->next_af_subtype == sd_act_frm->action) {
8004                                         WL_DBG(("We got a right next frame of SD!(%d)\n",
8005                                                 sd_act_frm->action));
8006                                         wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev);
8007
8008                                         /* Stop waiting for next AF. */
8009                                         wl_stop_wait_next_action_frame(wl);
8010                                 }
8011                         }
8012                         (void) sd_act_frm;
8013                 } else {
8014                         /*
8015                          *  if we got normal action frame and ndev is p2p0,
8016                          *  we have to change ndev from p2p0 to wlan0
8017                          */
8018 #if defined(WL_ENABLE_P2P_IF)
8019                         if (wl->p2p_net == cfgdev)
8020                                 cfgdev = wl_to_prmry_ndev(wl);
8021 #endif /* WL_ENABLE_P2P_IF */
8022
8023                         if (wl->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
8024                                 u8 action = 0;
8025                                 if (wl_get_public_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
8026                                         mgmt_frame_len - DOT11_MGMT_HDR_LEN, &action) != BCME_OK) {
8027                                         WL_DBG(("Recived action is not public action frame\n"));
8028                                 } else if (wl->next_af_subtype == action) {
8029                                         WL_DBG(("Recived action is the waiting action(%d)\n",
8030                                                 action));
8031                                         wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev);
8032
8033                                         /* Stop waiting for next AF. */
8034                                         wl_stop_wait_next_action_frame(wl);
8035                                 }
8036                         }
8037                 }
8038
8039                 if (act_frm) {
8040
8041                         if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) {
8042                                 if (wl->next_af_subtype == act_frm->subtype) {
8043                                         WL_DBG(("We got a right next frame!(%d)\n",
8044                                                 act_frm->subtype));
8045                                         wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev);
8046
8047                                         if (wl->next_af_subtype == P2P_PAF_GON_CONF) {
8048                                                 OSL_SLEEP(20);
8049                                         }
8050
8051                                         /* Stop waiting for next AF. */
8052                                         wl_stop_wait_next_action_frame(wl);
8053                                 }
8054                         }
8055                 }
8056
8057                 wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN],
8058                         mgmt_frame_len - DOT11_MGMT_HDR_LEN, channel);
8059                 /*
8060                  * After complete GO Negotiation, roll back to mpc mode
8061                  */
8062                 if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) ||
8063                         (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
8064                         wldev_iovar_setint(ndev, "mpc", 1);
8065                 }
8066                 if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) {
8067                         WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
8068                         wl_clr_p2p_status(wl, GO_NEG_PHASE);
8069                 }
8070         } else {
8071                 mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
8072
8073                 /* wpa supplicant use probe request event for restarting another GON Req.
8074                  * but it makes GON Req repetition.
8075                  * so if src addr of prb req is same as my target device,
8076                  * do not send probe request event during sending action frame.
8077                  */
8078                 if (event == WLC_E_P2P_PROBREQ_MSG) {
8079                         WL_DBG((" Event %s\n", (event == WLC_E_P2P_PROBREQ_MSG) ?
8080                                 "WLC_E_P2P_PROBREQ_MSG":"WLC_E_PROBREQ_MSG"));
8081
8082
8083                         /* Filter any P2P probe reqs arriving during the
8084                          * GO-NEG Phase
8085                          */
8086                         if (wl->p2p &&
8087                                 wl_get_p2p_status(wl, GO_NEG_PHASE)) {
8088                                 WL_DBG(("Filtering P2P probe_req while "
8089                                         "being in GO-Neg state\n"));
8090                                 return 0;
8091                         }
8092                 }
8093         }
8094
8095 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
8096         cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
8097 #else
8098         cfg80211_rx_mgmt(cfgdev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
8099 #endif 
8100
8101         WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n",
8102                 mgmt_frame_len, ntoh32(e->datalen), channel, freq));
8103 exit:
8104         if (isfree)
8105                 kfree(mgmt_frame);
8106         return 0;
8107 }
8108
8109 #ifdef WL_SCHED_SCAN
8110 /* If target scan is not reliable, set the below define to "1" to do a
8111  * full escan
8112  */
8113 #define FULL_ESCAN_ON_PFN_NET_FOUND             0
8114 static s32
8115 wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev,
8116         const wl_event_msg_t *e, void *data)
8117 {
8118         wl_pfn_net_info_t *netinfo, *pnetinfo;
8119         struct wiphy *wiphy     = wl_to_wiphy(wl);
8120         int err = 0;
8121         struct cfg80211_scan_request *request = NULL;
8122         struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
8123         struct ieee80211_channel *channel = NULL;
8124         int channel_req = 0;
8125         int band = 0;
8126         struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data;
8127         int n_pfn_results = pfn_result->count;
8128
8129         WL_DBG(("Enter\n"));
8130
8131         if (e->event_type == WLC_E_PFN_NET_LOST) {
8132                 WL_PNO(("PFN NET LOST event. Do Nothing \n"));
8133                 return 0;
8134         }
8135         WL_PNO((">>> PFN NET FOUND event. count:%d \n", n_pfn_results));
8136         if (n_pfn_results > 0) {
8137                 int i;
8138
8139                 if (n_pfn_results > MAX_PFN_LIST_COUNT)
8140                         n_pfn_results = MAX_PFN_LIST_COUNT;
8141                 pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t)
8142                                 - sizeof(wl_pfn_net_info_t));
8143
8144                 memset(&ssid, 0x00, sizeof(ssid));
8145
8146                 request = kzalloc(sizeof(*request)
8147                         + sizeof(*request->channels) * n_pfn_results,
8148                         GFP_KERNEL);
8149                 channel = (struct ieee80211_channel *)kzalloc(
8150                         (sizeof(struct ieee80211_channel) * n_pfn_results),
8151                         GFP_KERNEL);
8152                 if (!request || !channel) {
8153                         WL_ERR(("No memory"));
8154                         err = -ENOMEM;
8155                         goto out_err;
8156                 }
8157
8158                 request->wiphy = wiphy;
8159
8160                 for (i = 0; i < n_pfn_results; i++) {
8161                         netinfo = &pnetinfo[i];
8162                         if (!netinfo) {
8163                                 WL_ERR(("Invalid netinfo ptr. index:%d", i));
8164                                 err = -EINVAL;
8165                                 goto out_err;
8166                         }
8167                         WL_PNO((">>> SSID:%s Channel:%d \n",
8168                                 netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel));
8169                         /* PFN result doesn't have all the info which are required by the supplicant
8170                          * (For e.g IEs) Do a target Escan so that sched scan results are reported
8171                          * via wl_inform_single_bss in the required format. Escan does require the
8172                          * scan request in the form of cfg80211_scan_request. For timebeing, create
8173                          * cfg80211_scan_request one out of the received PNO event.
8174                          */
8175                         memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID,
8176                                 netinfo->pfnsubnet.SSID_len);
8177                         ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len;
8178                         request->n_ssids++;
8179
8180                         channel_req = netinfo->pfnsubnet.channel;
8181                         band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
8182                                 : NL80211_BAND_5GHZ;
8183                         channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band);
8184                         channel[i].band = band;
8185                         channel[i].flags |= IEEE80211_CHAN_NO_HT40;
8186                         request->channels[i] = &channel[i];
8187                         request->n_channels++;
8188                 }
8189
8190                 /* assign parsed ssid array */
8191                 if (request->n_ssids)
8192                         request->ssids = &ssid[0];
8193
8194                 if (wl_get_drv_status_all(wl, SCANNING)) {
8195                         /* Abort any on-going scan */
8196                         wl_notify_escan_complete(wl, ndev, true, true);
8197                 }
8198
8199                 if (wl_get_p2p_status(wl, DISCOVERY_ON)) {
8200                         WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
8201                         err = wl_cfgp2p_discover_enable_search(wl, false);
8202                         if (unlikely(err)) {
8203                                 wl_clr_drv_status(wl, SCANNING, ndev);
8204                                 goto out_err;
8205                         }
8206                 }
8207
8208                 wl_set_drv_status(wl, SCANNING, ndev);
8209 #if FULL_ESCAN_ON_PFN_NET_FOUND
8210                 WL_PNO((">>> Doing Full ESCAN on PNO event\n"));
8211                 err = wl_do_escan(wl, wiphy, ndev, NULL);
8212 #else
8213                 WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
8214                 err = wl_do_escan(wl, wiphy, ndev, request);
8215 #endif
8216                 if (err) {
8217                         wl_clr_drv_status(wl, SCANNING, ndev);
8218                         goto out_err;
8219                 }
8220                 wl->sched_scan_running = TRUE;
8221         }
8222         else {
8223                 WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
8224         }
8225 out_err:
8226         if (request)
8227                 kfree(request);
8228         if (channel)
8229                 kfree(channel);
8230         return err;
8231 }
8232 #endif /* WL_SCHED_SCAN */
8233
8234 static void wl_init_conf(struct wl_conf *conf)
8235 {
8236         WL_DBG(("Enter \n"));
8237         conf->frag_threshold = (u32)-1;
8238         conf->rts_threshold = (u32)-1;
8239         conf->retry_short = (u32)-1;
8240         conf->retry_long = (u32)-1;
8241         conf->tx_power = -1;
8242 }
8243
8244 static void wl_init_prof(struct wl_priv *wl, struct net_device *ndev)
8245 {
8246         unsigned long flags;
8247         struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
8248
8249         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
8250         memset(profile, 0, sizeof(struct wl_profile));
8251         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
8252 }
8253
8254 static void wl_init_event_handler(struct wl_priv *wl)
8255 {
8256         memset(wl->evt_handler, 0, sizeof(wl->evt_handler));
8257
8258         wl->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
8259         wl->evt_handler[WLC_E_AUTH] = wl_notify_connect_status;
8260         wl->evt_handler[WLC_E_ASSOC] = wl_notify_connect_status;
8261         wl->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
8262         wl->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
8263         wl->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
8264         wl->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
8265         wl->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
8266         wl->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
8267         wl->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;
8268         wl->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
8269         wl->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;
8270         wl->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;
8271         wl->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
8272         wl->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
8273         wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
8274         wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
8275         wl->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
8276         wl->evt_handler[WLC_E_JOIN] = wl_notify_connect_status;
8277         wl->evt_handler[WLC_E_START] = wl_notify_connect_status;
8278 #ifdef PNO_SUPPORT
8279         wl->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status;
8280 #endif /* PNO_SUPPORT */
8281 #ifdef WLTDLS
8282         wl->evt_handler[WLC_E_TDLS_PEER_EVENT] = wl_tdls_event_handler;
8283 #endif /* WLTDLS */
8284 #ifdef BCMCCX_S69
8285         wl->evt_handler[WLC_E_CCX_S69_RESP_RX] = wl_ccx_s69_response;
8286 #endif
8287 }
8288
8289 #if defined(STATIC_WL_PRIV_STRUCT)
8290 static void
8291 wl_init_escan_result_buf(struct wl_priv *wl)
8292 {
8293         wl->escan_info.escan_buf = dhd_os_prealloc(NULL, DHD_PREALLOC_WIPHY_ESCAN0, 0);
8294         bzero(wl->escan_info.escan_buf, ESCAN_BUF_SIZE);
8295 }
8296
8297 static void
8298 wl_deinit_escan_result_buf(struct wl_priv *wl)
8299 {
8300         wl->escan_info.escan_buf = NULL;
8301
8302 }
8303 #endif /* STATIC_WL_PRIV_STRUCT */
8304
8305 static s32 wl_init_priv_mem(struct wl_priv *wl)
8306 {
8307         WL_DBG(("Enter \n"));
8308         wl->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
8309         if (unlikely(!wl->scan_results)) {
8310                 WL_ERR(("Scan results alloc failed\n"));
8311                 goto init_priv_mem_out;
8312         }
8313         wl->conf = (void *)kzalloc(sizeof(*wl->conf), GFP_KERNEL);
8314         if (unlikely(!wl->conf)) {
8315                 WL_ERR(("wl_conf alloc failed\n"));
8316                 goto init_priv_mem_out;
8317         }
8318         wl->scan_req_int =
8319             (void *)kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL);
8320         if (unlikely(!wl->scan_req_int)) {
8321                 WL_ERR(("Scan req alloc failed\n"));
8322                 goto init_priv_mem_out;
8323         }
8324         wl->ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
8325         if (unlikely(!wl->ioctl_buf)) {
8326                 WL_ERR(("Ioctl buf alloc failed\n"));
8327                 goto init_priv_mem_out;
8328         }
8329         wl->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
8330         if (unlikely(!wl->escan_ioctl_buf)) {
8331                 WL_ERR(("Ioctl buf alloc failed\n"));
8332                 goto init_priv_mem_out;
8333         }
8334         wl->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
8335         if (unlikely(!wl->extra_buf)) {
8336                 WL_ERR(("Extra buf alloc failed\n"));
8337                 goto init_priv_mem_out;
8338         }
8339         wl->iscan = (void *)kzalloc(sizeof(*wl->iscan), GFP_KERNEL);
8340         if (unlikely(!wl->iscan)) {
8341                 WL_ERR(("Iscan buf alloc failed\n"));
8342                 goto init_priv_mem_out;
8343         }
8344         wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL);
8345         if (unlikely(!wl->pmk_list)) {
8346                 WL_ERR(("pmk list alloc failed\n"));
8347                 goto init_priv_mem_out;
8348         }
8349         wl->sta_info = (void *)kzalloc(sizeof(*wl->sta_info), GFP_KERNEL);
8350         if (unlikely(!wl->sta_info)) {
8351                 WL_ERR(("sta info  alloc failed\n"));
8352                 goto init_priv_mem_out;
8353         }
8354
8355 #if defined(STATIC_WL_PRIV_STRUCT)
8356         wl->conn_info = (void *)kzalloc(sizeof(*wl->conn_info), GFP_KERNEL);
8357         if (unlikely(!wl->conn_info)) {
8358                 WL_ERR(("wl->conn_info  alloc failed\n"));
8359                 goto init_priv_mem_out;
8360         }
8361         wl->ie = (void *)kzalloc(sizeof(*wl->ie), GFP_KERNEL);
8362         if (unlikely(!wl->ie)) {
8363                 WL_ERR(("wl->ie  alloc failed\n"));
8364                 goto init_priv_mem_out;
8365         }
8366         wl_init_escan_result_buf(wl);
8367 #endif /* STATIC_WL_PRIV_STRUCT */
8368         wl->afx_hdl = (void *)kzalloc(sizeof(*wl->afx_hdl), GFP_KERNEL);
8369         if (unlikely(!wl->afx_hdl)) {
8370                 WL_ERR(("afx hdl  alloc failed\n"));
8371                 goto init_priv_mem_out;
8372         } else {
8373                 init_completion(&wl->act_frm_scan);
8374                 init_completion(&wl->wait_next_af);
8375
8376                 INIT_WORK(&wl->afx_hdl->work, wl_cfg80211_afx_handler);
8377         }
8378         return 0;
8379
8380 init_priv_mem_out:
8381         wl_deinit_priv_mem(wl);
8382
8383         return -ENOMEM;
8384 }
8385
8386 static void wl_deinit_priv_mem(struct wl_priv *wl)
8387 {
8388         kfree(wl->scan_results);
8389         wl->scan_results = NULL;
8390         kfree(wl->conf);
8391         wl->conf = NULL;
8392         kfree(wl->scan_req_int);
8393         wl->scan_req_int = NULL;
8394         kfree(wl->ioctl_buf);
8395         wl->ioctl_buf = NULL;
8396         kfree(wl->escan_ioctl_buf);
8397         wl->escan_ioctl_buf = NULL;
8398         kfree(wl->extra_buf);
8399         wl->extra_buf = NULL;
8400         kfree(wl->iscan);
8401         wl->iscan = NULL;
8402         kfree(wl->pmk_list);
8403         wl->pmk_list = NULL;
8404         kfree(wl->sta_info);
8405         wl->sta_info = NULL;
8406 #if defined(STATIC_WL_PRIV_STRUCT)
8407         kfree(wl->conn_info);
8408         wl->conn_info = NULL;
8409         kfree(wl->ie);
8410         wl->ie = NULL;
8411         wl_deinit_escan_result_buf(wl);
8412 #endif /* STATIC_WL_PRIV_STRUCT */
8413         if (wl->afx_hdl) {
8414                 cancel_work_sync(&wl->afx_hdl->work);
8415                 kfree(wl->afx_hdl);
8416                 wl->afx_hdl = NULL;
8417         }
8418
8419         if (wl->ap_info) {
8420                 kfree(wl->ap_info->wpa_ie);
8421                 kfree(wl->ap_info->rsn_ie);
8422                 kfree(wl->ap_info->wps_ie);
8423                 kfree(wl->ap_info);
8424                 wl->ap_info = NULL;
8425         }
8426 }
8427
8428 static s32 wl_create_event_handler(struct wl_priv *wl)
8429 {
8430         int ret = 0;
8431         WL_DBG(("Enter \n"));
8432
8433         /* Do not use DHD in cfg driver */
8434         wl->event_tsk.thr_pid = -1;
8435
8436         PROC_START(wl_event_handler, wl, &wl->event_tsk, 0, "wl_event_handler");
8437         if (wl->event_tsk.thr_pid < 0)
8438                 ret = -ENOMEM;
8439         return ret;
8440 }
8441
8442 static void wl_destroy_event_handler(struct wl_priv *wl)
8443 {
8444         if (wl->event_tsk.thr_pid >= 0)
8445                 PROC_STOP(&wl->event_tsk);
8446 }
8447
8448 static void wl_term_iscan(struct wl_priv *wl)
8449 {
8450         struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
8451         WL_TRACE(("In\n"));
8452         if (wl->iscan_on && iscan->tsk) {
8453                 iscan->state = WL_ISCAN_STATE_IDLE;
8454                 WL_INFO(("SIGTERM\n"));
8455                 send_sig(SIGTERM, iscan->tsk, 1);
8456                 WL_DBG(("kthread_stop\n"));
8457                 kthread_stop(iscan->tsk);
8458                 iscan->tsk = NULL;
8459         }
8460 }
8461
8462 static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted)
8463 {
8464         struct wl_priv *wl = iscan_to_wl(iscan);
8465         struct net_device *ndev = wl_to_prmry_ndev(wl);
8466         unsigned long flags;
8467
8468         WL_DBG(("Enter \n"));
8469         if (!wl_get_drv_status(wl, SCANNING, ndev)) {
8470                 wl_clr_drv_status(wl, SCANNING, ndev);
8471                 WL_ERR(("Scan complete while device not scanning\n"));
8472                 return;
8473         }
8474         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
8475         wl_clr_drv_status(wl, SCANNING, ndev);
8476         if (likely(wl->scan_request)) {
8477                 cfg80211_scan_done(wl->scan_request, aborted);
8478                 wl->scan_request = NULL;
8479         }
8480         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
8481         wl->iscan_kickstart = false;
8482 }
8483
8484 static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan)
8485 {
8486         if (likely(iscan->state != WL_ISCAN_STATE_IDLE)) {
8487                 WL_DBG(("wake up iscan\n"));
8488                 up(&iscan->sync);
8489                 return 0;
8490         }
8491
8492         return -EIO;
8493 }
8494
8495 static s32
8496 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
8497         struct wl_scan_results **bss_list)
8498 {
8499         struct wl_iscan_results list;
8500         struct wl_scan_results *results;
8501         struct wl_iscan_results *list_buf;
8502         s32 err = 0;
8503
8504         WL_DBG(("Enter \n"));
8505         memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
8506         list_buf = (struct wl_iscan_results *)iscan->scan_buf;
8507         results = &list_buf->results;
8508         results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
8509         results->version = 0;
8510         results->count = 0;
8511
8512         memset(&list, 0, sizeof(list));
8513         list.results.buflen = htod32(WL_ISCAN_BUF_MAX);
8514         err = wldev_iovar_getbuf(iscan->dev, "iscanresults", &list,
8515                 WL_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf,
8516                 WL_ISCAN_BUF_MAX, NULL);
8517         if (unlikely(err)) {
8518                 WL_ERR(("error (%d)\n", err));
8519                 return err;
8520         }
8521         results->buflen = dtoh32(results->buflen);
8522         results->version = dtoh32(results->version);
8523         results->count = dtoh32(results->count);
8524         WL_DBG(("results->count = %d\n", results->count));
8525         WL_DBG(("results->buflen = %d\n", results->buflen));
8526         *status = dtoh32(list_buf->status);
8527         *bss_list = results;
8528
8529         return err;
8530 }
8531
8532 static s32 wl_iscan_done(struct wl_priv *wl)
8533 {
8534         struct wl_iscan_ctrl *iscan = wl->iscan;
8535         s32 err = 0;
8536
8537         iscan->state = WL_ISCAN_STATE_IDLE;
8538         mutex_lock(&wl->usr_sync);
8539         wl_inform_bss(wl);
8540         wl_notify_iscan_complete(iscan, false);
8541         mutex_unlock(&wl->usr_sync);
8542
8543         return err;
8544 }
8545
8546 static s32 wl_iscan_pending(struct wl_priv *wl)
8547 {
8548         struct wl_iscan_ctrl *iscan = wl->iscan;
8549         s32 err = 0;
8550
8551         /* Reschedule the timer */
8552         mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms));
8553         iscan->timer_on = 1;
8554
8555         return err;
8556 }
8557
8558 static s32 wl_iscan_inprogress(struct wl_priv *wl)
8559 {
8560         struct wl_iscan_ctrl *iscan = wl->iscan;
8561         s32 err = 0;
8562
8563         mutex_lock(&wl->usr_sync);
8564         wl_inform_bss(wl);
8565         wl_run_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
8566         mutex_unlock(&wl->usr_sync);
8567         /* Reschedule the timer */
8568         mod_timer(&iscan->timer, jiffies +  msecs_to_jiffies(iscan->timer_ms));
8569         iscan->timer_on = 1;
8570
8571         return err;
8572 }
8573
8574 static s32 wl_iscan_aborted(struct wl_priv *wl)
8575 {
8576         struct wl_iscan_ctrl *iscan = wl->iscan;
8577         s32 err = 0;
8578
8579         iscan->state = WL_ISCAN_STATE_IDLE;
8580         mutex_lock(&wl->usr_sync);
8581         wl_notify_iscan_complete(iscan, true);
8582         mutex_unlock(&wl->usr_sync);
8583
8584         return err;
8585 }
8586
8587 static s32 wl_iscan_thread(void *data)
8588 {
8589         struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
8590         struct wl_priv *wl = iscan_to_wl(iscan);
8591         u32 status;
8592         int err = 0;
8593
8594         allow_signal(SIGTERM);
8595         status = WL_SCAN_RESULTS_PARTIAL;
8596         while (likely(!down_interruptible(&iscan->sync))) {
8597                 if (kthread_should_stop())
8598                         break;
8599                 if (iscan->timer_on) {
8600                         del_timer_sync(&iscan->timer);
8601                         iscan->timer_on = 0;
8602                 }
8603                 mutex_lock(&wl->usr_sync);
8604                 err = wl_get_iscan_results(iscan, &status, &wl->bss_list);
8605                 if (unlikely(err)) {
8606                         status = WL_SCAN_RESULTS_ABORTED;
8607                         WL_ERR(("Abort iscan\n"));
8608                 }
8609                 mutex_unlock(&wl->usr_sync);
8610                 iscan->iscan_handler[status] (wl);
8611         }
8612         if (iscan->timer_on) {
8613                 del_timer_sync(&iscan->timer);
8614                 iscan->timer_on = 0;
8615         }
8616         WL_DBG(("was terminated\n"));
8617
8618         return 0;
8619 }
8620
8621 static void wl_scan_timeout(unsigned long data)
8622 {
8623         wl_event_msg_t msg;
8624         struct wl_priv *wl = (struct wl_priv *)data;
8625
8626         if (!(wl->scan_request)) {
8627                 WL_ERR(("timer expired but no scan request\n"));
8628                 return;
8629         }
8630         bzero(&msg, sizeof(wl_event_msg_t));
8631         WL_ERR(("timer expired\n"));
8632         if (wl->escan_on) {
8633                 msg.event_type = hton32(WLC_E_ESCAN_RESULT);
8634                 msg.status = hton32(WLC_E_STATUS_TIMEOUT);
8635                 msg.reason = 0xFFFFFFFF;
8636                 wl_cfg80211_event(wl_to_prmry_ndev(wl), &msg, NULL);
8637         } else {
8638                 /* Need to check it try to access SDIO */
8639                 WL_ERR(("SCAN Timeout(ISCAN)\n"));
8640                 wl_notify_iscan_complete(wl_to_iscan(wl), true);
8641         }
8642 }
8643
8644 static void wl_iscan_timer(unsigned long data)
8645 {
8646         struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
8647
8648         if (iscan) {
8649                 iscan->timer_on = 0;
8650                 WL_DBG(("timer expired\n"));
8651                 wl_wakeup_iscan(iscan);
8652         }
8653 }
8654
8655 static s32 wl_invoke_iscan(struct wl_priv *wl)
8656 {
8657         struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
8658         int err = 0;
8659
8660         if (wl->iscan_on && !iscan->tsk) {
8661                 iscan->state = WL_ISCAN_STATE_IDLE;
8662                 sema_init(&iscan->sync, 0);
8663                 iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan");
8664                 if (IS_ERR(iscan->tsk)) {
8665                         WL_ERR(("Could not create iscan thread\n"));
8666                         iscan->tsk = NULL;
8667                         return -ENOMEM;
8668                 }
8669         }
8670
8671         return err;
8672 }
8673
8674 static void wl_init_iscan_handler(struct wl_iscan_ctrl *iscan)
8675 {
8676         memset(iscan->iscan_handler, 0, sizeof(iscan->iscan_handler));
8677         iscan->iscan_handler[WL_SCAN_RESULTS_SUCCESS] = wl_iscan_done;
8678         iscan->iscan_handler[WL_SCAN_RESULTS_PARTIAL] = wl_iscan_inprogress;
8679         iscan->iscan_handler[WL_SCAN_RESULTS_PENDING] = wl_iscan_pending;
8680         iscan->iscan_handler[WL_SCAN_RESULTS_ABORTED] = wl_iscan_aborted;
8681         iscan->iscan_handler[WL_SCAN_RESULTS_NO_MEM] = wl_iscan_aborted;
8682 }
8683
8684 static s32
8685 wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
8686         unsigned long state,
8687         void *ndev)
8688 {
8689         struct net_device *dev = ndev;
8690         struct wireless_dev *wdev = dev->ieee80211_ptr;
8691         struct wl_priv *wl = wlcfg_drv_priv;
8692         int refcnt = 0;
8693
8694         WL_DBG(("Enter \n"));
8695         if (!wdev || !wl || dev == wl_to_prmry_ndev(wl))
8696                 return NOTIFY_DONE;
8697         switch (state) {
8698                 case NETDEV_DOWN:
8699                 {
8700                         int max_wait_timeout = 2;
8701                         int max_wait_count = 100;
8702                         unsigned long limit = jiffies + max_wait_timeout * HZ;
8703                         while (work_pending(&wdev->cleanup_work)) {
8704                                 if (refcnt%5 == 0) {
8705                                         WL_ERR(("[NETDEV_DOWN] wait for "
8706                                                 "complete of cleanup_work"
8707                                                 " (%d th)\n", refcnt));
8708                                 }
8709                                 if (!time_before(jiffies, limit)) {
8710                                         WL_ERR(("[NETDEV_DOWN] cleanup_work"
8711                                                 " of CFG80211 is not"
8712                                                 " completed in %d sec\n",
8713                                                 max_wait_timeout));
8714                                         break;
8715                                 }
8716                                 if (refcnt >= max_wait_count) {
8717                                         WL_ERR(("[NETDEV_DOWN] cleanup_work"
8718                                                 " of CFG80211 is not"
8719                                                 " completed in %d loop\n",
8720                                                 max_wait_count));
8721                                         break;
8722                                 }
8723                                 set_current_state(TASK_INTERRUPTIBLE);
8724                                 schedule_timeout(100);
8725                                 set_current_state(TASK_RUNNING);
8726                                 refcnt++;
8727                         }
8728                         break;
8729                 }
8730
8731                 case NETDEV_UNREGISTER:
8732                         /* after calling list_del_rcu(&wdev->list) */
8733                         wl_dealloc_netinfo(wl, ndev);
8734                         break;
8735                 case NETDEV_GOING_DOWN:
8736                         /* At NETDEV_DOWN state, wdev_cleanup_work work will be called.
8737                         *  In front of door, the function checks
8738                         *  whether current scan is working or not.
8739                         *  If the scanning is still working, wdev_cleanup_work call WARN_ON and
8740                         *  make the scan done forcibly.
8741                         */
8742                         if (wl_get_drv_status(wl, SCANNING, dev)) {
8743                                 if (wl->escan_on) {
8744                                         wl_notify_escan_complete(wl, dev, true, true);
8745                                 }
8746                         }
8747                         break;
8748         }
8749         return NOTIFY_DONE;
8750 }
8751 static struct notifier_block wl_cfg80211_netdev_notifier = {
8752         .notifier_call = wl_cfg80211_netdev_notifier_call,
8753 };
8754
8755 static void wl_cfg80211_scan_abort(struct wl_priv *wl)
8756 {
8757         wl_scan_params_t *params = NULL;
8758         s32 params_size = 0;
8759         s32 err = BCME_OK;
8760         struct net_device *dev = wl_to_prmry_ndev(wl);
8761         if (!in_atomic()) {
8762                 /* Our scan params only need space for 1 channel and 0 ssids */
8763                 params = wl_cfg80211_scan_alloc_params(-1, 0, &params_size);
8764                 if (params == NULL) {
8765                         WL_ERR(("scan params allocation failed \n"));
8766                         err = -ENOMEM;
8767                 } else {
8768                         /* Do a scan abort to stop the driver's scan engine */
8769                         err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true);
8770                         if (err < 0) {
8771                                 WL_ERR(("scan abort  failed \n"));
8772                         }
8773                         kfree(params);
8774                 }
8775         }
8776 }
8777 static s32 wl_notify_escan_complete(struct wl_priv *wl,
8778         struct net_device *ndev,
8779         bool aborted, bool fw_abort)
8780 {
8781         s32 err = BCME_OK;
8782         unsigned long flags;
8783         struct net_device *dev;
8784
8785         WL_DBG(("Enter \n"));
8786         if (!ndev) {
8787                 WL_ERR(("ndev is null\n"));
8788                 err = BCME_ERROR;
8789                 return err;
8790         }
8791
8792         if (wl->escan_info.ndev != ndev) {
8793                 WL_ERR(("ndev is different %p %p\n", wl->escan_info.ndev, ndev));
8794                 err = BCME_ERROR;
8795                 return err;
8796         }
8797
8798         if (wl->scan_request) {
8799                 dev = wl_to_prmry_ndev(wl);
8800 #if defined(WL_ENABLE_P2P_IF)
8801                 if (wl->scan_request->dev != wl->p2p_net)
8802                         dev = wl->scan_request->dev;
8803 #endif /* WL_ENABLE_P2P_IF */
8804         }
8805         else {
8806                 WL_DBG(("wl->scan_request is NULL may be internal scan."
8807                         "doing scan_abort for ndev %p primary %p",
8808                                 ndev, wl_to_prmry_ndev(wl)));
8809                 dev = ndev;
8810         }
8811         if (fw_abort && !in_atomic()) {
8812                 wl_cfg80211_scan_abort(wl);
8813         }
8814
8815         if (timer_pending(&wl->scan_timeout))
8816                 del_timer_sync(&wl->scan_timeout);
8817 #if defined(ESCAN_RESULT_PATCH)
8818         if (likely(wl->scan_request)) {
8819                 wl->bss_list = wl_escan_get_buf(wl, aborted);
8820                 wl_inform_bss(wl);
8821         }
8822 #endif /* ESCAN_RESULT_PATCH */
8823         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
8824 #ifdef WL_SCHED_SCAN
8825         if (wl->sched_scan_req && !wl->scan_request) {
8826                 WL_PNO((">>> REPORTING SCHED SCAN RESULTS \n"));
8827                 if (!aborted)
8828                         cfg80211_sched_scan_results(wl->sched_scan_req->wiphy);
8829                 wl->sched_scan_running = FALSE;
8830                 wl->sched_scan_req = NULL;
8831         }
8832 #endif /* WL_SCHED_SCAN */
8833         if (likely(wl->scan_request)) {
8834                 cfg80211_scan_done(wl->scan_request, aborted);
8835                 wl->scan_request = NULL;
8836         }
8837         if (p2p_is_on(wl))
8838                 wl_clr_p2p_status(wl, SCANNING);
8839         wl_clr_drv_status(wl, SCANNING, dev);
8840         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
8841         return err;
8842 }
8843
8844 static s32 wl_escan_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
8845         const wl_event_msg_t *e, void *data)
8846 {
8847         s32 err = BCME_OK;
8848         s32 status = ntoh32(e->status);
8849         wl_bss_info_t *bi;
8850         wl_escan_result_t *escan_result;
8851         wl_bss_info_t *bss = NULL;
8852         wl_scan_results_t *list;
8853         wifi_p2p_ie_t * p2p_ie;
8854         struct net_device *ndev = NULL;
8855         u32 bi_length;
8856         u32 i;
8857         u8 *p2p_dev_addr = NULL;
8858
8859         WL_DBG((" enter event type : %d, status : %d \n",
8860                 ntoh32(e->event_type), ntoh32(e->status)));
8861
8862         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
8863
8864         mutex_lock(&wl->usr_sync);
8865         /* P2P SCAN is coming from primary interface */
8866         if (wl_get_p2p_status(wl, SCANNING)) {
8867                 if (wl_get_drv_status_all(wl, SENDING_ACT_FRM))
8868                         ndev = wl->afx_hdl->dev;
8869                 else
8870                         ndev = wl->escan_info.ndev;
8871
8872         }
8873         if (!ndev || !wl->escan_on ||
8874                 (!wl_get_drv_status(wl, SCANNING, ndev) &&
8875                 !wl->sched_scan_running)) {
8876                 WL_ERR(("escan is not ready ndev %p wl->escan_on %d"
8877                         " drv_status 0x%x e_type %d e_states %d\n",
8878                         ndev, wl->escan_on, wl_get_drv_status(wl, SCANNING, ndev),
8879                         ntoh32(e->event_type), ntoh32(e->status)));
8880                 goto exit;
8881         }
8882         escan_result = (wl_escan_result_t *)data;
8883
8884         if (status == WLC_E_STATUS_PARTIAL) {
8885                 WL_INFO(("WLC_E_STATUS_PARTIAL \n"));
8886                 if (!escan_result) {
8887                         WL_ERR(("Invalid escan result (NULL pointer)\n"));
8888                         goto exit;
8889                 }
8890                 if (dtoh16(escan_result->bss_count) != 1) {
8891                         WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
8892                         goto exit;
8893                 }
8894                 bi = escan_result->bss_info;
8895                 if (!bi) {
8896                         WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
8897                         goto exit;
8898                 }
8899                 bi_length = dtoh32(bi->length);
8900                 if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
8901                         WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length));
8902                         goto exit;
8903                 }
8904                 if (wl_escan_check_sync_id(status, escan_result->sync_id,
8905                         wl->escan_info.cur_sync_id) < 0)
8906                         goto exit;
8907
8908                 if (!(wl_to_wiphy(wl)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
8909                         if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
8910                                 WL_DBG(("Ignoring IBSS result\n"));
8911                                 goto exit;
8912                         }
8913                 }
8914
8915                 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
8916                         p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
8917                         if (p2p_dev_addr && !memcmp(p2p_dev_addr,
8918                                 wl->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
8919                                 s32 channel = wf_chspec_ctlchan(
8920                                         wl_chspec_driver_to_host(bi->chanspec));
8921
8922                                 if ((channel > MAXCHANNEL) || (channel <= 0))
8923                                         channel = WL_INVALID;
8924                                 else
8925                                         WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
8926                                                 " channel : %d\n",
8927                                                 MAC2STRDBG(wl->afx_hdl->tx_dst_addr.octet),
8928                                                 channel));
8929
8930                                 wl_clr_p2p_status(wl, SCANNING);
8931                                 wl->afx_hdl->peer_chan = channel;
8932                                 complete(&wl->act_frm_scan);
8933                                 goto exit;
8934                         }
8935
8936                 } else {
8937                         int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
8938                         list = wl_escan_get_buf(wl, FALSE);
8939                         if (scan_req_match(wl)) {
8940                                 /* p2p scan && allow only probe response */
8941                                 if ((wl->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
8942                                         (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
8943                                         goto exit;
8944                                 if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset,
8945                                         bi->ie_length)) == NULL) {
8946                                                 WL_ERR(("Couldn't find P2PIE in probe"
8947                                                         " response/beacon\n"));
8948                                                 goto exit;
8949                                 }
8950                         }
8951                         for (i = 0; i < list->count; i++) {
8952                                 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
8953                                         : list->bss_info;
8954
8955                                 if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
8956                                         (CHSPEC_BAND(wl_chspec_driver_to_host(bi->chanspec))
8957                                         == CHSPEC_BAND(wl_chspec_driver_to_host(bss->chanspec))) &&
8958                                         bi->SSID_len == bss->SSID_len &&
8959                                         !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
8960
8961                                         /* do not allow beacon data to update
8962                                         *the data recd from a probe response
8963                                         */
8964                                         if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) &&
8965                                                 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
8966                                                 goto exit;
8967
8968                                         WL_DBG(("%s("MACDBG"), i=%d prev: RSSI %d"
8969                                                 " flags 0x%x, new: RSSI %d flags 0x%x\n",
8970                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet), i,
8971                                                 bss->RSSI, bss->flags, bi->RSSI, bi->flags));
8972
8973                                         if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
8974                                                 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) {
8975                                                 /* preserve max RSSI if the measurements are
8976                                                 * both on-channel or both off-channel
8977                                                 */
8978                                                 WL_SCAN(("%s("MACDBG"), same onchan"
8979                                                 ", RSSI: prev %d new %d\n",
8980                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
8981                                                 bss->RSSI, bi->RSSI));
8982                                                 bi->RSSI = MAX(bss->RSSI, bi->RSSI);
8983                                         } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
8984                                                 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
8985                                                 /* preserve the on-channel rssi measurement
8986                                                 * if the new measurement is off channel
8987                                                 */
8988                                                 WL_SCAN(("%s("MACDBG"), prev onchan"
8989                                                 ", RSSI: prev %d new %d\n",
8990                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
8991                                                 bss->RSSI, bi->RSSI));
8992                                                 bi->RSSI = bss->RSSI;
8993                                                 bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
8994                                         }
8995                                         if (dtoh32(bss->length) != bi_length) {
8996                                                 u32 prev_len = dtoh32(bss->length);
8997
8998                                                 WL_SCAN(("bss info replacement"
8999                                                         " is occured(bcast:%d->probresp%d)\n",
9000                                                         bss->ie_length, bi->ie_length));
9001                                                 WL_DBG(("%s("MACDBG"), replacement!(%d -> %d)\n",
9002                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
9003                                                 prev_len, bi_length));
9004
9005                                                 if (list->buflen - prev_len + bi_length
9006                                                         > ESCAN_BUF_SIZE) {
9007                                                         WL_ERR(("Buffer is too small: keep the"
9008                                                                 " previous result of this AP\n"));
9009                                                         /* Only update RSSI */
9010                                                         bss->RSSI = bi->RSSI;
9011                                                         bss->flags |= (bi->flags
9012                                                                 & WL_BSS_FLAGS_RSSI_ONCHANNEL);
9013                                                         goto exit;
9014                                                 }
9015
9016                                                 if (i < list->count - 1) {
9017                                                         /* memory copy required by this case only */
9018                                                         memmove((u8 *)bss + bi_length,
9019                                                                 (u8 *)bss + prev_len,
9020                                                                 list->buflen - cur_len - prev_len);
9021                                                 }
9022                                                 list->buflen -= prev_len;
9023                                                 list->buflen += bi_length;
9024                                         }
9025                                         list->version = dtoh32(bi->version);
9026                                         memcpy((u8 *)bss, (u8 *)bi, bi_length);
9027                                         goto exit;
9028                                 }
9029                                 cur_len += dtoh32(bss->length);
9030                         }
9031                         if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
9032                                 WL_ERR(("Buffer is too small: ignoring\n"));
9033                                 goto exit;
9034                         }
9035
9036                         memcpy(&(((char *)list)[list->buflen]), bi, bi_length);
9037                         list->version = dtoh32(bi->version);
9038                         list->buflen += bi_length;
9039                         list->count++;
9040
9041                 }
9042
9043         }
9044         else if (status == WLC_E_STATUS_SUCCESS) {
9045 #if defined(P2P_DISCOVERY_WAR)
9046                 if (scan_req_match(wl) && !wl->p2p->vif_created) {
9047                         if (wldev_iovar_setint(wl_to_prmry_ndev(wl), "mpc", 1) < 0) {
9048                                 WL_ERR(("mpc enabling back failed\n"));
9049                         }
9050                 }
9051 #endif /* defined(P2P_DISCOVERY_WAR) */
9052                 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9053                 wl_escan_print_sync_id(status, wl->escan_info.cur_sync_id,
9054                         escan_result->sync_id);
9055
9056                 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9057                         WL_INFO(("ACTION FRAME SCAN DONE\n"));
9058                         wl_clr_p2p_status(wl, SCANNING);
9059                         wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
9060                         if (wl->afx_hdl->peer_chan == WL_INVALID)
9061                                 complete(&wl->act_frm_scan);
9062                 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
9063                         WL_INFO(("ESCAN COMPLETED\n"));
9064                         wl->bss_list = wl_escan_get_buf(wl, FALSE);
9065                         if (!scan_req_match(wl)) {
9066                                 WL_TRACE_HW4(("SCAN COMPLETED: scanned AP count=%d\n",
9067                                         wl->bss_list->count));
9068                         }
9069                         wl_inform_bss(wl);
9070                         wl_notify_escan_complete(wl, ndev, false, false);
9071                 }
9072                 wl_escan_increment_sync_id(wl, SCAN_BUF_NEXT);
9073         }
9074         else if (status == WLC_E_STATUS_ABORT) {
9075 #if defined(P2P_DISCOVERY_WAR)
9076                 if (scan_req_match(wl) && !wl->p2p->vif_created) {
9077                         if (wldev_iovar_setint(wl_to_prmry_ndev(wl), "mpc", 1) < 0) {
9078                                 WL_ERR(("mpc enabling back failed\n"));
9079                         }
9080                 }
9081 #endif /* defined(P2P_DISCOVERY_WAR) */
9082                 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9083                 wl_escan_print_sync_id(status, escan_result->sync_id,
9084                         wl->escan_info.cur_sync_id);
9085                 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9086                         WL_INFO(("ACTION FRAME SCAN DONE\n"));
9087                         wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
9088                         wl_clr_p2p_status(wl, SCANNING);
9089                         if (wl->afx_hdl->peer_chan == WL_INVALID)
9090                                 complete(&wl->act_frm_scan);
9091                 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
9092                         WL_INFO(("ESCAN ABORTED\n"));
9093                         wl->bss_list = wl_escan_get_buf(wl, TRUE);
9094                         if (!scan_req_match(wl)) {
9095                                 WL_TRACE_HW4(("SCAN ABORTED: scanned AP count=%d\n",
9096                                         wl->bss_list->count));
9097                         }
9098                         wl_inform_bss(wl);
9099                         wl_notify_escan_complete(wl, ndev, true, false);
9100                 }
9101                 wl_escan_increment_sync_id(wl, SCAN_BUF_CNT);
9102         } else if (status == WLC_E_STATUS_NEWSCAN) {
9103                 WL_ERR(("WLC_E_STATUS_NEWSCAN : scan_request[%p]\n", wl->scan_request));
9104                 WL_ERR(("sync_id[%d], bss_count[%d]\n", escan_result->sync_id,
9105                         escan_result->bss_count));
9106         } else if (status == WLC_E_STATUS_TIMEOUT) {
9107                 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", wl->scan_request));
9108                 WL_ERR(("escan_on[%d], reason[0x%x]\n", wl->escan_on, e->reason));
9109                 if (e->reason == 0xFFFFFFFF) {
9110                         wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true);
9111                 }
9112         } else {
9113                 WL_ERR(("unexpected Escan Event %d : abort\n", status));
9114                 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9115                 wl_escan_print_sync_id(status, escan_result->sync_id,
9116                         wl->escan_info.cur_sync_id);
9117                 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9118                         WL_INFO(("ACTION FRAME SCAN DONE\n"));
9119                         wl_clr_p2p_status(wl, SCANNING);
9120                         wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
9121                         if (wl->afx_hdl->peer_chan == WL_INVALID)
9122                                 complete(&wl->act_frm_scan);
9123                 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
9124                         wl->bss_list = wl_escan_get_buf(wl, TRUE);
9125                         if (!scan_req_match(wl)) {
9126                                 WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): "
9127                                         "scanned AP count=%d\n",
9128                                         wl->bss_list->count));
9129                         }
9130                         wl_inform_bss(wl);
9131                         wl_notify_escan_complete(wl, ndev, true, false);
9132                 }
9133                 wl_escan_increment_sync_id(wl, 2);
9134         }
9135 exit:
9136         mutex_unlock(&wl->usr_sync);
9137         return err;
9138 }
9139
9140 static void wl_cfg80211_concurrent_roam(struct wl_priv *wl, int enable)
9141 {
9142         u32 connected_cnt  = wl_get_drv_status_all(wl, CONNECTED);
9143         struct net_info *iter, *next;
9144         int err;
9145
9146         if (!wl->roamoff_on_concurrent)
9147                 return;
9148         if (enable && connected_cnt > 1) {
9149                 for_each_ndev(wl, iter, next) {
9150                         /* Save the current roam setting */
9151                         if ((err = wldev_iovar_getint(iter->ndev, "roam_off",
9152                                 (s32 *)&iter->roam_off)) != BCME_OK) {
9153                                 WL_ERR(("%s:Failed to get current roam setting err %d\n",
9154                                         iter->ndev->name, err));
9155                                 continue;
9156                         }
9157                         if ((err = wldev_iovar_setint(iter->ndev, "roam_off", 1)) != BCME_OK) {
9158                                 WL_ERR((" %s:failed to set roam_off : %d\n",
9159                                         iter->ndev->name, err));
9160                         }
9161                 }
9162         }
9163         else if (!enable) {
9164                 for_each_ndev(wl, iter, next) {
9165                         if (iter->roam_off != WL_INVALID) {
9166                                 if ((err = wldev_iovar_setint(iter->ndev, "roam_off",
9167                                         iter->roam_off)) == BCME_OK)
9168                                         iter->roam_off = WL_INVALID;
9169                                 else {
9170                                         WL_ERR((" %s:failed to set roam_off : %d\n",
9171                                                 iter->ndev->name, err));
9172                                 }
9173                         }
9174                 }
9175         }
9176         return;
9177 }
9178
9179 static void wl_cfg80211_determine_vsdb_mode(struct wl_priv *wl)
9180 {
9181         struct net_info *iter, *next;
9182         u32 ctl_chan = 0;
9183         u32 chanspec = 0;
9184         u32 pre_ctl_chan = 0;
9185         u32 connected_cnt  = wl_get_drv_status_all(wl, CONNECTED);
9186         wl->vsdb_mode = false;
9187
9188         if (connected_cnt <= 1)  {
9189                 return;
9190         }
9191         for_each_ndev(wl, iter, next) {
9192                 chanspec = 0;
9193                 ctl_chan = 0;
9194                 if (wl_get_drv_status(wl, CONNECTED, iter->ndev)) {
9195                         if (wldev_iovar_getint(iter->ndev, "chanspec",
9196                                 (s32 *)&chanspec) == BCME_OK) {
9197                                 chanspec = wl_chspec_driver_to_host(chanspec);
9198                                 ctl_chan = wf_chspec_ctlchan(chanspec);
9199                                 wl_update_prof(wl, iter->ndev, NULL,
9200                                         &ctl_chan, WL_PROF_CHAN);
9201                         }
9202                         if (!wl->vsdb_mode) {
9203                                 if (!pre_ctl_chan && ctl_chan)
9204                                         pre_ctl_chan = ctl_chan;
9205                                 else if (pre_ctl_chan && (pre_ctl_chan != ctl_chan)) {
9206                                         wl->vsdb_mode = true;
9207                                 }
9208                         }
9209                 }
9210         }
9211         WL_ERR(("%s concurrency is enabled\n", wl->vsdb_mode ? "Multi Channel" : "Same Channel"));
9212         return;
9213 }
9214
9215 static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info,
9216         enum wl_status state, bool set)
9217 {
9218         s32 pm = PM_FAST;
9219         s32 err = BCME_OK;
9220         u32 mode;
9221         u32 chan = 0;
9222         struct net_info *iter, *next;
9223         struct net_device *primary_dev = wl_to_prmry_ndev(wl);
9224         WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n",
9225                 state, set, _net_info->pm_restore, _net_info->ndev->name));
9226
9227         if (state != WL_STATUS_CONNECTED)
9228                 return 0;
9229         mode = wl_get_mode_by_netdev(wl, _net_info->ndev);
9230         if (set) {
9231                 wl_cfg80211_concurrent_roam(wl, 1);
9232
9233                 if (mode == WL_MODE_AP) {
9234
9235                         if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false))
9236                                 WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
9237                 }
9238                 wl_cfg80211_determine_vsdb_mode(wl);
9239                 if (wl->vsdb_mode || _net_info->pm_block) {
9240                         /* Delete pm_enable_work */
9241                         wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_MAINTAIN);
9242                         /* save PM_FAST in _net_info to restore this
9243                          * if _net_info->pm_block is false
9244                          */
9245                         if (!_net_info->pm_block && (mode == WL_MODE_BSS)) {
9246                                 _net_info->pm = PM_FAST;
9247                                 _net_info->pm_restore = true;
9248                         }
9249                         pm = PM_OFF;
9250                         for_each_ndev(wl, iter, next) {
9251                                 if (iter->pm_restore)
9252                                         continue;
9253                                 /* Save the current power mode */
9254                                 err = wldev_ioctl(iter->ndev, WLC_GET_PM, &iter->pm,
9255                                         sizeof(iter->pm), false);
9256                                 WL_DBG(("%s:power save %s\n", iter->ndev->name,
9257                                         iter->pm ? "enabled" : "disabled"));
9258                                 if (!err && iter->pm) {
9259                                         iter->pm_restore = true;
9260                                 }
9261
9262                         }
9263                         for_each_ndev(wl, iter, next) {
9264                                 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm,
9265                                         sizeof(pm), true)) != 0) {
9266                                         if (err == -ENODEV)
9267                                                 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
9268                                         else
9269                                                 WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
9270                                 } else
9271                                         iter->ndev->ieee80211_ptr->ps = false;
9272                         }
9273                 } else {
9274                         /* add PM Enable timer to go to power save mode
9275                          * if supplicant control pm mode, it will be cleared or
9276                          * updated by wl_cfg80211_set_power_mgmt() if not - for static IP & HW4 P2P,
9277                          * PM will be configured when timer expired
9278                          */
9279
9280                         /*
9281                          * before calling pm_enable_timer, we need to set PM -1 for all ndev
9282                          */
9283                         pm = PM_OFF;
9284
9285                         for_each_ndev(wl, iter, next) {
9286                                 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm,
9287                                         sizeof(pm), true)) != 0) {
9288                                         if (err == -ENODEV)
9289                                                 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
9290                                         else
9291                                                 WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
9292                                 }
9293                         }
9294
9295                         if (wl->pm_enable_work_on) {
9296                                 wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_DEL);
9297                         }
9298
9299                         wl->pm_enable_work_on = true;
9300                         wl_add_remove_pm_enable_work(wl, TRUE, WL_HANDLER_NOTUSE);
9301                 }
9302         }
9303          else { /* clear */
9304                 chan = 0;
9305                 /* clear chan information when the net device is disconnected */
9306                 wl_update_prof(wl, _net_info->ndev, NULL, &chan, WL_PROF_CHAN);
9307                 wl_cfg80211_determine_vsdb_mode(wl);
9308                 for_each_ndev(wl, iter, next) {
9309                         if (iter->pm_restore && iter->pm) {
9310                                 WL_DBG(("%s:restoring power save %s\n",
9311                                         iter->ndev->name, (iter->pm ? "enabled" : "disabled")));
9312                                 err = wldev_ioctl(iter->ndev,
9313                                         WLC_SET_PM, &iter->pm, sizeof(iter->pm), true);
9314                                 if (unlikely(err)) {
9315                                         if (err == -ENODEV)
9316                                                 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
9317                                         else
9318                                                 WL_ERR(("%s:error(%d)\n", iter->ndev->name, err));
9319                                         break;
9320                                 }
9321                                 iter->pm_restore = 0;
9322                                 iter->ndev->ieee80211_ptr->ps = true;
9323                         }
9324                 }
9325                 wl_cfg80211_concurrent_roam(wl, 0);
9326         }
9327         return err;
9328 }
9329 static s32 wl_init_scan(struct wl_priv *wl)
9330 {
9331         struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
9332         int err = 0;
9333
9334         if (wl->iscan_on) {
9335                 iscan->dev = wl_to_prmry_ndev(wl);
9336                 iscan->state = WL_ISCAN_STATE_IDLE;
9337                 wl_init_iscan_handler(iscan);
9338                 iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
9339                 init_timer(&iscan->timer);
9340                 iscan->timer.data = (unsigned long) iscan;
9341                 iscan->timer.function = wl_iscan_timer;
9342                 sema_init(&iscan->sync, 0);
9343                 iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan");
9344                 if (IS_ERR(iscan->tsk)) {
9345                         WL_ERR(("Could not create iscan thread\n"));
9346                         iscan->tsk = NULL;
9347                         return -ENOMEM;
9348                 }
9349                 iscan->data = wl;
9350         } else if (wl->escan_on) {
9351                 wl->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
9352                 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9353                 wl_escan_init_sync_id(wl);
9354         }
9355         /* Init scan_timeout timer */
9356         init_timer(&wl->scan_timeout);
9357         wl->scan_timeout.data = (unsigned long) wl;
9358         wl->scan_timeout.function = wl_scan_timeout;
9359
9360         return err;
9361 }
9362
9363 static s32 wl_init_priv(struct wl_priv *wl)
9364 {
9365         struct wiphy *wiphy = wl_to_wiphy(wl);
9366         struct net_device *ndev = wl_to_prmry_ndev(wl);
9367         s32 err = 0;
9368
9369         wl->scan_request = NULL;
9370         wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
9371         wl->iscan_on = false;
9372         wl->escan_on = true;
9373         wl->roam_on = false;
9374         wl->iscan_kickstart = false;
9375         wl->active_scan = true;
9376         wl->rf_blocked = false;
9377         wl->vsdb_mode = false;
9378         wl->wlfc_on = false;
9379         wl->roamoff_on_concurrent = true;
9380         /* register interested state */
9381         set_bit(WL_STATUS_CONNECTED, &wl->interrested_state);
9382         spin_lock_init(&wl->cfgdrv_lock);
9383         mutex_init(&wl->ioctl_buf_sync);
9384         init_waitqueue_head(&wl->netif_change_event);
9385         init_completion(&wl->send_af_done);
9386         init_completion(&wl->iface_disable);
9387         wl_init_eq(wl);
9388         err = wl_init_priv_mem(wl);
9389         if (err)
9390                 return err;
9391         if (wl_create_event_handler(wl))
9392                 return -ENOMEM;
9393         wl_init_event_handler(wl);
9394         mutex_init(&wl->usr_sync);
9395         mutex_init(&wl->event_sync);
9396         err = wl_init_scan(wl);
9397         if (err)
9398                 return err;
9399         wl_init_conf(wl->conf);
9400         wl_init_prof(wl, ndev);
9401         wl_link_down(wl);
9402         DNGL_FUNC(dhd_cfg80211_init, (wl));
9403
9404         return err;
9405 }
9406
9407 static void wl_deinit_priv(struct wl_priv *wl)
9408 {
9409         DNGL_FUNC(dhd_cfg80211_deinit, (wl));
9410         wl_destroy_event_handler(wl);
9411         wl_flush_eq(wl);
9412         wl_link_down(wl);
9413         del_timer_sync(&wl->scan_timeout);
9414         wl_term_iscan(wl);
9415         wl_deinit_priv_mem(wl);
9416         unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
9417 }
9418
9419 #if defined(WL_ENABLE_P2P_IF)
9420 static s32 wl_cfg80211_attach_p2p(void)
9421 {
9422         struct wl_priv *wl = wlcfg_drv_priv;
9423
9424         WL_TRACE(("Enter \n"));
9425
9426         if (wl_cfgp2p_register_ndev(wl) < 0) {
9427                 WL_ERR(("P2P attach failed. \n"));
9428                 return -ENODEV;
9429         }
9430
9431         return 0;
9432 }
9433
9434 static s32  wl_cfg80211_detach_p2p(void)
9435 {
9436         struct wl_priv *wl = wlcfg_drv_priv;
9437         struct wireless_dev *wdev;
9438
9439         WL_DBG(("Enter \n"));
9440         if (!wl) {
9441                 WL_ERR(("Invalid Ptr\n"));
9442                 return -EINVAL;
9443         } else
9444                 wdev = wl->p2p_wdev;
9445
9446         if (!wdev) {
9447                 WL_ERR(("Invalid Ptr\n"));
9448                 return -EINVAL;
9449         }
9450
9451         wl_cfgp2p_unregister_ndev(wl);
9452
9453         wl->p2p_wdev = NULL;
9454         wl->p2p_net = NULL;
9455         WL_DBG(("Freeing 0x%08x \n", (unsigned int)wdev));
9456         kfree(wdev);
9457
9458         return 0;
9459 }
9460 #endif /* WL_ENABLE_P2P_IF */
9461
9462 s32 wl_cfg80211_attach_post(struct net_device *ndev)
9463 {
9464         struct wl_priv * wl = NULL;
9465         s32 err = 0;
9466         WL_TRACE(("In\n"));
9467         if (unlikely(!ndev)) {
9468                 WL_ERR(("ndev is invaild\n"));
9469                 return -ENODEV;
9470         }
9471         wl = wlcfg_drv_priv;
9472         if (unlikely(!wl)) {
9473                 WL_ERR(("wl is invaild\n"));
9474                 return -EINVAL;
9475         }
9476         if (!wl_get_drv_status(wl, READY, ndev)) {
9477                         if (wl->wdev && wl_cfgp2p_supported(wl, ndev)) {
9478 #if !defined(WL_ENABLE_P2P_IF)
9479                                         wl->wdev->wiphy->interface_modes |=
9480                                         (BIT(NL80211_IFTYPE_P2P_CLIENT)|
9481                                         BIT(NL80211_IFTYPE_P2P_GO));
9482 #endif /* !WL_ENABLE_P2P_IF */
9483                                 if ((err = wl_cfgp2p_init_priv(wl)) != 0)
9484                                         goto fail;
9485
9486 #if defined(WL_ENABLE_P2P_IF)
9487                                 if (wl->p2p_net) {
9488                                         /* Update MAC addr for p2p0 interface here. */
9489                                         memcpy(wl->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN);
9490                                         wl->p2p_net->dev_addr[0] |= 0x02;
9491                                         WL_ERR(("%s: p2p_dev_addr="MACDBG "\n",
9492                                                 wl->p2p_net->name,
9493                                                 MAC2STRDBG(wl->p2p_net->dev_addr)));
9494                                 } else {
9495                                         WL_ERR(("p2p_net not yet populated."
9496                                         " Couldn't update the MAC Address for p2p0 \n"));
9497                                         return -ENODEV;
9498                                 }
9499 #endif /* WL_ENABLE_P2P_IF */
9500
9501                                 wl->p2p_supported = true;
9502                         }
9503                 }
9504         wl_set_drv_status(wl, READY, ndev);
9505 fail:
9506         return err;
9507 }
9508
9509 s32 wl_cfg80211_attach(struct net_device *ndev, void *data)
9510 {
9511         struct wireless_dev *wdev;
9512         struct wl_priv *wl;
9513         s32 err = 0;
9514         struct device *dev;
9515
9516         WL_TRACE(("In\n"));
9517         if (!ndev) {
9518                 WL_ERR(("ndev is invaild\n"));
9519                 return -ENODEV;
9520         }
9521         WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev()));
9522         dev = wl_cfg80211_get_parent_dev();
9523
9524         wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
9525         if (unlikely(!wdev)) {
9526                 WL_ERR(("Could not allocate wireless device\n"));
9527                 return -ENOMEM;
9528         }
9529         err = wl_setup_wiphy(wdev, dev, data);
9530         if (unlikely(err)) {
9531                 kfree(wdev);
9532                 return -ENOMEM;
9533         }
9534         wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
9535         wl = (struct wl_priv *)wiphy_priv(wdev->wiphy);
9536         wl->wdev = wdev;
9537         wl->pub = data;
9538         INIT_LIST_HEAD(&wl->net_list);
9539         ndev->ieee80211_ptr = wdev;
9540         SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
9541         wdev->netdev = ndev;
9542         wl->state_notifier = wl_notifier_change_state;
9543         err = wl_alloc_netinfo(wl, ndev, wdev, WL_MODE_BSS, PM_ENABLE);
9544         if (err) {
9545                 WL_ERR(("Failed to alloc net_info (%d)\n", err));
9546                 goto cfg80211_attach_out;
9547         }
9548         err = wl_init_priv(wl);
9549         if (err) {
9550                 WL_ERR(("Failed to init iwm_priv (%d)\n", err));
9551                 goto cfg80211_attach_out;
9552         }
9553
9554         err = wl_setup_rfkill(wl, TRUE);
9555         if (err) {
9556                 WL_ERR(("Failed to setup rfkill %d\n", err));
9557                 goto cfg80211_attach_out;
9558         }
9559 #ifdef DEBUGFS_CFG80211
9560         err = wl_setup_debugfs(wl);
9561         if (err) {
9562                 WL_ERR(("Failed to setup debugfs %d\n", err));
9563                 goto cfg80211_attach_out;
9564         }
9565 #endif
9566         err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier);
9567         if (err) {
9568                 WL_ERR(("Failed to register notifierl %d\n", err));
9569                 goto cfg80211_attach_out;
9570         }
9571 #if defined(COEX_DHCP)
9572         err = wl_cfg80211_btcoex_init(wl);
9573         if (err)
9574                 goto cfg80211_attach_out;
9575 #endif 
9576
9577         wlcfg_drv_priv = wl;
9578
9579 #if defined(WL_ENABLE_P2P_IF)
9580         err = wl_cfg80211_attach_p2p();
9581         if (err)
9582                 goto cfg80211_attach_out;
9583 #endif /* WL_ENABLE_P2P_IF */
9584
9585         return err;
9586
9587 cfg80211_attach_out:
9588         wl_setup_rfkill(wl, FALSE);
9589         wl_free_wdev(wl);
9590         return err;
9591 }
9592
9593 void wl_cfg80211_detach(void *para)
9594 {
9595         struct wl_priv *wl;
9596
9597         (void)para;
9598         wl = wlcfg_drv_priv;
9599
9600         WL_TRACE(("In\n"));
9601
9602 #if defined(COEX_DHCP)
9603         wl_cfg80211_btcoex_deinit(wl);
9604 #endif 
9605
9606         wl_setup_rfkill(wl, FALSE);
9607 #ifdef DEBUGFS_CFG80211
9608         wl_free_debugfs(wl);
9609 #endif
9610         if (wl->p2p_supported) {
9611                 if (timer_pending(&wl->p2p->listen_timer))
9612                         del_timer_sync(&wl->p2p->listen_timer);
9613                 wl_cfgp2p_deinit_priv(wl);
9614         }
9615
9616 #if defined(WL_CFG80211_P2P_DEV_IF)
9617         wl_cfgp2p_del_p2p_disc_if(wl->p2p_wdev);
9618 #elif defined(WL_ENABLE_P2P_IF)
9619         wl_cfg80211_detach_p2p();
9620 #endif /* WL_CFG80211_P2P_DEV_IF */
9621
9622         wl_cfg80211_ibss_vsie_free(wl);
9623         wl_deinit_priv(wl);
9624         wlcfg_drv_priv = NULL;
9625         wl_cfg80211_clear_parent_dev();
9626         wl_free_wdev(wl);
9627          /* PLEASE do NOT call any function after wl_free_wdev, the driver's private structure "wl",
9628           * which is the private part of wiphy, has been freed in wl_free_wdev !!!!!!!!!!!
9629           */
9630 }
9631
9632 static void wl_wakeup_event(struct wl_priv *wl)
9633 {
9634         if (wl->event_tsk.thr_pid >= 0) {
9635                 DHD_OS_WAKE_LOCK(wl->pub);
9636                 up(&wl->event_tsk.sema);
9637         }
9638 }
9639
9640 #if (defined(WL_CFG80211_P2P_DEV_IF) || defined(WL_ENABLE_P2P_IF))
9641 static int wl_is_p2p_event(struct wl_event_q *e)
9642 {
9643         switch (e->etype) {
9644         /* We have to seperate out the P2P events received
9645          * on primary interface so that it can be send up
9646          * via p2p0 interface.
9647         */
9648         case WLC_E_P2P_PROBREQ_MSG:
9649         case WLC_E_P2P_DISC_LISTEN_COMPLETE:
9650         case WLC_E_ACTION_FRAME_RX:
9651         case WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE:
9652         case WLC_E_ACTION_FRAME_COMPLETE:
9653
9654                 if (e->emsg.ifidx != 0) {
9655                         WL_TRACE(("P2P event(%d) on virtual interface(ifidx:%d)\n",
9656                                 e->etype, e->emsg.ifidx));
9657                         /* We are only bothered about the P2P events received
9658                          * on primary interface. For rest of them return false
9659                          * so that it is sent over the interface corresponding
9660                          * to the ifidx.
9661                          */
9662                         return FALSE;
9663                 } else {
9664                         WL_TRACE(("P2P event(%d) on interface(ifidx:%d)\n",
9665                                 e->etype, e->emsg.ifidx));
9666                         return TRUE;
9667                 }
9668                 break;
9669
9670         default:
9671                 WL_TRACE(("NON-P2P event(%d) on interface(ifidx:%d)\n",
9672                         e->etype, e->emsg.ifidx));
9673                 return FALSE;
9674         }
9675 }
9676 #endif /* BCMDONGLEHOST && (WL_CFG80211_P2P_DEV_IF || WL_ENABLE_P2P_IF) */
9677
9678 static s32 wl_event_handler(void *data)
9679 {
9680         struct wl_priv *wl = NULL;
9681         struct wl_event_q *e;
9682         tsk_ctl_t *tsk = (tsk_ctl_t *)data;
9683         bcm_struct_cfgdev *cfgdev = NULL;
9684         struct net_device *netdev;
9685
9686         wl = (struct wl_priv *)tsk->parent;
9687
9688         WL_ERR(("tsk Enter, tsk = 0x%08x\n", (unsigned int)tsk));
9689
9690         while (down_interruptible (&tsk->sema) == 0) {
9691                 SMP_RD_BARRIER_DEPENDS();
9692                 if (tsk->terminated)
9693                         break;
9694                 while ((e = wl_deq_event(wl))) {
9695                         WL_DBG(("event type (%d), if idx: %d\n", e->etype, e->emsg.ifidx));
9696                         /* All P2P device address related events comes on primary interface since
9697                          * there is no corresponding bsscfg for P2P interface. Map it to p2p0
9698                          * interface.
9699                          */
9700 #if defined(WL_CFG80211_P2P_DEV_IF)
9701                         if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_wdev)) {
9702                                 cfgdev = wl_to_p2p_wdev(wl);
9703                         } else {
9704                                 netdev = dhd_idx2net((struct dhd_pub *)(wl->pub), e->emsg.ifidx);
9705                                 if (netdev)
9706                                         cfgdev = ndev_to_wdev(netdev);
9707                         }
9708 #elif defined(WL_ENABLE_P2P_IF)
9709                         if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_net)) {
9710                                 cfgdev = wl->p2p_net;
9711                         } else {
9712                                 cfgdev = dhd_idx2net((struct dhd_pub *)(wl->pub),
9713                                         e->emsg.ifidx);
9714                         }
9715 #endif /* WL_CFG80211_P2P_DEV_IF */
9716
9717                         if (!cfgdev) {
9718 #if defined(WL_CFG80211_P2P_DEV_IF)
9719                                 cfgdev = wl_to_prmry_wdev(wl);
9720 #elif defined(WL_ENABLE_P2P_IF)
9721                                 cfgdev = wl_to_prmry_ndev(wl);
9722 #endif /* WL_CFG80211_P2P_DEV_IF */
9723                         }
9724                         if (e->etype < WLC_E_LAST && wl->evt_handler[e->etype]) {
9725                                 wl->evt_handler[e->etype] (wl, cfgdev, &e->emsg, e->edata);
9726                         } else {
9727                                 WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
9728                         }
9729                         wl_put_event(e);
9730                 }
9731                 DHD_OS_WAKE_UNLOCK(wl->pub);
9732         }
9733         WL_ERR(("was terminated\n"));
9734         complete_and_exit(&tsk->completed, 0);
9735         return 0;
9736 }
9737
9738 void
9739 wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
9740 {
9741         u32 event_type = ntoh32(e->event_type);
9742         struct wl_priv *wl = wlcfg_drv_priv;
9743
9744 #if (WL_DBG_LEVEL > 0)
9745         s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
9746             wl_dbg_estr[event_type] : (s8 *) "Unknown";
9747         WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
9748 #endif /* (WL_DBG_LEVEL > 0) */
9749
9750         if (event_type == WLC_E_PFN_NET_FOUND) {
9751                 WL_DBG((" PNOEVENT: PNO_NET_FOUND\n"));
9752         }
9753         else if (event_type == WLC_E_PFN_NET_LOST) {
9754                 WL_DBG((" PNOEVENT: PNO_NET_LOST\n"));
9755         }
9756
9757         if (likely(!wl_enq_event(wl, ndev, event_type, e, data)))
9758                 wl_wakeup_event(wl);
9759 }
9760
9761 static void wl_init_eq(struct wl_priv *wl)
9762 {
9763         wl_init_eq_lock(wl);
9764         INIT_LIST_HEAD(&wl->eq_list);
9765 }
9766
9767 static void wl_flush_eq(struct wl_priv *wl)
9768 {
9769         struct wl_event_q *e;
9770         unsigned long flags;
9771
9772         flags = wl_lock_eq(wl);
9773         while (!list_empty(&wl->eq_list)) {
9774                 e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
9775                 list_del(&e->eq_list);
9776                 kfree(e);
9777         }
9778         wl_unlock_eq(wl, flags);
9779 }
9780
9781 /*
9782 * retrieve first queued event from head
9783 */
9784
9785 static struct wl_event_q *wl_deq_event(struct wl_priv *wl)
9786 {
9787         struct wl_event_q *e = NULL;
9788         unsigned long flags;
9789
9790         flags = wl_lock_eq(wl);
9791         if (likely(!list_empty(&wl->eq_list))) {
9792                 e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
9793                 list_del(&e->eq_list);
9794         }
9795         wl_unlock_eq(wl, flags);
9796
9797         return e;
9798 }
9799
9800 /*
9801  * push event to tail of the queue
9802  */
9803
9804 static s32
9805 wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 event, const wl_event_msg_t *msg,
9806         void *data)
9807 {
9808         struct wl_event_q *e;
9809         s32 err = 0;
9810         uint32 evtq_size;
9811         uint32 data_len;
9812         unsigned long flags;
9813         gfp_t aflags;
9814
9815         data_len = 0;
9816         if (data)
9817                 data_len = ntoh32(msg->datalen);
9818         evtq_size = sizeof(struct wl_event_q) + data_len;
9819         aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
9820         e = kzalloc(evtq_size, aflags);
9821         if (unlikely(!e)) {
9822                 WL_ERR(("event alloc failed\n"));
9823                 return -ENOMEM;
9824         }
9825         e->etype = event;
9826         memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
9827         if (data)
9828                 memcpy(e->edata, data, data_len);
9829         flags = wl_lock_eq(wl);
9830         list_add_tail(&e->eq_list, &wl->eq_list);
9831         wl_unlock_eq(wl, flags);
9832
9833         return err;
9834 }
9835
9836 static void wl_put_event(struct wl_event_q *e)
9837 {
9838         kfree(e);
9839 }
9840
9841 static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype)
9842 {
9843         s32 infra = 0;
9844         s32 err = 0;
9845         s32 mode = 0;
9846         switch (iftype) {
9847         case NL80211_IFTYPE_MONITOR:
9848         case NL80211_IFTYPE_WDS:
9849                 WL_ERR(("type (%d) : currently we do not support this mode\n",
9850                         iftype));
9851                 err = -EINVAL;
9852                 return err;
9853         case NL80211_IFTYPE_ADHOC:
9854                 mode = WL_MODE_IBSS;
9855                 break;
9856         case NL80211_IFTYPE_STATION:
9857         case NL80211_IFTYPE_P2P_CLIENT:
9858                 mode = WL_MODE_BSS;
9859                 infra = 1;
9860                 break;
9861         case NL80211_IFTYPE_AP:
9862         case NL80211_IFTYPE_P2P_GO:
9863                 mode = WL_MODE_AP;
9864                 infra = 1;
9865                 break;
9866         default:
9867                 err = -EINVAL;
9868                 WL_ERR(("invalid type (%d)\n", iftype));
9869                 return err;
9870         }
9871         infra = htod32(infra);
9872         err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true);
9873         if (unlikely(err)) {
9874                 WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
9875                 return err;
9876         }
9877
9878         wl_set_mode_by_netdev(wl, ndev, mode);
9879
9880         return 0;
9881 }
9882
9883 void wl_cfg80211_add_to_eventbuffer(struct wl_eventmsg_buf *ev, u16 event, bool set)
9884 {
9885         if (!ev || (event > WLC_E_LAST))
9886                 return;
9887
9888         if (ev->num < MAX_EVENT_BUF_NUM) {
9889                 ev->event[ev->num].type = event;
9890                 ev->event[ev->num].set = set;
9891                 ev->num++;
9892         } else {
9893                 WL_ERR(("evenbuffer doesn't support > %u events. Update"
9894                         " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM));
9895                 ASSERT(0);
9896         }
9897 }
9898
9899 s32 wl_cfg80211_apply_eventbuffer(
9900         struct net_device *ndev,
9901         struct wl_priv *wl,
9902         wl_eventmsg_buf_t *ev)
9903 {
9904         char eventmask[WL_EVENTING_MASK_LEN];
9905         int i, ret = 0;
9906         s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
9907
9908         if (!ev || (!ev->num))
9909                 return -EINVAL;
9910
9911         mutex_lock(&wl->event_sync);
9912
9913         /* Read event_msgs mask */
9914         bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
9915                 sizeof(iovbuf));
9916         ret = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
9917         if (unlikely(ret)) {
9918                 WL_ERR(("Get event_msgs error (%d)\n", ret));
9919                 goto exit;
9920         }
9921         memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
9922
9923         /* apply the set bits */
9924         for (i = 0; i < ev->num; i++) {
9925                 if (ev->event[i].set)
9926                         setbit(eventmask, ev->event[i].type);
9927                 else
9928                         clrbit(eventmask, ev->event[i].type);
9929         }
9930
9931         /* Write updated Event mask */
9932         bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
9933                 sizeof(iovbuf));
9934         ret = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
9935         if (unlikely(ret)) {
9936                 WL_ERR(("Set event_msgs error (%d)\n", ret));
9937         }
9938
9939 exit:
9940         mutex_unlock(&wl->event_sync);
9941         return ret;
9942 }
9943
9944 s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add)
9945 {
9946         s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
9947         s8 eventmask[WL_EVENTING_MASK_LEN];
9948         s32 err = 0;
9949         struct wl_priv *wl = wlcfg_drv_priv;
9950
9951         if (!ndev || !wl)
9952                 return -ENODEV;
9953
9954         mutex_lock(&wl->event_sync);
9955
9956         /* Setup event_msgs */
9957         bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
9958                 sizeof(iovbuf));
9959         err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
9960         if (unlikely(err)) {
9961                 WL_ERR(("Get event_msgs error (%d)\n", err));
9962                 goto eventmsg_out;
9963         }
9964         memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
9965         if (add) {
9966                 setbit(eventmask, event);
9967         } else {
9968                 clrbit(eventmask, event);
9969         }
9970         bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
9971                 sizeof(iovbuf));
9972         err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
9973         if (unlikely(err)) {
9974                 WL_ERR(("Set event_msgs error (%d)\n", err));
9975                 goto eventmsg_out;
9976         }
9977
9978 eventmsg_out:
9979         mutex_unlock(&wl->event_sync);
9980         return err;
9981 }
9982
9983 static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap)
9984 {
9985         struct net_device *dev = wl_to_prmry_ndev(wl);
9986         struct ieee80211_channel *band_chan_arr = NULL;
9987         wl_uint32_list_t *list;
9988         u32 i, j, index, n_2g, n_5g, band, channel, array_size;
9989         u32 *n_cnt = NULL;
9990         chanspec_t c = 0;
9991         s32 err = BCME_OK;
9992         bool update;
9993         bool ht40_allowed;
9994         u8 *pbuf = NULL;
9995         bool dfs_radar_disabled = FALSE;
9996
9997 #define LOCAL_BUF_LEN 1024
9998         pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL);
9999
10000         if (pbuf == NULL) {
10001                 WL_ERR(("failed to allocate local buf\n"));
10002                 return -ENOMEM;
10003         }
10004         list = (wl_uint32_list_t *)(void *)pbuf;
10005         list->count = htod32(WL_NUMCHANSPECS);
10006
10007
10008         err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
10009                 0, pbuf, LOCAL_BUF_LEN, 0, &wl->ioctl_buf_sync);
10010         if (err != 0) {
10011                 WL_ERR(("get chanspecs failed with %d\n", err));
10012                 kfree(pbuf);
10013                 return err;
10014         }
10015 #undef LOCAL_BUF_LEN
10016
10017         list = (wl_uint32_list_t *)(void *)pbuf;
10018         band = array_size = n_2g = n_5g = 0;
10019         for (i = 0; i < dtoh32(list->count); i++) {
10020                 index = 0;
10021                 update = false;
10022                 ht40_allowed = false;
10023                 c = (chanspec_t)dtoh32(list->element[i]);
10024                 c = wl_chspec_driver_to_host(c);
10025                 channel = CHSPEC_CHANNEL(c);
10026                 if (CHSPEC_IS40(c)) {
10027                         if (CHSPEC_SB_UPPER(c))
10028                                 channel += CH_10MHZ_APART;
10029                         else
10030                                 channel -= CH_10MHZ_APART;
10031                 } else if (CHSPEC_IS80(c)) {
10032                         WL_DBG(("HT80 center channel : %d\n", channel));
10033                         continue;
10034                 }
10035                 if (CHSPEC_IS2G(c) && (channel >= CH_MIN_2G_CHANNEL) &&
10036                         (channel <= CH_MAX_2G_CHANNEL)) {
10037                         band_chan_arr = __wl_2ghz_channels;
10038                         array_size = ARRAYSIZE(__wl_2ghz_channels);
10039                         n_cnt = &n_2g;
10040                         band = IEEE80211_BAND_2GHZ;
10041                         ht40_allowed = (bw_cap  == WLC_N_BW_40ALL)? true : false;
10042                 } else if (CHSPEC_IS5G(c) && channel >= CH_MIN_5G_CHANNEL) {
10043                         band_chan_arr = __wl_5ghz_a_channels;
10044                         array_size = ARRAYSIZE(__wl_5ghz_a_channels);
10045                         n_cnt = &n_5g;
10046                         band = IEEE80211_BAND_5GHZ;
10047                         ht40_allowed = (bw_cap  == WLC_N_BW_20ALL)? false : true;
10048                 } else {
10049                         WL_ERR(("Invalid channel Sepc. 0x%x.\n", c));
10050                         continue;
10051                 }
10052                 if (!ht40_allowed && CHSPEC_IS40(c))
10053                         continue;
10054                 for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
10055                         if (band_chan_arr[j].hw_value == channel) {
10056                                 update = true;
10057                                 break;
10058                         }
10059                 }
10060                 if (update)
10061                         index = j;
10062                 else
10063                         index = *n_cnt;
10064                 if (index <  array_size) {
10065 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
10066                         band_chan_arr[index].center_freq =
10067                                 ieee80211_channel_to_frequency(channel);
10068 #else
10069                         band_chan_arr[index].center_freq =
10070                                 ieee80211_channel_to_frequency(channel, band);
10071 #endif
10072                         band_chan_arr[index].hw_value = channel;
10073
10074                         if (CHSPEC_IS40(c) && ht40_allowed) {
10075                                 /* assuming the order is HT20, HT40 Upper,
10076                                  *  HT40 lower from chanspecs
10077                                  */
10078                                 u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
10079                                 if (CHSPEC_SB_UPPER(c)) {
10080                                         if (ht40_flag == IEEE80211_CHAN_NO_HT40)
10081                                                 band_chan_arr[index].flags &=
10082                                                         ~IEEE80211_CHAN_NO_HT40;
10083                                         band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
10084                                 } else {
10085                                         /* It should be one of
10086                                          * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
10087                                          */
10088                                         band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
10089                                         if (ht40_flag == IEEE80211_CHAN_NO_HT40)
10090                                                 band_chan_arr[index].flags |=
10091                                                         IEEE80211_CHAN_NO_HT40MINUS;
10092                                 }
10093                         } else {
10094                                 band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
10095                                 if (!dfs_radar_disabled) {
10096                                         if (band == IEEE80211_BAND_2GHZ)
10097                                                 channel |= WL_CHANSPEC_BAND_2G;
10098                                         else
10099                                                 channel |= WL_CHANSPEC_BAND_5G;
10100                                         channel |= WL_CHANSPEC_BW_20;
10101                                         channel = wl_chspec_host_to_driver(channel);
10102                                         err = wldev_iovar_getint(dev, "per_chan_info", &channel);
10103                                         if (!err) {
10104                                                 if (channel & WL_CHAN_RADAR)
10105                                                         band_chan_arr[index].flags |=
10106                                                                 (IEEE80211_CHAN_RADAR |
10107                                                                 IEEE80211_CHAN_NO_IBSS);
10108                                                 if (channel & WL_CHAN_PASSIVE)
10109                                                         band_chan_arr[index].flags |=
10110                                                                 IEEE80211_CHAN_PASSIVE_SCAN;
10111                                         } else if (err == BCME_UNSUPPORTED) {
10112                                                 dfs_radar_disabled = TRUE;
10113                                                 WL_ERR(("does not support per_chan_info\n"));
10114                                         }
10115                                 }
10116                         }
10117                         if (!update)
10118                                 (*n_cnt)++;
10119                 }
10120
10121         }
10122         __wl_band_2ghz.n_channels = n_2g;
10123         __wl_band_5ghz_a.n_channels = n_5g;
10124         kfree(pbuf);
10125         return err;
10126 }
10127
10128 s32 wl_update_wiphybands(struct wl_priv *wl, bool notify)
10129 {
10130         struct wiphy *wiphy;
10131         struct net_device *dev;
10132         u32 bandlist[3];
10133         u32 nband = 0;
10134         u32 i = 0;
10135         s32 err = 0;
10136         s32 index = 0;
10137         s32 nmode = 0;
10138         bool rollback_lock = false;
10139         s32 bw_cap = 0;
10140         s32 cur_band = -1;
10141         struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS] = {NULL, };
10142
10143         if (wl == NULL) {
10144                 wl = wlcfg_drv_priv;
10145                 mutex_lock(&wl->usr_sync);
10146                 rollback_lock = true;
10147         }
10148         dev = wl_to_prmry_ndev(wl);
10149
10150         memset(bandlist, 0, sizeof(bandlist));
10151         err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist,
10152                 sizeof(bandlist), false);
10153         if (unlikely(err)) {
10154                 WL_ERR(("error read bandlist (%d)\n", err));
10155                 goto end_bands;
10156         }
10157         err = wldev_ioctl(dev, WLC_GET_BAND, &cur_band,
10158                 sizeof(s32), false);
10159         if (unlikely(err)) {
10160                 WL_ERR(("error (%d)\n", err));
10161                 goto end_bands;
10162         }
10163
10164         err = wldev_iovar_getint(dev, "nmode", &nmode);
10165         if (unlikely(err)) {
10166                 WL_ERR(("error reading nmode (%d)\n", err));
10167         } else {
10168                 /* For nmodeonly  check bw cap */
10169                 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
10170                 if (unlikely(err)) {
10171                         WL_ERR(("error get mimo_bw_cap (%d)\n", err));
10172                 }
10173         }
10174
10175         err = wl_construct_reginfo(wl, bw_cap);
10176         if (err) {
10177                 WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
10178                 if (err != BCME_UNSUPPORTED)
10179                         goto end_bands;
10180                 err = 0;
10181         }
10182         wiphy = wl_to_wiphy(wl);
10183         nband = bandlist[0];
10184
10185         for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) {
10186                 index = -1;
10187                 if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
10188                         bands[IEEE80211_BAND_5GHZ] =
10189                                 &__wl_band_5ghz_a;
10190                         index = IEEE80211_BAND_5GHZ;
10191                         if (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G)
10192                                 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
10193                 }
10194                 else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
10195                         bands[IEEE80211_BAND_2GHZ] =
10196                                 &__wl_band_2ghz;
10197                         index = IEEE80211_BAND_2GHZ;
10198                         if (bw_cap == WLC_N_BW_40ALL)
10199                                 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
10200                 }
10201
10202                 if ((index >= 0) && nmode) {
10203                         bands[index]->ht_cap.cap |=
10204                                 (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40);
10205                         bands[index]->ht_cap.ht_supported = TRUE;
10206                         bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
10207                         bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
10208                         /* An HT shall support all EQM rates for one spatial stream */
10209                         bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
10210                 }
10211
10212         }
10213
10214         wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
10215         wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
10216
10217         /* check if any bands populated otherwise makes 2Ghz as default */
10218         if (wiphy->bands[IEEE80211_BAND_2GHZ] == NULL &&
10219                 wiphy->bands[IEEE80211_BAND_5GHZ] == NULL) {
10220                 /* Setup 2Ghz band as default */
10221                 wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
10222         }
10223
10224         if (notify)
10225                 wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
10226
10227         end_bands:
10228                 if (rollback_lock)
10229                         mutex_unlock(&wl->usr_sync);
10230         return err;
10231 }
10232
10233 static s32 __wl_cfg80211_up(struct wl_priv *wl)
10234 {
10235         s32 err = 0;
10236         struct net_device *ndev = wl_to_prmry_ndev(wl);
10237         struct wireless_dev *wdev = ndev->ieee80211_ptr;
10238
10239         WL_DBG(("In\n"));
10240
10241         err = dhd_config_dongle(wl, false);
10242         if (unlikely(err))
10243                 return err;
10244
10245         err = wl_config_ifmode(wl, ndev, wdev->iftype);
10246         if (unlikely(err && err != -EINPROGRESS)) {
10247                 WL_ERR(("wl_config_ifmode failed\n"));
10248         }
10249         err = wl_update_wiphybands(wl, true);
10250         if (unlikely(err)) {
10251                 WL_ERR(("wl_update_wiphybands failed\n"));
10252         }
10253
10254         err = dhd_monitor_init(wl->pub);
10255         err = wl_invoke_iscan(wl);
10256
10257
10258         INIT_DELAYED_WORK(&wl->pm_enable_work, wl_cfg80211_work_handler);
10259         wl_set_drv_status(wl, READY, ndev);
10260         return err;
10261 }
10262
10263 static s32 __wl_cfg80211_down(struct wl_priv *wl)
10264 {
10265         s32 err = 0;
10266         unsigned long flags;
10267         struct net_info *iter, *next;
10268         struct net_device *ndev = wl_to_prmry_ndev(wl);
10269 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
10270         struct net_device *p2p_net = wl->p2p_net;
10271 #endif /* WL_CFG80211 && WL_ENABLE_P2P_IF */
10272         u32 bssidx = 0;
10273 #ifdef PROP_TXSTATUS_VSDB
10274         dhd_pub_t *dhd =  (dhd_pub_t *)(wl->pub);
10275 #endif /* PROP_TXSTATUS_VSDB */
10276         WL_DBG(("In\n"));
10277         /* Delete pm_enable_work */
10278         wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_DEL);
10279
10280         if (wl->p2p_supported) {
10281                 wl_clr_p2p_status(wl, GO_NEG_PHASE);
10282 #ifdef PROP_TXSTATUS_VSDB
10283                 if (wl->p2p->vif_created) {
10284                         if (dhd-> op_mode != DHD_FLAG_IBSS_MODE &&
10285                                 dhd->wlfc_enabled && wl->wlfc_on) {
10286                                 dhd->wlfc_enabled = false;
10287                                 dhd_wlfc_deinit(dhd);
10288                                 if (dhd->plat_deinit)
10289                                         dhd->plat_deinit((void *)dhd);
10290                                 wl->wlfc_on = false;
10291                         }
10292                 }
10293 #endif /* PROP_TXSTATUS_VSDB */
10294         }
10295
10296
10297         /* If primary BSS is operational (for e.g SoftAP), bring it down */
10298         if (!(wl_cfgp2p_find_idx(wl, ndev, &bssidx)) &&
10299                 wl_cfgp2p_bss_isup(ndev, bssidx)) {
10300                 if (wl_cfgp2p_bss(wl, ndev, bssidx, 0) < 0)
10301                         WL_ERR(("BSS down failed \n"));
10302         }
10303
10304         /* Check if cfg80211 interface is already down */
10305         if (!wl_get_drv_status(wl, READY, ndev))
10306                 return err;     /* it is even not ready */
10307         for_each_ndev(wl, iter, next)
10308                 wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev);
10309
10310
10311         wl_term_iscan(wl);
10312         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
10313         if (wl->scan_request) {
10314                 cfg80211_scan_done(wl->scan_request, true);
10315                 wl->scan_request = NULL;
10316         }
10317         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
10318
10319         for_each_ndev(wl, iter, next) {
10320                 wl_clr_drv_status(wl, READY, iter->ndev);
10321                 wl_clr_drv_status(wl, SCANNING, iter->ndev);
10322                 wl_clr_drv_status(wl, SCAN_ABORTING, iter->ndev);
10323                 wl_clr_drv_status(wl, CONNECTING, iter->ndev);
10324                 wl_clr_drv_status(wl, CONNECTED, iter->ndev);
10325                 wl_clr_drv_status(wl, DISCONNECTING, iter->ndev);
10326                 wl_clr_drv_status(wl, AP_CREATED, iter->ndev);
10327                 wl_clr_drv_status(wl, AP_CREATING, iter->ndev);
10328         }
10329         wl_to_prmry_ndev(wl)->ieee80211_ptr->iftype =
10330                 NL80211_IFTYPE_STATION;
10331 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
10332                 if (p2p_net)
10333                         dev_close(p2p_net);
10334 #endif /* WL_CFG80211 && WL_ENABLE_P2P_IF */
10335         DNGL_FUNC(dhd_cfg80211_down, (wl));
10336         wl_flush_eq(wl);
10337         wl_link_down(wl);
10338         if (wl->p2p_supported)
10339                 wl_cfgp2p_down(wl);
10340         dhd_monitor_uninit();
10341
10342         return err;
10343 }
10344
10345 s32 wl_cfg80211_up(void *para)
10346 {
10347         struct wl_priv *wl;
10348         s32 err = 0;
10349         int val = 1;
10350         dhd_pub_t *dhd;
10351
10352         (void)para;
10353         WL_DBG(("In\n"));
10354         wl = wlcfg_drv_priv;
10355
10356         if ((err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_VERSION, &val,
10357                 sizeof(int), false) < 0)) {
10358                 WL_ERR(("WLC_GET_VERSION failed, err=%d\n", err));
10359                 return err;
10360         }
10361         val = dtoh32(val);
10362         if (val != WLC_IOCTL_VERSION && val != 1) {
10363                 WL_ERR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
10364                         val, WLC_IOCTL_VERSION));
10365                 return BCME_VERSION;
10366         }
10367         ioctl_version = val;
10368         WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version));
10369
10370         mutex_lock(&wl->usr_sync);
10371         dhd = (dhd_pub_t *)(wl->pub);
10372         if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
10373                 err = wl_cfg80211_attach_post(wl_to_prmry_ndev(wl));
10374                 if (unlikely(err))
10375                         return err;
10376         }
10377         err = __wl_cfg80211_up(wl);
10378         if (unlikely(err))
10379                 WL_ERR(("__wl_cfg80211_up failed\n"));
10380         mutex_unlock(&wl->usr_sync);
10381         return err;
10382 }
10383
10384 /* Private Event to Supplicant with indication that chip hangs */
10385 int wl_cfg80211_hang(struct net_device *dev, u16 reason)
10386 {
10387         struct wl_priv *wl;
10388         wl = wlcfg_drv_priv;
10389
10390         WL_ERR(("In : chip crash eventing\n"));
10391         wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_DEL);
10392         cfg80211_disconnected(dev, reason, NULL, 0, GFP_KERNEL);
10393         if (wl != NULL) {
10394                 wl_link_down(wl);
10395         }
10396         return 0;
10397 }
10398
10399 s32 wl_cfg80211_down(void *para)
10400 {
10401         struct wl_priv *wl;
10402         s32 err = 0;
10403
10404         (void)para;
10405         WL_DBG(("In\n"));
10406         wl = wlcfg_drv_priv;
10407         mutex_lock(&wl->usr_sync);
10408         err = __wl_cfg80211_down(wl);
10409         mutex_unlock(&wl->usr_sync);
10410
10411         return err;
10412 }
10413
10414 static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item)
10415 {
10416         unsigned long flags;
10417         void *rptr = NULL;
10418         struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
10419
10420         if (!profile)
10421                 return NULL;
10422         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
10423         switch (item) {
10424         case WL_PROF_SEC:
10425                 rptr = &profile->sec;
10426                 break;
10427         case WL_PROF_ACT:
10428                 rptr = &profile->active;
10429                 break;
10430         case WL_PROF_BSSID:
10431                 rptr = profile->bssid;
10432                 break;
10433         case WL_PROF_SSID:
10434                 rptr = &profile->ssid;
10435                 break;
10436         case WL_PROF_CHAN:
10437                 rptr = &profile->channel;
10438                 break;
10439         }
10440         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
10441         if (!rptr)
10442                 WL_ERR(("invalid item (%d)\n", item));
10443         return rptr;
10444 }
10445
10446 static s32
10447 wl_update_prof(struct wl_priv *wl, struct net_device *ndev,
10448         const wl_event_msg_t *e, void *data, s32 item)
10449 {
10450         s32 err = 0;
10451         struct wlc_ssid *ssid;
10452         unsigned long flags;
10453         struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
10454
10455         if (!profile)
10456                 return WL_INVALID;
10457         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
10458         switch (item) {
10459         case WL_PROF_SSID:
10460                 ssid = (wlc_ssid_t *) data;
10461                 memset(profile->ssid.SSID, 0,
10462                         sizeof(profile->ssid.SSID));
10463                 memcpy(profile->ssid.SSID, ssid->SSID, ssid->SSID_len);
10464                 profile->ssid.SSID_len = ssid->SSID_len;
10465                 break;
10466         case WL_PROF_BSSID:
10467                 if (data)
10468                         memcpy(profile->bssid, data, ETHER_ADDR_LEN);
10469                 else
10470                         memset(profile->bssid, 0, ETHER_ADDR_LEN);
10471                 break;
10472         case WL_PROF_SEC:
10473                 memcpy(&profile->sec, data, sizeof(profile->sec));
10474                 break;
10475         case WL_PROF_ACT:
10476                 profile->active = *(bool *)data;
10477                 break;
10478         case WL_PROF_BEACONINT:
10479                 profile->beacon_interval = *(u16 *)data;
10480                 break;
10481         case WL_PROF_DTIMPERIOD:
10482                 profile->dtim_period = *(u8 *)data;
10483                 break;
10484         case WL_PROF_CHAN:
10485                 profile->channel = *(u32*)data;
10486                 break;
10487         default:
10488                 err = -EOPNOTSUPP;
10489                 break;
10490         }
10491         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
10492
10493         if (err == -EOPNOTSUPP)
10494                 WL_ERR(("unsupported item (%d)\n", item));
10495
10496         return err;
10497 }
10498
10499 void wl_cfg80211_dbg_level(u32 level)
10500 {
10501         /*
10502         * prohibit to change debug level
10503         * by insmod parameter.
10504         * eventually debug level will be configured
10505         * in compile time by using CONFIG_XXX
10506         */
10507         /* wl_dbg_level = level; */
10508 }
10509
10510 static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev)
10511 {
10512         return wl_get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS;
10513 }
10514
10515 static __used bool wl_is_ibssstarter(struct wl_priv *wl)
10516 {
10517         return wl->ibss_starter;
10518 }
10519
10520 static void wl_rst_ie(struct wl_priv *wl)
10521 {
10522         struct wl_ie *ie = wl_to_ie(wl);
10523
10524         ie->offset = 0;
10525 }
10526
10527 static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v)
10528 {
10529         struct wl_ie *ie = wl_to_ie(wl);
10530         s32 err = 0;
10531
10532         if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
10533                 WL_ERR(("ei crosses buffer boundary\n"));
10534                 return -ENOSPC;
10535         }
10536         ie->buf[ie->offset] = t;
10537         ie->buf[ie->offset + 1] = l;
10538         memcpy(&ie->buf[ie->offset + 2], v, l);
10539         ie->offset += l + 2;
10540
10541         return err;
10542 }
10543
10544 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size)
10545 {
10546         u8 *ssidie;
10547         ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size);
10548         if (!ssidie)
10549                 return;
10550         if (ssidie[1] != bi->SSID_len) {
10551                 if (ssidie[1]) {
10552                         WL_ERR(("%s: Wrong SSID len: %d != %d\n",
10553                                 __FUNCTION__, ssidie[1], bi->SSID_len));
10554                         return;
10555                 }
10556                 memmove(ssidie + bi->SSID_len + 2, ssidie + 2, *ie_size - (ssidie + 2 - ie_stream));
10557                 memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
10558                 *ie_size = *ie_size + bi->SSID_len;
10559                 ssidie[1] = bi->SSID_len;
10560                 return;
10561         }
10562         if (*(ssidie + 2) == '\0')
10563                  memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
10564         return;
10565 }
10566
10567 static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size)
10568 {
10569         struct wl_ie *ie = wl_to_ie(wl);
10570         s32 err = 0;
10571
10572         if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
10573                 WL_ERR(("ei_stream crosses buffer boundary\n"));
10574                 return -ENOSPC;
10575         }
10576         memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
10577         ie->offset += ie_size;
10578
10579         return err;
10580 }
10581
10582 static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size)
10583 {
10584         struct wl_ie *ie = wl_to_ie(wl);
10585         s32 err = 0;
10586
10587         if (unlikely(ie->offset > dst_size)) {
10588                 WL_ERR(("dst_size is not enough\n"));
10589                 return -ENOSPC;
10590         }
10591         memcpy(dst, &ie->buf[0], ie->offset);
10592
10593         return err;
10594 }
10595
10596 static u32 wl_get_ielen(struct wl_priv *wl)
10597 {
10598         struct wl_ie *ie = wl_to_ie(wl);
10599
10600         return ie->offset;
10601 }
10602
10603 static void wl_link_up(struct wl_priv *wl)
10604 {
10605         wl->link_up = true;
10606 }
10607
10608 static void wl_link_down(struct wl_priv *wl)
10609 {
10610         struct wl_connect_info *conn_info = wl_to_conn(wl);
10611
10612         WL_DBG(("In\n"));
10613         wl->link_up = false;
10614         conn_info->req_ie_len = 0;
10615         conn_info->resp_ie_len = 0;
10616 }
10617
10618 static unsigned long wl_lock_eq(struct wl_priv *wl)
10619 {
10620         unsigned long flags;
10621
10622         spin_lock_irqsave(&wl->eq_lock, flags);
10623         return flags;
10624 }
10625
10626 static void wl_unlock_eq(struct wl_priv *wl, unsigned long flags)
10627 {
10628         spin_unlock_irqrestore(&wl->eq_lock, flags);
10629 }
10630
10631 static void wl_init_eq_lock(struct wl_priv *wl)
10632 {
10633         spin_lock_init(&wl->eq_lock);
10634 }
10635
10636 static void wl_delay(u32 ms)
10637 {
10638         if (in_atomic() || (ms < jiffies_to_msecs(1))) {
10639                 OSL_DELAY(ms*1000);
10640         } else {
10641                 OSL_SLEEP(ms);
10642         }
10643 }
10644
10645 s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
10646 {
10647         struct wl_priv *wl = wlcfg_drv_priv;
10648         struct ether_addr p2pif_addr;
10649         struct ether_addr primary_mac;
10650         if (!wl->p2p)
10651                 return -1;
10652         if (!p2p_is_on(wl)) {
10653                 get_primary_mac(wl, &primary_mac);
10654                 wl_cfgp2p_generate_bss_mac(&primary_mac, p2pdev_addr, &p2pif_addr);
10655         } else {
10656                 memcpy(p2pdev_addr->octet,
10657                         wl->p2p->dev_addr.octet, ETHER_ADDR_LEN);
10658         }
10659
10660
10661         return 0;
10662 }
10663 s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
10664 {
10665         struct wl_priv *wl;
10666
10667         wl = wlcfg_drv_priv;
10668
10669         return wl_cfgp2p_set_p2p_noa(wl, net, buf, len);
10670 }
10671
10672 s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
10673 {
10674         struct wl_priv *wl;
10675         wl = wlcfg_drv_priv;
10676
10677         return wl_cfgp2p_get_p2p_noa(wl, net, buf, len);
10678 }
10679
10680 s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
10681 {
10682         struct wl_priv *wl;
10683         wl = wlcfg_drv_priv;
10684
10685         return wl_cfgp2p_set_p2p_ps(wl, net, buf, len);
10686 }
10687
10688 s32 wl_cfg80211_channel_to_freq(u32 channel)
10689 {
10690         int freq = 0;
10691
10692 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
10693         freq = ieee80211_channel_to_frequency(channel);
10694 #else
10695         {
10696                 u16 band = 0;
10697                 if (channel <= CH_MAX_2G_CHANNEL)
10698                         band = IEEE80211_BAND_2GHZ;
10699                 else
10700                         band = IEEE80211_BAND_5GHZ;
10701                 freq = ieee80211_channel_to_frequency(channel, band);
10702         }
10703 #endif
10704         return freq;
10705 }
10706
10707
10708 #ifdef WLTDLS
10709 static s32
10710 wl_tdls_event_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
10711         const wl_event_msg_t *e, void *data) {
10712
10713         struct net_device *ndev = NULL;
10714         u32 reason = ntoh32(e->reason);
10715         s8 *msg = NULL;
10716
10717         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
10718
10719         switch (reason) {
10720         case WLC_E_TDLS_PEER_DISCOVERED :
10721                 msg = " TDLS PEER DISCOVERD ";
10722                 break;
10723         case WLC_E_TDLS_PEER_CONNECTED :
10724                 msg = " TDLS PEER CONNECTED ";
10725                 break;
10726         case WLC_E_TDLS_PEER_DISCONNECTED :
10727                 msg = "TDLS PEER DISCONNECTED ";
10728                 break;
10729         }
10730         if (msg) {
10731                 WL_ERR(("%s: " MACDBG " on %s ndev\n", msg, MAC2STRDBG((u8*)(&e->addr)),
10732                         (wl_to_prmry_ndev(wl) == ndev) ? "primary" : "secondary"));
10733         }
10734         return 0;
10735
10736 }
10737 #endif  /* WLTDLS */
10738
10739 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || 0
10740 static s32
10741 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
10742         u8 *peer, enum nl80211_tdls_operation oper)
10743 {
10744         s32 ret = 0;
10745 #ifdef WLTDLS
10746         struct wl_priv *wl = wlcfg_drv_priv;
10747
10748         if (!wl)
10749                 return ERR_PTR(-EINVAL);
10750
10751         tdls_iovar_t info;
10752         dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
10753         memset(&info, 0, sizeof(tdls_iovar_t));
10754         if (peer)
10755                 memcpy(&info.ea, peer, ETHER_ADDR_LEN);
10756         switch (oper) {
10757         case NL80211_TDLS_DISCOVERY_REQ:
10758                 if (!dhd->tdls_enable)
10759                         ret = dhd_tdls_enable_disable(dhd, 1);
10760                 if (ret < 0)
10761                         return ret;
10762                 info.mode = TDLS_MANUAL_EP_DISCOVERY;
10763                 break;
10764         case NL80211_TDLS_SETUP:
10765                 info.mode = TDLS_MANUAL_EP_CREATE;
10766                 break;
10767         case NL80211_TDLS_TEARDOWN:
10768                 info.mode = TDLS_MANUAL_EP_DELETE;
10769                 break;
10770         default:
10771                 WL_ERR(("Unsupported operation : %d\n", oper));
10772                 goto out;
10773         }
10774         ret = wldev_iovar_setbuf(dev, "tdls_endpoint", &info, sizeof(info),
10775                 wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
10776         if (ret) {
10777                 WL_ERR(("tdls_endpoint error %d\n", ret));
10778         }
10779 out:
10780 #endif /* WLTDLS */
10781         return ret;
10782 }
10783 #endif 
10784
10785 s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
10786         enum wl_management_type type)
10787 {
10788         struct wl_priv *wl;
10789         struct net_device *ndev = NULL;
10790         struct ether_addr primary_mac;
10791         s32 ret = 0;
10792         s32 bssidx = 0;
10793         s32 pktflag = 0;
10794         wl = wlcfg_drv_priv;
10795
10796         if (wl_get_drv_status(wl, AP_CREATING, net)) {
10797                 /* Vendor IEs should be set to FW
10798                  * after SoftAP interface is brought up
10799                  */
10800                 goto exit;
10801         } else if (wl_get_drv_status(wl, AP_CREATED, net)) {
10802                 ndev = net;
10803                 bssidx = 0;
10804         } else if (wl->p2p) {
10805                 net = ndev_to_wlc_ndev(net, wl);
10806                 if (!wl->p2p->on) {
10807                         get_primary_mac(wl, &primary_mac);
10808                         wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr,
10809                                 &wl->p2p->int_addr);
10810                         /* In case of p2p_listen command, supplicant send remain_on_channel
10811                         * without turning on P2P
10812                         */
10813
10814                         p2p_on(wl) = true;
10815                         ret = wl_cfgp2p_enable_discovery(wl, net, NULL, 0);
10816
10817                         if (unlikely(ret)) {
10818                                 goto exit;
10819                         }
10820                 }
10821                 if (net  != wl_to_prmry_ndev(wl)) {
10822                         if (wl_get_mode_by_netdev(wl, net) == WL_MODE_AP) {
10823                                 ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
10824                                 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION);
10825                         }
10826                 } else {
10827                                 ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY);
10828                                 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
10829                 }
10830         }
10831         if (ndev != NULL) {
10832                 switch (type) {
10833                         case WL_BEACON:
10834                                 pktflag = VNDR_IE_BEACON_FLAG;
10835                                 break;
10836                         case WL_PROBE_RESP:
10837                                 pktflag = VNDR_IE_PRBRSP_FLAG;
10838                                 break;
10839                         case WL_ASSOC_RESP:
10840                                 pktflag = VNDR_IE_ASSOCRSP_FLAG;
10841                                 break;
10842                 }
10843                 if (pktflag)
10844                         ret = wl_cfgp2p_set_management_ie(wl, ndev, bssidx, pktflag, buf, len);
10845         }
10846 exit:
10847         return ret;
10848 }
10849
10850 #ifdef WL_SUPPORT_AUTO_CHANNEL
10851 static s32
10852 wl_cfg80211_set_auto_channel_scan_state(struct net_device *ndev)
10853 {
10854         u32 val = 0;
10855         s32 ret = BCME_ERROR;
10856         struct wl_priv *wl = wlcfg_drv_priv;
10857
10858         /* Disable mpc, to avoid automatic interface down. */
10859         val = 0;
10860
10861         ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
10862                 sizeof(val), wl->ioctl_buf, WLC_IOCTL_SMLEN, 0,
10863                 &wl->ioctl_buf_sync);
10864         if (ret < 0) {
10865                 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
10866                 goto done;
10867         }
10868
10869         /* Set interface up, explicitly. */
10870         val = 1;
10871
10872         ret = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
10873         if (ret < 0) {
10874                 WL_ERR(("set interface up failed, error = %d\n", ret));
10875                 goto done;
10876         }
10877
10878         /* Stop all scan explicitly, till auto channel selection complete. */
10879         wl_set_drv_status(wl, SCANNING, ndev);
10880         ret = wl_notify_escan_complete(wl, ndev, true, true);
10881         if (ret < 0) {
10882                 WL_ERR(("set scan abort failed, error = %d\n", ret));
10883                 goto done;
10884         }
10885
10886 done:
10887         return ret;
10888 }
10889
10890 static bool
10891 wl_cfg80211_valid_chanspec_p2p(chanspec_t chanspec)
10892 {
10893         bool valid = false;
10894
10895         /* channel 1 to 14 */
10896         if ((chanspec >= 0x2b01) && (chanspec <= 0x2b0e)) {
10897                 valid = true;
10898         }
10899         /* channel 36 to 48 */
10900         else if ((chanspec >= 0x1b24) && (chanspec <= 0x1b30)) {
10901                 valid = true;
10902         }
10903         /* channel 149 to 161 */
10904         else if ((chanspec >= 0x1b95) && (chanspec <= 0x1ba1)) {
10905                 valid = true;
10906         }
10907         else {
10908                 valid = false;
10909                 WL_INFO(("invalid P2P chanspec, channel = %d, chanspec = %04x\n",
10910                         CHSPEC_CHANNEL(chanspec), chanspec));
10911         }
10912
10913         return valid;
10914 }
10915
10916 static s32
10917 wl_cfg80211_get_chanspecs_2g(struct net_device *ndev, void *buf, s32 buflen)
10918 {
10919         s32 ret = BCME_ERROR;
10920         struct wl_priv *wl = NULL;
10921         wl_uint32_list_t *list = NULL;
10922         chanspec_t chanspec = 0;
10923
10924         memset(buf, 0, buflen);
10925
10926         wl = wlcfg_drv_priv;
10927         list = (wl_uint32_list_t *)buf;
10928         list->count = htod32(WL_NUMCHANSPECS);
10929
10930         /* Restrict channels to 2.4GHz, 20MHz BW, no SB. */
10931         chanspec |= (WL_CHANSPEC_BAND_2G | WL_CHANSPEC_BW_20 |
10932                 WL_CHANSPEC_CTL_SB_NONE);
10933         chanspec = wl_chspec_host_to_driver(chanspec);
10934
10935         ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
10936                 sizeof(chanspec), buf, buflen, 0, &wl->ioctl_buf_sync);
10937         if (ret < 0) {
10938                 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
10939         }
10940
10941         return ret;
10942 }
10943
10944 static s32
10945 wl_cfg80211_get_chanspecs_5g(struct net_device *ndev, void *buf, s32 buflen)
10946 {
10947         u32 channel = 0;
10948         s32 ret = BCME_ERROR;
10949         s32 i = 0;
10950         s32 j = 0;
10951         struct wl_priv *wl = NULL;
10952         wl_uint32_list_t *list = NULL;
10953         chanspec_t chanspec = 0;
10954
10955         memset(buf, 0, buflen);
10956
10957         wl = wlcfg_drv_priv;
10958         list = (wl_uint32_list_t *)buf;
10959         list->count = htod32(WL_NUMCHANSPECS);
10960
10961         /* Restrict channels to 5GHz, 20MHz BW, no SB. */
10962         chanspec |= (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_20 |
10963                 WL_CHANSPEC_CTL_SB_NONE);
10964         chanspec = wl_chspec_host_to_driver(chanspec);
10965
10966         ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
10967                 sizeof(chanspec), buf, buflen, 0, &wl->ioctl_buf_sync);
10968         if (ret < 0) {
10969                 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
10970                 goto done;
10971         }
10972
10973         /* Skip DFS and inavlid P2P channel. */
10974         for (i = 0, j = 0; i < dtoh32(list->count); i++) {
10975                 chanspec = (chanspec_t) dtoh32(list->element[i]);
10976                 channel = CHSPEC_CHANNEL(chanspec);
10977
10978                 ret = wldev_iovar_getint(ndev, "per_chan_info", &channel);
10979                 if (ret < 0) {
10980                         WL_ERR(("get 'per_chan_info' failed, error = %d\n", ret));
10981                         goto done;
10982                 }
10983
10984                 if (CHANNEL_IS_RADAR(channel) ||
10985                         !(wl_cfg80211_valid_chanspec_p2p(chanspec))) {
10986                         continue;
10987                 } else {
10988                         list->element[j] = list->element[i];
10989                 }
10990
10991                 j++;
10992         }
10993
10994         list->count = j;
10995
10996 done:
10997         return ret;
10998 }
10999
11000 static s32
11001 wl_cfg80211_get_best_channel(struct net_device *ndev, void *buf, int buflen,
11002         int *channel)
11003 {
11004         s32 ret = BCME_ERROR;
11005         int chosen = 0;
11006         int retry = 0;
11007
11008         /* Start auto channel selection scan. */
11009         ret = wldev_ioctl(ndev, WLC_START_CHANNEL_SEL, buf, buflen, true);
11010         if (ret < 0) {
11011                 WL_ERR(("can't start auto channel scan, error = %d\n", ret));
11012                 *channel = 0;
11013                 goto done;
11014         }
11015
11016         /* Wait for auto channel selection, worst case possible delay is 5250ms. */
11017         retry = CHAN_SEL_RETRY_COUNT;
11018
11019         while (retry--) {
11020                 OSL_SLEEP(CHAN_SEL_IOCTL_DELAY);
11021
11022                 ret = wldev_ioctl(ndev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen),
11023                         false);
11024                 if ((ret == 0) && (dtoh32(chosen) != 0)) {
11025                         *channel = (u16)(chosen & 0x00FF);
11026                         WL_INFO(("selected channel = %d\n", *channel));
11027                         break;
11028                 }
11029                 WL_INFO(("attempt = %d, ret = %d, chosen = %d\n",
11030                         (CHAN_SEL_RETRY_COUNT - retry), ret, dtoh32(chosen)));
11031         }
11032
11033         if (retry <= 0) {
11034                 WL_ERR(("failure, auto channel selection timed out\n"));
11035                 *channel = 0;
11036                 ret = BCME_ERROR;
11037         }
11038
11039 done:
11040         return ret;
11041 }
11042
11043 static s32
11044 wl_cfg80211_restore_auto_channel_scan_state(struct net_device *ndev)
11045 {
11046         u32 val = 0;
11047         s32 ret = BCME_ERROR;
11048         struct wl_priv *wl = wlcfg_drv_priv;
11049
11050         /* Clear scan stop driver status. */
11051         wl_clr_drv_status(wl, SCANNING, ndev);
11052
11053         /* Enable mpc back to 1, irrespective of initial state. */
11054         val = 1;
11055
11056         ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
11057                 sizeof(val), wl->ioctl_buf, WLC_IOCTL_SMLEN, 0,
11058                 &wl->ioctl_buf_sync);
11059         if (ret < 0) {
11060                 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
11061         }
11062
11063         return ret;
11064 }
11065
11066 s32
11067 wl_cfg80211_get_best_channels(struct net_device *dev, char* cmd, int total_len)
11068 {
11069         int channel = 0;
11070         s32 ret = BCME_ERROR;
11071         u8 *buf = NULL;
11072         char *pos = cmd;
11073         struct wl_priv *wl = NULL;
11074         struct net_device *ndev = NULL;
11075
11076         memset(cmd, 0, total_len);
11077
11078         buf = kmalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
11079         if (buf == NULL) {
11080                 WL_ERR(("failed to allocate chanspec buffer\n"));
11081                 return -ENOMEM;
11082         }
11083
11084         /*
11085          * Always use primary interface, irrespective of interface on which
11086          * command came.
11087          */
11088         wl = wlcfg_drv_priv;
11089         ndev = wl_to_prmry_ndev(wl);
11090
11091         /*
11092          * Make sure that FW and driver are in right state to do auto channel
11093          * selection scan.
11094          */
11095         ret = wl_cfg80211_set_auto_channel_scan_state(ndev);
11096         if (ret < 0) {
11097                 WL_ERR(("can't set auto channel scan state, error = %d\n", ret));
11098                 goto done;
11099         }
11100
11101         /* Best channel selection in 2.4GHz band. */
11102         ret = wl_cfg80211_get_chanspecs_2g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
11103         if (ret < 0) {
11104                 WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
11105                 goto done;
11106         }
11107
11108         ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
11109                 &channel);
11110         if (ret < 0) {
11111                 WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
11112                 goto done;
11113         }
11114
11115         if (CHANNEL_IS_2G(channel)) {
11116                 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
11117         } else {
11118                 WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel));
11119                 channel = 0;
11120         }
11121
11122         sprintf(pos, "%04d ", channel);
11123         pos += 5;
11124
11125         /* Best channel selection in 5GHz band. */
11126         ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
11127         if (ret < 0) {
11128                 WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret));
11129                 goto done;
11130         }
11131
11132         ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
11133                 &channel);
11134         if (ret < 0) {
11135                 WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret));
11136                 goto done;
11137         }
11138
11139         if (CHANNEL_IS_5G(channel)) {
11140                 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
11141         } else {
11142                 WL_ERR(("invalid 5GHz channel, channel = %d\n", channel));
11143                 channel = 0;
11144         }
11145
11146         sprintf(pos, "%04d ", channel);
11147         pos += 5;
11148
11149         /* Set overall best channel same as 5GHz best channel. */
11150         sprintf(pos, "%04d ", channel);
11151         pos += 5;
11152
11153 done:
11154         if (NULL != buf) {
11155                 kfree(buf);
11156         }
11157
11158         /* Restore FW and driver back to normal state. */
11159         ret = wl_cfg80211_restore_auto_channel_scan_state(ndev);
11160         if (ret < 0) {
11161                 WL_ERR(("can't restore auto channel scan state, error = %d\n", ret));
11162         }
11163
11164         return (pos - cmd);
11165 }
11166 #endif /* WL_SUPPORT_AUTO_CHANNEL */
11167
11168 static const struct rfkill_ops wl_rfkill_ops = {
11169         .set_block = wl_rfkill_set
11170 };
11171
11172 static int wl_rfkill_set(void *data, bool blocked)
11173 {
11174         struct wl_priv *wl = (struct wl_priv *)data;
11175
11176         WL_DBG(("Enter \n"));
11177         WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked"));
11178
11179         if (!wl)
11180                 return -EINVAL;
11181
11182         wl->rf_blocked = blocked;
11183
11184         return 0;
11185 }
11186
11187 static int wl_setup_rfkill(struct wl_priv *wl, bool setup)
11188 {
11189         s32 err = 0;
11190
11191         WL_DBG(("Enter \n"));
11192         if (!wl)
11193                 return -EINVAL;
11194         if (setup) {
11195                 wl->rfkill = rfkill_alloc("brcmfmac-wifi",
11196                         wl_cfg80211_get_parent_dev(),
11197                         RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)wl);
11198
11199                 if (!wl->rfkill) {
11200                         err = -ENOMEM;
11201                         goto err_out;
11202                 }
11203
11204                 err = rfkill_register(wl->rfkill);
11205
11206                 if (err)
11207                         rfkill_destroy(wl->rfkill);
11208         } else {
11209                 if (!wl->rfkill) {
11210                         err = -ENOMEM;
11211                         goto err_out;
11212                 }
11213
11214                 rfkill_unregister(wl->rfkill);
11215                 rfkill_destroy(wl->rfkill);
11216         }
11217
11218 err_out:
11219         return err;
11220 }
11221
11222 #ifdef DEBUGFS_CFG80211
11223 /**
11224 * Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level
11225 * to turn on SCAN and DBG log.
11226 * To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level
11227 * To see current setting of debug level,
11228 * cat /sys/kernel/debug/dhd/debug_level
11229 */
11230 static ssize_t
11231 wl_debuglevel_write(struct file *file, const char __user *userbuf,
11232         size_t count, loff_t *ppos)
11233 {
11234         char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)], sublog[S_SUBLOGLEVEL];
11235         char *params, *token, *colon;
11236         uint i, tokens, log_on = 0;
11237         memset(tbuf, 0, sizeof(tbuf));
11238         memset(sublog, 0, sizeof(sublog));
11239         if (copy_from_user(&tbuf, userbuf, min_t(size_t, sizeof(tbuf), count)))
11240                 return -EFAULT;
11241
11242         params = &tbuf[0];
11243         colon = strchr(params, '\n');
11244         if (colon != NULL)
11245                 *colon = '\0';
11246         while ((token = strsep(&params, " ")) != NULL) {
11247                 memset(sublog, 0, sizeof(sublog));
11248                 if (token == NULL || !*token)
11249                         break;
11250                 if (*token == '\0')
11251                         continue;
11252                 colon = strchr(token, ':');
11253                 if (colon != NULL) {
11254                         *colon = ' ';
11255                 }
11256                 tokens = sscanf(token, "%s %u", sublog, &log_on);
11257                 if (colon != NULL)
11258                         *colon = ':';
11259
11260                 if (tokens == 2) {
11261                                 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
11262                                         if (!strncmp(sublog, sublogname_map[i].sublogname,
11263                                                 strlen(sublogname_map[i].sublogname))) {
11264                                                 if (log_on)
11265                                                         wl_dbg_level |=
11266                                                         (sublogname_map[i].log_level);
11267                                                 else
11268                                                         wl_dbg_level &=
11269                                                         ~(sublogname_map[i].log_level);
11270                                         }
11271                                 }
11272                 } else
11273                         WL_ERR(("%s: can't parse '%s' as a "
11274                                "SUBMODULE:LEVEL (%d tokens)\n",
11275                                tbuf, token, tokens));
11276
11277
11278         }
11279         return count;
11280 }
11281
11282 static ssize_t
11283 wl_debuglevel_read(struct file *file, char __user *user_buf,
11284         size_t count, loff_t *ppos)
11285 {
11286         char *param;
11287         char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)];
11288         uint i;
11289         memset(tbuf, 0, sizeof(tbuf));
11290         param = &tbuf[0];
11291         for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
11292                 param += snprintf(param, sizeof(tbuf) - 1, "%s:%d ",
11293                         sublogname_map[i].sublogname,
11294                         (wl_dbg_level & sublogname_map[i].log_level) ? 1 : 0);
11295         }
11296         *param = '\n';
11297         return simple_read_from_buffer(user_buf, count, ppos, tbuf, strlen(&tbuf[0]));
11298
11299 }
11300 static const struct file_operations fops_debuglevel = {
11301         .open = NULL,
11302         .write = wl_debuglevel_write,
11303         .read = wl_debuglevel_read,
11304         .owner = THIS_MODULE,
11305         .llseek = NULL,
11306 };
11307
11308 static s32 wl_setup_debugfs(struct wl_priv *wl)
11309 {
11310         s32 err = 0;
11311         struct dentry *_dentry;
11312         if (!wl)
11313                 return -EINVAL;
11314         wl->debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
11315         if (!wl->debugfs || IS_ERR(wl->debugfs)) {
11316                 if (wl->debugfs == ERR_PTR(-ENODEV))
11317                         WL_ERR(("Debugfs is not enabled on this kernel\n"));
11318                 else
11319                         WL_ERR(("Can not create debugfs directory\n"));
11320                 wl->debugfs = NULL;
11321                 goto exit;
11322
11323         }
11324         _dentry = debugfs_create_file("debug_level", S_IRUSR | S_IWUSR,
11325                 wl->debugfs, wl, &fops_debuglevel);
11326         if (!_dentry || IS_ERR(_dentry)) {
11327                 WL_ERR(("failed to create debug_level debug file\n"));
11328                 wl_free_debugfs(wl);
11329         }
11330 exit:
11331         return err;
11332 }
11333 static s32 wl_free_debugfs(struct wl_priv *wl)
11334 {
11335         if (!wl)
11336                 return -EINVAL;
11337         if (wl->debugfs)
11338                 debugfs_remove_recursive(wl->debugfs);
11339         wl->debugfs = NULL;
11340         return 0;
11341 }
11342 #endif /* DEBUGFS_CFG80211 */
11343
11344 struct device *wl_cfg80211_get_parent_dev(void)
11345 {
11346         return cfg80211_parent_dev;
11347 }
11348
11349 void wl_cfg80211_set_parent_dev(void *dev)
11350 {
11351         cfg80211_parent_dev = dev;
11352 }
11353
11354 static void wl_cfg80211_clear_parent_dev(void)
11355 {
11356         cfg80211_parent_dev = NULL;
11357 }
11358
11359 void get_primary_mac(struct wl_priv *wl, struct ether_addr *mac)
11360 {
11361         wldev_iovar_getbuf_bsscfg(wl_to_prmry_ndev(wl), "cur_etheraddr", NULL,
11362                 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, 0, &wl->ioctl_buf_sync);
11363         memcpy(mac->octet, wl->ioctl_buf, ETHER_ADDR_LEN);
11364 }
11365 static bool check_dev_role_integrity(struct wl_priv *wl, u32 dev_role)
11366 {
11367         dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
11368         if (((dev_role == NL80211_IFTYPE_AP) &&
11369                 !(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) ||
11370                 ((dev_role == NL80211_IFTYPE_P2P_GO) &&
11371                 !(dhd->op_mode & DHD_FLAG_P2P_GO_MODE)))
11372         {
11373                 WL_ERR(("device role select failed\n"));
11374                 return false;
11375         }
11376         return true;
11377 }
11378
11379 int wl_cfg80211_do_driver_init(struct net_device *net)
11380 {
11381         struct wl_priv *wl = *(struct wl_priv **)netdev_priv(net);
11382
11383         if (!wl || !wl->wdev)
11384                 return -EINVAL;
11385
11386         if (dhd_do_driver_init(wl->wdev->netdev) < 0)
11387                 return -1;
11388
11389         return 0;
11390 }
11391
11392 void wl_cfg80211_enable_trace(bool set, u32 level)
11393 {
11394         if (set)
11395                 wl_dbg_level = level & WL_DBG_LEVEL;
11396         else
11397                 wl_dbg_level |= (WL_DBG_LEVEL & level);
11398 }
11399 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
11400         2, 0))
11401 static s32
11402 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
11403         bcm_struct_cfgdev *cfgdev, u64 cookie)
11404 {
11405         /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION
11406          * is passed with CMD_FRAME. This callback is supposed to cancel
11407          * the OFFCHANNEL Wait. Since we are already taking care of that
11408          *  with the tx_mgmt logic, do nothing here.
11409          */
11410
11411         return 0;
11412 }
11413 #endif /* WL_SUPPORT_BACKPORTED_PATCHES || KERNEL >= 3.2.0 */
11414
11415
11416
11417
11418 static void wl_cfg80211_work_handler(struct work_struct * work)
11419 {
11420         struct wl_priv *wl = NULL;
11421         struct net_info *iter, *next;
11422         s32 err = BCME_OK;
11423         s32 pm = PM_FAST;
11424
11425         wl = container_of(work, struct wl_priv, pm_enable_work.work);
11426         WL_DBG(("Enter \n"));
11427         if (wl->pm_enable_work_on) {
11428                 wl->pm_enable_work_on = false;
11429                 for_each_ndev(wl, iter, next) {
11430                         if (!wl_get_drv_status(wl, CONNECTED, iter->ndev) ||
11431                                 (wl_get_mode_by_netdev(wl, iter->ndev) != WL_MODE_BSS))
11432                                 continue;
11433                         if (iter->ndev) {
11434                                 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM,
11435                                         &pm, sizeof(pm), true)) != 0) {
11436                                         if (err == -ENODEV)
11437                                                 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
11438                                         else
11439                                                 WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
11440                                 } else
11441                                         iter->ndev->ieee80211_ptr->ps = true;
11442                         }
11443                 }
11444         }
11445 }
11446
11447 u8
11448 wl_get_action_category(void *frame, u32 frame_len)
11449 {
11450         u8 category;
11451         u8 *ptr = (u8 *)frame;
11452         if (frame == NULL)
11453                 return DOT11_ACTION_CAT_ERR_MASK;
11454         if (frame_len < DOT11_ACTION_HDR_LEN)
11455                 return DOT11_ACTION_CAT_ERR_MASK;
11456         category = ptr[DOT11_ACTION_CAT_OFF];
11457         WL_INFO(("Action Category: %d\n", category));
11458         return category;
11459 }
11460
11461 int
11462 wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action)
11463 {
11464         u8 *ptr = (u8 *)frame;
11465         if (frame == NULL || ret_action == NULL)
11466                 return BCME_ERROR;
11467         if (frame_len < DOT11_ACTION_HDR_LEN)
11468                 return BCME_ERROR;
11469         if (DOT11_ACTION_CAT_PUBLIC != wl_get_action_category(frame, frame_len))
11470                 return BCME_ERROR;
11471         *ret_action = ptr[DOT11_ACTION_ACT_OFF];
11472         WL_INFO(("Public Action : %d\n", *ret_action));
11473         return BCME_OK;
11474 }
11475 #ifdef BCMCCX_S69
11476 static s32
11477 wl_ccx_s69_response(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
11478         const wl_event_msg_t *e, void *data)
11479 {
11480         struct net_device *ndev = NULL;
11481         u32 event = ntoh32(e->event_type);
11482         u32 datalen = ntoh32(e->datalen);
11483         s32 err;
11484
11485         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
11486         err = wl_genl_send_msg(ndev, event, data, (u16)datalen, 0, 0);
11487
11488         return err;
11489 }
11490 #endif /* BCMCCX_S69 */