]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/blob - drivers/net/wireless/bcmdhd/wl_cfg80211.c
bf05aca7f253914fef32e3fec8128f286fa26158
[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_40;
5204         u32 chanspec = 0;
5205         struct net_info *iter, *next;
5206
5207         s32 err = BCME_OK;
5208         struct wl_priv *wl = wiphy_priv(wiphy);
5209
5210         if (!wl)
5211                 return ERR_PTR(-EINVAL);
5212         dev = ndev_to_wlc_ndev(dev, wl);
5213         _chan = ieee80211_frequency_to_channel(chan->center_freq);
5214         WL_ERR(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
5215                 dev->ifindex, channel_type, _chan));
5216
5217         /* In 5GHz band If AP is connected in 20 MHz then follow AP's bw
5218            else 40MHz by default. */
5219         for_each_ndev(wl, iter, next) {
5220                 /* In case interface name is not wlan0 put the right
5221                    interface name. */
5222                 if(!strncmp(iter->ndev->name, "wlan0", strlen("wlan0"))) {
5223                         if (wl_get_drv_status(wl, CONNECTED, iter->ndev)) {
5224                                 if (chan->band == IEEE80211_BAND_5GHZ) {
5225                                         if(wldev_iovar_getint(iter->ndev,
5226                                                 "chanspec", (s32 *)&chanspec) == BCME_OK) {
5227                                                 chanspec = wl_chspec_driver_to_host(chanspec);
5228                                                 /* bits 11,12 and 13 starting from 0 are bw
5229                                                    bits. So, values formed with these bits
5230                                                    are 0 ,1, 2, 3, 4, 5, 6 which are mapped
5231                                                    to 5, 10, 20 ,40 ,80, 160, 80+80 MHz
5232                                                    respectively. In below case, 0x1000 = 2
5233                                                    which is for 20 MHz */
5234                                                 if((chanspec & 0x3800) == 0x1000)
5235                                                         bw = WL_CHANSPEC_BW_20;
5236                                         }
5237                                 } else {
5238                                         /* In 2.4 GHz supported bw is 20 MHz */
5239                                         bw = WL_CHANSPEC_BW_20;
5240                                 }
5241                         }
5242                 }
5243         }
5244 set_channel:
5245         chspec = wf_channel2chspec(_chan, bw);
5246         if (wf_chspec_valid(chspec)) {
5247                 fw_chspec = wl_chspec_host_to_driver(chspec);
5248                 if (fw_chspec != INVCHANSPEC) {
5249                         if ((err = wldev_iovar_setint(dev, "chanspec",
5250                                 fw_chspec)) == BCME_BADCHAN) {
5251                                 if (bw == WL_CHANSPEC_BW_80)
5252                                         goto change_bw;
5253                                 err = wldev_ioctl(dev, WLC_SET_CHANNEL,
5254                                         &_chan, sizeof(_chan), true);
5255                                 if (err < 0) {
5256                                         WL_ERR(("WLC_SET_CHANNEL error %d"
5257                                         "chip may not be supporting this channel\n", err));
5258                                 }
5259                         } else if (err) {
5260                                 WL_ERR(("failed to set chanspec error %d\n", err));
5261                         }
5262                 } else {
5263                         WL_ERR(("failed to convert host chanspec to fw chanspec\n"));
5264                         err = BCME_ERROR;
5265                 }
5266         } else {
5267 change_bw:
5268                 if (bw == WL_CHANSPEC_BW_80)
5269                         bw = WL_CHANSPEC_BW_40;
5270                 else if (bw == WL_CHANSPEC_BW_40)
5271                         bw = WL_CHANSPEC_BW_20;
5272                 else
5273                         bw = 0;
5274                 if (bw)
5275                         goto set_channel;
5276                 WL_ERR(("Invalid chanspec 0x%x\n", chspec));
5277                 err = BCME_ERROR;
5278         }
5279         return err;
5280 }
5281
5282 static s32
5283 wl_validate_opensecurity(struct net_device *dev, s32 bssidx)
5284 {
5285         s32 err = BCME_OK;
5286
5287         /* set auth */
5288         err = wldev_iovar_setint_bsscfg(dev, "auth", 0, bssidx);
5289         if (err < 0) {
5290                 WL_ERR(("auth error %d\n", err));
5291                 return BCME_ERROR;
5292         }
5293         /* set wsec */
5294         err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
5295         if (err < 0) {
5296                 WL_ERR(("wsec error %d\n", err));
5297                 return BCME_ERROR;
5298         }
5299         /* set upper-layer auth */
5300         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", WPA_AUTH_NONE, bssidx);
5301         if (err < 0) {
5302                 WL_ERR(("wpa_auth error %d\n", err));
5303                 return BCME_ERROR;
5304         }
5305
5306         return 0;
5307 }
5308
5309 static s32
5310 wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
5311 {
5312         s32 len = 0;
5313         s32 err = BCME_OK;
5314         u16 auth = 0; /* d11 open authentication */
5315         u32 wsec;
5316         u32 pval = 0;
5317         u32 gval = 0;
5318         u32 wpa_auth = 0;
5319         wpa_suite_mcast_t *mcast;
5320         wpa_suite_ucast_t *ucast;
5321         wpa_suite_auth_key_mgmt_t *mgmt;
5322
5323         u16 suite_count;
5324         u8 rsn_cap[2];
5325         u32 wme_bss_disable;
5326
5327         if (wpa2ie == NULL)
5328                 goto exit;
5329
5330         WL_DBG(("Enter \n"));
5331         len =  wpa2ie->len;
5332         /* check the mcast cipher */
5333         mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
5334         switch (mcast->type) {
5335                 case WPA_CIPHER_NONE:
5336                         gval = 0;
5337                         break;
5338                 case WPA_CIPHER_WEP_40:
5339                 case WPA_CIPHER_WEP_104:
5340                         gval = WEP_ENABLED;
5341                         break;
5342                 case WPA_CIPHER_TKIP:
5343                         gval = TKIP_ENABLED;
5344                         break;
5345                 case WPA_CIPHER_AES_CCM:
5346                         gval = AES_ENABLED;
5347                         break;
5348                 default:
5349                         WL_ERR(("No Security Info\n"));
5350                         break;
5351         }
5352         if ((len -= WPA_SUITE_LEN) <= 0)
5353                 return BCME_BADLEN;
5354
5355         /* check the unicast cipher */
5356         ucast = (wpa_suite_ucast_t *)&mcast[1];
5357         suite_count = ltoh16_ua(&ucast->count);
5358         switch (ucast->list[0].type) {
5359                 case WPA_CIPHER_NONE:
5360                         pval = 0;
5361                         break;
5362                 case WPA_CIPHER_WEP_40:
5363                 case WPA_CIPHER_WEP_104:
5364                         pval = WEP_ENABLED;
5365                         break;
5366                 case WPA_CIPHER_TKIP:
5367                         pval = TKIP_ENABLED;
5368                         break;
5369                 case WPA_CIPHER_AES_CCM:
5370                         pval = AES_ENABLED;
5371                         break;
5372                 default:
5373                         WL_ERR(("No Security Info\n"));
5374         }
5375         if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
5376                 return BCME_BADLEN;
5377
5378         /* FOR WPS , set SEC_OW_ENABLED */
5379         wsec = (pval | gval | SES_OW_ENABLED);
5380         /* check the AKM */
5381         mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
5382         suite_count = ltoh16_ua(&mgmt->count);
5383         switch (mgmt->list[0].type) {
5384                 case RSN_AKM_NONE:
5385                         wpa_auth = WPA_AUTH_NONE;
5386                         break;
5387                 case RSN_AKM_UNSPECIFIED:
5388                         wpa_auth = WPA2_AUTH_UNSPECIFIED;
5389                         break;
5390                 case RSN_AKM_PSK:
5391                         wpa_auth = WPA2_AUTH_PSK;
5392                         break;
5393                 default:
5394                         WL_ERR(("No Key Mgmt Info\n"));
5395         }
5396
5397         if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
5398                 rsn_cap[0] = *(u8 *)&mgmt->list[suite_count];
5399                 rsn_cap[1] = *((u8 *)&mgmt->list[suite_count] + 1);
5400
5401                 if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
5402                         wme_bss_disable = 0;
5403                 } else {
5404                         wme_bss_disable = 1;
5405                 }
5406
5407                 /* set wme_bss_disable to sync RSN Capabilities */
5408                 err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
5409                 if (err < 0) {
5410                         WL_ERR(("wme_bss_disable error %d\n", err));
5411                         return BCME_ERROR;
5412                 }
5413         } else {
5414                 WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
5415         }
5416
5417         /* set auth */
5418         err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
5419         if (err < 0) {
5420                 WL_ERR(("auth error %d\n", err));
5421                 return BCME_ERROR;
5422         }
5423         /* set wsec */
5424         err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
5425         if (err < 0) {
5426                 WL_ERR(("wsec error %d\n", err));
5427                 return BCME_ERROR;
5428         }
5429         /* set upper-layer auth */
5430         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
5431         if (err < 0) {
5432                 WL_ERR(("wpa_auth error %d\n", err));
5433                 return BCME_ERROR;
5434         }
5435 exit:
5436         return 0;
5437 }
5438
5439 static s32
5440 wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx)
5441 {
5442         wpa_suite_mcast_t *mcast;
5443         wpa_suite_ucast_t *ucast;
5444         wpa_suite_auth_key_mgmt_t *mgmt;
5445         u16 auth = 0; /* d11 open authentication */
5446         u16 count;
5447         s32 err = BCME_OK;
5448         s32 len = 0;
5449         u32 i;
5450         u32 wsec;
5451         u32 pval = 0;
5452         u32 gval = 0;
5453         u32 wpa_auth = 0;
5454         u32 tmp = 0;
5455
5456         if (wpaie == NULL)
5457                 goto exit;
5458         WL_DBG(("Enter \n"));
5459         len = wpaie->length;    /* value length */
5460         len -= WPA_IE_TAG_FIXED_LEN;
5461         /* check for multicast cipher suite */
5462         if (len < WPA_SUITE_LEN) {
5463                 WL_INFO(("no multicast cipher suite\n"));
5464                 goto exit;
5465         }
5466
5467         /* pick up multicast cipher */
5468         mcast = (wpa_suite_mcast_t *)&wpaie[1];
5469         len -= WPA_SUITE_LEN;
5470         if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
5471                 if (IS_WPA_CIPHER(mcast->type)) {
5472                         tmp = 0;
5473                         switch (mcast->type) {
5474                                 case WPA_CIPHER_NONE:
5475                                         tmp = 0;
5476                                         break;
5477                                 case WPA_CIPHER_WEP_40:
5478                                 case WPA_CIPHER_WEP_104:
5479                                         tmp = WEP_ENABLED;
5480                                         break;
5481                                 case WPA_CIPHER_TKIP:
5482                                         tmp = TKIP_ENABLED;
5483                                         break;
5484                                 case WPA_CIPHER_AES_CCM:
5485                                         tmp = AES_ENABLED;
5486                                         break;
5487                                 default:
5488                                         WL_ERR(("No Security Info\n"));
5489                         }
5490                         gval |= tmp;
5491                 }
5492         }
5493         /* Check for unicast suite(s) */
5494         if (len < WPA_IE_SUITE_COUNT_LEN) {
5495                 WL_INFO(("no unicast suite\n"));
5496                 goto exit;
5497         }
5498         /* walk thru unicast cipher list and pick up what we recognize */
5499         ucast = (wpa_suite_ucast_t *)&mcast[1];
5500         count = ltoh16_ua(&ucast->count);
5501         len -= WPA_IE_SUITE_COUNT_LEN;
5502         for (i = 0; i < count && len >= WPA_SUITE_LEN;
5503                 i++, len -= WPA_SUITE_LEN) {
5504                 if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
5505                         if (IS_WPA_CIPHER(ucast->list[i].type)) {
5506                                 tmp = 0;
5507                                 switch (ucast->list[i].type) {
5508                                         case WPA_CIPHER_NONE:
5509                                                 tmp = 0;
5510                                                 break;
5511                                         case WPA_CIPHER_WEP_40:
5512                                         case WPA_CIPHER_WEP_104:
5513                                                 tmp = WEP_ENABLED;
5514                                                 break;
5515                                         case WPA_CIPHER_TKIP:
5516                                                 tmp = TKIP_ENABLED;
5517                                                 break;
5518                                         case WPA_CIPHER_AES_CCM:
5519                                                 tmp = AES_ENABLED;
5520                                                 break;
5521                                         default:
5522                                                 WL_ERR(("No Security Info\n"));
5523                                 }
5524                                 pval |= tmp;
5525                         }
5526                 }
5527         }
5528         len -= (count - i) * WPA_SUITE_LEN;
5529         /* Check for auth key management suite(s) */
5530         if (len < WPA_IE_SUITE_COUNT_LEN) {
5531                 WL_INFO((" no auth key mgmt suite\n"));
5532                 goto exit;
5533         }
5534         /* walk thru auth management suite list and pick up what we recognize */
5535         mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
5536         count = ltoh16_ua(&mgmt->count);
5537         len -= WPA_IE_SUITE_COUNT_LEN;
5538         for (i = 0; i < count && len >= WPA_SUITE_LEN;
5539                 i++, len -= WPA_SUITE_LEN) {
5540                 if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
5541                         if (IS_WPA_AKM(mgmt->list[i].type)) {
5542                                 tmp = 0;
5543                                 switch (mgmt->list[i].type) {
5544                                         case RSN_AKM_NONE:
5545                                                 tmp = WPA_AUTH_NONE;
5546                                                 break;
5547                                         case RSN_AKM_UNSPECIFIED:
5548                                                 tmp = WPA_AUTH_UNSPECIFIED;
5549                                                 break;
5550                                         case RSN_AKM_PSK:
5551                                                 tmp = WPA_AUTH_PSK;
5552                                                 break;
5553                                         default:
5554                                                 WL_ERR(("No Key Mgmt Info\n"));
5555                                 }
5556                                 wpa_auth |= tmp;
5557                         }
5558                 }
5559
5560         }
5561         /* FOR WPS , set SEC_OW_ENABLED */
5562         wsec = (pval | gval | SES_OW_ENABLED);
5563         /* set auth */
5564         err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
5565         if (err < 0) {
5566                 WL_ERR(("auth error %d\n", err));
5567                 return BCME_ERROR;
5568         }
5569         /* set wsec */
5570         err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
5571         if (err < 0) {
5572                 WL_ERR(("wsec error %d\n", err));
5573                 return BCME_ERROR;
5574         }
5575         /* set upper-layer auth */
5576         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
5577         if (err < 0) {
5578                 WL_ERR(("wpa_auth error %d\n", err));
5579                 return BCME_ERROR;
5580         }
5581 exit:
5582         return 0;
5583 }
5584
5585 static s32
5586 wl_cfg80211_bcn_validate_sec(
5587         struct net_device *dev,
5588         struct parsed_ies *ies,
5589         u32 dev_role,
5590         s32 bssidx)
5591 {
5592         struct wl_priv *wl = wlcfg_drv_priv;
5593
5594         if (dev_role == NL80211_IFTYPE_P2P_GO && (ies->wpa2_ie)) {
5595                 /* For P2P GO, the sec type is WPA2-PSK */
5596                 WL_DBG(("P2P GO: validating wpa2_ie"));
5597                 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0)
5598                         return BCME_ERROR;
5599
5600         } else if (dev_role == NL80211_IFTYPE_AP) {
5601
5602                 WL_DBG(("SoftAP: validating security"));
5603                 /* If wpa2_ie or wpa_ie is present validate it */
5604                 if ((ies->wpa2_ie || ies->wpa_ie) &&
5605                         ((wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0 ||
5606                         wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0))) {
5607                         wl->ap_info->security_mode = false;
5608                         return BCME_ERROR;
5609                 }
5610
5611                 wl->ap_info->security_mode = true;
5612                 if (wl->ap_info->rsn_ie) {
5613                         kfree(wl->ap_info->rsn_ie);
5614                         wl->ap_info->rsn_ie = NULL;
5615                 }
5616                 if (wl->ap_info->wpa_ie) {
5617                         kfree(wl->ap_info->wpa_ie);
5618                         wl->ap_info->wpa_ie = NULL;
5619                 }
5620                 if (wl->ap_info->wps_ie) {
5621                         kfree(wl->ap_info->wps_ie);
5622                         wl->ap_info->wps_ie = NULL;
5623                 }
5624                 if (ies->wpa_ie != NULL) {
5625                         /* WPAIE */
5626                         wl->ap_info->rsn_ie = NULL;
5627                         wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie,
5628                                 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
5629                                 GFP_KERNEL);
5630                 } else if (ies->wpa2_ie != NULL) {
5631                         /* RSNIE */
5632                         wl->ap_info->wpa_ie = NULL;
5633                         wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie,
5634                                 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
5635                                 GFP_KERNEL);
5636                 }
5637
5638                 if (!ies->wpa2_ie && !ies->wpa_ie) {
5639                         wl_validate_opensecurity(dev, bssidx);
5640                         wl->ap_info->security_mode = false;
5641                 }
5642
5643                 if (ies->wps_ie) {
5644                         wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
5645                 }
5646         }
5647
5648         return 0;
5649
5650 }
5651
5652 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
5653 static s32 wl_cfg80211_bcn_set_params(
5654         struct cfg80211_ap_settings *info,
5655         struct net_device *dev,
5656         u32 dev_role, s32 bssidx)
5657 {
5658         struct wl_priv *wl = wlcfg_drv_priv;
5659         s32 err = BCME_OK;
5660
5661         WL_DBG(("interval (%d) \ndtim_period (%d) \n",
5662                 info->beacon_interval, info->dtim_period));
5663
5664         if (info->beacon_interval) {
5665                 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
5666                         &info->beacon_interval, sizeof(s32), true)) < 0) {
5667                         WL_ERR(("Beacon Interval Set Error, %d\n", err));
5668                         return err;
5669                 }
5670         }
5671
5672         if (info->dtim_period) {
5673                 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
5674                         &info->dtim_period, sizeof(s32), true)) < 0) {
5675                         WL_ERR(("DTIM Interval Set Error, %d\n", err));
5676                         return err;
5677                 }
5678         }
5679
5680         if ((info->ssid) && (info->ssid_len > 0) &&
5681                 (info->ssid_len <= 32)) {
5682                 WL_DBG(("SSID (%s) len:%d \n", info->ssid, info->ssid_len));
5683                 if (dev_role == NL80211_IFTYPE_AP) {
5684                         /* Store the hostapd SSID */
5685                         memset(wl->hostapd_ssid.SSID, 0x00, 32);
5686                         memcpy(wl->hostapd_ssid.SSID, info->ssid, info->ssid_len);
5687                         wl->hostapd_ssid.SSID_len = info->ssid_len;
5688                 } else {
5689                                 /* P2P GO */
5690                         memset(wl->p2p->ssid.SSID, 0x00, 32);
5691                         memcpy(wl->p2p->ssid.SSID, info->ssid, info->ssid_len);
5692                         wl->p2p->ssid.SSID_len = info->ssid_len;
5693                 }
5694         }
5695
5696         if (info->hidden_ssid) {
5697                 if ((err = wldev_iovar_setint(dev, "closednet", 1)) < 0)
5698                         WL_ERR(("failed to set hidden : %d\n", err));
5699                 WL_DBG(("hidden_ssid_enum_val: %d \n", info->hidden_ssid));
5700         }
5701
5702         return err;
5703 }
5704 #endif 
5705
5706 static s32
5707 wl_cfg80211_parse_ies(u8 *ptr, u32 len, struct parsed_ies *ies)
5708 {
5709         s32 err = BCME_OK;
5710
5711         memset(ies, 0, sizeof(struct parsed_ies));
5712
5713         /* find the WPSIE */
5714         if ((ies->wps_ie = wl_cfgp2p_find_wpsie(ptr, len)) != NULL) {
5715                 WL_DBG(("WPSIE in beacon \n"));
5716                 ies->wps_ie_len = ies->wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
5717         } else {
5718                 WL_ERR(("No WPSIE in beacon \n"));
5719         }
5720
5721         /* find the RSN_IE */
5722         if ((ies->wpa2_ie = bcm_parse_tlvs(ptr, len,
5723                 DOT11_MNG_RSN_ID)) != NULL) {
5724                 WL_DBG((" WPA2 IE found\n"));
5725                 ies->wpa2_ie_len = ies->wpa2_ie->len;
5726         }
5727
5728         /* find the WPA_IE */
5729         if ((ies->wpa_ie = wl_cfgp2p_find_wpaie(ptr, len)) != NULL) {
5730                 WL_DBG((" WPA found\n"));
5731                 ies->wpa_ie_len = ies->wpa_ie->length;
5732         }
5733
5734         return err;
5735
5736 }
5737
5738 static s32
5739 wl_cfg80211_bcn_bringup_ap(
5740         struct net_device *dev,
5741         struct parsed_ies *ies,
5742         u32 dev_role, s32 bssidx)
5743 {
5744         struct wl_priv *wl = wlcfg_drv_priv;
5745         struct wl_join_params join_params;
5746         bool is_bssup = false;
5747         s32 infra = 1;
5748         s32 join_params_size = 0;
5749         s32 ap = 1;
5750 #ifdef DISABLE_11H_SOFTAP
5751         s32 spect = 0;
5752 #endif /* DISABLE_11H_SOFTAP */
5753         s32 err = BCME_OK;
5754
5755         WL_DBG(("Enter dev_role: %d\n", dev_role));
5756
5757         /* Common code for SoftAP and P2P GO */
5758         wldev_iovar_setint(dev, "mpc", 0);
5759
5760         if (dev_role == NL80211_IFTYPE_P2P_GO) {
5761                 is_bssup = wl_cfgp2p_bss_isup(dev, bssidx);
5762                 if (!is_bssup && (ies->wpa2_ie != NULL)) {
5763
5764                         err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
5765                         if (err < 0) {
5766                                 WL_ERR(("SET INFRA error %d\n", err));
5767                                 goto exit;
5768                         }
5769
5770                         err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &wl->p2p->ssid,
5771                                 sizeof(wl->p2p->ssid), wl->ioctl_buf, WLC_IOCTL_MAXLEN,
5772                                 bssidx, &wl->ioctl_buf_sync);
5773                         if (err < 0) {
5774                                 WL_ERR(("GO SSID setting error %d\n", err));
5775                                 goto exit;
5776                         }
5777
5778                         /* Do abort scan before creating GO */
5779                         wl_cfg80211_scan_abort(wl);
5780
5781                         if ((err = wl_cfgp2p_bss(wl, dev, bssidx, 1)) < 0) {
5782                                 WL_ERR(("GO Bring up error %d\n", err));
5783                                 goto exit;
5784                         }
5785                 } else
5786                         WL_DBG(("Bss is already up\n"));
5787         } else if ((dev_role == NL80211_IFTYPE_AP) &&
5788                 (wl_get_drv_status(wl, AP_CREATING, dev))) {
5789                 /* Device role SoftAP */
5790                 err = wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), true);
5791                 if (err < 0) {
5792                         WL_ERR(("WLC_DOWN error %d\n", err));
5793                         goto exit;
5794                 }
5795                 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
5796                 if (err < 0) {
5797                         WL_ERR(("SET INFRA error %d\n", err));
5798                         goto exit;
5799                 }
5800                 if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
5801                         WL_ERR(("setting AP mode failed %d \n", err));
5802                         goto exit;
5803                 }
5804 #ifdef DISABLE_11H_SOFTAP
5805                 err = wldev_ioctl(dev, WLC_SET_SPECT_MANAGMENT,
5806                         &spect, sizeof(s32), true);
5807                 if (err < 0) {
5808                         WL_ERR(("SET SPECT_MANAGMENT error %d\n", err));
5809                         goto exit;
5810                 }
5811 #endif /* DISABLE_11H_SOFTAP */
5812
5813                 err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
5814                 if (unlikely(err)) {
5815                         WL_ERR(("WLC_UP error (%d)\n", err));
5816                         goto exit;
5817                 }
5818
5819                 memset(&join_params, 0, sizeof(join_params));
5820                 /* join parameters starts with ssid */
5821                 join_params_size = sizeof(join_params.ssid);
5822                 memcpy(join_params.ssid.SSID, wl->hostapd_ssid.SSID,
5823                         wl->hostapd_ssid.SSID_len);
5824                 join_params.ssid.SSID_len = htod32(wl->hostapd_ssid.SSID_len);
5825
5826                 /* create softap */
5827                 if ((err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
5828                         join_params_size, true)) == 0) {
5829                         WL_DBG(("SoftAP set SSID (%s) success\n", join_params.ssid.SSID));
5830                         wl_clr_drv_status(wl, AP_CREATING, dev);
5831                         wl_set_drv_status(wl, AP_CREATED, dev);
5832                 }
5833         }
5834
5835
5836 exit:
5837         return err;
5838 }
5839
5840 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
5841 s32
5842 wl_cfg80211_parse_ap_ies(
5843         struct net_device *dev,
5844         struct cfg80211_beacon_data *info,
5845         struct parsed_ies *ies)
5846 {
5847         struct parsed_ies prb_ies;
5848         struct wl_priv *wl = wlcfg_drv_priv;
5849         dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
5850         u8 *vndr = NULL;
5851         u32 vndr_ie_len = 0;
5852         s32 err = BCME_OK;
5853
5854         /* Parse Beacon IEs */
5855         if (wl_cfg80211_parse_ies((u8 *)info->tail,
5856                 info->tail_len, ies) < 0) {
5857                 WL_ERR(("Beacon get IEs failed \n"));
5858                 err = -EINVAL;
5859                 goto fail;
5860         }
5861
5862         vndr = (u8 *)info->proberesp_ies;
5863         vndr_ie_len = info->proberesp_ies_len;
5864
5865         if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
5866                 /* SoftAP mode */
5867                 struct ieee80211_mgmt *mgmt;
5868                 mgmt = (struct ieee80211_mgmt *)info->probe_resp;
5869                 if (mgmt != NULL) {
5870                         vndr = (u8 *)&mgmt->u.probe_resp.variable;
5871                         vndr_ie_len = info->probe_resp_len -
5872                                 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
5873                 }
5874         }
5875
5876         /* Parse Probe Response IEs */
5877         if (wl_cfg80211_parse_ies(vndr, vndr_ie_len, &prb_ies) < 0) {
5878                 WL_ERR(("PROBE RESP get IEs failed \n"));
5879                 err = -EINVAL;
5880         }
5881
5882 fail:
5883
5884         return err;
5885 }
5886
5887 s32
5888 wl_cfg80211_set_ies(
5889         struct net_device *dev,
5890         struct cfg80211_beacon_data *info,
5891         s32 bssidx)
5892 {
5893         struct wl_priv *wl = wlcfg_drv_priv;
5894         dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
5895         u8 *vndr = NULL;
5896         u32 vndr_ie_len = 0;
5897         s32 err = BCME_OK;
5898
5899         /* Set Beacon IEs to FW */
5900         if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx,
5901                 VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
5902                 info->tail_len)) < 0) {
5903                 WL_ERR(("Set Beacon IE Failed \n"));
5904         } else {
5905                 WL_DBG(("Applied Vndr IEs for Beacon \n"));
5906         }
5907
5908         vndr = (u8 *)info->proberesp_ies;
5909         vndr_ie_len = info->proberesp_ies_len;
5910
5911         if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
5912                 /* SoftAP mode */
5913                 struct ieee80211_mgmt *mgmt;
5914                 mgmt = (struct ieee80211_mgmt *)info->probe_resp;
5915                 if (mgmt != NULL) {
5916                         vndr = (u8 *)&mgmt->u.probe_resp.variable;
5917                         vndr_ie_len = info->probe_resp_len -
5918                                 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
5919                 }
5920         }
5921
5922         /* Set Probe Response IEs to FW */
5923         if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx,
5924                 VNDR_IE_PRBRSP_FLAG, vndr, vndr_ie_len)) < 0) {
5925                 WL_ERR(("Set Probe Resp IE Failed \n"));
5926         } else {
5927                 WL_DBG(("Applied Vndr IEs for Probe Resp \n"));
5928         }
5929
5930         return err;
5931 }
5932 #endif 
5933
5934 static s32 wl_cfg80211_hostapd_sec(
5935         struct net_device *dev,
5936         struct parsed_ies *ies,
5937         s32 bssidx)
5938 {
5939         bool update_bss = 0;
5940         struct wl_priv *wl = wlcfg_drv_priv;
5941
5942
5943         if (ies->wps_ie) {
5944                 if (wl->ap_info->wps_ie &&
5945                         memcmp(wl->ap_info->wps_ie, ies->wps_ie, ies->wps_ie_len)) {
5946                         WL_DBG((" WPS IE is changed\n"));
5947                         kfree(wl->ap_info->wps_ie);
5948                         wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
5949                 } else if (wl->ap_info->wps_ie == NULL) {
5950                         WL_DBG((" WPS IE is added\n"));
5951                         wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
5952                 }
5953                 if ((ies->wpa_ie != NULL || ies->wpa2_ie != NULL)) {
5954                         if (!wl->ap_info->security_mode) {
5955                                 /* change from open mode to security mode */
5956                                 update_bss = true;
5957                                 if (ies->wpa_ie != NULL) {
5958                                         wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie,
5959                                         ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
5960                                         GFP_KERNEL);
5961                                 } else {
5962                                         wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie,
5963                                         ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
5964                                         GFP_KERNEL);
5965                                 }
5966                         } else if (wl->ap_info->wpa_ie) {
5967                                 /* change from WPA2 mode to WPA mode */
5968                                 if (ies->wpa_ie != NULL) {
5969                                         update_bss = true;
5970                                         kfree(wl->ap_info->rsn_ie);
5971                                         wl->ap_info->rsn_ie = NULL;
5972                                         wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie,
5973                                         ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
5974                                         GFP_KERNEL);
5975                                 } else if (memcmp(wl->ap_info->rsn_ie,
5976                                         ies->wpa2_ie, ies->wpa2_ie->len
5977                                         + WPA_RSN_IE_TAG_FIXED_LEN)) {
5978                                         update_bss = true;
5979                                         kfree(wl->ap_info->rsn_ie);
5980                                         wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie,
5981                                         ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
5982                                         GFP_KERNEL);
5983                                         wl->ap_info->wpa_ie = NULL;
5984                                 }
5985                         }
5986                         if (update_bss) {
5987                                 wl->ap_info->security_mode = true;
5988                                 wl_cfgp2p_bss(wl, dev, bssidx, 0);
5989                                 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0 ||
5990                                         wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0) {
5991                                         return BCME_ERROR;
5992                                 }
5993                                 wl_cfgp2p_bss(wl, dev, bssidx, 1);
5994                         }
5995                 }
5996         } else {
5997                 WL_ERR(("No WPSIE in beacon \n"));
5998         }
5999         return 0;
6000 }
6001
6002 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
6003         2, 0))
6004 static s32
6005 wl_cfg80211_del_station(
6006         struct wiphy *wiphy,
6007         struct net_device *ndev,
6008         u8* mac_addr)
6009 {
6010         struct net_device *dev;
6011         struct wl_priv *wl = wiphy_priv(wiphy);
6012         scb_val_t scb_val;
6013         s8 eabuf[ETHER_ADDR_STR_LEN];
6014         int err;
6015         char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
6016                 sizeof(struct ether_addr) + sizeof(uint)] = {0};
6017         struct maclist *assoc_maclist = (struct maclist *)mac_buf;
6018         int num_associated = 0;
6019
6020         WL_DBG(("Entry\n"));
6021         if (mac_addr == NULL) {
6022                 WL_DBG(("mac_addr is NULL ignore it\n"));
6023                 return 0;
6024         }
6025
6026         if (!wl)
6027                 return ERR_PTR(-EINVAL);
6028
6029         dev = ndev_to_wlc_ndev(ndev, wl);
6030
6031         if (p2p_is_on(wl)) {
6032                 /* Suspend P2P discovery search-listen to prevent it from changing the
6033                  * channel.
6034                  */
6035                 if ((wl_cfgp2p_discover_enable_search(wl, false)) < 0) {
6036                         WL_ERR(("Can not disable discovery mode\n"));
6037                         return -EFAULT;
6038                 }
6039         }
6040
6041         assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
6042         err = wldev_ioctl(ndev, WLC_GET_ASSOCLIST,
6043                 assoc_maclist, sizeof(mac_buf), false);
6044         if (err < 0)
6045                 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
6046         else
6047                 num_associated = assoc_maclist->count;
6048
6049         memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN);
6050         scb_val.val = DOT11_RC_DEAUTH_LEAVING;
6051         err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
6052                 sizeof(scb_val_t), true);
6053         if (err < 0)
6054                 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err));
6055         WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
6056                 bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf),
6057                 scb_val.val));
6058
6059         if (num_associated > 0 && ETHER_ISBCAST(mac_addr))
6060                 wl_delay(400);
6061
6062         return 0;
6063 }
6064 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
6065
6066 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
6067 static s32
6068 wl_cfg80211_start_ap(
6069         struct wiphy *wiphy,
6070         struct net_device *dev,
6071         struct cfg80211_ap_settings *info)
6072 {
6073         struct wl_priv *wl = wiphy_priv(wiphy);
6074         s32 err = BCME_OK;
6075         struct parsed_ies ies;
6076         s32 bssidx = 0;
6077         u32 dev_role = 0;
6078
6079         WL_DBG(("Enter \n"));
6080
6081         if (!wl)
6082                 return ERR_PTR(-EINVAL);
6083
6084         if (dev == wl_to_prmry_ndev(wl)) {
6085                 WL_DBG(("Start AP req on primary iface: Softap\n"));
6086                 dev_role = NL80211_IFTYPE_AP;
6087         }
6088 #if defined(WL_ENABLE_P2P_IF)
6089         else if (dev == wl->p2p_net) {
6090                 /* Group Add request on p2p0 */
6091                 WL_DBG(("Start AP req on P2P iface: GO\n"));
6092                 dev = wl_to_prmry_ndev(wl);
6093                 dev_role = NL80211_IFTYPE_P2P_GO;
6094         }
6095 #endif /* WL_ENABLE_P2P_IF */
6096         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6097                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6098                 return BCME_ERROR;
6099         }
6100         if (p2p_is_on(wl) &&
6101                 (bssidx == wl_to_p2p_bss_bssidx(wl,
6102                 P2PAPI_BSSCFG_CONNECTION))) {
6103                 dev_role = NL80211_IFTYPE_P2P_GO;
6104                 WL_DBG(("Start AP req on P2P connection iface\n"));
6105         }
6106
6107         if (!check_dev_role_integrity(wl, dev_role))
6108                 goto fail;
6109
6110 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) && !0)
6111         if ((err = wl_cfg80211_set_channel(wiphy, dev,
6112                 dev->ieee80211_ptr->preset_chandef.chan,
6113                 NL80211_CHAN_HT20) < 0)) {
6114                 WL_ERR(("Set channel failed \n"));
6115                 goto fail;
6116         }
6117 #endif 
6118
6119         if ((err = wl_cfg80211_bcn_set_params(info, dev,
6120                 dev_role, bssidx)) < 0) {
6121                 WL_ERR(("Beacon params set failed \n"));
6122                 goto fail;
6123         }
6124
6125         /* Parse IEs */
6126         if ((err = wl_cfg80211_parse_ap_ies(dev, &info->beacon, &ies)) < 0) {
6127                 WL_ERR(("Set IEs failed \n"));
6128                 goto fail;
6129         }
6130
6131         if ((wl_cfg80211_bcn_validate_sec(dev, &ies,
6132                 dev_role, bssidx)) < 0)
6133         {
6134                 WL_ERR(("Beacon set security failed \n"));
6135                 goto fail;
6136         }
6137
6138         if ((err = wl_cfg80211_bcn_bringup_ap(dev, &ies,
6139                 dev_role, bssidx)) < 0) {
6140                 WL_ERR(("Beacon bring up AP/GO failed \n"));
6141                 goto fail;
6142         }
6143
6144         WL_DBG(("** AP/GO Created **\n"));
6145
6146         /* Set IEs to FW */
6147         if ((err = wl_cfg80211_set_ies(dev, &info->beacon, bssidx)) < 0)
6148                 WL_ERR(("Set IEs failed \n"));
6149
6150 fail:
6151         if (err) {
6152                 WL_ERR(("ADD/SET beacon failed\n"));
6153                 wldev_iovar_setint(dev, "mpc", 1);
6154         }
6155
6156         return err;
6157 }
6158
6159 static s32
6160 wl_cfg80211_stop_ap(
6161         struct wiphy *wiphy,
6162         struct net_device *dev)
6163 {
6164         int err = 0;
6165         u32 dev_role = 0;
6166         int infra = 0;
6167         int ap = 0;
6168         s32 bssidx = 0;
6169         struct wl_priv *wl = wiphy_priv(wiphy);
6170
6171         WL_DBG(("Enter \n"));
6172
6173         if (!wl)
6174                 return ERR_PTR(-EINVAL);
6175
6176         if (dev == wl_to_prmry_ndev(wl)) {
6177                 dev_role = NL80211_IFTYPE_AP;
6178         }
6179 #if defined(WL_ENABLE_P2P_IF)
6180         else if (dev == wl->p2p_net) {
6181                 /* Group Add request on p2p0 */
6182                 dev = wl_to_prmry_ndev(wl);
6183                 dev_role = NL80211_IFTYPE_P2P_GO;
6184         }
6185 #endif /* WL_ENABLE_P2P_IF */
6186         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6187                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6188                 return BCME_ERROR;
6189         }
6190         if (p2p_is_on(wl) &&
6191                 (bssidx == wl_to_p2p_bss_bssidx(wl,
6192                 P2PAPI_BSSCFG_CONNECTION))) {
6193                 dev_role = NL80211_IFTYPE_P2P_GO;
6194         }
6195
6196         if (!check_dev_role_integrity(wl, dev_role))
6197                 goto exit;
6198
6199         if (dev_role == NL80211_IFTYPE_AP) {
6200                 /* SoftAp on primary Interface.
6201                  * Shut down AP and turn on MPC
6202                  */
6203                 if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
6204                         WL_ERR(("setting AP mode failed %d \n", err));
6205                         err = -ENOTSUPP;
6206                         goto exit;
6207                 }
6208                 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
6209                 if (err < 0) {
6210                         WL_ERR(("SET INFRA error %d\n", err));
6211                         err = -ENOTSUPP;
6212                         goto exit;
6213                 }
6214
6215                 err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
6216                 if (unlikely(err)) {
6217                         WL_ERR(("WLC_UP error (%d)\n", err));
6218                         err = -EINVAL;
6219                         goto exit;
6220                 }
6221
6222                 wl_clr_drv_status(wl, AP_CREATED, dev);
6223                 /* Turn on the MPC */
6224                 wldev_iovar_setint(dev, "mpc", 1);
6225                 if (wl->ap_info) {
6226                         kfree(wl->ap_info->wpa_ie);
6227                         kfree(wl->ap_info->rsn_ie);
6228                         kfree(wl->ap_info->wps_ie);
6229                         kfree(wl->ap_info);
6230                         wl->ap_info = NULL;
6231                 }
6232         } else {
6233                 WL_DBG(("Stopping P2P GO \n"));
6234         }
6235
6236 exit:
6237         return err;
6238 }
6239
6240 static s32
6241 wl_cfg80211_change_beacon(
6242         struct wiphy *wiphy,
6243         struct net_device *dev,
6244         struct cfg80211_beacon_data *info)
6245 {
6246         s32 err = BCME_OK;
6247         struct wl_priv *wl = wiphy_priv(wiphy);
6248         struct parsed_ies ies;
6249         u32 dev_role = 0;
6250         s32 bssidx = 0;
6251
6252         WL_DBG(("Enter \n"));
6253
6254         if (!wl)
6255                 return ERR_PTR(-EINVAL);
6256         if (dev == wl_to_prmry_ndev(wl)) {
6257                 dev_role = NL80211_IFTYPE_AP;
6258         }
6259 #if defined(WL_ENABLE_P2P_IF)
6260         else if (dev == wl->p2p_net) {
6261                 /* Group Add request on p2p0 */
6262                 dev = wl_to_prmry_ndev(wl);
6263                 dev_role = NL80211_IFTYPE_P2P_GO;
6264         }
6265 #endif /* WL_ENABLE_P2P_IF */
6266         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6267                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6268                 return BCME_ERROR;
6269         }
6270         if (p2p_is_on(wl) &&
6271                 (bssidx == wl_to_p2p_bss_bssidx(wl,
6272                 P2PAPI_BSSCFG_CONNECTION))) {
6273                 dev_role = NL80211_IFTYPE_P2P_GO;
6274         }
6275
6276         if (dev_role == 0) {
6277                 WL_ERR(("Unknown device role!\n"));
6278                 err = BCME_ERROR;
6279                 goto fail;
6280         }
6281
6282         if (!check_dev_role_integrity(wl, dev_role))
6283                 goto fail;
6284
6285         if ((dev_role == NL80211_IFTYPE_P2P_GO) && (wl->p2p_wdev == NULL)) {
6286                 WL_ERR(("P2P already down status!\n"));
6287                 err = BCME_ERROR;
6288                 goto fail;
6289         }
6290
6291         /* Parse IEs */
6292         if ((err = wl_cfg80211_parse_ap_ies(dev, info, &ies)) < 0) {
6293                 WL_ERR(("Parse IEs failed \n"));
6294                 goto fail;
6295         }
6296
6297         /* Set IEs to FW */
6298         if ((err = wl_cfg80211_set_ies(dev, info, bssidx)) < 0) {
6299                 WL_ERR(("Set IEs failed \n"));
6300                 goto fail;
6301         }
6302
6303         if (dev_role == NL80211_IFTYPE_AP) {
6304                 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
6305                         WL_ERR(("Hostapd update sec failed \n"));
6306                         err = -EINVAL;
6307                         goto fail;
6308                 }
6309         }
6310
6311 fail:
6312         return err;
6313 }
6314 #else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) */
6315 static s32
6316 wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
6317         struct beacon_parameters *info)
6318 {
6319         s32 err = BCME_OK;
6320         struct wl_priv *wl = wiphy_priv(wiphy);
6321         s32 ie_offset = 0;
6322         s32 bssidx = 0;
6323         u32 dev_role = NL80211_IFTYPE_AP;
6324         struct parsed_ies ies;
6325         bcm_tlv_t *ssid_ie;
6326         bool pbc = 0;
6327         WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
6328                 info->interval, info->dtim_period, info->head_len, info->tail_len));
6329
6330         if (!wl)
6331                 return ERR_PTR(-EINVAL);
6332
6333         if (dev == wl_to_prmry_ndev(wl)) {
6334                 dev_role = NL80211_IFTYPE_AP;
6335         }
6336 #if defined(WL_ENABLE_P2P_IF)
6337         else if (dev == wl->p2p_net) {
6338                 /* Group Add request on p2p0 */
6339                 dev = wl_to_prmry_ndev(wl);
6340                 dev_role = NL80211_IFTYPE_P2P_GO;
6341         }
6342 #endif /* WL_ENABLE_P2P_IF */
6343         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6344                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6345                 return BCME_ERROR;
6346         }
6347         if (p2p_is_on(wl) &&
6348                 (bssidx == wl_to_p2p_bss_bssidx(wl,
6349                 P2PAPI_BSSCFG_CONNECTION))) {
6350                 dev_role = NL80211_IFTYPE_P2P_GO;
6351         }
6352
6353         if (dev_role == 0) {
6354                 WL_ERR(("Unknown device role!\n"));
6355                 err = BCME_ERROR;
6356                 goto fail;
6357         }
6358
6359         if (!check_dev_role_integrity(wl, dev_role))
6360                 goto fail;
6361
6362         if ((dev_role == NL80211_IFTYPE_P2P_GO) && (wl->p2p_wdev == NULL)) {
6363                 WL_ERR(("P2P already down status!\n"));
6364                 err = BCME_ERROR;
6365                 goto fail;
6366         }
6367
6368         ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
6369         /* find the SSID */
6370         if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
6371                 info->head_len - ie_offset,
6372                 DOT11_MNG_SSID_ID)) != NULL) {
6373                 if (dev_role == NL80211_IFTYPE_AP) {
6374                         /* Store the hostapd SSID */
6375                         memset(&wl->hostapd_ssid.SSID[0], 0x00, 32);
6376                         memcpy(&wl->hostapd_ssid.SSID[0], ssid_ie->data, ssid_ie->len);
6377                         wl->hostapd_ssid.SSID_len = ssid_ie->len;
6378                 } else {
6379                                 /* P2P GO */
6380                         memset(&wl->p2p->ssid.SSID[0], 0x00, 32);
6381                         memcpy(wl->p2p->ssid.SSID, ssid_ie->data, ssid_ie->len);
6382                         wl->p2p->ssid.SSID_len = ssid_ie->len;
6383                 }
6384         }
6385
6386         if (wl_cfg80211_parse_ies((u8 *)info->tail,
6387                 info->tail_len, &ies) < 0) {
6388                 WL_ERR(("Beacon get IEs failed \n"));
6389                 err = -EINVAL;
6390                 goto fail;
6391         }
6392
6393         if (wl_cfgp2p_set_management_ie(wl, dev, bssidx,
6394                 VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
6395                 info->tail_len) < 0) {
6396                 WL_ERR(("Beacon set IEs failed \n"));
6397                 goto fail;
6398         } else {
6399                 WL_DBG(("Applied Vndr IEs for Beacon \n"));
6400         }
6401         if (!wl_cfgp2p_bss_isup(dev, bssidx) &&
6402                 (wl_cfg80211_bcn_validate_sec(dev, &ies, dev_role, bssidx) < 0))
6403         {
6404                 WL_ERR(("Beacon set security failed \n"));
6405                 goto fail;
6406         }
6407
6408         /* Set BI and DTIM period */
6409         if (info->interval) {
6410                 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
6411                         &info->interval, sizeof(s32), true)) < 0) {
6412                         WL_ERR(("Beacon Interval Set Error, %d\n", err));
6413                         return err;
6414                 }
6415         }
6416         if (info->dtim_period) {
6417                 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
6418                         &info->dtim_period, sizeof(s32), true)) < 0) {
6419                         WL_ERR(("DTIM Interval Set Error, %d\n", err));
6420                         return err;
6421                 }
6422         }
6423
6424         if (wl_cfg80211_bcn_bringup_ap(dev, &ies, dev_role, bssidx) < 0) {
6425                 WL_ERR(("Beacon bring up AP/GO failed \n"));
6426                 goto fail;
6427         }
6428
6429         if (wl_get_drv_status(wl, AP_CREATED, dev)) {
6430                 /* Soft AP already running. Update changed params */
6431                 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
6432                         WL_ERR(("Hostapd update sec failed \n"));
6433                         err = -EINVAL;
6434                         goto fail;
6435                 }
6436         }
6437
6438         /* Enable Probe Req filter */
6439         if (((dev_role == NL80211_IFTYPE_P2P_GO) ||
6440                 (dev_role == NL80211_IFTYPE_AP)) && (ies.wps_ie != NULL)) {
6441                 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
6442                 if (pbc)
6443                         wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
6444         }
6445
6446         WL_DBG(("** ADD/SET beacon done **\n"));
6447
6448 fail:
6449         if (err) {
6450                 WL_ERR(("ADD/SET beacon failed\n"));
6451                 wldev_iovar_setint(dev, "mpc", 1);
6452         }
6453         return err;
6454
6455 }
6456 #endif 
6457
6458 #ifdef WL_SCHED_SCAN
6459 #define PNO_TIME                30
6460 #define PNO_REPEAT              4
6461 #define PNO_FREQ_EXPO_MAX       2
6462 int wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
6463                              struct net_device *dev,
6464                              struct cfg80211_sched_scan_request *request)
6465 {
6466         ushort pno_time = PNO_TIME;
6467         int pno_repeat = PNO_REPEAT;
6468         int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
6469         wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
6470         struct wl_priv *wl = wiphy_priv(wiphy);
6471         struct cfg80211_ssid *ssid = NULL;
6472         int ssid_count = 0;
6473         int i;
6474         int ret = 0;
6475
6476         WL_DBG(("Enter \n"));
6477
6478         if (!wl)
6479                 return ERR_PTR(-EINVAL);
6480
6481         WL_PNO((">>> SCHED SCAN START\n"));
6482         WL_PNO(("Enter n_match_sets:%d   n_ssids:%d \n",
6483                 request->n_match_sets, request->n_ssids));
6484         WL_PNO(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
6485                 request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max));
6486
6487
6488         if (!request || !request->n_ssids || !request->n_match_sets) {
6489                 WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids));
6490                 return -EINVAL;
6491         }
6492
6493         memset(&ssids_local, 0, sizeof(ssids_local));
6494
6495         if (request->n_match_sets > 0) {
6496                 for (i = 0; i < request->n_match_sets; i++) {
6497                         ssid = &request->match_sets[i].ssid;
6498                         memcpy(ssids_local[i].SSID, ssid->ssid, ssid->ssid_len);
6499                         ssids_local[i].SSID_len = ssid->ssid_len;
6500                         WL_PNO((">>> PNO filter set for ssid (%s) \n", ssid->ssid));
6501                         ssid_count++;
6502                 }
6503         }
6504
6505         if (request->n_ssids > 0) {
6506                 for (i = 0; i < request->n_ssids; i++) {
6507                         /* Active scan req for ssids */
6508                         WL_PNO((">>> Active scan req for ssid (%s) \n", request->ssids[i].ssid));
6509
6510                         /* match_set ssids is a supert set of n_ssid list, so we need
6511                          * not add these set seperately
6512                          */
6513                 }
6514         }
6515
6516         if (ssid_count) {
6517                 if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, request->n_match_sets,
6518                         pno_time, pno_repeat, pno_freq_expo_max, NULL, 0)) < 0) {
6519                         WL_ERR(("PNO setup failed!! ret=%d \n", ret));
6520                         return -EINVAL;
6521                 }
6522                 wl->sched_scan_req = request;
6523         } else {
6524                 return -EINVAL;
6525         }
6526
6527         return 0;
6528 }
6529
6530 int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
6531 {
6532         struct wl_priv *wl = wiphy_priv(wiphy);
6533
6534         WL_DBG(("Enter \n"));
6535
6536         if (!wl)
6537                 return ERR_PTR(-EINVAL);
6538
6539         WL_PNO((">>> SCHED SCAN STOP\n"));
6540
6541         if (dhd_dev_pno_stop_for_ssid(dev) < 0)
6542                 WL_ERR(("PNO Stop for SSID failed"));
6543
6544         if (wl->scan_request && wl->sched_scan_running) {
6545                 WL_PNO((">>> Sched scan running. Aborting it..\n"));
6546                 wl_notify_escan_complete(wl, dev, true, true);
6547         }
6548
6549          wl->sched_scan_req = NULL;
6550          wl->sched_scan_running = FALSE;
6551
6552         return 0;
6553 }
6554 #endif /* WL_SCHED_SCAN */
6555
6556 static struct cfg80211_ops wl_cfg80211_ops = {
6557         .add_virtual_intf = wl_cfg80211_add_virtual_iface,
6558         .del_virtual_intf = wl_cfg80211_del_virtual_iface,
6559         .change_virtual_intf = wl_cfg80211_change_virtual_iface,
6560 #if defined(WL_CFG80211_P2P_DEV_IF)
6561         .start_p2p_device = wl_cfgp2p_start_p2p_device,
6562         .stop_p2p_device = wl_cfgp2p_stop_p2p_device,
6563 #endif /* WL_CFG80211_P2P_DEV_IF */
6564         .scan = wl_cfg80211_scan,
6565         .set_wiphy_params = wl_cfg80211_set_wiphy_params,
6566         .join_ibss = wl_cfg80211_join_ibss,
6567         .leave_ibss = wl_cfg80211_leave_ibss,
6568         .get_station = wl_cfg80211_get_station,
6569         .set_tx_power = wl_cfg80211_set_tx_power,
6570         .get_tx_power = wl_cfg80211_get_tx_power,
6571         .add_key = wl_cfg80211_add_key,
6572         .del_key = wl_cfg80211_del_key,
6573         .get_key = wl_cfg80211_get_key,
6574         .set_default_key = wl_cfg80211_config_default_key,
6575         .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
6576         .set_power_mgmt = wl_cfg80211_set_power_mgmt,
6577         .connect = wl_cfg80211_connect,
6578         .disconnect = wl_cfg80211_disconnect,
6579         .suspend = wl_cfg80211_suspend,
6580         .resume = wl_cfg80211_resume,
6581         .set_pmksa = wl_cfg80211_set_pmksa,
6582         .del_pmksa = wl_cfg80211_del_pmksa,
6583         .flush_pmksa = wl_cfg80211_flush_pmksa,
6584         .remain_on_channel = wl_cfg80211_remain_on_channel,
6585         .cancel_remain_on_channel = wl_cfg80211_cancel_remain_on_channel,
6586         .mgmt_tx = wl_cfg80211_mgmt_tx,
6587         .mgmt_frame_register = wl_cfg80211_mgmt_frame_register,
6588         .change_bss = wl_cfg80211_change_bss,
6589 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) || 0
6590         .set_channel = wl_cfg80211_set_channel,
6591 #endif 
6592 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !0
6593         .set_beacon = wl_cfg80211_add_set_beacon,
6594         .add_beacon = wl_cfg80211_add_set_beacon,
6595 #else
6596         .change_beacon = wl_cfg80211_change_beacon,
6597         .start_ap = wl_cfg80211_start_ap,
6598         .stop_ap = wl_cfg80211_stop_ap,
6599 #endif 
6600 #ifdef WL_SCHED_SCAN
6601         .sched_scan_start = wl_cfg80211_sched_scan_start,
6602         .sched_scan_stop = wl_cfg80211_sched_scan_stop,
6603 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */
6604 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
6605         2, 0))
6606         .del_station = wl_cfg80211_del_station,
6607         .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait,
6608 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */
6609 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || 0
6610         .tdls_oper = wl_cfg80211_tdls_oper
6611 #endif 
6612 };
6613
6614 s32 wl_mode_to_nl80211_iftype(s32 mode)
6615 {
6616         s32 err = 0;
6617
6618         switch (mode) {
6619         case WL_MODE_BSS:
6620                 return NL80211_IFTYPE_STATION;
6621         case WL_MODE_IBSS:
6622                 return NL80211_IFTYPE_ADHOC;
6623         case WL_MODE_AP:
6624                 return NL80211_IFTYPE_AP;
6625         default:
6626                 return NL80211_IFTYPE_UNSPECIFIED;
6627         }
6628
6629         return err;
6630 }
6631
6632 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
6633 /*      Kernel Network Support->Wireless->Regulatory rules database
6634         options should be enabled and regulatory  CRDA regdb table populated in Kernel
6635         for proper country reg notification
6636 */
6637 static int
6638 wl_cfg80211_reg_notifier(
6639         struct wiphy *wiphy,
6640         struct regulatory_request *request)
6641 {
6642         struct wl_priv *wl = (struct wl_priv *)wiphy_priv(wiphy);
6643         int ret = 0;
6644
6645         if (!request || !wl) {
6646                 WL_ERR(("Invalid arg\n"));
6647                 return -EINVAL;
6648         }
6649
6650         WL_DBG(("ccode: %c%c Initiator: %d\n",
6651                 request->alpha2[0], request->alpha2[1], request->initiator));
6652
6653         /* We support only REGDOM_SET_BY_USER as of now */
6654         if ((request->initiator != NL80211_REGDOM_SET_BY_USER) &&
6655                 (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
6656                 WL_ERR(("reg_notifier for intiator:%d not supported : set default\n",
6657                         request->initiator));
6658                 /* in case of no supported country by regdb
6659                      lets driver setup platform default Locale
6660                 */
6661         }
6662
6663         WL_ERR(("Set country code %c%c from %s\n",
6664                 request->alpha2[0], request->alpha2[1],
6665                 ((request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) ? " 11d AP" : "User")));
6666
6667         if ((ret = wldev_set_country(wl_to_prmry_ndev(wl), request->alpha2,
6668                 false, (request->initiator == NL80211_REGDOM_SET_BY_USER ? true : false))) < 0) {
6669                 WL_ERR(("set country Failed :%d\n", ret));
6670         }
6671
6672         return ret;
6673 }
6674 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
6675
6676 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, void *data)
6677 {
6678         s32 err = 0;
6679 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
6680         (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
6681         dhd_pub_t *dhd = (dhd_pub_t *)data;
6682 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
6683
6684         wdev->wiphy =
6685             wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_priv));
6686         if (unlikely(!wdev->wiphy)) {
6687                 WL_ERR(("Couldn not allocate wiphy device\n"));
6688                 err = -ENOMEM;
6689                 return err;
6690         }
6691         set_wiphy_dev(wdev->wiphy, sdiofunc_dev);
6692         wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX;
6693         /* Report  how many SSIDs Driver can support per Scan request */
6694         wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX;
6695         wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
6696 #ifdef WL_SCHED_SCAN
6697         wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT;
6698         wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT;
6699         wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX;
6700         wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
6701 #endif /* WL_SCHED_SCAN */
6702         wdev->wiphy->interface_modes =
6703                 BIT(NL80211_IFTYPE_STATION)
6704                 | BIT(NL80211_IFTYPE_ADHOC)
6705 #if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
6706                 /*
6707                 * This monitor mode support creates an issue in registering
6708                 * Action frame for P2P-GO, this was leading an error in receiving
6709                 * action frames to GO interface.Keeping the code here because
6710                 * monitor mode code has kept as it is in other modules,
6711                 * though we are not supporting this mode.
6712                 */
6713                 | BIT(NL80211_IFTYPE_MONITOR)
6714 #endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
6715 #if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)
6716                 | BIT(NL80211_IFTYPE_P2P_CLIENT)
6717                 | BIT(NL80211_IFTYPE_P2P_GO)
6718 #endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */
6719 #if defined(WL_CFG80211_P2P_DEV_IF)
6720                 | BIT(NL80211_IFTYPE_P2P_DEVICE)
6721 #endif /* WL_CFG80211_P2P_DEV_IF */
6722                 | BIT(NL80211_IFTYPE_AP);
6723
6724 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
6725         (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
6726         if (dhd && dhd->op_mode == DHD_FLAG_HOSTAP_MODE) {
6727                 WL_DBG(("Setting interface combinations for SoftAP mode\n"));
6728                 wdev->wiphy->iface_combinations = softap_iface_combinations;
6729                 wdev->wiphy->n_iface_combinations =
6730                         ARRAY_SIZE(softap_iface_combinations);
6731         } else {
6732                 WL_DBG(("Setting interface combinations for STA+P2P mode\n"));
6733                 wdev->wiphy->iface_combinations = sta_p2p_iface_combinations;
6734                 wdev->wiphy->n_iface_combinations =
6735                         ARRAY_SIZE(sta_p2p_iface_combinations);
6736         }
6737 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
6738
6739         wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
6740
6741         wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
6742         wdev->wiphy->cipher_suites = __wl_cipher_suites;
6743         wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
6744         wdev->wiphy->max_remain_on_channel_duration = 5000;
6745         wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes;
6746 #ifndef WL_POWERSAVE_DISABLED
6747         wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
6748 #else
6749         wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
6750 #endif                          /* !WL_POWERSAVE_DISABLED */
6751         wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK |
6752                 WIPHY_FLAG_4ADDR_AP |
6753 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && !0
6754                 WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS |
6755 #endif
6756                 WIPHY_FLAG_4ADDR_STATION;
6757         /*  If driver advertises FW_ROAM, the supplicant wouldn't
6758          * send the BSSID & Freq in the connect command allowing the
6759          * the driver to choose the AP to connect to. But unless we
6760          * support ROAM_CACHE in firware this will delay the ASSOC as
6761          * as the FW need to do a full scan before attempting to connect
6762          * So that feature will just increase assoc. The better approach
6763          * to let Supplicant to provide channel info and FW letter may roam
6764          * if needed so DON'T advertise that featur eto Supplicant.
6765          */
6766 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
6767 /*      wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; */
6768 #endif
6769 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || 0
6770         wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
6771                 WIPHY_FLAG_OFFCHAN_TX;
6772 #endif
6773 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
6774         4, 0))
6775         /* From 3.4 kernel ownards AP_SME flag can be advertised
6776          * to remove the patch from supplicant
6777          */
6778         wdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
6779 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
6780
6781 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
6782         wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier;
6783 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
6784
6785 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || 0
6786         wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
6787 #endif
6788
6789 #if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
6790         /*
6791          * From linux-3.10 kernel, wowlan packet filter is mandated to avoid the
6792          * disconnection of connected network before suspend. So a dummy wowlan
6793          * filter is configured for kernels linux-3.8 and above.
6794          */
6795         wdev->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
6796 #endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
6797
6798         WL_DBG(("Registering custom regulatory)\n"));
6799         wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
6800         wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom);
6801         /* Now we can register wiphy with cfg80211 module */
6802         err = wiphy_register(wdev->wiphy);
6803         if (unlikely(err < 0)) {
6804                 WL_ERR(("Couldn not register wiphy device (%d)\n", err));
6805                 wiphy_free(wdev->wiphy);
6806         }
6807
6808 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \
6809         KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS)
6810         wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS;
6811 #endif /* ((LINUX_VER >= 3.0) && (LINUX_VER <= 3.3)) && WL_IFACE_COMB_NUM_CHANNELS */
6812
6813         return err;
6814 }
6815
6816 static void wl_free_wdev(struct wl_priv *wl)
6817 {
6818         struct wireless_dev *wdev = wl->wdev;
6819         struct wiphy *wiphy;
6820         if (!wdev) {
6821                 WL_ERR(("wdev is invalid\n"));
6822                 return;
6823         }
6824         wiphy = wdev->wiphy;
6825         wiphy_unregister(wdev->wiphy);
6826         wdev->wiphy->dev.parent = NULL;
6827
6828         wl_delete_all_netinfo(wl);
6829         wiphy_free(wiphy);
6830         /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "wl",
6831          * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
6832          */
6833 }
6834
6835 static s32 wl_inform_bss(struct wl_priv *wl)
6836 {
6837         struct wl_scan_results *bss_list;
6838         struct wl_bss_info *bi = NULL;  /* must be initialized */
6839         s32 err = 0;
6840         s32 i;
6841
6842         bss_list = wl->bss_list;
6843         WL_DBG(("scanned AP count (%d)\n", bss_list->count));
6844         bi = next_bss(bss_list, bi);
6845         for_each_bss(bss_list, bi, i) {
6846                 err = wl_inform_single_bss(wl, bi);
6847                 if (unlikely(err))
6848                         break;
6849         }
6850         return err;
6851 }
6852
6853 static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
6854 {
6855         struct wiphy *wiphy = wl_to_wiphy(wl);
6856         struct ieee80211_mgmt *mgmt;
6857         struct ieee80211_channel *channel;
6858         struct ieee80211_supported_band *band;
6859         struct wl_cfg80211_bss_info *notif_bss_info;
6860         struct wl_scan_req *sr = wl_to_sr(wl);
6861         struct beacon_proberesp *beacon_proberesp;
6862         struct cfg80211_bss *cbss = NULL;
6863         s32 mgmt_type;
6864         s32 signal;
6865         u32 freq;
6866         s32 err = 0;
6867         gfp_t aflags;
6868
6869         if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
6870                 WL_DBG(("Beacon is larger than buffer. Discarding\n"));
6871                 return err;
6872         }
6873         aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
6874         notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt)
6875                 - sizeof(u8) + WL_BSS_INFO_MAX, aflags);
6876         if (unlikely(!notif_bss_info)) {
6877                 WL_ERR(("notif_bss_info alloc failed\n"));
6878                 return -ENOMEM;
6879         }
6880         mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
6881         notif_bss_info->channel =
6882                 bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
6883
6884         if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
6885                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
6886         else
6887                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
6888         if (!band) {
6889                 WL_ERR(("No valid band"));
6890                 kfree(notif_bss_info);
6891                 return -EINVAL;
6892         }
6893         notif_bss_info->rssi = wl_rssi_offset(dtoh16(bi->RSSI));
6894         memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
6895         mgmt_type = wl->active_scan ?
6896                 IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
6897         if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
6898             mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
6899         }
6900         beacon_proberesp = wl->active_scan ?
6901                 (struct beacon_proberesp *)&mgmt->u.probe_resp :
6902                 (struct beacon_proberesp *)&mgmt->u.beacon;
6903         beacon_proberesp->timestamp = 0;
6904         beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
6905         beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
6906         wl_rst_ie(wl);
6907         wl_update_hidden_ap_ie(bi, ((u8 *) bi) + bi->ie_offset, &bi->ie_length);
6908         wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
6909         wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX -
6910                 offsetof(struct wl_cfg80211_bss_info, frame_buf));
6911         notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
6912                 u.beacon.variable) + wl_get_ielen(wl);
6913 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
6914         freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
6915         (void)band->band;
6916 #else
6917         freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band);
6918 #endif
6919         if (freq == 0) {
6920                 WL_ERR(("Invalid channel, fail to chcnage channel to freq\n"));
6921                 kfree(notif_bss_info);
6922                 return -EINVAL;
6923         }
6924         channel = ieee80211_get_channel(wiphy, freq);
6925         if (unlikely(!channel)) {
6926                 WL_ERR(("ieee80211_get_channel error\n"));
6927                 kfree(notif_bss_info);
6928                 return -EINVAL;
6929         }
6930         WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM"
6931                         "mgmt_type %d frame_len %d\n", bi->SSID,
6932                         notif_bss_info->rssi, notif_bss_info->channel,
6933                         mgmt->u.beacon.capab_info, &bi->BSSID, mgmt_type,
6934                         notif_bss_info->frame_len));
6935
6936         signal = notif_bss_info->rssi * 100;
6937         if (!mgmt->u.probe_resp.timestamp) {
6938 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
6939                 struct timespec ts;
6940                 get_monotonic_boottime(&ts);
6941                 mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000)
6942                                 + ts.tv_nsec / 1000;
6943 #else
6944                 struct timeval tv;
6945                 do_gettimeofday(&tv);
6946                 mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec*1000000)
6947                                 + tv.tv_usec;
6948 #endif
6949         }
6950
6951
6952         cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
6953                 le16_to_cpu(notif_bss_info->frame_len), signal, aflags);
6954         if (unlikely(!cbss)) {
6955                 WL_ERR(("cfg80211_inform_bss_frame error\n"));
6956                 kfree(notif_bss_info);
6957                 return -EINVAL;
6958         }
6959
6960 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
6961         cfg80211_put_bss(wiphy, cbss);
6962 #else
6963         cfg80211_put_bss(cbss);
6964 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
6965         kfree(notif_bss_info);
6966         return err;
6967 }
6968
6969 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev)
6970 {
6971         u32 event = ntoh32(e->event_type);
6972         u32 status =  ntoh32(e->status);
6973         u16 flags = ntoh16(e->flags);
6974
6975         WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
6976         if (event == WLC_E_SET_SSID) {
6977                 if (status == WLC_E_STATUS_SUCCESS) {
6978                         if (!wl_is_ibssmode(wl, ndev))
6979                                 return true;
6980                 }
6981         } else if (event == WLC_E_LINK) {
6982                 if (flags & WLC_EVENT_MSG_LINK)
6983                         return true;
6984         }
6985
6986         WL_DBG(("wl_is_linkup false\n"));
6987         return false;
6988 }
6989
6990 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
6991 {
6992         u32 event = ntoh32(e->event_type);
6993         u16 flags = ntoh16(e->flags);
6994
6995         if (event == WLC_E_DEAUTH_IND ||
6996         event == WLC_E_DISASSOC_IND ||
6997         event == WLC_E_DISASSOC ||
6998         event == WLC_E_DEAUTH) {
6999 #if (WL_DBG_LEVEL > 0)
7000         WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
7001 #endif /* (WL_DBG_LEVEL > 0) */
7002                 return true;
7003         } else if (event == WLC_E_LINK) {
7004                 if (!(flags & WLC_EVENT_MSG_LINK)) {
7005 #if (WL_DBG_LEVEL > 0)
7006         WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
7007 #endif /* (WL_DBG_LEVEL > 0) */
7008                         return true;
7009                 }
7010         }
7011
7012         return false;
7013 }
7014
7015 static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e)
7016 {
7017         u32 event = ntoh32(e->event_type);
7018         u32 status = ntoh32(e->status);
7019
7020         if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS)
7021                 return true;
7022         if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS)
7023                 return true;
7024
7025         return false;
7026 }
7027
7028 /* The mainline kernel >= 3.2.0 has support for indicating new/del station
7029  * to AP/P2P GO via events. If this change is backported to kernel for which
7030  * this driver is being built, then define WL_CFG80211_STA_EVENT. You
7031  * should use this new/del sta event mechanism for BRCM supplicant >= 22.
7032  */
7033 static s32
7034 wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev,
7035         const wl_event_msg_t *e, void *data)
7036 {
7037         s32 err = 0;
7038         u32 event = ntoh32(e->event_type);
7039         u32 reason = ntoh32(e->reason);
7040         u32 len = ntoh32(e->datalen);
7041
7042 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) \
7043         && !0
7044         bool isfree = false;
7045         u8 *mgmt_frame;
7046         u8 bsscfgidx = e->bsscfgidx;
7047         s32 freq;
7048         s32 channel;
7049         u8 *body = NULL;
7050         u16 fc = 0;
7051
7052         struct ieee80211_supported_band *band;
7053         struct ether_addr da;
7054         struct ether_addr bssid;
7055         struct wiphy *wiphy = wl_to_wiphy(wl);
7056         channel_info_t ci;
7057 #else
7058         struct station_info sinfo;
7059 #endif 
7060
7061         WL_DBG(("event %d status %d reason %d\n", event, ntoh32(e->status), reason));
7062         /* if link down, bsscfg is disabled. */
7063         if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
7064                 wl_get_p2p_status(wl, IF_DELETING) && (ndev != wl_to_prmry_ndev(wl))) {
7065                 wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
7066                 WL_INFO(("AP mode link down !! \n"));
7067                 complete(&wl->iface_disable);
7068                 return 0;
7069         }
7070
7071 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) \
7072         && !0
7073         WL_DBG(("Enter \n"));
7074         if (!len && (event == WLC_E_DEAUTH)) {
7075                 len = 2; /* reason code field */
7076                 data = &reason;
7077         }
7078         if (len) {
7079                 body = kzalloc(len, GFP_KERNEL);
7080
7081                 if (body == NULL) {
7082                         WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
7083                         return WL_INVALID;
7084                 }
7085         }
7086         memset(&bssid, 0, ETHER_ADDR_LEN);
7087         WL_DBG(("Enter event %d ndev %p\n", event, ndev));
7088         if (wl_get_mode_by_netdev(wl, ndev) == WL_INVALID) {
7089                 kfree(body);
7090                 return WL_INVALID;
7091         }
7092         if (len)
7093                 memcpy(body, data, len);
7094
7095         wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
7096                 NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync);
7097         memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN);
7098         err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
7099         switch (event) {
7100                 case WLC_E_ASSOC_IND:
7101                         fc = FC_ASSOC_REQ;
7102                         break;
7103                 case WLC_E_REASSOC_IND:
7104                         fc = FC_REASSOC_REQ;
7105                         break;
7106                 case WLC_E_DISASSOC_IND:
7107                         fc = FC_DISASSOC;
7108                         WL_ERR(("event %s(%d) status %d reason %d\n",
7109                                 bcmevent_names[event].name, event, ntoh32(e->status), reason));
7110                         break;
7111                 case WLC_E_DEAUTH_IND:
7112                         fc = FC_DISASSOC;
7113                         WL_ERR(("event %s(%d) status %d reason %d\n",
7114                                 bcmevent_names[event].name, event, ntoh32(e->status), reason));
7115                         break;
7116                 case WLC_E_DEAUTH:
7117                         fc = FC_DISASSOC;
7118                         WL_ERR(("event %s(%d) status %d reason %d\n",
7119                                 bcmevent_names[event].name, event, ntoh32(e->status), reason));
7120                         break;
7121                 default:
7122                         fc = 0;
7123                         goto exit;
7124         }
7125         if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) {
7126                 kfree(body);
7127                 return err;
7128         }
7129
7130         channel = dtoh32(ci.hw_channel);
7131         if (channel <= CH_MAX_2G_CHANNEL)
7132                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
7133         else
7134                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
7135         if (!band) {
7136                 WL_ERR(("No valid band"));
7137                 if (body)
7138                         kfree(body);
7139                 return -EINVAL;
7140         }
7141 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
7142         freq = ieee80211_channel_to_frequency(channel);
7143         (void)band->band;
7144 #else
7145         freq = ieee80211_channel_to_frequency(channel, band->band);
7146 #endif
7147
7148         err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
7149                 &mgmt_frame, &len, body);
7150         if (err < 0)
7151                 goto exit;
7152         isfree = true;
7153
7154         if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) {
7155 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
7156                 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
7157 #else
7158                 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
7159 #endif 
7160         } else if (event == WLC_E_DISASSOC_IND) {
7161 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
7162                 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
7163 #else
7164                 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
7165 #endif 
7166         } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
7167 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
7168                 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
7169 #else
7170                 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
7171 #endif 
7172         }
7173
7174 exit:
7175         if (isfree)
7176                 kfree(mgmt_frame);
7177         if (body)
7178                 kfree(body);
7179 #else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
7180         sinfo.filled = 0;
7181         if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
7182                 reason == DOT11_SC_SUCCESS) {
7183                 sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
7184                 if (!data) {
7185                         WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
7186                         return -EINVAL;
7187                 }
7188                 sinfo.assoc_req_ies = data;
7189                 sinfo.assoc_req_ies_len = len;
7190                 cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
7191         } else if (event == WLC_E_DISASSOC_IND) {
7192                 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
7193         } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
7194                 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
7195         }
7196 #endif 
7197         return err;
7198 }
7199
7200 static s32
7201 wl_get_auth_assoc_status(struct wl_priv *wl, struct net_device *ndev,
7202         const wl_event_msg_t *e)
7203 {
7204         u32 reason = ntoh32(e->reason);
7205         u32 event = ntoh32(e->event_type);
7206         struct wl_security *sec = wl_read_prof(wl, ndev, WL_PROF_SEC);
7207         WL_DBG(("event type : %d, reason : %d\n", event, reason));
7208         if (sec) {
7209                 switch (event) {
7210                 case WLC_E_ASSOC:
7211                 case WLC_E_AUTH:
7212                                 sec->auth_assoc_res_status = reason;
7213                 default:
7214                         break;
7215                 }
7216         } else
7217                 WL_ERR(("sec is NULL\n"));
7218         return 0;
7219 }
7220
7221 static s32
7222 wl_notify_connect_status_ibss(struct wl_priv *wl, struct net_device *ndev,
7223         const wl_event_msg_t *e, void *data)
7224 {
7225         s32 err = 0;
7226         u32 event = ntoh32(e->event_type);
7227         u16 flags = ntoh16(e->flags);
7228         u32 status =  ntoh32(e->status);
7229         bool active;
7230
7231         if (event == WLC_E_JOIN) {
7232                 WL_DBG(("joined in IBSS network\n"));
7233         }
7234         if (event == WLC_E_START) {
7235                 WL_DBG(("started IBSS network\n"));
7236         }
7237         if (event == WLC_E_JOIN || event == WLC_E_START ||
7238                 (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
7239                 if (wl_get_drv_status(wl, CONNECTED, ndev)) {
7240                         /* ROAM or Redundant */
7241                         u8 *cur_bssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7242                         if (memcmp(cur_bssid, &e->addr, ETHER_ADDR_LEN) == 0) {
7243                                 WL_DBG(("IBSS connected event from same BSSID("
7244                                         MACDBG "), ignore it\n", MAC2STRDBG(cur_bssid)));
7245                                 return err;
7246                         }
7247                         WL_INFO(("IBSS BSSID is changed from " MACDBG " to " MACDBG "\n",
7248                                 MAC2STRDBG(cur_bssid), MAC2STRDBG((u8 *)&e->addr)));
7249                         wl_get_assoc_ies(wl, ndev);
7250                         wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7251                         wl_update_bss_info(wl, ndev);
7252                         cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL);
7253                 }
7254                 else {
7255                         /* New connection */
7256                         WL_INFO(("IBSS connected to " MACDBG "\n", MAC2STRDBG((u8 *)&e->addr)));
7257                         wl_link_up(wl);
7258                         wl_get_assoc_ies(wl, ndev);
7259                         wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7260                         wl_update_bss_info(wl, ndev);
7261                         cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL);
7262                         wl_set_drv_status(wl, CONNECTED, ndev);
7263                         active = true;
7264                         wl_update_prof(wl, ndev, NULL, (void *)&active, WL_PROF_ACT);
7265                 }
7266         } else if ((event == WLC_E_LINK && !(flags & WLC_EVENT_MSG_LINK)) ||
7267                 event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
7268                 wl_clr_drv_status(wl, CONNECTED, ndev);
7269                 wl_link_down(wl);
7270                 wl_init_prof(wl, ndev);
7271         }
7272         else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
7273                 WL_DBG(("no action - join fail (IBSS mode)\n"));
7274         }
7275         else {
7276                 WL_DBG(("no action (IBSS mode)\n"));
7277         }
7278         return err;
7279 }
7280
7281 static s32
7282 wl_notify_connect_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7283         const wl_event_msg_t *e, void *data)
7284 {
7285         bool act;
7286         struct net_device *ndev = NULL;
7287         s32 err = 0;
7288         u32 event = ntoh32(e->event_type);
7289
7290         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7291
7292         if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) {
7293                 err = wl_notify_connect_status_ap(wl, ndev, e, data);
7294         } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS) {
7295                 err = wl_notify_connect_status_ibss(wl, ndev, e, data);
7296         } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_BSS) {
7297                 WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
7298                         ntoh32(e->event_type), ntoh32(e->status), ndev));
7299                 if (event == WLC_E_ASSOC || event == WLC_E_AUTH) {
7300                         wl_get_auth_assoc_status(wl, ndev, e);
7301                         return 0;
7302                 }
7303                 if (wl_is_linkup(wl, e, ndev)) {
7304                         wl_link_up(wl);
7305                         act = true;
7306                         if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) {
7307                                         printk("wl_bss_connect_done succeeded with " MACDBG "\n",
7308                                                 MAC2STRDBG((u8*)(&e->addr)));
7309                                         wl_bss_connect_done(wl, ndev, e, data, true);
7310                                         WL_DBG(("joined in BSS network \"%s\"\n",
7311                                         ((struct wlc_ssid *)
7312                                          wl_read_prof(wl, ndev, WL_PROF_SSID))->SSID));
7313                         }
7314                         wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT);
7315                         wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7316
7317                 } else if (wl_is_linkdown(wl, e)) {
7318                         if (wl->scan_request) {
7319                                 if (wl->escan_on) {
7320                                         wl_notify_escan_complete(wl, ndev, true, true);
7321                                 } else {
7322                                         del_timer_sync(&wl->scan_timeout);
7323                                         wl_iscan_aborted(wl);
7324                                 }
7325                         }
7326                         if (wl_get_drv_status(wl, CONNECTED, ndev)) {
7327                                 scb_val_t scbval;
7328                                 u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7329                                 s32 reason = 0;
7330                                 if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND)
7331                                         reason = ntoh32(e->reason);
7332                                 /* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */
7333                                 reason = (reason == WLAN_REASON_UNSPECIFIED)? 0 : reason;
7334
7335                                 printk("link down if %s may call cfg80211_disconnected. "
7336                                         "event : %d, reason=%d from " MACDBG "\n",
7337                                         ndev->name, event, ntoh32(e->reason),
7338                                         MAC2STRDBG((u8*)(&e->addr)));
7339                                 if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) {
7340                                         WL_ERR(("BSSID of event is not the connected BSSID"
7341                                                 "(ignore it) cur: " MACDBG " event: " MACDBG"\n",
7342                                                 MAC2STRDBG(curbssid), MAC2STRDBG((u8*)(&e->addr))));
7343                                         return 0;
7344                                 }
7345                                 wl_clr_drv_status(wl, CONNECTED, ndev);
7346                                 if (! wl_get_drv_status(wl, DISCONNECTING, ndev)) {
7347                                         /* To make sure disconnect, explictly send dissassoc
7348                                         *  for BSSID 00:00:00:00:00:00 issue
7349                                         */
7350                                         scbval.val = WLAN_REASON_DEAUTH_LEAVING;
7351
7352                                         memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
7353                                         scbval.val = htod32(scbval.val);
7354                                         err = wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
7355                                                 sizeof(scb_val_t), true);
7356                                         if (err < 0) {
7357                                                 WL_ERR(("WLC_DISASSOC error %d\n", err));
7358                                                 err = 0;
7359                                         }
7360                                         cfg80211_disconnected(ndev, reason, NULL, 0, GFP_KERNEL);
7361                                         wl_link_down(wl);
7362                                         wl_init_prof(wl, ndev);
7363                                 }
7364                         }
7365                         else if (wl_get_drv_status(wl, CONNECTING, ndev)) {
7366
7367                                 printk("link down, during connecting\n");
7368 #ifdef ESCAN_RESULT_PATCH
7369                                 if ((memcmp(connect_req_bssid, broad_bssid, ETHER_ADDR_LEN) == 0) ||
7370                                         (memcmp(&e->addr, broad_bssid, ETHER_ADDR_LEN) == 0) ||
7371                                         (memcmp(&e->addr, connect_req_bssid, ETHER_ADDR_LEN) == 0))
7372                                         /* In case this event comes while associating another AP */
7373 #endif /* ESCAN_RESULT_PATCH */
7374                                         wl_bss_connect_done(wl, ndev, e, data, false);
7375                         }
7376                         wl_clr_drv_status(wl, DISCONNECTING, ndev);
7377
7378                         /* if link down, bsscfg is diabled */
7379                         if (ndev != wl_to_prmry_ndev(wl))
7380                                 complete(&wl->iface_disable);
7381
7382                 } else if (wl_is_nonetwork(wl, e)) {
7383                         printk("connect failed event=%d e->status %d e->reason %d \n",
7384                                 event, (int)ntoh32(e->status), (int)ntoh32(e->reason));
7385                         /* Clean up any pending scan request */
7386                         if (wl->scan_request) {
7387                                 if (wl->escan_on) {
7388                                         wl_notify_escan_complete(wl, ndev, true, true);
7389                                 } else {
7390                                         del_timer_sync(&wl->scan_timeout);
7391                                         wl_iscan_aborted(wl);
7392                                 }
7393                         }
7394                         if (wl_get_drv_status(wl, CONNECTING, ndev))
7395                                 wl_bss_connect_done(wl, ndev, e, data, false);
7396                 } else {
7397                         printk("%s nothing\n", __FUNCTION__);
7398                 }
7399         } else {
7400                 WL_ERR(("Invalid ndev status %d\n", wl_get_mode_by_netdev(wl, ndev)));
7401         }
7402         return err;
7403 }
7404
7405
7406 static s32
7407 wl_notify_roaming_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7408         const wl_event_msg_t *e, void *data)
7409 {
7410         bool act;
7411         struct net_device *ndev = NULL;
7412         s32 err = 0;
7413         u32 event = be32_to_cpu(e->event_type);
7414         u32 status = be32_to_cpu(e->status);
7415
7416         WL_DBG(("Enter \n"));
7417
7418         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7419
7420         if (event == WLC_E_ROAM && status == WLC_E_STATUS_SUCCESS) {
7421                 if (wl_get_drv_status(wl, CONNECTED, ndev))
7422                         wl_bss_roaming_done(wl, ndev, e, data);
7423                 else
7424                         wl_bss_connect_done(wl, ndev, e, data, true);
7425                 act = true;
7426                 wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT);
7427                 wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7428         }
7429         return err;
7430 }
7431
7432 static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev)
7433 {
7434         wl_assoc_info_t assoc_info;
7435         struct wl_connect_info *conn_info = wl_to_conn(wl);
7436         s32 err = 0;
7437
7438         WL_DBG(("Enter \n"));
7439         err = wldev_iovar_getbuf(ndev, "assoc_info", NULL, 0, wl->extra_buf,
7440                 WL_ASSOC_INFO_MAX, NULL);
7441         if (unlikely(err)) {
7442                 WL_ERR(("could not get assoc info (%d)\n", err));
7443                 return err;
7444         }
7445         memcpy(&assoc_info, wl->extra_buf, sizeof(wl_assoc_info_t));
7446         assoc_info.req_len = htod32(assoc_info.req_len);
7447         assoc_info.resp_len = htod32(assoc_info.resp_len);
7448         assoc_info.flags = htod32(assoc_info.flags);
7449         if (conn_info->req_ie_len) {
7450                 conn_info->req_ie_len = 0;
7451                 bzero(conn_info->req_ie, sizeof(conn_info->req_ie));
7452         }
7453         if (conn_info->resp_ie_len) {
7454                 conn_info->resp_ie_len = 0;
7455                 bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie));
7456         }
7457         if (assoc_info.req_len) {
7458                 err = wldev_iovar_getbuf(ndev, "assoc_req_ies", NULL, 0, wl->extra_buf,
7459                         WL_ASSOC_INFO_MAX, NULL);
7460                 if (unlikely(err)) {
7461                         WL_ERR(("could not get assoc req (%d)\n", err));
7462                         return err;
7463                 }
7464                 conn_info->req_ie_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
7465                 if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
7466                         conn_info->req_ie_len -= ETHER_ADDR_LEN;
7467                 }
7468                 if (conn_info->req_ie_len <= MAX_REQ_LINE)
7469                         memcpy(conn_info->req_ie, wl->extra_buf, conn_info->req_ie_len);
7470                 else {
7471                         WL_ERR(("IE size %d above max %d size \n",
7472                                 conn_info->req_ie_len, MAX_REQ_LINE));
7473                         return err;
7474                 }
7475         } else {
7476                 conn_info->req_ie_len = 0;
7477         }
7478         if (assoc_info.resp_len) {
7479                 err = wldev_iovar_getbuf(ndev, "assoc_resp_ies", NULL, 0, wl->extra_buf,
7480                         WL_ASSOC_INFO_MAX, NULL);
7481                 if (unlikely(err)) {
7482                         WL_ERR(("could not get assoc resp (%d)\n", err));
7483                         return err;
7484                 }
7485                 conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp);
7486                 if (conn_info->resp_ie_len <= MAX_REQ_LINE)
7487                         memcpy(conn_info->resp_ie, wl->extra_buf, conn_info->resp_ie_len);
7488                 else {
7489                         WL_ERR(("IE size %d above max %d size \n",
7490                                 conn_info->resp_ie_len, MAX_REQ_LINE));
7491                         return err;
7492                 }
7493         } else {
7494                 conn_info->resp_ie_len = 0;
7495         }
7496         WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
7497                 conn_info->resp_ie_len));
7498
7499         return err;
7500 }
7501
7502 static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
7503         size_t *join_params_size)
7504 {
7505         chanspec_t chanspec = 0;
7506         if (ch != 0) {
7507                 join_params->params.chanspec_num = 1;
7508                 join_params->params.chanspec_list[0] = ch;
7509
7510                 if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
7511                         chanspec |= WL_CHANSPEC_BAND_2G;
7512                 else
7513                         chanspec |= WL_CHANSPEC_BAND_5G;
7514
7515                 chanspec |= WL_CHANSPEC_BW_20;
7516                 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
7517
7518                 *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
7519                         join_params->params.chanspec_num * sizeof(chanspec_t);
7520
7521                 join_params->params.chanspec_list[0]  &= WL_CHANSPEC_CHAN_MASK;
7522                 join_params->params.chanspec_list[0] |= chanspec;
7523                 join_params->params.chanspec_list[0] =
7524                         wl_chspec_host_to_driver(join_params->params.chanspec_list[0]);
7525
7526                 join_params->params.chanspec_num =
7527                         htod32(join_params->params.chanspec_num);
7528                 WL_DBG(("join_params->params.chanspec_list[0]= %X, %d channels\n",
7529                         join_params->params.chanspec_list[0],
7530                         join_params->params.chanspec_num));
7531         }
7532 }
7533
7534 static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev)
7535 {
7536         struct cfg80211_bss *bss;
7537         struct wl_bss_info *bi;
7538         struct wlc_ssid *ssid;
7539         struct bcm_tlv *tim;
7540         s32 beacon_interval;
7541         s32 dtim_period;
7542         size_t ie_len;
7543         u8 *ie;
7544         u8 *curbssid;
7545         s32 err = 0;
7546         struct wiphy *wiphy;
7547         struct ieee80211_supported_band *band;
7548         struct ieee80211_channel *channel = NULL;
7549         u16 chan;
7550         u32 freq;
7551
7552         mutex_lock(&wl->usr_sync);
7553         wiphy = wl_to_wiphy(wl);
7554
7555         ssid = (struct wlc_ssid *)wl_read_prof(wl, ndev, WL_PROF_SSID);
7556         curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7557         *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
7558         err = wldev_ioctl(ndev, WLC_GET_BSS_INFO,
7559                                 wl->extra_buf, WL_EXTRA_BUF_MAX, false);
7560         if (unlikely(err)) {
7561                 WL_ERR(("Could not get bss info %d\n", err));
7562                 goto update_bss_info_out;
7563         }
7564         bi = (struct wl_bss_info *)(wl->extra_buf + 4);
7565         chan = bi->ctl_ch ? bi->ctl_ch :
7566                 CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
7567         if (chan <= CH_MAX_2G_CHANNEL)
7568                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
7569         else
7570                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
7571         freq = ieee80211_channel_to_frequency(chan, band->band);
7572         channel = ieee80211_get_channel(wiphy, freq);
7573         bss = cfg80211_get_bss(wiphy, channel, curbssid,
7574                                 ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS,
7575                                 WLAN_CAPABILITY_ESS);
7576         if (!bss) {
7577                 WL_DBG(("Could not find the AP\n"));
7578                 if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) {
7579                         WL_ERR(("Bssid doesn't match\n"));
7580                         err = -EIO;
7581                         goto update_bss_info_out;
7582                 }
7583                 err = wl_inform_single_bss(wl, bi);
7584                 if (unlikely(err))
7585                         goto update_bss_info_out;
7586
7587                 ie = ((u8 *)bi) + bi->ie_offset;
7588                 ie_len = bi->ie_length;
7589                 beacon_interval = cpu_to_le16(bi->beacon_period);
7590         } else {
7591                 WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid));
7592 #if defined(WL_CFG80211_P2P_DEV_IF)
7593                 ie = (u8 *)bss->ies->data;
7594                 ie_len = bss->ies->len;
7595 #else
7596                 ie = bss->information_elements;
7597                 ie_len = bss->len_information_elements;
7598 #endif /* WL_CFG80211_P2P_DEV_IF */
7599                 beacon_interval = bss->beacon_interval;
7600 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
7601                 cfg80211_put_bss(wiphy, bss);
7602 #else
7603                 cfg80211_put_bss(bss);
7604 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
7605         }
7606
7607         tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
7608         if (tim) {
7609                 dtim_period = tim->data[1];
7610         } else {
7611                 /*
7612                 * active scan was done so we could not get dtim
7613                 * information out of probe response.
7614                 * so we speficially query dtim information.
7615                 */
7616                 err = wldev_ioctl(ndev, WLC_GET_DTIMPRD,
7617                         &dtim_period, sizeof(dtim_period), false);
7618                 if (unlikely(err)) {
7619                         WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
7620                         goto update_bss_info_out;
7621                 }
7622         }
7623
7624         wl_update_prof(wl, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT);
7625         wl_update_prof(wl, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
7626
7627 update_bss_info_out:
7628         if (unlikely(err)) {
7629                 WL_ERR(("Failed with error %d\n", err));
7630         }
7631         mutex_unlock(&wl->usr_sync);
7632         return err;
7633 }
7634
7635 static s32
7636 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
7637         const wl_event_msg_t *e, void *data)
7638 {
7639         struct wl_connect_info *conn_info = wl_to_conn(wl);
7640         s32 err = 0;
7641         u8 *curbssid;
7642 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || 0
7643         struct wl_bss_info *bss_info;
7644         struct wiphy *wiphy = wl_to_wiphy(wl);
7645         struct ieee80211_supported_band *band;
7646         struct ieee80211_channel *notify_channel = NULL;
7647         u8 *buf;
7648         u16 channel;
7649         u32 freq;
7650 #endif 
7651
7652         wl_get_assoc_ies(wl, ndev);
7653         wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID);
7654         curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7655         wl_update_bss_info(wl, ndev);
7656         wl_update_pmklist(ndev, wl->pmk_list, err);
7657
7658 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || 0
7659         /* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */
7660         buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
7661         if (!buf)
7662                 goto done;
7663
7664         *(__le32 *)buf = htod32(WL_EXTRA_BUF_MAX);
7665         err = wldev_ioctl(ndev, WLC_GET_BSS_INFO, buf, WL_EXTRA_BUF_MAX, false);
7666         if (err)
7667                 goto done;
7668
7669         bss_info = (struct wl_bss_info *)(buf + 4);
7670         channel = bss_info->ctl_ch ? bss_info->ctl_ch :
7671                 CHSPEC_CHANNEL(wl_chspec_driver_to_host(bss_info->chanspec));
7672         if (channel <= CH_MAX_2G_CHANNEL)
7673                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
7674         else
7675                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
7676         freq = ieee80211_channel_to_frequency(channel, band->band);
7677         notify_channel = ieee80211_get_channel(wiphy, freq);
7678 done:
7679         kfree(buf);
7680 #endif 
7681         printk("wl_bss_roaming_done succeeded to " MACDBG "\n",
7682                 MAC2STRDBG((u8*)(&e->addr)));
7683
7684         cfg80211_roamed(ndev,
7685 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || 0
7686                 notify_channel,
7687 #endif
7688                 curbssid,
7689                 conn_info->req_ie, conn_info->req_ie_len,
7690                 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
7691         WL_DBG(("Report roaming result\n"));
7692
7693         wl_set_drv_status(wl, CONNECTED, ndev);
7694
7695         return err;
7696 }
7697
7698 static s32
7699 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
7700         const wl_event_msg_t *e, void *data, bool completed)
7701 {
7702         struct wl_connect_info *conn_info = wl_to_conn(wl);
7703         struct wl_security *sec = wl_read_prof(wl, ndev, WL_PROF_SEC);
7704         s32 err = 0;
7705         u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7706         if (!sec) {
7707                 WL_ERR(("sec is NULL\n"));
7708                 return -ENODEV;
7709         }
7710         WL_DBG((" enter\n"));
7711 #ifdef ESCAN_RESULT_PATCH
7712         if (wl_get_drv_status(wl, CONNECTED, ndev)) {
7713                 if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) {
7714                         WL_DBG((" Connected event of connected device e=%d s=%d, ignore it\n",
7715                                 ntoh32(e->event_type), ntoh32(e->status)));
7716                         return err;
7717                 }
7718         }
7719         if (memcmp(curbssid, broad_bssid, ETHER_ADDR_LEN) == 0 &&
7720                 memcmp(broad_bssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) {
7721                 WL_DBG(("copy bssid\n"));
7722                 memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN);
7723         }
7724
7725 #else
7726         if (wl->scan_request) {
7727                 wl_notify_escan_complete(wl, ndev, true, true);
7728         }
7729 #endif /* ESCAN_RESULT_PATCH */
7730         if (wl_get_drv_status(wl, CONNECTING, ndev) && (e->event_type == WLC_E_SET_SSID)) {
7731                 wl_cfg80211_scan_abort(wl);
7732                 wl_clr_drv_status(wl, CONNECTING, ndev);
7733                 if (completed) {
7734                         wl_get_assoc_ies(wl, ndev);
7735                         wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID);
7736                         curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7737                         wl_update_bss_info(wl, ndev);
7738                         wl_update_pmklist(ndev, wl->pmk_list, err);
7739                         wl_set_drv_status(wl, CONNECTED, ndev);
7740                         if (ndev != wl_to_prmry_ndev(wl)) {
7741                                 /* reinitialize completion to clear previous count */
7742                                 INIT_COMPLETION(wl->iface_disable);
7743                         }
7744                 }
7745                 /* Update the cfg layer with the lates active channels available */
7746                 wl_update_wiphybands(NULL, true);
7747
7748                 cfg80211_connect_result(ndev,
7749                         curbssid,
7750                         conn_info->req_ie,
7751                         conn_info->req_ie_len,
7752                         conn_info->resp_ie,
7753                         conn_info->resp_ie_len,
7754                         completed ? WLAN_STATUS_SUCCESS :
7755                         (sec->auth_assoc_res_status) ?
7756                         sec->auth_assoc_res_status :
7757                         WLAN_STATUS_UNSPECIFIED_FAILURE,
7758                         GFP_KERNEL);
7759                 if (completed)
7760                         WL_INFO(("Report connect result - connection succeeded\n"));
7761                 else
7762                         WL_ERR(("Report connect result - connection failed\n"));
7763         }
7764         return err;
7765 }
7766
7767 static s32
7768 wl_notify_mic_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7769         const wl_event_msg_t *e, void *data)
7770 {
7771         struct net_device *ndev = NULL;
7772         u16 flags = ntoh16(e->flags);
7773         enum nl80211_key_type key_type;
7774
7775         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7776
7777         mutex_lock(&wl->usr_sync);
7778         if (flags & WLC_EVENT_MSG_GROUP)
7779                 key_type = NL80211_KEYTYPE_GROUP;
7780         else
7781                 key_type = NL80211_KEYTYPE_PAIRWISE;
7782
7783         cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
7784                 NULL, GFP_KERNEL);
7785         mutex_unlock(&wl->usr_sync);
7786
7787         return 0;
7788 }
7789
7790 #ifdef PNO_SUPPORT
7791 static s32
7792 wl_notify_pfn_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7793         const wl_event_msg_t *e, void *data)
7794 {
7795         struct net_device *ndev = NULL;
7796
7797         WL_ERR((">>> PNO Event\n"));
7798
7799         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7800
7801 #ifndef WL_SCHED_SCAN
7802         mutex_lock(&wl->usr_sync);
7803         /* TODO: Use cfg80211_sched_scan_results(wiphy); */
7804         cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
7805         mutex_unlock(&wl->usr_sync);
7806 #else
7807         /* If cfg80211 scheduled scan is supported, report the pno results via sched
7808          * scan results
7809          */
7810         wl_notify_sched_scan_results(wl, ndev, e, data);
7811 #endif /* WL_SCHED_SCAN */
7812         return 0;
7813 }
7814 #endif /* PNO_SUPPORT */
7815
7816 static s32
7817 wl_notify_scan_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7818         const wl_event_msg_t *e, void *data)
7819 {
7820         struct channel_info channel_inform;
7821         struct wl_scan_results *bss_list;
7822         struct net_device *ndev = NULL;
7823         u32 len = WL_SCAN_BUF_MAX;
7824         s32 err = 0;
7825         unsigned long flags;
7826
7827         WL_DBG(("Enter \n"));
7828         if (!wl_get_drv_status(wl, SCANNING, ndev)) {
7829                 WL_ERR(("scan is not ready \n"));
7830                 return err;
7831         }
7832         if (wl->iscan_on && wl->iscan_kickstart)
7833                 return wl_wakeup_iscan(wl_to_iscan(wl));
7834
7835         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7836
7837         mutex_lock(&wl->usr_sync);
7838         wl_clr_drv_status(wl, SCANNING, ndev);
7839         err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
7840                 sizeof(channel_inform), false);
7841         if (unlikely(err)) {
7842                 WL_ERR(("scan busy (%d)\n", err));
7843                 goto scan_done_out;
7844         }
7845         channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
7846         if (unlikely(channel_inform.scan_channel)) {
7847
7848                 WL_DBG(("channel_inform.scan_channel (%d)\n",
7849                         channel_inform.scan_channel));
7850         }
7851         wl->bss_list = wl->scan_results;
7852         bss_list = wl->bss_list;
7853         memset(bss_list, 0, len);
7854         bss_list->buflen = htod32(len);
7855         err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, false);
7856         if (unlikely(err) && unlikely(!wl->scan_suppressed)) {
7857                 WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
7858                 err = -EINVAL;
7859                 goto scan_done_out;
7860         }
7861         bss_list->buflen = dtoh32(bss_list->buflen);
7862         bss_list->version = dtoh32(bss_list->version);
7863         bss_list->count = dtoh32(bss_list->count);
7864
7865         err = wl_inform_bss(wl);
7866
7867 scan_done_out:
7868         del_timer_sync(&wl->scan_timeout);
7869         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
7870         if (wl->scan_request) {
7871                 cfg80211_scan_done(wl->scan_request, false);
7872                 wl->scan_request = NULL;
7873         }
7874         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
7875         WL_DBG(("cfg80211_scan_done\n"));
7876         mutex_unlock(&wl->usr_sync);
7877         return err;
7878 }
7879
7880 static s32
7881 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
7882         const struct ether_addr *sa, const struct ether_addr *bssid,
7883         u8 **pheader, u32 *body_len, u8 *pbody)
7884 {
7885         struct dot11_management_header *hdr;
7886         u32 totlen = 0;
7887         s32 err = 0;
7888         u8 *offset;
7889         u32 prebody_len = *body_len;
7890         switch (fc) {
7891                 case FC_ASSOC_REQ:
7892                         /* capability , listen interval */
7893                         totlen = DOT11_ASSOC_REQ_FIXED_LEN;
7894                         *body_len += DOT11_ASSOC_REQ_FIXED_LEN;
7895                         break;
7896
7897                 case FC_REASSOC_REQ:
7898                         /* capability, listen inteval, ap address */
7899                         totlen = DOT11_REASSOC_REQ_FIXED_LEN;
7900                         *body_len += DOT11_REASSOC_REQ_FIXED_LEN;
7901                         break;
7902         }
7903         totlen += DOT11_MGMT_HDR_LEN + prebody_len;
7904         *pheader = kzalloc(totlen, GFP_KERNEL);
7905         if (*pheader == NULL) {
7906                 WL_ERR(("memory alloc failed \n"));
7907                 return -ENOMEM;
7908         }
7909         hdr = (struct dot11_management_header *) (*pheader);
7910         hdr->fc = htol16(fc);
7911         hdr->durid = 0;
7912         hdr->seq = 0;
7913         offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
7914         bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
7915         bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
7916         bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
7917         if ((pbody != NULL) && prebody_len)
7918                 bcopy((const char*)pbody, offset, prebody_len);
7919         *body_len = totlen;
7920         return err;
7921 }
7922
7923
7924 void
7925 wl_stop_wait_next_action_frame(struct wl_priv *wl)
7926 {
7927         if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) {
7928                 if (!(wl_get_p2p_status(wl, ACTION_TX_COMPLETED) ||
7929                         wl_get_p2p_status(wl, ACTION_TX_NOACK)))
7930                         wl_set_p2p_status(wl, ACTION_TX_COMPLETED);
7931
7932                 WL_DBG(("*** Wake UP ** abort actframe iovar\n"));
7933                 /* if channel is not zero, "actfame" uses off channel scan.
7934                  * So abort scan for off channel completion.
7935                  */
7936                 if (wl->af_sent_channel)
7937                         wl_cfg80211_scan_abort(wl);
7938         }
7939 #ifdef WL_CFG80211_SYNC_GON
7940         else if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN)) {
7941                 WL_DBG(("*** Wake UP ** abort listen for next af frame\n"));
7942                 /* So abort scan to cancel listen */
7943                 wl_cfg80211_scan_abort(wl);
7944         }
7945 #endif /* WL_CFG80211_SYNC_GON */
7946 }
7947
7948
7949 int wl_cfg80211_get_ioctl_version(void)
7950 {
7951         return ioctl_version;
7952 }
7953
7954 static s32
7955 wl_notify_rx_mgmt_frame(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7956         const wl_event_msg_t *e, void *data)
7957
7958 {
7959         struct ieee80211_supported_band *band;
7960         struct wiphy *wiphy = wl_to_wiphy(wl);
7961         struct ether_addr da;
7962         struct ether_addr bssid;
7963         bool isfree = false;
7964         s32 err = 0;
7965         s32 freq;
7966         struct net_device *ndev = NULL;
7967         wifi_p2p_pub_act_frame_t *act_frm = NULL;
7968         wifi_p2p_action_frame_t *p2p_act_frm = NULL;
7969         wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
7970         wl_event_rx_frame_data_t *rxframe =
7971                 (wl_event_rx_frame_data_t*)data;
7972         u32 event = ntoh32(e->event_type);
7973         u8 *mgmt_frame;
7974         u8 bsscfgidx = e->bsscfgidx;
7975         u32 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t);
7976         u16 channel = ((ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK));
7977
7978         memset(&bssid, 0, ETHER_ADDR_LEN);
7979
7980         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7981
7982         if (channel <= CH_MAX_2G_CHANNEL)
7983                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
7984         else
7985                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
7986         if (!band) {
7987                 WL_ERR(("No valid band"));
7988                 return -EINVAL;
7989         }
7990 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
7991         freq = ieee80211_channel_to_frequency(channel);
7992         (void)band->band;
7993 #else
7994         freq = ieee80211_channel_to_frequency(channel, band->band);
7995 #endif
7996         if (event == WLC_E_ACTION_FRAME_RX) {
7997                 wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
7998                         NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync);
7999
8000                 err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
8001                 if (err < 0)
8002                          WL_ERR(("WLC_GET_BSSID error %d\n", err));
8003                 memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN);
8004                 err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid,
8005                         &mgmt_frame, &mgmt_frame_len,
8006                         (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1));
8007                 if (err < 0) {
8008                         WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n",
8009                                 mgmt_frame_len, channel, freq));
8010                         goto exit;
8011                 }
8012                 isfree = true;
8013                 if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
8014                         mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
8015                         act_frm = (wifi_p2p_pub_act_frame_t *)
8016                                         (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
8017                 } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
8018                         mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
8019                         p2p_act_frm = (wifi_p2p_action_frame_t *)
8020                                         (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
8021                         (void) p2p_act_frm;
8022                 } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
8023                         mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
8024
8025                         sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)
8026                                         (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
8027                         if (sd_act_frm && wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) {
8028                                 if (wl->next_af_subtype == sd_act_frm->action) {
8029                                         WL_DBG(("We got a right next frame of SD!(%d)\n",
8030                                                 sd_act_frm->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                         (void) sd_act_frm;
8038                 } else {
8039                         /*
8040                          *  if we got normal action frame and ndev is p2p0,
8041                          *  we have to change ndev from p2p0 to wlan0
8042                          */
8043 #if defined(WL_ENABLE_P2P_IF)
8044                         if (wl->p2p_net == cfgdev)
8045                                 cfgdev = wl_to_prmry_ndev(wl);
8046 #endif /* WL_ENABLE_P2P_IF */
8047
8048                         if (wl->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
8049                                 u8 action = 0;
8050                                 if (wl_get_public_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
8051                                         mgmt_frame_len - DOT11_MGMT_HDR_LEN, &action) != BCME_OK) {
8052                                         WL_DBG(("Recived action is not public action frame\n"));
8053                                 } else if (wl->next_af_subtype == action) {
8054                                         WL_DBG(("Recived action is the waiting action(%d)\n",
8055                                                 action));
8056                                         wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev);
8057
8058                                         /* Stop waiting for next AF. */
8059                                         wl_stop_wait_next_action_frame(wl);
8060                                 }
8061                         }
8062                 }
8063
8064                 if (act_frm) {
8065
8066                         if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) {
8067                                 if (wl->next_af_subtype == act_frm->subtype) {
8068                                         WL_DBG(("We got a right next frame!(%d)\n",
8069                                                 act_frm->subtype));
8070                                         wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev);
8071
8072                                         if (wl->next_af_subtype == P2P_PAF_GON_CONF) {
8073                                                 OSL_SLEEP(20);
8074                                         }
8075
8076                                         /* Stop waiting for next AF. */
8077                                         wl_stop_wait_next_action_frame(wl);
8078                                 }
8079                         }
8080                 }
8081
8082                 wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN],
8083                         mgmt_frame_len - DOT11_MGMT_HDR_LEN, channel);
8084                 /*
8085                  * After complete GO Negotiation, roll back to mpc mode
8086                  */
8087                 if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) ||
8088                         (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
8089                         wldev_iovar_setint(ndev, "mpc", 1);
8090                 }
8091                 if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) {
8092                         WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
8093                         wl_clr_p2p_status(wl, GO_NEG_PHASE);
8094                 }
8095         } else {
8096                 mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
8097
8098                 /* wpa supplicant use probe request event for restarting another GON Req.
8099                  * but it makes GON Req repetition.
8100                  * so if src addr of prb req is same as my target device,
8101                  * do not send probe request event during sending action frame.
8102                  */
8103                 if (event == WLC_E_P2P_PROBREQ_MSG) {
8104                         WL_DBG((" Event %s\n", (event == WLC_E_P2P_PROBREQ_MSG) ?
8105                                 "WLC_E_P2P_PROBREQ_MSG":"WLC_E_PROBREQ_MSG"));
8106
8107
8108                         /* Filter any P2P probe reqs arriving during the
8109                          * GO-NEG Phase
8110                          */
8111                         if (wl->p2p &&
8112                                 wl_get_p2p_status(wl, GO_NEG_PHASE)) {
8113                                 WL_DBG(("Filtering P2P probe_req while "
8114                                         "being in GO-Neg state\n"));
8115                                 return 0;
8116                         }
8117                 }
8118         }
8119
8120 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
8121         cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
8122 #else
8123         cfg80211_rx_mgmt(cfgdev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
8124 #endif 
8125
8126         WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n",
8127                 mgmt_frame_len, ntoh32(e->datalen), channel, freq));
8128 exit:
8129         if (isfree)
8130                 kfree(mgmt_frame);
8131         return 0;
8132 }
8133
8134 #ifdef WL_SCHED_SCAN
8135 /* If target scan is not reliable, set the below define to "1" to do a
8136  * full escan
8137  */
8138 #define FULL_ESCAN_ON_PFN_NET_FOUND             0
8139 static s32
8140 wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev,
8141         const wl_event_msg_t *e, void *data)
8142 {
8143         wl_pfn_net_info_t *netinfo, *pnetinfo;
8144         struct wiphy *wiphy     = wl_to_wiphy(wl);
8145         int err = 0;
8146         struct cfg80211_scan_request *request = NULL;
8147         struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
8148         struct ieee80211_channel *channel = NULL;
8149         int channel_req = 0;
8150         int band = 0;
8151         struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data;
8152         int n_pfn_results = pfn_result->count;
8153
8154         WL_DBG(("Enter\n"));
8155
8156         if (e->event_type == WLC_E_PFN_NET_LOST) {
8157                 WL_PNO(("PFN NET LOST event. Do Nothing \n"));
8158                 return 0;
8159         }
8160         WL_PNO((">>> PFN NET FOUND event. count:%d \n", n_pfn_results));
8161         if (n_pfn_results > 0) {
8162                 int i;
8163
8164                 if (n_pfn_results > MAX_PFN_LIST_COUNT)
8165                         n_pfn_results = MAX_PFN_LIST_COUNT;
8166                 pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t)
8167                                 - sizeof(wl_pfn_net_info_t));
8168
8169                 memset(&ssid, 0x00, sizeof(ssid));
8170
8171                 request = kzalloc(sizeof(*request)
8172                         + sizeof(*request->channels) * n_pfn_results,
8173                         GFP_KERNEL);
8174                 channel = (struct ieee80211_channel *)kzalloc(
8175                         (sizeof(struct ieee80211_channel) * n_pfn_results),
8176                         GFP_KERNEL);
8177                 if (!request || !channel) {
8178                         WL_ERR(("No memory"));
8179                         err = -ENOMEM;
8180                         goto out_err;
8181                 }
8182
8183                 request->wiphy = wiphy;
8184
8185                 for (i = 0; i < n_pfn_results; i++) {
8186                         netinfo = &pnetinfo[i];
8187                         if (!netinfo) {
8188                                 WL_ERR(("Invalid netinfo ptr. index:%d", i));
8189                                 err = -EINVAL;
8190                                 goto out_err;
8191                         }
8192                         WL_PNO((">>> SSID:%s Channel:%d \n",
8193                                 netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel));
8194                         /* PFN result doesn't have all the info which are required by the supplicant
8195                          * (For e.g IEs) Do a target Escan so that sched scan results are reported
8196                          * via wl_inform_single_bss in the required format. Escan does require the
8197                          * scan request in the form of cfg80211_scan_request. For timebeing, create
8198                          * cfg80211_scan_request one out of the received PNO event.
8199                          */
8200                         memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID,
8201                                 netinfo->pfnsubnet.SSID_len);
8202                         ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len;
8203                         request->n_ssids++;
8204
8205                         channel_req = netinfo->pfnsubnet.channel;
8206                         band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
8207                                 : NL80211_BAND_5GHZ;
8208                         channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band);
8209                         channel[i].band = band;
8210                         channel[i].flags |= IEEE80211_CHAN_NO_HT40;
8211                         request->channels[i] = &channel[i];
8212                         request->n_channels++;
8213                 }
8214
8215                 /* assign parsed ssid array */
8216                 if (request->n_ssids)
8217                         request->ssids = &ssid[0];
8218
8219                 if (wl_get_drv_status_all(wl, SCANNING)) {
8220                         /* Abort any on-going scan */
8221                         wl_notify_escan_complete(wl, ndev, true, true);
8222                 }
8223
8224                 if (wl_get_p2p_status(wl, DISCOVERY_ON)) {
8225                         WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
8226                         err = wl_cfgp2p_discover_enable_search(wl, false);
8227                         if (unlikely(err)) {
8228                                 wl_clr_drv_status(wl, SCANNING, ndev);
8229                                 goto out_err;
8230                         }
8231                 }
8232
8233                 wl_set_drv_status(wl, SCANNING, ndev);
8234 #if FULL_ESCAN_ON_PFN_NET_FOUND
8235                 WL_PNO((">>> Doing Full ESCAN on PNO event\n"));
8236                 err = wl_do_escan(wl, wiphy, ndev, NULL);
8237 #else
8238                 WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
8239                 err = wl_do_escan(wl, wiphy, ndev, request);
8240 #endif
8241                 if (err) {
8242                         wl_clr_drv_status(wl, SCANNING, ndev);
8243                         goto out_err;
8244                 }
8245                 wl->sched_scan_running = TRUE;
8246         }
8247         else {
8248                 WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
8249         }
8250 out_err:
8251         if (request)
8252                 kfree(request);
8253         if (channel)
8254                 kfree(channel);
8255         return err;
8256 }
8257 #endif /* WL_SCHED_SCAN */
8258
8259 static void wl_init_conf(struct wl_conf *conf)
8260 {
8261         WL_DBG(("Enter \n"));
8262         conf->frag_threshold = (u32)-1;
8263         conf->rts_threshold = (u32)-1;
8264         conf->retry_short = (u32)-1;
8265         conf->retry_long = (u32)-1;
8266         conf->tx_power = -1;
8267 }
8268
8269 static void wl_init_prof(struct wl_priv *wl, struct net_device *ndev)
8270 {
8271         unsigned long flags;
8272         struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
8273
8274         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
8275         memset(profile, 0, sizeof(struct wl_profile));
8276         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
8277 }
8278
8279 static void wl_init_event_handler(struct wl_priv *wl)
8280 {
8281         memset(wl->evt_handler, 0, sizeof(wl->evt_handler));
8282
8283         wl->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
8284         wl->evt_handler[WLC_E_AUTH] = wl_notify_connect_status;
8285         wl->evt_handler[WLC_E_ASSOC] = wl_notify_connect_status;
8286         wl->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
8287         wl->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
8288         wl->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
8289         wl->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
8290         wl->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
8291         wl->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
8292         wl->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;
8293         wl->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
8294         wl->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;
8295         wl->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;
8296         wl->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
8297         wl->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
8298         wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
8299         wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
8300         wl->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
8301         wl->evt_handler[WLC_E_JOIN] = wl_notify_connect_status;
8302         wl->evt_handler[WLC_E_START] = wl_notify_connect_status;
8303 #ifdef PNO_SUPPORT
8304         wl->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status;
8305 #endif /* PNO_SUPPORT */
8306 #ifdef WLTDLS
8307         wl->evt_handler[WLC_E_TDLS_PEER_EVENT] = wl_tdls_event_handler;
8308 #endif /* WLTDLS */
8309 #ifdef BCMCCX_S69
8310         wl->evt_handler[WLC_E_CCX_S69_RESP_RX] = wl_ccx_s69_response;
8311 #endif
8312 }
8313
8314 #if defined(STATIC_WL_PRIV_STRUCT)
8315 static void
8316 wl_init_escan_result_buf(struct wl_priv *wl)
8317 {
8318         wl->escan_info.escan_buf = dhd_os_prealloc(NULL, DHD_PREALLOC_WIPHY_ESCAN0, 0);
8319         bzero(wl->escan_info.escan_buf, ESCAN_BUF_SIZE);
8320 }
8321
8322 static void
8323 wl_deinit_escan_result_buf(struct wl_priv *wl)
8324 {
8325         wl->escan_info.escan_buf = NULL;
8326
8327 }
8328 #endif /* STATIC_WL_PRIV_STRUCT */
8329
8330 static s32 wl_init_priv_mem(struct wl_priv *wl)
8331 {
8332         WL_DBG(("Enter \n"));
8333         wl->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
8334         if (unlikely(!wl->scan_results)) {
8335                 WL_ERR(("Scan results alloc failed\n"));
8336                 goto init_priv_mem_out;
8337         }
8338         wl->conf = (void *)kzalloc(sizeof(*wl->conf), GFP_KERNEL);
8339         if (unlikely(!wl->conf)) {
8340                 WL_ERR(("wl_conf alloc failed\n"));
8341                 goto init_priv_mem_out;
8342         }
8343         wl->scan_req_int =
8344             (void *)kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL);
8345         if (unlikely(!wl->scan_req_int)) {
8346                 WL_ERR(("Scan req alloc failed\n"));
8347                 goto init_priv_mem_out;
8348         }
8349         wl->ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
8350         if (unlikely(!wl->ioctl_buf)) {
8351                 WL_ERR(("Ioctl buf alloc failed\n"));
8352                 goto init_priv_mem_out;
8353         }
8354         wl->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
8355         if (unlikely(!wl->escan_ioctl_buf)) {
8356                 WL_ERR(("Ioctl buf alloc failed\n"));
8357                 goto init_priv_mem_out;
8358         }
8359         wl->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
8360         if (unlikely(!wl->extra_buf)) {
8361                 WL_ERR(("Extra buf alloc failed\n"));
8362                 goto init_priv_mem_out;
8363         }
8364         wl->iscan = (void *)kzalloc(sizeof(*wl->iscan), GFP_KERNEL);
8365         if (unlikely(!wl->iscan)) {
8366                 WL_ERR(("Iscan buf alloc failed\n"));
8367                 goto init_priv_mem_out;
8368         }
8369         wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL);
8370         if (unlikely(!wl->pmk_list)) {
8371                 WL_ERR(("pmk list alloc failed\n"));
8372                 goto init_priv_mem_out;
8373         }
8374         wl->sta_info = (void *)kzalloc(sizeof(*wl->sta_info), GFP_KERNEL);
8375         if (unlikely(!wl->sta_info)) {
8376                 WL_ERR(("sta info  alloc failed\n"));
8377                 goto init_priv_mem_out;
8378         }
8379
8380 #if defined(STATIC_WL_PRIV_STRUCT)
8381         wl->conn_info = (void *)kzalloc(sizeof(*wl->conn_info), GFP_KERNEL);
8382         if (unlikely(!wl->conn_info)) {
8383                 WL_ERR(("wl->conn_info  alloc failed\n"));
8384                 goto init_priv_mem_out;
8385         }
8386         wl->ie = (void *)kzalloc(sizeof(*wl->ie), GFP_KERNEL);
8387         if (unlikely(!wl->ie)) {
8388                 WL_ERR(("wl->ie  alloc failed\n"));
8389                 goto init_priv_mem_out;
8390         }
8391         wl_init_escan_result_buf(wl);
8392 #endif /* STATIC_WL_PRIV_STRUCT */
8393         wl->afx_hdl = (void *)kzalloc(sizeof(*wl->afx_hdl), GFP_KERNEL);
8394         if (unlikely(!wl->afx_hdl)) {
8395                 WL_ERR(("afx hdl  alloc failed\n"));
8396                 goto init_priv_mem_out;
8397         } else {
8398                 init_completion(&wl->act_frm_scan);
8399                 init_completion(&wl->wait_next_af);
8400
8401                 INIT_WORK(&wl->afx_hdl->work, wl_cfg80211_afx_handler);
8402         }
8403         return 0;
8404
8405 init_priv_mem_out:
8406         wl_deinit_priv_mem(wl);
8407
8408         return -ENOMEM;
8409 }
8410
8411 static void wl_deinit_priv_mem(struct wl_priv *wl)
8412 {
8413         kfree(wl->scan_results);
8414         wl->scan_results = NULL;
8415         kfree(wl->conf);
8416         wl->conf = NULL;
8417         kfree(wl->scan_req_int);
8418         wl->scan_req_int = NULL;
8419         kfree(wl->ioctl_buf);
8420         wl->ioctl_buf = NULL;
8421         kfree(wl->escan_ioctl_buf);
8422         wl->escan_ioctl_buf = NULL;
8423         kfree(wl->extra_buf);
8424         wl->extra_buf = NULL;
8425         kfree(wl->iscan);
8426         wl->iscan = NULL;
8427         kfree(wl->pmk_list);
8428         wl->pmk_list = NULL;
8429         kfree(wl->sta_info);
8430         wl->sta_info = NULL;
8431 #if defined(STATIC_WL_PRIV_STRUCT)
8432         kfree(wl->conn_info);
8433         wl->conn_info = NULL;
8434         kfree(wl->ie);
8435         wl->ie = NULL;
8436         wl_deinit_escan_result_buf(wl);
8437 #endif /* STATIC_WL_PRIV_STRUCT */
8438         if (wl->afx_hdl) {
8439                 cancel_work_sync(&wl->afx_hdl->work);
8440                 kfree(wl->afx_hdl);
8441                 wl->afx_hdl = NULL;
8442         }
8443
8444         if (wl->ap_info) {
8445                 kfree(wl->ap_info->wpa_ie);
8446                 kfree(wl->ap_info->rsn_ie);
8447                 kfree(wl->ap_info->wps_ie);
8448                 kfree(wl->ap_info);
8449                 wl->ap_info = NULL;
8450         }
8451 }
8452
8453 static s32 wl_create_event_handler(struct wl_priv *wl)
8454 {
8455         int ret = 0;
8456         WL_DBG(("Enter \n"));
8457
8458         /* Do not use DHD in cfg driver */
8459         wl->event_tsk.thr_pid = -1;
8460
8461         PROC_START(wl_event_handler, wl, &wl->event_tsk, 0, "wl_event_handler");
8462         if (wl->event_tsk.thr_pid < 0)
8463                 ret = -ENOMEM;
8464         return ret;
8465 }
8466
8467 static void wl_destroy_event_handler(struct wl_priv *wl)
8468 {
8469         if (wl->event_tsk.thr_pid >= 0)
8470                 PROC_STOP(&wl->event_tsk);
8471 }
8472
8473 static void wl_term_iscan(struct wl_priv *wl)
8474 {
8475         struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
8476         WL_TRACE(("In\n"));
8477         if (wl->iscan_on && iscan->tsk) {
8478                 iscan->state = WL_ISCAN_STATE_IDLE;
8479                 WL_INFO(("SIGTERM\n"));
8480                 send_sig(SIGTERM, iscan->tsk, 1);
8481                 WL_DBG(("kthread_stop\n"));
8482                 kthread_stop(iscan->tsk);
8483                 iscan->tsk = NULL;
8484         }
8485 }
8486
8487 static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted)
8488 {
8489         struct wl_priv *wl = iscan_to_wl(iscan);
8490         struct net_device *ndev = wl_to_prmry_ndev(wl);
8491         unsigned long flags;
8492
8493         WL_DBG(("Enter \n"));
8494         if (!wl_get_drv_status(wl, SCANNING, ndev)) {
8495                 wl_clr_drv_status(wl, SCANNING, ndev);
8496                 WL_ERR(("Scan complete while device not scanning\n"));
8497                 return;
8498         }
8499         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
8500         wl_clr_drv_status(wl, SCANNING, ndev);
8501         if (likely(wl->scan_request)) {
8502                 cfg80211_scan_done(wl->scan_request, aborted);
8503                 wl->scan_request = NULL;
8504         }
8505         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
8506         wl->iscan_kickstart = false;
8507 }
8508
8509 static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan)
8510 {
8511         if (likely(iscan->state != WL_ISCAN_STATE_IDLE)) {
8512                 WL_DBG(("wake up iscan\n"));
8513                 up(&iscan->sync);
8514                 return 0;
8515         }
8516
8517         return -EIO;
8518 }
8519
8520 static s32
8521 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
8522         struct wl_scan_results **bss_list)
8523 {
8524         struct wl_iscan_results list;
8525         struct wl_scan_results *results;
8526         struct wl_iscan_results *list_buf;
8527         s32 err = 0;
8528
8529         WL_DBG(("Enter \n"));
8530         memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
8531         list_buf = (struct wl_iscan_results *)iscan->scan_buf;
8532         results = &list_buf->results;
8533         results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
8534         results->version = 0;
8535         results->count = 0;
8536
8537         memset(&list, 0, sizeof(list));
8538         list.results.buflen = htod32(WL_ISCAN_BUF_MAX);
8539         err = wldev_iovar_getbuf(iscan->dev, "iscanresults", &list,
8540                 WL_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf,
8541                 WL_ISCAN_BUF_MAX, NULL);
8542         if (unlikely(err)) {
8543                 WL_ERR(("error (%d)\n", err));
8544                 return err;
8545         }
8546         results->buflen = dtoh32(results->buflen);
8547         results->version = dtoh32(results->version);
8548         results->count = dtoh32(results->count);
8549         WL_DBG(("results->count = %d\n", results->count));
8550         WL_DBG(("results->buflen = %d\n", results->buflen));
8551         *status = dtoh32(list_buf->status);
8552         *bss_list = results;
8553
8554         return err;
8555 }
8556
8557 static s32 wl_iscan_done(struct wl_priv *wl)
8558 {
8559         struct wl_iscan_ctrl *iscan = wl->iscan;
8560         s32 err = 0;
8561
8562         iscan->state = WL_ISCAN_STATE_IDLE;
8563         mutex_lock(&wl->usr_sync);
8564         wl_inform_bss(wl);
8565         wl_notify_iscan_complete(iscan, false);
8566         mutex_unlock(&wl->usr_sync);
8567
8568         return err;
8569 }
8570
8571 static s32 wl_iscan_pending(struct wl_priv *wl)
8572 {
8573         struct wl_iscan_ctrl *iscan = wl->iscan;
8574         s32 err = 0;
8575
8576         /* Reschedule the timer */
8577         mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms));
8578         iscan->timer_on = 1;
8579
8580         return err;
8581 }
8582
8583 static s32 wl_iscan_inprogress(struct wl_priv *wl)
8584 {
8585         struct wl_iscan_ctrl *iscan = wl->iscan;
8586         s32 err = 0;
8587
8588         mutex_lock(&wl->usr_sync);
8589         wl_inform_bss(wl);
8590         wl_run_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
8591         mutex_unlock(&wl->usr_sync);
8592         /* Reschedule the timer */
8593         mod_timer(&iscan->timer, jiffies +  msecs_to_jiffies(iscan->timer_ms));
8594         iscan->timer_on = 1;
8595
8596         return err;
8597 }
8598
8599 static s32 wl_iscan_aborted(struct wl_priv *wl)
8600 {
8601         struct wl_iscan_ctrl *iscan = wl->iscan;
8602         s32 err = 0;
8603
8604         iscan->state = WL_ISCAN_STATE_IDLE;
8605         mutex_lock(&wl->usr_sync);
8606         wl_notify_iscan_complete(iscan, true);
8607         mutex_unlock(&wl->usr_sync);
8608
8609         return err;
8610 }
8611
8612 static s32 wl_iscan_thread(void *data)
8613 {
8614         struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
8615         struct wl_priv *wl = iscan_to_wl(iscan);
8616         u32 status;
8617         int err = 0;
8618
8619         allow_signal(SIGTERM);
8620         status = WL_SCAN_RESULTS_PARTIAL;
8621         while (likely(!down_interruptible(&iscan->sync))) {
8622                 if (kthread_should_stop())
8623                         break;
8624                 if (iscan->timer_on) {
8625                         del_timer_sync(&iscan->timer);
8626                         iscan->timer_on = 0;
8627                 }
8628                 mutex_lock(&wl->usr_sync);
8629                 err = wl_get_iscan_results(iscan, &status, &wl->bss_list);
8630                 if (unlikely(err)) {
8631                         status = WL_SCAN_RESULTS_ABORTED;
8632                         WL_ERR(("Abort iscan\n"));
8633                 }
8634                 mutex_unlock(&wl->usr_sync);
8635                 iscan->iscan_handler[status] (wl);
8636         }
8637         if (iscan->timer_on) {
8638                 del_timer_sync(&iscan->timer);
8639                 iscan->timer_on = 0;
8640         }
8641         WL_DBG(("was terminated\n"));
8642
8643         return 0;
8644 }
8645
8646 static void wl_scan_timeout(unsigned long data)
8647 {
8648         wl_event_msg_t msg;
8649         struct wl_priv *wl = (struct wl_priv *)data;
8650
8651         if (!(wl->scan_request)) {
8652                 WL_ERR(("timer expired but no scan request\n"));
8653                 return;
8654         }
8655         bzero(&msg, sizeof(wl_event_msg_t));
8656         WL_ERR(("timer expired\n"));
8657         if (wl->escan_on) {
8658                 msg.event_type = hton32(WLC_E_ESCAN_RESULT);
8659                 msg.status = hton32(WLC_E_STATUS_TIMEOUT);
8660                 msg.reason = 0xFFFFFFFF;
8661                 wl_cfg80211_event(wl_to_prmry_ndev(wl), &msg, NULL);
8662         } else {
8663                 /* Need to check it try to access SDIO */
8664                 WL_ERR(("SCAN Timeout(ISCAN)\n"));
8665                 wl_notify_iscan_complete(wl_to_iscan(wl), true);
8666         }
8667 }
8668
8669 static void wl_iscan_timer(unsigned long data)
8670 {
8671         struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
8672
8673         if (iscan) {
8674                 iscan->timer_on = 0;
8675                 WL_DBG(("timer expired\n"));
8676                 wl_wakeup_iscan(iscan);
8677         }
8678 }
8679
8680 static s32 wl_invoke_iscan(struct wl_priv *wl)
8681 {
8682         struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
8683         int err = 0;
8684
8685         if (wl->iscan_on && !iscan->tsk) {
8686                 iscan->state = WL_ISCAN_STATE_IDLE;
8687                 sema_init(&iscan->sync, 0);
8688                 iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan");
8689                 if (IS_ERR(iscan->tsk)) {
8690                         WL_ERR(("Could not create iscan thread\n"));
8691                         iscan->tsk = NULL;
8692                         return -ENOMEM;
8693                 }
8694         }
8695
8696         return err;
8697 }
8698
8699 static void wl_init_iscan_handler(struct wl_iscan_ctrl *iscan)
8700 {
8701         memset(iscan->iscan_handler, 0, sizeof(iscan->iscan_handler));
8702         iscan->iscan_handler[WL_SCAN_RESULTS_SUCCESS] = wl_iscan_done;
8703         iscan->iscan_handler[WL_SCAN_RESULTS_PARTIAL] = wl_iscan_inprogress;
8704         iscan->iscan_handler[WL_SCAN_RESULTS_PENDING] = wl_iscan_pending;
8705         iscan->iscan_handler[WL_SCAN_RESULTS_ABORTED] = wl_iscan_aborted;
8706         iscan->iscan_handler[WL_SCAN_RESULTS_NO_MEM] = wl_iscan_aborted;
8707 }
8708
8709 static s32
8710 wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
8711         unsigned long state,
8712         void *ndev)
8713 {
8714         struct net_device *dev = ndev;
8715         struct wireless_dev *wdev = dev->ieee80211_ptr;
8716         struct wl_priv *wl = wlcfg_drv_priv;
8717         int refcnt = 0;
8718
8719         WL_DBG(("Enter \n"));
8720         if (!wdev || !wl || dev == wl_to_prmry_ndev(wl))
8721                 return NOTIFY_DONE;
8722         switch (state) {
8723                 case NETDEV_DOWN:
8724                 {
8725                         int max_wait_timeout = 2;
8726                         int max_wait_count = 100;
8727                         unsigned long limit = jiffies + max_wait_timeout * HZ;
8728                         while (work_pending(&wdev->cleanup_work)) {
8729                                 if (refcnt%5 == 0) {
8730                                         WL_ERR(("[NETDEV_DOWN] wait for "
8731                                                 "complete of cleanup_work"
8732                                                 " (%d th)\n", refcnt));
8733                                 }
8734                                 if (!time_before(jiffies, limit)) {
8735                                         WL_ERR(("[NETDEV_DOWN] cleanup_work"
8736                                                 " of CFG80211 is not"
8737                                                 " completed in %d sec\n",
8738                                                 max_wait_timeout));
8739                                         break;
8740                                 }
8741                                 if (refcnt >= max_wait_count) {
8742                                         WL_ERR(("[NETDEV_DOWN] cleanup_work"
8743                                                 " of CFG80211 is not"
8744                                                 " completed in %d loop\n",
8745                                                 max_wait_count));
8746                                         break;
8747                                 }
8748                                 set_current_state(TASK_INTERRUPTIBLE);
8749                                 schedule_timeout(100);
8750                                 set_current_state(TASK_RUNNING);
8751                                 refcnt++;
8752                         }
8753                         break;
8754                 }
8755
8756                 case NETDEV_UNREGISTER:
8757                         /* after calling list_del_rcu(&wdev->list) */
8758                         wl_remove_netinfo(wl, ndev);
8759                         break;
8760                 case NETDEV_GOING_DOWN:
8761                         /* At NETDEV_DOWN state, wdev_cleanup_work work will be called.
8762                         *  In front of door, the function checks
8763                         *  whether current scan is working or not.
8764                         *  If the scanning is still working, wdev_cleanup_work call WARN_ON and
8765                         *  make the scan done forcibly.
8766                         */
8767                         if (wl_get_drv_status(wl, SCANNING, dev)) {
8768                                 if (wl->escan_on) {
8769                                         wl_notify_escan_complete(wl, dev, true, true);
8770                                 }
8771                         }
8772                         break;
8773         }
8774         return NOTIFY_DONE;
8775 }
8776 static struct notifier_block wl_cfg80211_netdev_notifier = {
8777         .notifier_call = wl_cfg80211_netdev_notifier_call,
8778 };
8779
8780 static void wl_cfg80211_scan_abort(struct wl_priv *wl)
8781 {
8782         wl_scan_params_t *params = NULL;
8783         s32 params_size = 0;
8784         s32 err = BCME_OK;
8785         struct net_device *dev = wl_to_prmry_ndev(wl);
8786         if (!in_atomic()) {
8787                 /* Our scan params only need space for 1 channel and 0 ssids */
8788                 params = wl_cfg80211_scan_alloc_params(-1, 0, &params_size);
8789                 if (params == NULL) {
8790                         WL_ERR(("scan params allocation failed \n"));
8791                         err = -ENOMEM;
8792                 } else {
8793                         /* Do a scan abort to stop the driver's scan engine */
8794                         err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true);
8795                         if (err < 0) {
8796                                 WL_ERR(("scan abort  failed \n"));
8797                         }
8798                         kfree(params);
8799                 }
8800         }
8801 }
8802 static s32 wl_notify_escan_complete(struct wl_priv *wl,
8803         struct net_device *ndev,
8804         bool aborted, bool fw_abort)
8805 {
8806         s32 err = BCME_OK;
8807         unsigned long flags;
8808         struct net_device *dev;
8809
8810         WL_DBG(("Enter \n"));
8811         if (!ndev) {
8812                 WL_ERR(("ndev is null\n"));
8813                 err = BCME_ERROR;
8814                 return err;
8815         }
8816
8817         if (wl->escan_info.ndev != ndev) {
8818                 WL_ERR(("ndev is different %p %p\n", wl->escan_info.ndev, ndev));
8819                 err = BCME_ERROR;
8820                 return err;
8821         }
8822
8823         if (wl->scan_request) {
8824                 dev = wl_to_prmry_ndev(wl);
8825 #if defined(WL_ENABLE_P2P_IF)
8826                 if (wl->scan_request->dev != wl->p2p_net)
8827                         dev = wl->scan_request->dev;
8828 #endif /* WL_ENABLE_P2P_IF */
8829         }
8830         else {
8831                 WL_DBG(("wl->scan_request is NULL may be internal scan."
8832                         "doing scan_abort for ndev %p primary %p",
8833                                 ndev, wl_to_prmry_ndev(wl)));
8834                 dev = ndev;
8835         }
8836         if (fw_abort && !in_atomic()) {
8837                 wl_cfg80211_scan_abort(wl);
8838         }
8839
8840         if (timer_pending(&wl->scan_timeout))
8841                 del_timer_sync(&wl->scan_timeout);
8842 #if defined(ESCAN_RESULT_PATCH)
8843         if (likely(wl->scan_request)) {
8844                 wl->bss_list = wl_escan_get_buf(wl, aborted);
8845                 wl_inform_bss(wl);
8846         }
8847 #endif /* ESCAN_RESULT_PATCH */
8848         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
8849 #ifdef WL_SCHED_SCAN
8850         if (wl->sched_scan_req && !wl->scan_request) {
8851                 WL_PNO((">>> REPORTING SCHED SCAN RESULTS \n"));
8852                 if (!aborted)
8853                         cfg80211_sched_scan_results(wl->sched_scan_req->wiphy);
8854                 wl->sched_scan_running = FALSE;
8855                 wl->sched_scan_req = NULL;
8856         }
8857 #endif /* WL_SCHED_SCAN */
8858         if (likely(wl->scan_request)) {
8859                 cfg80211_scan_done(wl->scan_request, aborted);
8860                 wl->scan_request = NULL;
8861         }
8862         if (p2p_is_on(wl))
8863                 wl_clr_p2p_status(wl, SCANNING);
8864         wl_clr_drv_status(wl, SCANNING, dev);
8865         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
8866         return err;
8867 }
8868
8869 static s32 wl_escan_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
8870         const wl_event_msg_t *e, void *data)
8871 {
8872         s32 err = BCME_OK;
8873         s32 status = ntoh32(e->status);
8874         wl_bss_info_t *bi;
8875         wl_escan_result_t *escan_result;
8876         wl_bss_info_t *bss = NULL;
8877         wl_scan_results_t *list;
8878         wifi_p2p_ie_t * p2p_ie;
8879         struct net_device *ndev = NULL;
8880         u32 bi_length;
8881         u32 i;
8882         u8 *p2p_dev_addr = NULL;
8883
8884         WL_DBG((" enter event type : %d, status : %d \n",
8885                 ntoh32(e->event_type), ntoh32(e->status)));
8886
8887         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
8888
8889         mutex_lock(&wl->usr_sync);
8890         /* P2P SCAN is coming from primary interface */
8891         if (wl_get_p2p_status(wl, SCANNING)) {
8892                 if (wl_get_drv_status_all(wl, SENDING_ACT_FRM))
8893                         ndev = wl->afx_hdl->dev;
8894                 else
8895                         ndev = wl->escan_info.ndev;
8896
8897         }
8898         if (!ndev || !wl->escan_on ||
8899                 (!wl_get_drv_status(wl, SCANNING, ndev) &&
8900                 !wl->sched_scan_running)) {
8901                 WL_ERR(("escan is not ready ndev %p wl->escan_on %d"
8902                         " drv_status 0x%x e_type %d e_states %d\n",
8903                         ndev, wl->escan_on, wl_get_drv_status(wl, SCANNING, ndev),
8904                         ntoh32(e->event_type), ntoh32(e->status)));
8905                 goto exit;
8906         }
8907         escan_result = (wl_escan_result_t *)data;
8908
8909         if (status == WLC_E_STATUS_PARTIAL) {
8910                 WL_INFO(("WLC_E_STATUS_PARTIAL \n"));
8911                 if (!escan_result) {
8912                         WL_ERR(("Invalid escan result (NULL pointer)\n"));
8913                         goto exit;
8914                 }
8915                 if (dtoh16(escan_result->bss_count) != 1) {
8916                         WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
8917                         goto exit;
8918                 }
8919                 bi = escan_result->bss_info;
8920                 if (!bi) {
8921                         WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
8922                         goto exit;
8923                 }
8924                 bi_length = dtoh32(bi->length);
8925                 if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
8926                         WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length));
8927                         goto exit;
8928                 }
8929                 if (wl_escan_check_sync_id(status, escan_result->sync_id,
8930                         wl->escan_info.cur_sync_id) < 0)
8931                         goto exit;
8932
8933                 if (!(wl_to_wiphy(wl)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
8934                         if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
8935                                 WL_DBG(("Ignoring IBSS result\n"));
8936                                 goto exit;
8937                         }
8938                 }
8939
8940                 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
8941                         p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
8942                         if (p2p_dev_addr && !memcmp(p2p_dev_addr,
8943                                 wl->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
8944                                 s32 channel = wf_chspec_ctlchan(
8945                                         wl_chspec_driver_to_host(bi->chanspec));
8946
8947                                 if ((channel > MAXCHANNEL) || (channel <= 0))
8948                                         channel = WL_INVALID;
8949                                 else
8950                                         WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
8951                                                 " channel : %d\n",
8952                                                 MAC2STRDBG(wl->afx_hdl->tx_dst_addr.octet),
8953                                                 channel));
8954
8955                                 wl_clr_p2p_status(wl, SCANNING);
8956                                 wl->afx_hdl->peer_chan = channel;
8957                                 complete(&wl->act_frm_scan);
8958                                 goto exit;
8959                         }
8960
8961                 } else {
8962                         int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
8963                         list = wl_escan_get_buf(wl, FALSE);
8964                         if (scan_req_match(wl)) {
8965                                 /* p2p scan && allow only probe response */
8966                                 if ((wl->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
8967                                         (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
8968                                         goto exit;
8969                                 if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset,
8970                                         bi->ie_length)) == NULL) {
8971                                                 WL_ERR(("Couldn't find P2PIE in probe"
8972                                                         " response/beacon\n"));
8973                                                 goto exit;
8974                                 }
8975                         }
8976                         for (i = 0; i < list->count; i++) {
8977                                 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
8978                                         : list->bss_info;
8979
8980                                 if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
8981                                         (CHSPEC_BAND(wl_chspec_driver_to_host(bi->chanspec))
8982                                         == CHSPEC_BAND(wl_chspec_driver_to_host(bss->chanspec))) &&
8983                                         bi->SSID_len == bss->SSID_len &&
8984                                         !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
8985
8986                                         /* do not allow beacon data to update
8987                                         *the data recd from a probe response
8988                                         */
8989                                         if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) &&
8990                                                 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
8991                                                 goto exit;
8992
8993                                         WL_DBG(("%s("MACDBG"), i=%d prev: RSSI %d"
8994                                                 " flags 0x%x, new: RSSI %d flags 0x%x\n",
8995                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet), i,
8996                                                 bss->RSSI, bss->flags, bi->RSSI, bi->flags));
8997
8998                                         if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
8999                                                 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) {
9000                                                 /* preserve max RSSI if the measurements are
9001                                                 * both on-channel or both off-channel
9002                                                 */
9003                                                 WL_SCAN(("%s("MACDBG"), same onchan"
9004                                                 ", RSSI: prev %d new %d\n",
9005                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
9006                                                 bss->RSSI, bi->RSSI));
9007                                                 bi->RSSI = MAX(bss->RSSI, bi->RSSI);
9008                                         } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
9009                                                 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
9010                                                 /* preserve the on-channel rssi measurement
9011                                                 * if the new measurement is off channel
9012                                                 */
9013                                                 WL_SCAN(("%s("MACDBG"), prev onchan"
9014                                                 ", RSSI: prev %d new %d\n",
9015                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
9016                                                 bss->RSSI, bi->RSSI));
9017                                                 bi->RSSI = bss->RSSI;
9018                                                 bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
9019                                         }
9020                                         if (dtoh32(bss->length) != bi_length) {
9021                                                 u32 prev_len = dtoh32(bss->length);
9022
9023                                                 WL_SCAN(("bss info replacement"
9024                                                         " is occured(bcast:%d->probresp%d)\n",
9025                                                         bss->ie_length, bi->ie_length));
9026                                                 WL_DBG(("%s("MACDBG"), replacement!(%d -> %d)\n",
9027                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
9028                                                 prev_len, bi_length));
9029
9030                                                 if (list->buflen - prev_len + bi_length
9031                                                         > ESCAN_BUF_SIZE) {
9032                                                         WL_ERR(("Buffer is too small: keep the"
9033                                                                 " previous result of this AP\n"));
9034                                                         /* Only update RSSI */
9035                                                         bss->RSSI = bi->RSSI;
9036                                                         bss->flags |= (bi->flags
9037                                                                 & WL_BSS_FLAGS_RSSI_ONCHANNEL);
9038                                                         goto exit;
9039                                                 }
9040
9041                                                 if (i < list->count - 1) {
9042                                                         /* memory copy required by this case only */
9043                                                         memmove((u8 *)bss + bi_length,
9044                                                                 (u8 *)bss + prev_len,
9045                                                                 list->buflen - cur_len - prev_len);
9046                                                 }
9047                                                 list->buflen -= prev_len;
9048                                                 list->buflen += bi_length;
9049                                         }
9050                                         list->version = dtoh32(bi->version);
9051                                         memcpy((u8 *)bss, (u8 *)bi, bi_length);
9052                                         goto exit;
9053                                 }
9054                                 cur_len += dtoh32(bss->length);
9055                         }
9056                         if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
9057                                 WL_ERR(("Buffer is too small: ignoring\n"));
9058                                 goto exit;
9059                         }
9060
9061                         memcpy(&(((char *)list)[list->buflen]), bi, bi_length);
9062                         list->version = dtoh32(bi->version);
9063                         list->buflen += bi_length;
9064                         list->count++;
9065
9066                 }
9067
9068         }
9069         else if (status == WLC_E_STATUS_SUCCESS) {
9070 #if defined(P2P_DISCOVERY_WAR)
9071                 if (scan_req_match(wl) && !wl->p2p->vif_created) {
9072                         if (wldev_iovar_setint(wl_to_prmry_ndev(wl), "mpc", 1) < 0) {
9073                                 WL_ERR(("mpc enabling back failed\n"));
9074                         }
9075                 }
9076 #endif /* defined(P2P_DISCOVERY_WAR) */
9077                 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9078                 wl_escan_print_sync_id(status, wl->escan_info.cur_sync_id,
9079                         escan_result->sync_id);
9080
9081                 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9082                         WL_INFO(("ACTION FRAME SCAN DONE\n"));
9083                         wl_clr_p2p_status(wl, SCANNING);
9084                         wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
9085                         if (wl->afx_hdl->peer_chan == WL_INVALID)
9086                                 complete(&wl->act_frm_scan);
9087                 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
9088                         WL_INFO(("ESCAN COMPLETED\n"));
9089                         wl->bss_list = wl_escan_get_buf(wl, FALSE);
9090                         if (!scan_req_match(wl)) {
9091                                 WL_TRACE_HW4(("SCAN COMPLETED: scanned AP count=%d\n",
9092                                         wl->bss_list->count));
9093                         }
9094                         wl_inform_bss(wl);
9095                         wl_notify_escan_complete(wl, ndev, false, false);
9096                 }
9097                 wl_escan_increment_sync_id(wl, SCAN_BUF_NEXT);
9098         }
9099         else if (status == WLC_E_STATUS_ABORT) {
9100 #if defined(P2P_DISCOVERY_WAR)
9101                 if (scan_req_match(wl) && !wl->p2p->vif_created) {
9102                         if (wldev_iovar_setint(wl_to_prmry_ndev(wl), "mpc", 1) < 0) {
9103                                 WL_ERR(("mpc enabling back failed\n"));
9104                         }
9105                 }
9106 #endif /* defined(P2P_DISCOVERY_WAR) */
9107                 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9108                 wl_escan_print_sync_id(status, escan_result->sync_id,
9109                         wl->escan_info.cur_sync_id);
9110                 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9111                         WL_INFO(("ACTION FRAME SCAN DONE\n"));
9112                         wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
9113                         wl_clr_p2p_status(wl, SCANNING);
9114                         if (wl->afx_hdl->peer_chan == WL_INVALID)
9115                                 complete(&wl->act_frm_scan);
9116                 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
9117                         WL_INFO(("ESCAN ABORTED\n"));
9118                         wl->bss_list = wl_escan_get_buf(wl, TRUE);
9119                         if (!scan_req_match(wl)) {
9120                                 WL_TRACE_HW4(("SCAN ABORTED: scanned AP count=%d\n",
9121                                         wl->bss_list->count));
9122                         }
9123                         wl_inform_bss(wl);
9124                         wl_notify_escan_complete(wl, ndev, true, false);
9125                 }
9126                 wl_escan_increment_sync_id(wl, SCAN_BUF_CNT);
9127         } else if (status == WLC_E_STATUS_NEWSCAN) {
9128                 WL_ERR(("WLC_E_STATUS_NEWSCAN : scan_request[%p]\n", wl->scan_request));
9129                 WL_ERR(("sync_id[%d], bss_count[%d]\n", escan_result->sync_id,
9130                         escan_result->bss_count));
9131         } else if (status == WLC_E_STATUS_TIMEOUT) {
9132                 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", wl->scan_request));
9133                 WL_ERR(("escan_on[%d], reason[0x%x]\n", wl->escan_on, e->reason));
9134                 if (e->reason == 0xFFFFFFFF) {
9135                         wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true);
9136                 }
9137         } else {
9138                 WL_ERR(("unexpected Escan Event %d : abort\n", status));
9139                 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9140                 wl_escan_print_sync_id(status, escan_result->sync_id,
9141                         wl->escan_info.cur_sync_id);
9142                 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9143                         WL_INFO(("ACTION FRAME SCAN DONE\n"));
9144                         wl_clr_p2p_status(wl, SCANNING);
9145                         wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
9146                         if (wl->afx_hdl->peer_chan == WL_INVALID)
9147                                 complete(&wl->act_frm_scan);
9148                 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
9149                         wl->bss_list = wl_escan_get_buf(wl, TRUE);
9150                         if (!scan_req_match(wl)) {
9151                                 WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): "
9152                                         "scanned AP count=%d\n",
9153                                         wl->bss_list->count));
9154                         }
9155                         wl_inform_bss(wl);
9156                         wl_notify_escan_complete(wl, ndev, true, false);
9157                 }
9158                 wl_escan_increment_sync_id(wl, 2);
9159         }
9160 exit:
9161         mutex_unlock(&wl->usr_sync);
9162         return err;
9163 }
9164
9165 static void wl_cfg80211_concurrent_roam(struct wl_priv *wl, int enable)
9166 {
9167         u32 connected_cnt  = wl_get_drv_status_all(wl, CONNECTED);
9168         struct net_info *iter, *next;
9169         int err;
9170
9171         if (!wl->roamoff_on_concurrent)
9172                 return;
9173         if (enable && connected_cnt > 1) {
9174                 for_each_ndev(wl, iter, next) {
9175                         /* Save the current roam setting */
9176                         if ((err = wldev_iovar_getint(iter->ndev, "roam_off",
9177                                 (s32 *)&iter->roam_off)) != BCME_OK) {
9178                                 WL_ERR(("%s:Failed to get current roam setting err %d\n",
9179                                         iter->ndev->name, err));
9180                                 continue;
9181                         }
9182                         if ((err = wldev_iovar_setint(iter->ndev, "roam_off", 1)) != BCME_OK) {
9183                                 WL_ERR((" %s:failed to set roam_off : %d\n",
9184                                         iter->ndev->name, err));
9185                         }
9186                 }
9187         }
9188         else if (!enable) {
9189                 for_each_ndev(wl, iter, next) {
9190                         if (iter->roam_off != WL_INVALID) {
9191                                 if ((err = wldev_iovar_setint(iter->ndev, "roam_off",
9192                                         iter->roam_off)) == BCME_OK)
9193                                         iter->roam_off = WL_INVALID;
9194                                 else {
9195                                         WL_ERR((" %s:failed to set roam_off : %d\n",
9196                                                 iter->ndev->name, err));
9197                                 }
9198                         }
9199                 }
9200         }
9201         return;
9202 }
9203
9204 static void wl_cfg80211_determine_vsdb_mode(struct wl_priv *wl)
9205 {
9206         struct net_info *iter, *next;
9207         u32 ctl_chan = 0;
9208         u32 chanspec = 0;
9209         u32 pre_ctl_chan = 0;
9210         u32 connected_cnt  = wl_get_drv_status_all(wl, CONNECTED);
9211         wl->vsdb_mode = false;
9212
9213         if (connected_cnt <= 1)  {
9214                 return;
9215         }
9216         for_each_ndev(wl, iter, next) {
9217                 chanspec = 0;
9218                 ctl_chan = 0;
9219                 if (wl_get_drv_status(wl, CONNECTED, iter->ndev)) {
9220                         if (wldev_iovar_getint(iter->ndev, "chanspec",
9221                                 (s32 *)&chanspec) == BCME_OK) {
9222                                 chanspec = wl_chspec_driver_to_host(chanspec);
9223                                 ctl_chan = wf_chspec_ctlchan(chanspec);
9224                                 wl_update_prof(wl, iter->ndev, NULL,
9225                                         &ctl_chan, WL_PROF_CHAN);
9226                         }
9227                         if (!wl->vsdb_mode) {
9228                                 if (!pre_ctl_chan && ctl_chan)
9229                                         pre_ctl_chan = ctl_chan;
9230                                 else if (pre_ctl_chan && (pre_ctl_chan != ctl_chan)) {
9231                                         wl->vsdb_mode = true;
9232                                 }
9233                         }
9234                 }
9235         }
9236         WL_ERR(("%s concurrency is enabled\n", wl->vsdb_mode ? "Multi Channel" : "Same Channel"));
9237         return;
9238 }
9239
9240 static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info,
9241         enum wl_status state, bool set)
9242 {
9243         s32 pm = PM_FAST;
9244         s32 err = BCME_OK;
9245         u32 mode;
9246         u32 chan = 0;
9247         struct net_info *iter, *next;
9248         struct net_device *primary_dev = wl_to_prmry_ndev(wl);
9249         WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n",
9250                 state, set, _net_info->pm_restore, _net_info->ndev->name));
9251
9252         if (state != WL_STATUS_CONNECTED)
9253                 return 0;
9254         mode = wl_get_mode_by_netdev(wl, _net_info->ndev);
9255         if (set) {
9256                 wl_cfg80211_concurrent_roam(wl, 1);
9257
9258                 if (mode == WL_MODE_AP) {
9259
9260                         if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false))
9261                                 WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
9262                 }
9263                 wl_cfg80211_determine_vsdb_mode(wl);
9264                 if (wl->vsdb_mode || _net_info->pm_block) {
9265                         /* Delete pm_enable_work */
9266                         wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_MAINTAIN);
9267                         /* save PM_FAST in _net_info to restore this
9268                          * if _net_info->pm_block is false
9269                          */
9270                         if (!_net_info->pm_block && (mode == WL_MODE_BSS)) {
9271                                 _net_info->pm = PM_FAST;
9272                                 _net_info->pm_restore = true;
9273                         }
9274                         pm = PM_OFF;
9275                         down_read(&wl->netif_sem);
9276                         for_each_ndev(wl, iter, next) {
9277                                 if (iter->pm_restore)
9278                                         continue;
9279                                 /* Save the current power mode */
9280                                 err = wldev_ioctl(iter->ndev, WLC_GET_PM, &iter->pm,
9281                                         sizeof(iter->pm), false);
9282                                 WL_DBG(("%s:power save %s\n", iter->ndev->name,
9283                                         iter->pm ? "enabled" : "disabled"));
9284                                 if (!err && iter->pm) {
9285                                         iter->pm_restore = true;
9286                                 }
9287
9288                         }
9289                         for_each_ndev(wl, iter, next) {
9290                                 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm,
9291                                         sizeof(pm), true)) != 0) {
9292                                         if (err == -ENODEV)
9293                                                 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
9294                                         else
9295                                                 WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
9296                                 } else
9297                                         iter->ndev->ieee80211_ptr->ps = false;
9298                         }
9299                         up_read(&wl->netif_sem);
9300                 } else {
9301                         /* add PM Enable timer to go to power save mode
9302                          * if supplicant control pm mode, it will be cleared or
9303                          * updated by wl_cfg80211_set_power_mgmt() if not - for static IP & HW4 P2P,
9304                          * PM will be configured when timer expired
9305                          */
9306
9307                         /*
9308                          * before calling pm_enable_timer, we need to set PM -1 for all ndev
9309                          */
9310                         pm = PM_OFF;
9311                         down_read(&wl->netif_sem);
9312                         for_each_ndev(wl, iter, next) {
9313                                 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm,
9314                                         sizeof(pm), true)) != 0) {
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                                 }
9320                         }
9321                         up_read(&wl->netif_sem);
9322
9323                         if (wl->pm_enable_work_on) {
9324                                 wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_DEL);
9325                         }
9326
9327                         wl->pm_enable_work_on = true;
9328                         wl_add_remove_pm_enable_work(wl, TRUE, WL_HANDLER_NOTUSE);
9329                 }
9330         }
9331          else { /* clear */
9332                 chan = 0;
9333                 /* clear chan information when the net device is disconnected */
9334                 wl_update_prof(wl, _net_info->ndev, NULL, &chan, WL_PROF_CHAN);
9335                 wl_cfg80211_determine_vsdb_mode(wl);
9336                 down_read(&wl->netif_sem);
9337                 for_each_ndev(wl, iter, next) {
9338                         if (iter->pm_restore && iter->pm) {
9339                                 WL_DBG(("%s:restoring power save %s\n",
9340                                         iter->ndev->name, (iter->pm ? "enabled" : "disabled")));
9341                                 err = wldev_ioctl(iter->ndev,
9342                                         WLC_SET_PM, &iter->pm, sizeof(iter->pm), true);
9343                                 if (unlikely(err)) {
9344                                         if (err == -ENODEV)
9345                                                 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
9346                                         else
9347                                                 WL_ERR(("%s:error(%d)\n", iter->ndev->name, err));
9348                                         break;
9349                                 }
9350                                 iter->pm_restore = 0;
9351                                 iter->ndev->ieee80211_ptr->ps = true;
9352                         }
9353                 }
9354                 up_read(&wl->netif_sem);
9355                 wl_cfg80211_concurrent_roam(wl, 0);
9356         }
9357         return err;
9358 }
9359 static s32 wl_init_scan(struct wl_priv *wl)
9360 {
9361         struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
9362         int err = 0;
9363
9364         if (wl->iscan_on) {
9365                 iscan->dev = wl_to_prmry_ndev(wl);
9366                 iscan->state = WL_ISCAN_STATE_IDLE;
9367                 wl_init_iscan_handler(iscan);
9368                 iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
9369                 init_timer(&iscan->timer);
9370                 iscan->timer.data = (unsigned long) iscan;
9371                 iscan->timer.function = wl_iscan_timer;
9372                 sema_init(&iscan->sync, 0);
9373                 iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan");
9374                 if (IS_ERR(iscan->tsk)) {
9375                         WL_ERR(("Could not create iscan thread\n"));
9376                         iscan->tsk = NULL;
9377                         return -ENOMEM;
9378                 }
9379                 iscan->data = wl;
9380         } else if (wl->escan_on) {
9381                 wl->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
9382                 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9383                 wl_escan_init_sync_id(wl);
9384         }
9385         /* Init scan_timeout timer */
9386         init_timer(&wl->scan_timeout);
9387         wl->scan_timeout.data = (unsigned long) wl;
9388         wl->scan_timeout.function = wl_scan_timeout;
9389
9390         return err;
9391 }
9392
9393 static void wl_dealloc_netinfo(struct work_struct *work)
9394 {
9395         struct net_info *_net_info, *next;
9396         struct wl_priv *wl = container_of(work, struct wl_priv, dealloc_work);
9397
9398         down_write(&wl->netif_sem);
9399         list_for_each_entry_safe(_net_info, next, &wl->dealloc_list, list) {
9400                 list_del(&_net_info->list);
9401                 if (_net_info->wdev) {
9402                         flush_work(&_net_info->wdev->cleanup_work);
9403                         WARN_ON(work_pending(&_net_info->wdev->cleanup_work));
9404                         kfree(_net_info->wdev);
9405                 }
9406                 kfree(_net_info);
9407         }
9408         up_write(&wl->netif_sem);
9409 }
9410
9411 static s32 wl_init_priv(struct wl_priv *wl)
9412 {
9413         struct wiphy *wiphy = wl_to_wiphy(wl);
9414         struct net_device *ndev = wl_to_prmry_ndev(wl);
9415         s32 err = 0;
9416
9417         wl->scan_request = NULL;
9418         wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
9419         wl->iscan_on = false;
9420         wl->escan_on = true;
9421         wl->roam_on = false;
9422         wl->iscan_kickstart = false;
9423         wl->active_scan = true;
9424         wl->rf_blocked = false;
9425         wl->vsdb_mode = false;
9426         wl->wlfc_on = false;
9427         wl->roamoff_on_concurrent = true;
9428         /* register interested state */
9429         set_bit(WL_STATUS_CONNECTED, &wl->interrested_state);
9430         spin_lock_init(&wl->cfgdrv_lock);
9431         mutex_init(&wl->ioctl_buf_sync);
9432         init_rwsem(&wl->netif_sem);
9433         init_waitqueue_head(&wl->netif_change_event);
9434         init_completion(&wl->send_af_done);
9435         init_completion(&wl->iface_disable);
9436         wl_init_eq(wl);
9437         err = wl_init_priv_mem(wl);
9438         if (err)
9439                 return err;
9440         if (wl_create_event_handler(wl))
9441                 return -ENOMEM;
9442         wl_init_event_handler(wl);
9443         mutex_init(&wl->usr_sync);
9444         mutex_init(&wl->event_sync);
9445         err = wl_init_scan(wl);
9446         if (err)
9447                 return err;
9448         wl_init_conf(wl->conf);
9449         wl_init_prof(wl, ndev);
9450         wl_link_down(wl);
9451         DNGL_FUNC(dhd_cfg80211_init, (wl));
9452         INIT_LIST_HEAD(&wl->dealloc_list);
9453         INIT_WORK(&wl->dealloc_work, wl_dealloc_netinfo);
9454
9455         return err;
9456 }
9457
9458 static void wl_deinit_priv(struct wl_priv *wl)
9459 {
9460         DNGL_FUNC(dhd_cfg80211_deinit, (wl));
9461         wl_destroy_event_handler(wl);
9462         wl_flush_eq(wl);
9463         wl_link_down(wl);
9464         del_timer_sync(&wl->scan_timeout);
9465         wl_term_iscan(wl);
9466         wl_deinit_priv_mem(wl);
9467         unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
9468 }
9469
9470 #if defined(WL_ENABLE_P2P_IF)
9471 static s32 wl_cfg80211_attach_p2p(void)
9472 {
9473         struct wl_priv *wl = wlcfg_drv_priv;
9474
9475         WL_TRACE(("Enter \n"));
9476
9477         if (wl_cfgp2p_register_ndev(wl) < 0) {
9478                 WL_ERR(("P2P attach failed. \n"));
9479                 return -ENODEV;
9480         }
9481
9482         return 0;
9483 }
9484
9485 static s32  wl_cfg80211_detach_p2p(void)
9486 {
9487         struct wl_priv *wl = wlcfg_drv_priv;
9488         struct wireless_dev *wdev;
9489
9490         WL_DBG(("Enter \n"));
9491         if (!wl) {
9492                 WL_ERR(("Invalid Ptr\n"));
9493                 return -EINVAL;
9494         } else
9495                 wdev = wl->p2p_wdev;
9496
9497         if (!wdev) {
9498                 WL_ERR(("Invalid Ptr\n"));
9499                 return -EINVAL;
9500         }
9501
9502         wl_cfgp2p_unregister_ndev(wl);
9503
9504         wl->p2p_wdev = NULL;
9505         wl->p2p_net = NULL;
9506         WL_DBG(("Freeing 0x%08x \n", (unsigned int)wdev));
9507         kfree(wdev);
9508
9509         return 0;
9510 }
9511 #endif /* WL_ENABLE_P2P_IF */
9512
9513 s32 wl_cfg80211_attach_post(struct net_device *ndev)
9514 {
9515         struct wl_priv * wl = NULL;
9516         s32 err = 0;
9517         WL_TRACE(("In\n"));
9518         if (unlikely(!ndev)) {
9519                 WL_ERR(("ndev is invaild\n"));
9520                 return -ENODEV;
9521         }
9522         wl = wlcfg_drv_priv;
9523         if (unlikely(!wl)) {
9524                 WL_ERR(("wl is invaild\n"));
9525                 return -EINVAL;
9526         }
9527         if (!wl_get_drv_status(wl, READY, ndev)) {
9528                         if (wl->wdev && wl_cfgp2p_supported(wl, ndev)) {
9529 #if !defined(WL_ENABLE_P2P_IF)
9530                                         wl->wdev->wiphy->interface_modes |=
9531                                         (BIT(NL80211_IFTYPE_P2P_CLIENT)|
9532                                         BIT(NL80211_IFTYPE_P2P_GO));
9533 #endif /* !WL_ENABLE_P2P_IF */
9534                                 if ((err = wl_cfgp2p_init_priv(wl)) != 0)
9535                                         goto fail;
9536
9537 #if defined(WL_ENABLE_P2P_IF)
9538                                 if (wl->p2p_net) {
9539                                         /* Update MAC addr for p2p0 interface here. */
9540                                         memcpy(wl->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN);
9541                                         wl->p2p_net->dev_addr[0] |= 0x02;
9542                                         WL_ERR(("%s: p2p_dev_addr="MACDBG "\n",
9543                                                 wl->p2p_net->name,
9544                                                 MAC2STRDBG(wl->p2p_net->dev_addr)));
9545                                 } else {
9546                                         WL_ERR(("p2p_net not yet populated."
9547                                         " Couldn't update the MAC Address for p2p0 \n"));
9548                                         return -ENODEV;
9549                                 }
9550 #endif /* WL_ENABLE_P2P_IF */
9551
9552                                 wl->p2p_supported = true;
9553                         }
9554                 }
9555         wl_set_drv_status(wl, READY, ndev);
9556 fail:
9557         return err;
9558 }
9559
9560 s32 wl_cfg80211_attach(struct net_device *ndev, void *data)
9561 {
9562         struct wireless_dev *wdev;
9563         struct wl_priv *wl;
9564         s32 err = 0;
9565         struct device *dev;
9566
9567         WL_TRACE(("In\n"));
9568         if (!ndev) {
9569                 WL_ERR(("ndev is invaild\n"));
9570                 return -ENODEV;
9571         }
9572         WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev()));
9573         dev = wl_cfg80211_get_parent_dev();
9574
9575         wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
9576         if (unlikely(!wdev)) {
9577                 WL_ERR(("Could not allocate wireless device\n"));
9578                 return -ENOMEM;
9579         }
9580         err = wl_setup_wiphy(wdev, dev, data);
9581         if (unlikely(err)) {
9582                 kfree(wdev);
9583                 return -ENOMEM;
9584         }
9585         wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
9586         wl = (struct wl_priv *)wiphy_priv(wdev->wiphy);
9587         wl->wdev = wdev;
9588         wl->pub = data;
9589         INIT_LIST_HEAD(&wl->net_list);
9590         ndev->ieee80211_ptr = wdev;
9591         SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
9592         wdev->netdev = ndev;
9593         wl->state_notifier = wl_notifier_change_state;
9594         err = wl_alloc_netinfo(wl, ndev, wdev, WL_MODE_BSS, PM_ENABLE);
9595         if (err) {
9596                 WL_ERR(("Failed to alloc net_info (%d)\n", err));
9597                 goto cfg80211_attach_out;
9598         }
9599         err = wl_init_priv(wl);
9600         if (err) {
9601                 WL_ERR(("Failed to init iwm_priv (%d)\n", err));
9602                 goto cfg80211_attach_out;
9603         }
9604
9605         err = wl_setup_rfkill(wl, TRUE);
9606         if (err) {
9607                 WL_ERR(("Failed to setup rfkill %d\n", err));
9608                 goto cfg80211_attach_out;
9609         }
9610 #ifdef DEBUGFS_CFG80211
9611         err = wl_setup_debugfs(wl);
9612         if (err) {
9613                 WL_ERR(("Failed to setup debugfs %d\n", err));
9614                 goto cfg80211_attach_out;
9615         }
9616 #endif
9617         err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier);
9618         if (err) {
9619                 WL_ERR(("Failed to register notifierl %d\n", err));
9620                 goto cfg80211_attach_out;
9621         }
9622 #if defined(COEX_DHCP)
9623         err = wl_cfg80211_btcoex_init(wl);
9624         if (err)
9625                 goto cfg80211_attach_out;
9626 #endif 
9627
9628         wlcfg_drv_priv = wl;
9629
9630 #if defined(WL_ENABLE_P2P_IF)
9631         err = wl_cfg80211_attach_p2p();
9632         if (err)
9633                 goto cfg80211_attach_out;
9634 #endif /* WL_ENABLE_P2P_IF */
9635
9636         return err;
9637
9638 cfg80211_attach_out:
9639         wl_setup_rfkill(wl, FALSE);
9640         wl_free_wdev(wl);
9641         return err;
9642 }
9643
9644 void wl_cfg80211_detach(void *para)
9645 {
9646         struct wl_priv *wl;
9647
9648         (void)para;
9649         wl = wlcfg_drv_priv;
9650
9651         WL_TRACE(("In\n"));
9652
9653 #if defined(COEX_DHCP)
9654         wl_cfg80211_btcoex_deinit(wl);
9655 #endif 
9656
9657         wl_setup_rfkill(wl, FALSE);
9658 #ifdef DEBUGFS_CFG80211
9659         wl_free_debugfs(wl);
9660 #endif
9661         if (wl->p2p_supported) {
9662                 if (timer_pending(&wl->p2p->listen_timer))
9663                         del_timer_sync(&wl->p2p->listen_timer);
9664                 wl_cfgp2p_deinit_priv(wl);
9665         }
9666
9667 #if defined(WL_CFG80211_P2P_DEV_IF)
9668         wl_cfgp2p_del_p2p_disc_if(wl->p2p_wdev);
9669 #elif defined(WL_ENABLE_P2P_IF)
9670         wl_cfg80211_detach_p2p();
9671 #endif /* WL_CFG80211_P2P_DEV_IF */
9672
9673         wl_cfg80211_ibss_vsie_free(wl);
9674         wl_deinit_priv(wl);
9675         wlcfg_drv_priv = NULL;
9676         wl_cfg80211_clear_parent_dev();
9677         wl_free_wdev(wl);
9678          /* PLEASE do NOT call any function after wl_free_wdev, the driver's private structure "wl",
9679           * which is the private part of wiphy, has been freed in wl_free_wdev !!!!!!!!!!!
9680           */
9681 }
9682
9683 static void wl_wakeup_event(struct wl_priv *wl)
9684 {
9685         if (wl->event_tsk.thr_pid >= 0) {
9686                 DHD_OS_WAKE_LOCK(wl->pub);
9687                 up(&wl->event_tsk.sema);
9688         }
9689 }
9690
9691 #if (defined(WL_CFG80211_P2P_DEV_IF) || defined(WL_ENABLE_P2P_IF))
9692 static int wl_is_p2p_event(struct wl_event_q *e)
9693 {
9694         switch (e->etype) {
9695         /* We have to seperate out the P2P events received
9696          * on primary interface so that it can be send up
9697          * via p2p0 interface.
9698         */
9699         case WLC_E_P2P_PROBREQ_MSG:
9700         case WLC_E_P2P_DISC_LISTEN_COMPLETE:
9701         case WLC_E_ACTION_FRAME_RX:
9702         case WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE:
9703         case WLC_E_ACTION_FRAME_COMPLETE:
9704
9705                 if (e->emsg.ifidx != 0) {
9706                         WL_TRACE(("P2P event(%d) on virtual interface(ifidx:%d)\n",
9707                                 e->etype, e->emsg.ifidx));
9708                         /* We are only bothered about the P2P events received
9709                          * on primary interface. For rest of them return false
9710                          * so that it is sent over the interface corresponding
9711                          * to the ifidx.
9712                          */
9713                         return FALSE;
9714                 } else {
9715                         WL_TRACE(("P2P event(%d) on interface(ifidx:%d)\n",
9716                                 e->etype, e->emsg.ifidx));
9717                         return TRUE;
9718                 }
9719                 break;
9720
9721         default:
9722                 WL_TRACE(("NON-P2P event(%d) on interface(ifidx:%d)\n",
9723                         e->etype, e->emsg.ifidx));
9724                 return FALSE;
9725         }
9726 }
9727 #endif /* BCMDONGLEHOST && (WL_CFG80211_P2P_DEV_IF || WL_ENABLE_P2P_IF) */
9728
9729 static s32 wl_event_handler(void *data)
9730 {
9731         struct wl_priv *wl = NULL;
9732         struct wl_event_q *e;
9733         tsk_ctl_t *tsk = (tsk_ctl_t *)data;
9734         bcm_struct_cfgdev *cfgdev = NULL;
9735         struct net_device *netdev;
9736
9737         wl = (struct wl_priv *)tsk->parent;
9738
9739         WL_ERR(("tsk Enter, tsk = 0x%08x\n", (unsigned int)tsk));
9740
9741         while (down_interruptible (&tsk->sema) == 0) {
9742                 SMP_RD_BARRIER_DEPENDS();
9743                 if (tsk->terminated)
9744                         break;
9745                 while ((e = wl_deq_event(wl))) {
9746                         WL_DBG(("event type (%d), if idx: %d\n", e->etype, e->emsg.ifidx));
9747                         /* All P2P device address related events comes on primary interface since
9748                          * there is no corresponding bsscfg for P2P interface. Map it to p2p0
9749                          * interface.
9750                          */
9751 #if defined(WL_CFG80211_P2P_DEV_IF)
9752                         if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_wdev)) {
9753                                 cfgdev = wl_to_p2p_wdev(wl);
9754                         } else {
9755                                 netdev = dhd_idx2net((struct dhd_pub *)(wl->pub), e->emsg.ifidx);
9756                                 if (netdev)
9757                                         cfgdev = ndev_to_wdev(netdev);
9758                         }
9759 #elif defined(WL_ENABLE_P2P_IF)
9760                         if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_net)) {
9761                                 cfgdev = wl->p2p_net;
9762                         } else {
9763                                 cfgdev = dhd_idx2net((struct dhd_pub *)(wl->pub),
9764                                         e->emsg.ifidx);
9765                         }
9766 #endif /* WL_CFG80211_P2P_DEV_IF */
9767
9768                         if (!cfgdev) {
9769 #if defined(WL_CFG80211_P2P_DEV_IF)
9770                                 cfgdev = wl_to_prmry_wdev(wl);
9771 #elif defined(WL_ENABLE_P2P_IF)
9772                                 cfgdev = wl_to_prmry_ndev(wl);
9773 #endif /* WL_CFG80211_P2P_DEV_IF */
9774                         }
9775                         if (e->etype < WLC_E_LAST && wl->evt_handler[e->etype]) {
9776                                 wl->evt_handler[e->etype] (wl, cfgdev, &e->emsg, e->edata);
9777                         } else {
9778                                 WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
9779                         }
9780                         wl_put_event(e);
9781                 }
9782                 DHD_OS_WAKE_UNLOCK(wl->pub);
9783         }
9784         WL_ERR(("was terminated\n"));
9785         complete_and_exit(&tsk->completed, 0);
9786         return 0;
9787 }
9788
9789 void
9790 wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
9791 {
9792         u32 event_type = ntoh32(e->event_type);
9793         struct wl_priv *wl = wlcfg_drv_priv;
9794
9795 #if (WL_DBG_LEVEL > 0)
9796         s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
9797             wl_dbg_estr[event_type] : (s8 *) "Unknown";
9798         WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
9799 #endif /* (WL_DBG_LEVEL > 0) */
9800
9801         if (event_type == WLC_E_PFN_NET_FOUND) {
9802                 WL_DBG((" PNOEVENT: PNO_NET_FOUND\n"));
9803         }
9804         else if (event_type == WLC_E_PFN_NET_LOST) {
9805                 WL_DBG((" PNOEVENT: PNO_NET_LOST\n"));
9806         }
9807
9808         if (likely(!wl_enq_event(wl, ndev, event_type, e, data)))
9809                 wl_wakeup_event(wl);
9810 }
9811
9812 static void wl_init_eq(struct wl_priv *wl)
9813 {
9814         wl_init_eq_lock(wl);
9815         INIT_LIST_HEAD(&wl->eq_list);
9816 }
9817
9818 static void wl_flush_eq(struct wl_priv *wl)
9819 {
9820         struct wl_event_q *e;
9821         unsigned long flags;
9822
9823         flags = wl_lock_eq(wl);
9824         while (!list_empty(&wl->eq_list)) {
9825                 e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
9826                 list_del(&e->eq_list);
9827                 kfree(e);
9828         }
9829         wl_unlock_eq(wl, flags);
9830 }
9831
9832 /*
9833 * retrieve first queued event from head
9834 */
9835
9836 static struct wl_event_q *wl_deq_event(struct wl_priv *wl)
9837 {
9838         struct wl_event_q *e = NULL;
9839         unsigned long flags;
9840
9841         flags = wl_lock_eq(wl);
9842         if (likely(!list_empty(&wl->eq_list))) {
9843                 e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
9844                 list_del(&e->eq_list);
9845         }
9846         wl_unlock_eq(wl, flags);
9847
9848         return e;
9849 }
9850
9851 /*
9852  * push event to tail of the queue
9853  */
9854
9855 static s32
9856 wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 event, const wl_event_msg_t *msg,
9857         void *data)
9858 {
9859         struct wl_event_q *e;
9860         s32 err = 0;
9861         uint32 evtq_size;
9862         uint32 data_len;
9863         unsigned long flags;
9864         gfp_t aflags;
9865
9866         data_len = 0;
9867         if (data)
9868                 data_len = ntoh32(msg->datalen);
9869         evtq_size = sizeof(struct wl_event_q) + data_len;
9870         aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
9871         e = kzalloc(evtq_size, aflags);
9872         if (unlikely(!e)) {
9873                 WL_ERR(("event alloc failed\n"));
9874                 return -ENOMEM;
9875         }
9876         e->etype = event;
9877         memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
9878         if (data)
9879                 memcpy(e->edata, data, data_len);
9880         flags = wl_lock_eq(wl);
9881         list_add_tail(&e->eq_list, &wl->eq_list);
9882         wl_unlock_eq(wl, flags);
9883
9884         return err;
9885 }
9886
9887 static void wl_put_event(struct wl_event_q *e)
9888 {
9889         kfree(e);
9890 }
9891
9892 static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype)
9893 {
9894         s32 infra = 0;
9895         s32 err = 0;
9896         s32 mode = 0;
9897         switch (iftype) {
9898         case NL80211_IFTYPE_MONITOR:
9899         case NL80211_IFTYPE_WDS:
9900                 WL_ERR(("type (%d) : currently we do not support this mode\n",
9901                         iftype));
9902                 err = -EINVAL;
9903                 return err;
9904         case NL80211_IFTYPE_ADHOC:
9905                 mode = WL_MODE_IBSS;
9906                 break;
9907         case NL80211_IFTYPE_STATION:
9908         case NL80211_IFTYPE_P2P_CLIENT:
9909                 mode = WL_MODE_BSS;
9910                 infra = 1;
9911                 break;
9912         case NL80211_IFTYPE_AP:
9913         case NL80211_IFTYPE_P2P_GO:
9914                 mode = WL_MODE_AP;
9915                 infra = 1;
9916                 break;
9917         default:
9918                 err = -EINVAL;
9919                 WL_ERR(("invalid type (%d)\n", iftype));
9920                 return err;
9921         }
9922         infra = htod32(infra);
9923         err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true);
9924         if (unlikely(err)) {
9925                 WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
9926                 return err;
9927         }
9928
9929         wl_set_mode_by_netdev(wl, ndev, mode);
9930
9931         return 0;
9932 }
9933
9934 void wl_cfg80211_add_to_eventbuffer(struct wl_eventmsg_buf *ev, u16 event, bool set)
9935 {
9936         if (!ev || (event > WLC_E_LAST))
9937                 return;
9938
9939         if (ev->num < MAX_EVENT_BUF_NUM) {
9940                 ev->event[ev->num].type = event;
9941                 ev->event[ev->num].set = set;
9942                 ev->num++;
9943         } else {
9944                 WL_ERR(("evenbuffer doesn't support > %u events. Update"
9945                         " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM));
9946                 ASSERT(0);
9947         }
9948 }
9949
9950 s32 wl_cfg80211_apply_eventbuffer(
9951         struct net_device *ndev,
9952         struct wl_priv *wl,
9953         wl_eventmsg_buf_t *ev)
9954 {
9955         char eventmask[WL_EVENTING_MASK_LEN];
9956         int i, ret = 0;
9957         s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
9958
9959         if (!ev || (!ev->num))
9960                 return -EINVAL;
9961
9962         mutex_lock(&wl->event_sync);
9963
9964         /* Read event_msgs mask */
9965         bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
9966                 sizeof(iovbuf));
9967         ret = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
9968         if (unlikely(ret)) {
9969                 WL_ERR(("Get event_msgs error (%d)\n", ret));
9970                 goto exit;
9971         }
9972         memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
9973
9974         /* apply the set bits */
9975         for (i = 0; i < ev->num; i++) {
9976                 if (ev->event[i].set)
9977                         setbit(eventmask, ev->event[i].type);
9978                 else
9979                         clrbit(eventmask, ev->event[i].type);
9980         }
9981
9982         /* Write updated Event mask */
9983         bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
9984                 sizeof(iovbuf));
9985         ret = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
9986         if (unlikely(ret)) {
9987                 WL_ERR(("Set event_msgs error (%d)\n", ret));
9988         }
9989
9990 exit:
9991         mutex_unlock(&wl->event_sync);
9992         return ret;
9993 }
9994
9995 s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add)
9996 {
9997         s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
9998         s8 eventmask[WL_EVENTING_MASK_LEN];
9999         s32 err = 0;
10000         struct wl_priv *wl = wlcfg_drv_priv;
10001
10002         if (!ndev || !wl)
10003                 return -ENODEV;
10004
10005         mutex_lock(&wl->event_sync);
10006
10007         /* Setup event_msgs */
10008         bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
10009                 sizeof(iovbuf));
10010         err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
10011         if (unlikely(err)) {
10012                 WL_ERR(("Get event_msgs error (%d)\n", err));
10013                 goto eventmsg_out;
10014         }
10015         memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
10016         if (add) {
10017                 setbit(eventmask, event);
10018         } else {
10019                 clrbit(eventmask, event);
10020         }
10021         bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
10022                 sizeof(iovbuf));
10023         err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
10024         if (unlikely(err)) {
10025                 WL_ERR(("Set event_msgs error (%d)\n", err));
10026                 goto eventmsg_out;
10027         }
10028
10029 eventmsg_out:
10030         mutex_unlock(&wl->event_sync);
10031         return err;
10032 }
10033
10034 static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap)
10035 {
10036         struct net_device *dev = wl_to_prmry_ndev(wl);
10037         struct ieee80211_channel *band_chan_arr = NULL;
10038         wl_uint32_list_t *list;
10039         u32 i, j, index, n_2g, n_5g, band, channel, array_size;
10040         u32 *n_cnt = NULL;
10041         chanspec_t c = 0;
10042         s32 err = BCME_OK;
10043         bool update;
10044         bool ht40_allowed;
10045         u8 *pbuf = NULL;
10046         bool dfs_radar_disabled = FALSE;
10047
10048 #define LOCAL_BUF_LEN 1024
10049         pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL);
10050
10051         if (pbuf == NULL) {
10052                 WL_ERR(("failed to allocate local buf\n"));
10053                 return -ENOMEM;
10054         }
10055         list = (wl_uint32_list_t *)(void *)pbuf;
10056         list->count = htod32(WL_NUMCHANSPECS);
10057
10058
10059         err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
10060                 0, pbuf, LOCAL_BUF_LEN, 0, &wl->ioctl_buf_sync);
10061         if (err != 0) {
10062                 WL_ERR(("get chanspecs failed with %d\n", err));
10063                 kfree(pbuf);
10064                 return err;
10065         }
10066 #undef LOCAL_BUF_LEN
10067
10068         list = (wl_uint32_list_t *)(void *)pbuf;
10069         band = array_size = n_2g = n_5g = 0;
10070         for (i = 0; i < dtoh32(list->count); i++) {
10071                 index = 0;
10072                 update = false;
10073                 ht40_allowed = false;
10074                 c = (chanspec_t)dtoh32(list->element[i]);
10075                 c = wl_chspec_driver_to_host(c);
10076                 channel = CHSPEC_CHANNEL(c);
10077                 if (CHSPEC_IS40(c)) {
10078                         if (CHSPEC_SB_UPPER(c))
10079                                 channel += CH_10MHZ_APART;
10080                         else
10081                                 channel -= CH_10MHZ_APART;
10082                 } else if (CHSPEC_IS80(c)) {
10083                         WL_DBG(("HT80 center channel : %d\n", channel));
10084                         continue;
10085                 }
10086                 if (CHSPEC_IS2G(c) && (channel >= CH_MIN_2G_CHANNEL) &&
10087                         (channel <= CH_MAX_2G_CHANNEL)) {
10088                         band_chan_arr = __wl_2ghz_channels;
10089                         array_size = ARRAYSIZE(__wl_2ghz_channels);
10090                         n_cnt = &n_2g;
10091                         band = IEEE80211_BAND_2GHZ;
10092                         ht40_allowed = (bw_cap  == WLC_N_BW_40ALL)? true : false;
10093                 } else if (CHSPEC_IS5G(c) && channel >= CH_MIN_5G_CHANNEL) {
10094                         band_chan_arr = __wl_5ghz_a_channels;
10095                         array_size = ARRAYSIZE(__wl_5ghz_a_channels);
10096                         n_cnt = &n_5g;
10097                         band = IEEE80211_BAND_5GHZ;
10098                         ht40_allowed = (bw_cap  == WLC_N_BW_20ALL)? false : true;
10099                 } else {
10100                         WL_ERR(("Invalid channel Sepc. 0x%x.\n", c));
10101                         continue;
10102                 }
10103                 if (!ht40_allowed && CHSPEC_IS40(c))
10104                         continue;
10105                 for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
10106                         if (band_chan_arr[j].hw_value == channel) {
10107                                 update = true;
10108                                 break;
10109                         }
10110                 }
10111                 if (update)
10112                         index = j;
10113                 else
10114                         index = *n_cnt;
10115                 if (index <  array_size) {
10116 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
10117                         band_chan_arr[index].center_freq =
10118                                 ieee80211_channel_to_frequency(channel);
10119 #else
10120                         band_chan_arr[index].center_freq =
10121                                 ieee80211_channel_to_frequency(channel, band);
10122 #endif
10123                         band_chan_arr[index].hw_value = channel;
10124
10125                         if (CHSPEC_IS40(c) && ht40_allowed) {
10126                                 /* assuming the order is HT20, HT40 Upper,
10127                                  *  HT40 lower from chanspecs
10128                                  */
10129                                 u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
10130                                 if (CHSPEC_SB_UPPER(c)) {
10131                                         if (ht40_flag == IEEE80211_CHAN_NO_HT40)
10132                                                 band_chan_arr[index].flags &=
10133                                                         ~IEEE80211_CHAN_NO_HT40;
10134                                         band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
10135                                 } else {
10136                                         /* It should be one of
10137                                          * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
10138                                          */
10139                                         band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
10140                                         if (ht40_flag == IEEE80211_CHAN_NO_HT40)
10141                                                 band_chan_arr[index].flags |=
10142                                                         IEEE80211_CHAN_NO_HT40MINUS;
10143                                 }
10144                         } else {
10145                                 band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
10146                                 if (!dfs_radar_disabled) {
10147                                         if (band == IEEE80211_BAND_2GHZ)
10148                                                 channel |= WL_CHANSPEC_BAND_2G;
10149                                         else
10150                                                 channel |= WL_CHANSPEC_BAND_5G;
10151                                         channel |= WL_CHANSPEC_BW_20;
10152                                         channel = wl_chspec_host_to_driver(channel);
10153                                         err = wldev_iovar_getint(dev, "per_chan_info", &channel);
10154                                         if (!err) {
10155                                                 if (channel & WL_CHAN_RADAR)
10156                                                         band_chan_arr[index].flags |=
10157                                                                 (IEEE80211_CHAN_RADAR |
10158                                                                 IEEE80211_CHAN_NO_IBSS);
10159                                                 if (channel & WL_CHAN_PASSIVE)
10160                                                         band_chan_arr[index].flags |=
10161                                                                 IEEE80211_CHAN_PASSIVE_SCAN;
10162                                         } else if (err == BCME_UNSUPPORTED) {
10163                                                 dfs_radar_disabled = TRUE;
10164                                                 WL_ERR(("does not support per_chan_info\n"));
10165                                         }
10166                                 }
10167                         }
10168                         if (!update)
10169                                 (*n_cnt)++;
10170                 }
10171
10172         }
10173         __wl_band_2ghz.n_channels = n_2g;
10174         __wl_band_5ghz_a.n_channels = n_5g;
10175         kfree(pbuf);
10176         return err;
10177 }
10178
10179 s32 wl_update_wiphybands(struct wl_priv *wl, bool notify)
10180 {
10181         struct wiphy *wiphy;
10182         struct net_device *dev;
10183         u32 bandlist[3];
10184         u32 nband = 0;
10185         u32 i = 0;
10186         s32 err = 0;
10187         s32 index = 0;
10188         s32 nmode = 0;
10189         bool rollback_lock = false;
10190         s32 bw_cap = 0;
10191         s32 cur_band = -1;
10192         struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS] = {NULL, };
10193
10194         if (wl == NULL) {
10195                 wl = wlcfg_drv_priv;
10196                 mutex_lock(&wl->usr_sync);
10197                 rollback_lock = true;
10198         }
10199         dev = wl_to_prmry_ndev(wl);
10200
10201         memset(bandlist, 0, sizeof(bandlist));
10202         err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist,
10203                 sizeof(bandlist), false);
10204         if (unlikely(err)) {
10205                 WL_ERR(("error read bandlist (%d)\n", err));
10206                 goto end_bands;
10207         }
10208         err = wldev_ioctl(dev, WLC_GET_BAND, &cur_band,
10209                 sizeof(s32), false);
10210         if (unlikely(err)) {
10211                 WL_ERR(("error (%d)\n", err));
10212                 goto end_bands;
10213         }
10214
10215         err = wldev_iovar_getint(dev, "nmode", &nmode);
10216         if (unlikely(err)) {
10217                 WL_ERR(("error reading nmode (%d)\n", err));
10218         } else {
10219                 /* For nmodeonly  check bw cap */
10220                 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
10221                 if (unlikely(err)) {
10222                         WL_ERR(("error get mimo_bw_cap (%d)\n", err));
10223                 }
10224         }
10225
10226         err = wl_construct_reginfo(wl, bw_cap);
10227         if (err) {
10228                 WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
10229                 if (err != BCME_UNSUPPORTED)
10230                         goto end_bands;
10231                 err = 0;
10232         }
10233         wiphy = wl_to_wiphy(wl);
10234         nband = bandlist[0];
10235
10236         for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) {
10237                 index = -1;
10238                 if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
10239                         bands[IEEE80211_BAND_5GHZ] =
10240                                 &__wl_band_5ghz_a;
10241                         index = IEEE80211_BAND_5GHZ;
10242                         if (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G)
10243                                 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
10244                 }
10245                 else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
10246                         bands[IEEE80211_BAND_2GHZ] =
10247                                 &__wl_band_2ghz;
10248                         index = IEEE80211_BAND_2GHZ;
10249                         if (bw_cap == WLC_N_BW_40ALL)
10250                                 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
10251                 }
10252
10253                 if ((index >= 0) && nmode) {
10254                         bands[index]->ht_cap.cap |=
10255                                 (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40);
10256                         bands[index]->ht_cap.ht_supported = TRUE;
10257                         bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
10258                         bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
10259                         /* An HT shall support all EQM rates for one spatial stream */
10260                         bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
10261                 }
10262
10263         }
10264
10265         wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
10266         wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
10267
10268         /* check if any bands populated otherwise makes 2Ghz as default */
10269         if (wiphy->bands[IEEE80211_BAND_2GHZ] == NULL &&
10270                 wiphy->bands[IEEE80211_BAND_5GHZ] == NULL) {
10271                 /* Setup 2Ghz band as default */
10272                 wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
10273         }
10274
10275         if (notify)
10276                 wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
10277
10278         end_bands:
10279                 if (rollback_lock)
10280                         mutex_unlock(&wl->usr_sync);
10281         return err;
10282 }
10283
10284 static s32 __wl_cfg80211_up(struct wl_priv *wl)
10285 {
10286         s32 err = 0;
10287         struct net_device *ndev = wl_to_prmry_ndev(wl);
10288         struct wireless_dev *wdev = ndev->ieee80211_ptr;
10289
10290         WL_DBG(("In\n"));
10291
10292         err = dhd_config_dongle(wl, false);
10293         if (unlikely(err))
10294                 return err;
10295
10296         err = wl_config_ifmode(wl, ndev, wdev->iftype);
10297         if (unlikely(err && err != -EINPROGRESS)) {
10298                 WL_ERR(("wl_config_ifmode failed\n"));
10299         }
10300         err = wl_update_wiphybands(wl, true);
10301         if (unlikely(err)) {
10302                 WL_ERR(("wl_update_wiphybands failed\n"));
10303         }
10304
10305         err = dhd_monitor_init(wl->pub);
10306         err = wl_invoke_iscan(wl);
10307
10308
10309         INIT_DELAYED_WORK(&wl->pm_enable_work, wl_cfg80211_work_handler);
10310         wl_set_drv_status(wl, READY, ndev);
10311         return err;
10312 }
10313
10314 static s32 __wl_cfg80211_down(struct wl_priv *wl)
10315 {
10316         s32 err = 0;
10317         unsigned long flags;
10318         struct net_info *iter, *next;
10319         struct net_device *ndev = wl_to_prmry_ndev(wl);
10320 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
10321         struct net_device *p2p_net = wl->p2p_net;
10322 #endif /* WL_CFG80211 && WL_ENABLE_P2P_IF */
10323         u32 bssidx = 0;
10324 #ifdef PROP_TXSTATUS_VSDB
10325         dhd_pub_t *dhd =  (dhd_pub_t *)(wl->pub);
10326 #endif /* PROP_TXSTATUS_VSDB */
10327         WL_DBG(("In\n"));
10328         /* Delete pm_enable_work */
10329         wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_DEL);
10330
10331         if (wl->p2p_supported) {
10332                 wl_clr_p2p_status(wl, GO_NEG_PHASE);
10333 #ifdef PROP_TXSTATUS_VSDB
10334                 if (wl->p2p->vif_created) {
10335                         if (dhd-> op_mode != DHD_FLAG_IBSS_MODE &&
10336                                 dhd->wlfc_enabled && wl->wlfc_on) {
10337                                 dhd->wlfc_enabled = false;
10338                                 dhd_wlfc_deinit(dhd);
10339                                 if (dhd->plat_deinit)
10340                                         dhd->plat_deinit((void *)dhd);
10341                                 wl->wlfc_on = false;
10342                         }
10343                 }
10344 #endif /* PROP_TXSTATUS_VSDB */
10345         }
10346
10347
10348         /* If primary BSS is operational (for e.g SoftAP), bring it down */
10349         if (!(wl_cfgp2p_find_idx(wl, ndev, &bssidx)) &&
10350                 wl_cfgp2p_bss_isup(ndev, bssidx)) {
10351                 if (wl_cfgp2p_bss(wl, ndev, bssidx, 0) < 0)
10352                         WL_ERR(("BSS down failed \n"));
10353         }
10354
10355         /* Check if cfg80211 interface is already down */
10356         if (!wl_get_drv_status(wl, READY, ndev))
10357                 return err;     /* it is even not ready */
10358         for_each_ndev(wl, iter, next)
10359                 wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev);
10360
10361
10362         wl_term_iscan(wl);
10363         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
10364         if (wl->scan_request) {
10365                 cfg80211_scan_done(wl->scan_request, true);
10366                 wl->scan_request = NULL;
10367         }
10368         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
10369
10370         for_each_ndev(wl, iter, next) {
10371                 wl_clr_drv_status(wl, READY, iter->ndev);
10372                 wl_clr_drv_status(wl, SCANNING, iter->ndev);
10373                 wl_clr_drv_status(wl, SCAN_ABORTING, iter->ndev);
10374                 wl_clr_drv_status(wl, CONNECTING, iter->ndev);
10375                 wl_clr_drv_status(wl, CONNECTED, iter->ndev);
10376                 wl_clr_drv_status(wl, DISCONNECTING, iter->ndev);
10377                 wl_clr_drv_status(wl, AP_CREATED, iter->ndev);
10378                 wl_clr_drv_status(wl, AP_CREATING, iter->ndev);
10379         }
10380         wl_to_prmry_ndev(wl)->ieee80211_ptr->iftype =
10381                 NL80211_IFTYPE_STATION;
10382 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
10383                 if (p2p_net)
10384                         dev_close(p2p_net);
10385 #endif /* WL_CFG80211 && WL_ENABLE_P2P_IF */
10386         DNGL_FUNC(dhd_cfg80211_down, (wl));
10387         wl_flush_eq(wl);
10388         wl_link_down(wl);
10389         if (wl->p2p_supported)
10390                 wl_cfgp2p_down(wl);
10391         dhd_monitor_uninit();
10392
10393         return err;
10394 }
10395
10396 s32 wl_cfg80211_up(void *para)
10397 {
10398         struct wl_priv *wl;
10399         s32 err = 0;
10400         int val = 1;
10401         dhd_pub_t *dhd;
10402
10403         (void)para;
10404         WL_DBG(("In\n"));
10405         wl = wlcfg_drv_priv;
10406
10407         if ((err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_VERSION, &val,
10408                 sizeof(int), false) < 0)) {
10409                 WL_ERR(("WLC_GET_VERSION failed, err=%d\n", err));
10410                 return err;
10411         }
10412         val = dtoh32(val);
10413         if (val != WLC_IOCTL_VERSION && val != 1) {
10414                 WL_ERR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
10415                         val, WLC_IOCTL_VERSION));
10416                 return BCME_VERSION;
10417         }
10418         ioctl_version = val;
10419         WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version));
10420
10421         mutex_lock(&wl->usr_sync);
10422         dhd = (dhd_pub_t *)(wl->pub);
10423         if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
10424                 err = wl_cfg80211_attach_post(wl_to_prmry_ndev(wl));
10425                 if (unlikely(err))
10426                         return err;
10427         }
10428         err = __wl_cfg80211_up(wl);
10429         if (unlikely(err))
10430                 WL_ERR(("__wl_cfg80211_up failed\n"));
10431         mutex_unlock(&wl->usr_sync);
10432         return err;
10433 }
10434
10435 /* Private Event to Supplicant with indication that chip hangs */
10436 int wl_cfg80211_hang(struct net_device *dev, u16 reason)
10437 {
10438         struct wl_priv *wl;
10439         wl = wlcfg_drv_priv;
10440
10441         WL_ERR(("In : chip crash eventing\n"));
10442         wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_DEL);
10443         cfg80211_disconnected(dev, reason, NULL, 0, GFP_KERNEL);
10444         if (wl != NULL) {
10445                 wl_link_down(wl);
10446         }
10447         return 0;
10448 }
10449
10450 s32 wl_cfg80211_down(void *para)
10451 {
10452         struct wl_priv *wl;
10453         s32 err = 0;
10454
10455         (void)para;
10456         WL_DBG(("In\n"));
10457         wl = wlcfg_drv_priv;
10458         mutex_lock(&wl->usr_sync);
10459         err = __wl_cfg80211_down(wl);
10460         mutex_unlock(&wl->usr_sync);
10461
10462         return err;
10463 }
10464
10465 static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item)
10466 {
10467         unsigned long flags;
10468         void *rptr = NULL;
10469         struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
10470
10471         if (!profile)
10472                 return NULL;
10473         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
10474         switch (item) {
10475         case WL_PROF_SEC:
10476                 rptr = &profile->sec;
10477                 break;
10478         case WL_PROF_ACT:
10479                 rptr = &profile->active;
10480                 break;
10481         case WL_PROF_BSSID:
10482                 rptr = profile->bssid;
10483                 break;
10484         case WL_PROF_SSID:
10485                 rptr = &profile->ssid;
10486                 break;
10487         case WL_PROF_CHAN:
10488                 rptr = &profile->channel;
10489                 break;
10490         }
10491         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
10492         if (!rptr)
10493                 WL_ERR(("invalid item (%d)\n", item));
10494         return rptr;
10495 }
10496
10497 static s32
10498 wl_update_prof(struct wl_priv *wl, struct net_device *ndev,
10499         const wl_event_msg_t *e, void *data, s32 item)
10500 {
10501         s32 err = 0;
10502         struct wlc_ssid *ssid;
10503         unsigned long flags;
10504         struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
10505
10506         if (!profile)
10507                 return WL_INVALID;
10508         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
10509         switch (item) {
10510         case WL_PROF_SSID:
10511                 ssid = (wlc_ssid_t *) data;
10512                 memset(profile->ssid.SSID, 0,
10513                         sizeof(profile->ssid.SSID));
10514                 memcpy(profile->ssid.SSID, ssid->SSID, ssid->SSID_len);
10515                 profile->ssid.SSID_len = ssid->SSID_len;
10516                 break;
10517         case WL_PROF_BSSID:
10518                 if (data)
10519                         memcpy(profile->bssid, data, ETHER_ADDR_LEN);
10520                 else
10521                         memset(profile->bssid, 0, ETHER_ADDR_LEN);
10522                 break;
10523         case WL_PROF_SEC:
10524                 memcpy(&profile->sec, data, sizeof(profile->sec));
10525                 break;
10526         case WL_PROF_ACT:
10527                 profile->active = *(bool *)data;
10528                 break;
10529         case WL_PROF_BEACONINT:
10530                 profile->beacon_interval = *(u16 *)data;
10531                 break;
10532         case WL_PROF_DTIMPERIOD:
10533                 profile->dtim_period = *(u8 *)data;
10534                 break;
10535         case WL_PROF_CHAN:
10536                 profile->channel = *(u32*)data;
10537                 break;
10538         default:
10539                 err = -EOPNOTSUPP;
10540                 break;
10541         }
10542         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
10543
10544         if (err == -EOPNOTSUPP)
10545                 WL_ERR(("unsupported item (%d)\n", item));
10546
10547         return err;
10548 }
10549
10550 void wl_cfg80211_dbg_level(u32 level)
10551 {
10552         /*
10553         * prohibit to change debug level
10554         * by insmod parameter.
10555         * eventually debug level will be configured
10556         * in compile time by using CONFIG_XXX
10557         */
10558         /* wl_dbg_level = level; */
10559 }
10560
10561 static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev)
10562 {
10563         return wl_get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS;
10564 }
10565
10566 static __used bool wl_is_ibssstarter(struct wl_priv *wl)
10567 {
10568         return wl->ibss_starter;
10569 }
10570
10571 static void wl_rst_ie(struct wl_priv *wl)
10572 {
10573         struct wl_ie *ie = wl_to_ie(wl);
10574
10575         ie->offset = 0;
10576 }
10577
10578 static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v)
10579 {
10580         struct wl_ie *ie = wl_to_ie(wl);
10581         s32 err = 0;
10582
10583         if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
10584                 WL_ERR(("ei crosses buffer boundary\n"));
10585                 return -ENOSPC;
10586         }
10587         ie->buf[ie->offset] = t;
10588         ie->buf[ie->offset + 1] = l;
10589         memcpy(&ie->buf[ie->offset + 2], v, l);
10590         ie->offset += l + 2;
10591
10592         return err;
10593 }
10594
10595 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size)
10596 {
10597         u8 *ssidie;
10598         ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size);
10599         if (!ssidie)
10600                 return;
10601         if (ssidie[1] != bi->SSID_len) {
10602                 if (ssidie[1]) {
10603                         WL_ERR(("%s: Wrong SSID len: %d != %d\n",
10604                                 __FUNCTION__, ssidie[1], bi->SSID_len));
10605                         return;
10606                 }
10607                 memmove(ssidie + bi->SSID_len + 2, ssidie + 2, *ie_size - (ssidie + 2 - ie_stream));
10608                 memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
10609                 *ie_size = *ie_size + bi->SSID_len;
10610                 ssidie[1] = bi->SSID_len;
10611                 return;
10612         }
10613         if (*(ssidie + 2) == '\0')
10614                  memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
10615         return;
10616 }
10617
10618 static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size)
10619 {
10620         struct wl_ie *ie = wl_to_ie(wl);
10621         s32 err = 0;
10622
10623         if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
10624                 WL_ERR(("ei_stream crosses buffer boundary\n"));
10625                 return -ENOSPC;
10626         }
10627         memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
10628         ie->offset += ie_size;
10629
10630         return err;
10631 }
10632
10633 static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size)
10634 {
10635         struct wl_ie *ie = wl_to_ie(wl);
10636         s32 err = 0;
10637
10638         if (unlikely(ie->offset > dst_size)) {
10639                 WL_ERR(("dst_size is not enough\n"));
10640                 return -ENOSPC;
10641         }
10642         memcpy(dst, &ie->buf[0], ie->offset);
10643
10644         return err;
10645 }
10646
10647 static u32 wl_get_ielen(struct wl_priv *wl)
10648 {
10649         struct wl_ie *ie = wl_to_ie(wl);
10650
10651         return ie->offset;
10652 }
10653
10654 static void wl_link_up(struct wl_priv *wl)
10655 {
10656         wl->link_up = true;
10657 }
10658
10659 static void wl_link_down(struct wl_priv *wl)
10660 {
10661         struct wl_connect_info *conn_info = wl_to_conn(wl);
10662
10663         WL_DBG(("In\n"));
10664         wl->link_up = false;
10665         conn_info->req_ie_len = 0;
10666         conn_info->resp_ie_len = 0;
10667 }
10668
10669 static unsigned long wl_lock_eq(struct wl_priv *wl)
10670 {
10671         unsigned long flags;
10672
10673         spin_lock_irqsave(&wl->eq_lock, flags);
10674         return flags;
10675 }
10676
10677 static void wl_unlock_eq(struct wl_priv *wl, unsigned long flags)
10678 {
10679         spin_unlock_irqrestore(&wl->eq_lock, flags);
10680 }
10681
10682 static void wl_init_eq_lock(struct wl_priv *wl)
10683 {
10684         spin_lock_init(&wl->eq_lock);
10685 }
10686
10687 static void wl_delay(u32 ms)
10688 {
10689         if (in_atomic() || (ms < jiffies_to_msecs(1))) {
10690                 OSL_DELAY(ms*1000);
10691         } else {
10692                 OSL_SLEEP(ms);
10693         }
10694 }
10695
10696 s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
10697 {
10698         struct wl_priv *wl = wlcfg_drv_priv;
10699         struct ether_addr p2pif_addr;
10700         struct ether_addr primary_mac;
10701         if (!wl->p2p)
10702                 return -1;
10703         if (!p2p_is_on(wl)) {
10704                 get_primary_mac(wl, &primary_mac);
10705                 wl_cfgp2p_generate_bss_mac(&primary_mac, p2pdev_addr, &p2pif_addr);
10706         } else {
10707                 memcpy(p2pdev_addr->octet,
10708                         wl->p2p->dev_addr.octet, ETHER_ADDR_LEN);
10709         }
10710
10711
10712         return 0;
10713 }
10714 s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
10715 {
10716         struct wl_priv *wl;
10717
10718         wl = wlcfg_drv_priv;
10719
10720         return wl_cfgp2p_set_p2p_noa(wl, net, buf, len);
10721 }
10722
10723 s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
10724 {
10725         struct wl_priv *wl;
10726         wl = wlcfg_drv_priv;
10727
10728         return wl_cfgp2p_get_p2p_noa(wl, net, buf, len);
10729 }
10730
10731 s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
10732 {
10733         struct wl_priv *wl;
10734         wl = wlcfg_drv_priv;
10735
10736         return wl_cfgp2p_set_p2p_ps(wl, net, buf, len);
10737 }
10738
10739 s32 wl_cfg80211_channel_to_freq(u32 channel)
10740 {
10741         int freq = 0;
10742
10743 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
10744         freq = ieee80211_channel_to_frequency(channel);
10745 #else
10746         {
10747                 u16 band = 0;
10748                 if (channel <= CH_MAX_2G_CHANNEL)
10749                         band = IEEE80211_BAND_2GHZ;
10750                 else
10751                         band = IEEE80211_BAND_5GHZ;
10752                 freq = ieee80211_channel_to_frequency(channel, band);
10753         }
10754 #endif
10755         return freq;
10756 }
10757
10758
10759 #ifdef WLTDLS
10760 static s32
10761 wl_tdls_event_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
10762         const wl_event_msg_t *e, void *data) {
10763
10764         struct net_device *ndev = NULL;
10765         u32 reason = ntoh32(e->reason);
10766         s8 *msg = NULL;
10767
10768         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
10769
10770         switch (reason) {
10771         case WLC_E_TDLS_PEER_DISCOVERED :
10772                 msg = " TDLS PEER DISCOVERD ";
10773                 break;
10774         case WLC_E_TDLS_PEER_CONNECTED :
10775                 msg = " TDLS PEER CONNECTED ";
10776                 break;
10777         case WLC_E_TDLS_PEER_DISCONNECTED :
10778                 msg = "TDLS PEER DISCONNECTED ";
10779                 break;
10780         }
10781         if (msg) {
10782                 WL_ERR(("%s: " MACDBG " on %s ndev\n", msg, MAC2STRDBG((u8*)(&e->addr)),
10783                         (wl_to_prmry_ndev(wl) == ndev) ? "primary" : "secondary"));
10784         }
10785         return 0;
10786
10787 }
10788 #endif  /* WLTDLS */
10789
10790 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || 0
10791 static s32
10792 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
10793         u8 *peer, enum nl80211_tdls_operation oper)
10794 {
10795         s32 ret = 0;
10796 #ifdef WLTDLS
10797         struct wl_priv *wl = wlcfg_drv_priv;
10798
10799         if (!wl)
10800                 return ERR_PTR(-EINVAL);
10801
10802         tdls_iovar_t info;
10803         dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
10804         memset(&info, 0, sizeof(tdls_iovar_t));
10805         if (peer)
10806                 memcpy(&info.ea, peer, ETHER_ADDR_LEN);
10807         switch (oper) {
10808         case NL80211_TDLS_DISCOVERY_REQ:
10809                 if (!dhd->tdls_enable)
10810                         ret = dhd_tdls_enable_disable(dhd, 1);
10811                 if (ret < 0)
10812                         return ret;
10813                 info.mode = TDLS_MANUAL_EP_DISCOVERY;
10814                 break;
10815         case NL80211_TDLS_SETUP:
10816                 info.mode = TDLS_MANUAL_EP_CREATE;
10817                 break;
10818         case NL80211_TDLS_TEARDOWN:
10819                 info.mode = TDLS_MANUAL_EP_DELETE;
10820                 break;
10821         default:
10822                 WL_ERR(("Unsupported operation : %d\n", oper));
10823                 goto out;
10824         }
10825         ret = wldev_iovar_setbuf(dev, "tdls_endpoint", &info, sizeof(info),
10826                 wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
10827         if (ret) {
10828                 WL_ERR(("tdls_endpoint error %d\n", ret));
10829         }
10830 out:
10831 #endif /* WLTDLS */
10832         return ret;
10833 }
10834 #endif 
10835
10836 s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
10837         enum wl_management_type type)
10838 {
10839         struct wl_priv *wl;
10840         struct net_device *ndev = NULL;
10841         struct ether_addr primary_mac;
10842         s32 ret = 0;
10843         s32 bssidx = 0;
10844         s32 pktflag = 0;
10845         wl = wlcfg_drv_priv;
10846
10847         if (wl_get_drv_status(wl, AP_CREATING, net)) {
10848                 /* Vendor IEs should be set to FW
10849                  * after SoftAP interface is brought up
10850                  */
10851                 goto exit;
10852         } else if (wl_get_drv_status(wl, AP_CREATED, net)) {
10853                 ndev = net;
10854                 bssidx = 0;
10855         } else if (wl->p2p) {
10856                 net = ndev_to_wlc_ndev(net, wl);
10857                 if (!wl->p2p->on) {
10858                         get_primary_mac(wl, &primary_mac);
10859                         wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr,
10860                                 &wl->p2p->int_addr);
10861                         /* In case of p2p_listen command, supplicant send remain_on_channel
10862                         * without turning on P2P
10863                         */
10864
10865                         p2p_on(wl) = true;
10866                         ret = wl_cfgp2p_enable_discovery(wl, net, NULL, 0);
10867
10868                         if (unlikely(ret)) {
10869                                 goto exit;
10870                         }
10871                 }
10872                 if (net  != wl_to_prmry_ndev(wl)) {
10873                         if (wl_get_mode_by_netdev(wl, net) == WL_MODE_AP) {
10874                                 ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
10875                                 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION);
10876                         }
10877                 } else {
10878                                 ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY);
10879                                 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
10880                 }
10881         }
10882         if (ndev != NULL) {
10883                 switch (type) {
10884                         case WL_BEACON:
10885                                 pktflag = VNDR_IE_BEACON_FLAG;
10886                                 break;
10887                         case WL_PROBE_RESP:
10888                                 pktflag = VNDR_IE_PRBRSP_FLAG;
10889                                 break;
10890                         case WL_ASSOC_RESP:
10891                                 pktflag = VNDR_IE_ASSOCRSP_FLAG;
10892                                 break;
10893                 }
10894                 if (pktflag)
10895                         ret = wl_cfgp2p_set_management_ie(wl, ndev, bssidx, pktflag, buf, len);
10896         }
10897 exit:
10898         return ret;
10899 }
10900
10901 #ifdef WL_SUPPORT_AUTO_CHANNEL
10902 static s32
10903 wl_cfg80211_set_auto_channel_scan_state(struct net_device *ndev)
10904 {
10905         u32 val = 0;
10906         s32 ret = BCME_ERROR;
10907         struct wl_priv *wl = wlcfg_drv_priv;
10908
10909         /* Disable mpc, to avoid automatic interface down. */
10910         val = 0;
10911
10912         ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
10913                 sizeof(val), wl->ioctl_buf, WLC_IOCTL_SMLEN, 0,
10914                 &wl->ioctl_buf_sync);
10915         if (ret < 0) {
10916                 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
10917                 goto done;
10918         }
10919
10920         /* Set interface up, explicitly. */
10921         val = 1;
10922
10923         ret = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
10924         if (ret < 0) {
10925                 WL_ERR(("set interface up failed, error = %d\n", ret));
10926                 goto done;
10927         }
10928
10929         /* Stop all scan explicitly, till auto channel selection complete. */
10930         wl_set_drv_status(wl, SCANNING, ndev);
10931         ret = wl_notify_escan_complete(wl, ndev, true, true);
10932         if (ret < 0) {
10933                 WL_ERR(("set scan abort failed, error = %d\n", ret));
10934                 goto done;
10935         }
10936
10937 done:
10938         return ret;
10939 }
10940
10941 static bool
10942 wl_cfg80211_valid_chanspec_p2p(chanspec_t chanspec)
10943 {
10944         bool valid = false;
10945
10946         /* channel 1 to 14 */
10947         if ((chanspec >= 0x2b01) && (chanspec <= 0x2b0e)) {
10948                 valid = true;
10949         }
10950         /* channel 36 to 48 */
10951         else if ((chanspec >= 0x1b24) && (chanspec <= 0x1b30)) {
10952                 valid = true;
10953         }
10954         /* channel 149 to 161 */
10955         else if ((chanspec >= 0x1b95) && (chanspec <= 0x1ba1)) {
10956                 valid = true;
10957         }
10958         else {
10959                 valid = false;
10960                 WL_INFO(("invalid P2P chanspec, channel = %d, chanspec = %04x\n",
10961                         CHSPEC_CHANNEL(chanspec), chanspec));
10962         }
10963
10964         return valid;
10965 }
10966
10967 static s32
10968 wl_cfg80211_get_chanspecs_2g(struct net_device *ndev, void *buf, s32 buflen)
10969 {
10970         s32 ret = BCME_ERROR;
10971         struct wl_priv *wl = NULL;
10972         wl_uint32_list_t *list = NULL;
10973         chanspec_t chanspec = 0;
10974
10975         memset(buf, 0, buflen);
10976
10977         wl = wlcfg_drv_priv;
10978         list = (wl_uint32_list_t *)buf;
10979         list->count = htod32(WL_NUMCHANSPECS);
10980
10981         /* Restrict channels to 2.4GHz, 20MHz BW, no SB. */
10982         chanspec |= (WL_CHANSPEC_BAND_2G | WL_CHANSPEC_BW_20 |
10983                 WL_CHANSPEC_CTL_SB_NONE);
10984         chanspec = wl_chspec_host_to_driver(chanspec);
10985
10986         ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
10987                 sizeof(chanspec), buf, buflen, 0, &wl->ioctl_buf_sync);
10988         if (ret < 0) {
10989                 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
10990         }
10991
10992         return ret;
10993 }
10994
10995 static s32
10996 wl_cfg80211_get_chanspecs_5g(struct net_device *ndev, void *buf, s32 buflen)
10997 {
10998         u32 channel = 0;
10999         s32 ret = BCME_ERROR;
11000         s32 i = 0;
11001         s32 j = 0;
11002         struct wl_priv *wl = NULL;
11003         wl_uint32_list_t *list = NULL;
11004         chanspec_t chanspec = 0;
11005
11006         memset(buf, 0, buflen);
11007
11008         wl = wlcfg_drv_priv;
11009         list = (wl_uint32_list_t *)buf;
11010         list->count = htod32(WL_NUMCHANSPECS);
11011
11012         /* Restrict channels to 5GHz, 20MHz BW, no SB. */
11013         chanspec |= (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_20 |
11014                 WL_CHANSPEC_CTL_SB_NONE);
11015         chanspec = wl_chspec_host_to_driver(chanspec);
11016
11017         ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
11018                 sizeof(chanspec), buf, buflen, 0, &wl->ioctl_buf_sync);
11019         if (ret < 0) {
11020                 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
11021                 goto done;
11022         }
11023
11024         /* Skip DFS and inavlid P2P channel. */
11025         for (i = 0, j = 0; i < dtoh32(list->count); i++) {
11026                 chanspec = (chanspec_t) dtoh32(list->element[i]);
11027                 channel = CHSPEC_CHANNEL(chanspec);
11028
11029                 ret = wldev_iovar_getint(ndev, "per_chan_info", &channel);
11030                 if (ret < 0) {
11031                         WL_ERR(("get 'per_chan_info' failed, error = %d\n", ret));
11032                         goto done;
11033                 }
11034
11035                 if (CHANNEL_IS_RADAR(channel) ||
11036                         !(wl_cfg80211_valid_chanspec_p2p(chanspec))) {
11037                         continue;
11038                 } else {
11039                         list->element[j] = list->element[i];
11040                 }
11041
11042                 j++;
11043         }
11044
11045         list->count = j;
11046
11047 done:
11048         return ret;
11049 }
11050
11051 static s32
11052 wl_cfg80211_get_best_channel(struct net_device *ndev, void *buf, int buflen,
11053         int *channel)
11054 {
11055         s32 ret = BCME_ERROR;
11056         int chosen = 0;
11057         int retry = 0;
11058
11059         /* Start auto channel selection scan. */
11060         ret = wldev_ioctl(ndev, WLC_START_CHANNEL_SEL, buf, buflen, true);
11061         if (ret < 0) {
11062                 WL_ERR(("can't start auto channel scan, error = %d\n", ret));
11063                 *channel = 0;
11064                 goto done;
11065         }
11066
11067         /* Wait for auto channel selection, worst case possible delay is 5250ms. */
11068         retry = CHAN_SEL_RETRY_COUNT;
11069
11070         while (retry--) {
11071                 OSL_SLEEP(CHAN_SEL_IOCTL_DELAY);
11072
11073                 ret = wldev_ioctl(ndev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen),
11074                         false);
11075                 if ((ret == 0) && (dtoh32(chosen) != 0)) {
11076                         *channel = (u16)(chosen & 0x00FF);
11077                         WL_INFO(("selected channel = %d\n", *channel));
11078                         break;
11079                 }
11080                 WL_INFO(("attempt = %d, ret = %d, chosen = %d\n",
11081                         (CHAN_SEL_RETRY_COUNT - retry), ret, dtoh32(chosen)));
11082         }
11083
11084         if (retry <= 0) {
11085                 WL_ERR(("failure, auto channel selection timed out\n"));
11086                 *channel = 0;
11087                 ret = BCME_ERROR;
11088         }
11089
11090 done:
11091         return ret;
11092 }
11093
11094 static s32
11095 wl_cfg80211_restore_auto_channel_scan_state(struct net_device *ndev)
11096 {
11097         u32 val = 0;
11098         s32 ret = BCME_ERROR;
11099         struct wl_priv *wl = wlcfg_drv_priv;
11100
11101         /* Clear scan stop driver status. */
11102         wl_clr_drv_status(wl, SCANNING, ndev);
11103
11104         /* Enable mpc back to 1, irrespective of initial state. */
11105         val = 1;
11106
11107         ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
11108                 sizeof(val), wl->ioctl_buf, WLC_IOCTL_SMLEN, 0,
11109                 &wl->ioctl_buf_sync);
11110         if (ret < 0) {
11111                 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
11112         }
11113
11114         return ret;
11115 }
11116
11117 s32
11118 wl_cfg80211_get_best_channels(struct net_device *dev, char* cmd, int total_len)
11119 {
11120         int channel = 0;
11121         s32 ret = BCME_ERROR;
11122         u8 *buf = NULL;
11123         char *pos = cmd;
11124         struct wl_priv *wl = NULL;
11125         struct net_device *ndev = NULL;
11126
11127         memset(cmd, 0, total_len);
11128
11129         buf = kmalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
11130         if (buf == NULL) {
11131                 WL_ERR(("failed to allocate chanspec buffer\n"));
11132                 return -ENOMEM;
11133         }
11134
11135         /*
11136          * Always use primary interface, irrespective of interface on which
11137          * command came.
11138          */
11139         wl = wlcfg_drv_priv;
11140         ndev = wl_to_prmry_ndev(wl);
11141
11142         /*
11143          * Make sure that FW and driver are in right state to do auto channel
11144          * selection scan.
11145          */
11146         ret = wl_cfg80211_set_auto_channel_scan_state(ndev);
11147         if (ret < 0) {
11148                 WL_ERR(("can't set auto channel scan state, error = %d\n", ret));
11149                 goto done;
11150         }
11151
11152         /* Best channel selection in 2.4GHz band. */
11153         ret = wl_cfg80211_get_chanspecs_2g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
11154         if (ret < 0) {
11155                 WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
11156                 goto done;
11157         }
11158
11159         ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
11160                 &channel);
11161         if (ret < 0) {
11162                 WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
11163                 goto done;
11164         }
11165
11166         if (CHANNEL_IS_2G(channel)) {
11167                 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
11168         } else {
11169                 WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel));
11170                 channel = 0;
11171         }
11172
11173         sprintf(pos, "%04d ", channel);
11174         pos += 5;
11175
11176         /* Best channel selection in 5GHz band. */
11177         ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
11178         if (ret < 0) {
11179                 WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret));
11180                 goto done;
11181         }
11182
11183         ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
11184                 &channel);
11185         if (ret < 0) {
11186                 WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret));
11187                 goto done;
11188         }
11189
11190         if (CHANNEL_IS_5G(channel)) {
11191                 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
11192         } else {
11193                 WL_ERR(("invalid 5GHz channel, channel = %d\n", channel));
11194                 channel = 0;
11195         }
11196
11197         sprintf(pos, "%04d ", channel);
11198         pos += 5;
11199
11200         /* Set overall best channel same as 5GHz best channel. */
11201         sprintf(pos, "%04d ", channel);
11202         pos += 5;
11203
11204 done:
11205         if (NULL != buf) {
11206                 kfree(buf);
11207         }
11208
11209         /* Restore FW and driver back to normal state. */
11210         ret = wl_cfg80211_restore_auto_channel_scan_state(ndev);
11211         if (ret < 0) {
11212                 WL_ERR(("can't restore auto channel scan state, error = %d\n", ret));
11213         }
11214
11215         return (pos - cmd);
11216 }
11217 #endif /* WL_SUPPORT_AUTO_CHANNEL */
11218
11219 static const struct rfkill_ops wl_rfkill_ops = {
11220         .set_block = wl_rfkill_set
11221 };
11222
11223 static int wl_rfkill_set(void *data, bool blocked)
11224 {
11225         struct wl_priv *wl = (struct wl_priv *)data;
11226
11227         WL_DBG(("Enter \n"));
11228         WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked"));
11229
11230         if (!wl)
11231                 return -EINVAL;
11232
11233         wl->rf_blocked = blocked;
11234
11235         return 0;
11236 }
11237
11238 static int wl_setup_rfkill(struct wl_priv *wl, bool setup)
11239 {
11240         s32 err = 0;
11241
11242         WL_DBG(("Enter \n"));
11243         if (!wl)
11244                 return -EINVAL;
11245         if (setup) {
11246                 wl->rfkill = rfkill_alloc("brcmfmac-wifi",
11247                         wl_cfg80211_get_parent_dev(),
11248                         RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)wl);
11249
11250                 if (!wl->rfkill) {
11251                         err = -ENOMEM;
11252                         goto err_out;
11253                 }
11254
11255                 err = rfkill_register(wl->rfkill);
11256
11257                 if (err)
11258                         rfkill_destroy(wl->rfkill);
11259         } else {
11260                 if (!wl->rfkill) {
11261                         err = -ENOMEM;
11262                         goto err_out;
11263                 }
11264
11265                 rfkill_unregister(wl->rfkill);
11266                 rfkill_destroy(wl->rfkill);
11267         }
11268
11269 err_out:
11270         return err;
11271 }
11272
11273 #ifdef DEBUGFS_CFG80211
11274 /**
11275 * Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level
11276 * to turn on SCAN and DBG log.
11277 * To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level
11278 * To see current setting of debug level,
11279 * cat /sys/kernel/debug/dhd/debug_level
11280 */
11281 static ssize_t
11282 wl_debuglevel_write(struct file *file, const char __user *userbuf,
11283         size_t count, loff_t *ppos)
11284 {
11285         char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)], sublog[S_SUBLOGLEVEL];
11286         char *params, *token, *colon;
11287         uint i, tokens, log_on = 0;
11288         memset(tbuf, 0, sizeof(tbuf));
11289         memset(sublog, 0, sizeof(sublog));
11290         if (copy_from_user(&tbuf, userbuf, min_t(size_t, sizeof(tbuf), count)))
11291                 return -EFAULT;
11292
11293         params = &tbuf[0];
11294         colon = strchr(params, '\n');
11295         if (colon != NULL)
11296                 *colon = '\0';
11297         while ((token = strsep(&params, " ")) != NULL) {
11298                 memset(sublog, 0, sizeof(sublog));
11299                 if (token == NULL || !*token)
11300                         break;
11301                 if (*token == '\0')
11302                         continue;
11303                 colon = strchr(token, ':');
11304                 if (colon != NULL) {
11305                         *colon = ' ';
11306                 }
11307                 tokens = sscanf(token, "%s %u", sublog, &log_on);
11308                 if (colon != NULL)
11309                         *colon = ':';
11310
11311                 if (tokens == 2) {
11312                                 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
11313                                         if (!strncmp(sublog, sublogname_map[i].sublogname,
11314                                                 strlen(sublogname_map[i].sublogname))) {
11315                                                 if (log_on)
11316                                                         wl_dbg_level |=
11317                                                         (sublogname_map[i].log_level);
11318                                                 else
11319                                                         wl_dbg_level &=
11320                                                         ~(sublogname_map[i].log_level);
11321                                         }
11322                                 }
11323                 } else
11324                         WL_ERR(("%s: can't parse '%s' as a "
11325                                "SUBMODULE:LEVEL (%d tokens)\n",
11326                                tbuf, token, tokens));
11327
11328
11329         }
11330         return count;
11331 }
11332
11333 static ssize_t
11334 wl_debuglevel_read(struct file *file, char __user *user_buf,
11335         size_t count, loff_t *ppos)
11336 {
11337         char *param;
11338         char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)];
11339         uint i;
11340         memset(tbuf, 0, sizeof(tbuf));
11341         param = &tbuf[0];
11342         for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
11343                 param += snprintf(param, sizeof(tbuf) - 1, "%s:%d ",
11344                         sublogname_map[i].sublogname,
11345                         (wl_dbg_level & sublogname_map[i].log_level) ? 1 : 0);
11346         }
11347         *param = '\n';
11348         return simple_read_from_buffer(user_buf, count, ppos, tbuf, strlen(&tbuf[0]));
11349
11350 }
11351 static const struct file_operations fops_debuglevel = {
11352         .open = NULL,
11353         .write = wl_debuglevel_write,
11354         .read = wl_debuglevel_read,
11355         .owner = THIS_MODULE,
11356         .llseek = NULL,
11357 };
11358
11359 static s32 wl_setup_debugfs(struct wl_priv *wl)
11360 {
11361         s32 err = 0;
11362         struct dentry *_dentry;
11363         if (!wl)
11364                 return -EINVAL;
11365         wl->debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
11366         if (!wl->debugfs || IS_ERR(wl->debugfs)) {
11367                 if (wl->debugfs == ERR_PTR(-ENODEV))
11368                         WL_ERR(("Debugfs is not enabled on this kernel\n"));
11369                 else
11370                         WL_ERR(("Can not create debugfs directory\n"));
11371                 wl->debugfs = NULL;
11372                 goto exit;
11373
11374         }
11375         _dentry = debugfs_create_file("debug_level", S_IRUSR | S_IWUSR,
11376                 wl->debugfs, wl, &fops_debuglevel);
11377         if (!_dentry || IS_ERR(_dentry)) {
11378                 WL_ERR(("failed to create debug_level debug file\n"));
11379                 wl_free_debugfs(wl);
11380         }
11381 exit:
11382         return err;
11383 }
11384 static s32 wl_free_debugfs(struct wl_priv *wl)
11385 {
11386         if (!wl)
11387                 return -EINVAL;
11388         if (wl->debugfs)
11389                 debugfs_remove_recursive(wl->debugfs);
11390         wl->debugfs = NULL;
11391         return 0;
11392 }
11393 #endif /* DEBUGFS_CFG80211 */
11394
11395 struct device *wl_cfg80211_get_parent_dev(void)
11396 {
11397         return cfg80211_parent_dev;
11398 }
11399
11400 void wl_cfg80211_set_parent_dev(void *dev)
11401 {
11402         cfg80211_parent_dev = dev;
11403 }
11404
11405 static void wl_cfg80211_clear_parent_dev(void)
11406 {
11407         cfg80211_parent_dev = NULL;
11408 }
11409
11410 void get_primary_mac(struct wl_priv *wl, struct ether_addr *mac)
11411 {
11412         wldev_iovar_getbuf_bsscfg(wl_to_prmry_ndev(wl), "cur_etheraddr", NULL,
11413                 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, 0, &wl->ioctl_buf_sync);
11414         memcpy(mac->octet, wl->ioctl_buf, ETHER_ADDR_LEN);
11415 }
11416 static bool check_dev_role_integrity(struct wl_priv *wl, u32 dev_role)
11417 {
11418         dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
11419         if (((dev_role == NL80211_IFTYPE_AP) &&
11420                 !(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) ||
11421                 ((dev_role == NL80211_IFTYPE_P2P_GO) &&
11422                 !(dhd->op_mode & DHD_FLAG_P2P_GO_MODE)))
11423         {
11424                 WL_ERR(("device role select failed\n"));
11425                 return false;
11426         }
11427         return true;
11428 }
11429
11430 int wl_cfg80211_do_driver_init(struct net_device *net)
11431 {
11432         struct wl_priv *wl = *(struct wl_priv **)netdev_priv(net);
11433
11434         if (!wl || !wl->wdev)
11435                 return -EINVAL;
11436
11437         if (dhd_do_driver_init(wl->wdev->netdev) < 0)
11438                 return -1;
11439
11440         return 0;
11441 }
11442
11443 void wl_cfg80211_enable_trace(bool set, u32 level)
11444 {
11445         if (set)
11446                 wl_dbg_level = level & WL_DBG_LEVEL;
11447         else
11448                 wl_dbg_level |= (WL_DBG_LEVEL & level);
11449 }
11450 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
11451         2, 0))
11452 static s32
11453 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
11454         bcm_struct_cfgdev *cfgdev, u64 cookie)
11455 {
11456         /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION
11457          * is passed with CMD_FRAME. This callback is supposed to cancel
11458          * the OFFCHANNEL Wait. Since we are already taking care of that
11459          *  with the tx_mgmt logic, do nothing here.
11460          */
11461
11462         return 0;
11463 }
11464 #endif /* WL_SUPPORT_BACKPORTED_PATCHES || KERNEL >= 3.2.0 */
11465
11466
11467
11468
11469 static void wl_cfg80211_work_handler(struct work_struct * work)
11470 {
11471         struct wl_priv *wl = NULL;
11472         struct net_info *iter, *next;
11473         s32 err = BCME_OK;
11474         s32 pm = PM_FAST;
11475
11476         wl = container_of(work, struct wl_priv, pm_enable_work.work);
11477         WL_DBG(("Enter \n"));
11478         if (wl->pm_enable_work_on) {
11479                 wl->pm_enable_work_on = false;
11480                 for_each_ndev(wl, iter, next) {
11481                         if (!wl_get_drv_status(wl, CONNECTED, iter->ndev) ||
11482                                 (wl_get_mode_by_netdev(wl, iter->ndev) != WL_MODE_BSS))
11483                                 continue;
11484                         if (iter->ndev) {
11485                                 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM,
11486                                         &pm, sizeof(pm), true)) != 0) {
11487                                         if (err == -ENODEV)
11488                                                 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
11489                                         else
11490                                                 WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
11491                                 } else
11492                                         iter->ndev->ieee80211_ptr->ps = true;
11493                         }
11494                 }
11495         }
11496 }
11497
11498 u8
11499 wl_get_action_category(void *frame, u32 frame_len)
11500 {
11501         u8 category;
11502         u8 *ptr = (u8 *)frame;
11503         if (frame == NULL)
11504                 return DOT11_ACTION_CAT_ERR_MASK;
11505         if (frame_len < DOT11_ACTION_HDR_LEN)
11506                 return DOT11_ACTION_CAT_ERR_MASK;
11507         category = ptr[DOT11_ACTION_CAT_OFF];
11508         WL_INFO(("Action Category: %d\n", category));
11509         return category;
11510 }
11511
11512 int
11513 wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action)
11514 {
11515         u8 *ptr = (u8 *)frame;
11516         if (frame == NULL || ret_action == NULL)
11517                 return BCME_ERROR;
11518         if (frame_len < DOT11_ACTION_HDR_LEN)
11519                 return BCME_ERROR;
11520         if (DOT11_ACTION_CAT_PUBLIC != wl_get_action_category(frame, frame_len))
11521                 return BCME_ERROR;
11522         *ret_action = ptr[DOT11_ACTION_ACT_OFF];
11523         WL_INFO(("Public Action : %d\n", *ret_action));
11524         return BCME_OK;
11525 }
11526 #ifdef BCMCCX_S69
11527 static s32
11528 wl_ccx_s69_response(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
11529         const wl_event_msg_t *e, void *data)
11530 {
11531         struct net_device *ndev = NULL;
11532         u32 event = ntoh32(e->event_type);
11533         u32 datalen = ntoh32(e->datalen);
11534         s32 err;
11535
11536         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
11537         err = wl_genl_send_msg(ndev, event, data, (u16)datalen, 0, 0);
11538
11539         return err;
11540 }
11541 #endif /* BCMCCX_S69 */