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