402c9891863eb3e19685e77f08ccd29a44d33417
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rkwifi / bcmdhd / wl_cfg80211.c
1
2 /*
3  * Linux cfg80211 driver
4  *
5  * $Copyright Open Broadcom Corporation$
6  *
7  * $Id: wl_cfg80211.c 419844 2013-08-23 00:07:03Z $
8  */
9 /* */
10 #include <typedefs.h>
11 #include <linuxver.h>
12 #include <osl.h>
13 #include <linux/kernel.h>
14
15 #include <bcmutils.h>
16 #include <bcmwifi_channels.h>
17 #include <bcmendian.h>
18 #include <proto/ethernet.h>
19 #include <proto/802.11.h>
20 #include <linux/if_arp.h>
21 #include <asm/uaccess.h>
22
23 #include <dngl_stats.h>
24 #include <dhd.h>
25 #include <dhdioctl.h>
26 #include <wlioctl.h>
27 #include <dhd_cfg80211.h>
28 #ifdef PNO_SUPPORT
29 #include <dhd_pno.h>
30 #endif /* PNO_SUPPORT */
31
32 #include <proto/ethernet.h>
33 #include <linux/kernel.h>
34 #include <linux/kthread.h>
35 #include <linux/netdevice.h>
36 #include <linux/sched.h>
37 #include <linux/etherdevice.h>
38 #include <linux/wireless.h>
39 #include <linux/ieee80211.h>
40 #include <linux/wait.h>
41 #include <net/cfg80211.h>
42 #include <net/rtnetlink.h>
43
44 #include <wlioctl.h>
45 #include <wldev_common.h>
46 #include <wl_cfg80211.h>
47 #include <wl_cfgp2p.h>
48 #include <wl_android.h>
49 #include <dhd_config.h>
50
51 #ifdef PROP_TXSTATUS
52 #include <dhd_wlfc.h>
53 #endif
54
55 #ifdef WL11U
56 #if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
57 #error You should enable 'WL_ENABLE_P2P_IF' or 'WL_CFG80211_P2P_DEV_IF' \
58         according to Kernel version and is supported only in Android-JB
59 #endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
60 #endif /* WL11U */
61
62 #ifdef BCMWAPI_WPI
63 /* these items should evetually go into wireless.h of the linux system headfile dir */
64 #ifndef IW_ENCODE_ALG_SM4
65 #define IW_ENCODE_ALG_SM4 0x20
66 #endif
67
68 #ifndef IW_AUTH_WAPI_ENABLED
69 #define IW_AUTH_WAPI_ENABLED 0x20
70 #endif
71
72 #ifndef IW_AUTH_WAPI_VERSION_1
73 #define IW_AUTH_WAPI_VERSION_1  0x00000008
74 #endif
75
76 #ifndef IW_AUTH_CIPHER_SMS4
77 #define IW_AUTH_CIPHER_SMS4     0x00000020
78 #endif
79
80 #ifndef IW_AUTH_KEY_MGMT_WAPI_PSK
81 #define IW_AUTH_KEY_MGMT_WAPI_PSK 4
82 #endif
83
84 #ifndef IW_AUTH_KEY_MGMT_WAPI_CERT
85 #define IW_AUTH_KEY_MGMT_WAPI_CERT 8
86 #endif
87 #endif /* BCMWAPI_WPI */
88
89 #ifdef BCMWAPI_WPI
90 #define IW_WSEC_ENABLED(wsec)   ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | SMS4_ENABLED))
91 #else /* BCMWAPI_WPI */
92 #define IW_WSEC_ENABLED(wsec)   ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
93 #endif /* BCMWAPI_WPI */
94
95 static struct device *cfg80211_parent_dev = NULL;
96 struct wl_priv *wlcfg_drv_priv = NULL;
97 u32 wl_dbg_level = WL_DBG_ERR;
98
99 #define MAX_WAIT_TIME 1500
100
101 #ifdef VSDB
102 /* sleep time to keep STA's connecting or connection for continuous af tx or finding a peer */
103 #define DEFAULT_SLEEP_TIME_VSDB         120
104 #define OFF_CHAN_TIME_THRESHOLD_MS      200
105 #define AF_RETRY_DELAY_TIME             40
106
107 /* if sta is connected or connecting, sleep for a while before retry af tx or finding a peer */
108 #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl)   \
109         do {    \
110                 if (wl_get_drv_status(wl, CONNECTED, wl_to_prmry_ndev(wl)) ||   \
111                         wl_get_drv_status(wl, CONNECTING, wl_to_prmry_ndev(wl))) {      \
112                         OSL_SLEEP(DEFAULT_SLEEP_TIME_VSDB);     \
113                 }       \
114         } while (0)
115 #else /* VSDB */
116 /* if not VSDB, do nothing */
117 #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl)
118 #endif /* VSDB */
119
120 #ifdef WL_CFG80211_SYNC_GON
121 #define WL_DRV_STATUS_SENDING_AF_FRM_EXT(wl) \
122         (wl_get_drv_status_all(wl, SENDING_ACT_FRM) || \
123                 wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN))
124 #else
125 #define WL_DRV_STATUS_SENDING_AF_FRM_EXT(wl) wl_get_drv_status_all(wl, SENDING_ACT_FRM)
126 #endif /* WL_CFG80211_SYNC_GON */
127
128 #define WL_CHANSPEC_CTL_SB_NONE WL_CHANSPEC_CTL_SB_LLL
129
130
131 #define DNGL_FUNC(func, parameters) func parameters;
132 #define COEX_DHCP
133
134 #define WLAN_EID_SSID   0
135 #define CH_MIN_5G_CHANNEL 34
136 #define CH_MIN_2G_CHANNEL 1
137
138 /* This is to override regulatory domains defined in cfg80211 module (reg.c)
139  * By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN
140  * and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165).
141  * With respect to these flags, wpa_supplicant doesn't start p2p operations on 5GHz channels.
142  * All the chnages in world regulatory domain are to be done here.
143  */
144 static const struct ieee80211_regdomain brcm_regdom = {
145         .n_reg_rules = 4,
146         .alpha2 =  "99",
147         .reg_rules = {
148                 /* IEEE 802.11b/g, channels 1..11 */
149                 REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
150                 /* If any */
151                 /* IEEE 802.11 channel 14 - Only JP enables
152                  * this and for 802.11b only
153                  */
154                 REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
155                 /* IEEE 802.11a, channel 36..64 */
156                 REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
157                 /* IEEE 802.11a, channel 100..165 */
158                 REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
159 };
160
161 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
162         (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
163 /*
164  * Possible interface combinations supported by driver
165  *
166  * ADHOC Mode     - #ADHOC <= 1 on channels = 1
167  * SoftAP Mode    - #AP <= 1 on channels = 1
168  * STA + P2P Mode - #STA <= 2, #{P2P-GO, P2P-client} <= 1, #P2P-device <= 1
169  *                  on channels = 2
170  */
171 static const struct ieee80211_iface_limit softap_limits[] = {
172         {
173         .max = 1,
174         .types = BIT(NL80211_IFTYPE_AP),
175         },
176 };
177
178 static const struct ieee80211_iface_limit sta_p2p_limits[] = {
179         /*
180          * During P2P-GO removal, P2P-GO is first changed to STA and later only
181          * removed. So setting maximum possible number of STA interfaces as 2 to
182          * accommodate the above behaviour.
183          */
184         {
185         .max = 2,
186         .types = BIT(NL80211_IFTYPE_STATION),
187         },
188         {
189         .max = 2,
190         .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
191         },
192 #if defined(WL_CFG80211_P2P_DEV_IF)
193         {
194         .max = 1,
195         .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
196         },
197 #endif /* WL_CFG80211_P2P_DEV_IF */
198         {
199         .max = 1,
200         .types = BIT(NL80211_IFTYPE_ADHOC),
201         },
202 };
203
204 static const struct ieee80211_iface_combination
205 softap_iface_combinations[] = {
206         {
207         .num_different_channels = 1,
208         .max_interfaces = 1,
209         .limits = softap_limits,
210         .n_limits = ARRAY_SIZE(softap_limits),
211         },
212 };
213
214 static const struct ieee80211_iface_combination
215 sta_p2p_iface_combinations[] = {
216         {
217         .num_different_channels = 2,
218         .max_interfaces = 3,
219         .limits = sta_p2p_limits,
220         .n_limits = ARRAY_SIZE(sta_p2p_limits),
221         },
222 };
223 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
224
225 /* Data Element Definitions */
226 #define WPS_ID_CONFIG_METHODS     0x1008
227 #define WPS_ID_REQ_TYPE           0x103A
228 #define WPS_ID_DEVICE_NAME        0x1011
229 #define WPS_ID_VERSION            0x104A
230 #define WPS_ID_DEVICE_PWD_ID      0x1012
231 #define WPS_ID_REQ_DEV_TYPE       0x106A
232 #define WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS 0x1053
233 #define WPS_ID_PRIM_DEV_TYPE      0x1054
234
235 /* Device Password ID */
236 #define DEV_PW_DEFAULT 0x0000
237 #define DEV_PW_USER_SPECIFIED 0x0001,
238 #define DEV_PW_MACHINE_SPECIFIED 0x0002
239 #define DEV_PW_REKEY 0x0003
240 #define DEV_PW_PUSHBUTTON 0x0004
241 #define DEV_PW_REGISTRAR_SPECIFIED 0x0005
242
243 /* Config Methods */
244 #define WPS_CONFIG_USBA 0x0001
245 #define WPS_CONFIG_ETHERNET 0x0002
246 #define WPS_CONFIG_LABEL 0x0004
247 #define WPS_CONFIG_DISPLAY 0x0008
248 #define WPS_CONFIG_EXT_NFC_TOKEN 0x0010
249 #define WPS_CONFIG_INT_NFC_TOKEN 0x0020
250 #define WPS_CONFIG_NFC_INTERFACE 0x0040
251 #define WPS_CONFIG_PUSHBUTTON 0x0080
252 #define WPS_CONFIG_KEYPAD 0x0100
253 #define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280
254 #define WPS_CONFIG_PHY_PUSHBUTTON 0x0480
255 #define WPS_CONFIG_VIRT_DISPLAY 0x2008
256 #define WPS_CONFIG_PHY_DISPLAY 0x4008
257
258 #define PM_BLOCK 1
259 #define PM_ENABLE 0
260
261 #ifdef BCMCCX
262 #ifndef WLAN_AKM_SUITE_CCKM
263 #define WLAN_AKM_SUITE_CCKM 0x00409600
264 #endif
265 #define DOT11_LEAP_AUTH 0x80 /* LEAP auth frame paylod constants */
266 #endif /* BCMCCX */
267
268 #ifdef MFP
269 #define WL_AKM_SUITE_MFP_1X  0x000FAC05
270 #define WL_AKM_SUITE_MFP_PSK 0x000FAC06
271 #endif /* MFP */
272
273 #ifndef IBSS_COALESCE_ALLOWED
274 #define IBSS_COALESCE_ALLOWED   0
275 #endif
276
277 #ifndef IBSS_INITIAL_SCAN_ALLOWED
278 #define IBSS_INITIAL_SCAN_ALLOWED       0
279 #endif
280 /*
281  * cfg80211_ops api/callback list
282  */
283 static s32 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
284         const struct ether_addr *sa, const struct ether_addr *bssid,
285         u8 **pheader, u32 *body_len, u8 *pbody);
286 static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
287         struct cfg80211_scan_request *request,
288         struct cfg80211_ssid *this_ssid);
289 static s32
290 #if defined(WL_CFG80211_P2P_DEV_IF)
291 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request);
292 #else
293 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
294         struct cfg80211_scan_request *request);
295 #endif /* WL_CFG80211_P2P_DEV_IF */
296 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
297 static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
298         struct cfg80211_ibss_params *params);
299 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy,
300         struct net_device *dev);
301 static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
302         struct net_device *dev, u8 *mac,
303         struct station_info *sinfo);
304 static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
305         struct net_device *dev, bool enabled,
306         s32 timeout);
307 static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
308         struct cfg80211_connect_params *sme);
309 static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
310         u16 reason_code);
311 static s32
312 #if defined(WL_CFG80211_P2P_DEV_IF)
313 wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
314         enum nl80211_tx_power_setting type, s32 mbm);
315 #else
316 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
317         enum nl80211_tx_power_setting type, s32 dbm);
318 #endif /* WL_CFG80211_P2P_DEV_IF */
319 static s32
320 #if defined(WL_CFG80211_P2P_DEV_IF)
321 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
322         struct wireless_dev *wdev, s32 *dbm);
323 #else
324 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
325 #endif /* WL_CFG80211_P2P_DEV_IF */
326 static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
327         struct net_device *dev,
328         u8 key_idx, bool unicast, bool multicast);
329 static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
330         u8 key_idx, bool pairwise, const u8 *mac_addr,
331         struct key_params *params);
332 static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
333         u8 key_idx, bool pairwise, const u8 *mac_addr);
334 static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
335         u8 key_idx, bool pairwise, const u8 *mac_addr,
336         void *cookie, void (*callback) (void *cookie,
337         struct key_params *params));
338 static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
339         struct net_device *dev, u8 key_idx);
340 static s32 wl_cfg80211_resume(struct wiphy *wiphy);
341 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
342         2, 0))
343 static s32 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
344         bcm_struct_cfgdev *cfgdev, u64 cookie);
345 static s32 wl_cfg80211_del_station(struct wiphy *wiphy,
346         struct net_device *ndev, u8* mac_addr);
347 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
348 static s32
349 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)
350 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
351 #else
352 wl_cfg80211_suspend(struct wiphy *wiphy);
353 #endif
354 static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
355         struct cfg80211_pmksa *pmksa);
356 static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
357         struct cfg80211_pmksa *pmksa);
358 static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
359         struct net_device *dev);
360 static void wl_cfg80211_scan_abort(struct wl_priv *wl);
361 static s32 wl_notify_escan_complete(struct wl_priv *wl,
362         struct net_device *ndev, bool aborted, bool fw_abort);
363 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS)
364 static s32 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
365         u8 *peer, enum nl80211_tdls_operation oper);
366 #endif /* LINUX_VERSION > KERNEL_VERSION(3,2,0) || WL_COMPAT_WIRELESS */
367
368 /*
369  * event & event Q handlers for cfg80211 interfaces
370  */
371 static s32 wl_create_event_handler(struct wl_priv *wl);
372 static void wl_destroy_event_handler(struct wl_priv *wl);
373 static s32 wl_event_handler(void *data);
374 static void wl_init_eq(struct wl_priv *wl);
375 static void wl_flush_eq(struct wl_priv *wl);
376 static unsigned long wl_lock_eq(struct wl_priv *wl);
377 static void wl_unlock_eq(struct wl_priv *wl, unsigned long flags);
378 static void wl_init_eq_lock(struct wl_priv *wl);
379 static void wl_init_event_handler(struct wl_priv *wl);
380 static struct wl_event_q *wl_deq_event(struct wl_priv *wl);
381 static s32 wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 type,
382         const wl_event_msg_t *msg, void *data);
383 static void wl_put_event(struct wl_event_q *e);
384 static void wl_wakeup_event(struct wl_priv *wl);
385 static s32 wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev,
386         const wl_event_msg_t *e, void *data);
387 static s32 wl_notify_connect_status(struct wl_priv *wl,
388         bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
389 static s32 wl_notify_roaming_status(struct wl_priv *wl,
390         bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
391 static s32 wl_notify_scan_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
392         const wl_event_msg_t *e, void *data);
393 static s32 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
394         const wl_event_msg_t *e, void *data, bool completed);
395 static s32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
396         const wl_event_msg_t *e, void *data);
397 static s32 wl_notify_mic_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
398         const wl_event_msg_t *e, void *data);
399 #ifdef WL_SCHED_SCAN
400 static s32
401 wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev,
402         const wl_event_msg_t *e, void *data);
403 #endif /* WL_SCHED_SCAN */
404 #ifdef PNO_SUPPORT
405 static s32 wl_notify_pfn_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
406         const wl_event_msg_t *e, void *data);
407 #endif /* PNO_SUPPORT */
408 static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info,
409         enum wl_status state, bool set);
410 #ifdef WL_SDO
411 static s32 wl_svc_resp_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
412         const wl_event_msg_t *e, void *data);
413 static s32 wl_notify_device_discovery(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
414         const wl_event_msg_t *e, void *data);
415 #endif
416
417 #ifdef WLTDLS
418 static s32 wl_tdls_event_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
419         const wl_event_msg_t *e, void *data);
420 #endif /* WLTDLS */
421 /*
422  * register/deregister parent device
423  */
424 static void wl_cfg80211_clear_parent_dev(void);
425
426 /*
427  * ioctl utilites
428  */
429
430 /*
431  * cfg80211 set_wiphy_params utilities
432  */
433 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold);
434 static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold);
435 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
436
437 /*
438  * wl profile utilities
439  */
440 static s32 wl_update_prof(struct wl_priv *wl, struct net_device *ndev,
441         const wl_event_msg_t *e, void *data, s32 item);
442 static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item);
443 static void wl_init_prof(struct wl_priv *wl, struct net_device *ndev);
444
445 /*
446  * cfg80211 connect utilites
447  */
448 static s32 wl_set_wpa_version(struct net_device *dev,
449         struct cfg80211_connect_params *sme);
450 static s32 wl_set_auth_type(struct net_device *dev,
451         struct cfg80211_connect_params *sme);
452 static s32 wl_set_set_cipher(struct net_device *dev,
453         struct cfg80211_connect_params *sme);
454 static s32 wl_set_key_mgmt(struct net_device *dev,
455         struct cfg80211_connect_params *sme);
456 static s32 wl_set_set_sharedkey(struct net_device *dev,
457         struct cfg80211_connect_params *sme);
458 #ifdef BCMWAPI_WPI
459 static s32 wl_set_set_wapi_ie(struct net_device *dev,
460         struct cfg80211_connect_params *sme);
461 #endif
462 static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev);
463 static void wl_ch_to_chanspec(int ch,
464         struct wl_join_params *join_params, size_t *join_params_size);
465
466 /*
467  * information element utilities
468  */
469 static void wl_rst_ie(struct wl_priv *wl);
470 static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v);
471 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size);
472 static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size);
473 static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size);
474 static u32 wl_get_ielen(struct wl_priv *wl);
475 #ifdef MFP
476 static int wl_cfg80211_get_rsn_capa(bcm_tlv_t *wpa2ie, u8* capa);
477 #endif
478
479 #ifdef WL11U
480 bcm_tlv_t *
481 wl_cfg80211_find_interworking_ie(u8 *parse, u32 len);
482 static s32
483 wl_cfg80211_add_iw_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag,
484             uint8 ie_id, uint8 *data, uint8 data_len);
485 #endif /* WL11U */
486
487 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev, void *data);
488 static void wl_free_wdev(struct wl_priv *wl);
489 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
490 static int
491 wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
492 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
493
494 static s32 wl_inform_bss(struct wl_priv *wl);
495 static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi);
496 static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev);
497 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy);
498 s32 wl_cfg80211_channel_to_freq(u32 channel);
499
500 #if defined(DHCP_SCAN_SUPPRESS)
501 static void wl_cfg80211_work_handler(struct work_struct *work);
502 static void wl_cfg80211_scan_supp_timerfunc(ulong data);
503 #endif /* DHCP_SCAN_SUPPRESS */
504
505 static void wl_cfg80211_work_handler(struct work_struct *work);
506 static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
507         u8 key_idx, const u8 *mac_addr,
508         struct key_params *params);
509 /*
510  * key indianess swap utilities
511  */
512 static void swap_key_from_BE(struct wl_wsec_key *key);
513 static void swap_key_to_BE(struct wl_wsec_key *key);
514
515 /*
516  * wl_priv memory init/deinit utilities
517  */
518 static s32 wl_init_priv_mem(struct wl_priv *wl);
519 static void wl_deinit_priv_mem(struct wl_priv *wl);
520
521 static void wl_delay(u32 ms);
522
523 /*
524  * ibss mode utilities
525  */
526 static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev);
527 static __used bool wl_is_ibssstarter(struct wl_priv *wl);
528
529 /*
530  * link up/down , default configuration utilities
531  */
532 static s32 __wl_cfg80211_up(struct wl_priv *wl);
533 static s32 __wl_cfg80211_down(struct wl_priv *wl);
534 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e);
535 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev);
536 static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e);
537 static void wl_link_up(struct wl_priv *wl);
538 static void wl_link_down(struct wl_priv *wl);
539 static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype);
540 static void wl_init_conf(struct wl_conf *conf);
541
542 /*
543  * iscan handler
544  */
545 static void wl_iscan_timer(unsigned long data);
546 static void wl_term_iscan(struct wl_priv *wl);
547 static s32 wl_init_scan(struct wl_priv *wl);
548 static s32 wl_iscan_thread(void *data);
549 static s32 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request,
550         u16 action);
551 static s32 wl_do_iscan(struct wl_priv *wl,  struct cfg80211_scan_request *request);
552 static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan);
553 static s32 wl_invoke_iscan(struct wl_priv *wl);
554 static s32 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
555         struct wl_scan_results **bss_list);
556 static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted);
557 static void wl_init_iscan_handler(struct wl_iscan_ctrl *iscan);
558 static s32 wl_iscan_done(struct wl_priv *wl);
559 static s32 wl_iscan_pending(struct wl_priv *wl);
560 static s32 wl_iscan_inprogress(struct wl_priv *wl);
561 static s32 wl_iscan_aborted(struct wl_priv *wl);
562
563 /*
564  * find most significant bit set
565  */
566 static __used u32 wl_find_msb(u16 bit16);
567
568 /*
569  * rfkill support
570  */
571 static int wl_setup_rfkill(struct wl_priv *wl, bool setup);
572 static int wl_rfkill_set(void *data, bool blocked);
573 #ifdef DEBUGFS_CFG80211
574 static s32 wl_setup_debugfs(struct wl_priv *wl);
575 static s32 wl_free_debugfs(struct wl_priv *wl);
576 #endif
577
578 static wl_scan_params_t *wl_cfg80211_scan_alloc_params(int channel,
579         int nprobes, int *out_params_size);
580 static bool check_dev_role_integrity(struct wl_priv *wl, u32 dev_role);
581
582 /*
583  * Some external functions, TODO: move them to dhd_linux.h
584  */
585 int dhd_add_monitor(char *name, struct net_device **new_ndev);
586 int dhd_del_monitor(struct net_device *ndev);
587 int dhd_monitor_init(void *dhd_pub);
588 int dhd_monitor_uninit(void);
589 int dhd_start_xmit(struct sk_buff *skb, struct net_device *net);
590
591
592 #ifdef WL_SDO
593 s32 wl_cfg80211_sdo_init(struct wl_priv *wl);
594 s32 wl_cfg80211_sdo_deinit(struct wl_priv *wl);
595 #define MAX_SDO_PROTO 5
596 wl_sdo_proto_t wl_sdo_protos [] = {
597         { "all", SVC_RPOTYPE_ALL },
598         { "upnp", SVC_RPOTYPE_UPNP },
599         { "bonjour", SVC_RPOTYPE_BONJOUR },
600         { "wsd", SVC_RPOTYPE_WSD },
601         { "vendor", SVC_RPOTYPE_VENDOR },
602 };
603 #endif
604
605 #define RETURN_EIO_IF_NOT_UP(wlpriv)                                            \
606 do {                                                                    \
607         struct net_device *checkSysUpNDev = wl_to_prmry_ndev(wlpriv);           \
608         if (unlikely(!wl_get_drv_status(wlpriv, READY, checkSysUpNDev))) {      \
609                 WL_INFO(("device is not ready\n"));                     \
610                 return -EIO;                                            \
611         }                                                               \
612 } while (0)
613
614
615 #define IS_WPA_AKM(akm) ((akm) == RSN_AKM_NONE ||                       \
616                                  (akm) == RSN_AKM_UNSPECIFIED ||        \
617                                  (akm) == RSN_AKM_PSK)
618
619
620 extern int dhd_wait_pend8021x(struct net_device *dev);
621 #ifdef PROP_TXSTATUS_VSDB
622 extern int disable_proptx;
623 extern int dhd_wlfc_init(dhd_pub_t *dhd);
624 extern void dhd_wlfc_deinit(dhd_pub_t *dhd);
625 #endif /* PROP_TXSTATUS_VSDB */
626
627 #if (WL_DBG_LEVEL > 0)
628 #define WL_DBG_ESTR_MAX 50
629 static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = {
630         "SET_SSID", "JOIN", "START", "AUTH", "AUTH_IND",
631         "DEAUTH", "DEAUTH_IND", "ASSOC", "ASSOC_IND", "REASSOC",
632         "REASSOC_IND", "DISASSOC", "DISASSOC_IND", "QUIET_START", "QUIET_END",
633         "BEACON_RX", "LINK", "MIC_ERROR", "NDIS_LINK", "ROAM",
634         "TXFAIL", "PMKID_CACHE", "RETROGRADE_TSF", "PRUNE", "AUTOAUTH",
635         "EAPOL_MSG", "SCAN_COMPLETE", "ADDTS_IND", "DELTS_IND", "BCNSENT_IND",
636         "BCNRX_MSG", "BCNLOST_MSG", "ROAM_PREP", "PFN_NET_FOUND",
637         "PFN_NET_LOST",
638         "RESET_COMPLETE", "JOIN_START", "ROAM_START", "ASSOC_START",
639         "IBSS_ASSOC",
640         "RADIO", "PSM_WATCHDOG", "WLC_E_CCX_ASSOC_START", "WLC_E_CCX_ASSOC_ABORT",
641         "PROBREQ_MSG",
642         "SCAN_CONFIRM_IND", "PSK_SUP", "COUNTRY_CODE_CHANGED",
643         "EXCEEDED_MEDIUM_TIME", "ICV_ERROR",
644         "UNICAST_DECODE_ERROR", "MULTICAST_DECODE_ERROR", "TRACE",
645         "WLC_E_BTA_HCI_EVENT", "IF", "WLC_E_P2P_DISC_LISTEN_COMPLETE",
646         "RSSI", "PFN_SCAN_COMPLETE", "WLC_E_EXTLOG_MSG",
647         "ACTION_FRAME", "ACTION_FRAME_COMPLETE", "WLC_E_PRE_ASSOC_IND",
648         "WLC_E_PRE_REASSOC_IND", "WLC_E_CHANNEL_ADOPTED", "WLC_E_AP_STARTED",
649         "WLC_E_DFS_AP_STOP", "WLC_E_DFS_AP_RESUME", "WLC_E_WAI_STA_EVENT",
650         "WLC_E_WAI_MSG", "WLC_E_ESCAN_RESULT", "WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE",
651         "WLC_E_PROBRESP_MSG", "WLC_E_P2P_PROBREQ_MSG", "WLC_E_DCS_REQUEST", "WLC_E_FIFO_CREDIT_MAP",
652         "WLC_E_ACTION_FRAME_RX", "WLC_E_WAKE_EVENT", "WLC_E_RM_COMPLETE"
653 };
654 #endif                          /* WL_DBG_LEVEL */
655
656 #define CHAN2G(_channel, _freq, _flags) {                       \
657         .band                   = IEEE80211_BAND_2GHZ,          \
658         .center_freq            = (_freq),                      \
659         .hw_value               = (_channel),                   \
660         .flags                  = (_flags),                     \
661         .max_antenna_gain       = 0,                            \
662         .max_power              = 30,                           \
663 }
664
665 #define CHAN5G(_channel, _flags) {                              \
666         .band                   = IEEE80211_BAND_5GHZ,          \
667         .center_freq            = 5000 + (5 * (_channel)),      \
668         .hw_value               = (_channel),                   \
669         .flags                  = (_flags),                     \
670         .max_antenna_gain       = 0,                            \
671         .max_power              = 30,                           \
672 }
673
674 #define RATE_TO_BASE100KBPS(rate)   (((rate) * 10) / 2)
675 #define RATETAB_ENT(_rateid, _flags) \
676         {                                                               \
677                 .bitrate        = RATE_TO_BASE100KBPS(_rateid),     \
678                 .hw_value       = (_rateid),                        \
679                 .flags    = (_flags),                        \
680         }
681
682 static struct ieee80211_rate __wl_rates[] = {
683         RATETAB_ENT(DOT11_RATE_1M, 0),
684         RATETAB_ENT(DOT11_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
685         RATETAB_ENT(DOT11_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
686         RATETAB_ENT(DOT11_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
687         RATETAB_ENT(DOT11_RATE_6M, 0),
688         RATETAB_ENT(DOT11_RATE_9M, 0),
689         RATETAB_ENT(DOT11_RATE_12M, 0),
690         RATETAB_ENT(DOT11_RATE_18M, 0),
691         RATETAB_ENT(DOT11_RATE_24M, 0),
692         RATETAB_ENT(DOT11_RATE_36M, 0),
693         RATETAB_ENT(DOT11_RATE_48M, 0),
694         RATETAB_ENT(DOT11_RATE_54M, 0)
695 };
696
697 #define wl_a_rates              (__wl_rates + 4)
698 #define wl_a_rates_size 8
699 #define wl_g_rates              (__wl_rates + 0)
700 #define wl_g_rates_size 12
701
702 static struct ieee80211_channel __wl_2ghz_channels[] = {
703         CHAN2G(1, 2412, 0),
704         CHAN2G(2, 2417, 0),
705         CHAN2G(3, 2422, 0),
706         CHAN2G(4, 2427, 0),
707         CHAN2G(5, 2432, 0),
708         CHAN2G(6, 2437, 0),
709         CHAN2G(7, 2442, 0),
710         CHAN2G(8, 2447, 0),
711         CHAN2G(9, 2452, 0),
712         CHAN2G(10, 2457, 0),
713         CHAN2G(11, 2462, 0),
714         CHAN2G(12, 2467, 0),
715         CHAN2G(13, 2472, 0),
716         CHAN2G(14, 2484, 0)
717 };
718
719 static struct ieee80211_channel __wl_5ghz_a_channels[] = {
720         CHAN5G(34, 0), CHAN5G(36, 0),
721         CHAN5G(38, 0), CHAN5G(40, 0),
722         CHAN5G(42, 0), CHAN5G(44, 0),
723         CHAN5G(46, 0), CHAN5G(48, 0),
724         CHAN5G(52, 0), CHAN5G(56, 0),
725         CHAN5G(60, 0), CHAN5G(64, 0),
726         CHAN5G(100, 0), CHAN5G(104, 0),
727         CHAN5G(108, 0), CHAN5G(112, 0),
728         CHAN5G(116, 0), CHAN5G(120, 0),
729         CHAN5G(124, 0), CHAN5G(128, 0),
730         CHAN5G(132, 0), CHAN5G(136, 0),
731         CHAN5G(140, 0), CHAN5G(149, 0),
732         CHAN5G(153, 0), CHAN5G(157, 0),
733         CHAN5G(161, 0), CHAN5G(165, 0)
734 };
735
736 static struct ieee80211_supported_band __wl_band_2ghz = {
737         .band = IEEE80211_BAND_2GHZ,
738         .channels = __wl_2ghz_channels,
739         .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
740         .bitrates = wl_g_rates,
741         .n_bitrates = wl_g_rates_size
742 };
743
744 static struct ieee80211_supported_band __wl_band_5ghz_a = {
745         .band = IEEE80211_BAND_5GHZ,
746         .channels = __wl_5ghz_a_channels,
747         .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
748         .bitrates = wl_a_rates,
749         .n_bitrates = wl_a_rates_size
750 };
751
752 static const u32 __wl_cipher_suites[] = {
753         WLAN_CIPHER_SUITE_WEP40,
754         WLAN_CIPHER_SUITE_WEP104,
755         WLAN_CIPHER_SUITE_TKIP,
756         WLAN_CIPHER_SUITE_CCMP,
757         WLAN_CIPHER_SUITE_AES_CMAC,
758 #ifdef BCMWAPI_WPI
759         WLAN_CIPHER_SUITE_SMS4,
760 #endif
761 #if defined(WLFBT) && defined(WLAN_CIPHER_SUITE_PMK)
762         WLAN_CIPHER_SUITE_PMK,
763 #endif
764 };
765
766
767 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
768 static int maxrxpktglom = 0;
769 #endif
770
771 /* IOCtl version read from targeted driver */
772 static int ioctl_version;
773 #ifdef DEBUGFS_CFG80211
774 #define S_SUBLOGLEVEL 20
775 static const struct {
776         u32 log_level;
777         char *sublogname;
778 } sublogname_map[] = {
779         {WL_DBG_ERR, "ERR"},
780         {WL_DBG_INFO, "INFO"},
781         {WL_DBG_DBG, "DBG"},
782         {WL_DBG_SCAN, "SCAN"},
783         {WL_DBG_TRACE, "TRACE"},
784         {WL_DBG_P2P_ACTION, "P2PACTION"}
785 };
786 #endif
787
788
789 /* Return a new chanspec given a legacy chanspec
790  * Returns INVCHANSPEC on error
791  */
792 static chanspec_t
793 wl_chspec_from_legacy(chanspec_t legacy_chspec)
794 {
795         chanspec_t chspec;
796
797         /* get the channel number */
798         chspec = LCHSPEC_CHANNEL(legacy_chspec);
799
800         /* convert the band */
801         if (LCHSPEC_IS2G(legacy_chspec)) {
802                 chspec |= WL_CHANSPEC_BAND_2G;
803         } else {
804                 chspec |= WL_CHANSPEC_BAND_5G;
805         }
806
807         /* convert the bw and sideband */
808         if (LCHSPEC_IS20(legacy_chspec)) {
809                 chspec |= WL_CHANSPEC_BW_20;
810         } else {
811                 chspec |= WL_CHANSPEC_BW_40;
812                 if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
813                         chspec |= WL_CHANSPEC_CTL_SB_L;
814                 } else {
815                         chspec |= WL_CHANSPEC_CTL_SB_U;
816                 }
817         }
818
819         if (wf_chspec_malformed(chspec)) {
820                 WL_ERR(("wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
821                         chspec));
822                 return INVCHANSPEC;
823         }
824
825         return chspec;
826 }
827
828 /* Return a legacy chanspec given a new chanspec
829  * Returns INVCHANSPEC on error
830  */
831 static chanspec_t
832 wl_chspec_to_legacy(chanspec_t chspec)
833 {
834         chanspec_t lchspec;
835
836         if (wf_chspec_malformed(chspec)) {
837                 WL_ERR(("wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n",
838                         chspec));
839                 return INVCHANSPEC;
840         }
841
842         /* get the channel number */
843         lchspec = CHSPEC_CHANNEL(chspec);
844
845         /* convert the band */
846         if (CHSPEC_IS2G(chspec)) {
847                 lchspec |= WL_LCHANSPEC_BAND_2G;
848         } else {
849                 lchspec |= WL_LCHANSPEC_BAND_5G;
850         }
851
852         /* convert the bw and sideband */
853         if (CHSPEC_IS20(chspec)) {
854                 lchspec |= WL_LCHANSPEC_BW_20;
855                 lchspec |= WL_LCHANSPEC_CTL_SB_NONE;
856         } else if (CHSPEC_IS40(chspec)) {
857                 lchspec |= WL_LCHANSPEC_BW_40;
858                 if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_L) {
859                         lchspec |= WL_LCHANSPEC_CTL_SB_LOWER;
860                 } else {
861                         lchspec |= WL_LCHANSPEC_CTL_SB_UPPER;
862                 }
863         } else {
864                 /* cannot express the bandwidth */
865                 char chanbuf[CHANSPEC_STR_LEN];
866                 WL_ERR((
867                         "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) "
868                         "to pre-11ac format\n",
869                         wf_chspec_ntoa(chspec, chanbuf), chspec));
870                 return INVCHANSPEC;
871         }
872
873         return lchspec;
874 }
875
876 /* given a chanspec value, do the endian and chanspec version conversion to
877  * a chanspec_t value
878  * Returns INVCHANSPEC on error
879  */
880 static chanspec_t
881 wl_chspec_host_to_driver(chanspec_t chanspec)
882 {
883         if (ioctl_version == 1) {
884                 chanspec = wl_chspec_to_legacy(chanspec);
885                 if (chanspec == INVCHANSPEC) {
886                         return chanspec;
887                 }
888         }
889         chanspec = htodchanspec(chanspec);
890
891         return chanspec;
892 }
893
894 /* given a channel value, do the endian and chanspec version conversion to
895  * a chanspec_t value
896  * Returns INVCHANSPEC on error
897  */
898 chanspec_t
899 wl_ch_host_to_driver(u16 channel)
900 {
901
902         chanspec_t chanspec;
903
904         chanspec = channel & WL_CHANSPEC_CHAN_MASK;
905
906         if (channel <= CH_MAX_2G_CHANNEL)
907                 chanspec |= WL_CHANSPEC_BAND_2G;
908         else
909                 chanspec |= WL_CHANSPEC_BAND_5G;
910
911         chanspec |= WL_CHANSPEC_BW_20;
912         chanspec |= WL_CHANSPEC_CTL_SB_NONE;
913
914         return wl_chspec_host_to_driver(chanspec);
915 }
916
917 /* given a chanspec value from the driver, do the endian and chanspec version conversion to
918  * a chanspec_t value
919  * Returns INVCHANSPEC on error
920  */
921 static chanspec_t
922 wl_chspec_driver_to_host(chanspec_t chanspec)
923 {
924         chanspec = dtohchanspec(chanspec);
925         if (ioctl_version == 1) {
926                 chanspec = wl_chspec_from_legacy(chanspec);
927         }
928
929         return chanspec;
930 }
931
932 /* There isn't a lot of sense in it, but you can transmit anything you like */
933 static const struct ieee80211_txrx_stypes
934 wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
935         [NL80211_IFTYPE_ADHOC] = {
936                 .tx = 0xffff,
937                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
938         },
939         [NL80211_IFTYPE_STATION] = {
940                 .tx = 0xffff,
941                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
942                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
943         },
944         [NL80211_IFTYPE_AP] = {
945                 .tx = 0xffff,
946                 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
947                 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
948                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
949                 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
950                 BIT(IEEE80211_STYPE_AUTH >> 4) |
951                 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
952                 BIT(IEEE80211_STYPE_ACTION >> 4)
953         },
954         [NL80211_IFTYPE_AP_VLAN] = {
955                 /* copy AP */
956                 .tx = 0xffff,
957                 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
958                 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
959                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
960                 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
961                 BIT(IEEE80211_STYPE_AUTH >> 4) |
962                 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
963                 BIT(IEEE80211_STYPE_ACTION >> 4)
964         },
965         [NL80211_IFTYPE_P2P_CLIENT] = {
966                 .tx = 0xffff,
967                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
968                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
969         },
970         [NL80211_IFTYPE_P2P_GO] = {
971                 .tx = 0xffff,
972                 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
973                 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
974                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
975                 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
976                 BIT(IEEE80211_STYPE_AUTH >> 4) |
977                 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
978                 BIT(IEEE80211_STYPE_ACTION >> 4)
979         },
980 #if defined(WL_CFG80211_P2P_DEV_IF)
981         [NL80211_IFTYPE_P2P_DEVICE] = {
982                 .tx = 0xffff,
983                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
984                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
985         },
986 #endif /* WL_CFG80211_P2P_DEV_IF */
987 };
988
989 static void swap_key_from_BE(struct wl_wsec_key *key)
990 {
991         key->index = htod32(key->index);
992         key->len = htod32(key->len);
993         key->algo = htod32(key->algo);
994         key->flags = htod32(key->flags);
995         key->rxiv.hi = htod32(key->rxiv.hi);
996         key->rxiv.lo = htod16(key->rxiv.lo);
997         key->iv_initialized = htod32(key->iv_initialized);
998 }
999
1000 static void swap_key_to_BE(struct wl_wsec_key *key)
1001 {
1002         key->index = dtoh32(key->index);
1003         key->len = dtoh32(key->len);
1004         key->algo = dtoh32(key->algo);
1005         key->flags = dtoh32(key->flags);
1006         key->rxiv.hi = dtoh32(key->rxiv.hi);
1007         key->rxiv.lo = dtoh16(key->rxiv.lo);
1008         key->iv_initialized = dtoh32(key->iv_initialized);
1009 }
1010
1011 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !defined(WL_COMPAT_WIRELESS)
1012 /* For debug: Dump the contents of the encoded wps ie buffe */
1013 static void
1014 wl_validate_wps_ie(char *wps_ie, s32 wps_ie_len, bool *pbc)
1015 {
1016         #define WPS_IE_FIXED_LEN 6
1017         u16 len;
1018         u8 *subel = NULL;
1019         u16 subelt_id;
1020         u16 subelt_len;
1021         u16 val;
1022         u8 *valptr = (uint8*) &val;
1023         if (wps_ie == NULL || wps_ie_len < WPS_IE_FIXED_LEN) {
1024                 WL_ERR(("invalid argument : NULL\n"));
1025                 return;
1026         }
1027         len = (u16)wps_ie[TLV_LEN_OFF];
1028
1029         if (len > wps_ie_len) {
1030                 WL_ERR(("invalid length len %d, wps ie len %d\n", len, wps_ie_len));
1031                 return;
1032         }
1033         WL_DBG(("wps_ie len=%d\n", len));
1034         len -= 4;       /* for the WPS IE's OUI, oui_type fields */
1035         subel = wps_ie + WPS_IE_FIXED_LEN;
1036         while (len >= 4) {              /* must have attr id, attr len fields */
1037                 valptr[0] = *subel++;
1038                 valptr[1] = *subel++;
1039                 subelt_id = HTON16(val);
1040
1041                 valptr[0] = *subel++;
1042                 valptr[1] = *subel++;
1043                 subelt_len = HTON16(val);
1044
1045                 len -= 4;                       /* for the attr id, attr len fields */
1046                 len -= subelt_len;      /* for the remaining fields in this attribute */
1047                 WL_DBG((" subel=%p, subelt_id=0x%x subelt_len=%u\n",
1048                         subel, subelt_id, subelt_len));
1049
1050                 if (subelt_id == WPS_ID_VERSION) {
1051                         WL_DBG(("  attr WPS_ID_VERSION: %u\n", *subel));
1052                 } else if (subelt_id == WPS_ID_REQ_TYPE) {
1053                         WL_DBG(("  attr WPS_ID_REQ_TYPE: %u\n", *subel));
1054                 } else if (subelt_id == WPS_ID_CONFIG_METHODS) {
1055                         valptr[0] = *subel;
1056                         valptr[1] = *(subel + 1);
1057                         WL_DBG(("  attr WPS_ID_CONFIG_METHODS: %x\n", HTON16(val)));
1058                 } else if (subelt_id == WPS_ID_DEVICE_NAME) {
1059                         char devname[100];
1060                         memcpy(devname, subel, subelt_len);
1061                         devname[subelt_len] = '\0';
1062                         WL_DBG(("  attr WPS_ID_DEVICE_NAME: %s (len %u)\n",
1063                                 devname, subelt_len));
1064                 } else if (subelt_id == WPS_ID_DEVICE_PWD_ID) {
1065                         valptr[0] = *subel;
1066                         valptr[1] = *(subel + 1);
1067                         WL_DBG(("  attr WPS_ID_DEVICE_PWD_ID: %u\n", HTON16(val)));
1068                         *pbc = (HTON16(val) == DEV_PW_PUSHBUTTON) ? true : false;
1069                 } else if (subelt_id == WPS_ID_PRIM_DEV_TYPE) {
1070                         valptr[0] = *subel;
1071                         valptr[1] = *(subel + 1);
1072                         WL_DBG(("  attr WPS_ID_PRIM_DEV_TYPE: cat=%u \n", HTON16(val)));
1073                         valptr[0] = *(subel + 6);
1074                         valptr[1] = *(subel + 7);
1075                         WL_DBG(("  attr WPS_ID_PRIM_DEV_TYPE: subcat=%u\n", HTON16(val)));
1076                 } else if (subelt_id == WPS_ID_REQ_DEV_TYPE) {
1077                         valptr[0] = *subel;
1078                         valptr[1] = *(subel + 1);
1079                         WL_DBG(("  attr WPS_ID_REQ_DEV_TYPE: cat=%u\n", HTON16(val)));
1080                         valptr[0] = *(subel + 6);
1081                         valptr[1] = *(subel + 7);
1082                         WL_DBG(("  attr WPS_ID_REQ_DEV_TYPE: subcat=%u\n", HTON16(val)));
1083                 } else if (subelt_id == WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS) {
1084                         valptr[0] = *subel;
1085                         valptr[1] = *(subel + 1);
1086                         WL_DBG(("  attr WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS"
1087                                 ": cat=%u\n", HTON16(val)));
1088                 } else {
1089                         WL_DBG(("  unknown attr 0x%x\n", subelt_id));
1090                 }
1091
1092                 subel += subelt_len;
1093         }
1094 }
1095 #endif /* LINUX_VERSION < VERSION(3, 4, 0) && !WL_COMPAT_WIRELESS */
1096
1097 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
1098 {
1099         chanspec_t chspec;
1100         int err = 0;
1101         struct wl_priv *wl = wiphy_priv(wiphy);
1102         struct net_device *dev = wl_to_prmry_ndev(wl);
1103         struct ether_addr bssid;
1104         struct wl_bss_info *bss = NULL;
1105
1106         if ((err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), false))) {
1107                 /* STA interface is not associated. So start the new interface on a temp
1108                  * channel . Later proper channel will be applied by the above framework
1109                  * via set_channel (cfg80211 API).
1110                  */
1111                 WL_DBG(("Not associated. Return a temp channel. \n"));
1112                 return wl_ch_host_to_driver(WL_P2P_TEMP_CHAN);
1113         }
1114
1115
1116         *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
1117         if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, wl->extra_buf,
1118                 WL_EXTRA_BUF_MAX, false))) {
1119                         WL_ERR(("Failed to get associated bss info, use temp channel \n"));
1120                         chspec = wl_ch_host_to_driver(WL_P2P_TEMP_CHAN);
1121         }
1122         else {
1123                         bss = (struct wl_bss_info *) (wl->extra_buf + 4);
1124                         chspec =  bss->chanspec;
1125
1126                         WL_DBG(("Valid BSS Found. chanspec:%d \n", chspec));
1127         }
1128         return chspec;
1129 }
1130
1131 static bcm_struct_cfgdev *
1132 wl_cfg80211_add_monitor_if(char *name)
1133 {
1134 #if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)
1135         WL_INFO(("wl_cfg80211_add_monitor_if: No more support monitor interface\n"));
1136         return ERR_PTR(-EOPNOTSUPP);
1137 #else
1138         struct net_device* ndev = NULL;
1139
1140         dhd_add_monitor(name, &ndev);
1141         WL_INFO(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev));
1142         return ndev_to_cfgdev(ndev);
1143 #endif /* WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF */
1144 }
1145
1146 static bcm_struct_cfgdev *
1147 wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
1148 #if defined(WL_CFG80211_P2P_DEV_IF)
1149         const char *name,
1150 #else
1151         char *name,
1152 #endif /* WL_CFG80211_P2P_DEV_IF */
1153         enum nl80211_iftype type, u32 *flags,
1154         struct vif_params *params)
1155 {
1156         s32 err;
1157         s32 timeout = -1;
1158         s32 wlif_type = -1;
1159         s32 mode = 0;
1160         s32 val = 0;
1161         s32 dhd_mode = 0;
1162         chanspec_t chspec;
1163         struct wl_priv *wl = wiphy_priv(wiphy);
1164         struct net_device *_ndev;
1165         struct ether_addr primary_mac;
1166         int (*net_attach)(void *dhdp, int ifidx);
1167         bool rollback_lock = false;
1168 #ifdef PROP_TXSTATUS_VSDB
1169         s32 up = 1;
1170         dhd_pub_t *dhd;
1171 #endif /* PROP_TXSTATUS_VSDB */
1172
1173         if (!wl)
1174                 return ERR_PTR(-EINVAL);
1175
1176 #ifdef PROP_TXSTATUS_VSDB
1177         dhd = (dhd_pub_t *)(wl->pub);
1178 #endif /* PROP_TXSTATUS_VSDB */
1179
1180         /* Use primary I/F for sending cmds down to firmware */
1181         _ndev = wl_to_prmry_ndev(wl);
1182
1183         WL_DBG(("if name: %s, type: %d\n", name, type));
1184         switch (type) {
1185         case NL80211_IFTYPE_ADHOC:
1186         case NL80211_IFTYPE_AP_VLAN:
1187         case NL80211_IFTYPE_WDS:
1188         case NL80211_IFTYPE_MESH_POINT:
1189                 WL_ERR(("Unsupported interface type\n"));
1190                 mode = WL_MODE_IBSS;
1191                 return NULL;
1192         case NL80211_IFTYPE_MONITOR:
1193                 return wl_cfg80211_add_monitor_if((char *)name);
1194 #if defined(WL_CFG80211_P2P_DEV_IF)
1195         case NL80211_IFTYPE_P2P_DEVICE:
1196                 return wl_cfgp2p_add_p2p_disc_if();
1197 #endif /* WL_CFG80211_P2P_DEV_IF */
1198         case NL80211_IFTYPE_P2P_CLIENT:
1199         case NL80211_IFTYPE_STATION:
1200                 wlif_type = WL_P2P_IF_CLIENT;
1201                 mode = WL_MODE_BSS;
1202                 break;
1203         case NL80211_IFTYPE_P2P_GO:
1204         case NL80211_IFTYPE_AP:
1205                 wlif_type = WL_P2P_IF_GO;
1206                 mode = WL_MODE_AP;
1207                 break;
1208         default:
1209                 WL_ERR(("Unsupported interface type\n"));
1210                 return NULL;
1211                 break;
1212         }
1213
1214         if (!name) {
1215                 WL_ERR(("name is NULL\n"));
1216                 return NULL;
1217         }
1218         if (wl->p2p_supported && (wlif_type != -1)) {
1219                 ASSERT(wl->p2p); /* ensure expectation of p2p initialization */
1220                 if (wl_get_p2p_status(wl, IF_DELETING)) {
1221                         /* wait till IF_DEL is complete
1222                          * release the lock for the unregister to proceed
1223                          */
1224                         if (rtnl_is_locked()) {
1225                                 rtnl_unlock();
1226                                 rollback_lock = true;
1227                         }
1228                         WL_INFO(("Released the lock and wait till IF_DEL is complete\n"));
1229                         timeout = wait_event_interruptible_timeout(wl->netif_change_event,
1230                                 (wl_get_p2p_status(wl, IF_DELETING) == false),
1231                                 msecs_to_jiffies(MAX_WAIT_TIME));
1232
1233                         /* put back the rtnl_lock again */
1234                         if (rollback_lock) {
1235                                 rtnl_lock();
1236                                 rollback_lock = false;
1237                         }
1238                         if (timeout > 0) {
1239                                 WL_ERR(("IF DEL is Success\n"));
1240
1241                         } else {
1242                                 WL_ERR(("timeount < 0, return -EAGAIN\n"));
1243                                 return ERR_PTR(-EAGAIN);
1244                         }
1245                         /* It should be now be safe to put this check here since we are sure
1246                          * by now netdev_notifier (unregister) would have been called
1247                          */
1248                         if (wl->iface_cnt == IFACE_MAX_CNT)
1249                                 return ERR_PTR(-ENOMEM);
1250                 }
1251
1252 #ifdef PROP_TXSTATUS_VSDB
1253                 if (!dhd)
1254                         return ERR_PTR(-ENODEV);
1255 #endif /* PROP_TXSTATUS_VSDB */
1256                 if (!wl->p2p)
1257                         return ERR_PTR(-ENODEV);
1258
1259                 if (wl->p2p && !wl->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
1260                         p2p_on(wl) = true;
1261                         wl_cfgp2p_set_firm_p2p(wl);
1262                         wl_cfgp2p_init_discovery(wl);
1263                         get_primary_mac(wl, &primary_mac);
1264                         wl_cfgp2p_generate_bss_mac(&primary_mac,
1265                                 &wl->p2p->dev_addr, &wl->p2p->int_addr);
1266                 }
1267
1268                 memset(wl->p2p->vir_ifname, 0, IFNAMSIZ);
1269                 strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1);
1270
1271                 wl_cfg80211_scan_abort(wl);
1272 #ifdef PROP_TXSTATUS_VSDB
1273                 if (!wl->wlfc_on && !disable_proptx) {
1274                         dhd->wlfc_enabled = true;
1275                         dhd_wlfc_init(dhd);
1276                         err = wldev_ioctl(_ndev, WLC_UP, &up, sizeof(s32), true);
1277                         if (err < 0)
1278                                 WL_ERR(("WLC_UP return err:%d\n", err));
1279                         wl->wlfc_on = true;
1280                 }
1281 #endif /* PROP_TXSTATUS_VSDB */
1282
1283                 /* In concurrency case, STA may be already associated in a particular channel.
1284                  * so retrieve the current channel of primary interface and then start the virtual
1285                  * interface on that.
1286                  */
1287                  chspec = wl_cfg80211_get_shared_freq(wiphy);
1288
1289                 /* For P2P mode, use P2P-specific driver features to create the
1290                  * bss: "wl p2p_ifadd"
1291                  */
1292                 wl_set_p2p_status(wl, IF_ADD);
1293                 if (wlif_type == WL_P2P_IF_GO)
1294                         wldev_iovar_setint(_ndev, "mpc", 0);
1295                 err = wl_cfgp2p_ifadd(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec);
1296
1297                 if (unlikely(err)) {
1298                         WL_ERR((" virtual iface add failed (%d) \n", err));
1299                         return ERR_PTR(-ENOMEM);
1300                 }
1301
1302                 timeout = wait_event_interruptible_timeout(wl->netif_change_event,
1303                         (wl_get_p2p_status(wl, IF_ADD) == false),
1304                         msecs_to_jiffies(MAX_WAIT_TIME));
1305                 if (timeout > 0 && (!wl_get_p2p_status(wl, IF_ADD))) {
1306
1307                         struct wireless_dev *vwdev;
1308                         vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL);
1309                         if (unlikely(!vwdev)) {
1310                                 WL_ERR(("Could not allocate wireless device\n"));
1311                                 return ERR_PTR(-ENOMEM);
1312                         }
1313                         vwdev->wiphy = wl->wdev->wiphy;
1314                         WL_INFO((" virtual interface(%s) is created memalloc done \n",
1315                                 wl->p2p->vir_ifname));
1316                         vwdev->iftype = type;
1317                         _ndev =  wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
1318                         _ndev->ieee80211_ptr = vwdev;
1319                         SET_NETDEV_DEV(_ndev, wiphy_dev(vwdev->wiphy));
1320                         vwdev->netdev = _ndev;
1321                         wl_set_drv_status(wl, READY, _ndev);
1322                         wl->p2p->vif_created = true;
1323                         wl_set_mode_by_netdev(wl, _ndev, mode);
1324                         net_attach =  wl_to_p2p_bss_private(wl, P2PAPI_BSSCFG_CONNECTION);
1325                         if (rtnl_is_locked()) {
1326                                 rtnl_unlock();
1327                                 rollback_lock = true;
1328                         }
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->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                                 /* put back the rtnl_lock again */
1355                                 if (rollback_lock)
1356                                         rtnl_lock();
1357                                 goto fail;
1358                         }
1359                         /* put back the rtnl_lock again */
1360                         if (rollback_lock)
1361                                 rtnl_lock();
1362                         return ndev_to_cfgdev(_ndev);
1363                 } else {
1364                         wl_clr_p2p_status(wl, IF_ADD);
1365                         WL_ERR((" virtual interface(%s) is not created \n", wl->p2p->vir_ifname));
1366                         memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ);
1367                         wl->p2p->vif_created = false;
1368 #ifdef PROP_TXSTATUS_VSDB
1369                 if (dhd->wlfc_enabled && wl->wlfc_on) {
1370                         dhd->wlfc_enabled = false;
1371                         dhd_wlfc_deinit(dhd);
1372                         if (dhd->plat_deinit)
1373                                 dhd->plat_deinit((void *)dhd);
1374                         wl->wlfc_on = false;
1375                 }
1376 #endif /* PROP_TXSTATUS_VSDB */
1377                 }
1378         }
1379 fail:
1380         if (wlif_type == WL_P2P_IF_GO)
1381                 wldev_iovar_setint(_ndev, "mpc", 1);
1382         return ERR_PTR(-ENODEV);
1383 }
1384
1385 static s32
1386 wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
1387 {
1388         struct net_device *dev = NULL;
1389         struct ether_addr p2p_mac;
1390         struct wl_priv *wl = wiphy_priv(wiphy);
1391         s32 timeout = -1;
1392         s32 ret = 0;
1393         s32 index = -1;
1394         WL_DBG(("Enter\n"));
1395
1396 #if defined(WL_CFG80211_P2P_DEV_IF)
1397         if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
1398                 return wl_cfgp2p_del_p2p_disc_if(cfgdev);
1399         }
1400 #endif /* WL_CFG80211_P2P_DEV_IF */
1401         dev = cfgdev_to_wlc_ndev(cfgdev, wl);
1402
1403         if (wl_cfgp2p_find_idx(wl, dev, &index) != BCME_OK) {
1404                 WL_ERR(("Find p2p index from ndev(%p) failed\n", dev));
1405                 return BCME_ERROR;
1406         }
1407         if (wl->p2p_supported) {
1408                 memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN);
1409
1410                 /* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases
1411                  */
1412                 WL_DBG(("P2P: GO_NEG_PHASE status cleared "));
1413                 wl_clr_p2p_status(wl, GO_NEG_PHASE);
1414                 if (wl->p2p->vif_created) {
1415                         if (wl_get_drv_status(wl, SCANNING, dev)) {
1416                                 wl_notify_escan_complete(wl, dev, true, true);
1417                         }
1418                         wldev_iovar_setint(dev, "mpc", 1);
1419
1420                         if (wl->pm_enable_work_on) {
1421                                 cancel_delayed_work_sync(&wl->pm_enable_work);
1422                                 wl->pm_enable_work_on = false;
1423                         }
1424
1425                         /* for GC */
1426                         if (wl_get_drv_status(wl, DISCONNECTING, dev) &&
1427                                 (wl_get_mode_by_netdev(wl, dev) != WL_MODE_AP)) {
1428                                 WL_ERR(("Wait for Link Down event for GC !\n"));
1429                                 wait_for_completion_timeout
1430                                         (&wl->iface_disable, msecs_to_jiffies(500));
1431                         }
1432                         wl_set_p2p_status(wl, IF_DELETING);
1433                         DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (wl));
1434
1435                         /* for GO */
1436                         if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) {
1437                                 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
1438                                 /* disable interface before bsscfg free */
1439                                 ret = wl_cfgp2p_ifdisable(wl, &p2p_mac);
1440                                 /* if fw doesn't support "ifdis",
1441                                    do not wait for link down of ap mode
1442                                  */
1443                                 if (ret == 0) {
1444                                         WL_ERR(("Wait for Link Down event for GO !!!\n"));
1445                                         wait_for_completion_timeout(&wl->iface_disable,
1446                                                 msecs_to_jiffies(500));
1447                                 }
1448                         }
1449                         wl_cfgp2p_clear_management_ie(wl, index);
1450
1451                         if (wl_get_mode_by_netdev(wl, dev) != WL_MODE_AP)
1452                                 wldev_iovar_setint(dev, "buf_key_b4_m4", 0);
1453
1454                         /* delete interface after link down */
1455                         ret = wl_cfgp2p_ifdel(wl, &p2p_mac);
1456                         /* Firmware could not delete the interface so we will not get WLC_E_IF
1457                         * event for cleaning the dhd virtual nw interace
1458                         * So lets do it here. Failures from fw will ensure the application to do
1459                         * ifconfig <inter> down and up sequnce, which will reload the fw
1460                         * however we should cleanup the linux network virtual interfaces
1461                         */
1462                         /* Request framework to RESET and clean up */
1463                         if (ret) {
1464                                 struct net_device *ndev = wl_to_prmry_ndev(wl);
1465                                 WL_ERR(("Firmware returned an error (%d) from p2p_ifdel"
1466                                         "HANG Notification sent to %s\n", ret, ndev->name));
1467                                 net_os_send_hang_message(ndev);
1468                         }
1469                         /* Wait for IF_DEL operation to be finished in firmware */
1470                         timeout = wait_event_interruptible_timeout(wl->netif_change_event,
1471                                 (wl->p2p->vif_created == false),
1472                                 msecs_to_jiffies(MAX_WAIT_TIME));
1473                         if (timeout > 0 && (wl->p2p->vif_created == false)) {
1474                                 WL_DBG(("IFDEL operation done\n"));
1475                         } else {
1476                                 WL_ERR(("IFDEL didn't complete properly\n"));
1477                         }
1478                         ret = dhd_del_monitor(dev);
1479                 }
1480         }
1481         return ret;
1482 }
1483
1484 static s32
1485 wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
1486         enum nl80211_iftype type, u32 *flags,
1487         struct vif_params *params)
1488 {
1489         s32 ap = 0;
1490         s32 infra = 0;
1491         s32 ibss = 0;
1492         s32 wlif_type;
1493         s32 mode = 0;
1494         s32 err = BCME_OK;
1495         chanspec_t chspec;
1496         struct wl_priv *wl = wiphy_priv(wiphy);
1497         dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
1498         WL_DBG(("Enter type %d\n", type));
1499         switch (type) {
1500         case NL80211_IFTYPE_MONITOR:
1501         case NL80211_IFTYPE_WDS:
1502         case NL80211_IFTYPE_MESH_POINT:
1503                 ap = 1;
1504                 WL_ERR(("type (%d) : currently we do not support this type\n",
1505                         type));
1506                 break;
1507         case NL80211_IFTYPE_ADHOC:
1508                 mode = WL_MODE_IBSS;
1509                 ibss = 1;
1510                 break;
1511         case NL80211_IFTYPE_STATION:
1512         case NL80211_IFTYPE_P2P_CLIENT:
1513                 mode = WL_MODE_BSS;
1514                 infra = 1;
1515                 break;
1516         case NL80211_IFTYPE_AP:
1517         case NL80211_IFTYPE_AP_VLAN:
1518         case NL80211_IFTYPE_P2P_GO:
1519                 mode = WL_MODE_AP;
1520                 ap = 1;
1521                 break;
1522         default:
1523                 return -EINVAL;
1524         }
1525         if (!dhd)
1526                 return -EINVAL;
1527         if (ap) {
1528                 wl_set_mode_by_netdev(wl, ndev, mode);
1529                 if (wl->p2p_supported && wl->p2p->vif_created) {
1530                         WL_DBG(("p2p_vif_created (%d) p2p_on (%d)\n", wl->p2p->vif_created,
1531                         p2p_on(wl)));
1532                         wldev_iovar_setint(ndev, "mpc", 0);
1533                         wl_notify_escan_complete(wl, ndev, true, true);
1534
1535                         /* In concurrency case, STA may be already associated in a particular
1536                          * channel. so retrieve the current channel of primary interface and
1537                          * then start the virtual interface on that.
1538                          */
1539                         chspec = wl_cfg80211_get_shared_freq(wiphy);
1540
1541                         wlif_type = WL_P2P_IF_GO;
1542                         printk("%s : ap (%d), infra (%d), iftype: (%d)\n",
1543                                 ndev->name, ap, infra, type);
1544                         wl_set_p2p_status(wl, IF_CHANGING);
1545                         wl_clr_p2p_status(wl, IF_CHANGED);
1546                         wl_cfgp2p_ifchange(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec);
1547                         wait_event_interruptible_timeout(wl->netif_change_event,
1548                                 (wl_get_p2p_status(wl, IF_CHANGED) == true),
1549                                 msecs_to_jiffies(MAX_WAIT_TIME));
1550                         wl_set_mode_by_netdev(wl, ndev, mode);
1551                         dhd->op_mode &= ~DHD_FLAG_P2P_GC_MODE;
1552                         dhd->op_mode |= DHD_FLAG_P2P_GO_MODE;
1553                         wl_clr_p2p_status(wl, IF_CHANGING);
1554                         wl_clr_p2p_status(wl, IF_CHANGED);
1555                         if (mode == WL_MODE_AP)
1556                                 wl_set_drv_status(wl, CONNECTED, ndev);
1557                 } else if (ndev == wl_to_prmry_ndev(wl) &&
1558                         !wl_get_drv_status(wl, AP_CREATED, ndev)) {
1559                         wl_set_drv_status(wl, AP_CREATING, ndev);
1560                         if (!wl->ap_info &&
1561                                 !(wl->ap_info = kzalloc(sizeof(struct ap_info), GFP_KERNEL))) {
1562                                 WL_ERR(("struct ap_saved_ie allocation failed\n"));
1563                                 return -ENOMEM;
1564                         }
1565                 } else {
1566                         WL_ERR(("Cannot change the interface for GO or SOFTAP\n"));
1567                         return -EINVAL;
1568                 }
1569         } else {
1570                 WL_DBG(("Change_virtual_iface for transition from GO/AP to client/STA"));
1571         }
1572
1573         if (ibss) {
1574                 infra = 0;
1575                 wl_set_mode_by_netdev(wl, ndev, mode);
1576                 err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(s32), true);
1577                 if (err < 0) {
1578                         WL_ERR(("SET Adhoc error %d\n", err));
1579                         return -EINVAL;
1580         }
1581         }
1582
1583         ndev->ieee80211_ptr->iftype = type;
1584         return 0;
1585 }
1586
1587 s32
1588 wl_cfg80211_notify_ifadd(struct net_device *ndev, s32 idx, s32 bssidx,
1589         void* _net_attach)
1590 {
1591         struct wl_priv *wl = wlcfg_drv_priv;
1592         s32 ret = BCME_OK;
1593         WL_DBG(("Enter"));
1594         if (!ndev) {
1595                 WL_ERR(("net is NULL\n"));
1596                 return 0;
1597         }
1598         if (wl->p2p_supported && wl_get_p2p_status(wl, IF_ADD)) {
1599                 WL_DBG(("IF_ADD event called from dongle, old interface name: %s,"
1600                         "new name: %s\n", ndev->name, wl->p2p->vir_ifname));
1601                 /* Assign the net device to CONNECT BSSCFG */
1602                 strncpy(ndev->name, wl->p2p->vir_ifname, IFNAMSIZ - 1);
1603                 wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = ndev;
1604                 wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = bssidx;
1605                 wl_to_p2p_bss_private(wl, P2PAPI_BSSCFG_CONNECTION) = _net_attach;
1606                 ndev->ifindex = idx;
1607                 wl_clr_p2p_status(wl, IF_ADD);
1608
1609                 wake_up_interruptible(&wl->netif_change_event);
1610         } else {
1611                 ret = BCME_NOTREADY;
1612         }
1613         return ret;
1614 }
1615
1616 s32
1617 wl_cfg80211_notify_ifdel(void)
1618 {
1619         struct wl_priv *wl = wlcfg_drv_priv;
1620
1621         WL_DBG(("Enter \n"));
1622         wl_clr_p2p_status(wl, IF_DELETING);
1623         wake_up_interruptible(&wl->netif_change_event);
1624         return 0;
1625 }
1626
1627 s32
1628 wl_cfg80211_ifdel_ops(struct net_device *ndev)
1629 {
1630         struct wl_priv *wl = wlcfg_drv_priv;
1631         bool rollback_lock = false;
1632         s32 type = -1;
1633         s32 bssidx = -1;
1634
1635 #ifdef PROP_TXSTATUS_VSDB
1636         dhd_pub_t *dhd =  (dhd_pub_t *)(wl->pub);
1637 #endif /* PROP_TXSTATUS_VSDB */
1638         if (!ndev || (strlen(ndev->name) == 0)) {
1639                 WL_ERR(("net is NULL\n"));
1640                 return 0;
1641         }
1642
1643         if (p2p_is_on(wl) && wl->p2p->vif_created &&
1644                 wl_get_p2p_status(wl, IF_DELETING)) {
1645                 if (wl->scan_request &&
1646                         (wl->escan_info.ndev == ndev)) {
1647                         /* Abort any pending scan requests */
1648                         wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
1649                         if (!rtnl_is_locked()) {
1650                                 rtnl_lock();
1651                                 rollback_lock = true;
1652                         }
1653                         WL_DBG(("ESCAN COMPLETED\n"));
1654                         wl_notify_escan_complete(wl, ndev, true, false);
1655                         if (rollback_lock)
1656                                 rtnl_unlock();
1657                 }
1658                 WL_ERR(("IF_DEL event called from dongle, net %p, vif name: %s\n",
1659                         ndev, wl->p2p->vir_ifname));
1660
1661                 memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ);
1662                 if (wl_cfgp2p_find_idx(wl, ndev, &bssidx) != BCME_OK) {
1663                         WL_ERR(("Find p2p bssidx from ndev(%p) failed\n", ndev));
1664                         return BCME_ERROR;
1665                 }
1666                 if (wl_cfgp2p_find_type(wl, bssidx, &type) != BCME_OK) {
1667                         WL_ERR(("Find p2p type from bssidx(%d) failed\n", bssidx));
1668                         return BCME_ERROR;
1669                 }
1670                 wl_to_p2p_bss_ndev(wl, type) = NULL;
1671                 wl_to_p2p_bss_bssidx(wl, type) = WL_INVALID;
1672                 wl->p2p->vif_created = false;
1673
1674                 WL_DBG(("type : %d\n", type));
1675 #ifdef PROP_TXSTATUS_VSDB
1676                 if (dhd->wlfc_enabled && wl->wlfc_on) {
1677                         dhd->wlfc_enabled = false;
1678                         dhd_wlfc_deinit(dhd);
1679                         if (dhd->plat_deinit)
1680                                 dhd->plat_deinit((void *)dhd);
1681                         wl->wlfc_on = false;
1682                 }
1683 #endif /* PROP_TXSTATUS_VSDB */
1684                 wl_clr_drv_status(wl, CONNECTED, ndev);
1685         }
1686         /* Wake up any waiting thread */
1687         wake_up_interruptible(&wl->netif_change_event);
1688
1689         return 0;
1690 }
1691
1692 s32
1693 wl_cfg80211_is_progress_ifadd(void)
1694 {
1695         s32 is_progress = 0;
1696         struct wl_priv *wl = wlcfg_drv_priv;
1697         if (wl_get_p2p_status(wl, IF_ADD))
1698                 is_progress = 1;
1699         return is_progress;
1700 }
1701
1702 s32
1703 wl_cfg80211_is_progress_ifchange(void)
1704 {
1705         s32 is_progress = 0;
1706         struct wl_priv *wl = wlcfg_drv_priv;
1707         if (wl_get_p2p_status(wl, IF_CHANGING))
1708                 is_progress = 1;
1709         return is_progress;
1710 }
1711
1712
1713 s32
1714 wl_cfg80211_notify_ifchange(void)
1715 {
1716         struct wl_priv *wl = wlcfg_drv_priv;
1717         if (wl_get_p2p_status(wl, IF_CHANGING)) {
1718                 wl_set_p2p_status(wl, IF_CHANGED);
1719                 wake_up_interruptible(&wl->netif_change_event);
1720         }
1721         return 0;
1722 }
1723
1724 /* Find listen channel */
1725 static s32 wl_find_listen_channel(struct wl_priv *wl,
1726         const u8 *ie, u32 ie_len)
1727 {
1728         wifi_p2p_ie_t *p2p_ie;
1729         u8 *end, *pos;
1730         s32 listen_channel;
1731
1732         pos = (u8 *)ie;
1733         p2p_ie = wl_cfgp2p_find_p2pie(pos, ie_len);
1734
1735         if (p2p_ie == NULL)
1736                 return 0;
1737
1738         pos = p2p_ie->subelts;
1739         end = p2p_ie->subelts + (p2p_ie->len - 4);
1740
1741         CFGP2P_DBG((" found p2p ie ! lenth %d \n",
1742                 p2p_ie->len));
1743
1744         while (pos < end) {
1745                 uint16 attr_len;
1746                 if (pos + 2 >= end) {
1747                         CFGP2P_DBG((" -- Invalid P2P attribute"));
1748                         return 0;
1749                 }
1750                 attr_len = ((uint16) (((pos + 1)[1] << 8) | (pos + 1)[0]));
1751
1752                 if (pos + 3 + attr_len > end) {
1753                         CFGP2P_DBG(("P2P: Attribute underflow "
1754                                    "(len=%u left=%d)",
1755                                    attr_len, (int) (end - pos - 3)));
1756                         return 0;
1757                 }
1758
1759                 /* if Listen Channel att id is 6 and the vailue is valid,
1760                  * return the listen channel
1761                  */
1762                 if (pos[0] == 6) {
1763                         /* listen channel subel length format
1764                          * 1(id) + 2(len) + 3(country) + 1(op. class) + 1(chan num)
1765                          */
1766                         listen_channel = pos[1 + 2 + 3 + 1];
1767
1768                         if (listen_channel == SOCIAL_CHAN_1 ||
1769                                 listen_channel == SOCIAL_CHAN_2 ||
1770                                 listen_channel == SOCIAL_CHAN_3) {
1771                                 CFGP2P_DBG((" Found my Listen Channel %d \n", listen_channel));
1772                                 return listen_channel;
1773                         }
1774                 }
1775                 pos += 3 + attr_len;
1776         }
1777         return 0;
1778 }
1779
1780 static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_request *request)
1781 {
1782         u32 n_ssids;
1783         u32 n_channels;
1784         u16 channel;
1785         chanspec_t chanspec;
1786         s32 i = 0, j = 0, offset;
1787         char *ptr;
1788         wlc_ssid_t ssid;
1789         struct wl_priv *wl = wlcfg_drv_priv;
1790
1791         memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
1792         params->bss_type = DOT11_BSSTYPE_ANY;
1793         params->scan_type = 0;
1794         params->nprobes = -1;
1795         params->active_time = -1;
1796         params->passive_time = -1;
1797         params->home_time = -1;
1798         params->channel_num = 0;
1799         memset(&params->ssid, 0, sizeof(wlc_ssid_t));
1800
1801         WL_SCAN(("Preparing Scan request\n"));
1802         WL_SCAN(("nprobes=%d\n", params->nprobes));
1803         WL_SCAN(("active_time=%d\n", params->active_time));
1804         WL_SCAN(("passive_time=%d\n", params->passive_time));
1805         WL_SCAN(("home_time=%d\n", params->home_time));
1806         WL_SCAN(("scan_type=%d\n", params->scan_type));
1807
1808         params->nprobes = htod32(params->nprobes);
1809         params->active_time = htod32(params->active_time);
1810         params->passive_time = htod32(params->passive_time);
1811         params->home_time = htod32(params->home_time);
1812
1813         /* if request is null just exit so it will be all channel broadcast scan */
1814         if (!request)
1815                 return;
1816
1817         n_ssids = request->n_ssids;
1818         n_channels = request->n_channels;
1819
1820         /* Copy channel array if applicable */
1821         WL_SCAN(("### List of channelspecs to scan ###\n"));
1822         if (n_channels > 0) {
1823                 for (i = 0; i < n_channels; i++) {
1824                         chanspec = 0;
1825                         channel = ieee80211_frequency_to_channel(request->channels[i]->center_freq);
1826                         /* SKIP DFS channels for Secondary interface */
1827                         if ((wl->escan_info.ndev != wl_to_prmry_ndev(wl)) &&
1828                                 (request->channels[i]->flags &
1829                                 (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN)))
1830                                 continue;
1831
1832                         if (request->channels[i]->band == IEEE80211_BAND_2GHZ) {
1833 #ifdef WL_HOST_BAND_MGMT
1834                                 if (wl->curr_band == WLC_BAND_5G) {
1835                                         WL_DBG(("In 5G only mode, omit 2G channel:%d\n", channel));
1836                                         continue;
1837                                 }
1838 #endif /* WL_HOST_BAND_MGMT */
1839                                 chanspec |= WL_CHANSPEC_BAND_2G;
1840                         } else {
1841 #ifdef WL_HOST_BAND_MGMT
1842                                 if (wl->curr_band == WLC_BAND_2G) {
1843                                         WL_DBG(("In 2G only mode, omit 5G channel:%d\n", channel));
1844                                         continue;
1845                                 }
1846 #endif /* WL_HOST_BAND_MGMT */
1847                                 chanspec |= WL_CHANSPEC_BAND_5G;
1848                         }
1849
1850                         chanspec |= WL_CHANSPEC_BW_20;
1851                         chanspec |= WL_CHANSPEC_CTL_SB_NONE;
1852
1853                         params->channel_list[j] = channel;
1854                         params->channel_list[j] &= WL_CHANSPEC_CHAN_MASK;
1855                         params->channel_list[j] |= chanspec;
1856                         WL_SCAN(("Chan : %d, Channel spec: %x \n",
1857                                 channel, params->channel_list[j]));
1858                         params->channel_list[j] = wl_chspec_host_to_driver(params->channel_list[j]);
1859                         j++;
1860                 }
1861         } else {
1862                 WL_SCAN(("Scanning all channels\n"));
1863         }
1864         n_channels = j;
1865         /* Copy ssid array if applicable */
1866         WL_SCAN(("### List of SSIDs to scan ###\n"));
1867         if (n_ssids > 0) {
1868                 offset = offsetof(wl_scan_params_t, channel_list) + n_channels * sizeof(u16);
1869                 offset = roundup(offset, sizeof(u32));
1870                 ptr = (char*)params + offset;
1871                 for (i = 0; i < n_ssids; i++) {
1872                         memset(&ssid, 0, sizeof(wlc_ssid_t));
1873                         ssid.SSID_len = request->ssids[i].ssid_len;
1874                         memcpy(ssid.SSID, request->ssids[i].ssid, ssid.SSID_len);
1875                         if (!ssid.SSID_len)
1876                                 WL_SCAN(("%d: Broadcast scan\n", i));
1877                         else
1878                                 WL_SCAN(("%d: scan  for  %s size =%d\n", i,
1879                                 ssid.SSID, ssid.SSID_len));
1880                         memcpy(ptr, &ssid, sizeof(wlc_ssid_t));
1881                         ptr += sizeof(wlc_ssid_t);
1882                 }
1883         } else {
1884                 WL_SCAN(("Broadcast scan\n"));
1885         }
1886         /* Adding mask to channel numbers */
1887         params->channel_num =
1888                 htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) |
1889                        (n_channels & WL_SCAN_PARAMS_COUNT_MASK));
1890
1891         if (n_channels == 1) {
1892                 params->active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
1893                 params->nprobes = htod32(params->active_time / WL_SCAN_JOIN_PROBE_INTERVAL_MS);
1894         }
1895 }
1896
1897 static s32
1898 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request, u16 action)
1899 {
1900         u32 n_channels;
1901         u32 n_ssids;
1902         s32 params_size =
1903             (WL_SCAN_PARAMS_FIXED_SIZE + offsetof(wl_iscan_params_t, params));
1904         struct wl_iscan_params *params = NULL;
1905         s32 err = 0;
1906
1907         if (request != NULL) {
1908                 n_channels = request->n_channels;
1909                 n_ssids = request->n_ssids;
1910                 /* Allocate space for populating ssids in wl_iscan_params struct */
1911                 if (n_channels % 2)
1912                         /* If n_channels is odd, add a padd of u16 */
1913                         params_size += sizeof(u16) * (n_channels + 1);
1914                 else
1915                         params_size += sizeof(u16) * n_channels;
1916
1917                 /* Allocate space for populating ssids in wl_iscan_params struct */
1918                 params_size += sizeof(struct wlc_ssid) * n_ssids;
1919         }
1920         params = (struct wl_iscan_params *)kzalloc(params_size, GFP_KERNEL);
1921         if (!params) {
1922                 err = -ENOMEM;
1923                 goto done;
1924         }
1925         wl_scan_prep(&params->params, request);
1926
1927         params->version = htod32(ISCAN_REQ_VERSION);
1928         params->action = htod16(action);
1929         params->scan_duration = htod16(0);
1930
1931         if (params_size + sizeof("iscan") >= WLC_IOCTL_MEDLEN) {
1932                 WL_ERR(("ioctl buffer length is not sufficient\n"));
1933                 err = -ENOMEM;
1934                 goto done;
1935         }
1936         err = wldev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
1937                 iscan->ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
1938         if (unlikely(err)) {
1939                 if (err == -EBUSY) {
1940                         WL_ERR(("system busy : iscan canceled\n"));
1941                 } else {
1942                         WL_ERR(("error (%d)\n", err));
1943                 }
1944         }
1945
1946 done:
1947         if (params)
1948                 kfree(params);
1949         return err;
1950 }
1951
1952 static s32 wl_do_iscan(struct wl_priv *wl, struct cfg80211_scan_request *request)
1953 {
1954         struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
1955         struct net_device *ndev = wl_to_prmry_ndev(wl);
1956         s32 passive_scan;
1957         s32 err = 0;
1958
1959         iscan->state = WL_ISCAN_STATE_SCANING;
1960
1961         passive_scan = wl->active_scan ? 0 : 1;
1962         err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
1963                 &passive_scan, sizeof(passive_scan), true);
1964         if (unlikely(err)) {
1965                 WL_DBG(("error (%d)\n", err));
1966                 return err;
1967         }
1968         wl->iscan_kickstart = true;
1969         wl_run_iscan(iscan, request, WL_SCAN_ACTION_START);
1970         mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms));
1971         iscan->timer_on = 1;
1972
1973         return err;
1974 }
1975
1976 static s32
1977 wl_get_valid_channels(struct net_device *ndev, u8 *valid_chan_list, s32 size)
1978 {
1979         wl_uint32_list_t *list;
1980         s32 err = BCME_OK;
1981         if (valid_chan_list == NULL || size <= 0)
1982                 return -ENOMEM;
1983
1984         memset(valid_chan_list, 0, size);
1985         list = (wl_uint32_list_t *)(void *) valid_chan_list;
1986         list->count = htod32(WL_NUMCHANNELS);
1987         err = wldev_ioctl(ndev, WLC_GET_VALID_CHANNELS, valid_chan_list, size, false);
1988         if (err != 0) {
1989                 WL_ERR(("get channels failed with %d\n", err));
1990         }
1991
1992         return err;
1993 }
1994
1995 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
1996 #define FIRST_SCAN_ACTIVE_DWELL_TIME_MS 40
1997 static bool
1998 g_first_broadcast_scan = TRUE;
1999 #endif 
2000
2001 static s32
2002 wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
2003         struct cfg80211_scan_request *request, uint16 action)
2004 {
2005         s32 err = BCME_OK;
2006         u32 n_channels;
2007         u32 n_ssids;
2008         s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params));
2009         wl_escan_params_t *params = NULL;
2010         u8 chan_buf[sizeof(u32)*(WL_NUMCHANNELS + 1)];
2011         u32 num_chans = 0;
2012         s32 channel;
2013         s32 n_valid_chan;
2014         s32 search_state = WL_P2P_DISC_ST_SCAN;
2015         u32 i, j, n_nodfs = 0;
2016         u16 *default_chan_list = NULL;
2017         wl_uint32_list_t *list;
2018         struct net_device *dev = NULL;
2019         scb_val_t scbval;
2020 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2021         bool is_first_init_2g_scan = false;
2022 #endif
2023         p2p_scan_purpose_t      p2p_scan_purpose = P2P_SCAN_PURPOSE_MIN;
2024         static int cnt = 0;
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 #ifdef WL_HOST_BAND_MGMT
2115                                         int channel_band = 0;
2116 #endif /* WL_HOST_BAND_MGMT */
2117                                         _freq = request->channels[i]->center_freq;
2118                                         channel = ieee80211_frequency_to_channel(_freq);
2119 #ifdef WL_HOST_BAND_MGMT
2120                                         channel_band = (channel > CH_MAX_2G_CHANNEL) ?
2121                                                 WLC_BAND_5G : WLC_BAND_2G;
2122                                         if ((wl->curr_band != WLC_BAND_AUTO) &&
2123                                                 (wl->curr_band != channel_band) &&
2124                                                 !IS_P2P_SOCIAL_CHANNEL(channel))
2125                                                         continue;
2126 #endif /* WL_HOST_BAND_MGMT */
2127
2128                                         /* ignore DFS channels */
2129                                         if (request->channels[i]->flags &
2130                                                 (IEEE80211_CHAN_RADAR
2131                                                 | IEEE80211_CHAN_PASSIVE_SCAN))
2132                                                 continue;
2133
2134                                         for (j = 0; j < n_valid_chan; j++) {
2135                                                 /* allows only supported channel on
2136                                                 *  current reguatory
2137                                                 */
2138                                                 if (channel == (dtoh32(list->element[j])))
2139                                                         default_chan_list[n_nodfs++] =
2140                                                                 channel;
2141                                         }
2142
2143                                 }
2144                         }
2145                         if (num_chans == SOCIAL_CHAN_CNT && (
2146                                                 (default_chan_list[0] == SOCIAL_CHAN_1) &&
2147                                                 (default_chan_list[1] == SOCIAL_CHAN_2) &&
2148                                                 (default_chan_list[2] == SOCIAL_CHAN_3))) {
2149                                 /* SOCIAL CHANNELS 1, 6, 11 */
2150                                 search_state = WL_P2P_DISC_ST_SEARCH;
2151                                 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2152                                 WL_INFO(("P2P SEARCH PHASE START \n"));
2153                         } else if ((dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION)) &&
2154                                 (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP)) {
2155                                 /* If you are already a GO, then do SEARCH only */
2156                                 WL_INFO(("Already a GO. Do SEARCH Only"));
2157                                 search_state = WL_P2P_DISC_ST_SEARCH;
2158                                 num_chans = n_nodfs;
2159                                 p2p_scan_purpose = P2P_SCAN_NORMAL;
2160
2161                         } else if (num_chans == 1) {
2162                                 p2p_scan_purpose = P2P_SCAN_CONNECT_TRY;
2163                         } else if (num_chans == SOCIAL_CHAN_CNT + 1) {
2164                         /* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by
2165                          * the supplicant
2166                          */
2167                                 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2168                         } else {
2169                                 WL_INFO(("P2P SCAN STATE START \n"));
2170                                 num_chans = n_nodfs;
2171                                 p2p_scan_purpose = P2P_SCAN_NORMAL;
2172                         }
2173                 } else {
2174                         err = -EINVAL;
2175                         goto exit;
2176                 }
2177                 err = wl_cfgp2p_escan(wl, ndev, wl->active_scan, num_chans, default_chan_list,
2178                         search_state, action,
2179                         wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE), NULL,
2180                         p2p_scan_purpose);
2181
2182                 if (!err)
2183                         wl->p2p->search_state = search_state;
2184
2185                 kfree(default_chan_list);
2186         }
2187 exit:
2188         if (unlikely(err)) {
2189                 /* Don't print Error incase of Scan suppress */
2190                 if ((err == BCME_EPERM) && wl->scan_suppressed)
2191                         WL_DBG(("Escan failed: Scan Suppressed \n"));
2192                 else {
2193                         cnt++;
2194                         WL_ERR(("error (%d), cnt=%d\n", err, cnt));
2195                         // terence 20140111: send disassoc to firmware
2196                         if (cnt >= 4) {
2197                                 dev = wl_to_prmry_ndev(wl);
2198                                 memset(&scbval, 0, sizeof(scb_val_t));
2199                                 wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true);
2200                                 WL_ERR(("Send disassoc to break the busy dev=%p\n", dev));
2201                                 cnt = 0;
2202                         }
2203                 }
2204         } else {
2205                 cnt = 0;
2206         }
2207         return err;
2208 }
2209
2210
2211 static s32
2212 wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev,
2213         struct cfg80211_scan_request *request)
2214 {
2215         s32 err = BCME_OK;
2216         s32 passive_scan;
2217         wl_scan_results_t *results;
2218         WL_SCAN(("Enter \n"));
2219         mutex_lock(&wl->usr_sync);
2220
2221         results = wl_escan_get_buf(wl, FALSE);
2222         results->version = 0;
2223         results->count = 0;
2224         results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
2225
2226         wl->escan_info.ndev = ndev;
2227         wl->escan_info.wiphy = wiphy;
2228         wl->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
2229         passive_scan = wl->active_scan ? 0 : 1;
2230         err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
2231                 &passive_scan, sizeof(passive_scan), true);
2232         if (unlikely(err)) {
2233                 WL_ERR(("error (%d)\n", err));
2234                 goto exit;
2235         }
2236
2237         err = wl_run_escan(wl, ndev, request, WL_SCAN_ACTION_START);
2238 exit:
2239         mutex_unlock(&wl->usr_sync);
2240         return err;
2241 }
2242
2243 static s32
2244 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
2245         struct cfg80211_scan_request *request,
2246         struct cfg80211_ssid *this_ssid)
2247 {
2248         struct wl_priv *wl = wiphy_priv(wiphy);
2249         struct cfg80211_ssid *ssids;
2250         struct wl_scan_req *sr = wl_to_sr(wl);
2251         struct ether_addr primary_mac;
2252         s32 passive_scan;
2253         bool iscan_req;
2254         bool escan_req = false;
2255         bool p2p_ssid;
2256 #ifdef WL11U
2257         bcm_tlv_t *interworking_ie;
2258 #endif
2259         s32 err = 0;
2260         s32 bssidx = -1;
2261         s32 i;
2262
2263         unsigned long flags;
2264         static s32 busy_count = 0;
2265
2266         dhd_pub_t *dhd;
2267
2268         dhd = (dhd_pub_t *)(wl->pub);
2269         if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
2270                 WL_ERR(("Invalid Scan Command at SoftAP mode\n"));
2271                 return -EINVAL;
2272         }
2273
2274         ndev = ndev_to_wlc_ndev(ndev, wl);
2275
2276         if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(wl)) {
2277                 WL_ERR(("Sending Action Frames. Try it again.\n"));
2278                 return -EAGAIN;
2279         }
2280
2281         WL_DBG(("Enter wiphy (%p)\n", wiphy));
2282         if (wl_get_drv_status_all(wl, SCANNING)) {
2283                 if (wl->scan_request == NULL) {
2284                         wl_clr_drv_status_all(wl, SCANNING);
2285                         WL_DBG(("<<<<<<<<<<<Force Clear Scanning Status>>>>>>>>>>>\n"));
2286                 } else {
2287                         WL_ERR(("Scanning already\n"));
2288                         return -EAGAIN;
2289                 }
2290         }
2291         if (wl_get_drv_status(wl, SCAN_ABORTING, ndev)) {
2292                 WL_ERR(("Scanning being aborted\n"));
2293                 return -EAGAIN;
2294         }
2295         if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) {
2296                 WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n"));
2297                 return -EOPNOTSUPP;
2298         }
2299 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
2300         if (wl_get_drv_status_all(wl, REMAINING_ON_CHANNEL)) {
2301                 WL_DBG(("Remain_on_channel bit is set, somehow it didn't get cleared\n"));
2302                 wl_notify_escan_complete(wl, ndev, true, true);
2303         }
2304 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
2305
2306 #ifdef WL_SDO
2307         if (wl_get_p2p_status(wl, DISC_IN_PROGRESS)) {
2308                 wl_cfg80211_pause_sdo(ndev, wl);
2309         }
2310 #endif
2311
2312         /* Arm scan timeout timer */
2313         mod_timer(&wl->scan_timeout, jiffies + msecs_to_jiffies(WL_SCAN_TIMER_INTERVAL_MS));
2314         iscan_req = false;
2315         if (request) {          /* scan bss */
2316                 ssids = request->ssids;
2317                 if (wl->iscan_on && (!ssids || !ssids->ssid_len || request->n_ssids != 1)) {
2318                         iscan_req = true;
2319                 } else if (wl->escan_on) {
2320                         escan_req = true;
2321                         p2p_ssid = false;
2322                         for (i = 0; i < request->n_ssids; i++) {
2323                                 if (ssids[i].ssid_len &&
2324                                         IS_P2P_SSID(ssids[i].ssid, ssids[i].ssid_len)) {
2325                                         p2p_ssid = true;
2326                                         break;
2327                                 }
2328                         }
2329                         if (p2p_ssid) {
2330                                 if (wl->p2p_supported) {
2331                                         /* p2p scan trigger */
2332                                         if (p2p_on(wl) == false) {
2333                                                 /* p2p on at the first time */
2334                                                 p2p_on(wl) = true;
2335                                                 wl_cfgp2p_set_firm_p2p(wl);
2336                                                 get_primary_mac(wl, &primary_mac);
2337                                                 wl_cfgp2p_generate_bss_mac(&primary_mac,
2338                                                         &wl->p2p->dev_addr, &wl->p2p->int_addr);
2339                                         }
2340                                         wl_clr_p2p_status(wl, GO_NEG_PHASE);
2341                                         WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
2342                                         p2p_scan(wl) = true;
2343                                 }
2344                         } else {
2345                                 /* legacy scan trigger
2346                                  * So, we have to disable p2p discovery if p2p discovery is on
2347                                  */
2348                                 if (wl->p2p_supported) {
2349                                         p2p_scan(wl) = false;
2350                                         /* If Netdevice is not equals to primary and p2p is on
2351                                         *  , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
2352                                         */
2353
2354                                         if (p2p_scan(wl) == false) {
2355                                                 if (wl_get_p2p_status(wl, DISCOVERY_ON)) {
2356                                                         err = wl_cfgp2p_discover_enable_search(wl,
2357                                                         false);
2358                                                         if (unlikely(err)) {
2359                                                                 goto scan_out;
2360                                                         }
2361
2362                                                 }
2363                                         }
2364                                 }
2365                                 if (!wl->p2p_supported || !p2p_scan(wl)) {
2366
2367                                         if (wl_cfgp2p_find_idx(wl, ndev, &bssidx) != BCME_OK) {
2368                                                 WL_ERR(("Find p2p index from ndev(%p) failed\n",
2369                                                         ndev));
2370                                                 err = BCME_ERROR;
2371                                                 goto scan_out;
2372                                         }
2373 #ifdef WL11U
2374                                         if ((interworking_ie = wl_cfg80211_find_interworking_ie(
2375                                                 (u8 *)request->ie, request->ie_len)) != NULL) {
2376                                                 err = wl_cfg80211_add_iw_ie(wl, ndev, bssidx,
2377                                                        VNDR_IE_CUSTOM_FLAG, interworking_ie->id,
2378                                                        interworking_ie->data, interworking_ie->len);
2379
2380                                                 if (unlikely(err)) {
2381                                                         goto scan_out;
2382                                                 }
2383                                         } else if (wl->iw_ie_len != 0) {
2384                                         /* we have to clear IW IE and disable gratuitous APR */
2385                                                 wl_cfg80211_add_iw_ie(wl, ndev, bssidx,
2386                                                         VNDR_IE_CUSTOM_FLAG,
2387                                                         DOT11_MNG_INTERWORKING_ID,
2388                                                         0, 0);
2389
2390                                                 wldev_iovar_setint_bsscfg(ndev, "grat_arp", 0,
2391                                                         bssidx);
2392                                                 wl->wl11u = FALSE;
2393                                                 /* we don't care about error */
2394                                         }
2395 #endif /* WL11U */
2396                                         err = wl_cfgp2p_set_management_ie(wl, ndev, bssidx,
2397                                                 VNDR_IE_PRBREQ_FLAG, (u8 *)request->ie,
2398                                                 request->ie_len);
2399
2400                                         if (unlikely(err)) {
2401                                                 goto scan_out;
2402                                         }
2403
2404                                 }
2405                         }
2406                 }
2407         } else {                /* scan in ibss */
2408                 /* we don't do iscan in ibss */
2409                 ssids = this_ssid;
2410         }
2411         if (request && !p2p_scan(wl))
2412                 WL_TRACE_HW4(("START SCAN\n"));
2413         wl->scan_request = request;
2414         wl_set_drv_status(wl, SCANNING, ndev);
2415         if (iscan_req) {
2416                 err = wl_do_iscan(wl, request);
2417                 if (likely(!err))
2418                         goto scan_success;
2419                 else
2420                         goto scan_out;
2421         } else if (escan_req) {
2422                 if (wl->p2p_supported) {
2423                         if (p2p_on(wl) && p2p_scan(wl)) {
2424
2425 #ifdef WL_SDO
2426                                 if (wl_get_p2p_status(wl, DISC_IN_PROGRESS)) {
2427                                         /* We shouldn't be getting p2p_find while discovery
2428                                          * offload is in progress
2429                                          */
2430                                         WL_SD(("P2P_FIND: Discovery offload is in progress."
2431                                                 " Do nothing\n"));
2432                                         err = -EINVAL;
2433                                         goto scan_out;
2434                                 }
2435 #endif
2436                                 /* find my listen channel */
2437                                 wl->afx_hdl->my_listen_chan =
2438                                         wl_find_listen_channel(wl, request->ie,
2439                                         request->ie_len);
2440                                 err = wl_cfgp2p_enable_discovery(wl, ndev,
2441                                 request->ie, request->ie_len);
2442
2443                                 if (unlikely(err)) {
2444                                         goto scan_out;
2445                                 }
2446                         }
2447                 }
2448                 err = wl_do_escan(wl, wiphy, ndev, request);
2449                 if (likely(!err))
2450                         goto scan_success;
2451                 else
2452                         goto scan_out;
2453
2454
2455         } else {
2456                 memset(&sr->ssid, 0, sizeof(sr->ssid));
2457                 sr->ssid.SSID_len =
2458                         min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len);
2459                 if (sr->ssid.SSID_len) {
2460                         memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len);
2461                         sr->ssid.SSID_len = htod32(sr->ssid.SSID_len);
2462                         WL_SCAN(("Specific scan ssid=\"%s\" len=%d\n",
2463                                 sr->ssid.SSID, sr->ssid.SSID_len));
2464                 } else {
2465                         WL_SCAN(("Broadcast scan\n"));
2466                 }
2467                 WL_SCAN(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len));
2468                 passive_scan = wl->active_scan ? 0 : 1;
2469                 err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
2470                         &passive_scan, sizeof(passive_scan), true);
2471                 if (unlikely(err)) {
2472                         WL_SCAN(("WLC_SET_PASSIVE_SCAN error (%d)\n", err));
2473                         goto scan_out;
2474                 }
2475                 err = wldev_ioctl(ndev, WLC_SCAN, &sr->ssid,
2476                         sizeof(sr->ssid), false);
2477                 if (err) {
2478                         if (err == -EBUSY) {
2479                                 WL_ERR(("system busy : scan for \"%s\" "
2480                                         "canceled\n", sr->ssid.SSID));
2481                         } else {
2482                                 WL_ERR(("WLC_SCAN error (%d)\n", err));
2483                         }
2484                         goto scan_out;
2485                 }
2486         }
2487
2488 scan_success:
2489         busy_count = 0;
2490
2491         return 0;
2492
2493 scan_out:
2494         if (err == BCME_BUSY || err == BCME_NOTREADY) {
2495                 WL_ERR(("Scan err = (%d), busy?%d", err, -EBUSY));
2496                 err = -EBUSY;
2497         }
2498
2499 #define SCAN_EBUSY_RETRY_LIMIT 10
2500         if (err == -EBUSY) {
2501                 if (busy_count++ > SCAN_EBUSY_RETRY_LIMIT) {
2502                         struct ether_addr bssid;
2503                         s32 ret = 0;
2504                         busy_count = 0;
2505                         WL_ERR(("Unusual continuous EBUSY error, %d %d %d %d %d %d %d %d %d\n",
2506                                 wl_get_drv_status(wl, SCANNING, ndev),
2507                                 wl_get_drv_status(wl, SCAN_ABORTING, ndev),
2508                                 wl_get_drv_status(wl, CONNECTING, ndev),
2509                                 wl_get_drv_status(wl, CONNECTED, ndev),
2510                                 wl_get_drv_status(wl, DISCONNECTING, ndev),
2511                                 wl_get_drv_status(wl, AP_CREATING, ndev),
2512                                 wl_get_drv_status(wl, AP_CREATED, ndev),
2513                                 wl_get_drv_status(wl, SENDING_ACT_FRM, ndev),
2514                                 wl_get_drv_status(wl, SENDING_ACT_FRM, ndev)));
2515
2516                         bzero(&bssid, sizeof(bssid));
2517                         if ((ret = wldev_ioctl(ndev, WLC_GET_BSSID,
2518                                 &bssid, ETHER_ADDR_LEN, false)) == 0)
2519                                 WL_ERR(("FW is connected with " MACDBG "/n",
2520                                         MAC2STRDBG(bssid.octet)));
2521                         else
2522                                 WL_ERR(("GET BSSID failed with %d\n", ret));
2523
2524                         wl_cfg80211_scan_abort(wl);
2525                 }
2526         } else {
2527                 busy_count = 0;
2528         }
2529
2530         wl_clr_drv_status(wl, SCANNING, ndev);
2531         if (timer_pending(&wl->scan_timeout))
2532                 del_timer_sync(&wl->scan_timeout);
2533         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
2534         wl->scan_request = NULL;
2535         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
2536
2537 #ifdef WL_SDO
2538         if (wl_get_p2p_status(wl, DISC_IN_PROGRESS)) {
2539                 wl_cfg80211_resume_sdo(ndev, wl);
2540         }
2541 #endif
2542         return err;
2543 }
2544
2545 static s32
2546 #if defined(WL_CFG80211_P2P_DEV_IF)
2547 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
2548 #else
2549 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
2550         struct cfg80211_scan_request *request)
2551 #endif /* WL_CFG80211_P2P_DEV_IF */
2552 {
2553         s32 err = 0;
2554         struct wl_priv *wl = wiphy_priv(wiphy);
2555 #if defined(WL_CFG80211_P2P_DEV_IF)
2556         struct net_device *ndev = wl_to_prmry_ndev(wl);
2557 #endif /* WL_CFG80211_P2P_DEV_IF */
2558
2559         WL_DBG(("Enter \n"));
2560         RETURN_EIO_IF_NOT_UP(wl);
2561
2562         err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
2563         if (unlikely(err)) {
2564                 if ((err == BCME_EPERM) && wl->scan_suppressed)
2565                         WL_DBG(("scan not permitted at this time (%d)\n", err));
2566                 else
2567                         WL_ERR(("scan error (%d)\n", err));
2568                 return err;
2569         }
2570
2571         return err;
2572 }
2573
2574 static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
2575 {
2576         s32 err = 0;
2577
2578         err = wldev_iovar_setint(dev, "rtsthresh", rts_threshold);
2579         if (unlikely(err)) {
2580                 WL_ERR(("Error (%d)\n", err));
2581                 return err;
2582         }
2583         return err;
2584 }
2585
2586 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
2587 {
2588         s32 err = 0;
2589
2590         err = wldev_iovar_setint_bsscfg(dev, "fragthresh", frag_threshold, 0);
2591         if (unlikely(err)) {
2592                 WL_ERR(("Error (%d)\n", err));
2593                 return err;
2594         }
2595         return err;
2596 }
2597
2598 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
2599 {
2600         s32 err = 0;
2601         u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
2602
2603         retry = htod32(retry);
2604         err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), true);
2605         if (unlikely(err)) {
2606                 WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
2607                 return err;
2608         }
2609         return err;
2610 }
2611
2612 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
2613 {
2614         struct wl_priv *wl = (struct wl_priv *)wiphy_priv(wiphy);
2615         struct net_device *ndev = wl_to_prmry_ndev(wl);
2616         s32 err = 0;
2617
2618         RETURN_EIO_IF_NOT_UP(wl);
2619         WL_DBG(("Enter\n"));
2620         if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
2621                 (wl->conf->rts_threshold != wiphy->rts_threshold)) {
2622                 wl->conf->rts_threshold = wiphy->rts_threshold;
2623                 err = wl_set_rts(ndev, wl->conf->rts_threshold);
2624                 if (!err)
2625                         return err;
2626         }
2627         if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
2628                 (wl->conf->frag_threshold != wiphy->frag_threshold)) {
2629                 wl->conf->frag_threshold = wiphy->frag_threshold;
2630                 err = wl_set_frag(ndev, wl->conf->frag_threshold);
2631                 if (!err)
2632                         return err;
2633         }
2634         if (changed & WIPHY_PARAM_RETRY_LONG &&
2635                 (wl->conf->retry_long != wiphy->retry_long)) {
2636                 wl->conf->retry_long = wiphy->retry_long;
2637                 err = wl_set_retry(ndev, wl->conf->retry_long, true);
2638                 if (!err)
2639                         return err;
2640         }
2641         if (changed & WIPHY_PARAM_RETRY_SHORT &&
2642                 (wl->conf->retry_short != wiphy->retry_short)) {
2643                 wl->conf->retry_short = wiphy->retry_short;
2644                 err = wl_set_retry(ndev, wl->conf->retry_short, false);
2645                 if (!err) {
2646                         return err;
2647                 }
2648         }
2649
2650         return err;
2651 }
2652 static chanspec_t channel_to_chanspec(struct wiphy *wiphy, struct net_device *dev, u32 channel)
2653 {
2654         struct wl_priv *wl = wiphy_priv(wiphy);
2655         u8 *buf = NULL;
2656         wl_uint32_list_t *list;
2657         int err = BCME_OK;
2658         chanspec_t c = 0, ret_c = 0;
2659         int bw = 0, tmp_bw = 0;
2660         int i;
2661         u32 tmp_c, sb;
2662         u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
2663 #define LOCAL_BUF_SIZE  1024
2664         buf = (u8 *) kzalloc(LOCAL_BUF_SIZE, kflags);
2665         if (!buf) {
2666                 WL_ERR(("buf memory alloc failed\n"));
2667                 goto exit;
2668         }
2669         list = (wl_uint32_list_t *)(void *)buf;
2670         list->count = htod32(WL_NUMCHANSPECS);
2671         err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
2672                 0, buf, LOCAL_BUF_SIZE, 0, &wl->ioctl_buf_sync);
2673         if (err != BCME_OK) {
2674                 WL_ERR(("get chanspecs failed with %d\n", err));
2675                 goto exit;
2676         }
2677         for (i = 0; i < dtoh32(list->count); i++) {
2678                 c = dtoh32(list->element[i]);
2679                 if (channel <= CH_MAX_2G_CHANNEL) {
2680                         if (!CHSPEC_IS20(c))
2681                                 continue;
2682                         if (channel == CHSPEC_CHANNEL(c)) {
2683                                 ret_c = c;
2684                                 bw = 20;
2685                                 goto exit;
2686                         }
2687                 }
2688                 if (CHSPEC_IS20(c)) {
2689                         tmp_c = CHSPEC_CHANNEL(c);
2690                         tmp_bw = 20;
2691                 }
2692                 else if (CHSPEC_IS40(c)) {
2693                         tmp_c = CHSPEC_CHANNEL(c);
2694                         if (CHSPEC_SB_UPPER(c)) {
2695                                 tmp_c += CH_10MHZ_APART;
2696                         } else {
2697                                 tmp_c -= CH_10MHZ_APART;
2698                         }
2699                         tmp_bw = 40;
2700                 }
2701                 else {
2702                         tmp_c = CHSPEC_CHANNEL(c);
2703                         sb = c & WL_CHANSPEC_CTL_SB_MASK;
2704                         if (sb == WL_CHANSPEC_CTL_SB_LL) {
2705                                 tmp_c -= (CH_10MHZ_APART + CH_20MHZ_APART);
2706                         } else if (sb == WL_CHANSPEC_CTL_SB_LU) {
2707                                 tmp_c -= CH_10MHZ_APART;
2708                         } else if (sb == WL_CHANSPEC_CTL_SB_UL) {
2709                                 tmp_c += CH_10MHZ_APART;
2710                         } else {
2711                                 /* WL_CHANSPEC_CTL_SB_UU */
2712                                 tmp_c += (CH_10MHZ_APART + CH_20MHZ_APART);
2713                         }
2714                         tmp_bw = 80;
2715                 }
2716                 if (tmp_c != channel)
2717                         continue;
2718
2719                 if (tmp_bw > bw) {
2720                         bw = tmp_bw;
2721                         ret_c = c;
2722                 }
2723         }
2724 exit:
2725         if (buf)
2726                 kfree(buf);
2727 #undef LOCAL_BUF_SIZE
2728         WL_INFO(("return chanspec %x %d\n", ret_c, bw));
2729         return ret_c;
2730 }
2731
2732 void
2733 wl_cfg80211_ibss_vsie_set_buffer(vndr_ie_setbuf_t *ibss_vsie, int ibss_vsie_len)
2734 {
2735         struct wl_priv *wl = wlcfg_drv_priv;
2736
2737         if (wl != NULL && ibss_vsie != NULL) {
2738                 if (wl->ibss_vsie != NULL) {
2739                         kfree(wl->ibss_vsie);
2740                 }
2741                 wl->ibss_vsie = ibss_vsie;
2742                 wl->ibss_vsie_len = ibss_vsie_len;
2743         }
2744 }
2745
2746 static void
2747 wl_cfg80211_ibss_vsie_free(struct wl_priv *wl)
2748 {
2749         /* free & initiralize VSIE (Vendor Specific IE) */
2750         if (wl->ibss_vsie != NULL) {
2751                 kfree(wl->ibss_vsie);
2752                 wl->ibss_vsie = NULL;
2753                 wl->ibss_vsie_len = 0;
2754         }
2755 }
2756
2757 s32
2758 wl_cfg80211_ibss_vsie_delete(struct net_device *dev)
2759 {
2760         struct wl_priv *wl = wlcfg_drv_priv;
2761         char *ioctl_buf = NULL;
2762         s32 ret = BCME_OK;
2763
2764         if (wl != NULL && wl->ibss_vsie != NULL) {
2765                 ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
2766                 if (!ioctl_buf) {
2767                         WL_ERR(("ioctl memory alloc failed\n"));
2768                         return -ENOMEM;
2769                 }
2770
2771                 /* change the command from "add" to "del" */
2772                 strncpy(wl->ibss_vsie->cmd, "del", VNDR_IE_CMD_LEN - 1);
2773                 wl->ibss_vsie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
2774
2775                 ret = wldev_iovar_setbuf(dev, "ie",
2776                         wl->ibss_vsie, wl->ibss_vsie_len,
2777                         ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
2778                 WL_ERR(("ret=%d\n", ret));
2779
2780                 if (ret == BCME_OK) {
2781                         /* free & initiralize VSIE */
2782                         kfree(wl->ibss_vsie);
2783                         wl->ibss_vsie = NULL;
2784                         wl->ibss_vsie_len = 0;
2785                 }
2786
2787                 if (ioctl_buf) {
2788                         kfree(ioctl_buf);
2789                 }
2790         }
2791
2792         return ret;
2793 }
2794
2795 static s32
2796 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
2797         struct cfg80211_ibss_params *params)
2798 {
2799         struct wl_priv *wl = wiphy_priv(wiphy);
2800         struct cfg80211_bss *bss;
2801         struct ieee80211_channel *chan;
2802         struct wl_join_params join_params;
2803         struct cfg80211_ssid ssid;
2804         s32 scan_retry = 0;
2805         s32 err = 0;
2806         int scan_suppress = 1;
2807         size_t join_params_size;
2808         chanspec_t chanspec;
2809
2810         WL_TRACE(("In\n"));
2811         RETURN_EIO_IF_NOT_UP(wl);
2812         WL_INFO(("JOIN BSSID:" MACDBG "\n", MAC2STRDBG(params->bssid)));
2813         if (!params->ssid || params->ssid_len <= 0) {
2814                 WL_ERR(("Invalid parameter\n"));
2815                 return -EINVAL;
2816         }
2817         if (wl_get_drv_status(wl, CONNECTED, dev)) {
2818                 struct wlc_ssid *ssid = (struct wlc_ssid *)wl_read_prof(wl, dev, WL_PROF_SSID);
2819                 u8 *bssid = (u8 *)wl_read_prof(wl, dev, WL_PROF_BSSID);
2820                 if (!params->bssid || (memcmp(params->bssid, bssid, ETHER_ADDR_LEN) == 0 &&
2821                         memcmp(params->ssid, ssid->SSID, ssid->SSID_len) == 0)) {
2822                         WL_ERR(("Connection already existed to " MACDBG "\n",
2823                                 MAC2STRDBG((u8 *)wl_read_prof(wl, dev, WL_PROF_BSSID))));
2824                         return -EISCONN;
2825                 }
2826                 WL_ERR(("Ignore Previous connecton to %s (" MACDBG ")\n",
2827                         ssid->SSID, MAC2STRDBG(bssid)));
2828         }
2829
2830         /* remove the VSIE */
2831         wl_cfg80211_ibss_vsie_delete(dev);
2832
2833         bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
2834         if (!bss) {
2835                 if (IBSS_INITIAL_SCAN_ALLOWED == TRUE) {
2836                         memcpy(ssid.ssid, params->ssid, params->ssid_len);
2837                         ssid.ssid_len = params->ssid_len;
2838                         do {
2839                                 if (unlikely
2840                                         (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
2841                                          -EBUSY)) {
2842                                         wl_delay(150);
2843                                 } else {
2844                                         break;
2845                                 }
2846                         } while (++scan_retry < WL_SCAN_RETRY_MAX);
2847
2848                         /* wait 4 secons till scan done.... */
2849                         schedule_timeout_interruptible(msecs_to_jiffies(4000));
2850                         bss = cfg80211_get_ibss(wiphy, NULL,
2851                                 params->ssid, params->ssid_len);
2852                 }
2853         }
2854         if (bss && ((IBSS_COALESCE_ALLOWED == TRUE) ||
2855                 ((IBSS_COALESCE_ALLOWED == FALSE) && params->bssid &&
2856                 !memcmp(bss->bssid, params->bssid, ETHER_ADDR_LEN)))) {
2857                 wl->ibss_starter = false;
2858                 WL_DBG(("Found IBSS\n"));
2859         } else {
2860                 wl->ibss_starter = true;
2861         }
2862 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
2863         chan = params->chandef.chan;
2864 #else
2865         chan = params->channel;
2866 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) */
2867         if (chan)
2868                 wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
2869         chanspec = channel_to_chanspec(wiphy, dev, wl->channel);
2870         /*
2871          * Join with specific BSSID and cached SSID
2872          * If SSID is zero join based on BSSID only
2873          */
2874         memset(&join_params, 0, sizeof(join_params));
2875         memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
2876                 params->ssid_len);
2877         join_params.ssid.SSID_len = htod32(params->ssid_len);
2878         if (params->bssid) {
2879                 memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
2880                 err = wldev_ioctl(dev, WLC_SET_DESIRED_BSSID, &join_params.params.bssid,
2881                         ETHER_ADDR_LEN, true);
2882                 if (unlikely(err)) {
2883                         WL_ERR(("Error (%d)\n", err));
2884                         return err;
2885                 }
2886         } else
2887                 memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
2888
2889         wldev_iovar_setint(dev, "ibss_coalesce_allowed", IBSS_COALESCE_ALLOWED);
2890
2891         if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
2892                 scan_suppress = TRUE;
2893                 /* Set the SCAN SUPRESS Flag in the firmware to skip join scan */
2894                 err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS, &scan_suppress, sizeof(int), true);
2895                 if (unlikely(err)) {
2896                         WL_ERR(("Scan Supress Setting failed(%d)\n", err));
2897                         return err;
2898                 }
2899         }
2900
2901         join_params.params.chanspec_list[0] = chanspec;
2902         join_params.params.chanspec_num = 1;
2903         wldev_iovar_setint(dev, "chanspec", chanspec);
2904         join_params_size = sizeof(join_params);
2905
2906         /* Disable Authentication, IBSS will add key if it required */
2907         wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
2908         wldev_iovar_setint(dev, "wsec", 0);
2909
2910         err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
2911                 join_params_size, true);
2912         if (unlikely(err)) {
2913                 WL_ERR(("Error (%d)\n", err));
2914                 return err;
2915         }
2916
2917         if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
2918                 scan_suppress = FALSE;
2919                 /* Restore the SCAN SUPPRESS Falg */
2920                 err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS,
2921                         &scan_suppress, sizeof(int), true);
2922                 if (unlikely(err)) {
2923                         WL_ERR(("Reset SCAN Suppress Flag failed (%d)\n", err));
2924                 return err;
2925                 }
2926         }
2927         wl_update_prof(wl, dev, NULL, &join_params.ssid, WL_PROF_SSID);
2928         return err;
2929 }
2930
2931 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
2932 {
2933         struct wl_priv *wl = wiphy_priv(wiphy);
2934         s32 err = 0;
2935         scb_val_t scbval;
2936         u8 *curbssid;
2937
2938         RETURN_EIO_IF_NOT_UP(wl);
2939         wl_link_down(wl);
2940         WL_ERR(("Leave IBSS\n"));
2941         curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID);
2942         wl_set_drv_status(wl, DISCONNECTING, dev);
2943         scbval.val = 0;
2944         memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
2945         err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
2946                 sizeof(scb_val_t), true);
2947         if (unlikely(err)) {
2948                 wl_clr_drv_status(wl, DISCONNECTING, dev);
2949                 WL_ERR(("error(%d)\n", err));
2950                 return err;
2951         }
2952
2953         /* remove the VSIE */
2954         wl_cfg80211_ibss_vsie_delete(dev);
2955
2956         return err;
2957 }
2958
2959 #ifdef MFP
2960 static int wl_cfg80211_get_rsn_capa(bcm_tlv_t *wpa2ie, u8* capa)
2961 {
2962         u16 suite_count;
2963         wpa_suite_mcast_t *mcast;
2964         wpa_suite_ucast_t *ucast;
2965         u16 len;
2966         wpa_suite_auth_key_mgmt_t *mgmt;
2967
2968         if (!wpa2ie)
2969                 return -1;
2970
2971         len = wpa2ie->len;
2972         mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
2973         if ((len -= WPA_SUITE_LEN) <= 0)
2974                 return BCME_BADLEN;
2975         ucast = (wpa_suite_ucast_t *)&mcast[1];
2976         suite_count = ltoh16_ua(&ucast->count);
2977         if ((suite_count > NL80211_MAX_NR_CIPHER_SUITES) ||
2978                 (len -= (WPA_IE_SUITE_COUNT_LEN +
2979                 (WPA_SUITE_LEN * suite_count))) <= 0)
2980                 return BCME_BADLEN;
2981
2982         mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
2983         suite_count = ltoh16_ua(&mgmt->count);
2984
2985         if ((suite_count > NL80211_MAX_NR_CIPHER_SUITES) ||
2986                 (len -= (WPA_IE_SUITE_COUNT_LEN +
2987                 (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
2988                 capa[0] = *(u8 *)&mgmt->list[suite_count];
2989                 capa[1] = *((u8 *)&mgmt->list[suite_count] + 1);
2990         } else
2991                 return BCME_BADLEN;
2992
2993         return 0;
2994 }
2995 #endif /* MFP */
2996
2997 static s32
2998 wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
2999 {
3000         struct wl_priv *wl = wlcfg_drv_priv;
3001         struct wl_security *sec;
3002         s32 val = 0;
3003         s32 err = 0;
3004         s32 bssidx;
3005         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3006                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3007                 return BCME_ERROR;
3008         }
3009
3010         if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
3011                 val = WPA_AUTH_PSK |
3012 #ifdef BCMCCX
3013                         WPA_AUTH_CCKM |
3014 #endif
3015                         WPA_AUTH_UNSPECIFIED;
3016         else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
3017                 val = WPA2_AUTH_PSK|
3018 #ifdef BCMCCX
3019                         WPA2_AUTH_CCKM |
3020 #endif
3021                         WPA2_AUTH_UNSPECIFIED;
3022         else
3023                 val = WPA_AUTH_DISABLED;
3024
3025         if (is_wps_conn(sme))
3026                 val = WPA_AUTH_DISABLED;
3027
3028 #ifdef BCMWAPI_WPI
3029         if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) {
3030                 WL_DBG((" * wl_set_wpa_version, set wpa_auth"
3031                         " to WPA_AUTH_WAPI 0x400"));
3032                 val = WAPI_AUTH_PSK | WAPI_AUTH_UNSPECIFIED;
3033         }
3034 #endif
3035         WL_DBG(("setting wpa_auth to 0x%0x\n", val));
3036         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
3037         if (unlikely(err)) {
3038                 WL_ERR(("set wpa_auth failed (%d)\n", err));
3039                 return err;
3040         }
3041         sec = wl_read_prof(wl, dev, WL_PROF_SEC);
3042         sec->wpa_versions = sme->crypto.wpa_versions;
3043         return err;
3044 }
3045
3046 #ifdef BCMWAPI_WPI
3047 static s32
3048 wl_set_set_wapi_ie(struct net_device *dev, struct cfg80211_connect_params *sme)
3049 {
3050         struct wl_priv *wl = wlcfg_drv_priv;
3051         s32 err = 0;
3052         s32 bssidx;
3053         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3054                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3055                 return BCME_ERROR;
3056         }
3057
3058         WL_DBG((" %s \n", __FUNCTION__));
3059
3060         if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) {
3061                 err = wldev_iovar_setbuf_bsscfg(dev, "wapiie", sme->ie,
3062                         sme->ie_len, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3063
3064                 if (unlikely(err)) {
3065                         WL_ERR(("===> set_wapi_ie Error (%d)\n", err));
3066                         return err;
3067                 }
3068         } else
3069                 WL_DBG((" * skip \n"));
3070         return err;
3071 }
3072 #endif /* BCMWAPI_WPI */
3073
3074 static s32
3075 wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
3076 {
3077         struct wl_priv *wl = wlcfg_drv_priv;
3078         struct wl_security *sec;
3079         s32 val = 0;
3080         s32 err = 0;
3081         s32 bssidx;
3082         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3083                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3084                 return BCME_ERROR;
3085         }
3086
3087         switch (sme->auth_type) {
3088         case NL80211_AUTHTYPE_OPEN_SYSTEM:
3089                 val = WL_AUTH_OPEN_SYSTEM;
3090                 WL_DBG(("open system\n"));
3091                 break;
3092         case NL80211_AUTHTYPE_SHARED_KEY:
3093                 val = WL_AUTH_SHARED_KEY;
3094                 WL_DBG(("shared key\n"));
3095                 break;
3096         case NL80211_AUTHTYPE_AUTOMATIC:
3097                 val = WL_AUTH_OPEN_SHARED;
3098                 WL_DBG(("automatic\n"));
3099                 break;
3100 #ifdef BCMCCX
3101         case NL80211_AUTHTYPE_NETWORK_EAP:
3102                 WL_DBG(("network eap\n"));
3103                 val = DOT11_LEAP_AUTH;
3104                 break;
3105 #endif
3106         default:
3107                 val = 2;
3108                 WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
3109                 break;
3110         }
3111
3112         err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
3113         if (unlikely(err)) {
3114                 WL_ERR(("set auth failed (%d)\n", err));
3115                 return err;
3116         }
3117         sec = wl_read_prof(wl, dev, WL_PROF_SEC);
3118         sec->auth_type = sme->auth_type;
3119         return err;
3120 }
3121
3122 static s32
3123 wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
3124 {
3125         struct wl_priv *wl = wlcfg_drv_priv;
3126         struct wl_security *sec;
3127         s32 pval = 0;
3128         s32 gval = 0;
3129         s32 err = 0;
3130         s32 wsec_val = 0;
3131 #ifdef MFP
3132         s32 mfp = 0;
3133         bcm_tlv_t *wpa2_ie;
3134         u8 rsn_cap[2];
3135 #endif /* MFP */
3136
3137 #ifdef BCMWAPI_WPI
3138         s32 val = 0;
3139 #endif
3140         s32 bssidx;
3141         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3142                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3143                 return BCME_ERROR;
3144         }
3145
3146         if (sme->crypto.n_ciphers_pairwise) {
3147                 switch (sme->crypto.ciphers_pairwise[0]) {
3148                 case WLAN_CIPHER_SUITE_WEP40:
3149                 case WLAN_CIPHER_SUITE_WEP104:
3150                         pval = WEP_ENABLED;
3151                         break;
3152                 case WLAN_CIPHER_SUITE_TKIP:
3153                         pval = TKIP_ENABLED;
3154                         break;
3155                 case WLAN_CIPHER_SUITE_CCMP:
3156                 case WLAN_CIPHER_SUITE_AES_CMAC:
3157                         pval = AES_ENABLED;
3158                         break;
3159 #ifdef BCMWAPI_WPI
3160                 case WLAN_CIPHER_SUITE_SMS4:
3161                         val = SMS4_ENABLED;
3162                         pval = SMS4_ENABLED;
3163                         break;
3164 #endif
3165                 default:
3166                         WL_ERR(("invalid cipher pairwise (%d)\n",
3167                                 sme->crypto.ciphers_pairwise[0]));
3168                         return -EINVAL;
3169                 }
3170         }
3171 #if defined(BCMSUP_4WAY_HANDSHAKE) && defined(WLAN_AKM_SUITE_FT_8021X)
3172         /* Ensure in-dongle supplicant is turned on when FBT wants to do the 4-way
3173          * handshake.
3174          * Note that the FW feature flag only exists on kernels that support the
3175          * FT-EAP AKM suite.
3176          */
3177         if (wl->wdev->wiphy->features & NL80211_FEATURE_FW_4WAY_HANDSHAKE) {
3178                 if (pval == AES_ENABLED)
3179                         err = wldev_iovar_setint_bsscfg(dev, "sup_wpa", 1, bssidx);
3180                 else
3181                         err = wldev_iovar_setint_bsscfg(dev, "sup_wpa", 0, bssidx);
3182
3183                 if (err) {
3184                         WL_ERR(("FBT: Error setting sup_wpa (%d)\n", err));
3185                         return err;
3186                 }
3187         }
3188 #endif /* BCMSUP_4WAY_HANDSHAKE && WLAN_AKM_SUITE_FT_8021X */
3189         if (sme->crypto.cipher_group) {
3190                 switch (sme->crypto.cipher_group) {
3191                 case WLAN_CIPHER_SUITE_WEP40:
3192                 case WLAN_CIPHER_SUITE_WEP104:
3193                         gval = WEP_ENABLED;
3194                         break;
3195                 case WLAN_CIPHER_SUITE_TKIP:
3196                         gval = TKIP_ENABLED;
3197                         break;
3198                 case WLAN_CIPHER_SUITE_CCMP:
3199                         gval = AES_ENABLED;
3200                         break;
3201                 case WLAN_CIPHER_SUITE_AES_CMAC:
3202                         gval = AES_ENABLED;
3203                         break;
3204 #ifdef BCMWAPI_WPI
3205                 case WLAN_CIPHER_SUITE_SMS4:
3206                         val = SMS4_ENABLED;
3207                         gval = SMS4_ENABLED;
3208                         break;
3209 #endif
3210                 default:
3211                         WL_ERR(("invalid cipher group (%d)\n",
3212                                 sme->crypto.cipher_group));
3213                         return -EINVAL;
3214                 }
3215         }
3216
3217         WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
3218
3219         if (is_wps_conn(sme)) {
3220                 if (sme->privacy)
3221                         err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
3222                 else
3223                         /* WPS-2.0 allows no security */
3224                         err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
3225         } else {
3226 #ifdef BCMWAPI_WPI
3227                 if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_SMS4) {
3228                         WL_DBG((" NO, is_wps_conn, WAPI set to SMS4_ENABLED"));
3229                         err = wldev_iovar_setint_bsscfg(dev, "wsec", val, bssidx);
3230                 } else {
3231 #endif
3232                         WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC"));
3233                         wsec_val = pval | gval;
3234
3235 #ifdef MFP
3236                         if (pval == AES_ENABLED) {
3237                                 if (((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
3238                                         DOT11_MNG_RSN_ID)) != NULL) &&
3239                                         (wl_cfg80211_get_rsn_capa(wpa2_ie, rsn_cap) == 0)) {
3240
3241                                         if (rsn_cap[0] & RSN_CAP_MFPC) {
3242                                                 /* MFP Capability advertised by supplicant. Check
3243                                                  * whether MFP is supported in the firmware
3244                                                  */
3245                                                 if ((err = wldev_iovar_getint_bsscfg(dev,
3246                                                                 "mfp", &mfp, bssidx)) < 0) {
3247                                                         WL_ERR(("Get MFP failed! "
3248                                                                 "Check MFP support in FW \n"));
3249                                                         return -1;
3250                                                 }
3251
3252                                                 if ((sme->crypto.n_akm_suites == 1) &&
3253                                                         ((sme->crypto.akm_suites[0] ==
3254                                                         WL_AKM_SUITE_MFP_PSK) ||
3255                                                         (sme->crypto.akm_suites[0] ==
3256                                                         WL_AKM_SUITE_MFP_1X))) {
3257                                                         wsec_val |= MFP_SHA256;
3258                                                 } else if (sme->crypto.n_akm_suites > 1) {
3259                                                         WL_ERR(("Multiple AKM Specified \n"));
3260                                                         return -EINVAL;
3261                                                 }
3262
3263                                                 wsec_val |= MFP_CAPABLE;
3264                                                 if (rsn_cap[0] & RSN_CAP_MFPR)
3265                                                         wsec_val |= MFP_REQUIRED;
3266                                         }
3267                                 }
3268                         }
3269 #endif /* MFP */
3270                         WL_DBG((" Set WSEC to fW 0x%x \n", wsec_val));
3271                         err = wldev_iovar_setint_bsscfg(dev, "wsec",
3272                                 wsec_val, bssidx);
3273 #ifdef BCMWAPI_WPI
3274                 }
3275 #endif
3276         }
3277         if (unlikely(err)) {
3278                 WL_ERR(("error (%d)\n", err));
3279                 return err;
3280         }
3281
3282         sec = wl_read_prof(wl, dev, WL_PROF_SEC);
3283         sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
3284         sec->cipher_group = sme->crypto.cipher_group;
3285
3286         return err;
3287 }
3288
3289 static s32
3290 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
3291 {
3292         struct wl_priv *wl = wlcfg_drv_priv;
3293         struct wl_security *sec;
3294         s32 val = 0;
3295         s32 err = 0;
3296         s32 bssidx;
3297         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3298                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3299                 return BCME_ERROR;
3300         }
3301
3302         if (sme->crypto.n_akm_suites) {
3303                 err = wldev_iovar_getint(dev, "wpa_auth", &val);
3304                 if (unlikely(err)) {
3305                         WL_ERR(("could not get wpa_auth (%d)\n", err));
3306                         return err;
3307                 }
3308                 if (val & (WPA_AUTH_PSK |
3309 #ifdef BCMCCX
3310                         WPA_AUTH_CCKM |
3311 #endif
3312                         WPA_AUTH_UNSPECIFIED)) {
3313                         switch (sme->crypto.akm_suites[0]) {
3314                         case WLAN_AKM_SUITE_8021X:
3315                                 val = WPA_AUTH_UNSPECIFIED;
3316                                 break;
3317                         case WLAN_AKM_SUITE_PSK:
3318                                 val = WPA_AUTH_PSK;
3319                                 break;
3320 #ifdef BCMCCX
3321                         case WLAN_AKM_SUITE_CCKM:
3322                                 val = WPA_AUTH_CCKM;
3323                                 break;
3324 #endif
3325                         default:
3326                                 WL_ERR(("invalid cipher group (%d)\n",
3327                                         sme->crypto.cipher_group));
3328                                 return -EINVAL;
3329                         }
3330                 } else if (val & (WPA2_AUTH_PSK |
3331 #ifdef BCMCCX
3332                         WPA2_AUTH_CCKM |
3333 #endif
3334                         WPA2_AUTH_UNSPECIFIED)) {
3335                         switch (sme->crypto.akm_suites[0]) {
3336                         case WLAN_AKM_SUITE_8021X:
3337                                 val = WPA2_AUTH_UNSPECIFIED;
3338                                 break;
3339 #ifdef MFP
3340                         case WL_AKM_SUITE_MFP_1X:
3341                                 val = WPA2_AUTH_UNSPECIFIED;
3342                                 break;
3343                         case WL_AKM_SUITE_MFP_PSK:
3344                                 val = WPA2_AUTH_PSK;
3345                                 break;
3346 #endif
3347                         case WLAN_AKM_SUITE_PSK:
3348                                 val = WPA2_AUTH_PSK;
3349                                 break;
3350 #if defined(WLFBT) && defined(WLAN_AKM_SUITE_FT_8021X)
3351                         case WLAN_AKM_SUITE_FT_8021X:
3352                                 val = WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_FT;
3353                                 break;
3354 #endif
3355 #if defined(WLFBT) && defined(WLAN_AKM_SUITE_FT_PSK)
3356                         case WLAN_AKM_SUITE_FT_PSK:
3357                                 val = WPA2_AUTH_PSK | WPA2_AUTH_FT;
3358                                 break;
3359 #endif
3360 #ifdef BCMCCX
3361                         case WLAN_AKM_SUITE_CCKM:
3362                                 val = WPA2_AUTH_CCKM;
3363                                 break;
3364 #endif
3365                         default:
3366                                 WL_ERR(("invalid cipher group (%d)\n",
3367                                         sme->crypto.cipher_group));
3368                                 return -EINVAL;
3369                         }
3370                 }
3371 #ifdef BCMWAPI_WPI
3372                 else if (val & (WAPI_AUTH_PSK | WAPI_AUTH_UNSPECIFIED)) {
3373                         switch (sme->crypto.akm_suites[0]) {
3374                         case WLAN_AKM_SUITE_WAPI_CERT:
3375                                 val = WAPI_AUTH_UNSPECIFIED;
3376                                 break;
3377                         case WLAN_AKM_SUITE_WAPI_PSK:
3378                                 val = WAPI_AUTH_PSK;
3379                                 break;
3380                         default:
3381                                 WL_ERR(("invalid cipher group (%d)\n",
3382                                         sme->crypto.cipher_group));
3383                                 return -EINVAL;
3384                         }
3385                 }
3386 #endif
3387                 WL_DBG(("setting wpa_auth to %d\n", val));
3388
3389
3390                 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
3391                 if (unlikely(err)) {
3392                         WL_ERR(("could not set wpa_auth (%d)\n", err));
3393                         return err;
3394                 }
3395         }
3396         sec = wl_read_prof(wl, dev, WL_PROF_SEC);
3397         sec->wpa_auth = sme->crypto.akm_suites[0];
3398
3399         return err;
3400 }
3401
3402 static s32
3403 wl_set_set_sharedkey(struct net_device *dev,
3404         struct cfg80211_connect_params *sme)
3405 {
3406         struct wl_priv *wl = wlcfg_drv_priv;
3407         struct wl_security *sec;
3408         struct wl_wsec_key key;
3409         s32 val;
3410         s32 err = 0;
3411         s32 bssidx;
3412         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3413                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3414                 return BCME_ERROR;
3415         }
3416
3417         WL_DBG(("key len (%d)\n", sme->key_len));
3418         if (sme->key_len) {
3419                 sec = wl_read_prof(wl, dev, WL_PROF_SEC);
3420                 WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
3421                         sec->wpa_versions, sec->cipher_pairwise));
3422                 if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 |
3423 #ifdef BCMWAPI_WPI
3424                         NL80211_WPA_VERSION_2 | NL80211_WAPI_VERSION_1)) &&
3425 #else
3426                         NL80211_WPA_VERSION_2)) &&
3427 #endif
3428                         (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
3429 #ifdef BCMWAPI_WPI
3430                 WLAN_CIPHER_SUITE_WEP104 | WLAN_CIPHER_SUITE_SMS4)))
3431 #else
3432                 WLAN_CIPHER_SUITE_WEP104)))
3433 #endif
3434                 {
3435                         memset(&key, 0, sizeof(key));
3436                         key.len = (u32) sme->key_len;
3437                         key.index = (u32) sme->key_idx;
3438                         if (unlikely(key.len > sizeof(key.data))) {
3439                                 WL_ERR(("Too long key length (%u)\n", key.len));
3440                                 return -EINVAL;
3441                         }
3442                         memcpy(key.data, sme->key, key.len);
3443                         key.flags = WL_PRIMARY_KEY;
3444                         switch (sec->cipher_pairwise) {
3445                         case WLAN_CIPHER_SUITE_WEP40:
3446                                 key.algo = CRYPTO_ALGO_WEP1;
3447                                 break;
3448                         case WLAN_CIPHER_SUITE_WEP104:
3449                                 key.algo = CRYPTO_ALGO_WEP128;
3450                                 break;
3451 #ifdef BCMWAPI_WPI
3452                         case WLAN_CIPHER_SUITE_SMS4:
3453                                 key.algo = CRYPTO_ALGO_SMS4;
3454                                 break;
3455 #endif
3456                         default:
3457                                 WL_ERR(("Invalid algorithm (%d)\n",
3458                                         sme->crypto.ciphers_pairwise[0]));
3459                                 return -EINVAL;
3460                         }
3461                         /* Set the new key/index */
3462                         WL_DBG(("key length (%d) key index (%d) algo (%d)\n",
3463                                 key.len, key.index, key.algo));
3464                         WL_DBG(("key \"%s\"\n", key.data));
3465                         swap_key_from_BE(&key);
3466                         err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
3467                                 wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3468                         if (unlikely(err)) {
3469                                 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
3470                                 return err;
3471                         }
3472                         if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
3473                                 WL_DBG(("set auth_type to shared key\n"));
3474                                 val = WL_AUTH_SHARED_KEY;       /* shared key */
3475                                 err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
3476                                 if (unlikely(err)) {
3477                                         WL_ERR(("set auth failed (%d)\n", err));
3478                                         return err;
3479                                 }
3480                         }
3481                 }
3482         }
3483         return err;
3484 }
3485
3486 #if defined(ESCAN_RESULT_PATCH)
3487 static u8 connect_req_bssid[6];
3488 static u8 broad_bssid[6];
3489 #endif /* ESCAN_RESULT_PATCH */
3490
3491
3492
3493 static s32
3494 wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
3495         struct cfg80211_connect_params *sme)
3496 {
3497         struct wl_priv *wl = wiphy_priv(wiphy);
3498         struct ieee80211_channel *chan = sme->channel;
3499         wl_extjoin_params_t *ext_join_params;
3500         struct wl_join_params join_params;
3501         size_t join_params_size;
3502         s32 err = 0;
3503         wpa_ie_fixed_t *wpa_ie;
3504         bcm_tlv_t *wpa2_ie;
3505         u8* wpaie  = 0;
3506         u32 wpaie_len = 0;
3507         u32 chan_cnt = 0;
3508         struct ether_addr bssid;
3509         s32 bssidx;
3510         int ret;
3511         int wait_cnt;
3512
3513         WL_DBG(("In\n"));
3514
3515         if (unlikely(!sme->ssid)) {
3516                 WL_ERR(("Invalid ssid\n"));
3517                 return -EOPNOTSUPP;
3518         }
3519
3520         if (unlikely(sme->ssid_len > DOT11_MAX_SSID_LEN)) {
3521                 WL_ERR(("Invalid SSID info: SSID=%s, length=%d\n",
3522                         sme->ssid, sme->ssid_len));
3523                 return -EINVAL;
3524         }
3525
3526         RETURN_EIO_IF_NOT_UP(wl);
3527
3528         /*
3529          * Cancel ongoing scan to sync up with sme state machine of cfg80211.
3530          */
3531 #if !defined(ESCAN_RESULT_PATCH)
3532         if (wl->scan_request) {
3533                 wl_notify_escan_complete(wl, dev, true, true);
3534         }
3535 #endif
3536 #if defined(ESCAN_RESULT_PATCH)
3537         if (sme->bssid)
3538                 memcpy(connect_req_bssid, sme->bssid, ETHER_ADDR_LEN);
3539         else
3540                 bzero(connect_req_bssid, ETHER_ADDR_LEN);
3541         bzero(broad_bssid, ETHER_ADDR_LEN);
3542 #endif
3543 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
3544         maxrxpktglom = 0;
3545 #endif
3546         bzero(&bssid, sizeof(bssid));
3547         if (!wl_get_drv_status(wl, CONNECTED, dev)&&
3548                 (ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false)) == 0) {
3549                 if (!ETHER_ISNULLADDR(&bssid)) {
3550                         scb_val_t scbval;
3551                         wl_set_drv_status(wl, DISCONNECTING, dev);
3552                         scbval.val = DOT11_RC_DISASSOC_LEAVING;
3553                         memcpy(&scbval.ea, &bssid, ETHER_ADDR_LEN);
3554                         scbval.val = htod32(scbval.val);
3555
3556                         WL_DBG(("drv status CONNECTED is not set, but connected in FW!" MACDBG "/n",
3557                                 MAC2STRDBG(bssid.octet)));
3558                         err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
3559                                 sizeof(scb_val_t), true);
3560                         if (unlikely(err)) {
3561                                 wl_clr_drv_status(wl, DISCONNECTING, dev);
3562                                 WL_ERR(("error (%d)\n", err));
3563                                 return err;
3564                         }
3565                         wait_cnt = 500/10;
3566                         while (wl_get_drv_status(wl, DISCONNECTING, dev) && wait_cnt) {
3567                                 WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n",
3568                                         wait_cnt));
3569                                 wait_cnt--;
3570                                 OSL_SLEEP(10);
3571                         }
3572                 } else
3573                         WL_DBG(("Currently not associated!\n"));
3574         } else {
3575                 /* if status is DISCONNECTING, wait for disconnection terminated max 500 ms */
3576                 wait_cnt = 500/10;
3577                 while (wl_get_drv_status(wl, DISCONNECTING, dev) && wait_cnt) {
3578                         WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n", wait_cnt));
3579                         wait_cnt--;
3580                         OSL_SLEEP(10);
3581                 }
3582         }
3583
3584         /* Clean BSSID */
3585         bzero(&bssid, sizeof(bssid));
3586         if (!wl_get_drv_status(wl, DISCONNECTING, dev))
3587                 wl_update_prof(wl, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
3588
3589         if (p2p_is_on(wl) && (dev != wl_to_prmry_ndev(wl))) {
3590                 /* we only allow to connect using virtual interface in case of P2P */
3591                         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3592                                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3593                                 return BCME_ERROR;
3594                         }
3595                         wl_cfgp2p_set_management_ie(wl, dev, bssidx,
3596                                 VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
3597         } else if (dev == wl_to_prmry_ndev(wl)) {
3598                 /* find the RSN_IE */
3599                 if ((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
3600                         DOT11_MNG_RSN_ID)) != NULL) {
3601                         WL_DBG((" WPA2 IE is found\n"));
3602                 }
3603                 /* find the WPA_IE */
3604                 if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)sme->ie,
3605                         sme->ie_len)) != NULL) {
3606                         WL_DBG((" WPA IE is found\n"));
3607                 }
3608                 if (wpa_ie != NULL || wpa2_ie != NULL) {
3609                         wpaie = (wpa_ie != NULL) ? (u8 *)wpa_ie : (u8 *)wpa2_ie;
3610                         wpaie_len = (wpa_ie != NULL) ? wpa_ie->length : wpa2_ie->len;
3611                         wpaie_len += WPA_RSN_IE_TAG_FIXED_LEN;
3612                         wldev_iovar_setbuf(dev, "wpaie", wpaie, wpaie_len,
3613                                 wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
3614                 } else {
3615                         wldev_iovar_setbuf(dev, "wpaie", NULL, 0,
3616                                 wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
3617                 }
3618
3619                 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3620                         WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3621                         return BCME_ERROR;
3622                 }
3623                 err = wl_cfgp2p_set_management_ie(wl, dev, bssidx,
3624                         VNDR_IE_ASSOCREQ_FLAG, (u8 *)sme->ie, sme->ie_len);
3625                 if (unlikely(err)) {
3626                         return err;
3627                 }
3628         }
3629         if (chan) {
3630                 wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
3631                 chan_cnt = 1;
3632                 WL_DBG(("channel (%d), center_req (%d), %d channels\n", wl->channel,
3633                         chan->center_freq, chan_cnt));
3634         } else
3635                 wl->channel = 0;
3636 #ifdef BCMWAPI_WPI
3637         WL_DBG(("1. enable wapi auth\n"));
3638         if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) {
3639                 WL_DBG(("2. set wapi ie  \n"));
3640                 err = wl_set_set_wapi_ie(dev, sme);
3641                 if (unlikely(err))
3642                         return err;
3643         } else
3644                 WL_DBG(("2. Not wapi ie  \n"));
3645 #endif
3646         WL_DBG(("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len));
3647         WL_DBG(("3. set wapi version \n"));
3648         err = wl_set_wpa_version(dev, sme);
3649         if (unlikely(err)) {
3650                 WL_ERR(("Invalid wpa_version\n"));
3651                 return err;
3652         }
3653 #ifdef BCMWAPI_WPI
3654         if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1)
3655                 WL_DBG(("4. WAPI Dont Set wl_set_auth_type\n"));
3656         else {
3657                 WL_DBG(("4. wl_set_auth_type\n"));
3658 #endif
3659                 err = wl_set_auth_type(dev, sme);
3660                 if (unlikely(err)) {
3661                         WL_ERR(("Invalid auth type\n"));
3662                         return err;
3663                 }
3664 #ifdef BCMWAPI_WPI
3665         }
3666 #endif
3667
3668         err = wl_set_set_cipher(dev, sme);
3669         if (unlikely(err)) {
3670                 WL_ERR(("Invalid ciper\n"));
3671                 return err;
3672         }
3673
3674         err = wl_set_key_mgmt(dev, sme);
3675         if (unlikely(err)) {
3676                 WL_ERR(("Invalid key mgmt\n"));
3677                 return err;
3678         }
3679
3680         err = wl_set_set_sharedkey(dev, sme);
3681         if (unlikely(err)) {
3682                 WL_ERR(("Invalid shared key\n"));
3683                 return err;
3684         }
3685
3686         /*
3687          *  Join with specific BSSID and cached SSID
3688          *  If SSID is zero join based on BSSID only
3689          */
3690         join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE +
3691                 chan_cnt * sizeof(chanspec_t);
3692         ext_join_params =  (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL);
3693         if (ext_join_params == NULL) {
3694                 err = -ENOMEM;
3695                 wl_clr_drv_status(wl, CONNECTING, dev);
3696                 goto exit;
3697         }
3698         ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len);
3699         memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len);
3700         wl_update_prof(wl, dev, NULL, &ext_join_params->ssid, WL_PROF_SSID);
3701         ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
3702         /* increate dwell time to receive probe response or detect Beacon
3703         * from target AP at a noisy air only when channel info is provided in connect command
3704         */
3705         ext_join_params->scan.active_time = chan_cnt ? WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS : -1;
3706         ext_join_params->scan.passive_time = chan_cnt ? WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS : -1;
3707         /* Set up join scan parameters */
3708         ext_join_params->scan.scan_type = -1;
3709         ext_join_params->scan.nprobes = chan_cnt ?
3710                 (ext_join_params->scan.active_time/WL_SCAN_JOIN_PROBE_INTERVAL_MS) : -1;
3711         ext_join_params->scan.home_time = -1;
3712
3713         if (sme->bssid)
3714                 memcpy(&ext_join_params->assoc.bssid, sme->bssid, ETH_ALEN);
3715         else
3716                 memcpy(&ext_join_params->assoc.bssid, &ether_bcast, ETH_ALEN);
3717         ext_join_params->assoc.chanspec_num = chan_cnt;
3718         if (chan_cnt) {
3719                 u16 channel, band, bw, ctl_sb;
3720                 chanspec_t chspec;
3721                 channel = wl->channel;
3722                 band = (channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G
3723                         : WL_CHANSPEC_BAND_5G;
3724                 bw = WL_CHANSPEC_BW_20;
3725                 ctl_sb = WL_CHANSPEC_CTL_SB_NONE;
3726                 chspec = (channel | band | bw | ctl_sb);
3727                 ext_join_params->assoc.chanspec_list[0]  &= WL_CHANSPEC_CHAN_MASK;
3728                 ext_join_params->assoc.chanspec_list[0] |= chspec;
3729                 ext_join_params->assoc.chanspec_list[0] =
3730                         wl_chspec_host_to_driver(ext_join_params->assoc.chanspec_list[0]);
3731         }
3732         ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num);
3733         if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
3734                 WL_INFO(("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID,
3735                         ext_join_params->ssid.SSID_len));
3736         }
3737         wl_set_drv_status(wl, CONNECTING, dev);
3738
3739         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3740                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3741                 return BCME_ERROR;
3742         }
3743         err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size,
3744                 wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3745         kfree(ext_join_params);
3746         if (err) {
3747                 wl_clr_drv_status(wl, CONNECTING, dev);
3748                 if (err == BCME_UNSUPPORTED) {
3749                         WL_DBG(("join iovar is not supported\n"));
3750                         goto set_ssid;
3751                 } else
3752                         WL_ERR(("error (%d)\n", err));
3753         } else
3754                 goto exit;
3755
3756 set_ssid:
3757         memset(&join_params, 0, sizeof(join_params));
3758         join_params_size = sizeof(join_params.ssid);
3759
3760         join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
3761         memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
3762         join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
3763         wl_update_prof(wl, dev, NULL, &join_params.ssid, WL_PROF_SSID);
3764         if (sme->bssid)
3765                 memcpy(&join_params.params.bssid, sme->bssid, ETH_ALEN);
3766         else
3767                 memcpy(&join_params.params.bssid, &ether_bcast, ETH_ALEN);
3768
3769         wl_ch_to_chanspec(wl->channel, &join_params, &join_params_size);
3770         WL_DBG(("join_param_size %zu\n", join_params_size));
3771
3772         if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
3773                 WL_INFO(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
3774                         join_params.ssid.SSID_len));
3775         }
3776         wl_set_drv_status(wl, CONNECTING, dev);
3777         err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true);
3778         if (err) {
3779                 WL_ERR(("error (%d)\n", err));
3780                 wl_clr_drv_status(wl, CONNECTING, dev);
3781         }
3782 exit:
3783         return err;
3784 }
3785
3786 static s32
3787 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
3788         u16 reason_code)
3789 {
3790         struct wl_priv *wl = wiphy_priv(wiphy);
3791         scb_val_t scbval;
3792         bool act = false;
3793         s32 err = 0;
3794         u8 *curbssid;
3795         WL_ERR(("Reason %d\n", reason_code));
3796         RETURN_EIO_IF_NOT_UP(wl);
3797         act = *(bool *) wl_read_prof(wl, dev, WL_PROF_ACT);
3798         curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID);
3799         if (act) {
3800                 /*
3801                 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
3802                 */
3803 #if !defined(ESCAN_RESULT_PATCH)
3804                 /* Let scan aborted by F/W */
3805                 if (wl->scan_request) {
3806                         wl_notify_escan_complete(wl, dev, true, true);
3807                 }
3808 #endif /* ESCAN_RESULT_PATCH */
3809                 wl_set_drv_status(wl, DISCONNECTING, dev);
3810                 scbval.val = reason_code;
3811                 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
3812                 scbval.val = htod32(scbval.val);
3813                 err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
3814                         sizeof(scb_val_t), true);
3815                 if (unlikely(err)) {
3816                         wl_clr_drv_status(wl, DISCONNECTING, dev);
3817                         WL_ERR(("error (%d)\n", err));
3818                         return err;
3819                 }
3820         }
3821
3822         return err;
3823 }
3824
3825 static s32
3826 #if defined(WL_CFG80211_P2P_DEV_IF)
3827 wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
3828         enum nl80211_tx_power_setting type, s32 mbm)
3829 #else
3830 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
3831         enum nl80211_tx_power_setting type, s32 dbm)
3832 #endif /* WL_CFG80211_P2P_DEV_IF */
3833 {
3834
3835         struct wl_priv *wl = wiphy_priv(wiphy);
3836         struct net_device *ndev = wl_to_prmry_ndev(wl);
3837         u16 txpwrmw;
3838         s32 err = 0;
3839         s32 disable = 0;
3840         s32 txpwrqdbm;
3841 #if defined(WL_CFG80211_P2P_DEV_IF)
3842         s32 dbm = MBM_TO_DBM(mbm);
3843 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || \
3844         defined(WL_COMPAT_WIRELESS) || defined(WL_SUPPORT_BACKPORTED_KPATCHES)
3845         dbm = MBM_TO_DBM(dbm);
3846 #endif /* WL_CFG80211_P2P_DEV_IF */
3847
3848         RETURN_EIO_IF_NOT_UP(wl);
3849         switch (type) {
3850         case NL80211_TX_POWER_AUTOMATIC:
3851                 break;
3852         case NL80211_TX_POWER_LIMITED:
3853                 if (dbm < 0) {
3854                         WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
3855                         return -EINVAL;
3856                 }
3857                 break;
3858         case NL80211_TX_POWER_FIXED:
3859                 if (dbm < 0) {
3860                         WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
3861                         return -EINVAL;
3862                 }
3863                 break;
3864         }
3865         /* Make sure radio is off or on as far as software is concerned */
3866         disable = WL_RADIO_SW_DISABLE << 16;
3867         disable = htod32(disable);
3868         err = wldev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable), true);
3869         if (unlikely(err)) {
3870                 WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
3871                 return err;
3872         }
3873
3874         if (dbm > 0xffff)
3875                 txpwrmw = 0xffff;
3876         else
3877                 txpwrmw = (u16) dbm;
3878         txpwrqdbm = (s32)bcm_mw_to_qdbm(txpwrmw);
3879 #ifdef SUPPORT_WL_TXPOWER
3880         if (type == NL80211_TX_POWER_AUTOMATIC)
3881                 txpwrqdbm = 127;
3882         txpwrqdbm |= WL_TXPWR_OVERRIDE;
3883 #endif /* SUPPORT_WL_TXPOWER */
3884         err = wldev_iovar_setint(ndev, "qtxpower", txpwrqdbm);
3885         if (unlikely(err)) {
3886                 WL_ERR(("qtxpower error (%d)\n", err));
3887                 return err;
3888         }
3889         wl->conf->tx_power = dbm;
3890
3891         return err;
3892 }
3893
3894 static s32
3895 #if defined(WL_CFG80211_P2P_DEV_IF)
3896 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
3897         struct wireless_dev *wdev, s32 *dbm)
3898 #else
3899 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
3900 #endif /* WL_CFG80211_P2P_DEV_IF */
3901 {
3902         struct wl_priv *wl = wiphy_priv(wiphy);
3903         struct net_device *ndev = wl_to_prmry_ndev(wl);
3904         s32 txpwrdbm;
3905         u8 result;
3906         s32 err = 0;
3907
3908         RETURN_EIO_IF_NOT_UP(wl);
3909         err = wldev_iovar_getint(ndev, "qtxpower", &txpwrdbm);
3910         if (unlikely(err)) {
3911                 WL_ERR(("error (%d)\n", err));
3912                 return err;
3913         }
3914         result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
3915         *dbm = (s32) bcm_qdbm_to_mw(result);
3916
3917         return err;
3918 }
3919
3920 static s32
3921 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
3922         u8 key_idx, bool unicast, bool multicast)
3923 {
3924         struct wl_priv *wl = wiphy_priv(wiphy);
3925         u32 index;
3926         s32 wsec;
3927         s32 err = 0;
3928         s32 bssidx;
3929         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3930                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3931                 return BCME_ERROR;
3932         }
3933
3934         WL_DBG(("key index (%d)\n", key_idx));
3935         RETURN_EIO_IF_NOT_UP(wl);
3936         err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
3937         if (unlikely(err)) {
3938                 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
3939                 return err;
3940         }
3941         /* fix IOT issue with Apple Airport */
3942         if (wsec == WEP_ENABLED) {
3943                 /* Just select a new current key */
3944                 index = (u32) key_idx;
3945                 index = htod32(index);
3946                 err = wldev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
3947                         sizeof(index), true);
3948                 if (unlikely(err)) {
3949                         WL_ERR(("error (%d)\n", err));
3950                 }
3951         }
3952         return err;
3953 }
3954
3955 static s32
3956 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
3957         u8 key_idx, const u8 *mac_addr, struct key_params *params)
3958 {
3959         struct wl_priv *wl = wiphy_priv(wiphy);
3960         struct wl_wsec_key key;
3961         s32 err = 0;
3962         s32 bssidx;
3963         s32 mode = wl_get_mode_by_netdev(wl, dev);
3964         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3965                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3966                 return BCME_ERROR;
3967         }
3968         memset(&key, 0, sizeof(key));
3969         key.index = (u32) key_idx;
3970
3971         if (!ETHER_ISMULTI(mac_addr))
3972                 memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN);
3973         key.len = (u32) params->key_len;
3974
3975         /* check for key index change */
3976         if (key.len == 0) {
3977                 /* key delete */
3978                 swap_key_from_BE(&key);
3979                 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
3980                         wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3981                 if (unlikely(err)) {
3982                         WL_ERR(("key delete error (%d)\n", err));
3983                         return err;
3984                 }
3985         } else {
3986                 if (key.len > sizeof(key.data)) {
3987                         WL_ERR(("Invalid key length (%d)\n", key.len));
3988                         return -EINVAL;
3989                 }
3990                 WL_DBG(("Setting the key index %d\n", key.index));
3991                 memcpy(key.data, params->key, key.len);
3992
3993                 if ((mode == WL_MODE_BSS) &&
3994                         (params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
3995                         u8 keybuf[8];
3996                         memcpy(keybuf, &key.data[24], sizeof(keybuf));
3997                         memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
3998                         memcpy(&key.data[16], keybuf, sizeof(keybuf));
3999                 }
4000
4001                 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
4002                 if (params->seq && params->seq_len == 6) {
4003                         /* rx iv */
4004                         u8 *ivptr;
4005                         ivptr = (u8 *) params->seq;
4006                         key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
4007                                 (ivptr[3] << 8) | ivptr[2];
4008                         key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
4009                         key.iv_initialized = true;
4010                 }
4011
4012                 switch (params->cipher) {
4013                 case WLAN_CIPHER_SUITE_WEP40:
4014                         key.algo = CRYPTO_ALGO_WEP1;
4015                         WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
4016                         break;
4017                 case WLAN_CIPHER_SUITE_WEP104:
4018                         key.algo = CRYPTO_ALGO_WEP128;
4019                         WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
4020                         break;
4021                 case WLAN_CIPHER_SUITE_TKIP:
4022                         key.algo = CRYPTO_ALGO_TKIP;
4023                         WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
4024                         break;
4025                 case WLAN_CIPHER_SUITE_AES_CMAC:
4026                         key.algo = CRYPTO_ALGO_AES_CCM;
4027                         WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
4028                         break;
4029                 case WLAN_CIPHER_SUITE_CCMP:
4030                         key.algo = CRYPTO_ALGO_AES_CCM;
4031                         WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
4032                         break;
4033 #ifdef BCMWAPI_WPI
4034                 case WLAN_CIPHER_SUITE_SMS4:
4035                         key.algo = CRYPTO_ALGO_SMS4;
4036                         WL_DBG(("WLAN_CIPHER_SUITE_SMS4\n"));
4037                         break;
4038 #endif
4039                 default:
4040                         WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
4041                         return -EINVAL;
4042                 }
4043                 swap_key_from_BE(&key);
4044                 /* need to guarantee EAPOL 4/4 send out before set key */
4045                 dhd_wait_pend8021x(dev);
4046                 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
4047                         wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
4048                 if (unlikely(err)) {
4049                         WL_ERR(("WLC_SET_KEY error (%d)\n", err));
4050                         return err;
4051                 }
4052         }
4053         return err;
4054 }
4055
4056 static s32
4057 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
4058         u8 key_idx, bool pairwise, const u8 *mac_addr,
4059         struct key_params *params)
4060 {
4061         struct wl_wsec_key key;
4062         s32 val = 0;
4063         s32 wsec = 0;
4064         s32 err = 0;
4065         u8 keybuf[8];
4066         s32 bssidx = 0;
4067         struct wl_priv *wl = wiphy_priv(wiphy);
4068         s32 mode = wl_get_mode_by_netdev(wl, dev);
4069         WL_DBG(("key index (%d)\n", key_idx));
4070         RETURN_EIO_IF_NOT_UP(wl);
4071
4072         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
4073                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4074                 return BCME_ERROR;
4075         }
4076
4077         if (mac_addr &&
4078                 ((params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
4079                 (params->cipher != WLAN_CIPHER_SUITE_WEP104))) {
4080                         wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
4081                         goto exit;
4082         }
4083         memset(&key, 0, sizeof(key));
4084
4085         key.len = (u32) params->key_len;
4086         key.index = (u32) key_idx;
4087
4088         if (unlikely(key.len > sizeof(key.data))) {
4089                 WL_ERR(("Too long key length (%u)\n", key.len));
4090                 return -EINVAL;
4091         }
4092         memcpy(key.data, params->key, key.len);
4093
4094         key.flags = WL_PRIMARY_KEY;
4095         switch (params->cipher) {
4096         case WLAN_CIPHER_SUITE_WEP40:
4097                 key.algo = CRYPTO_ALGO_WEP1;
4098                 val = WEP_ENABLED;
4099                 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
4100                 break;
4101         case WLAN_CIPHER_SUITE_WEP104:
4102                 key.algo = CRYPTO_ALGO_WEP128;
4103                 val = WEP_ENABLED;
4104                 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
4105                 break;
4106         case WLAN_CIPHER_SUITE_TKIP:
4107                 key.algo = CRYPTO_ALGO_TKIP;
4108                 val = TKIP_ENABLED;
4109                 /* wpa_supplicant switches the third and fourth quarters of the TKIP key */
4110                 if (mode == WL_MODE_BSS) {
4111                         bcopy(&key.data[24], keybuf, sizeof(keybuf));
4112                         bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
4113                         bcopy(keybuf, &key.data[16], sizeof(keybuf));
4114                 }
4115                 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
4116                 break;
4117         case WLAN_CIPHER_SUITE_AES_CMAC:
4118                 key.algo = CRYPTO_ALGO_AES_CCM;
4119                 val = AES_ENABLED;
4120                 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
4121                 break;
4122         case WLAN_CIPHER_SUITE_CCMP:
4123                 key.algo = CRYPTO_ALGO_AES_CCM;
4124                 val = AES_ENABLED;
4125                 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
4126                 break;
4127 #ifdef BCMWAPI_WPI
4128         case WLAN_CIPHER_SUITE_SMS4:
4129                 key.algo = CRYPTO_ALGO_SMS4;
4130                 WL_DBG(("WLAN_CIPHER_SUITE_SMS4\n"));
4131                 val = SMS4_ENABLED;
4132                 break;
4133 #endif /* BCMWAPI_WPI */
4134 #if defined(WLFBT) && defined(WLAN_CIPHER_SUITE_PMK)
4135         case WLAN_CIPHER_SUITE_PMK: {
4136                 int j;
4137                 wsec_pmk_t pmk;
4138                 char keystring[WSEC_MAX_PSK_LEN + 1];
4139                 char* charptr = keystring;
4140                 uint len;
4141
4142                 /* copy the raw hex key to the appropriate format */
4143                 for (j = 0; j < (WSEC_MAX_PSK_LEN / 2); j++) {
4144                         sprintf(charptr, "%02x", params->key[j]);
4145                         charptr += 2;
4146                 }
4147                 len = strlen(keystring);
4148                 pmk.key_len = htod16(len);
4149                 bcopy(keystring, pmk.key, len);
4150                 pmk.flags = htod16(WSEC_PASSPHRASE);
4151
4152                 err = wldev_ioctl(dev, WLC_SET_WSEC_PMK, &pmk, sizeof(pmk), true);
4153                 if (err)
4154                         return err;
4155         } break;
4156 #endif /* WLFBT && WLAN_CIPHER_SUITE_PMK */
4157         default:
4158                 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
4159                 return -EINVAL;
4160         }
4161
4162         /* Set the new key/index */
4163         if ((mode == WL_MODE_IBSS) && (val & (TKIP_ENABLED | AES_ENABLED))) {
4164                 WL_ERR(("IBSS KEY setted\n"));
4165                 wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_NONE);
4166         }
4167         swap_key_from_BE(&key);
4168         err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), wl->ioctl_buf,
4169                 WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
4170         if (unlikely(err)) {
4171                 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
4172                 return err;
4173         }
4174
4175 exit:
4176         err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
4177         if (unlikely(err)) {
4178                 WL_ERR(("get wsec error (%d)\n", err));
4179                 return err;
4180         }
4181
4182         wsec |= val;
4183         err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
4184         if (unlikely(err)) {
4185                 WL_ERR(("set wsec error (%d)\n", err));
4186                 return err;
4187         }
4188
4189         return err;
4190 }
4191
4192 static s32
4193 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
4194         u8 key_idx, bool pairwise, const u8 *mac_addr)
4195 {
4196         struct wl_wsec_key key;
4197         struct wl_priv *wl = wiphy_priv(wiphy);
4198         s32 err = 0;
4199         s32 bssidx;
4200         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
4201                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4202                 return BCME_ERROR;
4203         }
4204         WL_DBG(("Enter\n"));
4205
4206 #ifndef IEEE80211W
4207         if ((key_idx >= DOT11_MAX_DEFAULT_KEYS) && (key_idx < DOT11_MAX_DEFAULT_KEYS+2))
4208                 return -EINVAL;
4209 #endif
4210
4211         RETURN_EIO_IF_NOT_UP(wl);
4212         memset(&key, 0, sizeof(key));
4213
4214         key.flags = WL_PRIMARY_KEY;
4215         key.algo = CRYPTO_ALGO_OFF;
4216         key.index = (u32) key_idx;
4217
4218         WL_DBG(("key index (%d)\n", key_idx));
4219         /* Set the new key/index */
4220         swap_key_from_BE(&key);
4221         err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), wl->ioctl_buf,
4222                 WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
4223         if (unlikely(err)) {
4224                 if (err == -EINVAL) {
4225                         if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
4226                                 /* we ignore this key index in this case */
4227                                 WL_DBG(("invalid key index (%d)\n", key_idx));
4228                         }
4229                 } else {
4230                         WL_ERR(("WLC_SET_KEY error (%d)\n", err));
4231                 }
4232                 return err;
4233         }
4234         return err;
4235 }
4236
4237 static s32
4238 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
4239         u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
4240         void (*callback) (void *cookie, struct key_params * params))
4241 {
4242         struct key_params params;
4243         struct wl_wsec_key key;
4244         struct wl_priv *wl = wiphy_priv(wiphy);
4245         struct wl_security *sec;
4246         s32 wsec;
4247         s32 err = 0;
4248         s32 bssidx;
4249         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
4250                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4251                 return BCME_ERROR;
4252         }
4253         WL_DBG(("key index (%d)\n", key_idx));
4254         RETURN_EIO_IF_NOT_UP(wl);
4255         memset(&key, 0, sizeof(key));
4256         key.index = key_idx;
4257         swap_key_to_BE(&key);
4258         memset(&params, 0, sizeof(params));
4259         params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
4260         memcpy(params.key, key.data, params.key_len);
4261
4262         err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
4263         if (unlikely(err)) {
4264                 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
4265                 return err;
4266         }
4267         switch (wsec & ~SES_OW_ENABLED) {
4268                 case WEP_ENABLED:
4269                         sec = wl_read_prof(wl, dev, WL_PROF_SEC);
4270                         if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
4271                                 params.cipher = WLAN_CIPHER_SUITE_WEP40;
4272                                 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
4273                         } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
4274                                 params.cipher = WLAN_CIPHER_SUITE_WEP104;
4275                                 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
4276                         }
4277                         break;
4278                 case TKIP_ENABLED:
4279                         params.cipher = WLAN_CIPHER_SUITE_TKIP;
4280                         WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
4281                         break;
4282                 case AES_ENABLED:
4283                         params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
4284                         WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
4285                         break;
4286 #ifdef BCMWAPI_WPI
4287                 case WLAN_CIPHER_SUITE_SMS4:
4288                         key.algo = CRYPTO_ALGO_SMS4;
4289                         WL_DBG(("WLAN_CIPHER_SUITE_SMS4\n"));
4290                         break;
4291 #endif
4292                 default:
4293                         WL_ERR(("Invalid algo (0x%x)\n", wsec));
4294                         return -EINVAL;
4295         }
4296
4297         callback(cookie, &params);
4298         return err;
4299 }
4300
4301 // terence 20130703: Fix for wrong group_capab (timing issue)
4302 int p2p_disconnected = 0;
4303 struct ether_addr p2p_disconnected_bssid;
4304
4305 #if defined(RSSIAVG)
4306 static wl_rssi_cache_ctrl_t g_rssi_cache_ctrl;
4307 static wl_rssi_cache_ctrl_t g_rssi2_cache_ctrl;
4308 #endif
4309 #if defined(BSSCACHE)
4310 static wl_bss_cache_ctrl_t g_bss_cache_ctrl;
4311 #endif
4312
4313 static s32
4314 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
4315         struct net_device *dev, u8 key_idx)
4316 {
4317         WL_INFO(("Not supported\n"));
4318         return -EOPNOTSUPP;
4319 }
4320
4321 static s32
4322 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
4323         u8 *mac, struct station_info *sinfo)
4324 {
4325         struct wl_priv *wl = wiphy_priv(wiphy);
4326         scb_val_t scb_val;
4327         s32 rssi;
4328         s32 rate;
4329         s32 err = 0;
4330         sta_info_t *sta;
4331 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) || defined(WL_COMPAT_WIRELESS)
4332         s8 eabuf[ETHER_ADDR_STR_LEN];
4333 #endif
4334         static int err_cnt = 0;
4335         dhd_pub_t *dhd =  (dhd_pub_t *)(wl->pub);
4336         RETURN_EIO_IF_NOT_UP(wl);
4337         if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) {
4338                 err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac,
4339                         ETHER_ADDR_LEN, wl->ioctl_buf, WLC_IOCTL_SMLEN, &wl->ioctl_buf_sync);
4340                 if (err < 0) {
4341                         WL_ERR(("GET STA INFO failed, %d\n", err));
4342                         return err;
4343                 }
4344                 sinfo->filled = STATION_INFO_INACTIVE_TIME;
4345                 sta = (sta_info_t *)wl->ioctl_buf;
4346                 sta->len = dtoh16(sta->len);
4347                 sta->cap = dtoh16(sta->cap);
4348                 sta->flags = dtoh32(sta->flags);
4349                 sta->idle = dtoh32(sta->idle);
4350                 sta->in = dtoh32(sta->in);
4351                 sinfo->inactive_time = sta->idle * 1000;
4352 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) || defined(WL_COMPAT_WIRELESS)
4353                 if (sta->flags & WL_STA_ASSOC) {
4354                         sinfo->filled |= STATION_INFO_CONNECTED_TIME;
4355                         sinfo->connected_time = sta->in;
4356                 }
4357                 WL_INFO(("STA %s : idle time : %d sec, connected time :%d ms\n",
4358                         bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), sinfo->inactive_time,
4359                         sta->idle * 1000));
4360 #endif
4361         } else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_BSS ||
4362                 wl_get_mode_by_netdev(wl, dev) == WL_MODE_IBSS) {
4363                 get_pktcnt_t pktcnt;
4364                 u8 *curmacp = wl_read_prof(wl, dev, WL_PROF_BSSID);
4365                 if (!wl_get_drv_status(wl, CONNECTED, dev) ||
4366                         (dhd_is_associated(dhd, NULL, &err) == FALSE)) {
4367                         WL_ERR(("NOT assoc\n"));
4368                         if (err == -ERESTARTSYS)
4369                                 return err;
4370                         err = -ENODEV;
4371                         return err;
4372                 }
4373                 if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
4374                         WL_ERR(("Wrong Mac address: "MACDBG" != "MACDBG"\n",
4375                                 MAC2STRDBG(mac), MAC2STRDBG(curmacp)));
4376                 }
4377
4378                 /* Report the current tx rate */
4379                 err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
4380                 if (err) {
4381                         WL_ERR(("Could not get rate (%d)\n", err));
4382                 } else {
4383 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
4384                         int rxpktglom;
4385 #endif
4386                         rate = dtoh32(rate);
4387                         sinfo->filled |= STATION_INFO_TX_BITRATE;
4388                         sinfo->txrate.legacy = rate * 5;
4389                         WL_DBG(("Rate %d Mbps\n", (rate / 2)));
4390 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
4391                         rxpktglom = ((rate/2) > 150) ? 20 : 10;
4392
4393                         if (maxrxpktglom != rxpktglom) {
4394                                 maxrxpktglom = rxpktglom;
4395                                 WL_DBG(("Rate %d Mbps, update bus:maxtxpktglom=%d\n", (rate/2),
4396                                         maxrxpktglom));
4397                                 err = wldev_iovar_setbuf(dev, "bus:maxtxpktglom",
4398                                         (char*)&maxrxpktglom, 4, wl->ioctl_buf,
4399                                         WLC_IOCTL_MAXLEN, NULL);
4400                                 if (err < 0) {
4401                                         WL_ERR(("set bus:maxtxpktglom failed, %d\n", err));
4402                                 }
4403                         }
4404 #endif
4405                 }
4406
4407                 memset(&scb_val, 0, sizeof(scb_val));
4408                 scb_val.val = 0;
4409                 err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,
4410                         sizeof(scb_val_t), false);
4411                 if (err) {
4412                         WL_ERR(("Could not get rssi (%d)\n", err));
4413                         goto get_station_err;
4414                 }
4415                 rssi = dtoh32(scb_val.val);
4416 #if defined(RSSIAVG)
4417                 err = wl_update_connected_rssi_cache(dev, &g_rssi2_cache_ctrl, &rssi);
4418                 if (err) {
4419                         WL_ERR(("Could not get rssi (%d)\n", err));
4420                         goto get_station_err;
4421                 }
4422                 wl_delete_dirty_rssi_cache(&g_rssi2_cache_ctrl);
4423                 wl_reset_rssi_cache(&g_rssi2_cache_ctrl);
4424 #endif
4425 #if defined(RSSIOFFSET)
4426                 rssi = wl_update_rssi_offset(rssi);
4427 #endif
4428                 sinfo->filled |= STATION_INFO_SIGNAL;
4429                 sinfo->signal = rssi;
4430                 WL_DBG(("RSSI %d dBm\n", rssi));
4431                 err = wldev_ioctl(dev, WLC_GET_PKTCNTS, &pktcnt,
4432                         sizeof(pktcnt), false);
4433                 if (!err) {
4434                         sinfo->filled |= (STATION_INFO_RX_PACKETS |
4435                                 STATION_INFO_RX_DROP_MISC |
4436                                 STATION_INFO_TX_PACKETS |
4437                                 STATION_INFO_TX_FAILED);
4438                         sinfo->rx_packets = pktcnt.rx_good_pkt;
4439                         sinfo->rx_dropped_misc = pktcnt.rx_bad_pkt;
4440                         sinfo->tx_packets = pktcnt.tx_good_pkt;
4441                         sinfo->tx_failed  = pktcnt.tx_bad_pkt;
4442                 }
4443 get_station_err:
4444                 if (err)
4445                         err_cnt++;
4446                 else
4447                         err_cnt = 0;
4448                 if (err_cnt >= 3 && (err != -ERESTARTSYS)) {
4449                         /* Disconnect due to zero BSSID or error to get RSSI */
4450                         WL_ERR(("force cfg80211_disconnected: %d\n", err));
4451                         wl_clr_drv_status(wl, CONNECTED, dev);
4452                         cfg80211_disconnected(dev, 0, NULL, 0, GFP_KERNEL);
4453                         wl_link_down(wl);
4454                 }
4455         }
4456         else {
4457                 WL_ERR(("Invalid device mode %d\n", wl_get_mode_by_netdev(wl, dev)));
4458         }
4459
4460         return err;
4461 }
4462
4463 /* Function to update sta power save mode for Kernel wifi stack */
4464 int wl_cfg80211_update_power_mode(struct net_device *dev)
4465 {
4466         int pm = -1;
4467         int err;
4468
4469         err = wldev_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), false);
4470         if (err || (pm == -1)) {
4471                 WL_ERR(("error (%d)\n", err));
4472         } else {
4473                 pm = (pm == PM_OFF) ? false : true;
4474                 WL_DBG(("%s: %d\n", __func__, pm));
4475                 if (dev->ieee80211_ptr)
4476                         dev->ieee80211_ptr->ps = pm;
4477         }
4478         return err;
4479 }
4480
4481 static s32
4482 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
4483         bool enabled, s32 timeout)
4484 {
4485         s32 pm;
4486         s32 err = 0;
4487         struct wl_priv *wl = wiphy_priv(wiphy);
4488         struct net_info *_net_info = wl_get_netinfo_by_netdev(wl, dev);
4489 #if !defined(SUPPORT_PM2_ONLY)
4490         dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
4491 #endif /* (OEM_ANDROID) */
4492         RETURN_EIO_IF_NOT_UP(wl);
4493         WL_DBG(("Enter\n"));
4494 #if defined(WL_ENABLE_P2P_IF)
4495         if (wl->p2p_net == dev || _net_info == NULL || wl->vsdb_mode ||
4496                 !wl_get_drv_status(wl, CONNECTED, dev))
4497 #else
4498         if (_net_info == NULL || wl->vsdb_mode ||
4499                 !wl_get_drv_status(wl, CONNECTED, dev))
4500 #endif /* WL_ENABLE_P2P_IF */
4501         {
4502                 return err;
4503         }
4504         WL_DBG(("%s: Enter power save enabled %d\n", dev->name, enabled));
4505
4506         /* Delete pm_enable_work */
4507         if (wl->pm_enable_work_on) {
4508                 cancel_delayed_work_sync(&wl->pm_enable_work);
4509                 wl->pm_enable_work_on = false;
4510         }
4511
4512 #if !defined(SUPPORT_PM2_ONLY)
4513         /* android has special hooks to change pm when kernel suspended */
4514         pm = enabled ? ((dhd->in_suspend) ? PM_MAX : PM_FAST) : PM_OFF;
4515 #else
4516         pm = enabled ? PM_FAST : PM_OFF;
4517 #endif /* SUPPORT_PM2_ONLY */
4518         if (_net_info->pm_block) {
4519                 WL_ERR(("%s:Do not enable the power save for pm_block %d\n",
4520                         dev->name, _net_info->pm_block));
4521                 pm = PM_OFF;
4522         }
4523         pm = htod32(pm);
4524         WL_DBG(("%s:power save %s\n", dev->name, (pm ? "enabled" : "disabled")));
4525         err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true);
4526         if (unlikely(err)) {
4527                 if (err == -ENODEV)
4528                         WL_DBG(("net_device is not ready yet\n"));
4529                 else
4530                         WL_ERR(("error (%d)\n", err));
4531                 return err;
4532         }
4533         return err;
4534 }
4535
4536 static __used u32 wl_find_msb(u16 bit16)
4537 {
4538         u32 ret = 0;
4539
4540         if (bit16 & 0xff00) {
4541                 ret += 8;
4542                 bit16 >>= 8;
4543         }
4544
4545         if (bit16 & 0xf0) {
4546                 ret += 4;
4547                 bit16 >>= 4;
4548         }
4549
4550         if (bit16 & 0xc) {
4551                 ret += 2;
4552                 bit16 >>= 2;
4553         }
4554
4555         if (bit16 & 2)
4556                 ret += bit16 & 2;
4557         else if (bit16)
4558                 ret += bit16;
4559
4560         return ret;
4561 }
4562
4563 static s32 wl_cfg80211_resume(struct wiphy *wiphy)
4564 {
4565         struct wl_priv *wl = wiphy_priv(wiphy);
4566         struct net_device *ndev = wl_to_prmry_ndev(wl);
4567         s32 err = 0;
4568
4569         if (unlikely(!wl_get_drv_status(wl, READY, ndev))) {
4570                 WL_INFO(("device is not ready\n"));
4571                 return 0;
4572         }
4573
4574         wl_invoke_iscan(wl);
4575
4576         return err;
4577 }
4578
4579 static s32
4580 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)
4581 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
4582 #else
4583 wl_cfg80211_suspend(struct wiphy *wiphy)
4584 #endif
4585 {
4586 #ifdef DHD_CLEAR_ON_SUSPEND
4587         struct wl_priv *wl = wiphy_priv(wiphy);
4588         struct net_info *iter, *next;
4589         struct net_device *ndev = wl_to_prmry_ndev(wl);
4590         unsigned long flags;
4591         if (unlikely(!wl_get_drv_status(wl, READY, ndev))) {
4592                 WL_INFO(("device is not ready : status (%d)\n",
4593                         (int)wl->status));
4594                 return 0;
4595         }
4596         for_each_ndev(wl, iter, next)
4597                 wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev);
4598         wl_term_iscan(wl);
4599         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
4600         if (wl->scan_request) {
4601                 cfg80211_scan_done(wl->scan_request, true);
4602                 wl->scan_request = NULL;
4603         }
4604         for_each_ndev(wl, iter, next) {
4605                 wl_clr_drv_status(wl, SCANNING, iter->ndev);
4606                 wl_clr_drv_status(wl, SCAN_ABORTING, iter->ndev);
4607         }
4608         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
4609         for_each_ndev(wl, iter, next) {
4610                 if (wl_get_drv_status(wl, CONNECTING, iter->ndev)) {
4611                         wl_bss_connect_done(wl, iter->ndev, NULL, NULL, false);
4612                 }
4613         }
4614 #endif /* DHD_CLEAR_ON_SUSPEND */
4615         return 0;
4616 }
4617
4618 static s32
4619 wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
4620         s32 err)
4621 {
4622         int i, j;
4623         struct wl_priv *wl = wlcfg_drv_priv;
4624         struct net_device *primary_dev = wl_to_prmry_ndev(wl);
4625
4626         if (!pmk_list) {
4627                 printk("pmk_list is NULL\n");
4628                 return -EINVAL;
4629         }
4630         /* pmk list is supported only for STA interface i.e. primary interface
4631          * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
4632          */
4633         if (primary_dev != dev) {
4634                 WL_INFO(("Not supporting Flushing pmklist on virtual"
4635                         " interfaces than primary interface\n"));
4636                 return err;
4637         }
4638
4639         WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
4640         for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
4641                 WL_DBG(("PMKID[%d]: %pM =\n", i,
4642                         &pmk_list->pmkids.pmkid[i].BSSID));
4643                 for (j = 0; j < WPA2_PMKID_LEN; j++) {
4644                         WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
4645                 }
4646         }
4647         if (likely(!err)) {
4648                 err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmk_list,
4649                         sizeof(*pmk_list), wl->ioctl_buf, WLC_IOCTL_MAXLEN, NULL);
4650         }
4651
4652         return err;
4653 }
4654
4655 static s32
4656 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
4657         struct cfg80211_pmksa *pmksa)
4658 {
4659         struct wl_priv *wl = wiphy_priv(wiphy);
4660         s32 err = 0;
4661         int i;
4662
4663         RETURN_EIO_IF_NOT_UP(wl);
4664         for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
4665                 if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
4666                         ETHER_ADDR_LEN))
4667                         break;
4668         if (i < WL_NUM_PMKIDS_MAX) {
4669                 memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
4670                         ETHER_ADDR_LEN);
4671                 memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
4672                         WPA2_PMKID_LEN);
4673                 if (i == wl->pmk_list->pmkids.npmkid)
4674                         wl->pmk_list->pmkids.npmkid++;
4675         } else {
4676                 err = -EINVAL;
4677         }
4678         WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
4679                 &wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid - 1].BSSID));
4680         for (i = 0; i < WPA2_PMKID_LEN; i++) {
4681                 WL_DBG(("%02x\n",
4682                         wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid - 1].
4683                         PMKID[i]));
4684         }
4685
4686         err = wl_update_pmklist(dev, wl->pmk_list, err);
4687
4688         return err;
4689 }
4690
4691 static s32
4692 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
4693         struct cfg80211_pmksa *pmksa)
4694 {
4695         struct wl_priv *wl = wiphy_priv(wiphy);
4696         struct _pmkid_list pmkid = {0};
4697         s32 err = 0;
4698         int i;
4699
4700         RETURN_EIO_IF_NOT_UP(wl);
4701         memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
4702         memcpy(pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
4703
4704         WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
4705                 &pmkid.pmkid[0].BSSID));
4706         for (i = 0; i < WPA2_PMKID_LEN; i++) {
4707                 WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
4708         }
4709
4710         for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
4711                 if (!memcmp
4712                     (pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
4713                      ETHER_ADDR_LEN))
4714                         break;
4715
4716         if ((wl->pmk_list->pmkids.npmkid > 0) &&
4717                 (i < wl->pmk_list->pmkids.npmkid)) {
4718                 memset(&wl->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
4719                 for (; i < (wl->pmk_list->pmkids.npmkid - 1); i++) {
4720                         memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID,
4721                                 &wl->pmk_list->pmkids.pmkid[i + 1].BSSID,
4722                                 ETHER_ADDR_LEN);
4723                         memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID,
4724                                 &wl->pmk_list->pmkids.pmkid[i + 1].PMKID,
4725                                 WPA2_PMKID_LEN);
4726                 }
4727                 wl->pmk_list->pmkids.npmkid--;
4728         } else {
4729                 err = -EINVAL;
4730         }
4731
4732         err = wl_update_pmklist(dev, wl->pmk_list, err);
4733
4734         return err;
4735
4736 }
4737
4738 static s32
4739 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
4740 {
4741         struct wl_priv *wl = wiphy_priv(wiphy);
4742         s32 err = 0;
4743         RETURN_EIO_IF_NOT_UP(wl);
4744         memset(wl->pmk_list, 0, sizeof(*wl->pmk_list));
4745         err = wl_update_pmklist(dev, wl->pmk_list, err);
4746         return err;
4747
4748 }
4749
4750 static wl_scan_params_t *
4751 wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size)
4752 {
4753         wl_scan_params_t *params;
4754         int params_size;
4755         int num_chans;
4756
4757         *out_params_size = 0;
4758
4759         /* Our scan params only need space for 1 channel and 0 ssids */
4760         params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16);
4761         params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL);
4762         if (params == NULL) {
4763                 WL_ERR(("mem alloc failed (%d bytes)\n", params_size));
4764                 return params;
4765         }
4766         memset(params, 0, params_size);
4767         params->nprobes = nprobes;
4768
4769         num_chans = (channel == 0) ? 0 : 1;
4770
4771         memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
4772         params->bss_type = DOT11_BSSTYPE_ANY;
4773         params->scan_type = DOT11_SCANTYPE_ACTIVE;
4774         params->nprobes = htod32(1);
4775         params->active_time = htod32(-1);
4776         params->passive_time = htod32(-1);
4777         params->home_time = htod32(10);
4778         if (channel == -1)
4779                 params->channel_list[0] = htodchanspec(channel);
4780         else
4781                 params->channel_list[0] = wl_ch_host_to_driver(channel);
4782
4783         /* Our scan params have 1 channel and 0 ssids */
4784         params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
4785                 (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
4786
4787         *out_params_size = params_size; /* rtn size to the caller */
4788         return params;
4789 }
4790
4791 static s32
4792 #if defined(WL_CFG80211_P2P_DEV_IF)
4793 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
4794         struct ieee80211_channel *channel, unsigned int duration, u64 *cookie)
4795 #else
4796 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
4797         struct ieee80211_channel * channel,
4798         enum nl80211_channel_type channel_type,
4799         unsigned int duration, u64 *cookie)
4800 #endif /* WL_CFG80211_P2P_DEV_IF */
4801 {
4802         s32 target_channel;
4803         u32 id;
4804         s32 err = BCME_OK;
4805         struct ether_addr primary_mac;
4806         struct net_device *ndev = NULL;
4807         struct wl_priv *wl = wiphy_priv(wiphy);
4808
4809         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
4810
4811         WL_DBG(("Enter, channel: %d, duration ms (%d) SCANNING ?? %s \n",
4812                 ieee80211_frequency_to_channel(channel->center_freq),
4813                 duration, (wl_get_drv_status(wl, SCANNING, ndev)) ? "YES":"NO"));
4814
4815         if (!wl->p2p) {
4816                 WL_ERR(("wl->p2p is not initialized\n"));
4817                 err = BCME_ERROR;
4818                 goto exit;
4819         }
4820
4821 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4822         if (wl_get_drv_status_all(wl, SCANNING)) {
4823                 wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true);
4824         }
4825 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4826
4827         target_channel = ieee80211_frequency_to_channel(channel->center_freq);
4828         memcpy(&wl->remain_on_chan, channel, sizeof(struct ieee80211_channel));
4829 #if defined(WL_ENABLE_P2P_IF)
4830         wl->remain_on_chan_type = channel_type;
4831 #endif /* WL_ENABLE_P2P_IF */
4832         id = ++wl->last_roc_id;
4833         if (id == 0)
4834                 id = ++wl->last_roc_id;
4835         *cookie = id;
4836
4837 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4838         if (wl_get_drv_status(wl, SCANNING, ndev)) {
4839                 struct timer_list *_timer;
4840                 WL_DBG(("scan is running. go to fake listen state\n"));
4841
4842                 wl_set_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev);
4843
4844                 if (timer_pending(&wl->p2p->listen_timer)) {
4845                         WL_DBG(("cancel current listen timer \n"));
4846                         del_timer_sync(&wl->p2p->listen_timer);
4847                 }
4848
4849                 _timer = &wl->p2p->listen_timer;
4850                 wl_clr_p2p_status(wl, LISTEN_EXPIRED);
4851
4852                 INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration, 0);
4853
4854                 err = BCME_OK;
4855                 goto exit;
4856         }
4857 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4858
4859 #ifdef WL_CFG80211_SYNC_GON
4860         if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN)) {
4861                 /* do not enter listen mode again if we are in listen mode already for next af.
4862                  * remain on channel completion will be returned by waiting next af completion.
4863                  */
4864 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4865                 wl_set_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev);
4866 #else
4867                 wl_set_drv_status(wl, REMAINING_ON_CHANNEL, ndev);
4868 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4869                 goto exit;
4870         }
4871 #endif /* WL_CFG80211_SYNC_GON */
4872         if (wl->p2p && !wl->p2p->on) {
4873                 /* In case of p2p_listen command, supplicant send remain_on_channel
4874                  * without turning on P2P
4875                  */
4876                 get_primary_mac(wl, &primary_mac);
4877                 wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr);
4878                 p2p_on(wl) = true;
4879         }
4880
4881         if (p2p_is_on(wl)) {
4882                 err = wl_cfgp2p_enable_discovery(wl, ndev, NULL, 0);
4883                 if (unlikely(err)) {
4884                         goto exit;
4885                 }
4886 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4887                 wl_set_drv_status(wl, REMAINING_ON_CHANNEL, ndev);
4888 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4889                 err = wl_cfgp2p_discover_listen(wl, target_channel, duration);
4890
4891 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4892                 if (err == BCME_OK) {
4893                         wl_set_drv_status(wl, REMAINING_ON_CHANNEL, ndev);
4894                 } else {
4895                         /* if failed, firmware may be internal scanning state.
4896                          * so other scan request shall not abort it
4897                          */
4898                         wl_set_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev);
4899                 }
4900 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4901                 /* WAR: set err = ok to prevent cookie mismatch in wpa_supplicant
4902                  * and expire timer will send a completion to the upper layer
4903                  */
4904                 err = BCME_OK;
4905         }
4906
4907 exit:
4908         if (err == BCME_OK) {
4909                 WL_INFO(("Success\n"));
4910 #if defined(WL_CFG80211_P2P_DEV_IF)
4911                 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
4912                         duration, GFP_KERNEL);
4913 #else
4914                 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
4915                         channel_type, duration, GFP_KERNEL);
4916 #endif /* WL_CFG80211_P2P_DEV_IF */
4917         } else {
4918                 WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err, *cookie));
4919         }
4920         return err;
4921 }
4922
4923 static s32
4924 wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
4925         bcm_struct_cfgdev *cfgdev, u64 cookie)
4926 {
4927         s32 err = 0;
4928
4929 #if defined(WL_CFG80211_P2P_DEV_IF)
4930         if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
4931                 WL_DBG((" enter ) on P2P dedicated discover interface\n"));
4932         }
4933 #else
4934         WL_DBG((" enter ) netdev_ifidx: %d \n", cfgdev->ifindex));
4935 #endif /* WL_CFG80211_P2P_DEV_IF */
4936         return err;
4937 }
4938
4939 static void
4940 wl_cfg80211_afx_handler(struct work_struct *work)
4941 {
4942         struct afx_hdl *afx_instance;
4943         struct wl_priv *wl = wlcfg_drv_priv;
4944         s32 ret = BCME_OK;
4945
4946         afx_instance = container_of(work, struct afx_hdl, work);
4947         if (afx_instance != NULL && wl->afx_hdl->is_active) {
4948                 if (wl->afx_hdl->is_listen && wl->afx_hdl->my_listen_chan) {
4949                         ret = wl_cfgp2p_discover_listen(wl, wl->afx_hdl->my_listen_chan,
4950                                 (100 * (1 + (RANDOM32() % 3)))); /* 100ms ~ 300ms */
4951                 } else {
4952                         ret = wl_cfgp2p_act_frm_search(wl, wl->afx_hdl->dev,
4953                                 wl->afx_hdl->bssidx, wl->afx_hdl->peer_listen_chan,
4954                                 NULL);
4955                 }
4956                 if (unlikely(ret != BCME_OK)) {
4957                         WL_ERR(("ERROR occurred! returned value is (%d)\n", ret));
4958                         if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL))
4959                                 complete(&wl->act_frm_scan);
4960                 }
4961         }
4962 }
4963
4964 static s32
4965 wl_cfg80211_af_searching_channel(struct wl_priv *wl, struct net_device *dev)
4966 {
4967         u32 max_retry = WL_CHANNEL_SYNC_RETRY;
4968
4969         if (dev == NULL)
4970                 return -1;
4971
4972         WL_DBG((" enter ) \n"));
4973
4974         wl_set_drv_status(wl, FINDING_COMMON_CHANNEL, dev);
4975         wl->afx_hdl->is_active = TRUE;
4976
4977         /* Loop to wait until we find a peer's channel or the
4978          * pending action frame tx is cancelled.
4979          */
4980         while ((wl->afx_hdl->retry < max_retry) &&
4981                 (wl->afx_hdl->peer_chan == WL_INVALID)) {
4982                 wl->afx_hdl->is_listen = FALSE;
4983                 wl_set_drv_status(wl, SCANNING, dev);
4984                 WL_DBG(("Scheduling the action frame for sending.. retry %d\n",
4985                         wl->afx_hdl->retry));
4986                 /* search peer on peer's listen channel */
4987                 schedule_work(&wl->afx_hdl->work);
4988                 wait_for_completion_timeout(&wl->act_frm_scan,
4989                         msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
4990
4991                 if ((wl->afx_hdl->peer_chan != WL_INVALID) ||
4992                         !(wl_get_drv_status(wl, FINDING_COMMON_CHANNEL, dev)))
4993                         break;
4994
4995                 if (wl->afx_hdl->my_listen_chan) {
4996                         WL_DBG(("Scheduling Listen peer in my listen channel = %d\n",
4997                                 wl->afx_hdl->my_listen_chan));
4998                         /* listen on my listen channel */
4999                         wl->afx_hdl->is_listen = TRUE;
5000                         schedule_work(&wl->afx_hdl->work);
5001                         wait_for_completion_timeout(&wl->act_frm_scan,
5002                                 msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
5003                 }
5004                 if ((wl->afx_hdl->peer_chan != WL_INVALID) ||
5005                         !(wl_get_drv_status(wl, FINDING_COMMON_CHANNEL, dev)))
5006                         break;
5007
5008                 wl->afx_hdl->retry++;
5009
5010                 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl);
5011         }
5012
5013         wl->afx_hdl->is_active = FALSE;
5014
5015         wl_clr_drv_status(wl, SCANNING, dev);
5016         wl_clr_drv_status(wl, FINDING_COMMON_CHANNEL, dev);
5017
5018         return (wl->afx_hdl->peer_chan);
5019 }
5020
5021 struct p2p_config_af_params {
5022         s32 max_tx_retry;       /* max tx retry count if tx no ack */
5023         /* To make sure to send successfully action frame, we have to turn off mpc
5024          * 0: off, 1: on,  (-1): do nothing
5025          */
5026         s32 mpc_onoff;
5027 #ifdef WL_CFG80211_SYNC_GON
5028         bool extra_listen;
5029 #endif
5030         bool search_channel;    /* 1: search peer's channel to send af */
5031 };
5032
5033 static s32
5034 wl_cfg80211_config_p2p_pub_af_tx(struct wiphy *wiphy,
5035         wl_action_frame_t *action_frame, wl_af_params_t *af_params,
5036         struct p2p_config_af_params *config_af_params)
5037 {
5038         s32 err = BCME_OK;
5039         struct wl_priv *wl = wiphy_priv(wiphy);
5040         wifi_p2p_pub_act_frame_t *act_frm =
5041                 (wifi_p2p_pub_act_frame_t *) (action_frame->data);
5042
5043         /* initialize default value */
5044 #ifdef WL_CFG80211_SYNC_GON
5045         config_af_params->extra_listen = true;
5046 #endif
5047         config_af_params->search_channel = false;
5048         config_af_params->max_tx_retry = WL_AF_TX_MAX_RETRY;
5049         config_af_params->mpc_onoff = -1;
5050         wl->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
5051
5052         switch (act_frm->subtype) {
5053         case P2P_PAF_GON_REQ: {
5054                 WL_DBG(("P2P: GO_NEG_PHASE status set \n"));
5055                 wl_set_p2p_status(wl, GO_NEG_PHASE);
5056
5057                 config_af_params->mpc_onoff = 0;
5058                 config_af_params->search_channel = true;
5059                 wl->next_af_subtype = act_frm->subtype + 1;
5060
5061                 /* increase dwell time to wait for RESP frame */
5062                 af_params->dwell_time = WL_MED_DWELL_TIME;
5063
5064                 break;
5065         }
5066         case P2P_PAF_GON_RSP: {
5067                 wl->next_af_subtype = act_frm->subtype + 1;
5068                 /* increase dwell time to wait for CONF frame */
5069                 af_params->dwell_time = WL_MED_DWELL_TIME + 100;
5070                 break;
5071         }
5072         case P2P_PAF_GON_CONF: {
5073                 /* If we reached till GO Neg confirmation reset the filter */
5074                 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
5075                 wl_clr_p2p_status(wl, GO_NEG_PHASE);
5076
5077                 /* turn on mpc again if go nego is done */
5078                 config_af_params->mpc_onoff = 1;
5079
5080                 /* minimize dwell time */
5081                 af_params->dwell_time = WL_MIN_DWELL_TIME;
5082
5083 #ifdef WL_CFG80211_SYNC_GON
5084                 config_af_params->extra_listen = false;
5085 #endif /* WL_CFG80211_SYNC_GON */
5086                 break;
5087         }
5088         case P2P_PAF_INVITE_REQ: {
5089                 config_af_params->search_channel = true;
5090                 wl->next_af_subtype = act_frm->subtype + 1;
5091
5092                 /* increase dwell time */
5093                 af_params->dwell_time = WL_MED_DWELL_TIME;
5094                 break;
5095         }
5096         case P2P_PAF_INVITE_RSP:
5097                 /* minimize dwell time */
5098                 af_params->dwell_time = WL_MIN_DWELL_TIME;
5099 #ifdef WL_CFG80211_SYNC_GON
5100                 config_af_params->extra_listen = false;
5101 #endif /* WL_CFG80211_SYNC_GON */
5102                 break;
5103         case P2P_PAF_DEVDIS_REQ: {
5104                 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
5105                         action_frame->len)) {
5106                         config_af_params->search_channel = true;
5107                 }
5108
5109                 wl->next_af_subtype = act_frm->subtype + 1;
5110                 /* maximize dwell time to wait for RESP frame */
5111                 af_params->dwell_time = WL_LONG_DWELL_TIME;
5112                 break;
5113         }
5114         case P2P_PAF_DEVDIS_RSP:
5115                 /* minimize dwell time */
5116                 af_params->dwell_time = WL_MIN_DWELL_TIME;
5117 #ifdef WL_CFG80211_SYNC_GON
5118                 config_af_params->extra_listen = false;
5119 #endif /* WL_CFG80211_SYNC_GON */
5120                 break;
5121         case P2P_PAF_PROVDIS_REQ: {
5122                 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
5123                         action_frame->len)) {
5124                         config_af_params->search_channel = true;
5125                 }
5126
5127                 config_af_params->mpc_onoff = 0;
5128                 wl->next_af_subtype = act_frm->subtype + 1;
5129                 /* increase dwell time to wait for RESP frame */
5130                 af_params->dwell_time = WL_MED_DWELL_TIME;
5131                 break;
5132         }
5133         case P2P_PAF_PROVDIS_RSP: {
5134                 wl->next_af_subtype = P2P_PAF_GON_REQ;
5135                 af_params->dwell_time = WL_MIN_DWELL_TIME;
5136 #ifdef WL_CFG80211_SYNC_GON
5137                 config_af_params->extra_listen = false;
5138 #endif /* WL_CFG80211_SYNC_GON */
5139                 break;
5140         }
5141         default:
5142                 WL_DBG(("Unknown p2p pub act frame subtype: %d\n",
5143                         act_frm->subtype));
5144                 err = BCME_BADARG;
5145         }
5146         return err;
5147 }
5148
5149
5150 static bool
5151 wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev,
5152         bcm_struct_cfgdev *cfgdev, wl_af_params_t *af_params,
5153         wl_action_frame_t *action_frame, u16 action_frame_len, s32 bssidx)
5154 {
5155 #ifdef WL11U
5156         struct net_device *ndev = NULL;
5157 #endif /* WL11U */
5158         struct wl_priv *wl = wiphy_priv(wiphy);
5159         bool ack = false;
5160         u8 category, action;
5161         s32 tx_retry;
5162         struct p2p_config_af_params config_af_params;
5163 #ifdef VSDB
5164         ulong off_chan_started_jiffies = 0;
5165 #endif
5166         dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
5167
5168 #ifdef WL11U
5169 #if defined(WL_CFG80211_P2P_DEV_IF)
5170         ndev = dev;
5171 #else
5172         ndev = ndev_to_cfgdev(cfgdev);
5173 #endif /* WL_CFG80211_P2P_DEV_IF */
5174 #endif /* WL11U */
5175
5176         category = action_frame->data[DOT11_ACTION_CAT_OFF];
5177         action = action_frame->data[DOT11_ACTION_ACT_OFF];
5178
5179         /* initialize variables */
5180         tx_retry = 0;
5181         wl->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
5182         config_af_params.max_tx_retry = WL_AF_TX_MAX_RETRY;
5183         config_af_params.mpc_onoff = -1;
5184         config_af_params.search_channel = false;
5185 #ifdef WL_CFG80211_SYNC_GON
5186         config_af_params.extra_listen = false;
5187 #endif
5188
5189         /* config parameters */
5190         /* Public Action Frame Process - DOT11_ACTION_CAT_PUBLIC */
5191         if (category == DOT11_ACTION_CAT_PUBLIC) {
5192                 if ((action == P2P_PUB_AF_ACTION) &&
5193                         (action_frame_len >= sizeof(wifi_p2p_pub_act_frame_t))) {
5194                         /* p2p public action frame process */
5195                         if (BCME_OK != wl_cfg80211_config_p2p_pub_af_tx(wiphy,
5196                                 action_frame, af_params, &config_af_params)) {
5197                                 WL_DBG(("Unknown subtype.\n"));
5198                         }
5199
5200                 } else if (action_frame_len >= sizeof(wifi_p2psd_gas_pub_act_frame_t)) {
5201                         /* service discovery process */
5202                         if (action == P2PSD_ACTION_ID_GAS_IREQ ||
5203                                 action == P2PSD_ACTION_ID_GAS_CREQ) {
5204                                 /* configure service discovery query frame */
5205
5206                                 config_af_params.search_channel = true;
5207
5208                                 /* save next af suptype to cancel remained dwell time */
5209                                 wl->next_af_subtype = action + 1;
5210
5211                                 af_params->dwell_time = WL_MED_DWELL_TIME;
5212                         } else if (action == P2PSD_ACTION_ID_GAS_IRESP ||
5213                                 action == P2PSD_ACTION_ID_GAS_CRESP) {
5214                                 /* configure service discovery response frame */
5215                                 af_params->dwell_time = WL_MIN_DWELL_TIME;
5216                         } else {
5217                                 WL_DBG(("Unknown action type: %d\n", action));
5218                         }
5219                 } else {
5220                         WL_DBG(("Unknown Frame: category 0x%x, action 0x%x, length %d\n",
5221                                 category, action, action_frame_len));
5222                 }
5223         } else if (category == P2P_AF_CATEGORY) {
5224                 /* do not configure anything. it will be sent with a default configuration */
5225         } else {
5226                 WL_DBG(("Unknown Frame: category 0x%x, action 0x%x\n",
5227                         category, action));
5228                 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
5229                         wl_clr_drv_status(wl, SENDING_ACT_FRM, dev);
5230                         return false;
5231                 }
5232         }
5233
5234         /* To make sure to send successfully action frame, we have to turn off mpc */
5235         if (config_af_params.mpc_onoff == 0) {
5236                 wldev_iovar_setint(dev, "mpc", 0);
5237         }
5238
5239         /* validate channel and p2p ies */
5240         if (config_af_params.search_channel && IS_P2P_SOCIAL(af_params->channel) &&
5241                 wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len) {
5242                 config_af_params.search_channel = true;
5243         } else {
5244                 config_af_params.search_channel = false;
5245         }
5246
5247 #ifdef WL11U
5248         if (ndev == wl_to_prmry_ndev(wl))
5249                 config_af_params.search_channel = false;
5250 #endif /* WL11U */
5251
5252 #ifdef VSDB
5253         /* if connecting on primary iface, sleep for a while before sending af tx for VSDB */
5254         if (wl_get_drv_status(wl, CONNECTING, wl_to_prmry_ndev(wl))) {
5255                 OSL_SLEEP(50);
5256         }
5257 #endif
5258
5259         /* if scan is ongoing, abort current scan. */
5260         if (wl_get_drv_status_all(wl, SCANNING)) {
5261                 wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true);
5262         }
5263
5264         /* set status and destination address before sending af */
5265         if (wl->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
5266                 /* set this status to cancel the remained dwell time in rx process */
5267                 wl_set_drv_status(wl, WAITING_NEXT_ACT_FRM, dev);
5268         }
5269         wl_set_drv_status(wl, SENDING_ACT_FRM, dev);
5270         memcpy(wl->afx_hdl->tx_dst_addr.octet,
5271                 af_params->action_frame.da.octet,
5272                 sizeof(wl->afx_hdl->tx_dst_addr.octet));
5273
5274         /* save af_params for rx process */
5275         wl->afx_hdl->pending_tx_act_frm = af_params;
5276
5277         /* search peer's channel */
5278         if (config_af_params.search_channel) {
5279                 /* initialize afx_hdl */
5280                 if (wl_cfgp2p_find_idx(wl, dev, &wl->afx_hdl->bssidx) != BCME_OK) {
5281                         WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
5282                         goto exit;
5283                 }
5284                 wl->afx_hdl->dev = dev;
5285                 wl->afx_hdl->retry = 0;
5286                 wl->afx_hdl->peer_chan = WL_INVALID;
5287
5288                 if (wl_cfg80211_af_searching_channel(wl, dev) == WL_INVALID) {
5289                         WL_ERR(("couldn't find peer's channel.\n"));
5290                         wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len,
5291                                 af_params->channel);
5292                         goto exit;
5293                 }
5294
5295                 wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
5296                 /*
5297                  * Abort scan even for VSDB scenarios. Scan gets aborted in firmware
5298                  * but after the check of piggyback algorithm.
5299                  * To take care of current piggback algo, lets abort the scan here itself.
5300                  */
5301                 wl_notify_escan_complete(wl, dev, true, true);
5302                 /* Suspend P2P discovery's search-listen to prevent it from
5303                  * starting a scan or changing the channel.
5304                  */
5305                 wl_cfgp2p_discover_enable_search(wl, false);
5306
5307                 /* update channel */
5308                 af_params->channel = wl->afx_hdl->peer_chan;
5309         }
5310
5311 #ifdef VSDB
5312         off_chan_started_jiffies = jiffies;
5313 #endif /* VSDB */
5314
5315         wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len, af_params->channel);
5316
5317         /* Now send a tx action frame */
5318         ack = wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx) ? false : true;
5319
5320         /* if failed, retry it. tx_retry_max value is configure by .... */
5321         while ((ack == false) && (tx_retry++ < config_af_params.max_tx_retry)) {
5322 #ifdef VSDB
5323                 if (af_params->channel) {
5324                         if (jiffies_to_msecs(jiffies - off_chan_started_jiffies) >
5325                                 OFF_CHAN_TIME_THRESHOLD_MS) {
5326                                 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl);
5327                                 off_chan_started_jiffies = jiffies;
5328                         } else
5329                                 OSL_SLEEP(AF_RETRY_DELAY_TIME);
5330                 }
5331 #endif /* VSDB */
5332                 ack = wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx) ?
5333                         false : true;
5334         }
5335         if (ack == false) {
5336                 WL_ERR(("Failed to send Action Frame(retry %d)\n", tx_retry));
5337         }
5338 exit:
5339         /* Clear SENDING_ACT_FRM after all sending af is done */
5340         wl_clr_drv_status(wl, SENDING_ACT_FRM, dev);
5341
5342 #ifdef WL_CFG80211_SYNC_GON
5343         /* WAR: sometimes dongle does not keep the dwell time of 'actframe'.
5344          * if we coundn't get the next action response frame and dongle does not keep
5345          * the dwell time, go to listen state again to get next action response frame.
5346          */
5347         if (ack && config_af_params.extra_listen &&
5348                 wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM) &&
5349                 wl->af_sent_channel == wl->afx_hdl->my_listen_chan) {
5350                 s32 extar_listen_time;
5351
5352                 extar_listen_time = af_params->dwell_time -
5353                         jiffies_to_msecs(jiffies - wl->af_tx_sent_jiffies);
5354
5355                 if (extar_listen_time > 50) {
5356                         wl_set_drv_status(wl, WAITING_NEXT_ACT_FRM_LISTEN, dev);
5357                         WL_DBG(("Wait more time! actual af time:%d,"
5358                                 "calculated extar listen:%d\n",
5359                                 af_params->dwell_time, extar_listen_time));
5360                         if (wl_cfgp2p_discover_listen(wl, wl->af_sent_channel,
5361                                 extar_listen_time + 100) == BCME_OK) {
5362                                 wait_for_completion_timeout(&wl->wait_next_af,
5363                                         msecs_to_jiffies(extar_listen_time + 100 + 300));
5364                         }
5365                         wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM_LISTEN, dev);
5366                 }
5367         }
5368 #endif /* WL_CFG80211_SYNC_GON */
5369         wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, dev);
5370
5371         if (wl->afx_hdl->pending_tx_act_frm)
5372                 wl->afx_hdl->pending_tx_act_frm = NULL;
5373
5374         WL_INFO(("-- sending Action Frame is %s, listen chan: %d\n",
5375                 (ack) ? "Succeeded!!":"Failed!!", wl->afx_hdl->my_listen_chan));
5376
5377
5378         /* if all done, turn mpc on again */
5379         if (config_af_params.mpc_onoff == 1) {
5380                 wldev_iovar_setint(dev, "mpc", 1);
5381         }
5382
5383         return ack;
5384 }
5385
5386 #define MAX_NUM_OF_ASSOCIATED_DEV       64
5387 static s32
5388 #if defined(WL_CFG80211_P2P_DEV_IF)
5389 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
5390         struct ieee80211_channel *channel, bool offchan,
5391         unsigned int wait, const u8* buf, size_t len, bool no_cck,
5392         bool dont_wait_for_ack, u64 *cookie)
5393 #else
5394 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
5395         struct ieee80211_channel *channel, bool offchan,
5396         enum nl80211_channel_type channel_type,
5397         bool channel_type_valid, unsigned int wait,
5398         const u8* buf, size_t len,
5399 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS)
5400         bool no_cck,
5401 #endif
5402 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || defined(WL_COMPAT_WIRELESS)
5403         bool dont_wait_for_ack,
5404 #endif
5405         u64 *cookie)
5406 #endif /* WL_CFG80211_P2P_DEV_IF */
5407 {
5408         wl_action_frame_t *action_frame;
5409         wl_af_params_t *af_params;
5410         scb_val_t scb_val;
5411         const struct ieee80211_mgmt *mgmt;
5412         struct wl_priv *wl = wiphy_priv(wiphy);
5413         struct net_device *dev = NULL;
5414         s32 err = BCME_OK;
5415         s32 bssidx = 0;
5416         u32 id;
5417         bool ack = false;
5418         s8 eabuf[ETHER_ADDR_STR_LEN];
5419
5420         WL_DBG(("Enter \n"));
5421
5422         dev = cfgdev_to_wlc_ndev(cfgdev, wl);
5423
5424         /* find bssidx based on dev */
5425         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
5426                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
5427                 return BCME_ERROR;
5428         }
5429         if (p2p_is_on(wl)) {
5430                 /* Suspend P2P discovery search-listen to prevent it from changing the
5431                  * channel.
5432                  */
5433                 if ((err = wl_cfgp2p_discover_enable_search(wl, false)) < 0) {
5434                         WL_ERR(("Can not disable discovery mode\n"));
5435                         return -EFAULT;
5436                 }
5437         }
5438         *cookie = 0;
5439         id = wl->send_action_id++;
5440         if (id == 0)
5441                 id = wl->send_action_id++;
5442         *cookie = id;
5443         mgmt = (const struct ieee80211_mgmt *)buf;
5444         if (ieee80211_is_mgmt(mgmt->frame_control)) {
5445                 if (ieee80211_is_probe_resp(mgmt->frame_control)) {
5446                         s32 ie_offset =  DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
5447                         s32 ie_len = len - ie_offset;
5448                         if (dev == wl_to_prmry_ndev(wl))
5449                                 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
5450                                 wl_cfgp2p_set_management_ie(wl, dev, bssidx,
5451                                 VNDR_IE_PRBRSP_FLAG, (u8 *)(buf + ie_offset), ie_len);
5452                         cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
5453                         goto exit;
5454                 } else if (ieee80211_is_disassoc(mgmt->frame_control) ||
5455                         ieee80211_is_deauth(mgmt->frame_control)) {
5456                         char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
5457                                 sizeof(struct ether_addr) + sizeof(uint)] = {0};
5458                         int num_associated = 0;
5459                         struct maclist *assoc_maclist = (struct maclist *)mac_buf;
5460                         if (!bcmp((const uint8 *)BSSID_BROADCAST,
5461                                 (const struct ether_addr *)mgmt->da, ETHER_ADDR_LEN)) {
5462                                 assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
5463                                 err = wldev_ioctl(dev, WLC_GET_ASSOCLIST,
5464                                         assoc_maclist, sizeof(mac_buf), false);
5465                                 if (err < 0)
5466                                         WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
5467                                 else
5468                                         num_associated = assoc_maclist->count;
5469                         }
5470                         memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN);
5471                         scb_val.val = mgmt->u.disassoc.reason_code;
5472                         err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
5473                                 sizeof(scb_val_t), true);
5474                         if (err < 0)
5475                                 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON error %d\n", err));
5476                         WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
5477                                 bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf),
5478                                 scb_val.val));
5479
5480                         if (num_associated > 0 && ETHER_ISBCAST(mgmt->da))
5481                                 wl_delay(400);
5482
5483                         cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
5484                         goto exit;
5485
5486                 } else if (ieee80211_is_action(mgmt->frame_control)) {
5487                         /* Abort the dwell time of any previous off-channel
5488                         * action frame that may be still in effect.  Sending
5489                         * off-channel action frames relies on the driver's
5490                         * scan engine.  If a previous off-channel action frame
5491                         * tx is still in progress (including the dwell time),
5492                         * then this new action frame will not be sent out.
5493                         */
5494 /* Do not abort scan for VSDB. Scan will be aborted in firmware if necessary.
5495  * And previous off-channel action frame must be ended before new af tx.
5496  */
5497 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5498                         wl_notify_escan_complete(wl, dev, true, true);
5499 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5500                 }
5501
5502         } else {
5503                 WL_ERR(("Driver only allows MGMT packet type\n"));
5504                 goto exit;
5505         }
5506
5507         af_params = (wl_af_params_t *) kzalloc(WL_WIFI_AF_PARAMS_SIZE, GFP_KERNEL);
5508
5509         if (af_params == NULL)
5510         {
5511                 WL_ERR(("unable to allocate frame\n"));
5512                 return -ENOMEM;
5513         }
5514
5515         action_frame = &af_params->action_frame;
5516
5517         /* Add the packet Id */
5518         action_frame->packetId = *cookie;
5519         WL_DBG(("action frame %d\n", action_frame->packetId));
5520         /* Add BSSID */
5521         memcpy(&action_frame->da, &mgmt->da[0], ETHER_ADDR_LEN);
5522         memcpy(&af_params->BSSID, &mgmt->bssid[0], ETHER_ADDR_LEN);
5523
5524         /* Add the length exepted for 802.11 header  */
5525         action_frame->len = len - DOT11_MGMT_HDR_LEN;
5526         WL_DBG(("action_frame->len: %d\n", action_frame->len));
5527
5528         /* Add the channel */
5529         af_params->channel =
5530                 ieee80211_frequency_to_channel(channel->center_freq);
5531
5532         /* Save listen_chan for searching common channel */
5533         wl->afx_hdl->peer_listen_chan = af_params->channel;
5534         WL_DBG(("channel from upper layer %d\n", wl->afx_hdl->peer_listen_chan));
5535
5536         /* Add the default dwell time
5537          * Dwell time to stay off-channel to wait for a response action frame
5538          * after transmitting an GO Negotiation action frame
5539          */
5540         af_params->dwell_time = WL_DWELL_TIME;
5541
5542         memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len);
5543
5544         ack = wl_cfg80211_send_action_frame(wiphy, dev, cfgdev, af_params,
5545                 action_frame, action_frame->len, bssidx);
5546         cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, ack, GFP_KERNEL);
5547
5548         kfree(af_params);
5549 exit:
5550         return err;
5551 }
5552
5553
5554 static void
5555 wl_cfg80211_mgmt_frame_register(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
5556         u16 frame_type, bool reg)
5557 {
5558
5559         WL_DBG(("frame_type: %x, reg: %d\n", frame_type, reg));
5560
5561         if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
5562                 return;
5563
5564         return;
5565 }
5566
5567
5568 static s32
5569 wl_cfg80211_change_bss(struct wiphy *wiphy,
5570         struct net_device *dev,
5571         struct bss_parameters *params)
5572 {
5573         if (params->use_cts_prot >= 0) {
5574         }
5575
5576         if (params->use_short_preamble >= 0) {
5577         }
5578
5579         if (params->use_short_slot_time >= 0) {
5580         }
5581
5582         if (params->basic_rates) {
5583         }
5584
5585         if (params->ap_isolate >= 0) {
5586         }
5587
5588         if (params->ht_opmode >= 0) {
5589         }
5590
5591         return 0;
5592 }
5593
5594 static s32
5595 wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
5596         struct ieee80211_channel *chan,
5597         enum nl80211_channel_type channel_type)
5598 {
5599         s32 _chan;
5600         chanspec_t chspec = 0;
5601         chanspec_t fw_chspec = 0;
5602         u32 bw = WL_CHANSPEC_BW_20;
5603
5604         s32 err = BCME_OK;
5605         s32 bw_cap = 0;
5606         struct {
5607                 u32 band;
5608                 u32 bw_cap;
5609         } param = {0, 0};
5610         struct wl_priv *wl = wiphy_priv(wiphy);
5611
5612         dev = ndev_to_wlc_ndev(dev, wl);
5613         _chan = ieee80211_frequency_to_channel(chan->center_freq);
5614         printk("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
5615                 dev->ifindex, channel_type, _chan);
5616
5617
5618         if (chan->band == IEEE80211_BAND_5GHZ) {
5619                 param.band = WLC_BAND_5G;
5620                 err = wldev_iovar_getbuf(dev, "bw_cap", &param, sizeof(param),
5621                         wl->ioctl_buf, WLC_IOCTL_SMLEN, &wl->ioctl_buf_sync);
5622                 if (err) {
5623                         if (err != BCME_UNSUPPORTED) {
5624                                 WL_ERR(("bw_cap failed, %d\n", err));
5625                                 return err;
5626                         } else {
5627                                 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
5628                                 if (err) {
5629                                         WL_ERR(("error get mimo_bw_cap (%d)\n", err));
5630                                 }
5631                                 if (bw_cap != WLC_N_BW_20ALL)
5632                                         bw = WL_CHANSPEC_BW_40;
5633                         }
5634                 } else {
5635                         if (WL_BW_CAP_80MHZ(wl->ioctl_buf[0]))
5636                                 bw = WL_CHANSPEC_BW_80;
5637                         else if (WL_BW_CAP_40MHZ(wl->ioctl_buf[0]))
5638                                 bw = WL_CHANSPEC_BW_40;
5639                         else
5640                                 bw = WL_CHANSPEC_BW_20;
5641
5642                 }
5643
5644         } else if (chan->band == IEEE80211_BAND_2GHZ)
5645                 bw = WL_CHANSPEC_BW_20;
5646 set_channel:
5647         chspec = wf_channel2chspec(_chan, bw);
5648         if (wf_chspec_valid(chspec)) {
5649                 fw_chspec = wl_chspec_host_to_driver(chspec);
5650                 if (fw_chspec != INVCHANSPEC) {
5651                         if ((err = wldev_iovar_setint(dev, "chanspec",
5652                                 fw_chspec)) == BCME_BADCHAN) {
5653                                 if (bw == WL_CHANSPEC_BW_80)
5654                                         goto change_bw;
5655                                 err = wldev_ioctl(dev, WLC_SET_CHANNEL,
5656                                         &_chan, sizeof(_chan), true);
5657                                 if (err < 0) {
5658                                         WL_ERR(("WLC_SET_CHANNEL error %d"
5659                                         "chip may not be supporting this channel\n", err));
5660                                 }
5661                         } else if (err) {
5662                                 WL_ERR(("failed to set chanspec error %d\n", err));
5663                         }
5664                 } else {
5665                         WL_ERR(("failed to convert host chanspec to fw chanspec\n"));
5666                         err = BCME_ERROR;
5667                 }
5668         } else {
5669 change_bw:
5670                 if (bw == WL_CHANSPEC_BW_80)
5671                         bw = WL_CHANSPEC_BW_40;
5672                 else if (bw == WL_CHANSPEC_BW_40)
5673                         bw = WL_CHANSPEC_BW_20;
5674                 else
5675                         bw = 0;
5676                 if (bw)
5677                         goto set_channel;
5678                 WL_ERR(("Invalid chanspec 0x%x\n", chspec));
5679                 err = BCME_ERROR;
5680         }
5681         return err;
5682 }
5683
5684 static s32
5685 wl_validate_opensecurity(struct net_device *dev, s32 bssidx)
5686 {
5687         s32 err = BCME_OK;
5688
5689         /* set auth */
5690         err = wldev_iovar_setint_bsscfg(dev, "auth", 0, bssidx);
5691         if (err < 0) {
5692                 WL_ERR(("auth error %d\n", err));
5693                 return BCME_ERROR;
5694         }
5695         /* set wsec */
5696         err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
5697         if (err < 0) {
5698                 WL_ERR(("wsec error %d\n", err));
5699                 return BCME_ERROR;
5700         }
5701         /* set upper-layer auth */
5702         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", WPA_AUTH_NONE, bssidx);
5703         if (err < 0) {
5704                 WL_ERR(("wpa_auth error %d\n", err));
5705                 return BCME_ERROR;
5706         }
5707
5708         return 0;
5709 }
5710
5711 static s32
5712 wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
5713 {
5714         s32 len = 0;
5715         s32 err = BCME_OK;
5716         u16 auth = 0; /* d11 open authentication */
5717         u32 wsec;
5718         u32 pval = 0;
5719         u32 gval = 0;
5720         u32 wpa_auth = 0;
5721         wpa_suite_mcast_t *mcast;
5722         wpa_suite_ucast_t *ucast;
5723         wpa_suite_auth_key_mgmt_t *mgmt;
5724
5725         u16 suite_count;
5726         u8 rsn_cap[2];
5727         u32 wme_bss_disable;
5728
5729         if (wpa2ie == NULL)
5730                 goto exit;
5731
5732         WL_DBG(("Enter \n"));
5733         len =  wpa2ie->len;
5734         /* check the mcast cipher */
5735         mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
5736         switch (mcast->type) {
5737                 case WPA_CIPHER_NONE:
5738                         gval = 0;
5739                         break;
5740                 case WPA_CIPHER_WEP_40:
5741                 case WPA_CIPHER_WEP_104:
5742                         gval = WEP_ENABLED;
5743                         break;
5744                 case WPA_CIPHER_TKIP:
5745                         gval = TKIP_ENABLED;
5746                         break;
5747                 case WPA_CIPHER_AES_CCM:
5748                         gval = AES_ENABLED;
5749                         break;
5750 #ifdef BCMWAPI_WPI
5751                 case WAPI_CIPHER_SMS4:
5752                         gval = SMS4_ENABLED;
5753                         break;
5754 #endif
5755                 default:
5756                         WL_ERR(("No Security Info\n"));
5757                         break;
5758         }
5759         if ((len -= WPA_SUITE_LEN) <= 0)
5760                 return BCME_BADLEN;
5761
5762         /* check the unicast cipher */
5763         ucast = (wpa_suite_ucast_t *)&mcast[1];
5764         suite_count = ltoh16_ua(&ucast->count);
5765         switch (ucast->list[0].type) {
5766                 case WPA_CIPHER_NONE:
5767                         pval = 0;
5768                         break;
5769                 case WPA_CIPHER_WEP_40:
5770                 case WPA_CIPHER_WEP_104:
5771                         pval = WEP_ENABLED;
5772                         break;
5773                 case WPA_CIPHER_TKIP:
5774                         pval = TKIP_ENABLED;
5775                         break;
5776                 case WPA_CIPHER_AES_CCM:
5777                         pval = AES_ENABLED;
5778                         break;
5779 #ifdef BCMWAPI_WPI
5780                 case WAPI_CIPHER_SMS4:
5781                         pval = SMS4_ENABLED;
5782                         break;
5783 #endif
5784                 default:
5785                         WL_ERR(("No Security Info\n"));
5786         }
5787         if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
5788                 return BCME_BADLEN;
5789
5790         /* FOR WPS , set SEC_OW_ENABLED */
5791         wsec = (pval | gval | SES_OW_ENABLED);
5792         /* check the AKM */
5793         mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
5794         suite_count = ltoh16_ua(&mgmt->count);
5795         switch (mgmt->list[0].type) {
5796                 case RSN_AKM_NONE:
5797                         wpa_auth = WPA_AUTH_NONE;
5798                         break;
5799                 case RSN_AKM_UNSPECIFIED:
5800                         wpa_auth = WPA2_AUTH_UNSPECIFIED;
5801                         break;
5802                 case RSN_AKM_PSK:
5803                         wpa_auth = WPA2_AUTH_PSK;
5804                         break;
5805                 default:
5806                         WL_ERR(("No Key Mgmt Info\n"));
5807         }
5808
5809         if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
5810                 rsn_cap[0] = *(u8 *)&mgmt->list[suite_count];
5811                 rsn_cap[1] = *((u8 *)&mgmt->list[suite_count] + 1);
5812
5813                 if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
5814                         wme_bss_disable = 0;
5815                 } else {
5816                         wme_bss_disable = 1;
5817                 }
5818
5819                 /* set wme_bss_disable to sync RSN Capabilities */
5820                 err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
5821                 if (err < 0) {
5822                         WL_ERR(("wme_bss_disable error %d\n", err));
5823                         return BCME_ERROR;
5824                 }
5825         } else {
5826                 WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
5827         }
5828
5829         /* set auth */
5830         err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
5831         if (err < 0) {
5832                 WL_ERR(("auth error %d\n", err));
5833                 return BCME_ERROR;
5834         }
5835         /* set wsec */
5836         err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
5837         if (err < 0) {
5838                 WL_ERR(("wsec error %d\n", err));
5839                 return BCME_ERROR;
5840         }
5841         /* set upper-layer auth */
5842         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
5843         if (err < 0) {
5844                 WL_ERR(("wpa_auth error %d\n", err));
5845                 return BCME_ERROR;
5846         }
5847 exit:
5848         return 0;
5849 }
5850
5851 static s32
5852 wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx)
5853 {
5854         wpa_suite_mcast_t *mcast;
5855         wpa_suite_ucast_t *ucast;
5856         wpa_suite_auth_key_mgmt_t *mgmt;
5857         u16 auth = 0; /* d11 open authentication */
5858         u16 count;
5859         s32 err = BCME_OK;
5860         s32 len = 0;
5861         u32 i;
5862         u32 wsec;
5863         u32 pval = 0;
5864         u32 gval = 0;
5865         u32 wpa_auth = 0;
5866         u32 tmp = 0;
5867
5868         if (wpaie == NULL)
5869                 goto exit;
5870         WL_DBG(("Enter \n"));
5871         len = wpaie->length;    /* value length */
5872         len -= WPA_IE_TAG_FIXED_LEN;
5873         /* check for multicast cipher suite */
5874         if (len < WPA_SUITE_LEN) {
5875                 WL_INFO(("no multicast cipher suite\n"));
5876                 goto exit;
5877         }
5878
5879         /* pick up multicast cipher */
5880         mcast = (wpa_suite_mcast_t *)&wpaie[1];
5881         len -= WPA_SUITE_LEN;
5882         if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
5883                 if (IS_WPA_CIPHER(mcast->type)) {
5884                         tmp = 0;
5885                         switch (mcast->type) {
5886                                 case WPA_CIPHER_NONE:
5887                                         tmp = 0;
5888                                         break;
5889                                 case WPA_CIPHER_WEP_40:
5890                                 case WPA_CIPHER_WEP_104:
5891                                         tmp = WEP_ENABLED;
5892                                         break;
5893                                 case WPA_CIPHER_TKIP:
5894                                         tmp = TKIP_ENABLED;
5895                                         break;
5896                                 case WPA_CIPHER_AES_CCM:
5897                                         tmp = AES_ENABLED;
5898                                         break;
5899                                 default:
5900                                         WL_ERR(("No Security Info\n"));
5901                         }
5902                         gval |= tmp;
5903                 }
5904         }
5905         /* Check for unicast suite(s) */
5906         if (len < WPA_IE_SUITE_COUNT_LEN) {
5907                 WL_INFO(("no unicast suite\n"));
5908                 goto exit;
5909         }
5910         /* walk thru unicast cipher list and pick up what we recognize */
5911         ucast = (wpa_suite_ucast_t *)&mcast[1];
5912         count = ltoh16_ua(&ucast->count);
5913         len -= WPA_IE_SUITE_COUNT_LEN;
5914         for (i = 0; i < count && len >= WPA_SUITE_LEN;
5915                 i++, len -= WPA_SUITE_LEN) {
5916                 if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
5917                         if (IS_WPA_CIPHER(ucast->list[i].type)) {
5918                                 tmp = 0;
5919                                 switch (ucast->list[i].type) {
5920                                         case WPA_CIPHER_NONE:
5921                                                 tmp = 0;
5922                                                 break;
5923                                         case WPA_CIPHER_WEP_40:
5924                                         case WPA_CIPHER_WEP_104:
5925                                                 tmp = WEP_ENABLED;
5926                                                 break;
5927                                         case WPA_CIPHER_TKIP:
5928                                                 tmp = TKIP_ENABLED;
5929                                                 break;
5930                                         case WPA_CIPHER_AES_CCM:
5931                                                 tmp = AES_ENABLED;
5932                                                 break;
5933                                         default:
5934                                                 WL_ERR(("No Security Info\n"));
5935                                 }
5936                                 pval |= tmp;
5937                         }
5938                 }
5939         }
5940         len -= (count - i) * WPA_SUITE_LEN;
5941         /* Check for auth key management suite(s) */
5942         if (len < WPA_IE_SUITE_COUNT_LEN) {
5943                 WL_INFO((" no auth key mgmt suite\n"));
5944                 goto exit;
5945         }
5946         /* walk thru auth management suite list and pick up what we recognize */
5947         mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
5948         count = ltoh16_ua(&mgmt->count);
5949         len -= WPA_IE_SUITE_COUNT_LEN;
5950         for (i = 0; i < count && len >= WPA_SUITE_LEN;
5951                 i++, len -= WPA_SUITE_LEN) {
5952                 if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
5953                         if (IS_WPA_AKM(mgmt->list[i].type)) {
5954                                 tmp = 0;
5955                                 switch (mgmt->list[i].type) {
5956                                         case RSN_AKM_NONE:
5957                                                 tmp = WPA_AUTH_NONE;
5958                                                 break;
5959                                         case RSN_AKM_UNSPECIFIED:
5960                                                 tmp = WPA_AUTH_UNSPECIFIED;
5961                                                 break;
5962                                         case RSN_AKM_PSK:
5963                                                 tmp = WPA_AUTH_PSK;
5964                                                 break;
5965                                         default:
5966                                                 WL_ERR(("No Key Mgmt Info\n"));
5967                                 }
5968                                 wpa_auth |= tmp;
5969                         }
5970                 }
5971
5972         }
5973         /* FOR WPS , set SEC_OW_ENABLED */
5974         wsec = (pval | gval | SES_OW_ENABLED);
5975         /* set auth */
5976         err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
5977         if (err < 0) {
5978                 WL_ERR(("auth error %d\n", err));
5979                 return BCME_ERROR;
5980         }
5981         /* set wsec */
5982         err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
5983         if (err < 0) {
5984                 WL_ERR(("wsec error %d\n", err));
5985                 return BCME_ERROR;
5986         }
5987         /* set upper-layer auth */
5988         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
5989         if (err < 0) {
5990                 WL_ERR(("wpa_auth error %d\n", err));
5991                 return BCME_ERROR;
5992         }
5993 exit:
5994         return 0;
5995 }
5996
5997 static s32
5998 wl_cfg80211_bcn_validate_sec(
5999         struct net_device *dev,
6000         struct parsed_ies *ies,
6001         u32 dev_role,
6002         s32 bssidx)
6003 {
6004         struct wl_priv *wl = wlcfg_drv_priv;
6005
6006         if (dev_role == NL80211_IFTYPE_P2P_GO && (ies->wpa2_ie)) {
6007                 /* For P2P GO, the sec type is WPA2-PSK */
6008                 WL_DBG(("P2P GO: validating wpa2_ie"));
6009                 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0)
6010                         return BCME_ERROR;
6011
6012         } else if (dev_role == NL80211_IFTYPE_AP) {
6013
6014                 WL_DBG(("SoftAP: validating security"));
6015                 /* If wpa2_ie or wpa_ie is present validate it */
6016                 if ((ies->wpa2_ie || ies->wpa_ie) &&
6017                         ((wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0 ||
6018                         wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0))) {
6019                         wl->ap_info->security_mode = false;
6020                         return BCME_ERROR;
6021                 }
6022
6023                 wl->ap_info->security_mode = true;
6024                 if (wl->ap_info->rsn_ie) {
6025                         kfree(wl->ap_info->rsn_ie);
6026                         wl->ap_info->rsn_ie = NULL;
6027                 }
6028                 if (wl->ap_info->wpa_ie) {
6029                         kfree(wl->ap_info->wpa_ie);
6030                         wl->ap_info->wpa_ie = NULL;
6031                 }
6032                 if (wl->ap_info->wps_ie) {
6033                         kfree(wl->ap_info->wps_ie);
6034                         wl->ap_info->wps_ie = NULL;
6035                 }
6036                 if (ies->wpa_ie != NULL) {
6037                         /* WPAIE */
6038                         wl->ap_info->rsn_ie = NULL;
6039                         wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie,
6040                                 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
6041                                 GFP_KERNEL);
6042                 } else if (ies->wpa2_ie != NULL) {
6043                         /* RSNIE */
6044                         wl->ap_info->wpa_ie = NULL;
6045                         wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie,
6046                                 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
6047                                 GFP_KERNEL);
6048                 }
6049
6050                 if (!ies->wpa2_ie && !ies->wpa_ie) {
6051                         wl_validate_opensecurity(dev, bssidx);
6052                         wl->ap_info->security_mode = false;
6053                 }
6054
6055                 if (ies->wps_ie) {
6056                         wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
6057                 }
6058         }
6059
6060         return 0;
6061
6062 }
6063
6064 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WL_COMPAT_WIRELESS)
6065 static s32 wl_cfg80211_bcn_set_params(
6066         struct cfg80211_ap_settings *info,
6067         struct net_device *dev,
6068         u32 dev_role, s32 bssidx)
6069 {
6070         struct wl_priv *wl = wlcfg_drv_priv;
6071         s32 err = BCME_OK;
6072
6073         WL_DBG(("interval (%d) \ndtim_period (%d) \n",
6074                 info->beacon_interval, info->dtim_period));
6075
6076         if (info->beacon_interval) {
6077                 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
6078                         &info->beacon_interval, sizeof(s32), true)) < 0) {
6079                         WL_ERR(("Beacon Interval Set Error, %d\n", err));
6080                         return err;
6081                 }
6082         }
6083
6084         if (info->dtim_period) {
6085                 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
6086                         &info->dtim_period, sizeof(s32), true)) < 0) {
6087                         WL_ERR(("DTIM Interval Set Error, %d\n", err));
6088                         return err;
6089                 }
6090         }
6091
6092         if ((info->ssid) && (info->ssid_len > 0) &&
6093                 (info->ssid_len <= 32)) {
6094                 WL_DBG(("SSID (%s) len:%d \n", info->ssid, info->ssid_len));
6095                 if (dev_role == NL80211_IFTYPE_AP) {
6096                         /* Store the hostapd SSID */
6097                         memset(wl->hostapd_ssid.SSID, 0x00, 32);
6098                         memcpy(wl->hostapd_ssid.SSID, info->ssid, info->ssid_len);
6099                         wl->hostapd_ssid.SSID_len = info->ssid_len;
6100                 } else {
6101                                 /* P2P GO */
6102                         memset(wl->p2p->ssid.SSID, 0x00, 32);
6103                         memcpy(wl->p2p->ssid.SSID, info->ssid, info->ssid_len);
6104                         wl->p2p->ssid.SSID_len = info->ssid_len;
6105                 }
6106         }
6107
6108         if (info->hidden_ssid) {
6109                 if ((err = wldev_iovar_setint(dev, "closednet", 1)) < 0)
6110                         WL_ERR(("failed to set hidden : %d\n", err));
6111                 WL_DBG(("hidden_ssid_enum_val: %d \n", info->hidden_ssid));
6112         }
6113
6114         return err;
6115 }
6116 #endif /* LINUX_VERSION >= VERSION(3,4,0) || WL_COMPAT_WIRELESS */
6117
6118 static s32
6119 wl_cfg80211_parse_ies(u8 *ptr, u32 len, struct parsed_ies *ies)
6120 {
6121         s32 err = BCME_OK;
6122
6123         memset(ies, 0, sizeof(struct parsed_ies));
6124
6125         /* find the WPSIE */
6126         if ((ies->wps_ie = wl_cfgp2p_find_wpsie(ptr, len)) != NULL) {
6127                 WL_DBG(("WPSIE in beacon \n"));
6128                 ies->wps_ie_len = ies->wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
6129         } else {
6130                 WL_ERR(("No WPSIE in beacon \n"));
6131         }
6132
6133         /* find the RSN_IE */
6134         if ((ies->wpa2_ie = bcm_parse_tlvs(ptr, len,
6135                 DOT11_MNG_RSN_ID)) != NULL) {
6136                 WL_DBG((" WPA2 IE found\n"));
6137                 ies->wpa2_ie_len = ies->wpa2_ie->len;
6138         }
6139
6140         /* find the WPA_IE */
6141         if ((ies->wpa_ie = wl_cfgp2p_find_wpaie(ptr, len)) != NULL) {
6142                 WL_DBG((" WPA found\n"));
6143                 ies->wpa_ie_len = ies->wpa_ie->length;
6144         }
6145
6146         return err;
6147
6148 }
6149
6150 static s32
6151 wl_cfg80211_bcn_bringup_ap(
6152         struct net_device *dev,
6153         struct parsed_ies *ies,
6154         u32 dev_role, s32 bssidx)
6155 {
6156         struct wl_priv *wl = wlcfg_drv_priv;
6157         struct wl_join_params join_params;
6158         bool is_bssup = false;
6159         s32 infra = 1;
6160         s32 join_params_size = 0;
6161         s32 ap = 1;
6162 #ifdef DISABLE_11H_SOFTAP
6163         s32 spect = 0;
6164 #endif /* DISABLE_11H_SOFTAP */
6165         s32 err = BCME_OK;
6166
6167         WL_DBG(("Enter dev_role: %d\n", dev_role));
6168
6169         /* Common code for SoftAP and P2P GO */
6170         wldev_iovar_setint(dev, "mpc", 0);
6171
6172         if (dev_role == NL80211_IFTYPE_P2P_GO) {
6173                 is_bssup = wl_cfgp2p_bss_isup(dev, bssidx);
6174                 if (!is_bssup && (ies->wpa2_ie != NULL)) {
6175
6176                         err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
6177                         if (err < 0) {
6178                                 WL_ERR(("SET INFRA error %d\n", err));
6179                                 goto exit;
6180                         }
6181
6182                         err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &wl->p2p->ssid,
6183                                 sizeof(wl->p2p->ssid), wl->ioctl_buf, WLC_IOCTL_MAXLEN,
6184                                 bssidx, &wl->ioctl_buf_sync);
6185                         if (err < 0) {
6186                                 WL_ERR(("GO SSID setting error %d\n", err));
6187                                 goto exit;
6188                         }
6189
6190                         /* Do abort scan before creating GO */
6191                         wl_cfg80211_scan_abort(wl);
6192
6193                         if ((err = wl_cfgp2p_bss(wl, dev, bssidx, 1)) < 0) {
6194                                 WL_ERR(("GO Bring up error %d\n", err));
6195                                 goto exit;
6196                         }
6197                 } else
6198                         WL_DBG(("Bss is already up\n"));
6199         } else if ((dev_role == NL80211_IFTYPE_AP) &&
6200                 (wl_get_drv_status(wl, AP_CREATING, dev))) {
6201                 /* Device role SoftAP */
6202                 err = wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), true);
6203                 if (err < 0) {
6204                         WL_ERR(("WLC_DOWN error %d\n", err));
6205                         goto exit;
6206                 }
6207                 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
6208                 if (err < 0) {
6209                         WL_ERR(("SET INFRA error %d\n", err));
6210                         goto exit;
6211                 }
6212                 if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
6213                         WL_ERR(("setting AP mode failed %d \n", err));
6214                         goto exit;
6215                 }
6216 #ifdef DISABLE_11H_SOFTAP
6217                 err = wldev_ioctl(dev, WLC_SET_SPECT_MANAGMENT,
6218                         &spect, sizeof(s32), true);
6219                 if (err < 0) {
6220                         WL_ERR(("SET SPECT_MANAGMENT error %d\n", err));
6221                         goto exit;
6222                 }
6223 #endif /* DISABLE_11H_SOFTAP */
6224
6225                 err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
6226                 if (unlikely(err)) {
6227                         WL_ERR(("WLC_UP error (%d)\n", err));
6228                         goto exit;
6229                 }
6230
6231                 memset(&join_params, 0, sizeof(join_params));
6232                 /* join parameters starts with ssid */
6233                 join_params_size = sizeof(join_params.ssid);
6234                 memcpy(join_params.ssid.SSID, wl->hostapd_ssid.SSID,
6235                         wl->hostapd_ssid.SSID_len);
6236                 join_params.ssid.SSID_len = htod32(wl->hostapd_ssid.SSID_len);
6237
6238                 /* create softap */
6239                 if ((err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
6240                         join_params_size, true)) == 0) {
6241                         WL_DBG(("SoftAP set SSID (%s) success\n", join_params.ssid.SSID));
6242                         wl_clr_drv_status(wl, AP_CREATING, dev);
6243                         wl_set_drv_status(wl, AP_CREATED, dev);
6244                 }
6245         }
6246
6247
6248 exit:
6249         return err;
6250 }
6251
6252 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WL_COMPAT_WIRELESS)
6253 s32
6254 wl_cfg80211_parse_ap_ies(
6255         struct net_device *dev,
6256         struct cfg80211_beacon_data *info,
6257         struct parsed_ies *ies)
6258 {
6259         struct parsed_ies prb_ies;
6260         struct wl_priv *wl = wlcfg_drv_priv;
6261         dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
6262         u8 *vndr = NULL;
6263         u32 vndr_ie_len = 0;
6264         s32 err = BCME_OK;
6265
6266         /* Parse Beacon IEs */
6267         if (wl_cfg80211_parse_ies((u8 *)info->tail,
6268                 info->tail_len, ies) < 0) {
6269                 WL_ERR(("Beacon get IEs failed \n"));
6270                 err = -EINVAL;
6271                 goto fail;
6272         }
6273
6274         vndr = (u8 *)info->proberesp_ies;
6275         vndr_ie_len = info->proberesp_ies_len;
6276
6277         if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
6278                 /* SoftAP mode */
6279                 struct ieee80211_mgmt *mgmt;
6280                 mgmt = (struct ieee80211_mgmt *)info->probe_resp;
6281                 if (mgmt != NULL) {
6282                         vndr = (u8 *)&mgmt->u.probe_resp.variable;
6283                         vndr_ie_len = info->probe_resp_len -
6284                                 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
6285                 }
6286         }
6287
6288         /* Parse Probe Response IEs */
6289         if (wl_cfg80211_parse_ies(vndr, vndr_ie_len, &prb_ies) < 0) {
6290                 WL_ERR(("PROBE RESP get IEs failed \n"));
6291                 err = -EINVAL;
6292         }
6293
6294 fail:
6295
6296         return err;
6297 }
6298
6299 s32
6300 wl_cfg80211_set_ies(
6301         struct net_device *dev,
6302         struct cfg80211_beacon_data *info,
6303         s32 bssidx)
6304 {
6305         struct wl_priv *wl = wlcfg_drv_priv;
6306         dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
6307         u8 *vndr = NULL;
6308         u32 vndr_ie_len = 0;
6309         s32 err = BCME_OK;
6310
6311         /* Set Beacon IEs to FW */
6312         if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx,
6313                 VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
6314                 info->tail_len)) < 0) {
6315                 WL_ERR(("Set Beacon IE Failed \n"));
6316         } else {
6317                 WL_DBG(("Applied Vndr IEs for Beacon \n"));
6318         }
6319
6320         vndr = (u8 *)info->proberesp_ies;
6321         vndr_ie_len = info->proberesp_ies_len;
6322
6323         if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
6324                 /* SoftAP mode */
6325                 struct ieee80211_mgmt *mgmt;
6326                 mgmt = (struct ieee80211_mgmt *)info->probe_resp;
6327                 if (mgmt != NULL) {
6328                         vndr = (u8 *)&mgmt->u.probe_resp.variable;
6329                         vndr_ie_len = info->probe_resp_len -
6330                                 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
6331                 }
6332         }
6333
6334         /* Set Probe Response IEs to FW */
6335         if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx,
6336                 VNDR_IE_PRBRSP_FLAG, vndr, vndr_ie_len)) < 0) {
6337                 WL_ERR(("Set Probe Resp IE Failed \n"));
6338         } else {
6339                 WL_DBG(("Applied Vndr IEs for Probe Resp \n"));
6340         }
6341
6342         return err;
6343 }
6344 #endif /* LINUX_VERSION >= VERSION(3,4,0) || WL_COMPAT_WIRELESS */
6345
6346 static s32 wl_cfg80211_hostapd_sec(
6347         struct net_device *dev,
6348         struct parsed_ies *ies,
6349         s32 bssidx)
6350 {
6351         bool update_bss = 0;
6352         struct wl_priv *wl = wlcfg_drv_priv;
6353
6354
6355         if (ies->wps_ie) {
6356                 if (wl->ap_info->wps_ie &&
6357                         memcmp(wl->ap_info->wps_ie, ies->wps_ie, ies->wps_ie_len)) {
6358                         WL_DBG((" WPS IE is changed\n"));
6359                         kfree(wl->ap_info->wps_ie);
6360                         wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
6361                 } else if (wl->ap_info->wps_ie == NULL) {
6362                         WL_DBG((" WPS IE is added\n"));
6363                         wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
6364                 }
6365                 if ((ies->wpa_ie != NULL || ies->wpa2_ie != NULL)) {
6366                         if (!wl->ap_info->security_mode) {
6367                                 /* change from open mode to security mode */
6368                                 update_bss = true;
6369                                 if (ies->wpa_ie != NULL) {
6370                                         wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie,
6371                                         ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
6372                                         GFP_KERNEL);
6373                                 } else {
6374                                         wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie,
6375                                         ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
6376                                         GFP_KERNEL);
6377                                 }
6378                         } else if (wl->ap_info->wpa_ie) {
6379                                 /* change from WPA2 mode to WPA mode */
6380                                 if (ies->wpa_ie != NULL) {
6381                                         update_bss = true;
6382                                         kfree(wl->ap_info->rsn_ie);
6383                                         wl->ap_info->rsn_ie = NULL;
6384                                         wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie,
6385                                         ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
6386                                         GFP_KERNEL);
6387                                 } else if (memcmp(wl->ap_info->rsn_ie,
6388                                         ies->wpa2_ie, ies->wpa2_ie->len
6389                                         + WPA_RSN_IE_TAG_FIXED_LEN)) {
6390                                         update_bss = true;
6391                                         kfree(wl->ap_info->rsn_ie);
6392                                         wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie,
6393                                         ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
6394                                         GFP_KERNEL);
6395                                         wl->ap_info->wpa_ie = NULL;
6396                                 }
6397                         }
6398                         if (update_bss) {
6399                                 wl->ap_info->security_mode = true;
6400                                 wl_cfgp2p_bss(wl, dev, bssidx, 0);
6401                                 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0 ||
6402                                         wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0) {
6403                                         return BCME_ERROR;
6404                                 }
6405                                 wl_cfgp2p_bss(wl, dev, bssidx, 1);
6406                         }
6407                 }
6408         } else {
6409                 WL_ERR(("No WPSIE in beacon \n"));
6410         }
6411         return 0;
6412 }
6413
6414 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
6415         2, 0))
6416 static s32
6417 wl_cfg80211_del_station(
6418         struct wiphy *wiphy,
6419         struct net_device *ndev,
6420         u8* mac_addr)
6421 {
6422         struct net_device *dev;
6423         struct wl_priv *wl = wiphy_priv(wiphy);
6424         scb_val_t scb_val;
6425         s8 eabuf[ETHER_ADDR_STR_LEN];
6426         int err;
6427         char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
6428                 sizeof(struct ether_addr) + sizeof(uint)] = {0};
6429         struct maclist *assoc_maclist = (struct maclist *)mac_buf;
6430         int num_associated = 0;
6431
6432         WL_DBG(("Entry\n"));
6433         if (mac_addr == NULL) {
6434                 WL_DBG(("mac_addr is NULL ignore it\n"));
6435                 return 0;
6436         }
6437
6438         dev = ndev_to_wlc_ndev(ndev, wl);
6439
6440         if (p2p_is_on(wl)) {
6441                 /* Suspend P2P discovery search-listen to prevent it from changing the
6442                  * channel.
6443                  */
6444                 if ((wl_cfgp2p_discover_enable_search(wl, false)) < 0) {
6445                         WL_ERR(("Can not disable discovery mode\n"));
6446                         return -EFAULT;
6447                 }
6448         }
6449
6450         assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
6451         err = wldev_ioctl(ndev, WLC_GET_ASSOCLIST,
6452                 assoc_maclist, sizeof(mac_buf), false);
6453         if (err < 0)
6454                 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
6455         else
6456                 num_associated = assoc_maclist->count;
6457
6458         memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN);
6459         scb_val.val = DOT11_RC_DEAUTH_LEAVING;
6460         err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
6461                 sizeof(scb_val_t), true);
6462         if (err < 0)
6463                 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err));
6464         printk("Disconnect STA : %s scb_val.val %d\n",
6465                 bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf),
6466                 scb_val.val);
6467
6468         if (num_associated > 0 && ETHER_ISBCAST(mac_addr))
6469                 wl_delay(400);
6470
6471         return 0;
6472 }
6473 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
6474
6475 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WL_COMPAT_WIRELESS)
6476 static s32
6477 wl_cfg80211_start_ap(
6478         struct wiphy *wiphy,
6479         struct net_device *dev,
6480         struct cfg80211_ap_settings *info)
6481 {
6482         struct wl_priv *wl = wiphy_priv(wiphy);
6483         s32 err = BCME_OK;
6484         struct parsed_ies ies;
6485         s32 bssidx = 0;
6486         u32 dev_role = 0;
6487
6488         WL_DBG(("Enter \n"));
6489         if (dev == wl_to_prmry_ndev(wl)) {
6490                 WL_DBG(("Start AP req on primary iface: Softap\n"));
6491                 dev_role = NL80211_IFTYPE_AP;
6492         }
6493 #if defined(WL_ENABLE_P2P_IF)
6494         else if (dev == wl->p2p_net) {
6495                 /* Group Add request on p2p0 */
6496                 WL_DBG(("Start AP req on P2P iface: GO\n"));
6497                 dev = wl_to_prmry_ndev(wl);
6498                 dev_role = NL80211_IFTYPE_P2P_GO;
6499         }
6500 #endif /* WL_ENABLE_P2P_IF */
6501         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6502                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6503                 return BCME_ERROR;
6504         }
6505         if (p2p_is_on(wl) &&
6506                 (bssidx == wl_to_p2p_bss_bssidx(wl,
6507                 P2PAPI_BSSCFG_CONNECTION))) {
6508                 dev_role = NL80211_IFTYPE_P2P_GO;
6509                 WL_DBG(("Start AP req on P2P connection iface\n"));
6510         }
6511
6512         if (!check_dev_role_integrity(wl, dev_role))
6513                 goto fail;
6514
6515 #if defined(WL_CFG80211_P2P_DEV_IF) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
6516         if ((err = wl_cfg80211_set_channel(wiphy, dev,
6517                 dev->ieee80211_ptr->preset_chandef.chan,
6518                 NL80211_CHAN_HT20) < 0)) {
6519                 WL_ERR(("Set channel failed \n"));
6520                 goto fail;
6521         }
6522 #endif /* WL_CFG80211_P2P_DEV_IF || (LINUX_VERSION >= VERSION(3, 6, 0)) */
6523
6524         if ((err = wl_cfg80211_bcn_set_params(info, dev,
6525                 dev_role, bssidx)) < 0) {
6526                 WL_ERR(("Beacon params set failed \n"));
6527                 goto fail;
6528         }
6529
6530         /* Parse IEs */
6531         if ((err = wl_cfg80211_parse_ap_ies(dev, &info->beacon, &ies)) < 0) {
6532                 WL_ERR(("Set IEs failed \n"));
6533                 goto fail;
6534         }
6535
6536         if ((wl_cfg80211_bcn_validate_sec(dev, &ies,
6537                 dev_role, bssidx)) < 0)
6538         {
6539                 WL_ERR(("Beacon set security failed \n"));
6540                 goto fail;
6541         }
6542
6543         if ((err = wl_cfg80211_bcn_bringup_ap(dev, &ies,
6544                 dev_role, bssidx)) < 0) {
6545                 WL_ERR(("Beacon bring up AP/GO failed \n"));
6546                 goto fail;
6547         }
6548
6549         WL_DBG(("** AP/GO Created **\n"));
6550
6551         /* Set IEs to FW */
6552         if ((err = wl_cfg80211_set_ies(dev, &info->beacon, bssidx)) < 0)
6553                 WL_ERR(("Set IEs failed \n"));
6554
6555 fail:
6556         if (err) {
6557                 WL_ERR(("ADD/SET beacon failed\n"));
6558                 wldev_iovar_setint(dev, "mpc", 1);
6559         }
6560
6561         return err;
6562 }
6563
6564 static s32
6565 wl_cfg80211_stop_ap(
6566         struct wiphy *wiphy,
6567         struct net_device *dev)
6568 {
6569         int err = 0;
6570         u32 dev_role = 0;
6571         int infra = 0;
6572         int ap = 0;
6573         s32 bssidx = 0;
6574         struct wl_priv *wl = wiphy_priv(wiphy);
6575
6576         WL_DBG(("Enter \n"));
6577         if (dev == wl_to_prmry_ndev(wl)) {
6578                 dev_role = NL80211_IFTYPE_AP;
6579         }
6580 #if defined(WL_ENABLE_P2P_IF)
6581         else if (dev == wl->p2p_net) {
6582                 /* Group Add request on p2p0 */
6583                 dev = wl_to_prmry_ndev(wl);
6584                 dev_role = NL80211_IFTYPE_P2P_GO;
6585         }
6586 #endif /* WL_ENABLE_P2P_IF */
6587         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6588                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6589                 return BCME_ERROR;
6590         }
6591         if (p2p_is_on(wl) &&
6592                 (bssidx == wl_to_p2p_bss_bssidx(wl,
6593                 P2PAPI_BSSCFG_CONNECTION))) {
6594                 dev_role = NL80211_IFTYPE_P2P_GO;
6595         }
6596
6597         if (!check_dev_role_integrity(wl, dev_role))
6598                 goto exit;
6599
6600         if (dev_role == NL80211_IFTYPE_AP) {
6601                 /* SoftAp on primary Interface.
6602                  * Shut down AP and turn on MPC
6603                  */
6604                 if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
6605                         WL_ERR(("setting AP mode failed %d \n", err));
6606                         err = -ENOTSUPP;
6607                         goto exit;
6608                 }
6609                 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
6610                 if (err < 0) {
6611                         WL_ERR(("SET INFRA error %d\n", err));
6612                         err = -ENOTSUPP;
6613                         goto exit;
6614                 }
6615
6616                 err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
6617                 if (unlikely(err)) {
6618                         WL_ERR(("WLC_UP error (%d)\n", err));
6619                         err = -EINVAL;
6620                         goto exit;
6621                 }
6622
6623                 wl_clr_drv_status(wl, AP_CREATED, dev);
6624                 /* Turn on the MPC */
6625                 wldev_iovar_setint(dev, "mpc", 1);
6626         } else {
6627                 WL_DBG(("Stopping P2P GO \n"));
6628         }
6629
6630 exit:
6631         return err;
6632 }
6633
6634 static s32
6635 wl_cfg80211_change_beacon(
6636         struct wiphy *wiphy,
6637         struct net_device *dev,
6638         struct cfg80211_beacon_data *info)
6639 {
6640         s32 err = BCME_OK;
6641         struct wl_priv *wl = wiphy_priv(wiphy);
6642         struct parsed_ies ies;
6643         u32 dev_role = 0;
6644         s32 bssidx = 0;
6645
6646         WL_DBG(("Enter \n"));
6647
6648         if (dev == wl_to_prmry_ndev(wl)) {
6649                 dev_role = NL80211_IFTYPE_AP;
6650         }
6651 #if defined(WL_ENABLE_P2P_IF)
6652         else if (dev == wl->p2p_net) {
6653                 /* Group Add request on p2p0 */
6654                 dev = wl_to_prmry_ndev(wl);
6655                 dev_role = NL80211_IFTYPE_P2P_GO;
6656         }
6657 #endif /* WL_ENABLE_P2P_IF */
6658         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6659                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6660                 return BCME_ERROR;
6661         }
6662         if (p2p_is_on(wl) &&
6663                 (bssidx == wl_to_p2p_bss_bssidx(wl,
6664                 P2PAPI_BSSCFG_CONNECTION))) {
6665                 dev_role = NL80211_IFTYPE_P2P_GO;
6666         }
6667
6668         if (!check_dev_role_integrity(wl, dev_role))
6669                 goto fail;
6670
6671         /* Parse IEs */
6672         if ((err = wl_cfg80211_parse_ap_ies(dev, info, &ies)) < 0) {
6673                 WL_ERR(("Parse IEs failed \n"));
6674                 goto fail;
6675         }
6676
6677         /* Set IEs to FW */
6678         if ((err = wl_cfg80211_set_ies(dev, info, bssidx)) < 0) {
6679                 WL_ERR(("Set IEs failed \n"));
6680                 goto fail;
6681         }
6682
6683         if (dev_role == NL80211_IFTYPE_AP) {
6684                 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
6685                         WL_ERR(("Hostapd update sec failed \n"));
6686                         err = -EINVAL;
6687                         goto fail;
6688                 }
6689         }
6690
6691 fail:
6692         return err;
6693 }
6694 #else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) */
6695 static s32
6696 wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
6697         struct beacon_parameters *info)
6698 {
6699         s32 err = BCME_OK;
6700         struct wl_priv *wl = wiphy_priv(wiphy);
6701         s32 ie_offset = 0;
6702         s32 bssidx = 0;
6703         u32 dev_role = NL80211_IFTYPE_AP;
6704         struct parsed_ies ies;
6705         bcm_tlv_t *ssid_ie;
6706         bool pbc = 0;
6707
6708         WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
6709                 info->interval, info->dtim_period, info->head_len, info->tail_len));
6710
6711         if (dev == wl_to_prmry_ndev(wl)) {
6712                 dev_role = NL80211_IFTYPE_AP;
6713         }
6714 #if defined(WL_ENABLE_P2P_IF)
6715         else if (dev == wl->p2p_net) {
6716                 /* Group Add request on p2p0 */
6717                 dev = wl_to_prmry_ndev(wl);
6718                 dev_role = NL80211_IFTYPE_P2P_GO;
6719         }
6720 #endif /* WL_ENABLE_P2P_IF */
6721         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6722                 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6723                 return BCME_ERROR;
6724         }
6725         if (p2p_is_on(wl) &&
6726                 (bssidx == wl_to_p2p_bss_bssidx(wl,
6727                 P2PAPI_BSSCFG_CONNECTION))) {
6728                 dev_role = NL80211_IFTYPE_P2P_GO;
6729         }
6730
6731         if (!check_dev_role_integrity(wl, dev_role))
6732                 goto fail;
6733
6734         ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
6735         /* find the SSID */
6736         if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
6737                 info->head_len - ie_offset,
6738                 DOT11_MNG_SSID_ID)) != NULL) {
6739                 if (dev_role == NL80211_IFTYPE_AP) {
6740                         /* Store the hostapd SSID */
6741                         memset(&wl->hostapd_ssid.SSID[0], 0x00, 32);
6742                         memcpy(&wl->hostapd_ssid.SSID[0], ssid_ie->data, ssid_ie->len);
6743                         wl->hostapd_ssid.SSID_len = ssid_ie->len;
6744                 } else {
6745                                 /* P2P GO */
6746                         memset(&wl->p2p->ssid.SSID[0], 0x00, 32);
6747                         memcpy(wl->p2p->ssid.SSID, ssid_ie->data, ssid_ie->len);
6748                         wl->p2p->ssid.SSID_len = ssid_ie->len;
6749                 }
6750         }
6751
6752         if (wl_cfg80211_parse_ies((u8 *)info->tail,
6753                 info->tail_len, &ies) < 0) {
6754                 WL_ERR(("Beacon get IEs failed \n"));
6755                 err = -EINVAL;
6756                 goto fail;
6757         }
6758
6759         if (wl_cfgp2p_set_management_ie(wl, dev, bssidx,
6760                 VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
6761                 info->tail_len) < 0) {
6762                 WL_ERR(("Beacon set IEs failed \n"));
6763                 goto fail;
6764         } else {
6765                 WL_DBG(("Applied Vndr IEs for Beacon \n"));
6766         }
6767         if (!wl_cfgp2p_bss_isup(dev, bssidx) &&
6768                 (wl_cfg80211_bcn_validate_sec(dev, &ies, dev_role, bssidx) < 0))
6769         {
6770                 WL_ERR(("Beacon set security failed \n"));
6771                 goto fail;
6772         }
6773
6774         /* Set BI and DTIM period */
6775         if (info->interval) {
6776                 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
6777                         &info->interval, sizeof(s32), true)) < 0) {
6778                         WL_ERR(("Beacon Interval Set Error, %d\n", err));
6779                         return err;
6780                 }
6781         }
6782         if (info->dtim_period) {
6783                 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
6784                         &info->dtim_period, sizeof(s32), true)) < 0) {
6785                         WL_ERR(("DTIM Interval Set Error, %d\n", err));
6786                         return err;
6787                 }
6788         }
6789
6790         if (wl_cfg80211_bcn_bringup_ap(dev, &ies, dev_role, bssidx) < 0) {
6791                 WL_ERR(("Beacon bring up AP/GO failed \n"));
6792                 goto fail;
6793         }
6794
6795         if (wl_get_drv_status(wl, AP_CREATED, dev)) {
6796                 /* Soft AP already running. Update changed params */
6797                 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
6798                         WL_ERR(("Hostapd update sec failed \n"));
6799                         err = -EINVAL;
6800                         goto fail;
6801                 }
6802         }
6803
6804         /* Enable Probe Req filter */
6805         if (((dev_role == NL80211_IFTYPE_P2P_GO) ||
6806                 (dev_role == NL80211_IFTYPE_AP)) && (ies.wps_ie != NULL)) {
6807                 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
6808                 if (pbc)
6809                         wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
6810         }
6811
6812         WL_DBG(("** ADD/SET beacon done **\n"));
6813
6814 fail:
6815         if (err) {
6816                 WL_ERR(("ADD/SET beacon failed\n"));
6817                 wldev_iovar_setint(dev, "mpc", 1);
6818         }
6819         return err;
6820
6821 }
6822 #endif /* LINUX_VERSION < VERSION(3,4,0) || WL_COMPAT_WIRELESS */
6823
6824 #ifdef WL_SCHED_SCAN
6825 #define PNO_TIME                30
6826 #define PNO_REPEAT              4
6827 #define PNO_FREQ_EXPO_MAX       2
6828 int wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
6829                              struct net_device *dev,
6830                              struct cfg80211_sched_scan_request *request)
6831 {
6832         ushort pno_time = PNO_TIME;
6833         int pno_repeat = PNO_REPEAT;
6834         int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
6835         wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
6836         struct wl_priv *wl = wiphy_priv(wiphy);
6837         struct cfg80211_ssid *ssid = NULL;
6838         int ssid_count = 0;
6839         int i;
6840         int ret = 0;
6841
6842         WL_DBG(("Enter \n"));
6843         WL_PNO((">>> SCHED SCAN START\n"));
6844         WL_PNO(("Enter n_match_sets:%d   n_ssids:%d \n",
6845                 request->n_match_sets, request->n_ssids));
6846         WL_PNO(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
6847                 request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max));
6848
6849
6850         if (!request || !request->n_ssids || !request->n_match_sets) {
6851                 WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids));
6852                 return -EINVAL;
6853         }
6854
6855         memset(&ssids_local, 0, sizeof(ssids_local));
6856
6857         if (request->n_match_sets > 0) {
6858                 for (i = 0; i < request->n_match_sets; i++) {
6859                         ssid = &request->match_sets[i].ssid;
6860                         memcpy(ssids_local[i].SSID, ssid->ssid, ssid->ssid_len);
6861                         ssids_local[i].SSID_len = ssid->ssid_len;
6862                         WL_PNO((">>> PNO filter set for ssid (%s) \n", ssid->ssid));
6863                         ssid_count++;
6864                 }
6865         }
6866
6867         if (request->n_ssids > 0) {
6868                 for (i = 0; i < request->n_ssids; i++) {
6869                         /* Active scan req for ssids */
6870                         WL_PNO((">>> Active scan req for ssid (%s) \n", request->ssids[i].ssid));
6871
6872                         /* match_set ssids is a supert set of n_ssid list, so we need
6873                          * not add these set seperately
6874                          */
6875                 }
6876         }
6877
6878         if (ssid_count) {
6879                 if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, request->n_match_sets,
6880                         pno_time, pno_repeat, pno_freq_expo_max, NULL, 0)) < 0) {
6881                         WL_ERR(("PNO setup failed!! ret=%d \n", ret));
6882                         return -EINVAL;
6883                 }
6884                 wl->sched_scan_req = request;
6885         } else {
6886                 return -EINVAL;
6887         }
6888
6889         return 0;
6890 }
6891
6892 int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
6893 {
6894         struct wl_priv *wl = wiphy_priv(wiphy);
6895
6896         WL_DBG(("Enter \n"));
6897         WL_PNO((">>> SCHED SCAN STOP\n"));
6898
6899         if (dhd_dev_pno_stop_for_ssid(dev) < 0)
6900                 WL_ERR(("PNO Stop for SSID failed"));
6901
6902         if (wl->scan_request && wl->sched_scan_running) {
6903                 WL_PNO((">>> Sched scan running. Aborting it..\n"));
6904                 wl_notify_escan_complete(wl, dev, true, true);
6905         }
6906
6907          wl->sched_scan_req = NULL;
6908          wl->sched_scan_running = FALSE;
6909
6910         return 0;
6911 }
6912 #endif /* WL_SCHED_SCAN */
6913
6914 static struct cfg80211_ops wl_cfg80211_ops = {
6915         .add_virtual_intf = wl_cfg80211_add_virtual_iface,
6916         .del_virtual_intf = wl_cfg80211_del_virtual_iface,
6917         .change_virtual_intf = wl_cfg80211_change_virtual_iface,
6918 #if defined(WL_CFG80211_P2P_DEV_IF)
6919         .start_p2p_device = wl_cfgp2p_start_p2p_device,
6920         .stop_p2p_device = wl_cfgp2p_stop_p2p_device,
6921 #endif /* WL_CFG80211_P2P_DEV_IF */
6922         .scan = wl_cfg80211_scan,
6923         .set_wiphy_params = wl_cfg80211_set_wiphy_params,
6924         .join_ibss = wl_cfg80211_join_ibss,
6925         .leave_ibss = wl_cfg80211_leave_ibss,
6926         .get_station = wl_cfg80211_get_station,
6927         .set_tx_power = wl_cfg80211_set_tx_power,
6928         .get_tx_power = wl_cfg80211_get_tx_power,
6929         .add_key = wl_cfg80211_add_key,
6930         .del_key = wl_cfg80211_del_key,
6931         .get_key = wl_cfg80211_get_key,
6932         .set_default_key = wl_cfg80211_config_default_key,
6933         .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
6934         .set_power_mgmt = wl_cfg80211_set_power_mgmt,
6935         .connect = wl_cfg80211_connect,
6936         .disconnect = wl_cfg80211_disconnect,
6937         .suspend = wl_cfg80211_suspend,
6938         .resume = wl_cfg80211_resume,
6939         .set_pmksa = wl_cfg80211_set_pmksa,
6940         .del_pmksa = wl_cfg80211_del_pmksa,
6941         .flush_pmksa = wl_cfg80211_flush_pmksa,
6942         .remain_on_channel = wl_cfg80211_remain_on_channel,
6943         .cancel_remain_on_channel = wl_cfg80211_cancel_remain_on_channel,
6944         .mgmt_tx = wl_cfg80211_mgmt_tx,
6945         .mgmt_frame_register = wl_cfg80211_mgmt_frame_register,
6946         .change_bss = wl_cfg80211_change_bss,
6947 #if !defined(WL_CFG80211_P2P_DEV_IF) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
6948         .set_channel = wl_cfg80211_set_channel,
6949 #endif /* !WL_CFG80211_P2P_DEV_IF && (LINUX_VERSION < VERSION(3, 6, 0)) */
6950 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !defined(WL_COMPAT_WIRELESS)
6951         .set_beacon = wl_cfg80211_add_set_beacon,
6952         .add_beacon = wl_cfg80211_add_set_beacon,
6953 #else
6954         .change_beacon = wl_cfg80211_change_beacon,
6955         .start_ap = wl_cfg80211_start_ap,
6956         .stop_ap = wl_cfg80211_stop_ap,
6957 #endif /* LINUX_VERSION < KERNEL_VERSION(3,4,0) && !WL_COMPAT_WIRELESS */
6958 #ifdef WL_SCHED_SCAN
6959         .sched_scan_start = wl_cfg80211_sched_scan_start,
6960         .sched_scan_stop = wl_cfg80211_sched_scan_stop,
6961 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */
6962 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
6963         2, 0))
6964         .del_station = wl_cfg80211_del_station,
6965         .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait,
6966 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */
6967 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS)
6968         .tdls_oper = wl_cfg80211_tdls_oper
6969 #endif /* LINUX_VERSION > VERSION(3, 2, 0) || WL_COMPAT_WIRELESS */
6970 };
6971
6972 s32 wl_mode_to_nl80211_iftype(s32 mode)
6973 {
6974         s32 err = 0;
6975
6976         switch (mode) {
6977         case WL_MODE_BSS:
6978                 return NL80211_IFTYPE_STATION;
6979         case WL_MODE_IBSS:
6980                 return NL80211_IFTYPE_ADHOC;
6981         case WL_MODE_AP:
6982                 return NL80211_IFTYPE_AP;
6983         default:
6984                 return NL80211_IFTYPE_UNSPECIFIED;
6985         }
6986
6987         return err;
6988 }
6989
6990 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
6991 /*      Kernel Network Support->Wireless->Regulatory rules database
6992         options should be enabled and regulatory  CRDA regdb table populated in Kernel
6993         for proper country reg notification
6994 */
6995 static int
6996 wl_cfg80211_reg_notifier(
6997         struct wiphy *wiphy,
6998         struct regulatory_request *request)
6999 {
7000         struct wl_priv *wl = (struct wl_priv *)wiphy_priv(wiphy);
7001         int ret = 0;
7002
7003         if (!request || !wl) {
7004                 WL_ERR(("Invalid arg\n"));
7005                 return -EINVAL;
7006         }
7007
7008         WL_DBG(("ccode: %c%c Initiator: %d\n",
7009                 request->alpha2[0], request->alpha2[1], request->initiator));
7010
7011         /* We support only REGDOM_SET_BY_USER as of now */
7012         if ((request->initiator != NL80211_REGDOM_SET_BY_USER) &&
7013                 (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
7014                 WL_ERR(("reg_notifier for intiator:%d not supported : set default\n",
7015                         request->initiator));
7016                 /* in case of no supported country by regdb
7017                      lets driver setup platform default Locale
7018                 */
7019         }
7020
7021         WL_ERR(("Set country code %c%c from %s\n",
7022                 request->alpha2[0], request->alpha2[1],
7023                 ((request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) ? " 11d AP" : "User")));
7024
7025         if ((ret = wldev_set_country(wl_to_prmry_ndev(wl), request->alpha2,
7026                 false, (request->initiator == NL80211_REGDOM_SET_BY_USER ? true : false))) < 0) {
7027                 WL_ERR(("set country Failed :%d\n", ret));
7028         }
7029
7030         return ret;
7031 }
7032 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
7033
7034 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, void *data)
7035 {
7036         s32 err = 0;
7037 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
7038         (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
7039         dhd_pub_t *dhd = (dhd_pub_t *)data;
7040 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
7041
7042         wdev->wiphy =
7043             wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_priv));
7044         if (unlikely(!wdev->wiphy)) {
7045                 WL_ERR(("Couldn not allocate wiphy device\n"));
7046                 err = -ENOMEM;
7047                 return err;
7048         }
7049         set_wiphy_dev(wdev->wiphy, sdiofunc_dev);
7050         wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX;
7051         /* Report  how many SSIDs Driver can support per Scan request */
7052         wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX;
7053         wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
7054 #ifdef WL_SCHED_SCAN
7055         wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT;
7056         wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT;
7057         wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX;
7058         wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
7059 #endif /* WL_SCHED_SCAN */
7060         wdev->wiphy->interface_modes =
7061                 BIT(NL80211_IFTYPE_STATION)
7062                 | BIT(NL80211_IFTYPE_ADHOC)
7063 #if !defined(WL_ENABLE_P2P_IF)
7064                 | BIT(NL80211_IFTYPE_MONITOR)
7065 #endif /* !WL_ENABLE_P2P_IF */
7066 #if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)
7067                 | BIT(NL80211_IFTYPE_P2P_CLIENT)
7068                 | BIT(NL80211_IFTYPE_P2P_GO)
7069 #endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */
7070 #if defined(WL_CFG80211_P2P_DEV_IF)
7071                 | BIT(NL80211_IFTYPE_P2P_DEVICE)
7072 #endif /* WL_CFG80211_P2P_DEV_IF */
7073                 | BIT(NL80211_IFTYPE_AP);
7074
7075 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
7076         (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
7077         if (dhd && dhd->op_mode == DHD_FLAG_HOSTAP_MODE) {
7078                 WL_DBG(("Setting interface combinations for SoftAP mode\n"));
7079                 wdev->wiphy->iface_combinations = softap_iface_combinations;
7080                 wdev->wiphy->n_iface_combinations =
7081                         ARRAY_SIZE(softap_iface_combinations);
7082         } else {
7083                 WL_DBG(("Setting interface combinations for STA+P2P mode\n"));
7084                 wdev->wiphy->iface_combinations = sta_p2p_iface_combinations;
7085                 wdev->wiphy->n_iface_combinations =
7086                         ARRAY_SIZE(sta_p2p_iface_combinations);
7087         }
7088 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
7089
7090         wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
7091
7092         wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
7093         wdev->wiphy->cipher_suites = __wl_cipher_suites;
7094         wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
7095         wdev->wiphy->max_remain_on_channel_duration = 5000;
7096         wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes;
7097 #ifndef WL_POWERSAVE_DISABLED
7098         wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
7099 #else
7100         wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
7101 #endif                          /* !WL_POWERSAVE_DISABLED */
7102         wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK |
7103                 WIPHY_FLAG_4ADDR_AP |
7104 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && !defined(WL_COMPAT_WIRELESS)
7105                 WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS |
7106 #endif
7107                 WIPHY_FLAG_4ADDR_STATION;
7108         /*  If driver advertises FW_ROAM, the supplicant wouldn't
7109          * send the BSSID & Freq in the connect command allowing the
7110          * the driver to choose the AP to connect to. But unless we
7111          * support ROAM_CACHE in firware this will delay the ASSOC as
7112          * as the FW need to do a full scan before attempting to connect
7113          * So that feature will just increase assoc. The better approach
7114          * to let Supplicant to provide channel info and FW letter may roam
7115          * if needed so DON'T advertise that featur eto Supplicant.
7116          */
7117 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
7118         /* wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; */
7119 #endif
7120 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || defined(WL_COMPAT_WIRELESS)
7121         wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
7122                 WIPHY_FLAG_OFFCHAN_TX;
7123 #endif
7124 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
7125         4, 0))
7126         /* From 3.4 kernel ownards AP_SME flag can be advertised
7127          * to remove the patch from supplicant
7128          */
7129         wdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
7130 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
7131
7132 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
7133         wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier;
7134 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
7135
7136 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS)
7137         wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
7138 #endif
7139         WL_DBG(("Registering custom regulatory)\n"));
7140         wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
7141         wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom);
7142         /* Now we can register wiphy with cfg80211 module */
7143         err = wiphy_register(wdev->wiphy);
7144         if (unlikely(err < 0)) {
7145                 WL_ERR(("Couldn not register wiphy device (%d)\n", err));
7146                 wiphy_free(wdev->wiphy);
7147         }
7148
7149 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \
7150         KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS)
7151         wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS;
7152 #endif /* ((LINUX_VER >= 3.0) && (LINUX_VER <= 3.3)) && WL_IFACE_COMB_NUM_CHANNELS */
7153
7154         return err;
7155 }
7156
7157 static void wl_free_wdev(struct wl_priv *wl)
7158 {
7159         struct wireless_dev *wdev = wl->wdev;
7160         struct wiphy *wiphy;
7161         if (!wdev) {
7162                 WL_ERR(("wdev is invalid\n"));
7163                 return;
7164         }
7165         wiphy = wdev->wiphy;
7166         wiphy_unregister(wdev->wiphy);
7167         wdev->wiphy->dev.parent = NULL;
7168
7169         wl_delete_all_netinfo(wl);
7170         wiphy_free(wiphy);
7171         /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "wl",
7172          * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
7173          */
7174 }
7175
7176 static s32 wl_inform_bss(struct wl_priv *wl)
7177 {
7178         struct wl_scan_results *bss_list;
7179         struct wl_bss_info *bi = NULL;  /* must be initialized */
7180         s32 err = 0;
7181         s32 i;
7182 #if defined(RSSIAVG)
7183         struct net_device *ndev = wl_to_prmry_ndev(wl);
7184         int rssi;
7185 #endif
7186 #if defined(BSSCACHE)
7187         wl_bss_cache_t *node;
7188 #endif
7189
7190         bss_list = wl->bss_list;
7191
7192 #if defined(BSSCACHE)
7193         if (g_bss_cache_ctrl.m_timer_expired || (p2p_is_on(wl) && p2p_scan(wl))) {
7194 #if defined(RSSIAVG)
7195                 wl_free_rssi_cache(&g_rssi_cache_ctrl);
7196 #endif
7197                 wl_free_bss_cache(&g_bss_cache_ctrl);
7198                 g_bss_cache_ctrl.m_timer_expired ^= 1;
7199         }
7200         wl_update_bss_cache(&g_bss_cache_ctrl, bss_list);
7201         wl_delete_dirty_bss_cache(&g_bss_cache_ctrl);
7202         wl_reset_bss_cache(&g_bss_cache_ctrl);
7203 #endif
7204
7205 #if defined(RSSIAVG)
7206 #if defined(BSSCACHE)
7207         node = g_bss_cache_ctrl.m_cache_head;
7208         for (;node;) {
7209                 wl_update_rssi_cache(&g_rssi_cache_ctrl, &node->results);
7210                 node = node->next;
7211         }
7212 #else
7213         wl_update_rssi_cache(&g_rssi_cache_ctrl, bss_list);
7214 #endif
7215         if (!in_atomic())
7216                 wl_update_connected_rssi_cache(ndev, &g_rssi_cache_ctrl, &rssi);
7217         wl_delete_dirty_rssi_cache(&g_rssi_cache_ctrl);
7218         wl_reset_rssi_cache(&g_rssi_cache_ctrl);
7219 #endif
7220
7221 #if defined(BSSCACHE)
7222         if (p2p_disconnected > 0) {
7223                 // terence 20130703: Fix for wrong group_capab (timing issue)
7224                 wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl, (u8*)&p2p_disconnected_bssid);
7225 #if defined(RSSIAVG)
7226                 wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl, (u8*)&p2p_disconnected_bssid);
7227 #endif
7228         }
7229         WL_SCAN(("Inform cached AP list\n"));
7230         node = g_bss_cache_ctrl.m_cache_head;
7231         for (i=0; node && i<WL_AP_MAX; i++) {
7232                 if (node->dirty > 1) {
7233                         // just inform dirty bss
7234                         bi = node->results.bss_info;
7235                         err = wl_inform_single_bss(wl, bi);
7236                 }
7237                 node = node->next;
7238         }
7239         wl_run_bss_cache_timer(&g_bss_cache_ctrl, 0);
7240         wl_run_bss_cache_timer(&g_bss_cache_ctrl, 1);
7241         bi = NULL;
7242 #endif
7243
7244         WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
7245         bi = next_bss(bss_list, bi);
7246         for_each_bss(bss_list, bi, i) {
7247                 if (p2p_disconnected > 0 && !memcmp(&bi->BSSID, &p2p_disconnected_bssid, ETHER_ADDR_LEN))
7248                         continue;
7249                 err = wl_inform_single_bss(wl, bi);
7250         }
7251
7252         if (p2p_disconnected > 0) {
7253                 // terence 20130703: Fix for wrong group_capab (timing issue)
7254                 p2p_disconnected++;
7255                 if (p2p_disconnected >= REPEATED_SCAN_RESULT_CNT+1)
7256                         p2p_disconnected = 0;
7257         }
7258
7259         return err;
7260 }
7261
7262 static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
7263 {
7264         struct wiphy *wiphy = wl_to_wiphy(wl);
7265         struct ieee80211_mgmt *mgmt;
7266         struct ieee80211_channel *channel;
7267         struct ieee80211_supported_band *band;
7268         struct wl_cfg80211_bss_info *notif_bss_info;
7269         struct wl_scan_req *sr = wl_to_sr(wl);
7270         struct beacon_proberesp *beacon_proberesp;
7271         struct cfg80211_bss *cbss = NULL;
7272         s32 mgmt_type;
7273         s32 signal;
7274         u32 freq;
7275         s32 err = 0;
7276         gfp_t aflags;
7277
7278         if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
7279                 WL_ERR(("Beacon is larger than buffer. Discarding\n"));
7280                 return err;
7281         }
7282         aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
7283         notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt)
7284                 - sizeof(u8) + WL_BSS_INFO_MAX, aflags);
7285         if (unlikely(!notif_bss_info)) {
7286                 WL_ERR(("notif_bss_info alloc failed\n"));
7287                 return -ENOMEM;
7288         }
7289         mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
7290         notif_bss_info->channel =
7291                 bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
7292
7293         if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
7294                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
7295         else
7296                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
7297         if (!band) {
7298                 WL_DBG(("No valid band\n"));
7299                 kfree(notif_bss_info);
7300                 return -EINVAL;
7301         }
7302         notif_bss_info->rssi = dtoh16(bi->RSSI);
7303 #if defined(RSSIAVG)
7304         notif_bss_info->rssi = wl_get_avg_rssi(&g_rssi_cache_ctrl, &bi->BSSID);
7305         if (notif_bss_info->rssi == RSSI_MINVAL)
7306                 notif_bss_info->rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
7307 #endif
7308 #if defined(RSSIOFFSET)
7309         notif_bss_info->rssi = wl_update_rssi_offset(notif_bss_info->rssi);
7310 #endif
7311         memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
7312         mgmt_type = wl->active_scan ?
7313                 IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
7314         if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
7315             mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
7316         }
7317         beacon_proberesp = wl->active_scan ?
7318                 (struct beacon_proberesp *)&mgmt->u.probe_resp :
7319                 (struct beacon_proberesp *)&mgmt->u.beacon;
7320         beacon_proberesp->timestamp = 0;
7321         beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
7322         beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
7323         wl_rst_ie(wl);
7324         wl_update_hidden_ap_ie(bi, ((u8 *) bi) + bi->ie_offset, &bi->ie_length);
7325         wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
7326         wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX -
7327                 offsetof(struct wl_cfg80211_bss_info, frame_buf));
7328         notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
7329                 u.beacon.variable) + wl_get_ielen(wl);
7330 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
7331         freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
7332         (void)band->band;
7333 #else
7334         freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band);
7335 #endif
7336         if (freq == 0) {
7337                 WL_ERR(("Invalid channel, fail to change channel to freq\n"));
7338                 kfree(notif_bss_info);
7339                 return -EINVAL;
7340         }
7341         channel = ieee80211_get_channel(wiphy, freq);
7342         if (unlikely(!channel)) {
7343                 WL_ERR(("ieee80211_get_channel error, freq=%d, channel=%d\n",
7344                         freq, notif_bss_info->channel));
7345                 kfree(notif_bss_info);
7346                 return -EINVAL;
7347         }
7348         WL_SCAN(("BSSID %pM, channel %d, rssi %d, capa 0x04%x, mgmt_type %d, "
7349                 "frame_len %d, SSID \"%s\"\n", &bi->BSSID, notif_bss_info->channel,
7350                 notif_bss_info->rssi, mgmt->u.beacon.capab_info, mgmt_type,
7351                 notif_bss_info->frame_len, bi->SSID));
7352
7353         signal = notif_bss_info->rssi * 100;
7354         if (!mgmt->u.probe_resp.timestamp) {
7355 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
7356                 struct timespec ts;
7357                 get_monotonic_boottime(&ts);
7358                 mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000)
7359                                 + ts.tv_nsec / 1000;
7360 #else
7361                 struct timeval tv;
7362                 do_gettimeofday(&tv);
7363                 mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec*1000000)
7364                                 + tv.tv_usec;
7365 #endif
7366         }
7367
7368         cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
7369                 le16_to_cpu(notif_bss_info->frame_len), signal, aflags);
7370         if (unlikely(!cbss)) {
7371                 WL_ERR(("cfg80211_inform_bss_frame error\n"));
7372                 kfree(notif_bss_info);
7373                 return -EINVAL;
7374         }
7375
7376 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
7377         cfg80211_put_bss(wiphy, cbss);
7378 #else
7379         cfg80211_put_bss(cbss);
7380 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
7381         kfree(notif_bss_info);
7382         return err;
7383 }
7384
7385 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev)
7386 {
7387         u32 event = ntoh32(e->event_type);
7388         u32 status =  ntoh32(e->status);
7389         u16 flags = ntoh16(e->flags);
7390
7391         WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
7392         if (event == WLC_E_SET_SSID) {
7393                 if (status == WLC_E_STATUS_SUCCESS) {
7394                         if (!wl_is_ibssmode(wl, ndev))
7395                                 return true;
7396                 }
7397         } else if (event == WLC_E_LINK) {
7398                 if (flags & WLC_EVENT_MSG_LINK)
7399                         return true;
7400         }
7401
7402         WL_DBG(("wl_is_linkup false\n"));
7403         return false;
7404 }
7405
7406 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
7407 {
7408         u32 event = ntoh32(e->event_type);
7409         u16 flags = ntoh16(e->flags);
7410
7411         if (event == WLC_E_DEAUTH_IND ||
7412         event == WLC_E_DISASSOC_IND ||
7413         event == WLC_E_DISASSOC ||
7414         event == WLC_E_DEAUTH) {
7415 #if (WL_DBG_LEVEL > 0)
7416         WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
7417 #endif /* (WL_DBG_LEVEL > 0) */
7418                 return true;
7419         } else if (event == WLC_E_LINK) {
7420                 if (!(flags & WLC_EVENT_MSG_LINK)) {
7421 #if (WL_DBG_LEVEL > 0)
7422         WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
7423 #endif /* (WL_DBG_LEVEL > 0) */
7424                         return true;
7425                 }
7426         }
7427
7428         return false;
7429 }
7430
7431 static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e)
7432 {
7433         u32 event = ntoh32(e->event_type);
7434         u32 status = ntoh32(e->status);
7435
7436         if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS)
7437                 return true;
7438         if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS)
7439                 return true;
7440
7441         return false;
7442 }
7443
7444 /* The mainline kernel >= 3.2.0 has support for indicating new/del station
7445  * to AP/P2P GO via events. If this change is backported to kernel for which
7446  * this driver is being built, then define WL_CFG80211_STA_EVENT. You
7447  * should use this new/del sta event mechanism for BRCM supplicant >= 22.
7448  */
7449 static s32
7450 wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev,
7451         const wl_event_msg_t *e, void *data)
7452 {
7453         s32 err = 0;
7454         u32 event = ntoh32(e->event_type);
7455         u32 reason = ntoh32(e->reason);
7456         u32 len = ntoh32(e->datalen);
7457
7458 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) \
7459         && !defined(WL_COMPAT_WIRELESS)
7460         bool isfree = false;
7461         u8 *mgmt_frame;
7462         u8 bsscfgidx = e->bsscfgidx;
7463         s32 freq;
7464         s32 channel;
7465         u8 *body = NULL;
7466         u16 fc = 0;
7467
7468         struct ieee80211_supported_band *band;
7469         struct ether_addr da;
7470         struct ether_addr bssid;
7471         struct wiphy *wiphy = wl_to_wiphy(wl);
7472         channel_info_t ci;
7473 #else
7474         struct station_info sinfo;
7475 #endif /* (LINUX_VERSION < VERSION(3,2,0)) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
7476
7477         WL_DBG(("event %d status %d reason %d\n", event, ntoh32(e->status), reason));
7478         /* if link down, bsscfg is disabled. */
7479         if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
7480                 wl_get_p2p_status(wl, IF_DELETING) && (ndev != wl_to_prmry_ndev(wl))) {
7481                 wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
7482                 WL_INFO(("AP mode link down !! \n"));
7483                 complete(&wl->iface_disable);
7484                 return 0;
7485         }
7486
7487 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) \
7488         && !defined(WL_COMPAT_WIRELESS)
7489         WL_DBG(("Enter \n"));
7490         if (!len && (event == WLC_E_DEAUTH)) {
7491                 len = 2; /* reason code field */
7492                 data = &reason;
7493         }
7494         if (len) {
7495                 body = kzalloc(len, GFP_KERNEL);
7496
7497                 if (body == NULL) {
7498                         WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
7499                         return WL_INVALID;
7500                 }
7501         }
7502         memset(&bssid, 0, ETHER_ADDR_LEN);
7503         WL_DBG(("Enter event %d ndev %p\n", event, ndev));
7504         if (wl_get_mode_by_netdev(wl, ndev) == WL_INVALID) {
7505                 kfree(body);
7506                 return WL_INVALID;
7507         }
7508         if (len)
7509                 memcpy(body, data, len);
7510
7511         wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
7512                 NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync);
7513         memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN);
7514         err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
7515         switch (event) {
7516                 case WLC_E_ASSOC_IND:
7517                         fc = FC_ASSOC_REQ;
7518                         break;
7519                 case WLC_E_REASSOC_IND:
7520                         fc = FC_REASSOC_REQ;
7521                         break;
7522                 case WLC_E_DISASSOC_IND:
7523                         fc = FC_DISASSOC;
7524                         break;
7525                 case WLC_E_DEAUTH_IND:
7526                         fc = FC_DISASSOC;
7527                         break;
7528                 case WLC_E_DEAUTH:
7529                         fc = FC_DISASSOC;
7530                         break;
7531                 default:
7532                         fc = 0;
7533                         goto exit;
7534         }
7535         if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) {
7536                 kfree(body);
7537                 return err;
7538         }
7539
7540         channel = dtoh32(ci.hw_channel);
7541         if (channel <= CH_MAX_2G_CHANNEL)
7542                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
7543         else
7544                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
7545         if (!band) {
7546                 WL_DBG(("No valid band\n"));
7547                 if (body)
7548                         kfree(body);
7549                 return -EINVAL;
7550         }
7551 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
7552         freq = ieee80211_channel_to_frequency(channel);
7553         (void)band->band;
7554 #else
7555         freq = ieee80211_channel_to_frequency(channel, band->band);
7556 #endif
7557
7558         err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
7559                 &mgmt_frame, &len, body);
7560         if (err < 0)
7561                 goto exit;
7562         isfree = true;
7563
7564         if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) {
7565 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WL_COMPAT_WIRELESS)
7566                 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
7567 #else
7568                 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
7569 #endif /* LINUX_VERSION >= VERSION(3,4,0) || WL_COMPAT_WIRELESS */
7570         } else if (event == WLC_E_DISASSOC_IND) {
7571 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WL_COMPAT_WIRELESS)
7572                 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
7573 #else
7574                 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
7575 #endif /* LINUX_VERSION >= VERSION(3,4,0) || WL_COMPAT_WIRELESS */
7576         } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
7577 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WL_COMPAT_WIRELESS)
7578                 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
7579 #else
7580                 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
7581 #endif /* LINUX_VERSION >= VERSION(3,4,0) || WL_COMPAT_WIRELESS */
7582         }
7583
7584 exit:
7585         if (isfree)
7586                 kfree(mgmt_frame);
7587         if (body)
7588                 kfree(body);
7589 #else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
7590         sinfo.filled = 0;
7591         if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
7592                 reason == DOT11_SC_SUCCESS) {
7593                 sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
7594                 if (!data) {
7595                         WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
7596                         return -EINVAL;
7597                 }
7598                 sinfo.assoc_req_ies = data;
7599                 sinfo.assoc_req_ies_len = len;
7600                 printk("%s: connected device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
7601                 cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
7602         } else if (event == WLC_E_DISASSOC_IND) {
7603                 printk("%s: disassociated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
7604                 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
7605         } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
7606                 printk("%s: deauthenticated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
7607                 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
7608         }
7609 #endif /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
7610         return err;
7611 }
7612
7613 static s32
7614 wl_get_auth_assoc_status(struct wl_priv *wl, struct net_device *ndev,
7615         const wl_event_msg_t *e)
7616 {
7617         u32 reason = ntoh32(e->reason);
7618         u32 event = ntoh32(e->event_type);
7619         struct wl_security *sec = wl_read_prof(wl, ndev, WL_PROF_SEC);
7620         WL_DBG(("event type : %d, reason : %d\n", event, reason));
7621         if (sec) {
7622                 switch (event) {
7623                 case WLC_E_ASSOC:
7624                 case WLC_E_AUTH:
7625                                 sec->auth_assoc_res_status = reason;
7626                 default:
7627                         break;
7628                 }
7629         } else
7630                 WL_ERR(("sec is NULL\n"));
7631         return 0;
7632 }
7633
7634 static s32
7635 wl_notify_connect_status_ibss(struct wl_priv *wl, struct net_device *ndev,
7636         const wl_event_msg_t *e, void *data)
7637 {
7638         s32 err = 0;
7639         u32 event = ntoh32(e->event_type);
7640         u16 flags = ntoh16(e->flags);
7641         u32 status =  ntoh32(e->status);
7642         bool active;
7643
7644         if (event == WLC_E_JOIN) {
7645                 WL_DBG(("joined in IBSS network\n"));
7646         }
7647         if (event == WLC_E_START) {
7648                 WL_DBG(("started IBSS network\n"));
7649         }
7650         if (event == WLC_E_JOIN || event == WLC_E_START ||
7651                 (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
7652                 if (wl_get_drv_status(wl, CONNECTED, ndev)) {
7653                         /* ROAM or Redundant */
7654                         u8 *cur_bssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7655                         if (memcmp(cur_bssid, &e->addr, ETHER_ADDR_LEN) == 0) {
7656                                 WL_DBG(("IBSS connected event from same BSSID("
7657                                         MACDBG "), ignore it\n", MAC2STRDBG(cur_bssid)));
7658                                 return err;
7659                         }
7660                         WL_INFO(("IBSS BSSID is changed from " MACDBG " to " MACDBG "\n",
7661                                 MAC2STRDBG(cur_bssid), MAC2STRDBG((u8 *)&e->addr)));
7662                         wl_get_assoc_ies(wl, ndev);
7663                         wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7664                         wl_update_bss_info(wl, ndev);
7665                         cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL);
7666                 }
7667                 else {
7668                         /* New connection */
7669                         WL_INFO(("IBSS connected to " MACDBG "\n", MAC2STRDBG((u8 *)&e->addr)));
7670                         wl_link_up(wl);
7671                         wl_get_assoc_ies(wl, ndev);
7672                         wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7673                         wl_update_bss_info(wl, ndev);
7674                         cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL);
7675                         wl_set_drv_status(wl, CONNECTED, ndev);
7676                         active = true;
7677                         wl_update_prof(wl, ndev, NULL, (void *)&active, WL_PROF_ACT);
7678                 }
7679         } else if ((event == WLC_E_LINK && !(flags & WLC_EVENT_MSG_LINK)) ||
7680                 event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
7681                 wl_clr_drv_status(wl, CONNECTED, ndev);
7682                 wl_link_down(wl);
7683                 wl_init_prof(wl, ndev);
7684         }
7685         else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
7686                 WL_DBG(("no action - join fail (IBSS mode)\n"));
7687         }
7688         else {
7689                 WL_DBG(("no action (IBSS mode)\n"));
7690         }
7691         return err;
7692 }
7693
7694 static s32
7695 wl_notify_connect_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7696         const wl_event_msg_t *e, void *data)
7697 {
7698         bool act;
7699         struct net_device *ndev = NULL;
7700         s32 err = 0;
7701         u32 event = ntoh32(e->event_type);
7702
7703         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7704
7705         if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) {
7706                 err = wl_notify_connect_status_ap(wl, ndev, e, data);
7707         } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS) {
7708                 err = wl_notify_connect_status_ibss(wl, ndev, e, data);
7709         } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_BSS) {
7710                 WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
7711                         ntoh32(e->event_type), ntoh32(e->status), ndev));
7712                 if (event == WLC_E_ASSOC || event == WLC_E_AUTH) {
7713                         wl_get_auth_assoc_status(wl, ndev, e);
7714                         return 0;
7715                 }
7716                 if (wl_is_linkup(wl, e, ndev)) {
7717                         wl_link_up(wl);
7718                         act = true;
7719                         if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) {
7720                                         printk("wl_bss_connect_done succeeded with " MACDBG "\n",
7721                                                 MAC2STRDBG((u8*)(&e->addr)));
7722                                         wl_bss_connect_done(wl, ndev, e, data, true);
7723                                         dhd_conf_set_phyoclscdenable((dhd_pub_t *)wl->pub);
7724                                         WL_DBG(("joined in BSS network \"%s\"\n",
7725                                         ((struct wlc_ssid *)
7726                                          wl_read_prof(wl, ndev, WL_PROF_SSID))->SSID));
7727                         }
7728                         wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT);
7729                         wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7730                         dhd_conf_set_wme((dhd_pub_t *)wl->pub);
7731                 } else if (wl_is_linkdown(wl, e)) {
7732                         if (wl->scan_request) {
7733                                 if (wl->escan_on) {
7734                                         wl_notify_escan_complete(wl, ndev, true, true);
7735                                 } else {
7736                                         del_timer_sync(&wl->scan_timeout);
7737                                         wl_iscan_aborted(wl);
7738                                 }
7739                         }
7740                         if (wl_get_drv_status(wl, CONNECTED, ndev)) {
7741                                 scb_val_t scbval;
7742                                 u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7743                                 s32 reason = 0;
7744                                 if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND)
7745                                         reason = ntoh32(e->reason);
7746                                 /* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */
7747                                 reason = (reason == WLAN_REASON_UNSPECIFIED)? 0 : reason;
7748
7749                                 printk("link down if %s may call cfg80211_disconnected. "
7750                                         "event : %d, reason=%d from " MACDBG "\n",
7751                                         ndev->name, event, ntoh32(e->reason),
7752                                         MAC2STRDBG((u8*)(&e->addr)));
7753                                 if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) {
7754                                         WL_ERR(("BSSID of event is not the connected BSSID"
7755                                                 "(ignore it) cur: " MACDBG " event: " MACDBG"\n",
7756                                                 MAC2STRDBG(curbssid), MAC2STRDBG((u8*)(&e->addr))));
7757                                         return 0;
7758                                 }
7759                                 if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) {
7760                                         // terence 20130703: Fix for wrong group_capab (timing issue)
7761                                         p2p_disconnected = 1;
7762                                         memcpy(&p2p_disconnected_bssid, curbssid, ETHER_ADDR_LEN);
7763                                 }
7764                                 wl_clr_drv_status(wl, CONNECTED, ndev);
7765                                 if (! wl_get_drv_status(wl, DISCONNECTING, ndev)) {
7766                                         /* To make sure disconnect, explictly send dissassoc
7767                                         *  for BSSID 00:00:00:00:00:00 issue
7768                                         */
7769                                         scbval.val = WLAN_REASON_DEAUTH_LEAVING;
7770
7771                                         memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
7772                                         scbval.val = htod32(scbval.val);
7773                                         err = wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
7774                                                 sizeof(scb_val_t), true);
7775                                         if (err < 0) {
7776                                                 WL_ERR(("WLC_DISASSOC error %d\n", err));
7777                                                 err = 0;
7778                                         }
7779                                         cfg80211_disconnected(ndev, reason, NULL, 0, GFP_KERNEL);
7780                                         wl_link_down(wl);
7781                                         wl_init_prof(wl, ndev);
7782                                 }
7783                         }
7784                         else if (wl_get_drv_status(wl, CONNECTING, ndev)) {
7785
7786                                 printk("link down, during connecting\n");
7787 #ifdef ESCAN_RESULT_PATCH
7788                                 if ((memcmp(connect_req_bssid, broad_bssid, ETHER_ADDR_LEN) == 0) ||
7789                                         (memcmp(&e->addr, broad_bssid, ETHER_ADDR_LEN) == 0) ||
7790                                         (memcmp(&e->addr, connect_req_bssid, ETHER_ADDR_LEN) == 0))
7791                                         /* In case this event comes while associating another AP */
7792 #endif /* ESCAN_RESULT_PATCH */
7793                                         wl_bss_connect_done(wl, ndev, e, data, false);
7794                         }
7795                         wl_clr_drv_status(wl, DISCONNECTING, ndev);
7796
7797                         /* if link down, bsscfg is diabled */
7798                         if (ndev != wl_to_prmry_ndev(wl))
7799                                 complete(&wl->iface_disable);
7800
7801                 } else if (wl_is_nonetwork(wl, e)) {
7802                         printk("connect failed event=%d e->status %d e->reason %d \n",
7803                                 event, (int)ntoh32(e->status), (int)ntoh32(e->reason));
7804                         /* Clean up any pending scan request */
7805                         if (wl->scan_request) {
7806                                 if (wl->escan_on) {
7807                                         wl_notify_escan_complete(wl, ndev, true, true);
7808                                 } else {
7809                                         del_timer_sync(&wl->scan_timeout);
7810                                         wl_iscan_aborted(wl);
7811                                 }
7812                         }
7813                         if (wl_get_drv_status(wl, CONNECTING, ndev))
7814                                 wl_bss_connect_done(wl, ndev, e, data, false);
7815                 } else {
7816                         printk("%s nothing\n", __FUNCTION__);
7817                 }
7818         } else {
7819                 WL_ERR(("Invalid ndev status %d\n", wl_get_mode_by_netdev(wl, ndev)));
7820         }
7821         return err;
7822 }
7823
7824 static s32
7825 wl_notify_roaming_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7826         const wl_event_msg_t *e, void *data)
7827 {
7828         bool act;
7829         struct net_device *ndev = NULL;
7830         s32 err = 0;
7831         u32 event = be32_to_cpu(e->event_type);
7832         u32 status = be32_to_cpu(e->status);
7833
7834         WL_DBG(("Enter \n"));
7835
7836         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7837
7838         if (event == WLC_E_ROAM && status == WLC_E_STATUS_SUCCESS) {
7839                 if (wl_get_drv_status(wl, CONNECTED, ndev))
7840                         wl_bss_roaming_done(wl, ndev, e, data);
7841                 else
7842                         wl_bss_connect_done(wl, ndev, e, data, true);
7843                 act = true;
7844                 wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT);
7845                 wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7846                 dhd_conf_set_wme((dhd_pub_t *)wl->pub);
7847         }
7848         return err;
7849 }
7850
7851 static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev)
7852 {
7853         wl_assoc_info_t assoc_info;
7854         struct wl_connect_info *conn_info = wl_to_conn(wl);
7855         s32 err = 0;
7856
7857         WL_DBG(("Enter \n"));
7858         err = wldev_iovar_getbuf(ndev, "assoc_info", NULL, 0, wl->extra_buf,
7859                 WL_ASSOC_INFO_MAX, NULL);
7860         if (unlikely(err)) {
7861                 WL_ERR(("could not get assoc info (%d)\n", err));
7862                 return err;
7863         }
7864         memcpy(&assoc_info, wl->extra_buf, sizeof(wl_assoc_info_t));
7865         assoc_info.req_len = htod32(assoc_info.req_len);
7866         assoc_info.resp_len = htod32(assoc_info.resp_len);
7867         assoc_info.flags = htod32(assoc_info.flags);
7868         if (conn_info->req_ie_len) {
7869                 conn_info->req_ie_len = 0;
7870                 bzero(conn_info->req_ie, sizeof(conn_info->req_ie));
7871         }
7872         if (conn_info->resp_ie_len) {
7873                 conn_info->resp_ie_len = 0;
7874                 bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie));
7875         }
7876         if (assoc_info.req_len) {
7877                 err = wldev_iovar_getbuf(ndev, "assoc_req_ies", NULL, 0, wl->extra_buf,
7878                         WL_ASSOC_INFO_MAX, NULL);
7879                 if (unlikely(err)) {
7880                         WL_ERR(("could not get assoc req (%d)\n", err));
7881                         return err;
7882                 }
7883                 conn_info->req_ie_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
7884                 if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
7885                         conn_info->req_ie_len -= ETHER_ADDR_LEN;
7886                 }
7887                 if (conn_info->req_ie_len <= MAX_REQ_LINE)
7888                         memcpy(conn_info->req_ie, wl->extra_buf, conn_info->req_ie_len);
7889                 else {
7890                         WL_ERR(("IE size %d above max %d size \n",
7891                                 conn_info->req_ie_len, MAX_REQ_LINE));
7892                         return err;
7893                 }
7894         } else {
7895                 conn_info->req_ie_len = 0;
7896         }
7897         if (assoc_info.resp_len) {
7898                 err = wldev_iovar_getbuf(ndev, "assoc_resp_ies", NULL, 0, wl->extra_buf,
7899                         WL_ASSOC_INFO_MAX, NULL);
7900                 if (unlikely(err)) {
7901                         WL_ERR(("could not get assoc resp (%d)\n", err));
7902                         return err;
7903                 }
7904                 conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp);
7905                 if (conn_info->resp_ie_len <= MAX_REQ_LINE)
7906                         memcpy(conn_info->resp_ie, wl->extra_buf, conn_info->resp_ie_len);
7907                 else {
7908                         WL_ERR(("IE size %d above max %d size \n",
7909                                 conn_info->resp_ie_len, MAX_REQ_LINE));
7910                         return err;
7911                 }
7912         } else {
7913                 conn_info->resp_ie_len = 0;
7914         }
7915         WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
7916                 conn_info->resp_ie_len));
7917
7918         return err;
7919 }
7920
7921 static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
7922         size_t *join_params_size)
7923 {
7924         chanspec_t chanspec = 0;
7925         if (ch != 0) {
7926                 join_params->params.chanspec_num = 1;
7927                 join_params->params.chanspec_list[0] = ch;
7928
7929                 if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
7930                         chanspec |= WL_CHANSPEC_BAND_2G;
7931                 else
7932                         chanspec |= WL_CHANSPEC_BAND_5G;
7933
7934                 chanspec |= WL_CHANSPEC_BW_20;
7935                 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
7936
7937                 *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
7938                         join_params->params.chanspec_num * sizeof(chanspec_t);
7939
7940                 join_params->params.chanspec_list[0]  &= WL_CHANSPEC_CHAN_MASK;
7941                 join_params->params.chanspec_list[0] |= chanspec;
7942                 join_params->params.chanspec_list[0] =
7943                         wl_chspec_host_to_driver(join_params->params.chanspec_list[0]);
7944
7945                 join_params->params.chanspec_num =
7946                         htod32(join_params->params.chanspec_num);
7947                 WL_DBG(("join_params->params.chanspec_list[0]= %X, %d channels\n",
7948                         join_params->params.chanspec_list[0],
7949                         join_params->params.chanspec_num));
7950         }
7951 }
7952
7953 static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev)
7954 {
7955         struct cfg80211_bss *bss;
7956         struct wl_bss_info *bi;
7957         struct wlc_ssid *ssid;
7958         struct bcm_tlv *tim;
7959         s32 beacon_interval;
7960         s32 dtim_period;
7961         size_t ie_len;
7962         u8 *ie;
7963         u8 *curbssid;
7964         s32 err = 0;
7965         struct wiphy *wiphy;
7966
7967         wiphy = wl_to_wiphy(wl);
7968
7969         ssid = (struct wlc_ssid *)wl_read_prof(wl, ndev, WL_PROF_SSID);
7970         curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7971         bss = cfg80211_get_bss(wiphy, NULL, curbssid,
7972                 ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS,
7973                 WLAN_CAPABILITY_ESS);
7974
7975         mutex_lock(&wl->usr_sync);
7976         if (!bss) {
7977                 WL_DBG(("Could not find the AP\n"));
7978                 *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
7979                 err = wldev_ioctl(ndev, WLC_GET_BSS_INFO,
7980                         wl->extra_buf, WL_EXTRA_BUF_MAX, false);
7981                 if (unlikely(err)) {
7982                         WL_ERR(("Could not get bss info %d\n", err));
7983                         goto update_bss_info_out;
7984                 }
7985                 bi = (struct wl_bss_info *)(wl->extra_buf + 4);
7986                 if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) {
7987                         WL_ERR(("Bssid doesn't match\n"));
7988                         err = -EIO;
7989                         goto update_bss_info_out;
7990                 }
7991                 err = wl_inform_single_bss(wl, bi);
7992                 if (unlikely(err))
7993                         goto update_bss_info_out;
7994
7995                 ie = ((u8 *)bi) + bi->ie_offset;
7996                 ie_len = bi->ie_length;
7997                 beacon_interval = cpu_to_le16(bi->beacon_period);
7998         } else {
7999                 WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid));
8000 #if defined(WL_CFG80211_P2P_DEV_IF)
8001                 ie = (u8 *)bss->ies->data;
8002                 ie_len = bss->ies->len;
8003 #else
8004                 ie = bss->information_elements;
8005                 ie_len = bss->len_information_elements;
8006 #endif /* WL_CFG80211_P2P_DEV_IF */
8007                 beacon_interval = bss->beacon_interval;
8008 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
8009                 cfg80211_put_bss(wiphy, bss);
8010 #else
8011                 cfg80211_put_bss(bss);
8012 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
8013         }
8014
8015         tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
8016         if (tim) {
8017                 dtim_period = tim->data[1];
8018         } else {
8019                 /*
8020                 * active scan was done so we could not get dtim
8021                 * information out of probe response.
8022                 * so we speficially query dtim information.
8023                 */
8024                 err = wldev_ioctl(ndev, WLC_GET_DTIMPRD,
8025                         &dtim_period, sizeof(dtim_period), false);
8026                 if (unlikely(err)) {
8027                         WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
8028                         goto update_bss_info_out;
8029                 }
8030         }
8031
8032         wl_update_prof(wl, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT);
8033         wl_update_prof(wl, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
8034
8035 update_bss_info_out:
8036         if (unlikely(err)) {
8037                 WL_ERR(("Failed with error %d\n", err));
8038         }
8039         mutex_unlock(&wl->usr_sync);
8040         return err;
8041 }
8042
8043 static s32
8044 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
8045         const wl_event_msg_t *e, void *data)
8046 {
8047         struct wl_connect_info *conn_info = wl_to_conn(wl);
8048         s32 err = 0;
8049         u8 *curbssid;
8050 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)
8051         struct wl_bss_info *bss_info;
8052         struct wiphy *wiphy = wl_to_wiphy(wl);
8053         struct ieee80211_supported_band *band;
8054         struct ieee80211_channel *notify_channel = NULL;
8055         u8 *buf;
8056         u16 channel;
8057         u32 freq;
8058 #endif /* LINUX_VERSION > 2.6.39 || WL_COMPAT_WIRELESS */
8059
8060         wl_get_assoc_ies(wl, ndev);
8061         wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID);
8062         curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
8063         wl_update_bss_info(wl, ndev);
8064         wl_update_pmklist(ndev, wl->pmk_list, err);
8065
8066 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)
8067         /* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */
8068         buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
8069         if (!buf)
8070                 goto done;
8071
8072         *(__le32 *)buf = htod32(WL_EXTRA_BUF_MAX);
8073         err = wldev_ioctl(ndev, WLC_GET_BSS_INFO, buf, WL_EXTRA_BUF_MAX, false);
8074         if (err)
8075                 goto done;
8076
8077         bss_info = (struct wl_bss_info *)(buf + 4);
8078         channel = bss_info->ctl_ch ? bss_info->ctl_ch :
8079                 CHSPEC_CHANNEL(wl_chspec_driver_to_host(bss_info->chanspec));
8080         if (channel <= CH_MAX_2G_CHANNEL)
8081                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
8082         else
8083                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
8084         freq = ieee80211_channel_to_frequency(channel, band->band);
8085         notify_channel = ieee80211_get_channel(wiphy, freq);
8086 done:
8087         kfree(buf);
8088 #endif /* LINUX_VERSION > 2.6.39  || WL_COMPAT_WIRELESS */
8089
8090         printk("wl_bss_roaming_done succeeded to " MACDBG "\n",
8091                 MAC2STRDBG((u8*)(&e->addr)));
8092         dhd_conf_set_wme((dhd_pub_t *)wl->pub);
8093
8094         cfg80211_roamed(ndev,
8095 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)
8096                 notify_channel,
8097 #endif
8098                 curbssid,
8099                 conn_info->req_ie, conn_info->req_ie_len,
8100                 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
8101         WL_DBG(("Report roaming result\n"));
8102
8103         wl_set_drv_status(wl, CONNECTED, ndev);
8104
8105         return err;
8106 }
8107
8108 static s32
8109 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
8110         const wl_event_msg_t *e, void *data, bool completed)
8111 {
8112         struct wl_connect_info *conn_info = wl_to_conn(wl);
8113         struct wl_security *sec = wl_read_prof(wl, ndev, WL_PROF_SEC);
8114         s32 err = 0;
8115         u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
8116         if (!sec) {
8117                 WL_ERR(("sec is NULL\n"));
8118                 return -ENODEV;
8119         }
8120         WL_DBG((" enter\n"));
8121 #ifdef ESCAN_RESULT_PATCH
8122         if (wl_get_drv_status(wl, CONNECTED, ndev)) {
8123                 if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) {
8124                         WL_DBG((" Connected event of connected device e=%d s=%d, ignore it\n",
8125                                 ntoh32(e->event_type), ntoh32(e->status)));
8126                         return err;
8127                 }
8128         }
8129         if (memcmp(curbssid, broad_bssid, ETHER_ADDR_LEN) == 0 &&
8130                 memcmp(broad_bssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) {
8131                 WL_DBG(("copy bssid\n"));
8132                 memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN);
8133         }
8134
8135 #else
8136         if (wl->scan_request) {
8137                 wl_notify_escan_complete(wl, ndev, true, true);
8138         }
8139 #endif /* ESCAN_RESULT_PATCH */
8140         if (wl_get_drv_status(wl, CONNECTING, ndev)) {
8141                 wl_cfg80211_scan_abort(wl);
8142                 wl_clr_drv_status(wl, CONNECTING, ndev);
8143                 if (completed) {
8144                         wl_get_assoc_ies(wl, ndev);
8145                         wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID);
8146                         curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
8147                         wl_update_bss_info(wl, ndev);
8148                         wl_update_pmklist(ndev, wl->pmk_list, err);
8149                         wl_set_drv_status(wl, CONNECTED, ndev);
8150                         if (ndev != wl_to_prmry_ndev(wl)) {
8151                                 /* reinitialize completion to clear previous count */
8152                                 INIT_COMPLETION(wl->iface_disable);
8153                         }
8154                 }
8155                 cfg80211_connect_result(ndev,
8156                         curbssid,
8157                         conn_info->req_ie,
8158                         conn_info->req_ie_len,
8159                         conn_info->resp_ie,
8160                         conn_info->resp_ie_len,
8161                         completed ? WLAN_STATUS_SUCCESS :
8162                         (sec->auth_assoc_res_status) ?
8163                         sec->auth_assoc_res_status :
8164                         WLAN_STATUS_UNSPECIFIED_FAILURE,
8165                         GFP_KERNEL);
8166                 if (completed) {
8167                         WL_INFO(("Report connect result - connection succeeded\n"));
8168                         dhd_conf_set_wme((dhd_pub_t *)wl->pub);
8169                 } else
8170                         WL_ERR(("Report connect result - connection failed\n"));
8171         }
8172         return err;
8173 }
8174
8175 static s32
8176 wl_notify_mic_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
8177         const wl_event_msg_t *e, void *data)
8178 {
8179         struct net_device *ndev = NULL;
8180         u16 flags = ntoh16(e->flags);
8181         enum nl80211_key_type key_type;
8182
8183         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
8184
8185         mutex_lock(&wl->usr_sync);
8186         if (flags & WLC_EVENT_MSG_GROUP)
8187                 key_type = NL80211_KEYTYPE_GROUP;
8188         else
8189                 key_type = NL80211_KEYTYPE_PAIRWISE;
8190
8191         cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
8192                 NULL, GFP_KERNEL);
8193         mutex_unlock(&wl->usr_sync);
8194
8195         return 0;
8196 }
8197
8198 #ifdef PNO_SUPPORT
8199 static s32
8200 wl_notify_pfn_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
8201         const wl_event_msg_t *e, void *data)
8202 {
8203         struct net_device *ndev = NULL;
8204
8205         WL_ERR((">>> PNO Event\n"));
8206
8207         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
8208
8209 #ifndef WL_SCHED_SCAN
8210         mutex_lock(&wl->usr_sync);
8211         /* TODO: Use cfg80211_sched_scan_results(wiphy); */
8212         cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
8213         mutex_unlock(&wl->usr_sync);
8214 #else
8215         /* If cfg80211 scheduled scan is supported, report the pno results via sched
8216          * scan results
8217          */
8218         wl_notify_sched_scan_results(wl, ndev, e, data);
8219 #endif /* WL_SCHED_SCAN */
8220         return 0;
8221 }
8222 #endif /* PNO_SUPPORT */
8223
8224 static s32
8225 wl_notify_scan_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
8226         const wl_event_msg_t *e, void *data)
8227 {
8228         struct channel_info channel_inform;
8229         struct wl_scan_results *bss_list;
8230         struct net_device *ndev = NULL;
8231         u32 len = WL_SCAN_BUF_MAX;
8232         s32 err = 0;
8233         unsigned long flags;
8234
8235         WL_DBG(("Enter \n"));
8236         if (!wl_get_drv_status(wl, SCANNING, ndev)) {
8237                 WL_ERR(("scan is not ready \n"));
8238                 return err;
8239         }
8240         if (wl->iscan_on && wl->iscan_kickstart)
8241                 return wl_wakeup_iscan(wl_to_iscan(wl));
8242
8243         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
8244
8245         mutex_lock(&wl->usr_sync);
8246         wl_clr_drv_status(wl, SCANNING, ndev);
8247         err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
8248                 sizeof(channel_inform), false);
8249         if (unlikely(err)) {
8250                 WL_ERR(("scan busy (%d)\n", err));
8251                 goto scan_done_out;
8252         }
8253         channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
8254         if (unlikely(channel_inform.scan_channel)) {
8255
8256                 WL_DBG(("channel_inform.scan_channel (%d)\n",
8257                         channel_inform.scan_channel));
8258         }
8259         wl->bss_list = wl->scan_results;
8260         bss_list = wl->bss_list;
8261         memset(bss_list, 0, len);
8262         bss_list->buflen = htod32(len);
8263         err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, false);
8264         if (unlikely(err) && unlikely(!wl->scan_suppressed)) {
8265                 WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
8266                 err = -EINVAL;
8267                 goto scan_done_out;
8268         }
8269         bss_list->buflen = dtoh32(bss_list->buflen);
8270         bss_list->version = dtoh32(bss_list->version);
8271         bss_list->count = dtoh32(bss_list->count);
8272
8273         err = wl_inform_bss(wl);
8274
8275 scan_done_out:
8276         del_timer_sync(&wl->scan_timeout);
8277         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
8278         if (wl->scan_request) {
8279                 cfg80211_scan_done(wl->scan_request, false);
8280                 wl->scan_request = NULL;
8281         }
8282         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
8283         WL_DBG(("cfg80211_scan_done\n"));
8284         mutex_unlock(&wl->usr_sync);
8285         return err;
8286 }
8287
8288 static s32
8289 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
8290         const struct ether_addr *sa, const struct ether_addr *bssid,
8291         u8 **pheader, u32 *body_len, u8 *pbody)
8292 {
8293         struct dot11_management_header *hdr;
8294         u32 totlen = 0;
8295         s32 err = 0;
8296         u8 *offset;
8297         u32 prebody_len = *body_len;
8298         switch (fc) {
8299                 case FC_ASSOC_REQ:
8300                         /* capability , listen interval */
8301                         totlen = DOT11_ASSOC_REQ_FIXED_LEN;
8302                         *body_len += DOT11_ASSOC_REQ_FIXED_LEN;
8303                         break;
8304
8305                 case FC_REASSOC_REQ:
8306                         /* capability, listen inteval, ap address */
8307                         totlen = DOT11_REASSOC_REQ_FIXED_LEN;
8308                         *body_len += DOT11_REASSOC_REQ_FIXED_LEN;
8309                         break;
8310         }
8311         totlen += DOT11_MGMT_HDR_LEN + prebody_len;
8312         *pheader = kzalloc(totlen, GFP_KERNEL);
8313         if (*pheader == NULL) {
8314                 WL_ERR(("memory alloc failed \n"));
8315                 return -ENOMEM;
8316         }
8317         hdr = (struct dot11_management_header *) (*pheader);
8318         hdr->fc = htol16(fc);
8319         hdr->durid = 0;
8320         hdr->seq = 0;
8321         offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
8322         bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
8323         bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
8324         bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
8325         if ((pbody != NULL) && prebody_len)
8326                 bcopy((const char*)pbody, offset, prebody_len);
8327         *body_len = totlen;
8328         return err;
8329 }
8330
8331
8332 void
8333 wl_stop_wait_next_action_frame(struct wl_priv *wl)
8334 {
8335         if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) {
8336                 if (!(wl_get_p2p_status(wl, ACTION_TX_COMPLETED) ||
8337                         wl_get_p2p_status(wl, ACTION_TX_NOACK)))
8338                         wl_set_p2p_status(wl, ACTION_TX_COMPLETED);
8339
8340                 WL_DBG(("*** Wake UP ** abort actframe iovar\n"));
8341                 /* if channel is not zero, "actfame" uses off channel scan.
8342                  * So abort scan for off channel completion.
8343                  */
8344                 if (wl->af_sent_channel)
8345                         wl_cfg80211_scan_abort(wl);
8346         }
8347 #ifdef WL_CFG80211_SYNC_GON
8348         else if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN)) {
8349                 WL_DBG(("*** Wake UP ** abort listen for next af frame\n"));
8350                 /* So abort scan to cancel listen */
8351                 wl_cfg80211_scan_abort(wl);
8352         }
8353 #endif /* WL_CFG80211_SYNC_GON */
8354 }
8355
8356
8357 int wl_cfg80211_get_ioctl_version(void)
8358 {
8359         return ioctl_version;
8360 }
8361
8362 static s32
8363 wl_notify_rx_mgmt_frame(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
8364         const wl_event_msg_t *e, void *data)
8365 {
8366         struct ieee80211_supported_band *band;
8367         struct wiphy *wiphy = wl_to_wiphy(wl);
8368         struct ether_addr da;
8369         struct ether_addr bssid;
8370         bool isfree = false;
8371         s32 err = 0;
8372         s32 freq;
8373         struct net_device *ndev = NULL;
8374         wifi_p2p_pub_act_frame_t *act_frm = NULL;
8375         wifi_p2p_action_frame_t *p2p_act_frm = NULL;
8376         wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
8377         wl_event_rx_frame_data_t *rxframe =
8378                 (wl_event_rx_frame_data_t*)data;
8379         u32 event = ntoh32(e->event_type);
8380         u8 *mgmt_frame;
8381         u8 bsscfgidx = e->bsscfgidx;
8382         u32 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t);
8383         u16 channel = ((ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK));
8384
8385         memset(&bssid, 0, ETHER_ADDR_LEN);
8386
8387         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
8388
8389         if (channel <= CH_MAX_2G_CHANNEL)
8390                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
8391         else
8392                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
8393         if (!band) {
8394                 WL_DBG(("No valid band\n"));
8395                 return -EINVAL;
8396         }
8397 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
8398         freq = ieee80211_channel_to_frequency(channel);
8399         (void)band->band;
8400 #else
8401         freq = ieee80211_channel_to_frequency(channel, band->band);
8402 #endif
8403         if (event == WLC_E_ACTION_FRAME_RX) {
8404                 wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
8405                         NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync);
8406
8407                 err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
8408                 if (err < 0)
8409                          WL_ERR(("WLC_GET_BSSID error %d\n", err));
8410                 memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN);
8411                 err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid,
8412                         &mgmt_frame, &mgmt_frame_len,
8413                         (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1));
8414                 if (err < 0) {
8415                         WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n",
8416                                 mgmt_frame_len, channel, freq));
8417                         goto exit;
8418                 }
8419                 isfree = true;
8420                 if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
8421                         mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
8422                         act_frm = (wifi_p2p_pub_act_frame_t *)
8423                                         (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
8424                 } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
8425                         mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
8426                         p2p_act_frm = (wifi_p2p_action_frame_t *)
8427                                         (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
8428                         (void) p2p_act_frm;
8429                 } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
8430                         mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
8431 #ifdef WL_SDO
8432                         if (wl_get_p2p_status(wl, DISC_IN_PROGRESS)) {
8433                                 WL_ERR(("SD offload is in progress. Don't report the"
8434                                         "frame via rx_mgmt path\n"));
8435                                 goto exit;
8436                         }
8437 #endif
8438
8439                         sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)
8440                                         (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
8441                         if (sd_act_frm && wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) {
8442                                 if (wl->next_af_subtype == sd_act_frm->action) {
8443                                         WL_DBG(("We got a right next frame of SD!(%d)\n",
8444                                                 sd_act_frm->action));
8445                                         wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev);
8446
8447                                         /* Stop waiting for next AF. */
8448                                         wl_stop_wait_next_action_frame(wl);
8449                                 }
8450                         }
8451                         (void) sd_act_frm;
8452                 } else {
8453                         /*
8454                          *  if we got normal action frame and ndev is p2p0,
8455                          *  we have to change ndev from p2p0 to wlan0
8456                          */
8457 #if defined(WL_ENABLE_P2P_IF)
8458                         if (wl->p2p_net == cfgdev)
8459                                 cfgdev = wl_to_prmry_ndev(wl);
8460 #endif /* WL_ENABLE_P2P_IF */
8461
8462                         if (wl->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
8463                                 u8 action = 0;
8464                                 if (wl_get_public_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
8465                                         mgmt_frame_len - DOT11_MGMT_HDR_LEN, &action) != BCME_OK) {
8466                                         WL_DBG(("Recived action is not public action frame\n"));
8467                                 } else if (wl->next_af_subtype == action) {
8468                                         WL_DBG(("Recived action is the waiting action(%d)\n",
8469                                                 action));
8470                                         wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev);
8471
8472                                         /* Stop waiting for next AF. */
8473                                         wl_stop_wait_next_action_frame(wl);
8474                                 }
8475                         }
8476                 }
8477
8478                 if (act_frm) {
8479
8480                         if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) {
8481                                 if (wl->next_af_subtype == act_frm->subtype) {
8482                                         WL_DBG(("We got a right next frame!(%d)\n",
8483                                                 act_frm->subtype));
8484                                         wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev);
8485
8486                                         /* Stop waiting for next AF. */
8487                                         wl_stop_wait_next_action_frame(wl);
8488                                 }
8489                         }
8490                 }
8491
8492                 wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN],
8493                         mgmt_frame_len - DOT11_MGMT_HDR_LEN, channel);
8494                 /*
8495                  * After complete GO Negotiation, roll back to mpc mode
8496                  */
8497                 if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) ||
8498                         (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
8499                         wldev_iovar_setint(ndev, "mpc", 1);
8500                 }
8501                 if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) {
8502                         WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
8503                         wl_clr_p2p_status(wl, GO_NEG_PHASE);
8504                 }
8505         } else {
8506                 mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
8507
8508                 /* wpa supplicant use probe request event for restarting another GON Req.
8509                  * but it makes GON Req repetition.
8510                  * so if src addr of prb req is same as my target device,
8511                  * do not send probe request event during sending action frame.
8512                  */
8513                 if (event == WLC_E_P2P_PROBREQ_MSG) {
8514                         WL_DBG((" Event %s\n", (event == WLC_E_P2P_PROBREQ_MSG) ?
8515                                 "WLC_E_P2P_PROBREQ_MSG":"WLC_E_PROBREQ_MSG"));
8516
8517
8518                         /* Filter any P2P probe reqs arriving during the
8519                          * GO-NEG Phase
8520                          */
8521                         if (wl->p2p &&
8522                                 wl_get_p2p_status(wl, GO_NEG_PHASE)) {
8523                                 WL_DBG(("Filtering P2P probe_req while "
8524                                         "being in GO-Neg state\n"));
8525                                 return 0;
8526                         }
8527                 }
8528         }
8529
8530 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WL_COMPAT_WIRELESS)
8531         cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
8532 #else
8533         cfg80211_rx_mgmt(cfgdev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
8534 #endif /* LINUX_VERSION >= VERSION(3, 4, 0) || WL_COMPAT_WIRELESS */
8535
8536         WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n",
8537                 mgmt_frame_len, ntoh32(e->datalen), channel, freq));
8538 exit:
8539         if (isfree)
8540                 kfree(mgmt_frame);
8541         return 0;
8542 }
8543
8544 #ifdef WL_SCHED_SCAN
8545 /* If target scan is not reliable, set the below define to "1" to do a
8546  * full escan
8547  */
8548 #define FULL_ESCAN_ON_PFN_NET_FOUND             0
8549 static s32
8550 wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev,
8551         const wl_event_msg_t *e, void *data)
8552 {
8553         wl_pfn_net_info_t *netinfo, *pnetinfo;
8554         struct wiphy *wiphy     = wl_to_wiphy(wl);
8555         int err = 0;
8556         struct cfg80211_scan_request *request = NULL;
8557         struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
8558         struct ieee80211_channel *channel = NULL;
8559         int channel_req = 0;
8560         int band = 0;
8561         struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data;
8562         int n_pfn_results = pfn_result->count;
8563
8564         WL_DBG(("Enter\n"));
8565
8566         if (e->event_type == WLC_E_PFN_NET_LOST) {
8567                 WL_PNO(("PFN NET LOST event. Do Nothing \n"));
8568                 return 0;
8569         }
8570         WL_PNO((">>> PFN NET FOUND event. count:%d \n", n_pfn_results));
8571         if (n_pfn_results > 0) {
8572                 int i;
8573
8574                 if (n_pfn_results > MAX_PFN_LIST_COUNT)
8575                         n_pfn_results = MAX_PFN_LIST_COUNT;
8576                 pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t)
8577                                 - sizeof(wl_pfn_net_info_t));
8578
8579                 memset(&ssid, 0x00, sizeof(ssid));
8580
8581                 request = kzalloc(sizeof(*request)
8582                         + sizeof(*request->channels) * n_pfn_results,
8583                         GFP_KERNEL);
8584                 channel = (struct ieee80211_channel *)kzalloc(
8585                         (sizeof(struct ieee80211_channel) * n_pfn_results),
8586                         GFP_KERNEL);
8587                 if (!request || !channel) {
8588                         WL_ERR(("No memory"));
8589                         err = -ENOMEM;
8590                         goto out_err;
8591                 }
8592
8593                 request->wiphy = wiphy;
8594
8595                 for (i = 0; i < n_pfn_results; i++) {
8596                         netinfo = &pnetinfo[i];
8597                         if (!netinfo) {
8598                                 WL_ERR(("Invalid netinfo ptr. index:%d", i));
8599                                 err = -EINVAL;
8600                                 goto out_err;
8601                         }
8602                         WL_PNO((">>> SSID:%s Channel:%d \n",
8603                                 netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel));
8604                         /* PFN result doesn't have all the info which are required by the supplicant
8605                          * (For e.g IEs) Do a target Escan so that sched scan results are reported
8606                          * via wl_inform_single_bss in the required format. Escan does require the
8607                          * scan request in the form of cfg80211_scan_request. For timebeing, create
8608                          * cfg80211_scan_request one out of the received PNO event.
8609                          */
8610                         memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID,
8611                                 netinfo->pfnsubnet.SSID_len);
8612                         ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len;
8613                         request->n_ssids++;
8614
8615                         channel_req = netinfo->pfnsubnet.channel;
8616                         band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
8617                                 : NL80211_BAND_5GHZ;
8618                         channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band);
8619                         channel[i].band = band;
8620                         channel[i].flags |= IEEE80211_CHAN_NO_HT40;
8621                         request->channels[i] = &channel[i];
8622                         request->n_channels++;
8623                 }
8624
8625                 /* assign parsed ssid array */
8626                 if (request->n_ssids)
8627                         request->ssids = &ssid[0];
8628
8629                 if (wl_get_drv_status_all(wl, SCANNING)) {
8630                         /* Abort any on-going scan */
8631                         wl_notify_escan_complete(wl, ndev, true, true);
8632                 }
8633
8634                 if (wl_get_p2p_status(wl, DISCOVERY_ON)) {
8635                         WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
8636                         err = wl_cfgp2p_discover_enable_search(wl, false);
8637                         if (unlikely(err)) {
8638                                 wl_clr_drv_status(wl, SCANNING, ndev);
8639                                 goto out_err;
8640                         }
8641                 }
8642
8643                 wl_set_drv_status(wl, SCANNING, ndev);
8644 #if FULL_ESCAN_ON_PFN_NET_FOUND
8645                 WL_PNO((">>> Doing Full ESCAN on PNO event\n"));
8646                 err = wl_do_escan(wl, wiphy, ndev, NULL);
8647 #else
8648                 WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
8649                 err = wl_do_escan(wl, wiphy, ndev, request);
8650 #endif
8651                 if (err) {
8652                         wl_clr_drv_status(wl, SCANNING, ndev);
8653                         goto out_err;
8654                 }
8655                 wl->sched_scan_running = TRUE;
8656         }
8657         else {
8658                 WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
8659         }
8660 out_err:
8661         if (request)
8662                 kfree(request);
8663         if (channel)
8664                 kfree(channel);
8665         return err;
8666 }
8667 #endif /* WL_SCHED_SCAN */
8668
8669 static void wl_init_conf(struct wl_conf *conf)
8670 {
8671         WL_DBG(("Enter \n"));
8672         conf->frag_threshold = (u32)-1;
8673         conf->rts_threshold = (u32)-1;
8674         conf->retry_short = (u32)-1;
8675         conf->retry_long = (u32)-1;
8676         conf->tx_power = -1;
8677 }
8678
8679 static void wl_init_prof(struct wl_priv *wl, struct net_device *ndev)
8680 {
8681         unsigned long flags;
8682         struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
8683
8684         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
8685         memset(profile, 0, sizeof(struct wl_profile));
8686         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
8687 }
8688
8689 static void wl_init_event_handler(struct wl_priv *wl)
8690 {
8691         memset(wl->evt_handler, 0, sizeof(wl->evt_handler));
8692
8693         wl->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
8694         wl->evt_handler[WLC_E_AUTH] = wl_notify_connect_status;
8695         wl->evt_handler[WLC_E_ASSOC] = wl_notify_connect_status;
8696         wl->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
8697         wl->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
8698         wl->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
8699         wl->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
8700         wl->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
8701         wl->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
8702         wl->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;
8703         wl->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
8704         wl->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;
8705         wl->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;
8706         wl->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
8707         wl->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
8708         wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
8709         wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
8710         wl->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
8711         wl->evt_handler[WLC_E_JOIN] = wl_notify_connect_status;
8712         wl->evt_handler[WLC_E_START] = wl_notify_connect_status;
8713 #ifdef PNO_SUPPORT
8714         wl->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status;
8715 #endif /* PNO_SUPPORT */
8716 #ifdef WL_SDO
8717         wl->evt_handler[WLC_E_SERVICE_FOUND] = wl_svc_resp_handler;
8718         wl->evt_handler[WLC_E_P2PO_ADD_DEVICE] = wl_notify_device_discovery;
8719         wl->evt_handler[WLC_E_P2PO_DEL_DEVICE] = wl_notify_device_discovery;
8720 #endif
8721 #ifdef WLTDLS
8722         wl->evt_handler[WLC_E_TDLS_PEER_EVENT] = wl_tdls_event_handler;
8723 #endif /* WLTDLS */
8724 }
8725
8726 #if defined(STATIC_WL_PRIV_STRUCT)
8727 static void
8728 wl_init_escan_result_buf(struct wl_priv *wl)
8729 {
8730         wl->escan_info.escan_buf = dhd_os_prealloc(NULL, DHD_PREALLOC_WIPHY_ESCAN0, 0);
8731         bzero(wl->escan_info.escan_buf, ESCAN_BUF_SIZE);
8732 }
8733
8734 static void
8735 wl_deinit_escan_result_buf(struct wl_priv *wl)
8736 {
8737         wl->escan_info.escan_buf = NULL;
8738
8739 }
8740 #endif /* STATIC_WL_PRIV_STRUCT */
8741
8742 static s32 wl_init_priv_mem(struct wl_priv *wl)
8743 {
8744         WL_DBG(("Enter \n"));
8745         wl->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
8746         if (unlikely(!wl->scan_results)) {
8747                 WL_ERR(("Scan results alloc failed\n"));
8748                 goto init_priv_mem_out;
8749         }
8750         wl->conf = (void *)kzalloc(sizeof(*wl->conf), GFP_KERNEL);
8751         if (unlikely(!wl->conf)) {
8752                 WL_ERR(("wl_conf alloc failed\n"));
8753                 goto init_priv_mem_out;
8754         }
8755         wl->scan_req_int =
8756             (void *)kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL);
8757         if (unlikely(!wl->scan_req_int)) {
8758                 WL_ERR(("Scan req alloc failed\n"));
8759                 goto init_priv_mem_out;
8760         }
8761         wl->ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
8762         if (unlikely(!wl->ioctl_buf)) {
8763                 WL_ERR(("Ioctl buf alloc failed\n"));
8764                 goto init_priv_mem_out;
8765         }
8766         wl->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
8767         if (unlikely(!wl->escan_ioctl_buf)) {
8768                 WL_ERR(("Ioctl buf alloc failed\n"));
8769                 goto init_priv_mem_out;
8770         }
8771         wl->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
8772         if (unlikely(!wl->extra_buf)) {
8773                 WL_ERR(("Extra buf alloc failed\n"));
8774                 goto init_priv_mem_out;
8775         }
8776         wl->iscan = (void *)kzalloc(sizeof(*wl->iscan), GFP_KERNEL);
8777         if (unlikely(!wl->iscan)) {
8778                 WL_ERR(("Iscan buf alloc failed\n"));
8779                 goto init_priv_mem_out;
8780         }
8781         wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL);
8782         if (unlikely(!wl->pmk_list)) {
8783                 WL_ERR(("pmk list alloc failed\n"));
8784                 goto init_priv_mem_out;
8785         }
8786         wl->sta_info = (void *)kzalloc(sizeof(*wl->sta_info), GFP_KERNEL);
8787         if (unlikely(!wl->sta_info)) {
8788                 WL_ERR(("sta info  alloc failed\n"));
8789                 goto init_priv_mem_out;
8790         }
8791
8792 #if defined(STATIC_WL_PRIV_STRUCT)
8793         wl->conn_info = (void *)kzalloc(sizeof(*wl->conn_info), GFP_KERNEL);
8794         if (unlikely(!wl->conn_info)) {
8795                 WL_ERR(("wl->conn_info  alloc failed\n"));
8796                 goto init_priv_mem_out;
8797         }
8798         wl->ie = (void *)kzalloc(sizeof(*wl->ie), GFP_KERNEL);
8799         if (unlikely(!wl->ie)) {
8800                 WL_ERR(("wl->ie  alloc failed\n"));
8801                 goto init_priv_mem_out;
8802         }
8803         wl_init_escan_result_buf(wl);
8804 #endif /* STATIC_WL_PRIV_STRUCT */
8805         wl->afx_hdl = (void *)kzalloc(sizeof(*wl->afx_hdl), GFP_KERNEL);
8806         if (unlikely(!wl->afx_hdl)) {
8807                 WL_ERR(("afx hdl  alloc failed\n"));
8808                 goto init_priv_mem_out;
8809         } else {
8810                 init_completion(&wl->act_frm_scan);
8811                 init_completion(&wl->wait_next_af);
8812
8813                 INIT_WORK(&wl->afx_hdl->work, wl_cfg80211_afx_handler);
8814         }
8815         return 0;
8816
8817 init_priv_mem_out:
8818         wl_deinit_priv_mem(wl);
8819
8820         return -ENOMEM;
8821 }
8822
8823 static void wl_deinit_priv_mem(struct wl_priv *wl)
8824 {
8825         kfree(wl->scan_results);
8826         wl->scan_results = NULL;
8827         kfree(wl->conf);
8828         wl->conf = NULL;
8829         kfree(wl->scan_req_int);
8830         wl->scan_req_int = NULL;
8831         kfree(wl->ioctl_buf);
8832         wl->ioctl_buf = NULL;
8833         kfree(wl->escan_ioctl_buf);
8834         wl->escan_ioctl_buf = NULL;
8835         kfree(wl->extra_buf);
8836         wl->extra_buf = NULL;
8837         kfree(wl->iscan);
8838         wl->iscan = NULL;
8839         kfree(wl->pmk_list);
8840         wl->pmk_list = NULL;
8841         kfree(wl->sta_info);
8842         wl->sta_info = NULL;
8843 #if defined(STATIC_WL_PRIV_STRUCT)
8844         kfree(wl->conn_info);
8845         wl->conn_info = NULL;
8846         kfree(wl->ie);
8847         wl->ie = NULL;
8848         wl_deinit_escan_result_buf(wl);
8849 #endif /* STATIC_WL_PRIV_STRUCT */
8850         if (wl->afx_hdl) {
8851                 cancel_work_sync(&wl->afx_hdl->work);
8852                 kfree(wl->afx_hdl);
8853                 wl->afx_hdl = NULL;
8854         }
8855
8856         if (wl->ap_info) {
8857                 kfree(wl->ap_info->wpa_ie);
8858                 kfree(wl->ap_info->rsn_ie);
8859                 kfree(wl->ap_info->wps_ie);
8860                 kfree(wl->ap_info);
8861                 wl->ap_info = NULL;
8862         }
8863 }
8864
8865 static s32 wl_create_event_handler(struct wl_priv *wl)
8866 {
8867         int ret = 0;
8868         WL_DBG(("Enter \n"));
8869
8870         /* Do not use DHD in cfg driver */
8871         wl->event_tsk.thr_pid = -1;
8872
8873         PROC_START(wl_event_handler, wl, &wl->event_tsk, 0, "wl_event_handler");
8874         if (wl->event_tsk.thr_pid < 0)
8875                 ret = -ENOMEM;
8876         return ret;
8877 }
8878
8879 static void wl_destroy_event_handler(struct wl_priv *wl)
8880 {
8881         if (wl->event_tsk.thr_pid >= 0)
8882                 PROC_STOP(&wl->event_tsk);
8883 }
8884
8885 static void wl_term_iscan(struct wl_priv *wl)
8886 {
8887         struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
8888         WL_TRACE(("In\n"));
8889         if (wl->iscan_on && iscan->tsk) {
8890                 iscan->state = WL_ISCAN_STATE_IDLE;
8891                 WL_INFO(("SIGTERM\n"));
8892                 send_sig(SIGTERM, iscan->tsk, 1);
8893                 WL_DBG(("kthread_stop\n"));
8894                 kthread_stop(iscan->tsk);
8895                 iscan->tsk = NULL;
8896         }
8897 }
8898
8899 static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted)
8900 {
8901         struct wl_priv *wl = iscan_to_wl(iscan);
8902         struct net_device *ndev = wl_to_prmry_ndev(wl);
8903         unsigned long flags;
8904
8905         WL_DBG(("Enter \n"));
8906         if (!wl_get_drv_status(wl, SCANNING, ndev)) {
8907                 wl_clr_drv_status(wl, SCANNING, ndev);
8908                 WL_ERR(("Scan complete while device not scanning\n"));
8909                 return;
8910         }
8911         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
8912         wl_clr_drv_status(wl, SCANNING, ndev);
8913         if (likely(wl->scan_request)) {
8914                 cfg80211_scan_done(wl->scan_request, aborted);
8915                 wl->scan_request = NULL;
8916         }
8917         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
8918         wl->iscan_kickstart = false;
8919 }
8920
8921 static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan)
8922 {
8923         if (likely(iscan->state != WL_ISCAN_STATE_IDLE)) {
8924                 WL_DBG(("wake up iscan\n"));
8925                 up(&iscan->sync);
8926                 return 0;
8927         }
8928
8929         return -EIO;
8930 }
8931
8932 static s32
8933 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
8934         struct wl_scan_results **bss_list)
8935 {
8936         struct wl_iscan_results list;
8937         struct wl_scan_results *results;
8938         struct wl_iscan_results *list_buf;
8939         s32 err = 0;
8940
8941         WL_DBG(("Enter \n"));
8942         memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
8943         list_buf = (struct wl_iscan_results *)iscan->scan_buf;
8944         results = &list_buf->results;
8945         results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
8946         results->version = 0;
8947         results->count = 0;
8948
8949         memset(&list, 0, sizeof(list));
8950         list.results.buflen = htod32(WL_ISCAN_BUF_MAX);
8951         err = wldev_iovar_getbuf(iscan->dev, "iscanresults", &list,
8952                 WL_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf,
8953                 WL_ISCAN_BUF_MAX, NULL);
8954         if (unlikely(err)) {
8955                 WL_ERR(("error (%d)\n", err));
8956                 return err;
8957         }
8958         results->buflen = dtoh32(results->buflen);
8959         results->version = dtoh32(results->version);
8960         results->count = dtoh32(results->count);
8961         WL_DBG(("results->count = %d\n", results->count));
8962         WL_DBG(("results->buflen = %d\n", results->buflen));
8963         *status = dtoh32(list_buf->status);
8964         *bss_list = results;
8965
8966         return err;
8967 }
8968
8969 static s32 wl_iscan_done(struct wl_priv *wl)
8970 {
8971         struct wl_iscan_ctrl *iscan = wl->iscan;
8972         s32 err = 0;
8973
8974         iscan->state = WL_ISCAN_STATE_IDLE;
8975         mutex_lock(&wl->usr_sync);
8976         wl_inform_bss(wl);
8977         wl_notify_iscan_complete(iscan, false);
8978         mutex_unlock(&wl->usr_sync);
8979
8980         return err;
8981 }
8982
8983 static s32 wl_iscan_pending(struct wl_priv *wl)
8984 {
8985         struct wl_iscan_ctrl *iscan = wl->iscan;
8986         s32 err = 0;
8987
8988         /* Reschedule the timer */
8989         mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms));
8990         iscan->timer_on = 1;
8991
8992         return err;
8993 }
8994
8995 static s32 wl_iscan_inprogress(struct wl_priv *wl)
8996 {
8997         struct wl_iscan_ctrl *iscan = wl->iscan;
8998         s32 err = 0;
8999
9000         mutex_lock(&wl->usr_sync);
9001         wl_inform_bss(wl);
9002         wl_run_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
9003         mutex_unlock(&wl->usr_sync);
9004         /* Reschedule the timer */
9005         mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms));
9006         iscan->timer_on = 1;
9007
9008         return err;
9009 }
9010
9011 static s32 wl_iscan_aborted(struct wl_priv *wl)
9012 {
9013         struct wl_iscan_ctrl *iscan = wl->iscan;
9014         s32 err = 0;
9015
9016         iscan->state = WL_ISCAN_STATE_IDLE;
9017         mutex_lock(&wl->usr_sync);
9018         wl_notify_iscan_complete(iscan, true);
9019         mutex_unlock(&wl->usr_sync);
9020
9021         return err;
9022 }
9023
9024 static s32 wl_iscan_thread(void *data)
9025 {
9026         struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
9027         struct wl_priv *wl = iscan_to_wl(iscan);
9028         u32 status;
9029         int err = 0;
9030
9031         allow_signal(SIGTERM);
9032         status = WL_SCAN_RESULTS_PARTIAL;
9033         while (likely(!down_interruptible(&iscan->sync))) {
9034                 if (kthread_should_stop())
9035                         break;
9036                 if (iscan->timer_on) {
9037                         del_timer_sync(&iscan->timer);
9038                         iscan->timer_on = 0;
9039                 }
9040                 mutex_lock(&wl->usr_sync);
9041                 err = wl_get_iscan_results(iscan, &status, &wl->bss_list);
9042                 if (unlikely(err)) {
9043                         status = WL_SCAN_RESULTS_ABORTED;
9044                         WL_ERR(("Abort iscan\n"));
9045                 }
9046                 mutex_unlock(&wl->usr_sync);
9047                 iscan->iscan_handler[status] (wl);
9048         }
9049         if (iscan->timer_on) {
9050                 del_timer_sync(&iscan->timer);
9051                 iscan->timer_on = 0;
9052         }
9053         WL_DBG(("was terminated\n"));
9054
9055         return 0;
9056 }
9057
9058 static void wl_scan_timeout(unsigned long data)
9059 {
9060         wl_event_msg_t msg;
9061         struct wl_priv *wl = (struct wl_priv *)data;
9062         struct net_device *ndev = wl_to_prmry_ndev(wl);
9063
9064         if (!(wl->scan_request)) {
9065                 WL_ERR(("timer expired but no scan request\n"));
9066                 return;
9067         }
9068         bzero(&msg, sizeof(wl_event_msg_t));
9069         WL_ERR(("timer expired\n"));
9070         if (wl->escan_on) {
9071                 msg.event_type = hton32(WLC_E_ESCAN_RESULT);
9072                 msg.status = hton32(WLC_E_STATUS_TIMEOUT);
9073                 msg.reason = 0xFFFFFFFF;
9074                 wl_cfg80211_event(wl_to_prmry_ndev(wl), &msg, NULL);
9075         } else {
9076                 /* Need to check it try to access SDIO */
9077                 WL_ERR(("SCAN Timeout(ISCAN)\n"));
9078                 wl_notify_iscan_complete(wl_to_iscan(wl), true);
9079         }
9080         // terence 20130729: work around to fix out of memory in firmware
9081         WL_ERR(("Send hang event\n"));
9082         net_os_send_hang_message(ndev);
9083 }
9084
9085 static void wl_iscan_timer(unsigned long data)
9086 {
9087         struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
9088
9089         if (iscan) {
9090                 iscan->timer_on = 0;
9091                 WL_DBG(("timer expired\n"));
9092                 wl_wakeup_iscan(iscan);
9093         }
9094 }
9095
9096 static s32 wl_invoke_iscan(struct wl_priv *wl)
9097 {
9098         struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
9099         int err = 0;
9100
9101         if (wl->iscan_on && !iscan->tsk) {
9102                 iscan->state = WL_ISCAN_STATE_IDLE;
9103                 sema_init(&iscan->sync, 0);
9104                 iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan");
9105                 if (IS_ERR(iscan->tsk)) {
9106                         WL_ERR(("Could not create iscan thread\n"));
9107                         iscan->tsk = NULL;
9108                         return -ENOMEM;
9109                 }
9110         }
9111
9112         return err;
9113 }
9114
9115 static void wl_init_iscan_handler(struct wl_iscan_ctrl *iscan)
9116 {
9117         memset(iscan->iscan_handler, 0, sizeof(iscan->iscan_handler));
9118         iscan->iscan_handler[WL_SCAN_RESULTS_SUCCESS] = wl_iscan_done;
9119         iscan->iscan_handler[WL_SCAN_RESULTS_PARTIAL] = wl_iscan_inprogress;
9120         iscan->iscan_handler[WL_SCAN_RESULTS_PENDING] = wl_iscan_pending;
9121         iscan->iscan_handler[WL_SCAN_RESULTS_ABORTED] = wl_iscan_aborted;
9122         iscan->iscan_handler[WL_SCAN_RESULTS_NO_MEM] = wl_iscan_aborted;
9123 }
9124
9125 static s32
9126 wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
9127         unsigned long state,
9128         void *ndev)
9129 {
9130         struct net_device *dev = ndev;
9131         struct wireless_dev *wdev = dev->ieee80211_ptr;
9132         struct wl_priv *wl = wlcfg_drv_priv;
9133         int refcnt = 0;
9134
9135         WL_DBG(("Enter \n"));
9136         if (!wdev || !wl || dev == wl_to_prmry_ndev(wl))
9137                 return NOTIFY_DONE;
9138         switch (state) {
9139                 case NETDEV_DOWN:
9140                 {
9141                         int max_wait_timeout = 2;
9142                         int max_wait_count = 100;
9143                         unsigned long limit = jiffies + max_wait_timeout * HZ;
9144                         while (work_pending(&wdev->cleanup_work)) {
9145                                 if (refcnt%5 == 0) {
9146                                         WL_ERR(("[NETDEV_DOWN] wait for "
9147                                                 "complete of cleanup_work"
9148                                                 " (%d th)\n", refcnt));
9149                                 }
9150                                 if (!time_before(jiffies, limit)) {
9151                                         WL_ERR(("[NETDEV_DOWN] cleanup_work"
9152                                                 " of CFG80211 is not"
9153                                                 " completed in %d sec\n",
9154                                                 max_wait_timeout));
9155                                         break;
9156                                 }
9157                                 if (refcnt >= max_wait_count) {
9158                                         WL_ERR(("[NETDEV_DOWN] cleanup_work"
9159                                                 " of CFG80211 is not"
9160                                                 " completed in %d loop\n",
9161                                                 max_wait_count));
9162                                         break;
9163                                 }
9164                                 set_current_state(TASK_INTERRUPTIBLE);
9165                                 schedule_timeout(100);
9166                                 set_current_state(TASK_RUNNING);
9167                                 refcnt++;
9168                         }
9169                         break;
9170                 }
9171
9172                 case NETDEV_UNREGISTER:
9173                         /* after calling list_del_rcu(&wdev->list) */
9174                         wl_dealloc_netinfo(wl, ndev);
9175                         break;
9176                 case NETDEV_GOING_DOWN:
9177                         /* At NETDEV_DOWN state, wdev_cleanup_work work will be called.
9178                         *  In front of door, the function checks
9179                         *  whether current scan is working or not.
9180                         *  If the scanning is still working, wdev_cleanup_work call WARN_ON and
9181                         *  make the scan done forcibly.
9182                         */
9183                         if (wl_get_drv_status(wl, SCANNING, dev)) {
9184                                 if (wl->escan_on) {
9185                                         wl_notify_escan_complete(wl, dev, true, true);
9186                                 }
9187                         }
9188                         break;
9189         }
9190         return NOTIFY_DONE;
9191 }
9192 static struct notifier_block wl_cfg80211_netdev_notifier = {
9193         .notifier_call = wl_cfg80211_netdev_notifier_call,
9194 };
9195
9196 static void wl_cfg80211_scan_abort(struct wl_priv *wl)
9197 {
9198         wl_scan_params_t *params = NULL;
9199         s32 params_size = 0;
9200         s32 err = BCME_OK;
9201         struct net_device *dev = wl_to_prmry_ndev(wl);
9202         if (!in_atomic()) {
9203                 /* Our scan params only need space for 1 channel and 0 ssids */
9204                 params = wl_cfg80211_scan_alloc_params(-1, 0, &params_size);
9205                 if (params == NULL) {
9206                         WL_ERR(("scan params allocation failed \n"));
9207                         err = -ENOMEM;
9208                 } else {
9209                         /* Do a scan abort to stop the driver's scan engine */
9210                         err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true);
9211                         if (err < 0) {
9212                                 WL_ERR(("scan abort  failed \n"));
9213                         }
9214                         kfree(params);
9215                 }
9216         }
9217 }
9218
9219 static s32 wl_notify_escan_complete(struct wl_priv *wl,
9220         struct net_device *ndev,
9221         bool aborted, bool fw_abort)
9222 {
9223         s32 err = BCME_OK;
9224         unsigned long flags;
9225         struct net_device *dev;
9226
9227         WL_DBG(("Enter \n"));
9228         if (!ndev) {
9229                 WL_ERR(("ndev is null\n"));
9230                 err = BCME_ERROR;
9231                 return err;
9232         }
9233
9234         if (wl->escan_info.ndev != ndev) {
9235                 WL_ERR(("ndev is different %p %p\n", wl->escan_info.ndev, ndev));
9236                 err = BCME_ERROR;
9237                 return err;
9238         }
9239
9240         if (wl->scan_request) {
9241                 dev = wl_to_prmry_ndev(wl);
9242 #if defined(WL_ENABLE_P2P_IF)
9243                 if (wl->scan_request->dev != wl->p2p_net)
9244                         dev = wl->scan_request->dev;
9245 #endif /* WL_ENABLE_P2P_IF */
9246         }
9247         else {
9248                 WL_DBG(("wl->scan_request is NULL may be internal scan."
9249                         "doing scan_abort for ndev %p primary %p",
9250                                 ndev, wl_to_prmry_ndev(wl)));
9251                 dev = ndev;
9252         }
9253         if (fw_abort && !in_atomic()) {
9254                 wl_cfg80211_scan_abort(wl);
9255         }
9256
9257         if (timer_pending(&wl->scan_timeout))
9258                 del_timer_sync(&wl->scan_timeout);
9259 #if defined(ESCAN_RESULT_PATCH)
9260         if (likely(wl->scan_request)) {
9261                 wl->bss_list = wl_escan_get_buf(wl, aborted);
9262                 wl_inform_bss(wl);
9263         }
9264 #endif /* ESCAN_RESULT_PATCH */
9265         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
9266 #ifdef WL_SCHED_SCAN
9267         if (wl->sched_scan_req && !wl->scan_request) {
9268                 WL_PNO((">>> REPORTING SCHED SCAN RESULTS \n"));
9269                 if (!aborted)
9270                         cfg80211_sched_scan_results(wl->sched_scan_req->wiphy);
9271                 wl->sched_scan_running = FALSE;
9272                 wl->sched_scan_req = NULL;
9273         }
9274 #endif /* WL_SCHED_SCAN */
9275         if (likely(wl->scan_request)) {
9276                 cfg80211_scan_done(wl->scan_request, aborted);
9277                 wl->scan_request = NULL;
9278         }
9279         if (p2p_is_on(wl))
9280                 wl_clr_p2p_status(wl, SCANNING);
9281         wl_clr_drv_status(wl, SCANNING, dev);
9282         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
9283 #ifdef WL_SDO
9284         if (wl_get_p2p_status(wl, DISC_IN_PROGRESS) && !in_atomic()) {
9285                 wl_cfg80211_resume_sdo(ndev, wl);
9286         }
9287 #endif
9288         return err;
9289 }
9290
9291 static s32 wl_escan_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
9292         const wl_event_msg_t *e, void *data)
9293 {
9294         s32 err = BCME_OK;
9295         s32 status = ntoh32(e->status);
9296         wl_bss_info_t *bi;
9297         wl_escan_result_t *escan_result;
9298         wl_bss_info_t *bss = NULL;
9299         wl_scan_results_t *list;
9300         wifi_p2p_ie_t * p2p_ie;
9301         struct net_device *ndev = NULL;
9302         u32 bi_length;
9303         u32 i;
9304         u8 *p2p_dev_addr = NULL;
9305         struct wiphy *wiphy = wl_to_wiphy(wl);
9306         u16 channel;
9307         struct ieee80211_supported_band *band;
9308
9309         WL_DBG((" enter event type : %d, status : %d \n",
9310                 ntoh32(e->event_type), ntoh32(e->status)));
9311
9312         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
9313
9314         mutex_lock(&wl->usr_sync);
9315         /* P2P SCAN is coming from primary interface */
9316         if (wl_get_p2p_status(wl, SCANNING)) {
9317                 if (wl_get_drv_status_all(wl, SENDING_ACT_FRM))
9318                         ndev = wl->afx_hdl->dev;
9319                 else
9320                         ndev = wl->escan_info.ndev;
9321
9322         }
9323         if (!ndev || !wl->escan_on ||
9324                 (!wl_get_drv_status(wl, SCANNING, ndev) &&
9325                 !wl->sched_scan_running)) {
9326                 WL_ERR(("escan is not ready ndev %p wl->escan_on %d"
9327                         " drv_status 0x%x e_type %d e_states %d\n",
9328                         ndev, wl->escan_on, wl_get_drv_status(wl, SCANNING, ndev),
9329                         ntoh32(e->event_type), ntoh32(e->status)));
9330                 goto exit;
9331         }
9332         escan_result = (wl_escan_result_t *)data;
9333
9334         if (status == WLC_E_STATUS_PARTIAL) {
9335                 WL_INFO(("WLC_E_STATUS_PARTIAL \n"));
9336                 if (!escan_result) {
9337                         WL_ERR(("Invalid escan result (NULL pointer)\n"));
9338                         goto exit;
9339                 }
9340                 if (dtoh16(escan_result->bss_count) != 1) {
9341                         WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
9342                         goto exit;
9343                 }
9344                 bi = escan_result->bss_info;
9345                 if (!bi) {
9346                         WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
9347                         goto exit;
9348                 }
9349                 bi_length = dtoh32(bi->length);
9350                 if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
9351                         WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length));
9352                         goto exit;
9353                 }
9354
9355                 /* +++++ terence 20130524: skip invalid bss */
9356                 channel =
9357                         bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
9358                 if (channel <= CH_MAX_2G_CHANNEL)
9359                         band = wiphy->bands[IEEE80211_BAND_2GHZ];
9360                 else
9361                         band = wiphy->bands[IEEE80211_BAND_5GHZ];
9362                 if (!band) {
9363                         WL_DBG(("No valid band\n"));
9364                         goto exit;
9365                 }
9366                 if (!dhd_conf_match_channel((dhd_pub_t *)wl->pub, channel))
9367                         goto exit;
9368                 /* ----- terence 20130524: skip invalid bss */
9369
9370                 if (wl_escan_check_sync_id(status, escan_result->sync_id,
9371                                 wl->escan_info.cur_sync_id) < 0)
9372                         goto exit;
9373
9374                 if (!(wl_to_wiphy(wl)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
9375                         if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
9376                                 WL_DBG(("Ignoring IBSS result\n"));
9377                                 goto exit;
9378                         }
9379                 }
9380
9381                 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9382                         p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
9383                         if (p2p_dev_addr && !memcmp(p2p_dev_addr,
9384                                 wl->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
9385                                 s32 channel = wf_chspec_ctlchan(
9386                                         wl_chspec_driver_to_host(bi->chanspec));
9387
9388                                 if ((channel > MAXCHANNEL) || (channel <= 0))
9389                                         channel = WL_INVALID;
9390                                 else
9391                                         WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
9392                                                 " channel : %d\n",
9393                                                 MAC2STRDBG(wl->afx_hdl->tx_dst_addr.octet),
9394                                                 channel));
9395
9396                                 wl_clr_p2p_status(wl, SCANNING);
9397                                 wl->afx_hdl->peer_chan = channel;
9398                                 complete(&wl->act_frm_scan);
9399                                 goto exit;
9400                         }
9401
9402                 } else {
9403                         int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
9404                         list = wl_escan_get_buf(wl, FALSE);
9405                         if (scan_req_match(wl)) {
9406 #ifdef WL_HOST_BAND_MGMT
9407                                 s32 channel = 0;
9408                                 s32 channel_band = 0;
9409 #endif /* WL_HOST_BAND_MGMT */
9410                                 /* p2p scan && allow only probe response */
9411                                 if ((wl->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
9412                                         (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
9413                                         goto exit;
9414                                 if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset,
9415                                         bi->ie_length)) == NULL) {
9416                                                 WL_INFO(("Couldn't find P2PIE in probe"
9417                                                         " response/beacon\n"));
9418                                                 goto exit;
9419                                 }
9420 #ifdef WL_HOST_BAND_MGMT
9421                                 channel = CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
9422                                 channel_band = (channel > CH_MAX_2G_CHANNEL) ?
9423                                 WLC_BAND_5G : WLC_BAND_2G;
9424
9425
9426                                 if ((wl->curr_band == WLC_BAND_5G) &&
9427                                         (channel_band == WLC_BAND_2G)) {
9428                                         /* Avoid sending the GO results in band conflict */
9429                                         if (wl_cfgp2p_retreive_p2pattrib(p2p_ie,
9430                                                 P2P_SEID_GROUP_ID) != NULL)
9431                                                 goto exit;
9432                                 }
9433 #endif /* WL_HOST_BAND_MGMT */
9434                         }
9435                         WL_SCAN(("%s("MACDBG") RSSI %d flags 0x%x length %d\n", bi->SSID,
9436                                 MAC2STRDBG(bi->BSSID.octet), bi->RSSI, bi->flags, bi->length));
9437                         for (i = 0; i < list->count; i++) {
9438                                 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
9439                                         : list->bss_info;
9440
9441                                 if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
9442                                         (CHSPEC_BAND(wl_chspec_driver_to_host(bi->chanspec))
9443                                         == CHSPEC_BAND(wl_chspec_driver_to_host(bss->chanspec))) &&
9444                                         bi->SSID_len == bss->SSID_len &&
9445                                         !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
9446
9447                                         /* do not allow beacon data to update
9448                                         *the data recd from a probe response
9449                                         */
9450                                         if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) &&
9451                                                 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
9452                                                 goto exit;
9453
9454                                         WL_SCAN(("%s("MACDBG"), i=%d prev: RSSI %d"
9455                                                 " flags 0x%x, new: RSSI %d flags 0x%x\n",
9456                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet), i,
9457                                                 bss->RSSI, bss->flags, bi->RSSI, bi->flags));
9458
9459                                         if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
9460                                                 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) {
9461                                                 /* preserve max RSSI if the measurements are
9462                                                 * both on-channel or both off-channel
9463                                                 */
9464                                                 WL_SCAN(("%s("MACDBG"), same onchan"
9465                                                 ", RSSI: prev %d new %d\n",
9466                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
9467                                                 bss->RSSI, bi->RSSI));
9468                                                 bi->RSSI = MAX(bss->RSSI, bi->RSSI);
9469                                         } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
9470                                                 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
9471                                                 /* preserve the on-channel rssi measurement
9472                                                 * if the new measurement is off channel
9473                                                 */
9474                                                 WL_SCAN(("%s("MACDBG"), prev onchan"
9475                                                 ", RSSI: prev %d new %d\n",
9476                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
9477                                                 bss->RSSI, bi->RSSI));
9478                                                 bi->RSSI = bss->RSSI;
9479                                                 bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
9480                                         }
9481                                         if (dtoh32(bss->length) != bi_length) {
9482                                                 u32 prev_len = dtoh32(bss->length);
9483
9484                                                 WL_SCAN(("bss info replacement"
9485                                                         " is occured(bcast:%d->probresp%d)\n",
9486                                                         bss->ie_length, bi->ie_length));
9487                                                 WL_SCAN(("%s("MACDBG"), replacement!(%d -> %d)\n",
9488                                                 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
9489                                                 prev_len, bi_length));
9490
9491                                                 if (list->buflen - prev_len + bi_length
9492                                                         > ESCAN_BUF_SIZE) {
9493                                                         WL_ERR(("Buffer is too small: keep the"
9494                                                                 " previous result of this AP\n"));
9495                                                         /* Only update RSSI */
9496                                                         bss->RSSI = bi->RSSI;
9497                                                         bss->flags |= (bi->flags
9498                                                                 & WL_BSS_FLAGS_RSSI_ONCHANNEL);
9499                                                         goto exit;
9500                                                 }
9501
9502                                                 if (i < list->count - 1) {
9503                                                         /* memory copy required by this case only */
9504                                                         memmove((u8 *)bss + bi_length,
9505                                                                 (u8 *)bss + prev_len,
9506                                                                 list->buflen - cur_len - prev_len);
9507                                                 }
9508                                                 list->buflen -= prev_len;
9509                                                 list->buflen += bi_length;
9510                                         }
9511                                         list->version = dtoh32(bi->version);
9512                                         memcpy((u8 *)bss, (u8 *)bi, bi_length);
9513                                         goto exit;
9514                                 }
9515                                 cur_len += dtoh32(bss->length);
9516                         }
9517                         if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
9518                                 WL_ERR(("Buffer is too small: ignoring\n"));
9519                                 goto exit;
9520                         }
9521                         if (strlen(bi->SSID) == 0) { // terence: fix for hidden SSID
9522                                 WL_SCAN(("Skip hidden SSID %pM\n", &bi->BSSID));
9523                                 goto exit;
9524                         }
9525
9526                         memcpy(&(((char *)list)[list->buflen]), bi, bi_length);
9527                         list->version = dtoh32(bi->version);
9528                         list->buflen += bi_length;
9529                         list->count++;
9530
9531                 }
9532
9533         }
9534         else if (status == WLC_E_STATUS_SUCCESS) {
9535                 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9536                 wl_escan_print_sync_id(status, wl->escan_info.cur_sync_id,
9537                         escan_result->sync_id);
9538
9539                 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9540                         WL_INFO(("ACTION FRAME SCAN DONE\n"));
9541                         wl_clr_p2p_status(wl, SCANNING);
9542                         wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
9543                         if (wl->afx_hdl->peer_chan == WL_INVALID)
9544                                 complete(&wl->act_frm_scan);
9545                 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
9546                         WL_INFO(("ESCAN COMPLETED\n"));
9547                         wl->bss_list = wl_escan_get_buf(wl, FALSE);
9548                         if (!scan_req_match(wl)) {
9549                                 WL_TRACE_HW4(("SCAN COMPLETED: scanned AP count=%d\n",
9550                                         wl->bss_list->count));
9551                         }
9552                         wl_inform_bss(wl);
9553                         wl_notify_escan_complete(wl, ndev, false, false);
9554                 }
9555                 wl_escan_increment_sync_id(wl, SCAN_BUF_NEXT);
9556         }
9557         else if (status == WLC_E_STATUS_ABORT) {
9558                 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9559                 wl_escan_print_sync_id(status, escan_result->sync_id,
9560                         wl->escan_info.cur_sync_id);
9561                 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9562                         WL_INFO(("ACTION FRAME SCAN DONE\n"));
9563                         wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
9564                         wl_clr_p2p_status(wl, SCANNING);
9565                         if (wl->afx_hdl->peer_chan == WL_INVALID)
9566                                 complete(&wl->act_frm_scan);
9567                 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
9568                         WL_INFO(("ESCAN ABORTED\n"));
9569                         wl->bss_list = wl_escan_get_buf(wl, TRUE);
9570                         if (!scan_req_match(wl)) {
9571                                 WL_TRACE_HW4(("SCAN ABORTED: scanned AP count=%d\n",
9572                                         wl->bss_list->count));
9573                         }
9574                         wl_inform_bss(wl);
9575                         wl_notify_escan_complete(wl, ndev, true, false);
9576                 }
9577                 wl_escan_increment_sync_id(wl, SCAN_BUF_CNT);
9578         } else if (status == WLC_E_STATUS_NEWSCAN) {
9579                 WL_ERR(("WLC_E_STATUS_NEWSCAN : scan_request[%p]\n", wl->scan_request));
9580                 WL_ERR(("sync_id[%d], bss_count[%d]\n", escan_result->sync_id,
9581                         escan_result->bss_count));
9582         } else if (status == WLC_E_STATUS_TIMEOUT) {
9583                 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", wl->scan_request));
9584                 WL_ERR(("escan_on[%d], reason[0x%x]\n", wl->escan_on, e->reason));
9585                 if (e->reason == 0xFFFFFFFF) {
9586                         wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true);
9587                 }
9588         } else {
9589                 WL_ERR(("unexpected Escan Event %d : abort\n", status));
9590                 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9591                 wl_escan_print_sync_id(status, escan_result->sync_id,
9592                         wl->escan_info.cur_sync_id);
9593                 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9594                         WL_INFO(("ACTION FRAME SCAN DONE\n"));
9595                         wl_clr_p2p_status(wl, SCANNING);
9596                         wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
9597                         if (wl->afx_hdl->peer_chan == WL_INVALID)
9598                                 complete(&wl->act_frm_scan);
9599                 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
9600                         wl->bss_list = wl_escan_get_buf(wl, TRUE);
9601                         if (!scan_req_match(wl)) {
9602                                 WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): "
9603                                         "scanned AP count=%d\n",
9604                                         wl->bss_list->count));
9605                         }
9606                         wl_inform_bss(wl);
9607                         wl_notify_escan_complete(wl, ndev, true, false);
9608                 }
9609                 wl_escan_increment_sync_id(wl, 2);
9610         }
9611 exit:
9612         mutex_unlock(&wl->usr_sync);
9613         return err;
9614 }
9615
9616 static void wl_cfg80211_concurrent_roam(struct wl_priv *wl, int enable)
9617 {
9618         u32 connected_cnt  = wl_get_drv_status_all(wl, CONNECTED);
9619         struct net_info *iter, *next;
9620         int err;
9621
9622         if (!wl->roamoff_on_concurrent)
9623                 return;
9624         if (enable && connected_cnt > 1) {
9625                 for_each_ndev(wl, iter, next) {
9626                         /* Save the current roam setting */
9627                         if ((err = wldev_iovar_getint(iter->ndev, "roam_off",
9628                                 (s32 *)&iter->roam_off)) != BCME_OK) {
9629                                 WL_ERR(("%s:Failed to get current roam setting err %d\n",
9630                                         iter->ndev->name, err));
9631                                 continue;
9632                         }
9633                         if ((err = wldev_iovar_setint(iter->ndev, "roam_off", 1)) != BCME_OK) {
9634                                 WL_ERR((" %s:failed to set roam_off : %d\n",
9635                                         iter->ndev->name, err));
9636                         }
9637                 }
9638         }
9639         else if (!enable) {
9640                 for_each_ndev(wl, iter, next) {
9641                         if (iter->roam_off != WL_INVALID) {
9642                                 if ((err = wldev_iovar_setint(iter->ndev, "roam_off",
9643                                         iter->roam_off)) == BCME_OK)
9644                                         iter->roam_off = WL_INVALID;
9645                                 else {
9646                                         WL_ERR((" %s:failed to set roam_off : %d\n",
9647                                                 iter->ndev->name, err));
9648                                 }
9649                         }
9650                 }
9651         }
9652         return;
9653 }
9654
9655 static void wl_cfg80211_determine_vsdb_mode(struct wl_priv *wl)
9656 {
9657         struct net_info *iter, *next;
9658         u32 ctl_chan = 0;
9659         u32 chanspec = 0;
9660         u32 pre_ctl_chan = 0;
9661         u32 connected_cnt  = wl_get_drv_status_all(wl, CONNECTED);
9662         wl->vsdb_mode = false;
9663
9664         if (connected_cnt <= 1)  {
9665                 return;
9666         }
9667         for_each_ndev(wl, iter, next) {
9668                 chanspec = 0;
9669                 ctl_chan = 0;
9670                 if (wl_get_drv_status(wl, CONNECTED, iter->ndev)) {
9671                         if (wldev_iovar_getint(iter->ndev, "chanspec",
9672                                 (s32 *)&chanspec) == BCME_OK) {
9673                                 chanspec = wl_chspec_driver_to_host(chanspec);
9674                                 ctl_chan = wf_chspec_ctlchan(chanspec);
9675                                 wl_update_prof(wl, iter->ndev, NULL,
9676                                         &ctl_chan, WL_PROF_CHAN);
9677                         }
9678                         if (!wl->vsdb_mode) {
9679                                 if (!pre_ctl_chan && ctl_chan)
9680                                         pre_ctl_chan = ctl_chan;
9681                                 else if (pre_ctl_chan && (pre_ctl_chan != ctl_chan)) {
9682                                         wl->vsdb_mode = true;
9683                                 }
9684                         }
9685                 }
9686         }
9687         printk("%s concurrency is enabled\n", wl->vsdb_mode ? "Multi Channel" : "Same Channel");
9688         return;
9689 }
9690
9691 static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info,
9692         enum wl_status state, bool set)
9693 {
9694         s32 pm = PM_FAST;
9695         s32 err = BCME_OK;
9696         u32 mode;
9697         u32 chan = 0;
9698         struct net_info *iter, *next;
9699         struct net_device *primary_dev = wl_to_prmry_ndev(wl);
9700         WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n",
9701                 state, set, _net_info->pm_restore, _net_info->ndev->name));
9702
9703         if (state != WL_STATUS_CONNECTED)
9704                 return 0;
9705         mode = wl_get_mode_by_netdev(wl, _net_info->ndev);
9706         if (set) {
9707                 wl_cfg80211_concurrent_roam(wl, 1);
9708
9709                 if (mode == WL_MODE_AP) {
9710
9711                         if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false))
9712                                 WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
9713                 }
9714                 wl_cfg80211_determine_vsdb_mode(wl);
9715                 if (wl->vsdb_mode || _net_info->pm_block) {
9716                         if (wl->pm_enable_work_on) {
9717                                 cancel_delayed_work_sync(&wl->pm_enable_work);
9718                                 wl->pm_enable_work_on = false;
9719                         }
9720                         /* save PM_FAST in _net_info to restore this
9721                          * if _net_info->pm_block is false
9722                          */
9723                         if (!_net_info->pm_block && (mode == WL_MODE_BSS)) {
9724                                 _net_info->pm = PM_FAST;
9725                                 _net_info->pm_restore = true;
9726                         }
9727                         pm = PM_OFF;
9728                         for_each_ndev(wl, iter, next) {
9729                                 if (iter->pm_restore)
9730                                         continue;
9731                                 /* Save the current power mode */
9732                                 err = wldev_ioctl(iter->ndev, WLC_GET_PM, &iter->pm,
9733                                         sizeof(iter->pm), false);
9734                                 WL_DBG(("%s:power save %s\n", iter->ndev->name,
9735                                         iter->pm ? "enabled" : "disabled"));
9736                                 if (!err && iter->pm) {
9737                                         iter->pm_restore = true;
9738                                 }
9739
9740                         }
9741                         for_each_ndev(wl, iter, next) {
9742                                 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm,
9743                                         sizeof(pm), true)) != 0) {
9744                                         if (err == -ENODEV)
9745                                                 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
9746                                         else
9747                                                 WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
9748                                 } else
9749                                         iter->ndev->ieee80211_ptr->ps = false;
9750                         }
9751                 } else {
9752                         /* add PM Enable timer to go to power save mode
9753                          * if supplicant control pm mode, it will be cleared or
9754                          * updated by wl_cfg80211_set_power_mgmt() if not - for static IP & HW4 P2P,
9755                          * PM will be configured when timer expired
9756                          */
9757
9758                         /*
9759                          * before calling pm_enable_timer, we need to set PM -1 for all ndev
9760                          */
9761                         pm = PM_OFF;
9762
9763                         for_each_ndev(wl, iter, next) {
9764                                 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm,
9765                                         sizeof(pm), true)) != 0) {
9766                                         if (err == -ENODEV)
9767                                                 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
9768                                         else
9769                                                 WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
9770                                 }
9771                         }
9772                         wl->pm_enable_work_on = true;
9773                         schedule_delayed_work(&wl->pm_enable_work,
9774                                 msecs_to_jiffies(WL_PM_ENABLE_TIMEOUT));
9775                 }
9776         }
9777          else { /* clear */
9778                 chan = 0;
9779                 /* clear chan information when the net device is disconnected */
9780                 wl_update_prof(wl, _net_info->ndev, NULL, &chan, WL_PROF_CHAN);
9781                 wl_cfg80211_determine_vsdb_mode(wl);
9782                 for_each_ndev(wl, iter, next) {
9783                         if (iter->pm_restore && iter->pm) {
9784                                 WL_DBG(("%s:restoring power save %s\n",
9785                                         iter->ndev->name, (iter->pm ? "enabled" : "disabled")));
9786                                 err = wldev_ioctl(iter->ndev,
9787                                         WLC_SET_PM, &iter->pm, sizeof(iter->pm), true);
9788                                 if (unlikely(err)) {
9789                                         if (err == -ENODEV)
9790                                                 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
9791                                         else
9792                                                 WL_ERR(("%s:error(%d)\n", iter->ndev->name, err));
9793                                         break;
9794                                 }
9795                                 iter->pm_restore = 0;
9796                                 iter->ndev->ieee80211_ptr->ps = true;
9797                         }
9798                 }
9799                 wl_cfg80211_concurrent_roam(wl, 0);
9800         }
9801         return err;
9802 }
9803
9804 static s32 wl_init_scan(struct wl_priv *wl)
9805 {
9806         struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
9807         int err = 0;
9808
9809         if (wl->iscan_on) {
9810                 iscan->dev = wl_to_prmry_ndev(wl);
9811                 iscan->state = WL_ISCAN_STATE_IDLE;
9812                 wl_init_iscan_handler(iscan);
9813                 iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
9814                 init_timer(&iscan->timer);
9815                 iscan->timer.data = (unsigned long) iscan;
9816                 iscan->timer.function = wl_iscan_timer;
9817                 sema_init(&iscan->sync, 0);
9818                 iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan");
9819                 if (IS_ERR(iscan->tsk)) {
9820                         WL_ERR(("Could not create iscan thread\n"));
9821                         iscan->tsk = NULL;
9822                         return -ENOMEM;
9823                 }
9824                 iscan->data = wl;
9825         } else if (wl->escan_on) {
9826                 wl->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
9827                 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9828                 wl_escan_init_sync_id(wl);
9829         }
9830         /* Init scan_timeout timer */
9831         init_timer(&wl->scan_timeout);
9832         wl->scan_timeout.data = (unsigned long) wl;
9833         wl->scan_timeout.function = wl_scan_timeout;
9834
9835         return err;
9836 }
9837
9838 static s32 wl_init_priv(struct wl_priv *wl)
9839 {
9840         struct wiphy *wiphy = wl_to_wiphy(wl);
9841         struct net_device *ndev = wl_to_prmry_ndev(wl);
9842         s32 err = 0;
9843
9844         wl->scan_request = NULL;
9845         wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
9846         wl->iscan_on = false;
9847         wl->escan_on = true;
9848         wl->roam_on = false;
9849         wl->iscan_kickstart = false;
9850         wl->active_scan = true;
9851         wl->rf_blocked = false;
9852         wl->vsdb_mode = false;
9853         wl->wlfc_on = false;
9854         wl->roamoff_on_concurrent = true;
9855         /* register interested state */
9856         set_bit(WL_STATUS_CONNECTED, &wl->interrested_state);
9857         spin_lock_init(&wl->cfgdrv_lock);
9858         mutex_init(&wl->ioctl_buf_sync);
9859         init_waitqueue_head(&wl->netif_change_event);
9860         init_completion(&wl->send_af_done);
9861         init_completion(&wl->iface_disable);
9862         wl_init_eq(wl);
9863         err = wl_init_priv_mem(wl);
9864         if (err)
9865                 return err;
9866         if (wl_create_event_handler(wl))
9867                 return -ENOMEM;
9868         wl_init_event_handler(wl);
9869         mutex_init(&wl->usr_sync);
9870         mutex_init(&wl->event_sync);
9871         err = wl_init_scan(wl);
9872         if (err)
9873                 return err;
9874         wl_init_conf(wl->conf);
9875         wl_init_prof(wl, ndev);
9876         wl_link_down(wl);
9877         DNGL_FUNC(dhd_cfg80211_init, (wl));
9878
9879         return err;
9880 }
9881
9882 static void wl_deinit_priv(struct wl_priv *wl)
9883 {
9884         DNGL_FUNC(dhd_cfg80211_deinit, (wl));
9885         wl_destroy_event_handler(wl);
9886         wl_flush_eq(wl);
9887         wl_link_down(wl);
9888         del_timer_sync(&wl->scan_timeout);
9889         wl_term_iscan(wl);
9890         wl_deinit_priv_mem(wl);
9891         unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
9892 }
9893
9894 #if defined(WL_ENABLE_P2P_IF)
9895 static s32 wl_cfg80211_attach_p2p(void)
9896 {
9897         struct wl_priv *wl = wlcfg_drv_priv;
9898
9899         WL_TRACE(("Enter \n"));
9900
9901         if (wl_cfgp2p_register_ndev(wl) < 0) {
9902                 WL_ERR(("P2P attach failed. \n"));
9903                 return -ENODEV;
9904         }
9905
9906         return 0;
9907 }
9908
9909 static s32  wl_cfg80211_detach_p2p(void)
9910 {
9911         struct wl_priv *wl = wlcfg_drv_priv;
9912         struct wireless_dev *wdev;
9913
9914         WL_DBG(("Enter \n"));
9915         if (!wl) {
9916                 WL_ERR(("Invalid Ptr\n"));
9917                 return -EINVAL;
9918         } else
9919                 wdev = wl->p2p_wdev;
9920
9921         if (!wdev) {
9922                 WL_ERR(("Invalid Ptr\n"));
9923                 return -EINVAL;
9924         }
9925
9926         wl_cfgp2p_unregister_ndev(wl);
9927
9928         wl->p2p_wdev = NULL;
9929         wl->p2p_net = NULL;
9930         WL_DBG(("Freeing 0x%08x \n", (unsigned int)wdev));
9931         kfree(wdev);
9932
9933         return 0;
9934 }
9935 #endif /* WL_ENABLE_P2P_IF */
9936
9937 s32 wl_cfg80211_attach_post(struct net_device *ndev)
9938 {
9939         struct wl_priv * wl = NULL;
9940         s32 err = 0;
9941         WL_TRACE(("In\n"));
9942         if (unlikely(!ndev)) {
9943                 WL_ERR(("ndev is invaild\n"));
9944                 return -ENODEV;
9945         }
9946         wl = wlcfg_drv_priv;
9947         if (unlikely(!wl)) {
9948                 WL_ERR(("wl is invaild\n"));
9949                 return -EINVAL;
9950         }
9951         if (!wl_get_drv_status(wl, READY, ndev)) {
9952                         if (wl->wdev && wl_cfgp2p_supported(wl, ndev)) {
9953 #if !defined(WL_ENABLE_P2P_IF)
9954                                 wl->wdev->wiphy->interface_modes |=
9955                                         (BIT(NL80211_IFTYPE_P2P_CLIENT)|
9956                                         BIT(NL80211_IFTYPE_P2P_GO));
9957 #endif /* !WL_ENABLE_P2P_IF */
9958                                 if ((err = wl_cfgp2p_init_priv(wl)) != 0)
9959                                         goto fail;
9960
9961 #if defined(WL_ENABLE_P2P_IF)
9962                                 if (wl->p2p_net) {
9963                                         /* Update MAC addr for p2p0 interface here. */
9964                                         memcpy(wl->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN);
9965                                         wl->p2p_net->dev_addr[0] |= 0x02;
9966                                         printk("%s: %s p2p_dev_addr="MACDBG "\n", __FUNCTION__,
9967                                                 wl->p2p_net->name,
9968                                                 MAC2STRDBG(wl->p2p_net->dev_addr));
9969                                 } else {
9970                                         WL_ERR(("p2p_net not yet populated."
9971                                         " Couldn't update the MAC Address for p2p0 \n"));
9972                                         return -ENODEV;
9973                                 }
9974 #endif /* WL_ENABLE_P2P_IF */
9975
9976                                 wl->p2p_supported = true;
9977                         }
9978         }
9979         wl_set_drv_status(wl, READY, ndev);
9980 fail:
9981         return err;
9982 }
9983
9984 s32 wl_cfg80211_attach(struct net_device *ndev, void *data)
9985 {
9986         struct wireless_dev *wdev;
9987         struct wl_priv *wl;
9988         s32 err = 0;
9989         struct device *dev;
9990
9991         WL_TRACE(("In\n"));
9992         if (!ndev) {
9993                 WL_ERR(("ndev is invaild\n"));
9994                 return -ENODEV;
9995         }
9996         WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev()));
9997         dev = wl_cfg80211_get_parent_dev();
9998
9999         wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
10000         if (unlikely(!wdev)) {
10001                 WL_ERR(("Could not allocate wireless device\n"));
10002                 return -ENOMEM;
10003         }
10004         err = wl_setup_wiphy(wdev, dev, data);
10005         if (unlikely(err)) {
10006                 kfree(wdev);
10007                 return -ENOMEM;
10008         }
10009         wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
10010         wl = (struct wl_priv *)wiphy_priv(wdev->wiphy);
10011         wl->wdev = wdev;
10012         wl->pub = data;
10013         INIT_LIST_HEAD(&wl->net_list);
10014         ndev->ieee80211_ptr = wdev;
10015         SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
10016         wdev->netdev = ndev;
10017         wl->state_notifier = wl_notifier_change_state;
10018         err = wl_alloc_netinfo(wl, ndev, wdev, WL_MODE_BSS, PM_ENABLE);
10019         if (err) {
10020                 WL_ERR(("Failed to alloc net_info (%d)\n", err));
10021                 goto cfg80211_attach_out;
10022         }
10023         err = wl_init_priv(wl);
10024         if (err) {
10025                 WL_ERR(("Failed to init iwm_priv (%d)\n", err));
10026                 goto cfg80211_attach_out;
10027         }
10028
10029         err = wl_setup_rfkill(wl, TRUE);
10030         if (err) {
10031                 WL_ERR(("Failed to setup rfkill %d\n", err));
10032                 goto cfg80211_attach_out;
10033         }
10034 #ifdef DEBUGFS_CFG80211
10035         err = wl_setup_debugfs(wl);
10036         if (err) {
10037                 WL_ERR(("Failed to setup debugfs %d\n", err));
10038                 goto cfg80211_attach_out;
10039         }
10040 #endif
10041         err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier);
10042         if (err) {
10043                 WL_ERR(("Failed to register notifierl %d\n", err));
10044                 goto cfg80211_attach_out;
10045         }
10046 #if defined(COEX_DHCP)
10047         err = wl_cfg80211_btcoex_init(wl);
10048         if (err)
10049                 goto cfg80211_attach_out;
10050 #endif 
10051 #if defined(BSSCACHE)
10052         if (wl_init_bss_cache_ctrl(&g_bss_cache_ctrl))
10053                 goto cfg80211_attach_out;
10054 #endif
10055
10056         wlcfg_drv_priv = wl;
10057
10058 #if defined(WL_ENABLE_P2P_IF)
10059         err = wl_cfg80211_attach_p2p();
10060         if (err)
10061                 goto cfg80211_attach_out;
10062 #endif /* WL_ENABLE_P2P_IF */
10063
10064         return err;
10065
10066 cfg80211_attach_out:
10067         wl_setup_rfkill(wl, FALSE);
10068         wl_free_wdev(wl);
10069         return err;
10070 }
10071
10072 void wl_cfg80211_detach(void *para)
10073 {
10074         struct wl_priv *wl;
10075
10076         (void)para;
10077         wl = wlcfg_drv_priv;
10078
10079         WL_TRACE(("In\n"));
10080
10081 #if defined(COEX_DHCP)
10082         wl_cfg80211_btcoex_deinit(wl);
10083 #endif 
10084
10085         wl_setup_rfkill(wl, FALSE);
10086 #ifdef DEBUGFS_CFG80211
10087         wl_free_debugfs(wl);
10088 #endif
10089         if (wl->p2p_supported) {
10090                 if (timer_pending(&wl->p2p->listen_timer))
10091                         del_timer_sync(&wl->p2p->listen_timer);
10092                 wl_cfgp2p_deinit_priv(wl);
10093         }
10094
10095 #if defined(WL_CFG80211_P2P_DEV_IF)
10096         wl_cfgp2p_del_p2p_disc_if(wl->p2p_wdev);
10097 #elif defined(WL_ENABLE_P2P_IF)
10098         wl_cfg80211_detach_p2p();
10099 #endif /* WL_CFG80211_P2P_DEV_IF */
10100
10101         wl_cfg80211_ibss_vsie_free(wl);
10102         wl_deinit_priv(wl);
10103         wlcfg_drv_priv = NULL;
10104         wl_cfg80211_clear_parent_dev();
10105         wl_free_wdev(wl);
10106 #if defined(RSSIAVG)
10107         wl_free_rssi_cache(&g_rssi_cache_ctrl);
10108         wl_free_rssi_cache(&g_rssi2_cache_ctrl);
10109 #endif
10110 #if defined(BSSCACHE)
10111         wl_release_bss_cache_ctrl(&g_bss_cache_ctrl);
10112 #endif
10113          /* PLEASE do NOT call any function after wl_free_wdev, the driver's private structure "wl",
10114           * which is the private part of wiphy, has been freed in wl_free_wdev !!!!!!!!!!!
10115           */
10116 }
10117
10118 static void wl_wakeup_event(struct wl_priv *wl)
10119 {
10120         if (wl->event_tsk.thr_pid >= 0) {
10121                 DHD_OS_WAKE_LOCK(wl->pub);
10122                 up(&wl->event_tsk.sema);
10123         }
10124 }
10125
10126 #if (defined(WL_CFG80211_P2P_DEV_IF) || defined(WL_ENABLE_P2P_IF))
10127 static int wl_is_p2p_event(struct wl_event_q *e)
10128 {
10129         switch (e->etype) {
10130         /* We have to seperate out the P2P events received
10131          * on primary interface so that it can be send up
10132          * via p2p0 interface.
10133         */
10134         case WLC_E_P2P_PROBREQ_MSG:
10135         case WLC_E_P2P_DISC_LISTEN_COMPLETE:
10136         case WLC_E_ACTION_FRAME_RX:
10137         case WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE:
10138         case WLC_E_ACTION_FRAME_COMPLETE:
10139
10140                 if (e->emsg.ifidx != 0) {
10141                         WL_TRACE(("P2P event(%d) on virtual interface(ifidx:%d)\n",
10142                                 e->etype, e->emsg.ifidx));
10143                         /* We are only bothered about the P2P events received
10144                          * on primary interface. For rest of them return false
10145                          * so that it is sent over the interface corresponding
10146                          * to the ifidx.
10147                          */
10148                         return FALSE;
10149                 } else {
10150                         WL_TRACE(("P2P event(%d) on interface(ifidx:%d)\n",
10151                                 e->etype, e->emsg.ifidx));
10152                         return TRUE;
10153                 }
10154                 break;
10155
10156         default:
10157                 WL_TRACE(("NON-P2P event(%d) on interface(ifidx:%d)\n",
10158                         e->etype, e->emsg.ifidx));
10159                 return FALSE;
10160         }
10161 }
10162 #endif /* BCMDONGLEHOST && (WL_CFG80211_P2P_DEV_IF || WL_ENABLE_P2P_IF) */
10163
10164 static s32 wl_event_handler(void *data)
10165 {
10166         struct wl_priv *wl = NULL;
10167         struct wl_event_q *e;
10168         tsk_ctl_t *tsk = (tsk_ctl_t *)data;
10169         bcm_struct_cfgdev *cfgdev = NULL;
10170
10171         wl = (struct wl_priv *)tsk->parent;
10172
10173         printk("tsk Enter, tsk = 0x%08x\n", (unsigned int)tsk);
10174
10175         while (down_interruptible (&tsk->sema) == 0) {
10176                 SMP_RD_BARRIER_DEPENDS();
10177                 if (tsk->terminated)
10178                         break;
10179                 while ((e = wl_deq_event(wl))) {
10180                         WL_DBG(("event type (%d), if idx: %d\n", e->etype, e->emsg.ifidx));
10181                         /* All P2P device address related events comes on primary interface since
10182                          * there is no corresponding bsscfg for P2P interface. Map it to p2p0
10183                          * interface.
10184                          */
10185 #if defined(WL_CFG80211_P2P_DEV_IF)
10186                         if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_wdev)) {
10187                                 cfgdev = wl_to_p2p_wdev(wl);
10188                         } else {
10189                                 cfgdev = ndev_to_wdev(dhd_idx2net((struct dhd_pub *)(wl->pub),
10190                                         e->emsg.ifidx));
10191                         }
10192 #elif defined(WL_ENABLE_P2P_IF)
10193                         if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_net)) {
10194                                 cfgdev = wl->p2p_net;
10195                         } else {
10196                                 cfgdev = dhd_idx2net((struct dhd_pub *)(wl->pub),
10197                                         e->emsg.ifidx);
10198                         }
10199 #endif /* WL_CFG80211_P2P_DEV_IF */
10200
10201                         if (!cfgdev) {
10202 #if defined(WL_CFG80211_P2P_DEV_IF)
10203                                 cfgdev = wl_to_prmry_wdev(wl);
10204 #elif defined(WL_ENABLE_P2P_IF)
10205                                 cfgdev = wl_to_prmry_ndev(wl);
10206 #endif /* WL_CFG80211_P2P_DEV_IF */
10207                         }
10208                         if (e->etype < WLC_E_LAST && wl->evt_handler[e->etype]) {
10209                                 wl->evt_handler[e->etype] (wl, cfgdev, &e->emsg, e->edata);
10210                         } else {
10211                                 WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
10212                         }
10213                         wl_put_event(e);
10214                 }
10215                 DHD_OS_WAKE_UNLOCK(wl->pub);
10216         }
10217         WL_ERR(("was terminated\n"));
10218         complete_and_exit(&tsk->completed, 0);
10219         return 0;
10220 }
10221
10222 void
10223 wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
10224 {
10225         u32 event_type = ntoh32(e->event_type);
10226         struct wl_priv *wl = wlcfg_drv_priv;
10227
10228 #if (WL_DBG_LEVEL > 0)
10229         s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
10230             wl_dbg_estr[event_type] : (s8 *) "Unknown";
10231         WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
10232 #endif /* (WL_DBG_LEVEL > 0) */
10233
10234         if (event_type == WLC_E_PFN_NET_FOUND) {
10235                 WL_DBG((" PNOEVENT: PNO_NET_FOUND\n"));
10236         }
10237         else if (event_type == WLC_E_PFN_NET_LOST) {
10238                 WL_DBG((" PNOEVENT: PNO_NET_LOST\n"));
10239         }
10240
10241         if (likely(!wl_enq_event(wl, ndev, event_type, e, data)))
10242                 wl_wakeup_event(wl);
10243 }
10244
10245 static void wl_init_eq(struct wl_priv *wl)
10246 {
10247         wl_init_eq_lock(wl);
10248         INIT_LIST_HEAD(&wl->eq_list);
10249 }
10250
10251 static void wl_flush_eq(struct wl_priv *wl)
10252 {
10253         struct wl_event_q *e;
10254         unsigned long flags;
10255
10256         flags = wl_lock_eq(wl);
10257         while (!list_empty(&wl->eq_list)) {
10258                 e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
10259                 list_del(&e->eq_list);
10260                 kfree(e);
10261         }
10262         wl_unlock_eq(wl, flags);
10263 }
10264
10265 /*
10266 * retrieve first queued event from head
10267 */
10268
10269 static struct wl_event_q *wl_deq_event(struct wl_priv *wl)
10270 {
10271         struct wl_event_q *e = NULL;
10272         unsigned long flags;
10273
10274         flags = wl_lock_eq(wl);
10275         if (likely(!list_empty(&wl->eq_list))) {
10276                 e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
10277                 list_del(&e->eq_list);
10278         }
10279         wl_unlock_eq(wl, flags);
10280
10281         return e;
10282 }
10283
10284 /*
10285  * push event to tail of the queue
10286  */
10287
10288 static s32
10289 wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 event, const wl_event_msg_t *msg,
10290         void *data)
10291 {
10292         struct wl_event_q *e;
10293         s32 err = 0;
10294         uint32 evtq_size;
10295         uint32 data_len;
10296         unsigned long flags;
10297         gfp_t aflags;
10298
10299         data_len = 0;
10300         if (data)
10301                 data_len = ntoh32(msg->datalen);
10302         evtq_size = sizeof(struct wl_event_q) + data_len;
10303         aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
10304         e = kzalloc(evtq_size, aflags);
10305         if (unlikely(!e)) {
10306                 WL_ERR(("event alloc failed\n"));
10307                 return -ENOMEM;
10308         }
10309         e->etype = event;
10310         memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
10311         if (data)
10312                 memcpy(e->edata, data, data_len);
10313         flags = wl_lock_eq(wl);
10314         list_add_tail(&e->eq_list, &wl->eq_list);
10315         wl_unlock_eq(wl, flags);
10316
10317         return err;
10318 }
10319
10320 static void wl_put_event(struct wl_event_q *e)
10321 {
10322         kfree(e);
10323 }
10324
10325 static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype)
10326 {
10327         s32 infra = 0;
10328         s32 err = 0;
10329         s32 mode = 0;
10330         switch (iftype) {
10331         case NL80211_IFTYPE_MONITOR:
10332         case NL80211_IFTYPE_WDS:
10333                 WL_ERR(("type (%d) : currently we do not support this mode\n",
10334                         iftype));
10335                 err = -EINVAL;
10336                 return err;
10337         case NL80211_IFTYPE_ADHOC:
10338                 mode = WL_MODE_IBSS;
10339                 break;
10340         case NL80211_IFTYPE_STATION:
10341         case NL80211_IFTYPE_P2P_CLIENT:
10342                 mode = WL_MODE_BSS;
10343                 infra = 1;
10344                 break;
10345         case NL80211_IFTYPE_AP:
10346         case NL80211_IFTYPE_P2P_GO:
10347                 mode = WL_MODE_AP;
10348                 infra = 1;
10349                 break;
10350         default:
10351                 err = -EINVAL;
10352                 WL_ERR(("invalid type (%d)\n", iftype));
10353                 return err;
10354         }
10355         infra = htod32(infra);
10356         err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true);
10357         if (unlikely(err)) {
10358                 WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
10359                 return err;
10360         }
10361
10362         wl_set_mode_by_netdev(wl, ndev, mode);
10363
10364         return 0;
10365 }
10366
10367 void wl_cfg80211_add_to_eventbuffer(struct wl_eventmsg_buf *ev, u16 event, bool set)
10368 {
10369         if (!ev || (event > WLC_E_LAST))
10370                 return;
10371
10372         if (ev->num < MAX_EVENT_BUF_NUM) {
10373                 ev->event[ev->num].type = event;
10374                 ev->event[ev->num].set = set;
10375                 ev->num++;
10376         } else {
10377                 WL_ERR(("evenbuffer doesn't support > %u events. Update"
10378                         " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM));
10379                 ASSERT(0);
10380         }
10381 }
10382
10383 s32 wl_cfg80211_apply_eventbuffer(
10384         struct net_device *ndev,
10385         struct wl_priv *wl,
10386         wl_eventmsg_buf_t *ev)
10387 {
10388         char eventmask[WL_EVENTING_MASK_LEN];
10389         int i, ret = 0;
10390         s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
10391
10392         if (!ev || (!ev->num))
10393                 return -EINVAL;
10394
10395         mutex_lock(&wl->event_sync);
10396
10397         /* Read event_msgs mask */
10398         bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
10399                 sizeof(iovbuf));
10400         ret = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
10401         if (unlikely(ret)) {
10402                 WL_ERR(("Get event_msgs error (%d)\n", ret));
10403                 goto exit;
10404         }
10405         memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
10406
10407         /* apply the set bits */
10408         for (i = 0; i < ev->num; i++) {
10409                 if (ev->event[i].set)
10410                         setbit(eventmask, ev->event[i].type);
10411                 else
10412                         clrbit(eventmask, ev->event[i].type);
10413         }
10414
10415         /* Write updated Event mask */
10416         bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
10417                 sizeof(iovbuf));
10418         ret = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
10419         if (unlikely(ret)) {
10420                 WL_ERR(("Set event_msgs error (%d)\n", ret));
10421         }
10422
10423 exit:
10424         mutex_unlock(&wl->event_sync);
10425         return ret;
10426 }
10427
10428 s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add)
10429 {
10430         s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
10431         s8 eventmask[WL_EVENTING_MASK_LEN];
10432         s32 err = 0;
10433         struct wl_priv *wl = wlcfg_drv_priv;
10434
10435         if (!ndev || !wl)
10436                 return -ENODEV;
10437
10438         mutex_lock(&wl->event_sync);
10439
10440         /* Setup event_msgs */
10441         bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
10442                 sizeof(iovbuf));
10443         err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
10444         if (unlikely(err)) {
10445                 WL_ERR(("Get event_msgs error (%d)\n", err));
10446                 goto eventmsg_out;
10447         }
10448         memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
10449         if (add) {
10450                 setbit(eventmask, event);
10451         } else {
10452                 clrbit(eventmask, event);
10453         }
10454         bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
10455                 sizeof(iovbuf));
10456         err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
10457         if (unlikely(err)) {
10458                 WL_ERR(("Set event_msgs error (%d)\n", err));
10459                 goto eventmsg_out;
10460         }
10461
10462 eventmsg_out:
10463         mutex_unlock(&wl->event_sync);
10464         return err;
10465 }
10466
10467 static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap)
10468 {
10469         struct net_device *dev = wl_to_prmry_ndev(wl);
10470         struct ieee80211_channel *band_chan_arr = NULL;
10471         wl_uint32_list_t *list;
10472         u32 i, j, index, n_2g, n_5g, band, channel, array_size;
10473         u32 *n_cnt = NULL;
10474         chanspec_t c = 0;
10475         s32 err = BCME_OK;
10476         bool update;
10477         bool ht40_allowed;
10478         u8 *pbuf = NULL;
10479         bool dfs_radar_disabled = FALSE;
10480
10481 #define LOCAL_BUF_LEN 1024
10482         pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL);
10483
10484         if (pbuf == NULL) {
10485                 WL_ERR(("failed to allocate local buf\n"));
10486                 return -ENOMEM;
10487         }
10488         list = (wl_uint32_list_t *)(void *)pbuf;
10489         list->count = htod32(WL_NUMCHANSPECS);
10490
10491
10492         err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
10493                 0, pbuf, LOCAL_BUF_LEN, 0, &wl->ioctl_buf_sync);
10494         if (err != 0) {
10495                 WL_ERR(("get chanspecs failed with %d\n", err));
10496                 kfree(pbuf);
10497                 return err;
10498         }
10499 #undef LOCAL_BUF_LEN
10500
10501         list = (wl_uint32_list_t *)(void *)pbuf;
10502         band = array_size = n_2g = n_5g = 0;
10503         for (i = 0; i < dtoh32(list->count); i++) {
10504                 index = 0;
10505                 update = false;
10506                 ht40_allowed = false;
10507                 c = (chanspec_t)dtoh32(list->element[i]);
10508                 c = wl_chspec_driver_to_host(c);
10509                 channel = CHSPEC_CHANNEL(c);
10510                 if (!dhd_conf_match_channel((dhd_pub_t *)wl->pub, channel))
10511                         continue;
10512                 if (CHSPEC_IS40(c)) {
10513                         if (CHSPEC_SB_UPPER(c))
10514                                 channel += CH_10MHZ_APART;
10515                         else
10516                                 channel -= CH_10MHZ_APART;
10517                 } else if (CHSPEC_IS80(c)) {
10518                         WL_DBG(("HT80 center channel : %d\n", channel));
10519                         continue;
10520                 }
10521                 if (CHSPEC_IS2G(c) && (channel >= CH_MIN_2G_CHANNEL) &&
10522                         (channel <= CH_MAX_2G_CHANNEL)) {
10523                         band_chan_arr = __wl_2ghz_channels;
10524                         array_size = ARRAYSIZE(__wl_2ghz_channels);
10525                         n_cnt = &n_2g;
10526                         band = IEEE80211_BAND_2GHZ;
10527                         ht40_allowed = (bw_cap  == WLC_N_BW_40ALL)? true : false;
10528                 } else if (CHSPEC_IS5G(c) && channel >= CH_MIN_5G_CHANNEL) {
10529                         band_chan_arr = __wl_5ghz_a_channels;
10530                         array_size = ARRAYSIZE(__wl_5ghz_a_channels);
10531                         n_cnt = &n_5g;
10532                         band = IEEE80211_BAND_5GHZ;
10533                         ht40_allowed = (bw_cap  == WLC_N_BW_20ALL)? false : true;
10534                 } else {
10535                         WL_ERR(("Invalid channel Sepc. 0x%x.\n", c));
10536                         continue;
10537                 }
10538                 if (!ht40_allowed && CHSPEC_IS40(c))
10539                         continue;
10540                 for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
10541                         if (band_chan_arr[j].hw_value == channel) {
10542                                 update = true;
10543                                 break;
10544                         }
10545                 }
10546                 if (update)
10547                         index = j;
10548                 else
10549                         index = *n_cnt;
10550                 if (index <  array_size) {
10551 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
10552                         band_chan_arr[index].center_freq =
10553                                 ieee80211_channel_to_frequency(channel);
10554 #else
10555                         band_chan_arr[index].center_freq =
10556                                 ieee80211_channel_to_frequency(channel, band);
10557 #endif
10558                         band_chan_arr[index].hw_value = channel;
10559
10560                         if (CHSPEC_IS40(c) && ht40_allowed) {
10561                                 /* assuming the order is HT20, HT40 Upper,
10562                                  *  HT40 lower from chanspecs
10563                                  */
10564                                 u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
10565                                 if (CHSPEC_SB_UPPER(c)) {
10566                                         if (ht40_flag == IEEE80211_CHAN_NO_HT40)
10567                                                 band_chan_arr[index].flags &=
10568                                                         ~IEEE80211_CHAN_NO_HT40;
10569                                         band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
10570                                 } else {
10571                                         /* It should be one of
10572                                          * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
10573                                          */
10574                                         band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
10575                                         if (ht40_flag == IEEE80211_CHAN_NO_HT40)
10576                                                 band_chan_arr[index].flags |=
10577                                                         IEEE80211_CHAN_NO_HT40MINUS;
10578                                 }
10579                         } else {
10580                                 band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
10581                                 if (!dfs_radar_disabled) {
10582                                         if (band == IEEE80211_BAND_2GHZ)
10583                                                 channel |= WL_CHANSPEC_BAND_2G;
10584                                         else
10585                                                 channel |= WL_CHANSPEC_BAND_5G;
10586                                         channel |= WL_CHANSPEC_BW_20;
10587                                         channel = wl_chspec_host_to_driver(channel);
10588                                         err = wldev_iovar_getint(dev, "per_chan_info", &channel);
10589                                         if (!err) {
10590                                                 if (channel & WL_CHAN_RADAR)
10591                                                         band_chan_arr[index].flags |=
10592                                                                 (IEEE80211_CHAN_RADAR |
10593                                                                 IEEE80211_CHAN_NO_IBSS);
10594                                                 if (channel & WL_CHAN_PASSIVE)
10595                                                         band_chan_arr[index].flags |=
10596                                                                 IEEE80211_CHAN_PASSIVE_SCAN;
10597                                         } else if (err == BCME_UNSUPPORTED) {
10598                                                 dfs_radar_disabled = TRUE;
10599                                                 WL_ERR(("does not support per_chan_info\n"));
10600                                         }
10601                                 }
10602                         }
10603                         if (!update)
10604                                 (*n_cnt)++;
10605                 }
10606
10607         }
10608         __wl_band_2ghz.n_channels = n_2g;
10609         __wl_band_5ghz_a.n_channels = n_5g;
10610         kfree(pbuf);
10611         return err;
10612 }
10613
10614 s32 wl_update_wiphybands(struct wl_priv *wl, bool notify)
10615 {
10616         struct wiphy *wiphy;
10617         struct net_device *dev;
10618         u32 bandlist[3];
10619         u32 nband = 0;
10620         u32 i = 0;
10621         s32 err = 0;
10622         s32 index = 0;
10623         s32 nmode = 0;
10624         bool rollback_lock = false;
10625         s32 bw_cap = 0;
10626         s32 cur_band = -1;
10627         struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS] = {NULL, };
10628
10629         if (wl == NULL) {
10630                 wl = wlcfg_drv_priv;
10631                 mutex_lock(&wl->usr_sync);
10632                 rollback_lock = true;
10633         }
10634         dev = wl_to_prmry_ndev(wl);
10635
10636         memset(bandlist, 0, sizeof(bandlist));
10637         err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist,
10638                 sizeof(bandlist), false);
10639         if (unlikely(err)) {
10640                 WL_ERR(("error read bandlist (%d)\n", err));
10641                 goto end_bands;
10642         }
10643         err = wldev_ioctl(dev, WLC_GET_BAND, &cur_band,
10644                 sizeof(s32), false);
10645         if (unlikely(err)) {
10646                 WL_ERR(("error (%d)\n", err));
10647                 goto end_bands;
10648         }
10649
10650         err = wldev_iovar_getint(dev, "nmode", &nmode);
10651         if (unlikely(err)) {
10652                 WL_ERR(("error reading nmode (%d)\n", err));
10653         } else {
10654                 /* For nmodeonly check bw cap */
10655                 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
10656                 if (unlikely(err)) {
10657                         WL_ERR(("error get mimo_bw_cap (%d)\n", err));
10658                 }
10659         }
10660
10661         err = wl_construct_reginfo(wl, bw_cap);
10662         if (err) {
10663                 WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
10664                 if (err != BCME_UNSUPPORTED)
10665                         goto end_bands;
10666                 err = 0;
10667         }
10668         wiphy = wl_to_wiphy(wl);
10669         nband = bandlist[0];
10670
10671         for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) {
10672                 index = -1;
10673                 if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
10674                         bands[IEEE80211_BAND_5GHZ] =
10675                                 &__wl_band_5ghz_a;
10676                         index = IEEE80211_BAND_5GHZ;
10677                         if (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G)
10678                                 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
10679                 }
10680                 else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
10681                         bands[IEEE80211_BAND_2GHZ] =
10682                                 &__wl_band_2ghz;
10683                         index = IEEE80211_BAND_2GHZ;
10684                         if (bw_cap == WLC_N_BW_40ALL)
10685                                 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
10686                 }
10687
10688                 if ((index >= 0) && nmode) {
10689                         bands[index]->ht_cap.cap |=
10690                                 (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40);
10691                         bands[index]->ht_cap.ht_supported = TRUE;
10692                         bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
10693                         bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
10694                         /* An HT shall support all EQM rates for one spatial stream */
10695                         bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
10696                 }
10697
10698         }
10699
10700         wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
10701         wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
10702
10703         /* check if any bands populated otherwise makes 2Ghz as default */
10704         if (wiphy->bands[IEEE80211_BAND_2GHZ] == NULL &&
10705                 wiphy->bands[IEEE80211_BAND_5GHZ] == NULL) {
10706                 /* Setup 2Ghz band as default */
10707                 wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
10708         }
10709
10710         if (notify)
10711                 wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
10712
10713 end_bands:
10714         if (rollback_lock)
10715                 mutex_unlock(&wl->usr_sync);
10716         return err;
10717 }
10718
10719 static s32 __wl_cfg80211_up(struct wl_priv *wl)
10720 {
10721         s32 err = 0;
10722 #ifdef WL_HOST_BAND_MGMT
10723         s32 ret = 0;
10724 #endif /* WL_HOST_BAND_MGMT */
10725         struct net_device *ndev = wl_to_prmry_ndev(wl);
10726         struct wireless_dev *wdev = ndev->ieee80211_ptr;
10727
10728         WL_DBG(("In\n"));
10729
10730         err = dhd_config_dongle(wl, false);
10731         if (unlikely(err))
10732                 return err;
10733
10734         err = wl_config_ifmode(wl, ndev, wdev->iftype);
10735         if (unlikely(err && err != -EINPROGRESS)) {
10736                 WL_ERR(("wl_config_ifmode failed\n"));
10737         }
10738         err = wl_update_wiphybands(wl, true);
10739         if (unlikely(err)) {
10740                 WL_ERR(("wl_update_wiphybands failed\n"));
10741         }
10742
10743         err = dhd_monitor_init(wl->pub);
10744         err = wl_invoke_iscan(wl);
10745
10746 #ifdef WL_HOST_BAND_MGMT
10747         /* By default the curr_band is initialized to BAND_AUTO */
10748         if ((ret = wl_cfg80211_set_band(ndev, WLC_BAND_AUTO)) < 0) {
10749                 if (ret == BCME_UNSUPPORTED) {
10750                         /* Don't fail the initialization, lets just
10751                          * fall back to the original method
10752                          */
10753                         WL_ERR(("WL_HOST_BAND_MGMT defined, "
10754                                 "but roam_band iovar not supported \n"));
10755                 } else {
10756                         WL_ERR(("roam_band failed. ret=%d", ret));
10757                         err = -1;
10758                 }
10759         }
10760 #endif /* WL_HOST_BAND_MGMT */
10761
10762 #if defined(DHCP_SCAN_SUPPRESS)
10763         /* wlan scan_supp timer and work thread info */
10764         init_timer(&wl->scan_supp_timer);
10765         wl->scan_supp_timer.data = (ulong)wl;
10766         wl->scan_supp_timer.function = wl_cfg80211_scan_supp_timerfunc;
10767         INIT_WORK(&wl->wlan_work, wl_cfg80211_work_handler);
10768 #endif /* DHCP_SCAN_SUPPRESS */
10769         INIT_DELAYED_WORK(&wl->pm_enable_work, wl_cfg80211_work_handler);
10770         wl_set_drv_status(wl, READY, ndev);
10771         return err;
10772 }
10773
10774 static s32 __wl_cfg80211_down(struct wl_priv *wl)
10775 {
10776         s32 err = 0;
10777         unsigned long flags;
10778         struct net_info *iter, *next;
10779         struct net_device *ndev = wl_to_prmry_ndev(wl);
10780 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
10781 //      struct net_device *p2p_net = wl->p2p_net;
10782 #endif /* WL_CFG80211 && WL_ENABLE_P2P_IF */
10783         u32 bssidx = 0;
10784 #ifdef PROP_TXSTATUS_VSDB
10785         dhd_pub_t *dhd =  (dhd_pub_t *)(wl->pub);
10786 #endif /* PROP_TXSTATUS_VSDB */
10787         WL_DBG(("In\n"));
10788         if (wl->pm_enable_work_on) {
10789                 cancel_delayed_work_sync(&wl->pm_enable_work);
10790                 wl->pm_enable_work_on = false;
10791         }
10792
10793         if (wl->p2p_supported) {
10794                 wl_clr_p2p_status(wl, GO_NEG_PHASE);
10795 #ifdef PROP_TXSTATUS_VSDB
10796                 if (wl->p2p->vif_created) {
10797                         if (dhd->wlfc_enabled && wl->wlfc_on) {
10798                                 dhd->wlfc_enabled = false;
10799                                 dhd_wlfc_deinit(dhd);
10800                                 if (dhd->plat_deinit)
10801                                         dhd->plat_deinit((void *)dhd);
10802                                 wl->wlfc_on = false;
10803                         }
10804                 }
10805 #endif /* PROP_TXSTATUS_VSDB */
10806         }
10807
10808 #if defined(DHCP_SCAN_SUPPRESS)
10809         /* Force clear of scan_suppress */
10810         if (wl->scan_suppressed)
10811                 wl_cfg80211_scan_suppress(ndev, 0);
10812         if (timer_pending(&wl->scan_supp_timer))
10813                 del_timer_sync(&wl->scan_supp_timer);
10814         cancel_work_sync(&wl->wlan_work);
10815 #endif /* DHCP_SCAN_SUPPRESS */
10816
10817         /* If primary BSS is operational (for e.g SoftAP), bring it down */
10818         if (!(wl_cfgp2p_find_idx(wl, ndev, &bssidx)) &&
10819                 wl_cfgp2p_bss_isup(ndev, bssidx)) {
10820                 if (wl_cfgp2p_bss(wl, ndev, bssidx, 0) < 0)
10821                         WL_ERR(("BSS down failed \n"));
10822         }
10823
10824         /* Check if cfg80211 interface is already down */
10825         if (!wl_get_drv_status(wl, READY, ndev))
10826                 return err;     /* it is even not ready */
10827         for_each_ndev(wl, iter, next)
10828                 wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev);
10829
10830 #ifdef WL_SDO
10831         wl_cfg80211_sdo_deinit(wl);
10832 #endif
10833
10834         wl_term_iscan(wl);
10835         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
10836         if (wl->scan_request) {
10837                 cfg80211_scan_done(wl->scan_request, true);
10838                 wl->scan_request = NULL;
10839         }
10840         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
10841
10842         for_each_ndev(wl, iter, next) {
10843                 wl_clr_drv_status(wl, READY, iter->ndev);
10844                 wl_clr_drv_status(wl, SCANNING, iter->ndev);
10845                 wl_clr_drv_status(wl, SCAN_ABORTING, iter->ndev);
10846                 wl_clr_drv_status(wl, CONNECTING, iter->ndev);
10847                 wl_clr_drv_status(wl, CONNECTED, iter->ndev);
10848                 wl_clr_drv_status(wl, DISCONNECTING, iter->ndev);
10849                 wl_clr_drv_status(wl, AP_CREATED, iter->ndev);
10850                 wl_clr_drv_status(wl, AP_CREATING, iter->ndev);
10851         }
10852         wl_to_prmry_ndev(wl)->ieee80211_ptr->iftype =
10853                 NL80211_IFTYPE_STATION;
10854 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
10855 //              if (p2p_net) // terence 20131219: don't close p2p0 or p2p0 never go back anymore
10856 //                      dev_close(p2p_net);
10857 #endif /* WL_CFG80211 && WL_ENABLE_P2P_IF */
10858         DNGL_FUNC(dhd_cfg80211_down, (wl));
10859         wl_flush_eq(wl);
10860         wl_link_down(wl);
10861         if (wl->p2p_supported)
10862                 wl_cfgp2p_down(wl);
10863         dhd_monitor_uninit();
10864
10865         return err;
10866 }
10867
10868 s32 wl_cfg80211_up(void *para)
10869 {
10870         struct wl_priv *wl;
10871         s32 err = 0;
10872         int val = 1;
10873         dhd_pub_t *dhd;
10874
10875         (void)para;
10876         WL_DBG(("In\n"));
10877         wl = wlcfg_drv_priv;
10878
10879         if ((err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_VERSION, &val,
10880                 sizeof(int), false) < 0)) {
10881                 WL_ERR(("WLC_GET_VERSION failed, err=%d\n", err));
10882                 return err;
10883         }
10884         val = dtoh32(val);
10885         if (val != WLC_IOCTL_VERSION && val != 1) {
10886                 WL_ERR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
10887                         val, WLC_IOCTL_VERSION));
10888                 return BCME_VERSION;
10889         }
10890         ioctl_version = val;
10891         WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version));
10892
10893         mutex_lock(&wl->usr_sync);
10894         dhd = (dhd_pub_t *)(wl->pub);
10895         if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
10896                 err = wl_cfg80211_attach_post(wl_to_prmry_ndev(wl));
10897                 if (unlikely(err))
10898                         return err;
10899         }
10900 #if defined(BCMSUP_4WAY_HANDSHAKE) && defined(WLAN_AKM_SUITE_FT_8021X)
10901         if (dhd->fw_4way_handshake)
10902                 wl->wdev->wiphy->features |= NL80211_FEATURE_FW_4WAY_HANDSHAKE;
10903 #endif
10904         err = __wl_cfg80211_up(wl);
10905         if (unlikely(err))
10906                 WL_ERR(("__wl_cfg80211_up failed\n"));
10907         mutex_unlock(&wl->usr_sync);
10908         return err;
10909 }
10910
10911 /* Private Event to Supplicant with indication that chip hangs */
10912 int wl_cfg80211_hang(struct net_device *dev, u16 reason)
10913 {
10914         struct wl_priv *wl;
10915         wl = wlcfg_drv_priv;
10916
10917         WL_ERR(("In : chip crash eventing\n"));
10918         cfg80211_disconnected(dev, reason, NULL, 0, GFP_KERNEL);
10919 #if defined(RSSIAVG)
10920         wl_free_rssi_cache(&g_rssi_cache_ctrl);
10921 #endif
10922 #if defined(BSSCACHE)
10923         wl_free_bss_cache(&g_bss_cache_ctrl);
10924         wl_run_bss_cache_timer(&g_bss_cache_ctrl, 0);
10925 #endif
10926         if (wl != NULL) {
10927                 wl_link_down(wl);
10928         }
10929         return 0;
10930 }
10931
10932 s32 wl_cfg80211_down(void *para)
10933 {
10934         struct wl_priv *wl;
10935         s32 err = 0;
10936
10937         (void)para;
10938         WL_DBG(("In\n"));
10939         wl = wlcfg_drv_priv;
10940         mutex_lock(&wl->usr_sync);
10941 #if defined(RSSIAVG)
10942         wl_free_rssi_cache(&g_rssi_cache_ctrl);
10943 #endif
10944 #if defined(BSSCACHE)
10945         wl_free_bss_cache(&g_bss_cache_ctrl);
10946         wl_run_bss_cache_timer(&g_bss_cache_ctrl, 0);
10947 #endif
10948         err = __wl_cfg80211_down(wl);
10949         mutex_unlock(&wl->usr_sync);
10950
10951         return err;
10952 }
10953
10954 static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item)
10955 {
10956         unsigned long flags;
10957         void *rptr = NULL;
10958         struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
10959
10960         if (!profile)
10961                 return NULL;
10962         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
10963         switch (item) {
10964         case WL_PROF_SEC:
10965                 rptr = &profile->sec;
10966                 break;
10967         case WL_PROF_ACT:
10968                 rptr = &profile->active;
10969                 break;
10970         case WL_PROF_BSSID:
10971                 rptr = profile->bssid;
10972                 break;
10973         case WL_PROF_SSID:
10974                 rptr = &profile->ssid;
10975                 break;
10976         case WL_PROF_CHAN:
10977                 rptr = &profile->channel;
10978                 break;
10979         }
10980         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
10981         if (!rptr)
10982                 WL_ERR(("invalid item (%d)\n", item));
10983         return rptr;
10984 }
10985
10986 static s32
10987 wl_update_prof(struct wl_priv *wl, struct net_device *ndev,
10988         const wl_event_msg_t *e, void *data, s32 item)
10989 {
10990         s32 err = 0;
10991         struct wlc_ssid *ssid;
10992         unsigned long flags;
10993         struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
10994
10995         if (!profile)
10996                 return WL_INVALID;
10997         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
10998         switch (item) {
10999         case WL_PROF_SSID:
11000                 ssid = (wlc_ssid_t *) data;
11001                 memset(profile->ssid.SSID, 0,
11002                         sizeof(profile->ssid.SSID));
11003                 memcpy(profile->ssid.SSID, ssid->SSID, ssid->SSID_len);
11004                 profile->ssid.SSID_len = ssid->SSID_len;
11005                 break;
11006         case WL_PROF_BSSID:
11007                 if (data)
11008                         memcpy(profile->bssid, data, ETHER_ADDR_LEN);
11009                 else
11010                         memset(profile->bssid, 0, ETHER_ADDR_LEN);
11011                 break;
11012         case WL_PROF_SEC:
11013                 memcpy(&profile->sec, data, sizeof(profile->sec));
11014                 break;
11015         case WL_PROF_ACT:
11016                 profile->active = *(bool *)data;
11017                 break;
11018         case WL_PROF_BEACONINT:
11019                 profile->beacon_interval = *(u16 *)data;
11020                 break;
11021         case WL_PROF_DTIMPERIOD:
11022                 profile->dtim_period = *(u8 *)data;
11023                 break;
11024         case WL_PROF_CHAN:
11025                 profile->channel = *(u32*)data;
11026                 break;
11027         default:
11028                 err = -EOPNOTSUPP;
11029                 break;
11030         }
11031         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
11032
11033         if (err == -EOPNOTSUPP)
11034                 WL_ERR(("unsupported item (%d)\n", item));
11035
11036         return err;
11037 }
11038
11039 void wl_cfg80211_dbg_level(u32 level)
11040 {
11041         /*
11042         * prohibit to change debug level
11043         * by insmod parameter.
11044         * eventually debug level will be configured
11045         * in compile time by using CONFIG_XXX
11046         */
11047         /* wl_dbg_level = level; */
11048 }
11049
11050 static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev)
11051 {
11052         return wl_get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS;
11053 }
11054
11055 static __used bool wl_is_ibssstarter(struct wl_priv *wl)
11056 {
11057         return wl->ibss_starter;
11058 }
11059
11060 static void wl_rst_ie(struct wl_priv *wl)
11061 {
11062         struct wl_ie *ie = wl_to_ie(wl);
11063
11064         ie->offset = 0;
11065 }
11066
11067 static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v)
11068 {
11069         struct wl_ie *ie = wl_to_ie(wl);
11070         s32 err = 0;
11071
11072         if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
11073                 WL_ERR(("ei crosses buffer boundary\n"));
11074                 return -ENOSPC;
11075         }
11076         ie->buf[ie->offset] = t;
11077         ie->buf[ie->offset + 1] = l;
11078         memcpy(&ie->buf[ie->offset + 2], v, l);
11079         ie->offset += l + 2;
11080
11081         return err;
11082 }
11083
11084 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size)
11085 {
11086         u8 *ssidie;
11087         ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size);
11088         if (!ssidie)
11089                 return;
11090         if (ssidie[1] != bi->SSID_len) {
11091                 if (ssidie[1]) {
11092                         WL_ERR(("%s: Wrong SSID len: %d != %d\n",
11093                                 __FUNCTION__, ssidie[1], bi->SSID_len));
11094                         return;
11095                 }
11096                 memmove(ssidie + bi->SSID_len + 2, ssidie + 2, *ie_size - (ssidie + 2 - ie_stream));
11097                 memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
11098                 *ie_size = *ie_size + bi->SSID_len;
11099                 ssidie[1] = bi->SSID_len;
11100                 return;
11101         }
11102         if (*(ssidie + 2) == '\0')
11103                  memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
11104         return;
11105 }
11106
11107 static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size)
11108 {
11109         struct wl_ie *ie = wl_to_ie(wl);
11110         s32 err = 0;
11111
11112         if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
11113                 WL_ERR(("ei_stream crosses buffer boundary\n"));
11114                 return -ENOSPC;
11115         }
11116         memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
11117         ie->offset += ie_size;
11118
11119         return err;
11120 }
11121
11122 static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size)
11123 {
11124         struct wl_ie *ie = wl_to_ie(wl);
11125         s32 err = 0;
11126
11127         if (unlikely(ie->offset > dst_size)) {
11128                 WL_ERR(("dst_size is not enough\n"));
11129                 return -ENOSPC;
11130         }
11131         memcpy(dst, &ie->buf[0], ie->offset);
11132
11133         return err;
11134 }
11135
11136 static u32 wl_get_ielen(struct wl_priv *wl)
11137 {
11138         struct wl_ie *ie = wl_to_ie(wl);
11139
11140         return ie->offset;
11141 }
11142
11143 static void wl_link_up(struct wl_priv *wl)
11144 {
11145         wl->link_up = true;
11146 }
11147
11148 static void wl_link_down(struct wl_priv *wl)
11149 {
11150         struct wl_connect_info *conn_info = wl_to_conn(wl);
11151
11152         WL_DBG(("In\n"));
11153         wl->link_up = false;
11154         conn_info->req_ie_len = 0;
11155         conn_info->resp_ie_len = 0;
11156 }
11157
11158 static unsigned long wl_lock_eq(struct wl_priv *wl)
11159 {
11160         unsigned long flags;
11161
11162         spin_lock_irqsave(&wl->eq_lock, flags);
11163         return flags;
11164 }
11165
11166 static void wl_unlock_eq(struct wl_priv *wl, unsigned long flags)
11167 {
11168         spin_unlock_irqrestore(&wl->eq_lock, flags);
11169 }
11170
11171 static void wl_init_eq_lock(struct wl_priv *wl)
11172 {
11173         spin_lock_init(&wl->eq_lock);
11174 }
11175
11176 static void wl_delay(u32 ms)
11177 {
11178         if (in_atomic() || (ms < jiffies_to_msecs(1))) {
11179                 OSL_DELAY(ms*1000);
11180         } else {
11181                 OSL_SLEEP(ms);
11182         }
11183 }
11184
11185 s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
11186 {
11187         struct wl_priv *wl = wlcfg_drv_priv;
11188         struct ether_addr p2pif_addr;
11189         struct ether_addr primary_mac;
11190         if (!wl->p2p)
11191                 return -1;
11192         if (!p2p_is_on(wl)) {
11193                 get_primary_mac(wl, &primary_mac);
11194                 wl_cfgp2p_generate_bss_mac(&primary_mac, p2pdev_addr, &p2pif_addr);
11195         } else {
11196                 memcpy(p2pdev_addr->octet,
11197                         wl->p2p->dev_addr.octet, ETHER_ADDR_LEN);
11198         }
11199
11200
11201         return 0;
11202 }
11203 s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
11204 {
11205         struct wl_priv *wl;
11206
11207         wl = wlcfg_drv_priv;
11208
11209         return wl_cfgp2p_set_p2p_noa(wl, net, buf, len);
11210 }
11211
11212 s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
11213 {
11214         struct wl_priv *wl;
11215         wl = wlcfg_drv_priv;
11216
11217         return wl_cfgp2p_get_p2p_noa(wl, net, buf, len);
11218 }
11219
11220 s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
11221 {
11222         struct wl_priv *wl;
11223         wl = wlcfg_drv_priv;
11224
11225         return wl_cfgp2p_set_p2p_ps(wl, net, buf, len);
11226 }
11227
11228 s32 wl_cfg80211_channel_to_freq(u32 channel)
11229 {
11230         int freq = 0;
11231
11232 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
11233         freq = ieee80211_channel_to_frequency(channel);
11234 #else
11235         {
11236                 u16 band = 0;
11237                 if (channel <= CH_MAX_2G_CHANNEL)
11238                         band = IEEE80211_BAND_2GHZ;
11239                 else
11240                         band = IEEE80211_BAND_5GHZ;
11241                 freq = ieee80211_channel_to_frequency(channel, band);
11242         }
11243 #endif
11244         return freq;
11245 }
11246
11247 #ifdef WL_SDO
11248 #define MAX_QR_LEN NLMSG_GOODSIZE
11249
11250 typedef struct wl_cfg80211_dev_info {
11251         u16 band;
11252         u16 freq;
11253         s16 rssi;
11254         u16 ie_len;
11255         u8 bssid[ETH_ALEN];
11256 } wl_cfg80211_dev_info_t;
11257
11258 static s32
11259 wl_notify_device_discovery(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
11260         const wl_event_msg_t *e, void *data)
11261 {
11262         int err = 0;
11263         u32 event = ntoh32(e->event_type);
11264         wl_cfg80211_dev_info_t info;
11265         struct wl_bss_info *bi = NULL;
11266         struct net_device *ndev = NULL;
11267         u8 *buf = NULL;
11268         u32 buflen = 0;
11269         u16 channel = 0;
11270          wl_escan_result_t *escan_result;
11271
11272         WL_SD(("Enter. type:%d \n", event));
11273
11274         if ((event != WLC_E_P2PO_ADD_DEVICE) && (event != WLC_E_P2PO_DEL_DEVICE)) {
11275                 WL_ERR(("Unknown Event\n"));
11276                 return -EINVAL;
11277         }
11278
11279         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
11280
11281         mutex_lock(&wl->usr_sync);
11282         if (event == WLC_E_P2PO_DEL_DEVICE) {
11283                 WL_SD(("DEV_LOST MAC:"MACDBG" \n", MAC2STRDBG(e->addr.octet)));
11284                 err = wl_genl_send_msg(ndev, event, (u8 *)e->addr.octet, ETH_ALEN, 0, 0);
11285         } else {
11286
11287                 escan_result = (wl_escan_result_t *) data;
11288
11289                 if (dtoh16(escan_result->bss_count) != 1) {
11290                         WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
11291                         err = -EINVAL;
11292                         goto exit;
11293                 }
11294
11295                 bi = escan_result->bss_info;
11296                 buflen = dtoh32(bi->length);
11297                 if (unlikely(buflen > WL_BSS_INFO_MAX)) {
11298                         WL_DBG(("Beacon is larger than buffer. Discarding\n"));
11299                         err = -EINVAL;
11300                         goto exit;
11301                 }
11302
11303                 /* Update sub-header */
11304                 bzero(&info, sizeof(wl_cfg80211_dev_info_t));
11305                 channel = bi->ctl_ch ? bi->ctl_ch :
11306                         CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
11307                 info.freq = wl_cfg80211_channel_to_freq(channel);
11308                 info.rssi = dtoh16(bi->RSSI);
11309 #if defined(RSSIOFFSET)
11310                 info.rssi = wl_update_rssi_offset(info.rssi);
11311 #endif
11312                 memcpy(info.bssid, &bi->BSSID, ETH_ALEN);
11313                 info.ie_len = buflen;
11314
11315                 WL_SD(("DEV_FOUND band:%x Freq:%d rssi:%x "MACDBG" \n",
11316                         info.band, info.freq, info.rssi, MAC2STRDBG(info.bssid)));
11317
11318                 buf =  ((u8 *) bi) + bi->ie_offset;
11319                 err = wl_genl_send_msg(ndev, event, buf,
11320                         buflen, (u8 *)&info, sizeof(wl_cfg80211_dev_info_t));
11321         }
11322 exit:
11323         mutex_unlock(&wl->usr_sync);
11324         return err;
11325 }
11326
11327 s32
11328 wl_cfg80211_sdo_init(struct wl_priv *wl)
11329 {
11330         u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
11331
11332         if (wl->sdo) {
11333                 WL_SD(("SDO already initialized\n"));
11334                 return 0;
11335         }
11336
11337         wl->sdo = kzalloc(sizeof(sd_offload_t), kflags);
11338         if (!wl->sdo) {
11339                 WL_ERR(("malloc failed for SDO \n"));
11340                 return -ENOMEM;
11341         }
11342
11343         return  0;
11344 }
11345
11346 s32
11347 wl_cfg80211_sdo_deinit(struct wl_priv *wl)
11348 {
11349         s32 bssidx;
11350         int ret = 0;
11351         int sdo_pause = 0;
11352         if (!wl || !wl->p2p) {
11353                 WL_ERR(("Wl %p or wl->p2p %p is null\n",
11354                         wl, wl ? wl->p2p : 0));
11355                 return 0;
11356         }
11357
11358         bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
11359         if (!wl->sdo) {
11360                 WL_DBG(("SDO Not Initialized. Do nothing. \n"));
11361                 return 0;
11362         }
11363         if (wl->sdo->dd_state &&
11364                 (ret = wldev_iovar_setbuf_bsscfg(wl_to_prmry_ndev(wl),
11365                 "p2po_stop", (void*)&sdo_pause, sizeof(sdo_pause),
11366                 wl->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, NULL)) < 0) {
11367                 WL_ERR(("p2po_stop Failed :%d\n", ret));
11368         }
11369         kfree(wl->sdo);
11370         wl->sdo = NULL;
11371
11372         WL_SD(("SDO Deinit Done \n"));
11373
11374         return  0;
11375 }
11376
11377 s32
11378 wl_cfg80211_resume_sdo(struct net_device *dev, struct wl_priv *wl)
11379 {
11380         wl_sd_listen_t sd_listen;
11381         int ret = 0;
11382         s32 bssidx =  wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
11383
11384         WL_DBG(("Enter\n"));
11385
11386         if (!wl->sdo) {
11387                 return -EINVAL;
11388         }
11389
11390         if (dev == NULL)
11391                 dev = wl_to_prmry_ndev(wl);
11392
11393         /* Disable back the ESCAN events for the offload */
11394         wl_add_remove_eventmsg(dev, WLC_E_ESCAN_RESULT, false);
11395
11396         /* Resume according to the saved state */
11397         if (wl->sdo->dd_state == WL_DD_STATE_SEARCH) {
11398                 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_find", NULL, 0,
11399                         wl->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, NULL)) < 0) {
11400                         WL_ERR(("p2po_find Failed :%d\n", ret));
11401                 }
11402         } else if (wl->sdo->dd_state == WL_DD_STATE_LISTEN) {
11403                 sd_listen.interval = wl->sdo->sd_listen.interval;
11404                 sd_listen.period = wl->sdo->sd_listen.period;
11405
11406                 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen", (void*)&sd_listen,
11407                         sizeof(wl_sd_listen_t), wl->ioctl_buf, WLC_IOCTL_SMLEN,
11408                         bssidx, NULL)) < 0) {
11409                         WL_ERR(("p2po_listen Failed :%d\n", ret));
11410                 }
11411
11412         }
11413
11414          /* p2po_stop clears of the eventmask for GAS. Set it back */
11415          wl_add_remove_eventmsg(dev, WLC_E_SERVICE_FOUND, true);
11416          wl_add_remove_eventmsg(dev, WLC_E_GAS_FRAGMENT_RX, true);
11417          wl_add_remove_eventmsg(dev, WLC_E_GAS_COMPLETE, true);
11418
11419         WL_SD(("SDO Resumed \n"));
11420
11421         return ret;
11422 }
11423
11424 s32 wl_cfg80211_pause_sdo(struct net_device *dev, struct wl_priv *wl)
11425 {
11426
11427         int ret = 0;
11428         s32 bssidx =  wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
11429         int sdo_pause = 1;
11430
11431         WL_DBG(("Enter \n"));
11432
11433         if (!wl->sdo) {
11434                 WL_ERR(("SDO not initialized \n"));
11435                 return -EINVAL;
11436         }
11437
11438         if (dev == NULL)
11439                 dev = wl_to_prmry_ndev(wl);
11440
11441         if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_stop",
11442                 (void*)&sdo_pause, sizeof(sdo_pause),
11443                 wl->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, &wl->ioctl_buf_sync)) < 0) {
11444                 WL_ERR(("p2po_stop Failed :%d\n", ret));
11445         }
11446
11447         /* Enable back the ESCAN events for the SCAN */
11448         wl_add_remove_eventmsg(dev, WLC_E_ESCAN_RESULT, true);
11449
11450         WL_SD(("SDO Paused \n"));
11451
11452         return ret;
11453 }
11454
11455 static s32
11456 wl_svc_resp_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
11457         const wl_event_msg_t *e, void *data)
11458 {
11459         u32 event = ntoh32(e->event_type);
11460         struct net_device *ndev = NULL;
11461         u8 *dst_mac = (u8 *)e->addr.octet;
11462         int ret = 0;
11463         wl_event_sd_t *gas = NULL;
11464         int status = ntoh32(e->status);
11465         sdo_event_t sdo_hdr;
11466         u32 data_len = ntoh32(e->datalen);
11467         u8 *data_ptr = NULL;
11468         u32 tot_len = 0;
11469
11470
11471         WL_SD(("Enter event_type:%d status:%d\n", event, status));
11472
11473         if (!wl->sdo) {
11474                 WL_ERR(("SDO Not initialized \n"));
11475                 return -EINVAL;
11476         }
11477
11478         if (!(wl->sdo->sd_state & WL_SD_SEARCH_SVC)) {
11479                 /* We are not searching for any service. Drop
11480                  * any bogus Event
11481                  */
11482                 WL_ERR(("Bogus SDO Event. Do nothing.. \n"));
11483                 return -1;
11484         }
11485
11486         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
11487
11488         mutex_lock(&wl->usr_sync);
11489         if (event == WLC_E_SERVICE_FOUND) {
11490
11491                 if ((status != WLC_E_STATUS_SUCCESS) && (status != WLC_E_STATUS_PARTIAL)) {
11492                         WL_ERR(("WLC_E_SERVICE_FOUND: unknown status \n"));
11493                         goto exit;
11494                 }
11495
11496                 gas = (wl_event_sd_t *)data;
11497                 if (!gas) {
11498                         ret = -EINVAL;
11499                         goto exit;
11500                 }
11501
11502                 bzero(&sdo_hdr, sizeof(sdo_event_t));
11503                 sdo_hdr.freq = wl_cfg80211_channel_to_freq(gas->channel);
11504                 sdo_hdr.count = gas->count;
11505                 memcpy(sdo_hdr.addr, dst_mac, ETH_ALEN);
11506                 data_ptr = (char *)gas->tlv;
11507                 tot_len = data_len - (sizeof(wl_event_sd_t) - sizeof(wl_sd_tlv_t));
11508
11509                 WL_SD(("WLC_E_SERVICE_FOUND "MACDBG" data_len:%d tlv_count:%d \n",
11510                         MAC2STRDBG(dst_mac), data_len, sdo_hdr.count));
11511
11512                 if (tot_len > NLMSG_DEFAULT_SIZE) {
11513                         WL_ERR(("size(%u)  > %lu not supported \n", tot_len, NLMSG_DEFAULT_SIZE));
11514                         ret = -ENOMEM;
11515                         goto exit;
11516                 }
11517
11518                 if (wl_genl_send_msg(ndev, event, data_ptr,
11519                         tot_len, (u8 *)&sdo_hdr, sizeof(sdo_event_t)) < 0)
11520                         WL_ERR(("Couldn't send up the NETLINK Event \n"));
11521                 else
11522                         WL_SD(("GAS event sent up \n"));
11523         } else {
11524                 WL_ERR(("Unsupported Event: %d \n", event));
11525         }
11526
11527 exit:
11528         mutex_unlock(&wl->usr_sync);
11529         return ret;
11530 }
11531
11532 s32 wl_cfg80211_DsdOffloadParseProto(char* proto_str, u8* proto)
11533 {
11534         s32 len = -1;
11535         int i = 0;
11536
11537         for (i = 0; i < MAX_SDO_PROTO; i++) {
11538                 if (strncmp(proto_str, wl_sdo_protos[i].str, strlen(wl_sdo_protos[i].str)) == 0) {
11539                         WL_SD(("Matching proto (%d) found \n", wl_sdo_protos[i].val));
11540                         *proto = wl_sdo_protos[i].val;
11541                         len = strlen(wl_sdo_protos[i].str);
11542                         break;
11543                 }
11544         }
11545         return len;
11546 }
11547
11548 /*
11549  * register to search for a UPnP service
11550  * ./DRIVER P2P_SD_REQ upnp 0x10urn:schemas-upnporg:device:InternetGatewayDevice:1
11551  *
11552  * Enable discovery
11553  * ./wl p2po_find
11554 */
11555 #define UPNP_QUERY_VER_OFFSET 3
11556 s32 wl_sd_handle_sd_req(
11557         struct net_device *dev,
11558         u8 * buf,
11559         int len)
11560 {
11561         struct wl_priv *wl = wlcfg_drv_priv;
11562         s32 bssidx = 0;
11563         wl_sd_qr_t *sdreq;
11564         u8 proto = 0;
11565         s32 ret = 0;
11566         u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
11567         u32 tot_len = len + sizeof(wl_sd_qr_t);
11568         u16 version = 0;
11569
11570         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
11571                 WL_ERR(("find_idx failed\n"));
11572                 return -EINVAL;
11573         }
11574         /* Check for the least arg length expected */
11575         if (!buf || (len < strlen("all"))) {
11576                 WL_ERR(("Wrong Arg\n"));
11577                 return -EINVAL;
11578         }
11579
11580         if (tot_len > WLC_IOCTL_MAXLEN) {
11581                 WL_ERR(("Length > %lu not supported \n", MAX_QR_LEN));
11582                 return -EINVAL;
11583         }
11584
11585         sdreq = kzalloc(tot_len, kflags);
11586         if (!sdreq) {
11587                 WL_ERR(("malloc failed\n"));
11588                 return -ENOMEM;
11589         }
11590
11591         WL_SD(("%s Len: %d\n", buf, len));
11592         if ((ret = wl_cfg80211_DsdOffloadParseProto(buf, &proto)) < 0) {
11593                 WL_ERR(("Unknown proto \n"));
11594                 goto exit;
11595         }
11596
11597         sdreq->protocol = proto;
11598         buf += ret;
11599         buf++; /* skip the space */
11600         sdreq->transaction_id = simple_strtoul(buf, NULL, 16);
11601         WL_SD(("transaction_id:%d\n", sdreq->transaction_id));
11602         buf += sizeof(sdreq->transaction_id);
11603
11604         if (*buf == '\0') {
11605                 WL_SD(("No Query present. Proto:%d \n", proto));
11606                 sdreq->query_len = 0;
11607         } else {
11608                 buf++; /* skip the space */
11609                 /* UPNP version needs to put as binary val */
11610                 if (sdreq->protocol == SVC_RPOTYPE_UPNP) {
11611                         /* Extract UPNP version */
11612                         version = simple_strtoul(buf, NULL, 16);
11613                         buf = buf + UPNP_QUERY_VER_OFFSET;
11614                         buf[0] = version;
11615                         WL_SD(("Upnp version: 0x%x \n", version));
11616                 }
11617
11618                 len = strlen(buf);
11619                 WL_SD(("Len after stripping proto: %d Query: %s\n", len, buf));
11620                 /* copy the query part */
11621                 memcpy(sdreq->qrbuf, buf, len);
11622                 sdreq->query_len = len;
11623         }
11624
11625         /* Enable discovery */
11626         if ((ret = wl_cfgp2p_enable_discovery(wl, dev, NULL, 0)) < 0) {
11627                 WL_ERR(("cfgp2p_enable discovery failed"));
11628                 goto exit;
11629         }
11630
11631         if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_sd_req_resp", (void*)sdreq,
11632                 tot_len, wl->ioctl_buf, WLC_IOCTL_MAXLEN,
11633                 bssidx, &wl->ioctl_buf_sync)) < 0) {
11634                 WL_ERR(("Find SVC Failed \n"));
11635                 goto exit;
11636         }
11637
11638         wl->sdo->sd_state |= WL_SD_SEARCH_SVC;
11639
11640 exit:
11641         kfree(sdreq);
11642         return ret;
11643 }
11644
11645 s32 wl_sd_handle_sd_cancel_req(
11646         struct net_device *dev,
11647         u8 *buf)
11648 {
11649         struct wl_priv *wl = wlcfg_drv_priv;
11650         s32 bssidx =  wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
11651
11652         if (wldev_iovar_setbuf_bsscfg(dev, "p2po_sd_cancel", NULL,
11653                 0, wl->ioctl_buf, WLC_IOCTL_SMLEN,
11654                 bssidx, &wl->ioctl_buf_sync) < 0) {
11655                 WL_ERR(("Cancel SD Failed \n"));
11656                 return -EINVAL;
11657         }
11658
11659         wl->sdo->sd_state &= ~WL_SD_SEARCH_SVC;
11660
11661         return 0;
11662 }
11663
11664 /*
11665  * register a UPnP service to be discovered
11666  * ./wl P2P_SD_SVC_ADD upnp 0x10urn:schemas-upnporg:device:InternetGatewayDevice:1 0x10uu
11667  * id:6859dede-8574-59ab-9332-123456789012::urn:schemas-upnporg:device:InternetGate
11668  * wayDevice:1
11669 */
11670 s32 wl_sd_handle_sd_add_svc(
11671         struct net_device *dev,
11672         u8 * buf,
11673         int len)
11674 {
11675         struct wl_priv *wl = wlcfg_drv_priv;
11676         s32 bssidx = 0;
11677         wl_sd_qr_t *sdreq;
11678         u8 proto = 0;
11679         u16 version = 0;
11680         s32 ret = 0;
11681         u8 *resp = NULL;
11682         u8 *query = NULL;
11683         u32 tot_len = len + sizeof(wl_sd_qr_t);
11684         u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
11685
11686         if (!buf || !len)
11687                 return -EINVAL;
11688
11689         WL_SD(("%s Len: %d\n", buf, len));
11690         if (tot_len > WLC_IOCTL_MAXLEN) {
11691                 WL_ERR(("Query-Resp length > %d not supported \n", WLC_IOCTL_MAXLEN));
11692                 return -ENOMEM;
11693         }
11694
11695         sdreq = kzalloc(tot_len, kflags);
11696         if (!sdreq) {
11697                 WL_ERR(("malloc failed\n"));
11698                 return -ENOMEM;
11699         }
11700
11701         if ((ret = wl_cfg80211_DsdOffloadParseProto(buf, &proto)) < 0) {
11702                 WL_ERR(("Unknown Proto \n"));
11703                 goto exit;
11704         }
11705
11706         sdreq->protocol = proto;
11707         buf += ret;
11708
11709         if (*buf == '\0') {
11710                 WL_ERR(("No Query Resp pair present \n"));
11711                 ret = -EINVAL;
11712                 goto exit;
11713         }
11714
11715         buf++; /* Skip the space */
11716         len = strlen(buf);
11717         query = strsep((char **)&buf, " ");
11718         if (!query || !buf) {
11719                 WL_ERR(("No Query RESP Present\n"));
11720                 ret = -EINVAL;
11721                 goto exit;
11722         }
11723         resp = buf;
11724
11725         if (sdreq->protocol == SVC_RPOTYPE_UPNP) {
11726                 /* Extract UPNP version */
11727                 version = simple_strtoul(query, NULL, 16);
11728                 query = query + UPNP_QUERY_VER_OFFSET;
11729                 resp = resp + UPNP_QUERY_VER_OFFSET;
11730                 query[0] = version;
11731                 resp[0] = version;
11732                 WL_SD(("Upnp version: 0x%x \n", version));
11733         }
11734
11735         sdreq->query_len = strlen(query);
11736         sdreq->response_len = strlen(buf);
11737         WL_SD(("query:%s len:%u \n", query, sdreq->query_len));
11738         WL_SD(("resp:%s len:%u \n", buf, sdreq->response_len));
11739
11740         memcpy(sdreq->qrbuf, query, sdreq->query_len);
11741         memcpy((sdreq->qrbuf + sdreq->query_len), resp, sdreq->response_len);
11742
11743         /* Enable discovery */
11744         if ((ret = wl_cfgp2p_enable_discovery(wl, dev, NULL, 0)) < 0) {
11745                 WL_ERR(("cfgp2p_enable discovery failed"));
11746                 goto exit;
11747         }
11748
11749         if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_addsvc", (void*)sdreq,
11750                 tot_len, wl->ioctl_buf, WLC_IOCTL_MAXLEN,
11751                 bssidx, &wl->ioctl_buf_sync)) < 0) {
11752                 WL_ERR(("FW Failed in doing p2po_addsvc. RET:%d \n", ret));
11753                 goto exit;
11754         }
11755
11756         wl->sdo->sd_state |= WL_SD_ADV_SVC;
11757
11758 exit:
11759         kfree(sdreq);
11760         return ret;
11761 }
11762
11763 s32 wl_sd_handle_sd_del_svc(
11764         struct net_device *dev,
11765         u8 * buf,
11766         int len)
11767 {
11768         struct wl_priv *wl = wlcfg_drv_priv;
11769         s32 bssidx = 0;
11770         wl_sd_qr_t *sdreq;
11771         u8 proto = 0;
11772         s32 ret = 0;
11773         u32 tot_len = len + sizeof(wl_sd_qr_t);
11774         u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
11775         u16 version = 0;
11776
11777         if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
11778                 WL_ERR(("find_idx failed\n"));
11779                 return -EINVAL;
11780         }
11781
11782         sdreq = (wl_sd_qr_t *)kzalloc(tot_len, kflags);
11783         if (!sdreq) {
11784                 WL_ERR(("malloc failed\n"));
11785                 ret = -ENOMEM;
11786                 goto exit;
11787         }
11788
11789         /* Check for the least arg length expected */
11790         if (buf && len >= strlen("all")) {
11791                 WL_DBG(("%s Len: %d\n", buf, len));
11792                 if ((ret = wl_cfg80211_DsdOffloadParseProto(buf, &proto)) < 0) {
11793                         WL_ERR(("Unknown Proto \n"));
11794                         goto exit;
11795                 }
11796                 sdreq->protocol = proto;
11797                 buf += ret;
11798
11799                 if (*buf == ' ') {
11800                         /* Query present */
11801                         buf++; /* Skip the space */
11802                         /* UPNP version needs to put as binary val */
11803                         if (sdreq->protocol == SVC_RPOTYPE_UPNP) {
11804                                 /* Extract UPNP version */
11805                                 version = simple_strtoul(buf, NULL, 16);
11806                                 buf = buf + UPNP_QUERY_VER_OFFSET;
11807                                 buf[0] = version;
11808                                 WL_SD(("Upnp version: 0x%x \n", version));
11809                         }
11810                         memcpy(sdreq->qrbuf, buf, strlen(buf));
11811                         sdreq->query_len = strlen(buf);
11812                         WL_SD(("Query to be deleted:%s len:%d\n", buf, sdreq->query_len));
11813                 }
11814         } else {
11815                 /* ALL */
11816                 proto = 0;
11817         }
11818
11819         sdreq->protocol = proto;
11820         WL_SD(("Proto: %d \n", proto));
11821
11822         if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_delsvc", (void*)sdreq,
11823                 tot_len, wl->ioctl_buf, WLC_IOCTL_MAXLEN,
11824                 bssidx, &wl->ioctl_buf_sync)) < 0) {
11825                 WL_ERR(("FW Failed in doing sd_delsvc. ret=%d \n", ret));
11826                 goto exit;
11827         }
11828
11829         wl->sdo->sd_state &= ~WL_SD_ADV_SVC;
11830
11831 exit:
11832         if (sdreq)
11833                 kfree(sdreq);
11834
11835         return ret;
11836 }
11837
11838 s32 wl_sd_handle_sd_stop_discovery(
11839         struct net_device *dev,
11840         u8 * buf,
11841         int len)
11842 {
11843         struct wl_priv *wl = wlcfg_drv_priv;
11844         s32 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
11845         int ret = 0;
11846         int sdo_pause = 0;
11847
11848         if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_stop", (void*)&sdo_pause,
11849                 sizeof(sdo_pause), wl->ioctl_buf, WLC_IOCTL_SMLEN,
11850                 bssidx, &wl->ioctl_buf_sync)) < 0) {
11851                 WL_ERR(("p2po_stop Failed :%d\n", ret));
11852                 return -1;
11853         }
11854
11855         if (wldev_iovar_setint(dev, "mpc", 1) < 0) {
11856                 /* Setting of MPC failed */
11857                 WL_ERR(("mpc enabling back failed\n"));
11858                 return -1;
11859         }
11860
11861         /* clear the states */
11862         wl->sdo->dd_state = WL_DD_STATE_IDLE;
11863         wl_clr_p2p_status(wl, DISC_IN_PROGRESS);
11864
11865         bzero(&wl->sdo->sd_listen, sizeof(wl_sd_listen_t));
11866
11867         /* Remove ESCAN from waking up the host if ofind/olisten is enabled */
11868         wl_add_remove_eventmsg(dev, WLC_E_ESCAN_RESULT, true);
11869
11870         return ret;
11871 }
11872
11873 s32 wl_sd_handle_sd_find(
11874         struct net_device *dev,
11875         u8 * buf,
11876         int len)
11877 {
11878         struct wl_priv *wl = wlcfg_drv_priv;
11879         s32 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
11880         int ret = 0;
11881         s32 disc_bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
11882         vndr_ie_setbuf_t *ie_setbuf;
11883         vndr_ie_t *vndrie;
11884         vndr_ie_buf_t *vndriebuf;
11885         u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
11886         int tot_len = 0;
11887         uint channel = 0;
11888
11889         u8 p2pie_buf[] = {
11890                                 0x09, 0x02, 0x02, 0x00, 0x27, 0x0c, 0x06, 0x05, 0x00,
11891                                 0x55, 0x53, 0x04, 0x51, 0x0b, 0x11, 0x05, 0x00, 0x55,
11892                                 0x53, 0x04, 0x51, 0x0b
11893                           };
11894
11895         /* Enable discovery */
11896         if ((ret = wl_cfgp2p_enable_discovery(wl, dev, NULL, 0)) < 0) {
11897                 WL_ERR(("cfgp2p_enable discovery failed"));
11898                 return -1;
11899         }
11900
11901         if (buf && strncmp(buf, "chan=", strlen("chan=")) == 0) {
11902                 buf += strlen("chan=");
11903                 channel = simple_strtol(buf, NULL, 10);
11904                 WL_SD(("listen_chan to be set:%d\n", channel));
11905                 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen_channel", (void*)&channel,
11906                         sizeof(channel), wl->ioctl_buf, WLC_IOCTL_SMLEN,
11907                         bssidx, &wl->ioctl_buf_sync)) < 0) {
11908                                 WL_ERR(("p2po_listen_channel Failed :%d\n", ret));
11909                                 return -1;
11910                 }
11911         }
11912
11913         tot_len = sizeof(vndr_ie_setbuf_t) + sizeof(p2pie_buf);
11914         ie_setbuf = (vndr_ie_setbuf_t *) kzalloc(tot_len, kflags);
11915         if (!ie_setbuf) {
11916                 WL_ERR(("IE memory alloc failed\n"));
11917                 return -ENOMEM;
11918         }
11919
11920         /* Apply the p2p_ie for p2po_find */
11921         strcpy(ie_setbuf->cmd, "add");
11922
11923         vndriebuf = &ie_setbuf->vndr_ie_buffer;
11924         vndriebuf->iecount = htod32(1);
11925         vndriebuf->vndr_ie_list[0].pktflag =  htod32(16);
11926
11927         vndrie =  &vndriebuf->vndr_ie_list[0].vndr_ie_data;
11928
11929         vndrie->id = (uchar) DOT11_MNG_PROPR_ID;
11930         vndrie->len = sizeof(p2pie_buf);
11931         memcpy(vndrie->oui, WFA_OUI, WFA_OUI_LEN);
11932         memcpy(vndrie->data, p2pie_buf, sizeof(p2pie_buf));
11933
11934         /* Remove ESCAN from waking up the host if SDO is enabled */
11935         wl_add_remove_eventmsg(dev, WLC_E_ESCAN_RESULT, false);
11936
11937         if (wldev_iovar_setbuf_bsscfg(dev, "ie", (void*)ie_setbuf,
11938                 tot_len, wl->ioctl_buf, WLC_IOCTL_SMLEN,
11939                 disc_bssidx, &wl->ioctl_buf_sync) < 0) {
11940                 WL_ERR(("p2p add_ie failed \n"));
11941                 ret = -EINVAL;
11942                 goto exit;
11943         } else
11944                 WL_SD(("p2p add_ie applied successfully len:%d \n", tot_len));
11945
11946         if (wldev_iovar_setint(dev, "mpc", 0) < 0) {
11947                 /* Setting of MPC failed */
11948                 WL_ERR(("mpc disabling faild\n"));
11949                 ret = -1;
11950                 goto exit;
11951         }
11952
11953         if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_find", NULL, 0,
11954                 wl->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, &wl->ioctl_buf_sync)) < 0) {
11955                 WL_ERR(("p2po_find Failed :%d\n", ret));
11956                 ret = -1;
11957                 goto exit;
11958         }
11959
11960         /* set the states */
11961         wl->sdo->dd_state = WL_DD_STATE_SEARCH;
11962         wl_set_p2p_status(wl, DISC_IN_PROGRESS);
11963
11964 exit:
11965         if (ie_setbuf)
11966                 kfree(ie_setbuf);
11967
11968         /* Incase of failure enable back the ESCAN event */
11969         if (ret)
11970                 wl_add_remove_eventmsg(dev, WLC_E_ESCAN_RESULT, true);
11971
11972         return ret;
11973 }
11974
11975 s32 wl_sd_handle_sd_listen(
11976         struct net_device *dev,
11977         u8 *buf,
11978         int len)
11979 {
11980         struct wl_priv *wl = wlcfg_drv_priv;
11981         s32 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
11982         wl_sd_listen_t sd_listen;
11983         int ret = 0;
11984         u8 * ptr = NULL;
11985         uint channel = 0;
11986
11987         /* Just in case if it is not enabled */
11988         if ((ret = wl_cfgp2p_enable_discovery(wl, dev, NULL, 0)) < 0) {
11989                 WL_ERR(("cfgp2p_enable discovery failed"));
11990                 return -1;
11991         }
11992
11993         if (wldev_iovar_setint(dev, "mpc", 0) < 0) {
11994                 /* Setting of MPC failed */
11995                 WL_ERR(("mpc disabling faild\n"));
11996                 return -1;
11997         }
11998
11999         bzero(&sd_listen, sizeof(wl_sd_listen_t));
12000
12001         if (len) {
12002                 ptr = strsep((char **)&buf, " ");
12003                 if (ptr == NULL) {
12004                         /* period and duration given wrongly */
12005                         WL_ERR(("Arguments in wrong format \n"));
12006                         return -EINVAL;
12007                 }
12008                 else if (strncmp(ptr, "chan=", strlen("chan=")) == 0) {
12009                         sd_listen.interval = 65535;
12010                         sd_listen.period = 65535;
12011                         ptr += strlen("chan=");
12012                         channel = simple_strtol(ptr, NULL, 10);
12013                 }
12014                 else {
12015                         sd_listen.period = simple_strtol(ptr, NULL, 10);
12016                         ptr = strsep((char **)&buf, " ");
12017                         if (ptr == NULL) {
12018                                 WL_ERR(("Arguments in wrong format \n"));
12019                                 return -EINVAL;
12020                         }
12021                         sd_listen.interval = simple_strtol(ptr, NULL, 10);
12022                         if (buf && strncmp(buf, "chan=", strlen("chan=")) == 0) {
12023                                 buf += strlen("chan=");
12024                                 channel = simple_strtol(buf, NULL, 10);
12025                         }
12026                 }
12027                 WL_SD(("listen_period:%d, listen_interval:%d and listen_channel:%d\n",
12028                         sd_listen.period, sd_listen.interval, channel));
12029         }
12030         if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen_channel", (void*)&channel,
12031                 sizeof(channel), wl->ioctl_buf, WLC_IOCTL_SMLEN,
12032                 bssidx, &wl->ioctl_buf_sync)) < 0) {
12033                         WL_ERR(("p2po_listen_channel Failed :%d\n", ret));
12034                         return -1;
12035         }
12036
12037         WL_SD(("p2po_listen period:%d  interval:%d \n",
12038                 sd_listen.period, sd_listen.interval));
12039         if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen", (void*)&sd_listen,
12040                 sizeof(wl_sd_listen_t), wl->ioctl_buf, WLC_IOCTL_SMLEN,
12041                 bssidx, &wl->ioctl_buf_sync)) < 0) {
12042                 WL_ERR(("p2po_listen Failed :%d\n", ret));
12043                 return -1;
12044         }
12045
12046         /* Remove ESCAN from waking up the host if ofind/olisten is enabled */
12047         wl_add_remove_eventmsg(dev, WLC_E_ESCAN_RESULT, false);
12048
12049         /* Store the extended listen values for use in sdo_resume */
12050         wl->sdo->sd_listen.interval = sd_listen.interval;
12051         wl->sdo->sd_listen.period = sd_listen.period;
12052
12053         /* set the states */
12054         wl->sdo->dd_state = WL_DD_STATE_LISTEN;
12055         wl_set_p2p_status(wl, DISC_IN_PROGRESS);
12056
12057         return 0;
12058 }
12059
12060 s32 wl_cfg80211_sd_offload(struct net_device *dev, char *cmd, char* buf, int len)
12061 {
12062         int ret = 0;
12063         struct wl_priv *wl = wlcfg_drv_priv;
12064
12065         WL_SD(("Entry cmd:%s arg_len:%d \n", cmd, len));
12066
12067         if (!wl->sdo) {
12068                 WL_SD(("Initializing SDO \n"));
12069                 if ((ret = wl_cfg80211_sdo_init(wl)) < 0)
12070                         goto exit;
12071         }
12072
12073         if (strncmp(cmd, "P2P_SD_REQ", strlen("P2P_SD_REQ")) == 0) {
12074                 ret = wl_sd_handle_sd_req(dev, buf, len);
12075         } else if (strncmp(cmd, "P2P_SD_CANCEL_REQ", strlen("P2P_SD_CANCEL_REQ")) == 0) {
12076                 ret = wl_sd_handle_sd_cancel_req(dev, buf);
12077         } else if (strncmp(cmd, "P2P_SD_SVC_ADD", strlen("P2P_SD_SVC_ADD")) == 0) {
12078                 ret = wl_sd_handle_sd_add_svc(dev, buf, len);
12079         } else if (strncmp(cmd, "P2P_SD_SVC_DEL", strlen("P2P_SD_SVC_DEL")) == 0) {
12080                 ret = wl_sd_handle_sd_del_svc(dev, buf, len);
12081         } else if (strncmp(cmd, "P2P_SD_FIND", strlen("P2P_SD_FIND")) == 0) {
12082                 ret = wl_sd_handle_sd_find(dev, buf, len);
12083         } else if (strncmp(cmd, "P2P_SD_LISTEN", strlen("P2P_SD_LISTEN")) == 0) {
12084                 ret = wl_sd_handle_sd_listen(dev, buf, len);
12085         } else if (strncmp(cmd, "P2P_SD_STOP", strlen("P2P_STOP")) == 0) {
12086                 ret = wl_sd_handle_sd_stop_discovery(dev, buf, len);
12087         } else {
12088                 WL_ERR(("Request for Unsupported CMD:%s \n", buf));
12089                 ret = -EINVAL;
12090         }
12091
12092 exit:
12093         return ret;
12094 }
12095 #endif /* WL_SDO */
12096
12097 #ifdef WLTDLS
12098 static s32
12099 wl_tdls_event_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
12100         const wl_event_msg_t *e, void *data) {
12101
12102         struct net_device *ndev = NULL;
12103         u32 reason = ntoh32(e->reason);
12104         s8 *msg = NULL;
12105
12106         ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
12107
12108         switch (reason) {
12109         case WLC_E_TDLS_PEER_DISCOVERED :
12110                 msg = " TDLS PEER DISCOVERD ";
12111                 break;
12112         case WLC_E_TDLS_PEER_CONNECTED :
12113                 msg = " TDLS PEER CONNECTED ";
12114                 break;
12115         case WLC_E_TDLS_PEER_DISCONNECTED :
12116                 msg = "TDLS PEER DISCONNECTED ";
12117                 break;
12118         }
12119         if (msg) {
12120                 WL_ERR(("%s: " MACDBG " on %s ndev\n", msg, MAC2STRDBG((u8*)(&e->addr)),
12121                         (wl_to_prmry_ndev(wl) == ndev) ? "primary" : "secondary"));
12122         }
12123         return 0;
12124
12125 }
12126 #endif  /* WLTDLS */
12127
12128 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS)
12129 static s32
12130 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
12131         u8 *peer, enum nl80211_tdls_operation oper)
12132 {
12133         s32 ret = 0;
12134 #ifdef WLTDLS
12135         struct wl_priv *wl = wlcfg_drv_priv;
12136         tdls_iovar_t info;
12137         dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
12138         memset(&info, 0, sizeof(tdls_iovar_t));
12139         if (peer)
12140                 memcpy(&info.ea, peer, ETHER_ADDR_LEN);
12141         switch (oper) {
12142         case NL80211_TDLS_DISCOVERY_REQ:
12143                 if (!dhd->tdls_enable)
12144                         ret = dhd_tdls_enable_disable(dhd, 1);
12145                 if (ret < 0)
12146                         return ret;
12147                 info.mode = TDLS_MANUAL_EP_DISCOVERY;
12148                 break;
12149         case NL80211_TDLS_SETUP:
12150                 info.mode = TDLS_MANUAL_EP_CREATE;
12151                 break;
12152         case NL80211_TDLS_TEARDOWN:
12153                 info.mode = TDLS_MANUAL_EP_DELETE;
12154                 break;
12155         default:
12156                 WL_ERR(("Unsupported operation : %d\n", oper));
12157                 goto out;
12158         }
12159         ret = wldev_iovar_setbuf(dev, "tdls_endpoint", &info, sizeof(info),
12160                 wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
12161         if (ret) {
12162                 WL_ERR(("tdls_endpoint error %d\n", ret));
12163         }
12164 out:
12165 #endif /* WLTDLS */
12166         return ret;
12167 }
12168 #endif /* LINUX_VERSION > VERSION(3,2,0) || WL_COMPAT_WIRELESS */
12169
12170 s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
12171         enum wl_management_type type)
12172 {
12173         struct wl_priv *wl;
12174         struct net_device *ndev = NULL;
12175         struct ether_addr primary_mac;
12176         s32 ret = 0;
12177         s32 bssidx = 0;
12178         s32 pktflag = 0;
12179         wl = wlcfg_drv_priv;
12180
12181         if (wl_get_drv_status(wl, AP_CREATING, net)) {
12182                 /* Vendor IEs should be set to FW
12183                  * after SoftAP interface is brought up
12184                  */
12185                 goto exit;
12186         } else if (wl_get_drv_status(wl, AP_CREATED, net)) {
12187                 ndev = net;
12188                 bssidx = 0;
12189         } else if (wl->p2p) {
12190                 net = ndev_to_wlc_ndev(net, wl);
12191                 if (!wl->p2p->on) {
12192                         get_primary_mac(wl, &primary_mac);
12193                         wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr,
12194                                 &wl->p2p->int_addr);
12195                         /* In case of p2p_listen command, supplicant send remain_on_channel
12196                         * without turning on P2P
12197                         */
12198
12199                         p2p_on(wl) = true;
12200                         ret = wl_cfgp2p_enable_discovery(wl, net, NULL, 0);
12201
12202                         if (unlikely(ret)) {
12203                                 goto exit;
12204                         }
12205                 }
12206                 if (net  != wl_to_prmry_ndev(wl)) {
12207                         if (wl_get_mode_by_netdev(wl, net) == WL_MODE_AP) {
12208                                 ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
12209                                 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION);
12210                         }
12211                 } else {
12212                                 ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY);
12213                                 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
12214                 }
12215         }
12216         if (ndev != NULL) {
12217                 switch (type) {
12218                         case WL_BEACON:
12219                                 pktflag = VNDR_IE_BEACON_FLAG;
12220                                 break;
12221                         case WL_PROBE_RESP:
12222                                 pktflag = VNDR_IE_PRBRSP_FLAG;
12223                                 break;
12224                         case WL_ASSOC_RESP:
12225                                 pktflag = VNDR_IE_ASSOCRSP_FLAG;
12226                                 break;
12227                 }
12228                 if (pktflag)
12229                         ret = wl_cfgp2p_set_management_ie(wl, ndev, bssidx, pktflag, buf, len);
12230         }
12231 exit:
12232         return ret;
12233 }
12234
12235 #ifdef WL_SUPPORT_AUTO_CHANNEL
12236 static s32
12237 wl_cfg80211_set_auto_channel_scan_state(struct net_device *ndev)
12238 {
12239         u32 val = 0;
12240         s32 ret = BCME_ERROR;
12241         struct wl_priv *wl = wlcfg_drv_priv;
12242
12243         /* Disable mpc, to avoid automatic interface down. */
12244         val = 0;
12245
12246         ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
12247                 sizeof(val), wl->ioctl_buf, WLC_IOCTL_SMLEN, 0,
12248                 &wl->ioctl_buf_sync);
12249         if (ret < 0) {
12250                 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
12251                 goto done;
12252         }
12253
12254         /* Set interface up, explicitly. */
12255         val = 1;
12256
12257         ret = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
12258         if (ret < 0) {
12259                 WL_ERR(("set interface up failed, error = %d\n", ret));
12260                 goto done;
12261         }
12262
12263         /* Stop all scan explicitly, till auto channel selection complete. */
12264         wl_set_drv_status(wl, SCANNING, ndev);
12265         ret = wl_notify_escan_complete(wl, ndev, true, true);
12266         if (ret < 0) {
12267                 WL_ERR(("set scan abort failed, error = %d\n", ret));
12268                 ret = BCME_OK; // terence 20140115: fix escan_complete error
12269                 goto done;
12270         }
12271
12272 done:
12273         return ret;
12274 }
12275
12276 static bool
12277 wl_cfg80211_valid_chanspec_p2p(chanspec_t chanspec)
12278 {
12279         bool valid = false;
12280
12281         /* channel 1 to 14 */
12282         if ((chanspec >= 0x2b01) && (chanspec <= 0x2b0e)) {
12283                 valid = true;
12284         }
12285         /* channel 36 to 48 */
12286         else if ((chanspec >= 0x1b24) && (chanspec <= 0x1b30)) {
12287                 valid = true;
12288         }
12289         /* channel 149 to 161 */
12290         else if ((chanspec >= 0x1b95) && (chanspec <= 0x1ba1)) {
12291                 valid = true;
12292         }
12293         else {
12294                 valid = false;
12295                 WL_INFO(("invalid P2P chanspec, channel = %d, chanspec = %04x\n",
12296                         CHSPEC_CHANNEL(chanspec), chanspec));
12297         }
12298
12299         return valid;
12300 }
12301
12302 static s32
12303 wl_cfg80211_get_chanspecs_2g(struct net_device *ndev, void *buf, s32 buflen)
12304 {
12305         s32 ret = BCME_ERROR;
12306         struct wl_priv *wl = NULL;
12307         wl_uint32_list_t *list = NULL;
12308         chanspec_t chanspec = 0;
12309
12310         memset(buf, 0, buflen);
12311
12312         wl = wlcfg_drv_priv;
12313         list = (wl_uint32_list_t *)buf;
12314         list->count = htod32(WL_NUMCHANSPECS);
12315
12316         /* Restrict channels to 2.4GHz, 20MHz BW, no SB. */
12317         chanspec |= (WL_CHANSPEC_BAND_2G | WL_CHANSPEC_BW_20 |
12318                 WL_CHANSPEC_CTL_SB_NONE);
12319         chanspec = wl_chspec_host_to_driver(chanspec);
12320
12321         ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
12322                 sizeof(chanspec), buf, buflen, 0, &wl->ioctl_buf_sync);
12323         if (ret < 0) {
12324                 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
12325         }
12326
12327         return ret;
12328 }
12329
12330 static s32
12331 wl_cfg80211_get_chanspecs_5g(struct net_device *ndev, void *buf, s32 buflen)
12332 {
12333         u32 channel = 0;
12334         s32 ret = BCME_ERROR;
12335         s32 i = 0;
12336         s32 j = 0;
12337         struct wl_priv *wl = NULL;
12338         wl_uint32_list_t *list = NULL;
12339         chanspec_t chanspec = 0;
12340
12341         memset(buf, 0, buflen);
12342
12343         wl = wlcfg_drv_priv;
12344         list = (wl_uint32_list_t *)buf;
12345         list->count = htod32(WL_NUMCHANSPECS);
12346
12347         /* Restrict channels to 5GHz, 20MHz BW, no SB. */
12348         chanspec |= (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_20 |
12349                 WL_CHANSPEC_CTL_SB_NONE);
12350         chanspec = wl_chspec_host_to_driver(chanspec);
12351
12352         ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
12353                 sizeof(chanspec), buf, buflen, 0, &wl->ioctl_buf_sync);
12354         if (ret < 0) {
12355                 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
12356                 goto done;
12357         }
12358
12359         /* Skip DFS and inavlid P2P channel. */
12360         for (i = 0, j = 0; i < dtoh32(list->count); i++) {
12361                 chanspec = (chanspec_t) dtoh32(list->element[i]);
12362                 channel = CHSPEC_CHANNEL(chanspec);
12363
12364                 ret = wldev_iovar_getint(ndev, "per_chan_info", &channel);
12365                 if (ret < 0) {
12366                         WL_ERR(("get 'per_chan_info' failed, error = %d\n", ret));
12367                         goto done;
12368                 }
12369
12370                 if (CHANNEL_IS_RADAR(channel) ||
12371                         !(wl_cfg80211_valid_chanspec_p2p(chanspec))) {
12372                         continue;
12373                 } else {
12374                         list->element[j] = list->element[i];
12375                 }
12376
12377                 j++;
12378         }
12379
12380         list->count = j;
12381
12382 done:
12383         return ret;
12384 }
12385
12386 static s32
12387 wl_cfg80211_get_best_channel(struct net_device *ndev, void *buf, int buflen,
12388         int *channel)
12389 {
12390         s32 ret = BCME_ERROR;
12391         int chosen = 0;
12392         int retry = 0;
12393
12394         /* Start auto channel selection scan. */
12395         ret = wldev_ioctl(ndev, WLC_START_CHANNEL_SEL, buf, buflen, true);
12396         if (ret < 0) {
12397                 WL_ERR(("can't start auto channel scan, error = %d\n", ret));
12398                 *channel = 0;
12399                 goto done;
12400         }
12401
12402         /* Wait for auto channel selection, worst case possible delay is 5250ms. */
12403         retry = CHAN_SEL_RETRY_COUNT;
12404
12405         while (retry--) {
12406                 OSL_SLEEP(CHAN_SEL_IOCTL_DELAY);
12407
12408                 ret = wldev_ioctl(ndev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen),
12409                         false);
12410                 if ((ret == 0) && (dtoh32(chosen) != 0)) {
12411                         if (dhd_bus_chip_id(bcmsdh_get_drvdata()) != BCM43362_CHIP_ID &&
12412                                 dhd_bus_chip_id(bcmsdh_get_drvdata()) != BCM4330_CHIP_ID) {
12413                                 u32 chanspec = 0;
12414                                 int ctl_chan;
12415                                 chanspec = wl_chspec_driver_to_host(chosen);
12416                                 printf("selected chanspec = 0x%x\n", chanspec);
12417                                 ctl_chan = wf_chspec_ctlchan(chanspec);
12418                                 printf("selected ctl_chan = 0x%x\n", ctl_chan);
12419                                 *channel = (u16)(ctl_chan & 0x00FF);
12420                         } else
12421                                 *channel = (u16)(chosen & 0x00FF);
12422                         WL_INFO(("selected channel = %d\n", *channel));
12423                         break;
12424                 }
12425                 WL_INFO(("attempt = %d, ret = %d, chosen = %d\n",
12426                         (CHAN_SEL_RETRY_COUNT - retry), ret, dtoh32(chosen)));
12427         }
12428
12429         if (retry <= 0) {
12430                 WL_ERR(("failure, auto channel selection timed out\n"));
12431                 *channel = 0;
12432                 ret = BCME_ERROR;
12433         }
12434
12435 done:
12436         return ret;
12437 }
12438
12439 static s32
12440 wl_cfg80211_restore_auto_channel_scan_state(struct net_device *ndev)
12441 {
12442         u32 val = 0;
12443         s32 ret = BCME_ERROR;
12444         struct wl_priv *wl = wlcfg_drv_priv;
12445
12446         /* Clear scan stop driver status. */
12447         wl_clr_drv_status(wl, SCANNING, ndev);
12448
12449         /* Enable mpc back to 1, irrespective of initial state. */
12450         val = 1;
12451
12452         ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
12453                 sizeof(val), wl->ioctl_buf, WLC_IOCTL_SMLEN, 0,
12454                 &wl->ioctl_buf_sync);
12455         if (ret < 0) {
12456                 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
12457         }
12458
12459         return ret;
12460 }
12461
12462 s32
12463 wl_cfg80211_get_best_channels(struct net_device *dev, char* cmd, int total_len)
12464 {
12465         int channel = 0, band, band_cur;
12466         s32 ret = BCME_ERROR;
12467         u8 *buf = NULL;
12468         char *pos = cmd;
12469         struct wl_priv *wl = NULL;
12470         struct net_device *ndev = NULL;
12471
12472         memset(cmd, 0, total_len);
12473
12474         buf = kmalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
12475         if (buf == NULL) {
12476                 WL_ERR(("failed to allocate chanspec buffer\n"));
12477                 return -ENOMEM;
12478         }
12479
12480         /*
12481          * Always use primary interface, irrespective of interface on which
12482          * command came.
12483          */
12484         wl = wlcfg_drv_priv;
12485         ndev = wl_to_prmry_ndev(wl);
12486
12487         /*
12488          * Make sure that FW and driver are in right state to do auto channel
12489          * selection scan.
12490          */
12491         ret = wl_cfg80211_set_auto_channel_scan_state(ndev);
12492         if (ret < 0) {
12493                 WL_ERR(("can't set auto channel scan state, error = %d\n", ret));
12494                 goto done;
12495         }
12496
12497         /* Best channel selection in 2.4GHz band. */
12498         ret = wl_cfg80211_get_chanspecs_2g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
12499         if (ret < 0) {
12500                 WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
12501                 goto done;
12502         }
12503
12504         ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
12505                 &channel);
12506         if (ret < 0) {
12507                 WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
12508                 goto done;
12509         }
12510
12511         if (CHANNEL_IS_2G(channel)) {
12512                 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
12513         } else {
12514                 WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel));
12515                 channel = 0;
12516         }
12517
12518         sprintf(pos, "%04d ", channel);
12519         pos += 5;
12520
12521         // terence 20140120: fix for some chipsets only return 2.4GHz channel (4330b2/43341b0/4339a0)
12522         ret = wldev_ioctl(dev, WLC_GET_BAND, &band_cur, sizeof(band_cur), false);
12523         band = band_cur==WLC_BAND_2G ? band_cur : WLC_BAND_5G;
12524         ret = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), true);
12525         if (ret < 0)
12526                 WL_ERR(("WLC_SET_BAND error %d\n", ret));
12527
12528         /* Best channel selection in 5GHz band. */
12529         ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
12530         if (ret < 0) {
12531                 WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret));
12532                 goto done;
12533         }
12534
12535         ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
12536                 &channel);
12537         if (ret < 0) {
12538                 WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret));
12539                 goto done;
12540         }
12541
12542         if (CHANNEL_IS_5G(channel)) {
12543                 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
12544         } else {
12545                 WL_ERR(("invalid 5GHz channel, channel = %d\n", channel));
12546                 channel = 0;
12547         }
12548
12549         ret = wldev_ioctl(dev, WLC_SET_BAND, &band_cur, sizeof(band_cur), true);
12550         if (ret < 0)
12551                 WL_ERR(("WLC_SET_BAND error %d\n", ret));
12552
12553         sprintf(pos, "%04d ", channel);
12554         pos += 5;
12555
12556         /* Set overall best channel same as 5GHz best channel. */
12557         sprintf(pos, "%04d ", channel);
12558         pos += 5;
12559
12560 done:
12561         if (NULL != buf) {
12562                 kfree(buf);
12563         }
12564
12565         /* Restore FW and driver back to normal state. */
12566         ret = wl_cfg80211_restore_auto_channel_scan_state(ndev);
12567         if (ret < 0) {
12568                 WL_ERR(("can't restore auto channel scan state, error = %d\n", ret));
12569         }
12570
12571         printf("%s: channel %s\n", __FUNCTION__, cmd);
12572
12573         return (pos - cmd);
12574 }
12575 #endif /* WL_SUPPORT_AUTO_CHANNEL */
12576
12577 static const struct rfkill_ops wl_rfkill_ops = {
12578         .set_block = wl_rfkill_set
12579 };
12580
12581 static int wl_rfkill_set(void *data, bool blocked)
12582 {
12583         struct wl_priv *wl = (struct wl_priv *)data;
12584
12585         WL_DBG(("Enter \n"));
12586         WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked"));
12587
12588         if (!wl)
12589                 return -EINVAL;
12590
12591         wl->rf_blocked = blocked;
12592
12593         return 0;
12594 }
12595
12596 static int wl_setup_rfkill(struct wl_priv *wl, bool setup)
12597 {
12598         s32 err = 0;
12599
12600         WL_DBG(("Enter \n"));
12601         if (!wl)
12602                 return -EINVAL;
12603         if (setup) {
12604                 wl->rfkill = rfkill_alloc("brcmfmac-wifi",
12605                         wl_cfg80211_get_parent_dev(),
12606                         RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)wl);
12607
12608                 if (!wl->rfkill) {
12609                         err = -ENOMEM;
12610                         goto err_out;
12611                 }
12612
12613                 err = rfkill_register(wl->rfkill);
12614
12615                 if (err)
12616                         rfkill_destroy(wl->rfkill);
12617         } else {
12618                 if (!wl->rfkill) {
12619                         err = -ENOMEM;
12620                         goto err_out;
12621                 }
12622
12623                 rfkill_unregister(wl->rfkill);
12624                 rfkill_destroy(wl->rfkill);
12625         }
12626
12627 err_out:
12628         return err;
12629 }
12630
12631 #ifdef DEBUGFS_CFG80211
12632 /**
12633 * Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level
12634 * to turn on SCAN and DBG log.
12635 * To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level
12636 * To see current setting of debug level,
12637 * cat /sys/kernel/debug/dhd/debug_level
12638 */
12639 static ssize_t
12640 wl_debuglevel_write(struct file *file, const char __user *userbuf,
12641         size_t count, loff_t *ppos)
12642 {
12643         char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)], sublog[S_SUBLOGLEVEL];
12644         char *params, *token, *colon;
12645         uint i, tokens, log_on = 0;
12646         memset(tbuf, 0, sizeof(tbuf));
12647         memset(sublog, 0, sizeof(sublog));
12648         if (copy_from_user(&tbuf, userbuf, min_t(size_t, sizeof(tbuf), count)))
12649                 return -EFAULT;
12650
12651         params = &tbuf[0];
12652         colon = strchr(params, '\n');
12653         if (colon != NULL)
12654                 *colon = '\0';
12655         while ((token = strsep(&params, " ")) != NULL) {
12656                 memset(sublog, 0, sizeof(sublog));
12657                 if (token == NULL || !*token)
12658                         break;
12659                 if (*token == '\0')
12660                         continue;
12661                 colon = strchr(token, ':');
12662                 if (colon != NULL) {
12663                         *colon = ' ';
12664                 }
12665                 tokens = sscanf(token, "%s %u", sublog, &log_on);
12666                 if (colon != NULL)
12667                         *colon = ':';
12668
12669                 if (tokens == 2) {
12670                                 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
12671                                         if (!strncmp(sublog, sublogname_map[i].sublogname,
12672                                                 strlen(sublogname_map[i].sublogname))) {
12673                                                 if (log_on)
12674                                                         wl_dbg_level |=
12675                                                         (sublogname_map[i].log_level);
12676                                                 else
12677                                                         wl_dbg_level &=
12678                                                         ~(sublogname_map[i].log_level);
12679                                         }
12680                                 }
12681                 } else
12682                         WL_ERR(("%s: can't parse '%s' as a "
12683                                "SUBMODULE:LEVEL (%d tokens)\n",
12684                                tbuf, token, tokens));
12685
12686
12687         }
12688         return count;
12689 }
12690
12691 static ssize_t
12692 wl_debuglevel_read(struct file *file, char __user *user_buf,
12693         size_t count, loff_t *ppos)
12694 {
12695         char *param;
12696         char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)];
12697         uint i;
12698         memset(tbuf, 0, sizeof(tbuf));
12699         param = &tbuf[0];
12700         for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
12701                 param += snprintf(param, sizeof(tbuf) - 1, "%s:%d ",
12702                         sublogname_map[i].sublogname,
12703                         (wl_dbg_level & sublogname_map[i].log_level) ? 1 : 0);
12704         }
12705         *param = '\n';
12706         return simple_read_from_buffer(user_buf, count, ppos, tbuf, strlen(&tbuf[0]));
12707
12708 }
12709 static const struct file_operations fops_debuglevel = {
12710         .open = NULL,
12711         .write = wl_debuglevel_write,
12712         .read = wl_debuglevel_read,
12713         .owner = THIS_MODULE,
12714         .llseek = NULL,
12715 };
12716
12717 static s32 wl_setup_debugfs(struct wl_priv *wl)
12718 {
12719         s32 err = 0;
12720         struct dentry *_dentry;
12721         if (!wl)
12722                 return -EINVAL;
12723         wl->debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
12724         if (!wl->debugfs || IS_ERR(wl->debugfs)) {
12725                 if (wl->debugfs == ERR_PTR(-ENODEV))
12726                         WL_ERR(("Debugfs is not enabled on this kernel\n"));
12727                 else
12728                         WL_ERR(("Can not create debugfs directory\n"));
12729                 wl->debugfs = NULL;
12730                 goto exit;
12731
12732         }
12733         _dentry = debugfs_create_file("debug_level", S_IRUSR | S_IWUSR,
12734                 wl->debugfs, wl, &fops_debuglevel);
12735         if (!_dentry || IS_ERR(_dentry)) {
12736                 WL_ERR(("failed to create debug_level debug file\n"));
12737                 wl_free_debugfs(wl);
12738         }
12739 exit:
12740         return err;
12741 }
12742 static s32 wl_free_debugfs(struct wl_priv *wl)
12743 {
12744         if (!wl)
12745                 return -EINVAL;
12746         if (wl->debugfs)
12747                 debugfs_remove_recursive(wl->debugfs);
12748         wl->debugfs = NULL;
12749         return 0;
12750 }
12751 #endif /* DEBUGFS_CFG80211 */
12752
12753 struct device *wl_cfg80211_get_parent_dev(void)
12754 {
12755         return cfg80211_parent_dev;
12756 }
12757
12758 void wl_cfg80211_set_parent_dev(void *dev)
12759 {
12760         cfg80211_parent_dev = dev;
12761 }
12762
12763 static void wl_cfg80211_clear_parent_dev(void)
12764 {
12765         cfg80211_parent_dev = NULL;
12766 }
12767
12768 void get_primary_mac(struct wl_priv *wl, struct ether_addr *mac)
12769 {
12770         wldev_iovar_getbuf_bsscfg(wl_to_prmry_ndev(wl), "cur_etheraddr", NULL,
12771                 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, 0, &wl->ioctl_buf_sync);
12772         memcpy(mac->octet, wl->ioctl_buf, ETHER_ADDR_LEN);
12773 }
12774 static bool check_dev_role_integrity(struct wl_priv *wl, u32 dev_role)
12775 {
12776         dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
12777         if (((dev_role == NL80211_IFTYPE_AP) &&
12778                 !(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) ||
12779                 ((dev_role == NL80211_IFTYPE_P2P_GO) &&
12780                 !(dhd->op_mode & DHD_FLAG_P2P_GO_MODE)))
12781         {
12782                 WL_ERR(("device role select failed\n"));
12783                 return false;
12784         }
12785         return true;
12786 }
12787
12788 int wl_cfg80211_do_driver_init(struct net_device *net)
12789 {
12790         struct wl_priv *wl = *(struct wl_priv **)netdev_priv(net);
12791
12792         if (!wl || !wl->wdev)
12793                 return -EINVAL;
12794
12795         if (dhd_do_driver_init(wl->wdev->netdev) < 0)
12796                 return -1;
12797
12798         return 0;
12799 }
12800
12801 void wl_cfg80211_enable_trace(u32 level)
12802 {
12803         wl_dbg_level = level;
12804         printk("%s: wl_dbg_level = 0x%x\n", __FUNCTION__, wl_dbg_level);
12805 }
12806
12807 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
12808         2, 0))
12809 static s32
12810 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
12811         bcm_struct_cfgdev *cfgdev, u64 cookie)
12812 {
12813         /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION
12814          * is passed with CMD_FRAME. This callback is supposed to cancel
12815          * the OFFCHANNEL Wait. Since we are already taking care of that
12816          *  with the tx_mgmt logic, do nothing here.
12817          */
12818
12819         return 0;
12820 }
12821 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL >= 3.2.0 */
12822
12823 #ifdef WL11U
12824 bcm_tlv_t *
12825 wl_cfg80211_find_interworking_ie(u8 *parse, u32 len)
12826 {
12827         bcm_tlv_t *ie;
12828
12829         while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_INTERWORKING_ID))) {
12830                         return (bcm_tlv_t *)ie;
12831         }
12832         return NULL;
12833 }
12834
12835 static s32
12836 wl_cfg80211_add_iw_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag,
12837             uint8 ie_id, uint8 *data, uint8 data_len)
12838 {
12839         s32 err = BCME_OK;
12840         s32 buf_len;
12841         s32 iecount;
12842         ie_setbuf_t *ie_setbuf;
12843
12844         if (ie_id != DOT11_MNG_INTERWORKING_ID)
12845                 return BCME_UNSUPPORTED;
12846
12847         /* Validate the pktflag parameter */
12848         if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
12849                     VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
12850                     VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG|
12851                     VNDR_IE_CUSTOM_FLAG))) {
12852                 WL_ERR(("cfg80211 Add IE: Invalid packet flag 0x%x\n", pktflag));
12853                 return -1;
12854         }
12855
12856         /* use VNDR_IE_CUSTOM_FLAG flags for none vendor IE . currently fixed value */
12857         pktflag = htod32(pktflag);
12858
12859         buf_len = sizeof(ie_setbuf_t) + data_len - 1;
12860         ie_setbuf = (ie_setbuf_t *) kzalloc(buf_len, GFP_KERNEL);
12861
12862         if (!ie_setbuf) {
12863                 WL_ERR(("Error allocating buffer for IE\n"));
12864                 return -ENOMEM;
12865         }
12866
12867         if (wl->iw_ie_len == data_len && !memcmp(wl->iw_ie, data, data_len)) {
12868                 WL_ERR(("Previous IW IE is equals to current IE\n"));
12869                 err = BCME_OK;
12870                 goto exit;
12871         }
12872
12873         strncpy(ie_setbuf->cmd, "add", VNDR_IE_CMD_LEN - 1);
12874         ie_setbuf->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
12875
12876         /* Buffer contains only 1 IE */
12877         iecount = htod32(1);
12878         memcpy((void *)&ie_setbuf->ie_buffer.iecount, &iecount, sizeof(int));
12879         memcpy((void *)&ie_setbuf->ie_buffer.ie_list[0].pktflag, &pktflag, sizeof(uint32));
12880
12881         /* Now, add the IE to the buffer */
12882         ie_setbuf->ie_buffer.ie_list[0].ie_data.id = ie_id;
12883
12884         /* if already set with previous values, delete it first */
12885         if (wl->iw_ie_len != 0) {
12886                 WL_DBG(("Different IW_IE was already set. clear first\n"));
12887
12888                 ie_setbuf->ie_buffer.ie_list[0].ie_data.len = 0;
12889
12890                 err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
12891                         wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
12892
12893                 if (err != BCME_OK)
12894                         goto exit;
12895         }
12896
12897         ie_setbuf->ie_buffer.ie_list[0].ie_data.len = data_len;
12898         memcpy((uchar *)&ie_setbuf->ie_buffer.ie_list[0].ie_data.data[0], data, data_len);
12899
12900         err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
12901                 wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
12902
12903         if (err == BCME_OK) {
12904                 memcpy(wl->iw_ie, data, data_len);
12905                 wl->iw_ie_len = data_len;
12906                 wl->wl11u = TRUE;
12907
12908                 err = wldev_iovar_setint_bsscfg(ndev, "grat_arp", 1, bssidx);
12909         }
12910
12911 exit:
12912         if (ie_setbuf)
12913                 kfree(ie_setbuf);
12914         return err;
12915 }
12916 #endif /* WL11U */
12917
12918 #ifdef WL_HOST_BAND_MGMT
12919 s32
12920 wl_cfg80211_set_band(struct net_device *ndev, int band)
12921 {
12922         struct wl_priv *wl = wlcfg_drv_priv;
12923         int ret = 0;
12924         char ioctl_buf[50];
12925
12926         if ((band < WLC_BAND_AUTO) || (band > WLC_BAND_2G)) {
12927                 WL_ERR(("Invalid band\n"));
12928                 return -EINVAL;
12929         }
12930
12931         if ((ret = wldev_iovar_setbuf(ndev, "roam_band", &band,
12932                 sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
12933                 WL_ERR(("seting roam_band failed code=%d\n", ret));
12934                 return ret;
12935         }
12936
12937         WL_DBG(("Setting band to %d\n", band));
12938         wl->curr_band = band;
12939
12940         return 0;
12941 }
12942 #endif /* WL_HOST_BAND_MGMT */
12943
12944 #if defined(DHCP_SCAN_SUPPRESS)
12945 static void wl_cfg80211_scan_supp_timerfunc(ulong data)
12946 {
12947         struct wl_priv *wl = (struct wl_priv *)data;
12948
12949         WL_DBG(("Enter \n"));
12950         schedule_work(&wl->wlan_work);
12951 }
12952
12953 int wl_cfg80211_scan_suppress(struct net_device *dev, int suppress)
12954 {
12955         int ret = 0;
12956         struct wireless_dev *wdev;
12957         struct wl_priv *wl;
12958         if (!dev || ((suppress != 0) && (suppress != 1))) {
12959                 ret = -EINVAL;
12960                 goto exit;
12961         }
12962         wdev = ndev_to_wdev(dev);
12963         if (!wdev) {
12964                 ret = -EINVAL;
12965                 goto exit;
12966         }
12967         wl = (struct wl_priv *)wiphy_priv(wdev->wiphy);
12968         if (!wl) {
12969                 ret = -EINVAL;
12970                 goto exit;
12971         }
12972
12973         if (suppress == wl->scan_suppressed) {
12974                 WL_DBG(("No change in scan_suppress state. Ignoring cmd..\n"));
12975                 return 0;
12976         }
12977
12978         if (timer_pending(&wl->scan_supp_timer))
12979                 del_timer_sync(&wl->scan_supp_timer);
12980
12981         if ((ret = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS,
12982                 &suppress, sizeof(int), true)) < 0) {
12983                 WL_ERR(("Scan suppress setting failed ret:%d \n", ret));
12984         } else {
12985                 WL_DBG(("Scan suppress %s \n", suppress ? "Enabled" : "Disabled"));
12986                 wl->scan_suppressed = suppress;
12987         }
12988
12989         /* If scan_suppress is set, Start a timer to monitor it (just incase) */
12990         if (wl->scan_suppressed) {
12991                 if (ret) {
12992                         WL_ERR(("Retry scan_suppress reset at a later time \n"));
12993                         mod_timer(&wl->scan_supp_timer,
12994                                 jiffies + msecs_to_jiffies(WL_SCAN_SUPPRESS_RETRY));
12995                 } else {
12996                         WL_DBG(("Start wlan_timer to clear of scan_suppress \n"));
12997                         mod_timer(&wl->scan_supp_timer,
12998                                 jiffies + msecs_to_jiffies(WL_SCAN_SUPPRESS_TIMEOUT));
12999                 }
13000         }
13001 exit:
13002         return ret;
13003 }
13004 #endif /* DHCP_SCAN_SUPPRESS */
13005
13006 static void wl_cfg80211_work_handler(struct work_struct * work)
13007 {
13008         struct wl_priv *wl = NULL;
13009         struct net_info *iter, *next;
13010         s32 err = BCME_OK;
13011         s32 pm = PM_FAST;
13012
13013         wl = container_of(work, struct wl_priv, pm_enable_work.work);
13014         WL_DBG(("Enter \n"));
13015         if (wl->pm_enable_work_on) {
13016                 wl->pm_enable_work_on = false;
13017                 for_each_ndev(wl, iter, next) {
13018                         if (!wl_get_drv_status(wl, CONNECTED, iter->ndev) ||
13019                                 (wl_get_mode_by_netdev(wl, iter->ndev) != WL_MODE_BSS))
13020                                 continue;
13021                         if (iter->ndev) {
13022                                 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM,
13023                                         &pm, sizeof(pm), true)) != 0) {
13024                                         if (err == -ENODEV)
13025                                                 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
13026                                         else
13027                                                 WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
13028                                 } else
13029                                         iter->ndev->ieee80211_ptr->ps = true;
13030                         }
13031                 }
13032
13033         }
13034 #if defined(DHCP_SCAN_SUPPRESS)
13035         else if (wl->scan_suppressed) {
13036                 /* There is pending scan_suppress. Clean it */
13037                 WL_ERR(("Clean up from timer after %d msec\n", WL_SCAN_SUPPRESS_TIMEOUT));
13038                 wl_cfg80211_scan_suppress(wl_to_prmry_ndev(wl), 0);
13039         }
13040 #endif /* DHCP_SCAN_SUPPRESS */
13041 }
13042
13043 u8
13044 wl_get_action_category(void *frame, u32 frame_len)
13045 {
13046         u8 category;
13047         u8 *ptr = (u8 *)frame;
13048         if (frame == NULL)
13049                 return DOT11_ACTION_CAT_ERR_MASK;
13050         if (frame_len < DOT11_ACTION_HDR_LEN)
13051                 return DOT11_ACTION_CAT_ERR_MASK;
13052         category = ptr[DOT11_ACTION_CAT_OFF];
13053         WL_INFO(("Action Category: %d\n", category));
13054         return category;
13055 }
13056
13057 int
13058 wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action)
13059 {
13060         u8 *ptr = (u8 *)frame;
13061         if (frame == NULL || ret_action == NULL)
13062                 return BCME_ERROR;
13063         if (frame_len < DOT11_ACTION_HDR_LEN)
13064                 return BCME_ERROR;
13065         if (DOT11_ACTION_CAT_PUBLIC != wl_get_action_category(frame, frame_len))
13066                 return BCME_ERROR;
13067         *ret_action = ptr[DOT11_ACTION_ACT_OFF];
13068         WL_INFO(("Public Action : %d\n", *ret_action));
13069         return BCME_OK;
13070 }
13071
13072 #ifdef POWER_OFF_IN_SUSPEND
13073 static void wl_scan_complete(struct wl_priv *wl)
13074 {
13075         wl_event_msg_t msg;
13076         WL_TRACE(("In\n"));
13077
13078         if (!(wl->scan_request)) {
13079                 WL_ERR(("timer expired but no scan request\n"));
13080                 return;
13081         }
13082         bzero(&msg, sizeof(wl_event_msg_t));
13083         if (wl->escan_on && wl->escan_info.escan_state == WL_ESCAN_STATE_SCANING) {
13084                 msg.event_type = hton32(WLC_E_ESCAN_RESULT);
13085                 msg.status = hton32(WLC_E_STATUS_SUCCESS);
13086                 msg.reason = 0;
13087                 wl_cfg80211_event(wl_to_prmry_ndev(wl), &msg, NULL);
13088         }
13089 }
13090
13091 void wl_cfg80211_stop(void)
13092 {
13093         struct wl_priv *wl;
13094
13095         wl = wlcfg_drv_priv;
13096
13097         WL_TRACE(("In\n"));
13098
13099         wl_scan_complete(wl);
13100
13101         if (wl->btcoex_info && wl->btcoex_info->timer_on) {
13102                 wl->btcoex_info->timer_on = 0;
13103                 del_timer_sync(&wl->btcoex_info->timer);
13104         }
13105
13106         if (wl->p2p_supported) {
13107                 if (timer_pending(&wl->p2p->listen_timer))
13108                         del_timer_sync(&wl->p2p->listen_timer);
13109         }
13110
13111         del_timer_sync(&wl->scan_timeout);
13112
13113 #if defined(RSSIAVG)
13114         wl_free_rssi_cache(&g_rssi_cache_ctrl);
13115         wl_free_rssi_cache(&g_rssi2_cache_ctrl);
13116 #endif
13117 #if defined(BSSCACHE)
13118         wl_free_bss_cache(&g_bss_cache_ctrl);
13119         wl_run_bss_cache_timer(&g_bss_cache_ctrl, 0);
13120 #endif
13121 }
13122
13123 void wl_cfg80211_send_disconnect(void)
13124 {
13125         struct wl_priv *wl;
13126
13127         wl = wlcfg_drv_priv;
13128
13129         WL_TRACE(("In\n"));
13130         cfg80211_disconnected(wl_to_prmry_ndev(wl), 0, NULL, 0, GFP_KERNEL);
13131 }
13132
13133 void wl_cfg80211_user_sync(bool lock)
13134 {
13135         struct wl_priv *wl;
13136
13137         wl = wlcfg_drv_priv;
13138         if (lock)
13139                 mutex_lock(&wl->usr_sync);
13140         else
13141                 mutex_unlock(&wl->usr_sync);
13142 }
13143 #endif