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