OSDN Git Service

net: wireless: bcmdhd: Combined P2P fixes
[android-x86/kernel.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 #include <bcmutils.h>
33 #include <bcmwifi.h>
34 #include <bcmendian.h>
35 #include <proto/ethernet.h>
36 #include <proto/802.11.h>
37 #include <linux/if_arp.h>
38 #include <asm/uaccess.h>
39
40 #include <dngl_stats.h>
41 #include <dhd.h>
42 #include <dhdioctl.h>
43 #include <wlioctl.h>
44 #include <dhd_cfg80211.h>
45
46 #include <proto/ethernet.h>
47 #include <linux/kernel.h>
48 #include <linux/kthread.h>
49 #include <linux/netdevice.h>
50 #include <linux/sched.h>
51 #include <linux/etherdevice.h>
52 #include <linux/wireless.h>
53 #include <linux/ieee80211.h>
54 #include <linux/wait.h>
55 #include <net/cfg80211.h>
56 #include <net/rtnetlink.h>
57
58 #include <wlioctl.h>
59 #include <wldev_common.h>
60 #include <wl_cfg80211.h>
61 #include <wl_cfgp2p.h>
62
63 static struct device *cfg80211_parent_dev = NULL;
64 static int vsdb_supported = 0;
65 struct wl_priv *wlcfg_drv_priv = NULL;
66
67 u32 wl_dbg_level = WL_DBG_ERR;
68
69 #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
70 #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
71 #define MAX_WAIT_TIME 1500
72 #define WL_SCAN_ACTIVE_TIME      40
73 #define WL_SCAN_PASSIVE_TIME    130
74 #define WL_FRAME_LEN                    300
75
76 #define DNGL_FUNC(func, parameters) func parameters;
77 #define COEX_DHCP
78
79
80 /* This is to override regulatory domains defined in cfg80211 module (reg.c)
81  * By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN
82  * and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165).
83  * With respect to these flags, wpa_supplicant doesn't start p2p operations on 5GHz channels.
84  * All the chnages in world regulatory domain are to be done here.
85  */
86 static const struct ieee80211_regdomain brcm_regdom = {
87         .n_reg_rules = 4,
88         .alpha2 =  "99",
89         .reg_rules = {
90                 /* IEEE 802.11b/g, channels 1..11 */
91                 REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
92                 /* IEEE 802.11b/g, channels 12..13. No HT40
93                  * channel fits here.
94                  */
95                 /* If any */
96                 /*
97                  * IEEE 802.11 channel 14 - is for JP only,
98                  * we need cfg80211 to allow it (reg_flags = 0); so that
99                  * hostapd could request auto channel by sending down ch 14
100                  */
101                 REG_RULE(2484-10, 2484+10, 20, 6, 20,
102                 NL80211_RRF_PASSIVE_SCAN |
103                 NL80211_RRF_NO_IBSS |
104                 NL80211_RRF_NO_OFDM),
105                 /* IEEE 802.11a, channel 36..64 */
106                 REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
107                 /* IEEE 802.11a, channel 100..165 */
108                 REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
109 };
110
111
112 /* Data Element Definitions */
113 #define WPS_ID_CONFIG_METHODS     0x1008
114 #define WPS_ID_REQ_TYPE           0x103A
115 #define WPS_ID_DEVICE_NAME        0x1011
116 #define WPS_ID_VERSION            0x104A
117 #define WPS_ID_DEVICE_PWD_ID      0x1012
118 #define WPS_ID_REQ_DEV_TYPE       0x106A
119 #define WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS 0x1053
120 #define WPS_ID_PRIM_DEV_TYPE      0x1054
121
122 /* Device Password ID */
123 #define DEV_PW_DEFAULT 0x0000
124 #define DEV_PW_USER_SPECIFIED 0x0001,
125 #define DEV_PW_MACHINE_SPECIFIED 0x0002
126 #define DEV_PW_REKEY 0x0003
127 #define DEV_PW_PUSHBUTTON 0x0004
128 #define DEV_PW_REGISTRAR_SPECIFIED 0x0005
129
130 /* Config Methods */
131 #define WPS_CONFIG_USBA 0x0001
132 #define WPS_CONFIG_ETHERNET 0x0002
133 #define WPS_CONFIG_LABEL 0x0004
134 #define WPS_CONFIG_DISPLAY 0x0008
135 #define WPS_CONFIG_EXT_NFC_TOKEN 0x0010
136 #define WPS_CONFIG_INT_NFC_TOKEN 0x0020
137 #define WPS_CONFIG_NFC_INTERFACE 0x0040
138 #define WPS_CONFIG_PUSHBUTTON 0x0080
139 #define WPS_CONFIG_KEYPAD 0x0100
140 #define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280
141 #define WPS_CONFIG_PHY_PUSHBUTTON 0x0480
142 #define WPS_CONFIG_VIRT_DISPLAY 0x2008
143 #define WPS_CONFIG_PHY_DISPLAY 0x4008
144
145 /*
146  * cfg80211_ops api/callback list
147  */
148 static s32 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
149         const struct ether_addr *sa, const struct ether_addr *bssid,
150         u8 **pheader, u32 *body_len, u8 *pbody);
151 static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
152         struct cfg80211_scan_request *request,
153         struct cfg80211_ssid *this_ssid);
154 static s32 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
155         struct cfg80211_scan_request *request);
156 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
157 static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
158         struct cfg80211_ibss_params *params);
159 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy,
160         struct net_device *dev);
161 static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
162         struct net_device *dev, u8 *mac,
163         struct station_info *sinfo);
164 static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
165         struct net_device *dev, bool enabled,
166         s32 timeout);
167 static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
168         struct cfg80211_connect_params *sme);
169 static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
170         u16 reason_code);
171 static s32 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
172         enum nl80211_tx_power_setting type,
173         s32 dbm);
174 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
175 static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
176         struct net_device *dev,
177         u8 key_idx, bool unicast, bool multicast);
178 static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
179         u8 key_idx, bool pairwise, const u8 *mac_addr,
180         struct key_params *params);
181 static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
182         u8 key_idx, bool pairwise, const u8 *mac_addr);
183 static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
184         u8 key_idx, bool pairwise, const u8 *mac_addr,
185         void *cookie, void (*callback) (void *cookie,
186         struct key_params *params));
187 static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
188         struct net_device *dev, u8 key_idx);
189 static s32 wl_cfg80211_resume(struct wiphy *wiphy);
190 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)
191 static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
192 #else
193 static s32 wl_cfg80211_suspend(struct wiphy *wiphy);
194 #endif
195 static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
196         struct cfg80211_pmksa *pmksa);
197 static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
198         struct cfg80211_pmksa *pmksa);
199 static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
200         struct net_device *dev);
201 static s32 wl_notify_escan_complete(struct wl_priv *wl,
202         struct net_device *ndev, bool aborted, bool fw_abort);
203 /*
204  * event & event Q handlers for cfg80211 interfaces
205  */
206 static s32 wl_create_event_handler(struct wl_priv *wl);
207 static void wl_destroy_event_handler(struct wl_priv *wl);
208 static s32 wl_event_handler(void *data);
209 static void wl_init_eq(struct wl_priv *wl);
210 static void wl_flush_eq(struct wl_priv *wl);
211 static unsigned long wl_lock_eq(struct wl_priv *wl);
212 static void wl_unlock_eq(struct wl_priv *wl, unsigned long flags);
213 static void wl_init_eq_lock(struct wl_priv *wl);
214 static void wl_init_event_handler(struct wl_priv *wl);
215 static struct wl_event_q *wl_deq_event(struct wl_priv *wl);
216 static s32 wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 type,
217         const wl_event_msg_t *msg, void *data);
218 static void wl_put_event(struct wl_event_q *e);
219 static void wl_wakeup_event(struct wl_priv *wl);
220 static s32 wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev,
221         const wl_event_msg_t *e, void *data);
222 static s32 wl_notify_connect_status(struct wl_priv *wl,
223         struct net_device *ndev,
224         const wl_event_msg_t *e, void *data);
225 static s32 wl_notify_roaming_status(struct wl_priv *wl,
226         struct net_device *ndev,
227         const wl_event_msg_t *e, void *data);
228 static s32 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
229         const wl_event_msg_t *e, void *data);
230 static s32 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
231         const wl_event_msg_t *e, void *data, bool completed);
232 static s32 wl_ibss_join_done(struct wl_priv *wl, struct net_device *ndev,
233         const wl_event_msg_t *e, void *data, bool completed);
234 static s32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
235         const wl_event_msg_t *e, void *data);
236 static s32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
237         const wl_event_msg_t *e, void *data);
238 #ifdef WL_SCHED_SCAN
239 static s32
240 wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev,
241         const wl_event_msg_t *e, void *data);
242 #endif /* WL_SCHED_SCAN */
243 #ifdef PNO_SUPPORT
244 static s32 wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev,
245         const wl_event_msg_t *e, void *data);
246 #endif /* PNO_SUPPORT */
247 /*
248  * register/deregister parent device
249  */
250 static void wl_cfg80211_clear_parent_dev(void);
251
252 /*
253  * cfg80211 set_wiphy_params utilities
254  */
255 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold);
256 static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold);
257 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
258
259 /*
260  * wl profile utilities
261  */
262 static s32 wl_update_prof(struct wl_priv *wl, struct net_device *ndev,
263         const wl_event_msg_t *e, void *data, s32 item);
264 static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item);
265 static void wl_init_prof(struct wl_priv *wl, struct net_device *ndev);
266
267 /*
268  * cfg80211 connect utilites
269  */
270 static s32 wl_set_wpa_version(struct net_device *dev,
271         struct cfg80211_connect_params *sme);
272 static s32 wl_set_auth_type(struct net_device *dev,
273         struct cfg80211_connect_params *sme);
274 static s32 wl_set_set_cipher(struct net_device *dev,
275         struct cfg80211_connect_params *sme);
276 static s32 wl_set_key_mgmt(struct net_device *dev,
277         struct cfg80211_connect_params *sme);
278 static s32 wl_set_set_sharedkey(struct net_device *dev,
279         struct cfg80211_connect_params *sme);
280 static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev);
281 static void wl_ch_to_chanspec(int ch,
282         struct wl_join_params *join_params, size_t *join_params_size);
283
284 /*
285  * information element utilities
286  */
287 static void wl_rst_ie(struct wl_priv *wl);
288 static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v);
289 static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size);
290 static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size);
291 static u32 wl_get_ielen(struct wl_priv *wl);
292
293
294 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev);
295 static void wl_free_wdev(struct wl_priv *wl);
296
297 static s32 wl_inform_bss(struct wl_priv *wl);
298 static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi);
299 static s32 wl_inform_ibss(struct wl_priv *wl, const u8 *bssid);
300 static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev);
301 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy);
302
303 static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
304         u8 key_idx, const u8 *mac_addr,
305         struct key_params *params);
306 /*
307  * key indianess swap utilities
308  */
309 static void swap_key_from_BE(struct wl_wsec_key *key);
310 static void swap_key_to_BE(struct wl_wsec_key *key);
311
312 /*
313  * wl_priv memory init/deinit utilities
314  */
315 static s32 wl_init_priv_mem(struct wl_priv *wl);
316 static void wl_deinit_priv_mem(struct wl_priv *wl);
317
318 static void wl_delay(u32 ms);
319
320 /*
321  * ibss mode utilities
322  */
323 static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev);
324 static __used bool wl_is_ibssstarter(struct wl_priv *wl);
325
326 /*
327  * link up/down , default configuration utilities
328  */
329 static s32 __wl_cfg80211_up(struct wl_priv *wl);
330 static s32 __wl_cfg80211_down(struct wl_priv *wl);
331 static s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add);
332 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e);
333 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev);
334 static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e);
335 static void wl_link_up(struct wl_priv *wl);
336 static void wl_link_down(struct wl_priv *wl);
337 static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype);
338 static void wl_init_conf(struct wl_conf *conf);
339
340 /*
341  * iscan handler
342  */
343 static void wl_iscan_timer(unsigned long data);
344 static void wl_term_iscan(struct wl_priv *wl);
345 static s32 wl_init_scan(struct wl_priv *wl);
346 static s32 wl_iscan_thread(void *data);
347 static s32 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request,
348         u16 action);
349 static s32 wl_do_iscan(struct wl_priv *wl,  struct cfg80211_scan_request *request);
350 static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan);
351 static s32 wl_invoke_iscan(struct wl_priv *wl);
352 static s32 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
353         struct wl_scan_results **bss_list);
354 static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted);
355 static void wl_init_iscan_handler(struct wl_iscan_ctrl *iscan);
356 static s32 wl_iscan_done(struct wl_priv *wl);
357 static s32 wl_iscan_pending(struct wl_priv *wl);
358 static s32 wl_iscan_inprogress(struct wl_priv *wl);
359 static s32 wl_iscan_aborted(struct wl_priv *wl);
360
361 /*
362  * find most significant bit set
363  */
364 static __used u32 wl_find_msb(u16 bit16);
365
366 /*
367  * rfkill support
368  */
369 static int wl_setup_rfkill(struct wl_priv *wl, bool setup);
370 static int wl_rfkill_set(void *data, bool blocked);
371
372 static wl_scan_params_t *wl_cfg80211_scan_alloc_params(int channel,
373         int nprobes, int *out_params_size);
374 static void get_primary_mac(struct wl_priv *wl, struct ether_addr *mac);
375
376 /*
377  * Some external functions, TODO: move them to dhd_linux.h
378  */
379 int dhd_add_monitor(char *name, struct net_device **new_ndev);
380 int dhd_del_monitor(struct net_device *ndev);
381 int dhd_monitor_init(void *dhd_pub);
382 int dhd_monitor_uninit(void);
383 int dhd_start_xmit(struct sk_buff *skb, struct net_device *net);
384
385 #define CHECK_SYS_UP(wlpriv)                                                    \
386 do {                                                                    \
387         struct net_device *ndev = wl_to_prmry_ndev(wlpriv);       \
388         if (unlikely(!wl_get_drv_status(wlpriv, READY, ndev))) {        \
389                 WL_INFO(("device is not ready\n"));             \
390                         return -EIO;                                    \
391         }                                                               \
392 } while (0)
393
394
395 #define IS_WPA_AKM(akm) ((akm) == RSN_AKM_NONE || \
396                                  (akm) == RSN_AKM_UNSPECIFIED || \
397                                  (akm) == RSN_AKM_PSK)
398
399
400 extern int dhd_wait_pend8021x(struct net_device *dev);
401
402 #if (WL_DBG_LEVEL > 0)
403 #define WL_DBG_ESTR_MAX 50
404 static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = {
405         "SET_SSID", "JOIN", "START", "AUTH", "AUTH_IND",
406         "DEAUTH", "DEAUTH_IND", "ASSOC", "ASSOC_IND", "REASSOC",
407         "REASSOC_IND", "DISASSOC", "DISASSOC_IND", "QUIET_START", "QUIET_END",
408         "BEACON_RX", "LINK", "MIC_ERROR", "NDIS_LINK", "ROAM",
409         "TXFAIL", "PMKID_CACHE", "RETROGRADE_TSF", "PRUNE", "AUTOAUTH",
410         "EAPOL_MSG", "SCAN_COMPLETE", "ADDTS_IND", "DELTS_IND", "BCNSENT_IND",
411         "BCNRX_MSG", "BCNLOST_MSG", "ROAM_PREP", "PFN_NET_FOUND",
412         "PFN_NET_LOST",
413         "RESET_COMPLETE", "JOIN_START", "ROAM_START", "ASSOC_START",
414         "IBSS_ASSOC",
415         "RADIO", "PSM_WATCHDOG", "WLC_E_CCX_ASSOC_START", "WLC_E_CCX_ASSOC_ABORT",
416         "PROBREQ_MSG",
417         "SCAN_CONFIRM_IND", "PSK_SUP", "COUNTRY_CODE_CHANGED",
418         "EXCEEDED_MEDIUM_TIME", "ICV_ERROR",
419         "UNICAST_DECODE_ERROR", "MULTICAST_DECODE_ERROR", "TRACE",
420         "WLC_E_BTA_HCI_EVENT", "IF", "WLC_E_P2P_DISC_LISTEN_COMPLETE",
421         "RSSI", "PFN_SCAN_COMPLETE", "WLC_E_EXTLOG_MSG",
422         "ACTION_FRAME", "ACTION_FRAME_COMPLETE", "WLC_E_PRE_ASSOC_IND",
423         "WLC_E_PRE_REASSOC_IND", "WLC_E_CHANNEL_ADOPTED", "WLC_E_AP_STARTED",
424         "WLC_E_DFS_AP_STOP", "WLC_E_DFS_AP_RESUME", "WLC_E_WAI_STA_EVENT",
425         "WLC_E_WAI_MSG", "WLC_E_ESCAN_RESULT", "WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE",
426         "WLC_E_PROBRESP_MSG", "WLC_E_P2P_PROBREQ_MSG", "WLC_E_DCS_REQUEST", "WLC_E_FIFO_CREDIT_MAP",
427         "WLC_E_ACTION_FRAME_RX", "WLC_E_WAKE_EVENT", "WLC_E_RM_COMPLETE"
428 };
429 #endif                          /* WL_DBG_LEVEL */
430
431 #define CHAN2G(_channel, _freq, _flags) {                       \
432         .band                   = IEEE80211_BAND_2GHZ,          \
433         .center_freq            = (_freq),                      \
434         .hw_value               = (_channel),                   \
435         .flags                  = (_flags),                     \
436         .max_antenna_gain       = 0,                            \
437         .max_power              = 30,                           \
438 }
439
440 #define CHAN5G(_channel, _flags) {                              \
441         .band                   = IEEE80211_BAND_5GHZ,          \
442         .center_freq            = 5000 + (5 * (_channel)),      \
443         .hw_value               = (_channel),                   \
444         .flags                  = (_flags),                     \
445         .max_antenna_gain       = 0,                            \
446         .max_power              = 30,                           \
447 }
448
449 #define RATE_TO_BASE100KBPS(rate)   (((rate) * 10) / 2)
450 #define RATETAB_ENT(_rateid, _flags) \
451         {                                                               \
452                 .bitrate        = RATE_TO_BASE100KBPS(_rateid),     \
453                 .hw_value       = (_rateid),                        \
454                 .flags    = (_flags),                        \
455         }
456
457 static struct ieee80211_rate __wl_rates[] = {
458         RATETAB_ENT(WLC_RATE_1M, 0),
459         RATETAB_ENT(WLC_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
460         RATETAB_ENT(WLC_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
461         RATETAB_ENT(WLC_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
462         RATETAB_ENT(WLC_RATE_6M, 0),
463         RATETAB_ENT(WLC_RATE_9M, 0),
464         RATETAB_ENT(WLC_RATE_12M, 0),
465         RATETAB_ENT(WLC_RATE_18M, 0),
466         RATETAB_ENT(WLC_RATE_24M, 0),
467         RATETAB_ENT(WLC_RATE_36M, 0),
468         RATETAB_ENT(WLC_RATE_48M, 0),
469         RATETAB_ENT(WLC_RATE_54M, 0)
470 };
471
472 #define wl_a_rates              (__wl_rates + 4)
473 #define wl_a_rates_size 8
474 #define wl_g_rates              (__wl_rates + 0)
475 #define wl_g_rates_size 12
476
477 static struct ieee80211_channel __wl_2ghz_channels[] = {
478         CHAN2G(1, 2412, 0),
479         CHAN2G(2, 2417, 0),
480         CHAN2G(3, 2422, 0),
481         CHAN2G(4, 2427, 0),
482         CHAN2G(5, 2432, 0),
483         CHAN2G(6, 2437, 0),
484         CHAN2G(7, 2442, 0),
485         CHAN2G(8, 2447, 0),
486         CHAN2G(9, 2452, 0),
487         CHAN2G(10, 2457, 0),
488         CHAN2G(11, 2462, 0),
489         CHAN2G(12, 2467, 0),
490         CHAN2G(13, 2472, 0),
491         CHAN2G(14, 2484, 0)
492 };
493
494 static struct ieee80211_channel __wl_5ghz_a_channels[] = {
495         CHAN5G(34, 0), CHAN5G(36, 0),
496         CHAN5G(38, 0), CHAN5G(40, 0),
497         CHAN5G(42, 0), CHAN5G(44, 0),
498         CHAN5G(46, 0), CHAN5G(48, 0),
499         CHAN5G(52, 0), CHAN5G(56, 0),
500         CHAN5G(60, 0), CHAN5G(64, 0),
501         CHAN5G(100, 0), CHAN5G(104, 0),
502         CHAN5G(108, 0), CHAN5G(112, 0),
503         CHAN5G(116, 0), CHAN5G(120, 0),
504         CHAN5G(124, 0), CHAN5G(128, 0),
505         CHAN5G(132, 0), CHAN5G(136, 0),
506         CHAN5G(140, 0), CHAN5G(149, 0),
507         CHAN5G(153, 0), CHAN5G(157, 0),
508         CHAN5G(161, 0), CHAN5G(165, 0)
509 };
510
511 static struct ieee80211_supported_band __wl_band_2ghz = {
512         .band = IEEE80211_BAND_2GHZ,
513         .channels = __wl_2ghz_channels,
514         .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
515         .bitrates = wl_g_rates,
516         .n_bitrates = wl_g_rates_size
517 };
518
519 static struct ieee80211_supported_band __wl_band_5ghz_a = {
520         .band = IEEE80211_BAND_5GHZ,
521         .channels = __wl_5ghz_a_channels,
522         .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
523         .bitrates = wl_a_rates,
524         .n_bitrates = wl_a_rates_size
525 };
526
527 static const u32 __wl_cipher_suites[] = {
528         WLAN_CIPHER_SUITE_WEP40,
529         WLAN_CIPHER_SUITE_WEP104,
530         WLAN_CIPHER_SUITE_TKIP,
531         WLAN_CIPHER_SUITE_CCMP,
532         WLAN_CIPHER_SUITE_AES_CMAC,
533 };
534
535 /* There isn't a lot of sense in it, but you can transmit anything you like */
536 static const struct ieee80211_txrx_stypes
537 wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
538         [NL80211_IFTYPE_ADHOC] = {
539                 .tx = 0xffff,
540                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
541         },
542         [NL80211_IFTYPE_STATION] = {
543                 .tx = 0xffff,
544                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
545                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
546         },
547         [NL80211_IFTYPE_AP] = {
548                 .tx = 0xffff,
549                 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
550                 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
551                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
552                 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
553                 BIT(IEEE80211_STYPE_AUTH >> 4) |
554                 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
555                 BIT(IEEE80211_STYPE_ACTION >> 4)
556         },
557         [NL80211_IFTYPE_AP_VLAN] = {
558                 /* copy AP */
559                 .tx = 0xffff,
560                 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
561                 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
562                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
563                 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
564                 BIT(IEEE80211_STYPE_AUTH >> 4) |
565                 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
566                 BIT(IEEE80211_STYPE_ACTION >> 4)
567         },
568         [NL80211_IFTYPE_P2P_CLIENT] = {
569                 .tx = 0xffff,
570                 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
571                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
572         },
573         [NL80211_IFTYPE_P2P_GO] = {
574                 .tx = 0xffff,
575                 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
576                 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
577                 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
578                 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
579                 BIT(IEEE80211_STYPE_AUTH >> 4) |
580                 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
581                 BIT(IEEE80211_STYPE_ACTION >> 4)
582         }
583 };
584
585 static void swap_key_from_BE(struct wl_wsec_key *key)
586 {
587         key->index = htod32(key->index);
588         key->len = htod32(key->len);
589         key->algo = htod32(key->algo);
590         key->flags = htod32(key->flags);
591         key->rxiv.hi = htod32(key->rxiv.hi);
592         key->rxiv.lo = htod16(key->rxiv.lo);
593         key->iv_initialized = htod32(key->iv_initialized);
594 }
595
596 static void swap_key_to_BE(struct wl_wsec_key *key)
597 {
598         key->index = dtoh32(key->index);
599         key->len = dtoh32(key->len);
600         key->algo = dtoh32(key->algo);
601         key->flags = dtoh32(key->flags);
602         key->rxiv.hi = dtoh32(key->rxiv.hi);
603         key->rxiv.lo = dtoh16(key->rxiv.lo);
604         key->iv_initialized = dtoh32(key->iv_initialized);
605 }
606
607 /* For debug: Dump the contents of the encoded wps ie buffe */
608 static void
609 wl_validate_wps_ie(char *wps_ie, bool *pbc)
610 {
611         #define WPS_IE_FIXED_LEN 6
612         u16 len = (u16) wps_ie[TLV_LEN_OFF];
613         u8 *subel = wps_ie+  WPS_IE_FIXED_LEN;
614         u16 subelt_id;
615         u16 subelt_len;
616         u16 val;
617         u8 *valptr = (uint8*) &val;
618
619         WL_DBG(("wps_ie len=%d\n", len));
620
621         len -= 4;       /* for the WPS IE's OUI, oui_type fields */
622
623         while (len >= 4) {              /* must have attr id, attr len fields */
624                 valptr[0] = *subel++;
625                 valptr[1] = *subel++;
626                 subelt_id = HTON16(val);
627
628                 valptr[0] = *subel++;
629                 valptr[1] = *subel++;
630                 subelt_len = HTON16(val);
631
632                 len -= 4;                       /* for the attr id, attr len fields */
633                 len -= subelt_len;      /* for the remaining fields in this attribute */
634                 WL_DBG((" subel=%p, subelt_id=0x%x subelt_len=%u\n",
635                         subel, subelt_id, subelt_len));
636
637                 if (subelt_id == WPS_ID_VERSION) {
638                         WL_DBG(("  attr WPS_ID_VERSION: %u\n", *subel));
639                 } else if (subelt_id == WPS_ID_REQ_TYPE) {
640                         WL_DBG(("  attr WPS_ID_REQ_TYPE: %u\n", *subel));
641                 } else if (subelt_id == WPS_ID_CONFIG_METHODS) {
642                         valptr[0] = *subel;
643                         valptr[1] = *(subel + 1);
644                         WL_DBG(("  attr WPS_ID_CONFIG_METHODS: %x\n", HTON16(val)));
645                 } else if (subelt_id == WPS_ID_DEVICE_NAME) {
646                         char devname[100];
647                         memcpy(devname, subel, subelt_len);
648                         devname[subelt_len] = '\0';
649                         WL_DBG(("  attr WPS_ID_DEVICE_NAME: %s (len %u)\n",
650                                 devname, subelt_len));
651                 } else if (subelt_id == WPS_ID_DEVICE_PWD_ID) {
652                         valptr[0] = *subel;
653                         valptr[1] = *(subel + 1);
654                         WL_DBG(("  attr WPS_ID_DEVICE_PWD_ID: %u\n", HTON16(val)));
655                         *pbc = (HTON16(val) == DEV_PW_PUSHBUTTON) ? true : false;
656                 } else if (subelt_id == WPS_ID_PRIM_DEV_TYPE) {
657                         valptr[0] = *subel;
658                         valptr[1] = *(subel + 1);
659                         WL_DBG(("  attr WPS_ID_PRIM_DEV_TYPE: cat=%u \n", HTON16(val)));
660                         valptr[0] = *(subel + 6);
661                         valptr[1] = *(subel + 7);
662                         WL_DBG(("  attr WPS_ID_PRIM_DEV_TYPE: subcat=%u\n", HTON16(val)));
663                 } else if (subelt_id == WPS_ID_REQ_DEV_TYPE) {
664                         valptr[0] = *subel;
665                         valptr[1] = *(subel + 1);
666                         WL_DBG(("  attr WPS_ID_REQ_DEV_TYPE: cat=%u\n", HTON16(val)));
667                         valptr[0] = *(subel + 6);
668                         valptr[1] = *(subel + 7);
669                         WL_DBG(("  attr WPS_ID_REQ_DEV_TYPE: subcat=%u\n", HTON16(val)));
670                 } else if (subelt_id == WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS) {
671                         valptr[0] = *subel;
672                         valptr[1] = *(subel + 1);
673                         WL_DBG(("  attr WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS"
674                                 ": cat=%u\n", HTON16(val)));
675                 } else {
676                         WL_DBG(("  unknown attr 0x%x\n", subelt_id));
677                 }
678
679                 subel += subelt_len;
680         }
681 }
682
683 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
684 {
685         if (vsdb_supported) {
686                 return wf_chspec_aton(WL_P2P_TEMP_CHAN);
687         }
688         else {
689                 chanspec_t chspec;
690                 int err = 0;
691                 struct wl_priv *wl = wiphy_priv(wiphy);
692                 struct net_device *dev = wl_to_prmry_ndev(wl);
693                 struct ether_addr bssid;
694                 struct wl_bss_info *bss = NULL;
695                 if ((err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), false))) {
696                         /* STA interface is not associated. So start the new interface on a temp
697                          * channel . Later proper channel will be applied by the above framework
698                          * via set_channel (cfg80211 API).
699                          */
700                         WL_DBG(("Not associated. Return a temp channel. \n"));
701                         return wf_chspec_aton(WL_P2P_TEMP_CHAN);
702                 }
703
704
705                 *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
706                 if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, wl->extra_buf,
707                         WL_EXTRA_BUF_MAX, false))) {
708                                 WL_ERR(("Failed to get associated bss info, use temp channel \n"));
709                                 chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN);
710                 }
711                 else {
712                                 bss = (struct wl_bss_info *) (wl->extra_buf + 4);
713                                 chspec =  bss->chanspec;
714                                 WL_DBG(("Valid BSS Found. chanspec:%d \n", bss->chanspec));
715                 }
716                 return chspec;
717         }
718 }
719
720 static struct net_device* wl_cfg80211_add_monitor_if(char *name)
721 {
722         int ret = 0;
723         struct net_device* ndev = NULL;
724
725         ret = dhd_add_monitor(name, &ndev);
726         WL_INFO(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev));
727         return ndev;
728 }
729
730 static struct net_device *
731 wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
732         enum nl80211_iftype type, u32 *flags,
733         struct vif_params *params)
734 {
735         s32 err;
736         s32 timeout = -1;
737         s32 wlif_type = -1;
738         s32 mode = 0;
739 #if defined(WL_ENABLE_P2P_IF)
740         s32 dhd_mode = 0;
741 #endif /* (WL_ENABLE_P2P_IF) */
742         chanspec_t chspec;
743         struct wl_priv *wl = wiphy_priv(wiphy);
744         struct net_device *_ndev;
745         struct ether_addr primary_mac;
746         int (*net_attach)(void *dhdp, int ifidx);
747         bool rollback_lock = false;
748
749         /* Use primary I/F for sending cmds down to firmware */
750         _ndev = wl_to_prmry_ndev(wl);
751
752         WL_DBG(("if name: %s, type: %d\n", name, type));
753         switch (type) {
754         case NL80211_IFTYPE_ADHOC:
755         case NL80211_IFTYPE_AP_VLAN:
756         case NL80211_IFTYPE_WDS:
757         case NL80211_IFTYPE_MESH_POINT:
758                 WL_ERR(("Unsupported interface type\n"));
759                 mode = WL_MODE_IBSS;
760                 return NULL;
761         case NL80211_IFTYPE_MONITOR:
762                 return wl_cfg80211_add_monitor_if(name);
763         case NL80211_IFTYPE_P2P_CLIENT:
764         case NL80211_IFTYPE_STATION:
765                 wlif_type = WL_P2P_IF_CLIENT;
766                 mode = WL_MODE_BSS;
767                 break;
768         case NL80211_IFTYPE_P2P_GO:
769         case NL80211_IFTYPE_AP:
770                 wlif_type = WL_P2P_IF_GO;
771                 mode = WL_MODE_AP;
772                 break;
773         default:
774                 WL_ERR(("Unsupported interface type\n"));
775                 return NULL;
776                 break;
777         }
778
779         if (!name) {
780                 WL_ERR(("name is NULL\n"));
781                 return NULL;
782         }
783         if (wl->iface_cnt == IFACE_MAX_CNT)
784                 return ERR_PTR(-ENOMEM);
785         if (wl->p2p_supported && (wlif_type != -1)) {
786                 if (wl_get_p2p_status(wl, IF_DELETING)) {
787                         /* wait till IF_DEL is complete
788                          * release the lock for the unregister to proceed
789                          */
790                         if (rtnl_is_locked()) {
791                                 rtnl_unlock();
792                                 rollback_lock = true;
793                         }
794                         WL_INFO(("%s: Released the lock and wait till IF_DEL is complete\n",
795                                 __func__));
796                         timeout = wait_event_interruptible_timeout(wl->netif_change_event,
797                                 (wl_get_p2p_status(wl, IF_DELETING) == false),
798                                 msecs_to_jiffies(MAX_WAIT_TIME));
799
800                         /* put back the rtnl_lock again */
801                         if (rollback_lock) {
802                                 rtnl_lock();
803                                 rollback_lock = false;
804                         }
805                         if (timeout > 0) {
806                                 WL_ERR(("IF DEL is Success\n"));
807
808                         } else {
809                                 WL_ERR(("timeount < 0, return -EAGAIN\n"));
810                                 return ERR_PTR(-EAGAIN);
811                         }
812                 }
813                 if (wl->p2p && !wl->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
814                         p2p_on(wl) = true;
815                         wl_cfgp2p_set_firm_p2p(wl);
816                         wl_cfgp2p_init_discovery(wl);
817                         get_primary_mac(wl, &primary_mac);
818                         wl_cfgp2p_generate_bss_mac(&primary_mac,
819                                 &wl->p2p->dev_addr, &wl->p2p->int_addr);
820                 }
821
822                 memset(wl->p2p->vir_ifname, 0, IFNAMSIZ);
823                 strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1);
824
825                 wldev_iovar_setint(_ndev, "mpc", 0);
826                 wl_notify_escan_complete(wl, _ndev, true, true);
827                 /* In concurrency case, STA may be already associated in a particular channel.
828                  * so retrieve the current channel of primary interface and then start the virtual
829                  * interface on that.
830                  */
831                  chspec = wl_cfg80211_get_shared_freq(wiphy);
832
833                 /* For P2P mode, use P2P-specific driver features to create the
834                  * bss: "wl p2p_ifadd"
835                  */
836                 wl_set_p2p_status(wl, IF_ADD);
837                 err = wl_cfgp2p_ifadd(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec);
838
839                 if (unlikely(err)) {
840                         WL_ERR((" virtual iface add failed (%d) \n", err));
841                         return ERR_PTR(-ENOMEM);
842                 }
843
844                 timeout = wait_event_interruptible_timeout(wl->netif_change_event,
845                         (wl_get_p2p_status(wl, IF_ADD) == false),
846                         msecs_to_jiffies(MAX_WAIT_TIME));
847                 if (timeout > 0 && (!wl_get_p2p_status(wl, IF_ADD))) {
848
849                         struct wireless_dev *vwdev;
850                         vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL);
851                         if (unlikely(!vwdev)) {
852                                 WL_ERR(("Could not allocate wireless device\n"));
853                                 return ERR_PTR(-ENOMEM);
854                         }
855                         vwdev->wiphy = wl->wdev->wiphy;
856                         WL_INFO((" virtual interface(%s) is created memalloc done \n",
857                                 wl->p2p->vir_ifname));
858                         vwdev->iftype = type;
859                         _ndev =  wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
860                         _ndev->ieee80211_ptr = vwdev;
861                         SET_NETDEV_DEV(_ndev, wiphy_dev(vwdev->wiphy));
862                         vwdev->netdev = _ndev;
863                         wl_set_drv_status(wl, READY, _ndev);
864                         wl->p2p->vif_created = true;
865                         wl_set_mode_by_netdev(wl, _ndev, mode);
866                         net_attach =  wl_to_p2p_bss_private(wl, P2PAPI_BSSCFG_CONNECTION);
867                         if (rtnl_is_locked()) {
868                                 rtnl_unlock();
869                                 rollback_lock = true;
870                         }
871                         if (net_attach && !net_attach(wl->pub, _ndev->ifindex)) {
872                                 wl_alloc_netinfo(wl, _ndev, vwdev, mode);
873                                 WL_ERR((" virtual interface(%s) is "
874                                         "created net attach done\n", wl->p2p->vir_ifname));
875 #if defined(WL_ENABLE_P2P_IF)
876                                 if (type == NL80211_IFTYPE_P2P_CLIENT)
877                                         dhd_mode = P2P_GC_ENABLED;
878                                 else if (type == NL80211_IFTYPE_P2P_GO)
879                                         dhd_mode = P2P_GO_ENABLED;
880                                 DNGL_FUNC(dhd_cfg80211_set_p2p_info, (wl, dhd_mode));
881 #endif /* (WL_ENABLE_P2P_IF) */
882                                 /* Start the P2P I/F with PM disabled. Enable PM from
883                                  * the framework
884                                  */
885                                  if ((type == NL80211_IFTYPE_P2P_CLIENT) || (
886                                          type == NL80211_IFTYPE_P2P_GO))
887                                         vwdev->ps = NL80211_PS_DISABLED;
888                         } else {
889                                 /* put back the rtnl_lock again */
890                                 if (rollback_lock)
891                                         rtnl_lock();
892                                 goto fail;
893                         }
894                         /* put back the rtnl_lock again */
895                         if (rollback_lock)
896                                 rtnl_lock();
897                         return _ndev;
898
899                 } else {
900                         wl_clr_p2p_status(wl, IF_ADD);
901                         WL_ERR((" virtual interface(%s) is not created \n", wl->p2p->vir_ifname));
902                         memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ);
903                         wl->p2p->vif_created = false;
904                 }
905         }
906 fail:
907         return ERR_PTR(-ENODEV);
908 }
909
910 static s32
911 wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
912 {
913         struct ether_addr p2p_mac;
914         struct wl_priv *wl = wiphy_priv(wiphy);
915         s32 timeout = -1;
916         s32 ret = 0;
917         WL_DBG(("Enter\n"));
918
919         if (wl->p2p_net == dev) {
920                 /* Since there is no ifidx corresponding to p2p0, cmds to
921                  * firmware should be routed through primary I/F
922                  */
923                 dev = wl_to_prmry_ndev(wl);
924         }
925
926         if (wl->p2p_supported) {
927                 memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN);
928
929                 /* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases
930                  */
931                 WL_DBG(("P2P: GO_NEG_PHASE status cleared "));
932                 wl_clr_p2p_status(wl, GO_NEG_PHASE);
933                 if (wl->p2p->vif_created) {
934                         if (wl_get_drv_status(wl, SCANNING, dev)) {
935                                 wl_notify_escan_complete(wl, dev, true, true);
936                         }
937                         wldev_iovar_setint(dev, "mpc", 1);
938                         wl_set_p2p_status(wl, IF_DELETING);
939                         ret = wl_cfgp2p_ifdel(wl, &p2p_mac);
940                         /* Firmware could not delete the interface so we will not get WLC_E_IF
941                         * event for cleaning the dhd virtual nw interace
942                         * So lets do it here. Failures from fw will ensure the application to do
943                         * ifconfig <inter> down and up sequnce, which will reload the fw
944                         * however we should cleanup the linux network virtual interfaces
945                         */
946                         /* Request framework to RESET and clean up */
947                         if (ret) {
948                                 struct net_device *ndev = wl_to_prmry_ndev(wl);
949                                 WL_ERR(("Firmware returned an error (%d) from p2p_ifdel"
950                                         "HANG Notification sent to %s\n", ret, ndev->name));
951                                 wl_cfg80211_hang(ndev, WLAN_REASON_UNSPECIFIED);
952                         }
953
954                         /* Wait for any pending scan req to get aborted from the sysioc context */
955                         timeout = wait_event_interruptible_timeout(wl->netif_change_event,
956                                 (wl->p2p->vif_created == false),
957                                 msecs_to_jiffies(MAX_WAIT_TIME));
958                         if (timeout > 0 && (wl->p2p->vif_created == false)) {
959                                 WL_DBG(("IFDEL operation done\n"));
960 #if  defined(WL_ENABLE_P2P_IF)
961                                 DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (wl));
962 #endif /*  (WL_ENABLE_P2P_IF)) */
963                         } else {
964                                 WL_ERR(("IFDEL didn't complete properly\n"));
965                         }
966                         ret = dhd_del_monitor(dev);
967                 }
968         }
969         return ret;
970 }
971
972 static s32
973 wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
974         enum nl80211_iftype type, u32 *flags,
975         struct vif_params *params)
976 {
977         s32 ap = 0;
978         s32 infra = 0;
979         s32 err = BCME_OK;
980         s32 timeout = -1;
981         s32 wlif_type;
982         s32 mode = 0;
983         chanspec_t chspec;
984         struct wl_priv *wl = wiphy_priv(wiphy);
985
986         WL_DBG(("Enter type %d\n", type));
987         switch (type) {
988         case NL80211_IFTYPE_MONITOR:
989         case NL80211_IFTYPE_WDS:
990         case NL80211_IFTYPE_MESH_POINT:
991                 ap = 1;
992                 WL_ERR(("type (%d) : currently we do not support this type\n",
993                         type));
994                 break;
995         case NL80211_IFTYPE_ADHOC:
996                 mode = WL_MODE_IBSS;
997                 break;
998         case NL80211_IFTYPE_STATION:
999         case NL80211_IFTYPE_P2P_CLIENT:
1000                 mode = WL_MODE_BSS;
1001                 infra = 1;
1002                 break;
1003         case NL80211_IFTYPE_AP:
1004         case NL80211_IFTYPE_AP_VLAN:
1005         case NL80211_IFTYPE_P2P_GO:
1006                 mode = WL_MODE_AP;
1007                 ap = 1;
1008                 break;
1009         default:
1010                 return -EINVAL;
1011         }
1012         WL_DBG(("%s : ap (%d), infra (%d), iftype: (%d)\n", ndev->name, ap, infra, type));
1013
1014         if (ap) {
1015                 wl_set_mode_by_netdev(wl, ndev, mode);
1016                 if (wl->p2p_supported && wl->p2p->vif_created) {
1017                         WL_DBG(("p2p_vif_created (%d) p2p_on (%d)\n", wl->p2p->vif_created,
1018                                 p2p_on(wl)));
1019                         wldev_iovar_setint(ndev, "mpc", 0);
1020                         wl_notify_escan_complete(wl, ndev, true, true);
1021
1022                         /* In concurrency case, STA may be already associated in a particular
1023                          * channel. so retrieve the current channel of primary interface and
1024                          * then start the virtual interface on that.
1025                          */
1026                         chspec = wl_cfg80211_get_shared_freq(wiphy);
1027
1028                         wlif_type = WL_P2P_IF_GO;
1029                         WL_ERR(("%s : ap (%d), infra (%d), iftype: (%d)\n",
1030                                 ndev->name, ap, infra, type));
1031                         wl_set_p2p_status(wl, IF_CHANGING);
1032                         wl_clr_p2p_status(wl, IF_CHANGED);
1033                         err = wl_cfgp2p_ifchange(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec);
1034                         timeout = wait_event_interruptible_timeout(wl->netif_change_event,
1035                                 (wl_get_p2p_status(wl, IF_CHANGED) == true),
1036                                 msecs_to_jiffies(MAX_WAIT_TIME));
1037                         wl_set_mode_by_netdev(wl, ndev, mode);
1038                         wl_clr_p2p_status(wl, IF_CHANGING);
1039                         wl_clr_p2p_status(wl, IF_CHANGED);
1040                 } else if (ndev == wl_to_prmry_ndev(wl) &&
1041                         !wl_get_drv_status(wl, AP_CREATED, ndev)) {
1042                         wl_set_drv_status(wl, AP_CREATING, ndev);
1043                         if (!wl->ap_info &&
1044                                 !(wl->ap_info = kzalloc(sizeof(struct ap_info), GFP_KERNEL))) {
1045                                 WL_ERR(("struct ap_saved_ie allocation failed\n"));
1046                                 return -ENOMEM;
1047                         }
1048                 } else {
1049                         WL_ERR(("Cannot change the interface for GO or SOFTAP\n"));
1050                         return -EINVAL;
1051                 }
1052         } else {
1053                 infra = htod32(infra);
1054                 err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(s32), true);
1055                 if (err) {
1056                         WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
1057                         return -EAGAIN;
1058                 }
1059                 wl_set_mode_by_netdev(wl, ndev, mode);
1060         }
1061
1062         ndev->ieee80211_ptr->iftype = type;
1063         return 0;
1064 }
1065
1066 s32
1067 wl_cfg80211_notify_ifadd(struct net_device *ndev, s32 idx, s32 bssidx,
1068         void* _net_attach)
1069 {
1070         struct wl_priv *wl = wlcfg_drv_priv;
1071         s32 ret = BCME_OK;
1072         WL_DBG(("Enter"));
1073         if (!ndev) {
1074                 WL_ERR(("net is NULL\n"));
1075                 return 0;
1076         }
1077         if (wl->p2p_supported && wl_get_p2p_status(wl, IF_ADD)) {
1078                 WL_DBG(("IF_ADD event called from dongle, old interface name: %s,"
1079                         "new name: %s\n", ndev->name, wl->p2p->vir_ifname));
1080                 /* Assign the net device to CONNECT BSSCFG */
1081                 strncpy(ndev->name, wl->p2p->vir_ifname, IFNAMSIZ - 1);
1082                 wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = ndev;
1083                 wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = bssidx;
1084                 wl_to_p2p_bss_private(wl, P2PAPI_BSSCFG_CONNECTION) = _net_attach;
1085                 ndev->ifindex = idx;
1086                 wl_clr_p2p_status(wl, IF_ADD);
1087
1088                 wake_up_interruptible(&wl->netif_change_event);
1089         } else {
1090                 ret = BCME_NOTREADY;
1091         }
1092         return ret;
1093 }
1094
1095 s32
1096 wl_cfg80211_notify_ifdel(void)
1097 {
1098         struct wl_priv *wl = wlcfg_drv_priv;
1099
1100         WL_DBG(("Enter \n"));
1101         wl_clr_p2p_status(wl, IF_DELETING);
1102
1103         return 0;
1104 }
1105
1106 s32
1107 wl_cfg80211_ifdel_ops(struct net_device *ndev)
1108 {
1109         struct wl_priv *wl = wlcfg_drv_priv;
1110         bool rollback_lock = false;
1111         s32 index = 0;
1112
1113         if (!ndev || !ndev->name) {
1114                 WL_ERR(("net is NULL\n"));
1115                 return 0;
1116         }
1117
1118         if (p2p_is_on(wl) && wl->p2p->vif_created &&
1119                 wl_get_p2p_status(wl, IF_DELETING)) {
1120                 if (wl->scan_request &&
1121                         (wl->escan_info.ndev == ndev)) {
1122                         /* Abort any pending scan requests */
1123                         wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
1124                         if (!rtnl_is_locked()) {
1125                                 rtnl_lock();
1126                                 rollback_lock = true;
1127                         }
1128                         WL_DBG(("ESCAN COMPLETED\n"));
1129                         wl_notify_escan_complete(wl, ndev, true, false);
1130                         if (rollback_lock)
1131                                 rtnl_unlock();
1132                 }
1133                 WL_ERR(("IF_DEL event called from dongle, net %x, vif name: %s\n",
1134                         (unsigned int)ndev, wl->p2p->vir_ifname));
1135
1136                 memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ);
1137                 index = wl_cfgp2p_find_idx(wl, ndev);
1138                 wl_to_p2p_bss_ndev(wl, index) = NULL;
1139                 wl_to_p2p_bss_bssidx(wl, index) = 0;
1140                 wl->p2p->vif_created = false;
1141                 wl_cfgp2p_clear_management_ie(wl,
1142                         index);
1143                 WL_DBG(("index : %d\n", index));
1144
1145         }
1146
1147         /* Wake up any waiting thread */
1148         wake_up_interruptible(&wl->netif_change_event);
1149
1150         return 0;
1151 }
1152
1153 s32
1154 wl_cfg80211_is_progress_ifadd(void)
1155 {
1156         s32 is_progress = 0;
1157         struct wl_priv *wl = wlcfg_drv_priv;
1158         if (wl_get_p2p_status(wl, IF_ADD))
1159                 is_progress = 1;
1160         return is_progress;
1161 }
1162
1163 s32
1164 wl_cfg80211_is_progress_ifchange(void)
1165 {
1166         s32 is_progress = 0;
1167         struct wl_priv *wl = wlcfg_drv_priv;
1168         if (wl_get_p2p_status(wl, IF_CHANGING))
1169                 is_progress = 1;
1170         return is_progress;
1171 }
1172
1173
1174 s32
1175 wl_cfg80211_notify_ifchange(void)
1176 {
1177         struct wl_priv *wl = wlcfg_drv_priv;
1178         if (wl_get_p2p_status(wl, IF_CHANGING)) {
1179                 wl_set_p2p_status(wl, IF_CHANGED);
1180                 wake_up_interruptible(&wl->netif_change_event);
1181         }
1182         return 0;
1183 }
1184
1185 static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_request *request)
1186 {
1187         u32 n_ssids;
1188         u32 n_channels;
1189         u16 channel;
1190         chanspec_t chanspec;
1191         s32 i, offset;
1192         char *ptr;
1193         wlc_ssid_t ssid;
1194
1195         memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
1196         params->bss_type = DOT11_BSSTYPE_ANY;
1197         params->scan_type = 0;
1198         params->nprobes = -1;
1199         params->active_time = -1;
1200         params->passive_time = -1;
1201         params->home_time = -1;
1202         params->channel_num = 0;
1203         memset(&params->ssid, 0, sizeof(wlc_ssid_t));
1204
1205         WL_SCAN(("Preparing Scan request\n"));
1206         WL_SCAN(("nprobes=%d\n", params->nprobes));
1207         WL_SCAN(("active_time=%d\n", params->active_time));
1208         WL_SCAN(("passive_time=%d\n", params->passive_time));
1209         WL_SCAN(("home_time=%d\n", params->home_time));
1210         WL_SCAN(("scan_type=%d\n", params->scan_type));
1211
1212         params->nprobes = htod32(params->nprobes);
1213         params->active_time = htod32(params->active_time);
1214         params->passive_time = htod32(params->passive_time);
1215         params->home_time = htod32(params->home_time);
1216
1217         /* if request is null just exit so it will be all channel broadcast scan */
1218         if (!request)
1219                 return;
1220
1221         n_ssids = request->n_ssids;
1222         n_channels = request->n_channels;
1223
1224         /* Copy channel array if applicable */
1225         WL_SCAN(("### List of channelspecs to scan ###\n"));
1226         if (n_channels > 0) {
1227                 for (i = 0; i < n_channels; i++) {
1228                         chanspec = 0;
1229                         channel = ieee80211_frequency_to_channel(request->channels[i]->center_freq);
1230                         if (request->channels[i]->band == IEEE80211_BAND_2GHZ)
1231                                 chanspec |= WL_CHANSPEC_BAND_2G;
1232                         else
1233                                 chanspec |= WL_CHANSPEC_BAND_5G;
1234
1235                         if (request->channels[i]->flags & IEEE80211_CHAN_NO_HT40) {
1236                                 chanspec |= WL_CHANSPEC_BW_20;
1237                                 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
1238                         } else {
1239                                 chanspec |= WL_CHANSPEC_BW_40;
1240                                 if (request->channels[i]->flags & IEEE80211_CHAN_NO_HT40PLUS)
1241                                         chanspec |= WL_CHANSPEC_CTL_SB_LOWER;
1242                                 else
1243                                         chanspec |= WL_CHANSPEC_CTL_SB_UPPER;
1244                         }
1245
1246                         params->channel_list[i] = channel;
1247                         params->channel_list[i] &= WL_CHANSPEC_CHAN_MASK;
1248                         params->channel_list[i] |= chanspec;
1249                         WL_SCAN(("Chan : %d, Channel spec: %x \n",
1250                                 channel, params->channel_list[i]));
1251                         params->channel_list[i] = htod16(params->channel_list[i]);
1252                 }
1253         } else {
1254                 WL_SCAN(("Scanning all channels\n"));
1255         }
1256
1257         /* Copy ssid array if applicable */
1258         WL_SCAN(("### List of SSIDs to scan ###\n"));
1259         if (n_ssids > 0) {
1260                 offset = offsetof(wl_scan_params_t, channel_list) + n_channels * sizeof(u16);
1261                 offset = roundup(offset, sizeof(u32));
1262                 ptr = (char*)params + offset;
1263                 for (i = 0; i < n_ssids; i++) {
1264                         memset(&ssid, 0, sizeof(wlc_ssid_t));
1265                         ssid.SSID_len = request->ssids[i].ssid_len;
1266                         memcpy(ssid.SSID, request->ssids[i].ssid, ssid.SSID_len);
1267                         if (!ssid.SSID_len)
1268                                 WL_SCAN(("%d: Broadcast scan\n", i));
1269                         else
1270                                 WL_SCAN(("%d: scan  for  %s size =%d\n", i,
1271                                 ssid.SSID, ssid.SSID_len));
1272                         memcpy(ptr, &ssid, sizeof(wlc_ssid_t));
1273                         ptr += sizeof(wlc_ssid_t);
1274                 }
1275         } else {
1276                 WL_SCAN(("Broadcast scan\n"));
1277         }
1278         /* Adding mask to channel numbers */
1279         params->channel_num =
1280                 htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) |
1281                        (n_channels & WL_SCAN_PARAMS_COUNT_MASK));
1282 }
1283
1284 static s32
1285 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request, u16 action)
1286 {
1287         u32 n_channels;
1288         u32 n_ssids;
1289         s32 params_size =
1290             (WL_SCAN_PARAMS_FIXED_SIZE + offsetof(wl_iscan_params_t, params));
1291         struct wl_iscan_params *params;
1292         s32 err = 0;
1293
1294         if (request != NULL) {
1295                 n_channels = request->n_channels;
1296                 n_ssids = request->n_ssids;
1297                 /* Allocate space for populating ssids in wl_iscan_params struct */
1298                 if (n_channels % 2)
1299                         /* If n_channels is odd, add a padd of u16 */
1300                         params_size += sizeof(u16) * (n_channels + 1);
1301                 else
1302                         params_size += sizeof(u16) * n_channels;
1303
1304                 /* Allocate space for populating ssids in wl_iscan_params struct */
1305                 params_size += sizeof(struct wlc_ssid) * n_ssids;
1306         }
1307         params = (struct wl_iscan_params *)kzalloc(params_size, GFP_KERNEL);
1308         if (!params) {
1309                 return -ENOMEM;
1310         }
1311
1312         wl_scan_prep(&params->params, request);
1313
1314         params->version = htod32(ISCAN_REQ_VERSION);
1315         params->action = htod16(action);
1316         params->scan_duration = htod16(0);
1317
1318         if (params_size + sizeof("iscan") >= WLC_IOCTL_MEDLEN) {
1319                 WL_ERR(("ioctl buffer length is not sufficient\n"));
1320                 err = -ENOMEM;
1321                 goto done;
1322         }
1323         err = wldev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
1324                 iscan->ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
1325         if (unlikely(err)) {
1326                 if (err == -EBUSY) {
1327                         WL_ERR(("system busy : iscan canceled\n"));
1328                 } else {
1329                         WL_ERR(("error (%d)\n", err));
1330                 }
1331         }
1332 done:
1333         kfree(params);
1334         return err;
1335 }
1336
1337 static s32 wl_do_iscan(struct wl_priv *wl, struct cfg80211_scan_request *request)
1338 {
1339         struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
1340         struct net_device *ndev = wl_to_prmry_ndev(wl);
1341         s32 passive_scan;
1342         s32 err = 0;
1343
1344         iscan->state = WL_ISCAN_STATE_SCANING;
1345
1346         passive_scan = wl->active_scan ? 0 : 1;
1347         err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
1348                 &passive_scan, sizeof(passive_scan), false);
1349         if (unlikely(err)) {
1350                 WL_DBG(("error (%d)\n", err));
1351                 return err;
1352         }
1353         wl->iscan_kickstart = true;
1354         wl_run_iscan(iscan, request, WL_SCAN_ACTION_START);
1355         mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
1356         iscan->timer_on = 1;
1357
1358         return err;
1359 }
1360
1361 static s32
1362 wl_get_valid_channels(struct net_device *ndev, u8 *valid_chan_list, s32 size)
1363 {
1364         wl_uint32_list_t *list;
1365         s32 err = BCME_OK;
1366         if (valid_chan_list == NULL || size <= 0)
1367                 return -ENOMEM;
1368
1369         memset(valid_chan_list, 0, size);
1370         list = (wl_uint32_list_t *)(void *) valid_chan_list;
1371         list->count = htod32(WL_NUMCHANNELS);
1372         err = wldev_ioctl(ndev, WLC_GET_VALID_CHANNELS, valid_chan_list, size, false);
1373         if (err != 0) {
1374                 WL_ERR(("get channels failed with %d\n", err));
1375         }
1376
1377         return err;
1378 }
1379
1380 static s32
1381 wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
1382         struct cfg80211_scan_request *request, uint16 action)
1383 {
1384         s32 err = BCME_OK;
1385         u32 n_channels;
1386         u32 n_ssids;
1387         s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params));
1388         wl_escan_params_t *params = NULL;
1389         struct cfg80211_scan_request *scan_request = wl->scan_request;
1390         u8 chan_buf[sizeof(u32)*(WL_NUMCHANNELS + 1)];
1391         u32 num_chans = 0;
1392         s32 channel;
1393         s32 n_valid_chan;
1394         s32 search_state = WL_P2P_DISC_ST_SCAN;
1395         u32 i, j, n_nodfs = 0;
1396         u16 *default_chan_list = NULL;
1397         wl_uint32_list_t *list;
1398         struct net_device *dev = NULL;
1399         WL_DBG(("Enter \n"));
1400
1401
1402         if (!wl->p2p_supported || ((ndev == wl_to_prmry_ndev(wl)) &&
1403                 !p2p_scan(wl))) {
1404                 /* LEGACY SCAN TRIGGER */
1405                 WL_SCAN((" LEGACY E-SCAN START\n"));
1406
1407                 if (request != NULL) {
1408                         n_channels = request->n_channels;
1409                         n_ssids = request->n_ssids;
1410                         /* Allocate space for populating ssids in wl_iscan_params struct */
1411                         if (n_channels % 2)
1412                                 /* If n_channels is odd, add a padd of u16 */
1413                                 params_size += sizeof(u16) * (n_channels + 1);
1414                         else
1415                                 params_size += sizeof(u16) * n_channels;
1416
1417                         /* Allocate space for populating ssids in wl_iscan_params struct */
1418                         params_size += sizeof(struct wlc_ssid) * n_ssids;
1419                 }
1420                 params = (wl_escan_params_t *) kzalloc(params_size, GFP_KERNEL);
1421                 if (params == NULL) {
1422                         err = -ENOMEM;
1423                         goto exit;
1424                 }
1425
1426                 wl_scan_prep(&params->params, request);
1427                 params->version = htod32(ESCAN_REQ_VERSION);
1428                 params->action =  htod16(action);
1429                 params->sync_id = htod16(0x1234);
1430                 if (params_size + sizeof("escan") >= WLC_IOCTL_MEDLEN) {
1431                         WL_ERR(("ioctl buffer length not sufficient\n"));
1432                         kfree(params);
1433                         err = -ENOMEM;
1434                         goto exit;
1435                 }
1436                 err = wldev_iovar_setbuf(ndev, "escan", params, params_size,
1437                         wl->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
1438                 if (unlikely(err))
1439                         WL_ERR((" Escan set error (%d)\n", err));
1440                 kfree(params);
1441         }
1442         else if (p2p_is_on(wl) && p2p_scan(wl)) {
1443                 /* P2P SCAN TRIGGER */
1444                 s32 _freq = 0;
1445                 n_nodfs = 0;
1446                 if (scan_request && scan_request->n_channels) {
1447                         num_chans = scan_request->n_channels;
1448                         WL_SCAN((" chann number : %d\n", num_chans));
1449                         default_chan_list = kzalloc(num_chans * sizeof(*default_chan_list),
1450                                 GFP_KERNEL);
1451                         if (default_chan_list == NULL) {
1452                                 WL_ERR(("channel list allocation failed \n"));
1453                                 err = -ENOMEM;
1454                                 goto exit;
1455                         }
1456                         if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) {
1457                                 list = (wl_uint32_list_t *) chan_buf;
1458                                 n_valid_chan = dtoh32(list->count);
1459                                 for (i = 0; i < num_chans; i++)
1460                                 {
1461                                         _freq = scan_request->channels[i]->center_freq;
1462                                         channel = ieee80211_frequency_to_channel(_freq);
1463                                         /* remove DFS channels */
1464                                         if (channel < 52 || channel > 140) {
1465                                                 for (j = 0; j < n_valid_chan; j++) {
1466                                                         /* allows only supported channel on
1467                                                         *  current reguatory
1468                                                         */
1469                                                         if (channel == (dtoh32(list->element[j])))
1470                                                                 default_chan_list[n_nodfs++] =
1471                                                                         channel;
1472                                                 }
1473                                         }
1474
1475                                 }
1476                         }
1477                         if (num_chans == 3 && (
1478                                                 (default_chan_list[0] == SOCIAL_CHAN_1) &&
1479                                                 (default_chan_list[1] == SOCIAL_CHAN_2) &&
1480                                                 (default_chan_list[2] == SOCIAL_CHAN_3))) {
1481                                 /* SOCIAL CHANNELS 1, 6, 11 */
1482                                 search_state = WL_P2P_DISC_ST_SEARCH;
1483                                 WL_INFO(("P2P SEARCH PHASE START \n"));
1484                         } else if ((dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION)) &&
1485                                 (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP)) {
1486                                 /* If you are already a GO, then do SEARCH only */
1487                                 WL_INFO(("Already a GO. Do SEARCH Only"));
1488                                 search_state = WL_P2P_DISC_ST_SEARCH;
1489                                 num_chans = n_nodfs;
1490
1491                         } else {
1492                                 WL_INFO(("P2P SCAN STATE START \n"));
1493                                 num_chans = n_nodfs;
1494                         }
1495
1496                 }
1497                 err = wl_cfgp2p_escan(wl, ndev, wl->active_scan, num_chans, default_chan_list,
1498                         search_state, action,
1499                         wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE));
1500                 kfree(default_chan_list);
1501         }
1502 exit:
1503         if (unlikely(err)) {
1504                 WL_ERR(("error (%d)\n", err));
1505         }
1506         return err;
1507 }
1508
1509
1510 static s32
1511 wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev,
1512         struct cfg80211_scan_request *request)
1513 {
1514         s32 err = BCME_OK;
1515         s32 passive_scan;
1516         wl_scan_results_t *results;
1517         WL_SCAN(("Enter \n"));
1518         wl->escan_info.ndev = ndev;
1519         wl->escan_info.wiphy = wiphy;
1520         wl->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
1521         passive_scan = wl->active_scan ? 0 : 1;
1522         err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
1523                 &passive_scan, sizeof(passive_scan), false);
1524         if (unlikely(err)) {
1525                 WL_ERR(("error (%d)\n", err));
1526                 return err;
1527         }
1528         results = (wl_scan_results_t *) wl->escan_info.escan_buf;
1529         results->version = 0;
1530         results->count = 0;
1531         results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
1532
1533         err = wl_run_escan(wl, ndev, request, WL_SCAN_ACTION_START);
1534         return err;
1535 }
1536
1537 static s32
1538 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
1539         struct cfg80211_scan_request *request,
1540         struct cfg80211_ssid *this_ssid)
1541 {
1542         struct wl_priv *wl = wiphy_priv(wiphy);
1543         struct cfg80211_ssid *ssids;
1544         struct wl_scan_req *sr = wl_to_sr(wl);
1545         struct ether_addr primary_mac;
1546         wpa_ie_fixed_t *wps_ie;
1547         s32 passive_scan;
1548         bool iscan_req;
1549         bool escan_req = false;
1550         bool p2p_ssid;
1551         s32 err = 0;
1552         s32 i;
1553         u32 wpsie_len = 0;
1554         u8 wpsie[IE_MAX_LEN];
1555
1556         /* If scan req comes for p2p0, send it over primary I/F
1557          * Scan results will be delivered corresponding to cfg80211_scan_request
1558          */
1559         if (ndev == wl->p2p_net) {
1560                 ndev = wl_to_prmry_ndev(wl);
1561         }
1562
1563         WL_DBG(("Enter wiphy (%p)\n", wiphy));
1564         if (wl_get_drv_status_all(wl, SCANNING)) {
1565                 WL_ERR(("Scanning already\n"));
1566                 return -EAGAIN;
1567         }
1568         if (wl_get_drv_status(wl, SCAN_ABORTING, ndev)) {
1569                 WL_ERR(("Scanning being aborted\n"));
1570                 return -EAGAIN;
1571         }
1572         if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) {
1573                 WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n"));
1574                 return -EOPNOTSUPP;
1575         }
1576
1577         /* Arm scan timeout timer */
1578         mod_timer(&wl->scan_timeout, jiffies + WL_SCAN_TIMER_INTERVAL_MS * HZ / 1000);
1579         iscan_req = false;
1580         if (request) {          /* scan bss */
1581                 ssids = request->ssids;
1582                 if (wl->iscan_on && (!ssids || !ssids->ssid_len || request->n_ssids != 1)) {
1583                         iscan_req = true;
1584                 } else if (wl->escan_on) {
1585                         escan_req = true;
1586                         p2p_ssid = false;
1587                         for (i = 0; i < request->n_ssids; i++) {
1588                                 if (ssids[i].ssid_len && IS_P2P_SSID(ssids[i].ssid)) {
1589                                         p2p_ssid = true;
1590                                         break;
1591                                 }
1592                         }
1593                         if (p2p_ssid) {
1594                                 if (wl->p2p_supported) {
1595                                         /* p2p scan trigger */
1596                                         if (p2p_on(wl) == false) {
1597                                                 /* p2p on at the first time */
1598                                                 p2p_on(wl) = true;
1599                                                 wl_cfgp2p_set_firm_p2p(wl);
1600                                                 get_primary_mac(wl, &primary_mac);
1601                                                 wl_cfgp2p_generate_bss_mac(&primary_mac,
1602                                                         &wl->p2p->dev_addr, &wl->p2p->int_addr);
1603                                         }
1604                                         wl_clr_p2p_status(wl, GO_NEG_PHASE);
1605                                         WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
1606                                         p2p_scan(wl) = true;
1607                                 }
1608                         } else {
1609                                 /* legacy scan trigger
1610                                  * So, we have to disable p2p discovery if p2p discovery is on
1611                                  */
1612                                 if (wl->p2p_supported) {
1613                                         p2p_scan(wl) = false;
1614                                         /* If Netdevice is not equals to primary and p2p is on
1615                                         *  , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
1616                                         */
1617                                         if (p2p_on(wl) && (ndev != wl_to_prmry_ndev(wl)))
1618                                                 p2p_scan(wl) = true;
1619
1620                                         if (p2p_scan(wl) == false) {
1621                                                 if (wl_get_p2p_status(wl, DISCOVERY_ON)) {
1622                                                         err = wl_cfgp2p_discover_enable_search(wl,
1623                                                         false);
1624                                                         if (unlikely(err)) {
1625                                                                 goto scan_out;
1626                                                         }
1627
1628                                                 }
1629                                         }
1630                                 }
1631                                 if (!wl->p2p_supported || !p2p_scan(wl)) {
1632                                         if (ndev == wl_to_prmry_ndev(wl)) {
1633                                                 /* find the WPSIE */
1634                                                 memset(wpsie, 0, sizeof(wpsie));
1635                                                 if ((wps_ie = wl_cfgp2p_find_wpsie(
1636                                                         (u8 *)request->ie,
1637                                                         request->ie_len)) != NULL) {
1638                                                         wpsie_len =
1639                                                         wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
1640                                                         memcpy(wpsie, wps_ie, wpsie_len);
1641                                                 } else {
1642                                                         wpsie_len = 0;
1643                                                 }
1644                                                 if (wpsie_len > 0) {
1645                                                         err = wl_cfgp2p_set_management_ie(wl,
1646                                                                 ndev, -1, VNDR_IE_PRBREQ_FLAG,
1647                                                                 wpsie, wpsie_len);
1648                                                         if (unlikely(err)) {
1649                                                                 goto scan_out;
1650                                                         }
1651                                                 }
1652                                         }
1653                                 }
1654                         }
1655                 }
1656         } else {                /* scan in ibss */
1657                 /* we don't do iscan in ibss */
1658                 ssids = this_ssid;
1659         }
1660         wl->scan_request = request;
1661         wl_set_drv_status(wl, SCANNING, ndev);
1662         if (iscan_req) {
1663                 err = wl_do_iscan(wl, request);
1664                 if (likely(!err))
1665                         return err;
1666                 else
1667                         goto scan_out;
1668         } else if (escan_req) {
1669                 if (wl->p2p_supported) {
1670                         if (p2p_on(wl) && p2p_scan(wl)) {
1671
1672                                 err = wl_cfgp2p_enable_discovery(wl, ndev,
1673                                 request->ie, request->ie_len);
1674
1675                                 if (unlikely(err)) {
1676                                         goto scan_out;
1677                                 }
1678                         }
1679                 }
1680                 err = wl_do_escan(wl, wiphy, ndev, request);
1681                 if (likely(!err))
1682                         return err;
1683                 else
1684                         goto scan_out;
1685
1686
1687         } else {
1688                 memset(&sr->ssid, 0, sizeof(sr->ssid));
1689                 sr->ssid.SSID_len =
1690                         min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len);
1691                 if (sr->ssid.SSID_len) {
1692                         memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len);
1693                         sr->ssid.SSID_len = htod32(sr->ssid.SSID_len);
1694                         WL_SCAN(("Specific scan ssid=\"%s\" len=%d\n",
1695                                 sr->ssid.SSID, sr->ssid.SSID_len));
1696                 } else {
1697                         WL_SCAN(("Broadcast scan\n"));
1698                 }
1699                 WL_SCAN(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len));
1700                 passive_scan = wl->active_scan ? 0 : 1;
1701                 err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
1702                         &passive_scan, sizeof(passive_scan), false);
1703                 if (unlikely(err)) {
1704                         WL_SCAN(("WLC_SET_PASSIVE_SCAN error (%d)\n", err));
1705                         goto scan_out;
1706                 }
1707                 err = wldev_ioctl(ndev, WLC_SCAN, &sr->ssid,
1708                         sizeof(sr->ssid), false);
1709                 if (err) {
1710                         if (err == -EBUSY) {
1711                                 WL_ERR(("system busy : scan for \"%s\" "
1712                                         "canceled\n", sr->ssid.SSID));
1713                         } else {
1714                                 WL_ERR(("WLC_SCAN error (%d)\n", err));
1715                         }
1716                         goto scan_out;
1717                 }
1718         }
1719
1720         return 0;
1721
1722 scan_out:
1723         wl_clr_drv_status(wl, SCANNING, ndev);
1724         wl->scan_request = NULL;
1725         return err;
1726 }
1727
1728 static s32
1729 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
1730         struct cfg80211_scan_request *request)
1731 {
1732         s32 err = 0;
1733         struct wl_priv *wl = wiphy_priv(wiphy);
1734
1735         WL_DBG(("Enter \n"));
1736         CHECK_SYS_UP(wl);
1737
1738         err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
1739         if (unlikely(err)) {
1740                 WL_ERR(("scan error (%d)\n", err));
1741                 return err;
1742         }
1743
1744         return err;
1745 }
1746
1747 static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
1748 {
1749         s32 err = 0;
1750
1751         err = wldev_iovar_setint(dev, "rtsthresh", rts_threshold);
1752         if (unlikely(err)) {
1753                 WL_ERR(("Error (%d)\n", err));
1754                 return err;
1755         }
1756         return err;
1757 }
1758
1759 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
1760 {
1761         s32 err = 0;
1762
1763         err = wldev_iovar_setint_bsscfg(dev, "fragthresh", frag_threshold, 0);
1764         if (unlikely(err)) {
1765                 WL_ERR(("Error (%d)\n", err));
1766                 return err;
1767         }
1768         return err;
1769 }
1770
1771 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
1772 {
1773         s32 err = 0;
1774         u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
1775
1776         retry = htod32(retry);
1777         err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), false);
1778         if (unlikely(err)) {
1779                 WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
1780                 return err;
1781         }
1782         return err;
1783 }
1784
1785 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1786 {
1787         struct wl_priv *wl = (struct wl_priv *)wiphy_priv(wiphy);
1788         struct net_device *ndev = wl_to_prmry_ndev(wl);
1789         s32 err = 0;
1790
1791         CHECK_SYS_UP(wl);
1792         WL_DBG(("Enter\n"));
1793         if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
1794                 (wl->conf->rts_threshold != wiphy->rts_threshold)) {
1795                 wl->conf->rts_threshold = wiphy->rts_threshold;
1796                 err = wl_set_rts(ndev, wl->conf->rts_threshold);
1797                 if (!err)
1798                         return err;
1799         }
1800         if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
1801                 (wl->conf->frag_threshold != wiphy->frag_threshold)) {
1802                 wl->conf->frag_threshold = wiphy->frag_threshold;
1803                 err = wl_set_frag(ndev, wl->conf->frag_threshold);
1804                 if (!err)
1805                         return err;
1806         }
1807         if (changed & WIPHY_PARAM_RETRY_LONG &&
1808                 (wl->conf->retry_long != wiphy->retry_long)) {
1809                 wl->conf->retry_long = wiphy->retry_long;
1810                 err = wl_set_retry(ndev, wl->conf->retry_long, true);
1811                 if (!err)
1812                         return err;
1813         }
1814         if (changed & WIPHY_PARAM_RETRY_SHORT &&
1815                 (wl->conf->retry_short != wiphy->retry_short)) {
1816                 wl->conf->retry_short = wiphy->retry_short;
1817                 err = wl_set_retry(ndev, wl->conf->retry_short, false);
1818                 if (!err) {
1819                         return err;
1820                 }
1821         }
1822         return err;
1823 }
1824
1825 static s32
1826 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
1827         struct cfg80211_ibss_params *params)
1828 {
1829         struct wl_priv *wl = wiphy_priv(wiphy);
1830         struct wl_join_params join_params;
1831         struct wlc_ssid ssid;
1832         struct ether_addr bssid;
1833         size_t join_params_size = 0;
1834         s32 wsec = 0;
1835         s32 bcnprd;
1836         s32 err = 0;
1837
1838         WL_TRACE(("In\n"));
1839         CHECK_SYS_UP(wl);
1840
1841         /*
1842          * Cancel ongoing scan to sync up with sme state machine of cfg80211.
1843          */
1844         if (wl->scan_request) {
1845                 wl_notify_escan_complete(wl, dev, true, true);
1846         }
1847         /* Clean BSSID */
1848         bzero(&bssid, sizeof(bssid));
1849         wl_update_prof(wl, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
1850
1851         if (params->ssid)
1852                 WL_INFO(("SSID: %s\n", params->ssid));
1853         else {
1854                 WL_ERR(("SSID: NULL, Not supported\n"));
1855                 err = -EOPNOTSUPP;
1856                 goto CleanUp;
1857         }
1858
1859         if (params->bssid)
1860                 WL_INFO(("BSSID: %02X:%02X:%02X:%02X:%02X:%02X\n",
1861                         params->bssid[0], params->bssid[1], params->bssid[2],
1862                         params->bssid[3], params->bssid[4], params->bssid[5]));
1863
1864         if (params->channel)
1865                 WL_INFO(("channel: %d\n", params->channel->center_freq));
1866
1867         if (params->channel_fixed)
1868                 WL_INFO(("fixed channel required\n"));
1869
1870         if (params->ie && params->ie_len)
1871                 WL_INFO(("ie len: %d\n", params->ie_len));
1872
1873         if (params->beacon_interval)
1874                 WL_INFO(("beacon interval: %d\n", params->beacon_interval));
1875
1876         if (params->basic_rates)
1877                 WL_INFO(("basic rates: %08X\n", params->basic_rates));
1878
1879         if (params->privacy)
1880                 WL_INFO(("privacy required\n"));
1881
1882         wl_set_drv_status(wl, CONNECTING, dev);
1883
1884         /* Configure Privacy for starter */
1885         if (params->privacy)
1886                 wsec |= WEP_ENABLED;
1887
1888         err = wldev_iovar_setint(dev, "wsec", wsec);
1889         if (err) {
1890                 WL_ERR(("wsec failed (%d)\n", err));
1891                 goto CleanUp;
1892         }
1893
1894         err = wldev_iovar_setint(dev, "auth", WL_AUTH_OPEN_SYSTEM);
1895         if (err) {
1896                 WL_ERR(("auth failed (%d)\n", err));
1897                 goto CleanUp;
1898         }
1899
1900         err = wldev_iovar_setint(dev, "wpa_auth", 0);
1901         if (err) {
1902                 WL_ERR(("wpa_auth failed (%d)\n", err));
1903                 goto CleanUp;
1904         }
1905
1906         /* Configure Beacon Interval for starter */
1907         if (params->beacon_interval)
1908                 bcnprd = params->beacon_interval;
1909         else
1910                 bcnprd = 100;
1911
1912         bcnprd = htod32(bcnprd);
1913         err = wldev_ioctl(dev, WLC_SET_BCNPRD, &bcnprd, sizeof(bcnprd), true);
1914         if (err) {
1915                 WL_ERR(("WLC_SET_BCNPRD failed (%d)\n", err));
1916                 goto CleanUp;
1917         }
1918
1919         /* Configure required join parameter */
1920         memset(&join_params, 0, sizeof(struct wl_join_params));
1921
1922         /* SSID */
1923         memset(&ssid, 0, sizeof(struct wlc_ssid));
1924         ssid.SSID_len = MIN(params->ssid_len, 32);
1925         join_params.ssid.SSID_len = htod32(ssid.SSID_len);
1926         memcpy(ssid.SSID, params->ssid, ssid.SSID_len);
1927         memcpy(join_params.ssid.SSID, params->ssid, ssid.SSID_len);
1928         join_params_size = sizeof(join_params.ssid);
1929
1930         wl_update_prof(wl, dev, NULL, &ssid, WL_PROF_SSID);
1931
1932         /* BSSID */
1933         if (params->bssid) {
1934                 memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
1935                 join_params_size = sizeof(join_params.ssid) +
1936                         WL_ASSOC_PARAMS_FIXED_SIZE;
1937
1938                 wl_update_prof(wl, dev, NULL, params->bssid, WL_PROF_BSSID);
1939         } else {
1940                 memcpy(&join_params.params.bssid, &ether_bcast, ETHER_ADDR_LEN);
1941         }
1942
1943         /* Channel */
1944         if (params->channel) {
1945                 u32 target_channel;
1946
1947                 target_channel = ieee80211_frequency_to_channel(
1948                                                         params->channel->center_freq);
1949                 if (params->channel_fixed) {
1950                         /* adding chanspec */
1951                         wl_ch_to_chanspec(target_channel,
1952                                 &join_params, &join_params_size);
1953                 }
1954
1955                 /* set channel for starter */
1956                 target_channel = htod32(target_channel);
1957                 err = wldev_ioctl(dev, WLC_SET_CHANNEL,
1958                         &target_channel, sizeof(target_channel), true);
1959                 if (err) {
1960                         WL_ERR(("WLC_SET_CHANNEL failed (%d)\n", err));
1961                         goto CleanUp;
1962                 }
1963         }
1964
1965         wl->ibss_starter = false;
1966
1967         err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true);
1968         if (err) {
1969                 WL_ERR(("WLC_SET_SSID failed (%d)\n", err));
1970                 goto CleanUp;
1971         }
1972
1973 CleanUp:
1974
1975         if (err)
1976                 wl_clr_drv_status(wl, CONNECTING, dev);
1977
1978         WL_TRACE(("Exit\n"));
1979         return err;
1980 }
1981
1982 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
1983 {
1984         struct wl_priv *wl = wiphy_priv(wiphy);
1985         scb_val_t scbval;
1986         bool act = false;
1987         s32 err = 0;
1988         u8 *curbssid;
1989
1990         WL_TRACE(("Enter\n"));
1991
1992         CHECK_SYS_UP(wl);
1993         act = *(bool *) wl_read_prof(wl, dev, WL_PROF_ACT);
1994         curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID);
1995         if (act) {
1996                 /*
1997                 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
1998                 */
1999                 if (wl->scan_request) {
2000                         wl_notify_escan_complete(wl, dev, true, true);
2001                 }
2002                 wl_set_drv_status(wl, DISCONNECTING, dev);
2003                 scbval.val = DOT11_RC_DISASSOC_LEAVING;
2004                 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
2005                 scbval.val = htod32(scbval.val);
2006                 err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
2007                                 sizeof(scb_val_t), true);
2008                 if (unlikely(err)) {
2009                         wl_clr_drv_status(wl, DISCONNECTING, dev);
2010                         WL_ERR(("error (%d)\n", err));
2011                         return err;
2012                 }
2013         }
2014
2015         WL_TRACE(("Exit\n"));
2016         return err;
2017 }
2018
2019 static s32
2020 wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
2021 {
2022         struct wl_priv *wl = wlcfg_drv_priv;
2023         struct wl_security *sec;
2024         s32 val = 0;
2025         s32 err = 0;
2026         s32 bssidx = wl_cfgp2p_find_idx(wl, dev);
2027
2028         if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
2029                 val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
2030         else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
2031                 val = WPA2_AUTH_PSK| WPA2_AUTH_UNSPECIFIED;
2032         else
2033                 val = WPA_AUTH_DISABLED;
2034
2035         if (is_wps_conn(sme))
2036                 val = WPA_AUTH_DISABLED;
2037
2038         WL_DBG(("setting wpa_auth to 0x%0x\n", val));
2039         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
2040         if (unlikely(err)) {
2041                 WL_ERR(("set wpa_auth failed (%d)\n", err));
2042                 return err;
2043         }
2044         sec = wl_read_prof(wl, dev, WL_PROF_SEC);
2045         sec->wpa_versions = sme->crypto.wpa_versions;
2046         return err;
2047 }
2048
2049 static s32
2050 wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
2051 {
2052         struct wl_priv *wl = wlcfg_drv_priv;
2053         struct wl_security *sec;
2054         s32 val = 0;
2055         s32 err = 0;
2056         s32 bssidx = wl_cfgp2p_find_idx(wl, dev);
2057         switch (sme->auth_type) {
2058         case NL80211_AUTHTYPE_OPEN_SYSTEM:
2059                 val = WL_AUTH_OPEN_SYSTEM;
2060                 WL_DBG(("open system\n"));
2061                 break;
2062         case NL80211_AUTHTYPE_SHARED_KEY:
2063                 val = WL_AUTH_SHARED_KEY;
2064                 WL_DBG(("shared key\n"));
2065                 break;
2066         case NL80211_AUTHTYPE_AUTOMATIC:
2067                 val = WL_AUTH_OPEN_SHARED;
2068                 WL_DBG(("automatic\n"));
2069                 break;
2070         case NL80211_AUTHTYPE_NETWORK_EAP:
2071                 WL_DBG(("network eap\n"));
2072         default:
2073                 val = WL_AUTH_OPEN_SHARED;
2074                 WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
2075                 break;
2076         }
2077
2078         err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
2079         if (unlikely(err)) {
2080                 WL_ERR(("set auth failed (%d)\n", err));
2081                 return err;
2082         }
2083         sec = wl_read_prof(wl, dev, WL_PROF_SEC);
2084         sec->auth_type = sme->auth_type;
2085         return err;
2086 }
2087
2088 static s32
2089 wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
2090 {
2091         struct wl_priv *wl = wlcfg_drv_priv;
2092         struct wl_security *sec;
2093         s32 pval = 0;
2094         s32 gval = 0;
2095         s32 err = 0;
2096         s32 bssidx = wl_cfgp2p_find_idx(wl, dev);
2097
2098         if (sme->crypto.n_ciphers_pairwise) {
2099                 switch (sme->crypto.ciphers_pairwise[0]) {
2100                 case WLAN_CIPHER_SUITE_WEP40:
2101                 case WLAN_CIPHER_SUITE_WEP104:
2102                         pval = WEP_ENABLED;
2103                         break;
2104                 case WLAN_CIPHER_SUITE_TKIP:
2105                         pval = TKIP_ENABLED;
2106                         break;
2107                 case WLAN_CIPHER_SUITE_CCMP:
2108                         pval = AES_ENABLED;
2109                         break;
2110                 case WLAN_CIPHER_SUITE_AES_CMAC:
2111                         pval = AES_ENABLED;
2112                         break;
2113                 default:
2114                         WL_ERR(("invalid cipher pairwise (%d)\n",
2115                                 sme->crypto.ciphers_pairwise[0]));
2116                         return -EINVAL;
2117                 }
2118         }
2119         if (sme->crypto.cipher_group) {
2120                 switch (sme->crypto.cipher_group) {
2121                 case WLAN_CIPHER_SUITE_WEP40:
2122                 case WLAN_CIPHER_SUITE_WEP104:
2123                         gval = WEP_ENABLED;
2124                         break;
2125                 case WLAN_CIPHER_SUITE_TKIP:
2126                         gval = TKIP_ENABLED;
2127                         break;
2128                 case WLAN_CIPHER_SUITE_CCMP:
2129                         gval = AES_ENABLED;
2130                         break;
2131                 case WLAN_CIPHER_SUITE_AES_CMAC:
2132                         gval = AES_ENABLED;
2133                         break;
2134                 default:
2135                         WL_ERR(("invalid cipher group (%d)\n",
2136                                 sme->crypto.cipher_group));
2137                         return -EINVAL;
2138                 }
2139         }
2140
2141         WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
2142
2143         if (is_wps_conn(sme)) {
2144                 if (sme->privacy)
2145                         err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
2146                 else
2147                         /* WPS-2.0 allowes no security */
2148                         err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
2149         } else {
2150                 WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC"));
2151                 err = wldev_iovar_setint_bsscfg(dev, "wsec",
2152                                 pval | gval, bssidx);
2153         }
2154         if (unlikely(err)) {
2155                 WL_ERR(("error (%d)\n", err));
2156                 return err;
2157         }
2158
2159         sec = wl_read_prof(wl, dev, WL_PROF_SEC);
2160         sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
2161         sec->cipher_group = sme->crypto.cipher_group;
2162
2163         return err;
2164 }
2165
2166 static s32
2167 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
2168 {
2169         struct wl_priv *wl = wlcfg_drv_priv;
2170         struct wl_security *sec;
2171         s32 val = 0;
2172         s32 err = 0;
2173         s32 bssidx = wl_cfgp2p_find_idx(wl, dev);
2174
2175         if (sme->crypto.n_akm_suites) {
2176                 err = wldev_iovar_getint(dev, "wpa_auth", &val);
2177                 if (unlikely(err)) {
2178                         WL_ERR(("could not get wpa_auth (%d)\n", err));
2179                         return err;
2180                 }
2181                 if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
2182                         switch (sme->crypto.akm_suites[0]) {
2183                         case WLAN_AKM_SUITE_8021X:
2184                                 val = WPA_AUTH_UNSPECIFIED;
2185                                 break;
2186                         case WLAN_AKM_SUITE_PSK:
2187                                 val = WPA_AUTH_PSK;
2188                                 break;
2189                         default:
2190                                 WL_ERR(("invalid cipher group (%d)\n",
2191                                         sme->crypto.cipher_group));
2192                                 return -EINVAL;
2193                         }
2194                 } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
2195                         switch (sme->crypto.akm_suites[0]) {
2196                         case WLAN_AKM_SUITE_8021X:
2197                                 val = WPA2_AUTH_UNSPECIFIED;
2198                                 break;
2199                         case WLAN_AKM_SUITE_PSK:
2200                                 val = WPA2_AUTH_PSK;
2201                                 break;
2202                         default:
2203                                 WL_ERR(("invalid cipher group (%d)\n",
2204                                         sme->crypto.cipher_group));
2205                                 return -EINVAL;
2206                         }
2207                 }
2208                 WL_DBG(("setting wpa_auth to %d\n", val));
2209
2210                 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
2211                 if (unlikely(err)) {
2212                         WL_ERR(("could not set wpa_auth (%d)\n", err));
2213                         return err;
2214                 }
2215         }
2216         sec = wl_read_prof(wl, dev, WL_PROF_SEC);
2217         sec->wpa_auth = sme->crypto.akm_suites[0];
2218
2219         return err;
2220 }
2221
2222 static s32
2223 wl_set_set_sharedkey(struct net_device *dev,
2224         struct cfg80211_connect_params *sme)
2225 {
2226         struct wl_priv *wl = wlcfg_drv_priv;
2227         struct wl_security *sec;
2228         struct wl_wsec_key key;
2229         s32 val;
2230         s32 err = 0;
2231         s32 bssidx = wl_cfgp2p_find_idx(wl, dev);
2232
2233         WL_DBG(("key len (%d)\n", sme->key_len));
2234         if (sme->key_len) {
2235                 sec = wl_read_prof(wl, dev, WL_PROF_SEC);
2236                 WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
2237                         sec->wpa_versions, sec->cipher_pairwise));
2238                 if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 |
2239                         NL80211_WPA_VERSION_2)) &&
2240                         (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
2241                 WLAN_CIPHER_SUITE_WEP104)))
2242                 {
2243                         memset(&key, 0, sizeof(key));
2244                         key.len = (u32) sme->key_len;
2245                         key.index = (u32) sme->key_idx;
2246                         if (unlikely(key.len > sizeof(key.data))) {
2247                                 WL_ERR(("Too long key length (%u)\n", key.len));
2248                                 return -EINVAL;
2249                         }
2250                         memcpy(key.data, sme->key, key.len);
2251                         key.flags = WL_PRIMARY_KEY;
2252                         switch (sec->cipher_pairwise) {
2253                         case WLAN_CIPHER_SUITE_WEP40:
2254                                 key.algo = CRYPTO_ALGO_WEP1;
2255                                 break;
2256                         case WLAN_CIPHER_SUITE_WEP104:
2257                                 key.algo = CRYPTO_ALGO_WEP128;
2258                                 break;
2259                         default:
2260                                 WL_ERR(("Invalid algorithm (%d)\n",
2261                                         sme->crypto.ciphers_pairwise[0]));
2262                                 return -EINVAL;
2263                         }
2264                         /* Set the new key/index */
2265                         WL_DBG(("key length (%d) key index (%d) algo (%d)\n",
2266                                 key.len, key.index, key.algo));
2267                         WL_DBG(("key \"%s\"\n", key.data));
2268                         swap_key_from_BE(&key);
2269                         err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
2270                                 wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
2271                         if (unlikely(err)) {
2272                                 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
2273                                 return err;
2274                         }
2275                         if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
2276                                 WL_DBG(("set auth_type to shared key\n"));
2277                                 val = WL_AUTH_SHARED_KEY;       /* shared key */
2278                                 err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
2279                                 if (unlikely(err)) {
2280                                         WL_ERR(("set auth failed (%d)\n", err));
2281                                         return err;
2282                                 }
2283                         }
2284                 }
2285         }
2286         return err;
2287 }
2288
2289 static s32
2290 wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
2291         struct cfg80211_connect_params *sme)
2292 {
2293         struct wl_priv *wl = wiphy_priv(wiphy);
2294         struct ieee80211_channel *chan = sme->channel;
2295         wl_extjoin_params_t *ext_join_params;
2296         struct wl_join_params join_params;
2297         size_t join_params_size;
2298         s32 err = 0;
2299         wpa_ie_fixed_t *wpa_ie;
2300         wpa_ie_fixed_t *wps_ie;
2301         bcm_tlv_t *wpa2_ie;
2302         u8* wpaie  = 0;
2303         u32 wpaie_len = 0;
2304         u32 wpsie_len = 0;
2305         u32 chan_cnt = 0;
2306         u8 wpsie[IE_MAX_LEN];
2307         struct ether_addr bssid;
2308
2309         WL_DBG(("In\n"));
2310         CHECK_SYS_UP(wl);
2311
2312         /*
2313          * Cancel ongoing scan to sync up with sme state machine of cfg80211.
2314          */
2315         if (wl->scan_request) {
2316                 wl_notify_escan_complete(wl, dev, true, true);
2317         }
2318         /* Clean BSSID */
2319         bzero(&bssid, sizeof(bssid));
2320         wl_update_prof(wl, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
2321
2322         if (IS_P2P_SSID(sme->ssid) && (dev != wl_to_prmry_ndev(wl))) {
2323                 /* we only allow to connect using virtual interface in case of P2P */
2324                 if (p2p_is_on(wl) && is_wps_conn(sme)) {
2325                         WL_DBG(("ASSOC1 p2p index : %d sme->ie_len %d\n",
2326                                 wl_cfgp2p_find_idx(wl, dev), sme->ie_len));
2327                         /* Have to apply WPS IE + P2P IE in assoc req frame */
2328                         wl_cfgp2p_set_management_ie(wl, dev,
2329                                 wl_cfgp2p_find_idx(wl, dev), VNDR_IE_PRBREQ_FLAG,
2330                                 wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie,
2331                                 wl_to_p2p_bss_saved_ie(wl,
2332                                 P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len);
2333                         wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev),
2334                                 VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
2335                 } else if (p2p_is_on(wl) && (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)) {
2336                         /* This is the connect req after WPS is done [credentials exchanged]
2337                          * currently identified with WPA_VERSION_2 .
2338                          * Update the previously set IEs with
2339                          * the newly received IEs from Supplicant. This will remove the WPS IE from
2340                          * the Assoc Req.
2341                          */
2342                         WL_DBG(("ASSOC2 p2p index : %d sme->ie_len %d\n",
2343                                 wl_cfgp2p_find_idx(wl, dev), sme->ie_len));
2344                         wl_cfgp2p_set_management_ie(wl, dev,
2345                                 wl_cfgp2p_find_idx(wl, dev), VNDR_IE_PRBREQ_FLAG,
2346                                 sme->ie, sme->ie_len);
2347                         wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev),
2348                                 VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
2349                 }
2350
2351         } else if (dev == wl_to_prmry_ndev(wl)) {
2352                         /* find the RSN_IE */
2353                         if ((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
2354                                 DOT11_MNG_RSN_ID)) != NULL) {
2355                                 WL_DBG((" WPA2 IE is found\n"));
2356                         }
2357                         /* find the WPA_IE */
2358                         if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)sme->ie,
2359                                 sme->ie_len)) != NULL) {
2360                                 WL_DBG((" WPA IE is found\n"));
2361                         }
2362                         if (wpa_ie != NULL || wpa2_ie != NULL) {
2363                                 wpaie = (wpa_ie != NULL) ? (u8 *)wpa_ie : (u8 *)wpa2_ie;
2364                                 wpaie_len = (wpa_ie != NULL) ? wpa_ie->length : wpa2_ie->len;
2365                                 wpaie_len += WPA_RSN_IE_TAG_FIXED_LEN;
2366                                 wldev_iovar_setbuf(dev, "wpaie", wpaie, wpaie_len,
2367                                         wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
2368                         } else {
2369                                 wldev_iovar_setbuf(dev, "wpaie", NULL, 0,
2370                                         wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
2371                         }
2372
2373                         /* find the WPSIE */
2374                         memset(wpsie, 0, sizeof(wpsie));
2375                         if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)sme->ie,
2376                                 sme->ie_len)) != NULL) {
2377                                 wpsie_len = wps_ie->length +WPA_RSN_IE_TAG_FIXED_LEN;
2378                                 memcpy(wpsie, wps_ie, wpsie_len);
2379                         } else {
2380                                 wpsie_len = 0;
2381                         }
2382                         err = wl_cfgp2p_set_management_ie(wl, dev, -1,
2383                                 VNDR_IE_ASSOCREQ_FLAG, wpsie, wpsie_len);
2384                         if (unlikely(err)) {
2385                                 return err;
2386                         }
2387         }
2388         if (unlikely(!sme->ssid)) {
2389                 WL_ERR(("Invalid ssid\n"));
2390                 return -EOPNOTSUPP;
2391         }
2392         if (chan) {
2393                 wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
2394                 chan_cnt = 1;
2395                 WL_DBG(("channel (%d), center_req (%d)\n", wl->channel,
2396                         chan->center_freq));
2397         } else
2398                 wl->channel = 0;
2399         WL_DBG(("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len));
2400         err = wl_set_wpa_version(dev, sme);
2401         if (unlikely(err)) {
2402                 WL_ERR(("Invalid wpa_version\n"));
2403                 return err;
2404         }
2405
2406         err = wl_set_auth_type(dev, sme);
2407         if (unlikely(err)) {
2408                 WL_ERR(("Invalid auth type\n"));
2409                 return err;
2410         }
2411
2412         err = wl_set_set_cipher(dev, sme);
2413         if (unlikely(err)) {
2414                 WL_ERR(("Invalid ciper\n"));
2415                 return err;
2416         }
2417
2418         err = wl_set_key_mgmt(dev, sme);
2419         if (unlikely(err)) {
2420                 WL_ERR(("Invalid key mgmt\n"));
2421                 return err;
2422         }
2423
2424         err = wl_set_set_sharedkey(dev, sme);
2425         if (unlikely(err)) {
2426                 WL_ERR(("Invalid shared key\n"));
2427                 return err;
2428         }
2429
2430         /*
2431          *  Join with specific BSSID and cached SSID
2432          *  If SSID is zero join based on BSSID only
2433          */
2434         join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE +
2435                 chan_cnt * sizeof(chanspec_t);
2436         ext_join_params =  (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL);
2437         if (ext_join_params == NULL) {
2438                 err = -ENOMEM;
2439                 wl_clr_drv_status(wl, CONNECTING, dev);
2440                 goto exit;
2441         }
2442         ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len);
2443         memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len);
2444         ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
2445         /* Set up join scan parameters */
2446         ext_join_params->scan.scan_type = -1;
2447         ext_join_params->scan.nprobes = 2;
2448         /* increate dwell time to receive probe response or detect Beacon
2449         * from target AP at a noisy air only during connect command
2450         */
2451         ext_join_params->scan.active_time = WL_SCAN_ACTIVE_TIME*3;
2452         ext_join_params->scan.passive_time = WL_SCAN_PASSIVE_TIME*3;
2453         ext_join_params->scan.home_time = -1;
2454
2455         if (sme->bssid)
2456                 memcpy(&ext_join_params->assoc.bssid, sme->bssid, ETH_ALEN);
2457         else
2458                 memcpy(&ext_join_params->assoc.bssid, &ether_bcast, ETH_ALEN);
2459         ext_join_params->assoc.chanspec_num = chan_cnt;
2460         if (chan_cnt) {
2461                 u16 channel, band, bw, ctl_sb;
2462                 chanspec_t chspec;
2463                 channel = wl->channel;
2464                 band = (channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G
2465                         : WL_CHANSPEC_BAND_5G;
2466                 bw = WL_CHANSPEC_BW_20;
2467                 ctl_sb = WL_CHANSPEC_CTL_SB_NONE;
2468                 chspec = (channel | band | bw | ctl_sb);
2469                 ext_join_params->assoc.chanspec_list[0]  &= WL_CHANSPEC_CHAN_MASK;
2470                 ext_join_params->assoc.chanspec_list[0] |= chspec;
2471                 ext_join_params->assoc.chanspec_list[0] =
2472                         htodchanspec(ext_join_params->assoc.chanspec_list[0]);
2473         }
2474         ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num);
2475         if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
2476                 WL_INFO(("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID,
2477                         ext_join_params->ssid.SSID_len));
2478         }
2479         wl_set_drv_status(wl, CONNECTING, dev);
2480         err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size,
2481                 wl->ioctl_buf, WLC_IOCTL_MAXLEN, wl_cfgp2p_find_idx(wl, dev), &wl->ioctl_buf_sync);
2482         kfree(ext_join_params);
2483         if (err) {
2484                 wl_clr_drv_status(wl, CONNECTING, dev);
2485                 if (err == BCME_UNSUPPORTED) {
2486                         WL_DBG(("join iovar is not supported\n"));
2487                         goto set_ssid;
2488                 } else
2489                         WL_ERR(("error (%d)\n", err));
2490         } else
2491                 goto exit;
2492
2493 set_ssid:
2494         memset(&join_params, 0, sizeof(join_params));
2495         join_params_size = sizeof(join_params.ssid);
2496
2497         join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
2498         memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
2499         join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
2500         wl_update_prof(wl, dev, NULL, &join_params.ssid, WL_PROF_SSID);
2501         if (sme->bssid)
2502                 memcpy(&join_params.params.bssid, sme->bssid, ETH_ALEN);
2503         else
2504                 memcpy(&join_params.params.bssid, &ether_bcast, ETH_ALEN);
2505
2506         wl_ch_to_chanspec(wl->channel, &join_params, &join_params_size);
2507         WL_DBG(("join_param_size %d\n", join_params_size));
2508
2509         if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
2510                 WL_INFO(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
2511                         join_params.ssid.SSID_len));
2512         }
2513         wl_set_drv_status(wl, CONNECTING, dev);
2514         err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true);
2515         if (err) {
2516                 WL_ERR(("error (%d)\n", err));
2517                 wl_clr_drv_status(wl, CONNECTING, dev);
2518         }
2519 exit:
2520         return err;
2521 }
2522
2523 static s32
2524 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
2525         u16 reason_code)
2526 {
2527         struct wl_priv *wl = wiphy_priv(wiphy);
2528         scb_val_t scbval;
2529         bool act = false;
2530         s32 err = 0;
2531         u8 *curbssid;
2532         WL_ERR(("Reason %d\n", reason_code));
2533         CHECK_SYS_UP(wl);
2534         act = *(bool *) wl_read_prof(wl, dev, WL_PROF_ACT);
2535         curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID);
2536         if (act) {
2537                 /*
2538                 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
2539                 */
2540                 if (wl->scan_request) {
2541                         wl_notify_escan_complete(wl, dev, true, true);
2542                 }
2543                 wl_set_drv_status(wl, DISCONNECTING, dev);
2544                 scbval.val = reason_code;
2545                 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
2546                 scbval.val = htod32(scbval.val);
2547                 err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
2548                         sizeof(scb_val_t), true);
2549                 if (unlikely(err)) {
2550                         wl_clr_drv_status(wl, DISCONNECTING, dev);
2551                         WL_ERR(("error (%d)\n", err));
2552                         return err;
2553                 }
2554         }
2555
2556         return err;
2557 }
2558
2559 static s32
2560 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
2561         enum nl80211_tx_power_setting type, s32 dbm)
2562 {
2563
2564         struct wl_priv *wl = wiphy_priv(wiphy);
2565         struct net_device *ndev = wl_to_prmry_ndev(wl);
2566         u16 txpwrmw;
2567         s32 err = 0;
2568         s32 disable = 0;
2569
2570         CHECK_SYS_UP(wl);
2571         switch (type) {
2572         case NL80211_TX_POWER_AUTOMATIC:
2573                 break;
2574         case NL80211_TX_POWER_LIMITED:
2575                 if (dbm < 0) {
2576                         WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
2577                         return -EINVAL;
2578                 }
2579                 break;
2580         case NL80211_TX_POWER_FIXED:
2581                 if (dbm < 0) {
2582                         WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
2583                         return -EINVAL;
2584                 }
2585                 break;
2586         }
2587         /* Make sure radio is off or on as far as software is concerned */
2588         disable = WL_RADIO_SW_DISABLE << 16;
2589         disable = htod32(disable);
2590         err = wldev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable), true);
2591         if (unlikely(err)) {
2592                 WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
2593                 return err;
2594         }
2595
2596         if (dbm > 0xffff)
2597                 txpwrmw = 0xffff;
2598         else
2599                 txpwrmw = (u16) dbm;
2600         err = wldev_iovar_setint(ndev, "qtxpower",
2601                 (s32) (bcm_mw_to_qdbm(txpwrmw)));
2602         if (unlikely(err)) {
2603                 WL_ERR(("qtxpower error (%d)\n", err));
2604                 return err;
2605         }
2606         wl->conf->tx_power = dbm;
2607
2608         return err;
2609 }
2610
2611 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
2612 {
2613         struct wl_priv *wl = wiphy_priv(wiphy);
2614         struct net_device *ndev = wl_to_prmry_ndev(wl);
2615         s32 txpwrdbm;
2616         u8 result;
2617         s32 err = 0;
2618
2619         CHECK_SYS_UP(wl);
2620         err = wldev_iovar_getint(ndev, "qtxpower", &txpwrdbm);
2621         if (unlikely(err)) {
2622                 WL_ERR(("error (%d)\n", err));
2623                 return err;
2624         }
2625         result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
2626         *dbm = (s32) bcm_qdbm_to_mw(result);
2627
2628         return err;
2629 }
2630
2631 static s32
2632 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
2633         u8 key_idx, bool unicast, bool multicast)
2634 {
2635         struct wl_priv *wl = wiphy_priv(wiphy);
2636         u32 index;
2637         s32 wsec;
2638         s32 err = 0;
2639         s32 bssidx = wl_cfgp2p_find_idx(wl, dev);
2640
2641         WL_DBG(("key index (%d)\n", key_idx));
2642         CHECK_SYS_UP(wl);
2643         err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
2644         if (unlikely(err)) {
2645                 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
2646                 return err;
2647         }
2648         if (wsec & WEP_ENABLED) {
2649                 /* Just select a new current key */
2650                 index = (u32) key_idx;
2651                 index = htod32(index);
2652                 err = wldev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
2653                         sizeof(index), true);
2654                 if (unlikely(err)) {
2655                         WL_ERR(("error (%d)\n", err));
2656                 }
2657         }
2658         return err;
2659 }
2660
2661 static s32
2662 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
2663         u8 key_idx, const u8 *mac_addr, struct key_params *params)
2664 {
2665         struct wl_priv *wl = wiphy_priv(wiphy);
2666         struct wl_wsec_key key;
2667         s32 err = 0;
2668         s32 bssidx = wl_cfgp2p_find_idx(wl, dev);
2669         s32 mode = wl_get_mode_by_netdev(wl, dev);
2670         memset(&key, 0, sizeof(key));
2671         key.index = (u32) key_idx;
2672
2673         if (!ETHER_ISMULTI(mac_addr))
2674                 memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN);
2675         key.len = (u32) params->key_len;
2676
2677         /* check for key index change */
2678         if (key.len == 0) {
2679                 /* key delete */
2680                 swap_key_from_BE(&key);
2681                 wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
2682                         wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
2683                 if (unlikely(err)) {
2684                         WL_ERR(("key delete error (%d)\n", err));
2685                         return err;
2686                 }
2687         } else {
2688                 if (key.len > sizeof(key.data)) {
2689                         WL_ERR(("Invalid key length (%d)\n", key.len));
2690                         return -EINVAL;
2691                 }
2692                 WL_DBG(("Setting the key index %d\n", key.index));
2693                 memcpy(key.data, params->key, key.len);
2694
2695                 if ((mode == WL_MODE_BSS) &&
2696                         (params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
2697                         u8 keybuf[8];
2698                         memcpy(keybuf, &key.data[24], sizeof(keybuf));
2699                         memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
2700                         memcpy(&key.data[16], keybuf, sizeof(keybuf));
2701                 }
2702
2703                 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
2704                 if (params->seq && params->seq_len == 6) {
2705                         /* rx iv */
2706                         u8 *ivptr;
2707                         ivptr = (u8 *) params->seq;
2708                         key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
2709                                 (ivptr[3] << 8) | ivptr[2];
2710                         key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
2711                         key.iv_initialized = true;
2712                 }
2713
2714                 switch (params->cipher) {
2715                 case WLAN_CIPHER_SUITE_WEP40:
2716                         key.algo = CRYPTO_ALGO_WEP1;
2717                         WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
2718                         break;
2719                 case WLAN_CIPHER_SUITE_WEP104:
2720                         key.algo = CRYPTO_ALGO_WEP128;
2721                         WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
2722                         break;
2723                 case WLAN_CIPHER_SUITE_TKIP:
2724                         key.algo = CRYPTO_ALGO_TKIP;
2725                         WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
2726                         break;
2727                 case WLAN_CIPHER_SUITE_AES_CMAC:
2728                         key.algo = CRYPTO_ALGO_AES_CCM;
2729                         WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
2730                         break;
2731                 case WLAN_CIPHER_SUITE_CCMP:
2732                         key.algo = CRYPTO_ALGO_AES_CCM;
2733                         WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
2734                         break;
2735                 default:
2736                         WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
2737                         return -EINVAL;
2738                 }
2739                 swap_key_from_BE(&key);
2740                 wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
2741                         wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
2742                 if (unlikely(err)) {
2743                         WL_ERR(("WLC_SET_KEY error (%d)\n", err));
2744                         return err;
2745                 }
2746         }
2747         return err;
2748 }
2749
2750 static s32
2751 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
2752         u8 key_idx, bool pairwise, const u8 *mac_addr,
2753         struct key_params *params)
2754 {
2755         struct wl_wsec_key key;
2756         s32 val = 0;
2757         s32 wsec = 0;
2758         s32 err = 0;
2759         u8 keybuf[8];
2760         s32 bssidx = 0;
2761         struct wl_priv *wl = wiphy_priv(wiphy);
2762         s32 mode = wl_get_mode_by_netdev(wl, dev);
2763         WL_DBG(("key index (%d)\n", key_idx));
2764         CHECK_SYS_UP(wl);
2765
2766         bssidx = wl_cfgp2p_find_idx(wl, dev);
2767
2768         if (mac_addr) {
2769                 wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
2770                 goto exit;
2771         }
2772         memset(&key, 0, sizeof(key));
2773
2774         key.len = (u32) params->key_len;
2775         key.index = (u32) key_idx;
2776
2777         if (unlikely(key.len > sizeof(key.data))) {
2778                 WL_ERR(("Too long key length (%u)\n", key.len));
2779                 return -EINVAL;
2780         }
2781         memcpy(key.data, params->key, key.len);
2782
2783         key.flags = WL_PRIMARY_KEY;
2784         switch (params->cipher) {
2785         case WLAN_CIPHER_SUITE_WEP40:
2786                 key.algo = CRYPTO_ALGO_WEP1;
2787                 val = WEP_ENABLED;
2788                 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
2789                 break;
2790         case WLAN_CIPHER_SUITE_WEP104:
2791                 key.algo = CRYPTO_ALGO_WEP128;
2792                 val = WEP_ENABLED;
2793                 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
2794                 break;
2795         case WLAN_CIPHER_SUITE_TKIP:
2796                 key.algo = CRYPTO_ALGO_TKIP;
2797                 val = TKIP_ENABLED;
2798                 /* wpa_supplicant switches the third and fourth quarters of the TKIP key */
2799                 if (mode == WL_MODE_BSS) {
2800                         bcopy(&key.data[24], keybuf, sizeof(keybuf));
2801                         bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
2802                         bcopy(keybuf, &key.data[16], sizeof(keybuf));
2803                 }
2804                 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
2805                 break;
2806         case WLAN_CIPHER_SUITE_AES_CMAC:
2807                 key.algo = CRYPTO_ALGO_AES_CCM;
2808                 val = AES_ENABLED;
2809                 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
2810                 break;
2811         case WLAN_CIPHER_SUITE_CCMP:
2812                 key.algo = CRYPTO_ALGO_AES_CCM;
2813                 val = AES_ENABLED;
2814                 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
2815                 break;
2816         default:
2817                 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
2818                 return -EINVAL;
2819         }
2820
2821         /* Set the new key/index */
2822         swap_key_from_BE(&key);
2823         err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), wl->ioctl_buf,
2824                 WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
2825         if (unlikely(err)) {
2826                 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
2827                 return err;
2828         }
2829
2830 exit:
2831         err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
2832         if (unlikely(err)) {
2833                 WL_ERR(("get wsec error (%d)\n", err));
2834                 return err;
2835         }
2836
2837         wsec |= val;
2838         err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
2839         if (unlikely(err)) {
2840                 WL_ERR(("set wsec error (%d)\n", err));
2841                 return err;
2842         }
2843
2844         return err;
2845 }
2846
2847 static s32
2848 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
2849         u8 key_idx, bool pairwise, const u8 *mac_addr)
2850 {
2851         struct wl_wsec_key key;
2852         struct wl_priv *wl = wiphy_priv(wiphy);
2853         s32 err = 0;
2854         s32 bssidx = wl_cfgp2p_find_idx(wl, dev);
2855
2856         WL_DBG(("Enter\n"));
2857         CHECK_SYS_UP(wl);
2858         memset(&key, 0, sizeof(key));
2859
2860         key.flags = WL_PRIMARY_KEY;
2861         key.algo = CRYPTO_ALGO_OFF;
2862         key.index = (u32) key_idx;
2863
2864         WL_DBG(("key index (%d)\n", key_idx));
2865         /* Set the new key/index */
2866         swap_key_from_BE(&key);
2867         wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), wl->ioctl_buf,
2868                 WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
2869         if (unlikely(err)) {
2870                 if (err == -EINVAL) {
2871                         if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
2872                                 /* we ignore this key index in this case */
2873                                 WL_DBG(("invalid key index (%d)\n", key_idx));
2874                         }
2875                 } else {
2876                         WL_ERR(("WLC_SET_KEY error (%d)\n", err));
2877                 }
2878                 return err;
2879         }
2880         return err;
2881 }
2882
2883 static s32
2884 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
2885         u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
2886         void (*callback) (void *cookie, struct key_params * params))
2887 {
2888         struct key_params params;
2889         struct wl_wsec_key key;
2890         struct wl_priv *wl = wiphy_priv(wiphy);
2891         struct wl_security *sec;
2892         s32 wsec;
2893         s32 err = 0;
2894         s32 bssidx = wl_cfgp2p_find_idx(wl, dev);
2895
2896         WL_DBG(("key index (%d)\n", key_idx));
2897         CHECK_SYS_UP(wl);
2898         memset(&key, 0, sizeof(key));
2899         key.index = key_idx;
2900         swap_key_to_BE(&key);
2901         memset(&params, 0, sizeof(params));
2902         params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
2903         memcpy(params.key, key.data, params.key_len);
2904
2905         wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
2906         if (unlikely(err)) {
2907                 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
2908                 return err;
2909         }
2910         switch (wsec & ~SES_OW_ENABLED) {
2911                 case WEP_ENABLED:
2912                         sec = wl_read_prof(wl, dev, WL_PROF_SEC);
2913                         if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
2914                                 params.cipher = WLAN_CIPHER_SUITE_WEP40;
2915                                 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
2916                         } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
2917                                 params.cipher = WLAN_CIPHER_SUITE_WEP104;
2918                                 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
2919                         }
2920                         break;
2921                 case TKIP_ENABLED:
2922                         params.cipher = WLAN_CIPHER_SUITE_TKIP;
2923                         WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
2924                         break;
2925                 case AES_ENABLED:
2926                         params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
2927                         WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
2928                         break;
2929                 default:
2930                         WL_ERR(("Invalid algo (0x%x)\n", wsec));
2931                         return -EINVAL;
2932         }
2933
2934         callback(cookie, &params);
2935         return err;
2936 }
2937
2938 static s32
2939 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
2940         struct net_device *dev, u8 key_idx)
2941 {
2942         WL_INFO(("Not supported\n"));
2943         return -EOPNOTSUPP;
2944 }
2945
2946 static s32
2947 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
2948         u8 *mac, struct station_info *sinfo)
2949 {
2950         struct wl_priv *wl = wiphy_priv(wiphy);
2951         scb_val_t scb_val;
2952         s32 rssi;
2953         s32 rate;
2954         s32 err = 0;
2955         sta_info_t *sta;
2956 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
2957         s8 eabuf[ETHER_ADDR_STR_LEN];
2958 #endif
2959         dhd_pub_t *dhd =  (dhd_pub_t *)(wl->pub);
2960
2961         CHECK_SYS_UP(wl);
2962         if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) {
2963                 err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac,
2964                         ETHER_ADDR_LEN, wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
2965                 if (err < 0) {
2966                         WL_ERR(("GET STA INFO failed, %d\n", err));
2967                         return err;
2968                 }
2969                 sinfo->filled = STATION_INFO_INACTIVE_TIME;
2970                 sta = (sta_info_t *)wl->ioctl_buf;
2971                 sta->len = dtoh16(sta->len);
2972                 sta->cap = dtoh16(sta->cap);
2973                 sta->flags = dtoh32(sta->flags);
2974                 sta->idle = dtoh32(sta->idle);
2975                 sta->in = dtoh32(sta->in);
2976                 sinfo->inactive_time = sta->idle * 1000;
2977 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
2978                 if (sta->flags & WL_STA_ASSOC) {
2979                         sinfo->filled |= STATION_INFO_CONNECTED_TIME;
2980                         sinfo->connected_time = sta->in;
2981                 }
2982                 WL_INFO(("STA %s : idle time : %d sec, connected time :%d ms\n",
2983                         bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), sinfo->inactive_time,
2984                         sta->idle * 1000));
2985 #endif
2986         } else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_BSS) {
2987                 u8 *curmacp = wl_read_prof(wl, dev, WL_PROF_BSSID);
2988                 err = -ENODEV;
2989                 if (!wl_get_drv_status(wl, CONNECTED, dev) ||
2990                         (dhd_is_associated(dhd, NULL, &err) == FALSE)) {
2991                         WL_ERR(("NOT assoc: %d\n", err));
2992                         goto get_station_err;
2993                 }
2994                 if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
2995                         WL_ERR(("Wrong Mac address: "MACSTR" != "MACSTR"\n",
2996                                 MAC2STR(mac), MAC2STR(curmacp)));
2997                 }
2998
2999                 /* Report the current tx rate */
3000                 err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
3001                 if (err) {
3002                         WL_ERR(("Could not get rate (%d)\n", err));
3003                 } else {
3004                         rate = dtoh32(rate);
3005                         sinfo->filled |= STATION_INFO_TX_BITRATE;
3006                         sinfo->txrate.legacy = rate * 5;
3007                         WL_DBG(("Rate %d Mbps\n", (rate / 2)));
3008                 }
3009
3010                 memset(&scb_val, 0, sizeof(scb_val));
3011                 scb_val.val = 0;
3012                 err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,
3013                         sizeof(scb_val_t), false);
3014                 if (err) {
3015                         WL_ERR(("Could not get rssi (%d)\n", err));
3016                         goto get_station_err;
3017                 }
3018                 rssi = dtoh32(scb_val.val);
3019                 sinfo->filled |= STATION_INFO_SIGNAL;
3020                 sinfo->signal = rssi;
3021                 WL_DBG(("RSSI %d dBm\n", rssi));
3022
3023 get_station_err:
3024                 if (err && (err != -ETIMEDOUT) && (err != -EIO)) {
3025                         /* Disconnect due to zero BSSID or error to get RSSI */
3026                         WL_ERR(("force cfg80211_disconnected: %d\n", err));
3027                         wl_clr_drv_status(wl, CONNECTED, dev);
3028                         cfg80211_disconnected(dev, 0, NULL, 0, GFP_KERNEL);
3029                         wl_link_down(wl);
3030                 }
3031         }
3032
3033         return err;
3034 }
3035
3036 static s32
3037 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
3038         bool enabled, s32 timeout)
3039 {
3040         s32 pm;
3041         s32 err = 0;
3042         struct wl_priv *wl = wiphy_priv(wiphy);
3043
3044         CHECK_SYS_UP(wl);
3045
3046         WL_DBG(("Enter : power save %s\n", (enabled ? "enable" : "disable")));
3047         if (wl->p2p_net == dev) {
3048                 return err;
3049         }
3050
3051         pm = enabled ? PM_FAST : PM_OFF;
3052         pm = htod32(pm);
3053         err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true);
3054         if (unlikely(err)) {
3055                 if (err == -ENODEV)
3056                         WL_DBG(("net_device is not ready yet\n"));
3057                 else
3058                         WL_ERR(("error (%d)\n", err));
3059                 return err;
3060         }
3061         WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled")));
3062         return err;
3063 }
3064
3065 static __used u32 wl_find_msb(u16 bit16)
3066 {
3067         u32 ret = 0;
3068
3069         if (bit16 & 0xff00) {
3070                 ret += 8;
3071                 bit16 >>= 8;
3072         }
3073
3074         if (bit16 & 0xf0) {
3075                 ret += 4;
3076                 bit16 >>= 4;
3077         }
3078
3079         if (bit16 & 0xc) {
3080                 ret += 2;
3081                 bit16 >>= 2;
3082         }
3083
3084         if (bit16 & 2)
3085                 ret += bit16 & 2;
3086         else if (bit16)
3087                 ret += bit16;
3088
3089         return ret;
3090 }
3091
3092 static s32 wl_cfg80211_resume(struct wiphy *wiphy)
3093 {
3094         struct wl_priv *wl = wiphy_priv(wiphy);
3095         struct net_device *ndev = wl_to_prmry_ndev(wl);
3096         s32 err = 0;
3097
3098         if (unlikely(!wl_get_drv_status(wl, READY, ndev))) {
3099                 WL_INFO(("device is not ready\n"));
3100                 return 0;
3101         }
3102
3103         wl_invoke_iscan(wl);
3104
3105         return err;
3106 }
3107
3108 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)
3109 static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
3110 #else
3111 static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
3112 #endif
3113 {
3114 #ifdef DHD_CLEAR_ON_SUSPEND
3115         struct wl_priv *wl = wiphy_priv(wiphy);
3116         struct net_info *iter, *next;
3117         struct net_device *ndev = wl_to_prmry_ndev(wl);
3118         unsigned long flags;
3119
3120         if (unlikely(!wl_get_drv_status(wl, READY, ndev))) {
3121                 WL_INFO(("device is not ready : status (%d)\n",
3122                         (int)wl->status));
3123                 return 0;
3124         }
3125         for_each_ndev(wl, iter, next)
3126                 wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev);
3127         wl_term_iscan(wl);
3128         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
3129         if (wl->scan_request) {
3130                 cfg80211_scan_done(wl->scan_request, true);
3131                 wl->scan_request = NULL;
3132         }
3133         for_each_ndev(wl, iter, next) {
3134                 wl_clr_drv_status(wl, SCANNING, iter->ndev);
3135                 wl_clr_drv_status(wl, SCAN_ABORTING, iter->ndev);
3136         }
3137         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
3138         for_each_ndev(wl, iter, next) {
3139                 if (wl_get_drv_status(wl, CONNECTING, iter->ndev)) {
3140                         wl_bss_connect_done(wl, iter->ndev, NULL, NULL, false);
3141                 }
3142         }
3143 #endif /* DHD_CLEAR_ON_SUSPEND */
3144         return 0;
3145 }
3146
3147 static s32
3148 wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
3149         s32 err)
3150 {
3151         int i, j;
3152         struct wl_priv *wl = wlcfg_drv_priv;
3153         struct net_device *primary_dev = wl_to_prmry_ndev(wl);
3154
3155         if (!pmk_list) {
3156                 printk("pmk_list is NULL\n");
3157                 return -EINVAL;
3158         }
3159         /* pmk list is supported only for STA interface i.e. primary interface
3160          * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
3161          */
3162         if (primary_dev != dev) {
3163                 WL_INFO(("Not supporting Flushing pmklist on virtual"
3164                         " interfaces than primary interface\n"));
3165                 return err;
3166         }
3167
3168         WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
3169         for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
3170                 WL_DBG(("PMKID[%d]: %pM =\n", i,
3171                         &pmk_list->pmkids.pmkid[i].BSSID));
3172                 for (j = 0; j < WPA2_PMKID_LEN; j++) {
3173                         WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
3174                 }
3175         }
3176         if (likely(!err)) {
3177                 err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmk_list,
3178                         sizeof(*pmk_list), wl->ioctl_buf, WLC_IOCTL_MAXLEN, NULL);
3179         }
3180
3181         return err;
3182 }
3183
3184 static s32
3185 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
3186         struct cfg80211_pmksa *pmksa)
3187 {
3188         struct wl_priv *wl = wiphy_priv(wiphy);
3189         s32 err = 0;
3190         int i;
3191
3192         CHECK_SYS_UP(wl);
3193         for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
3194                 if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
3195                         ETHER_ADDR_LEN))
3196                         break;
3197         if (i < WL_NUM_PMKIDS_MAX) {
3198                 memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
3199                         ETHER_ADDR_LEN);
3200                 memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
3201                         WPA2_PMKID_LEN);
3202                 if (i == wl->pmk_list->pmkids.npmkid)
3203                         wl->pmk_list->pmkids.npmkid++;
3204         } else {
3205                 err = -EINVAL;
3206         }
3207         WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
3208                 &wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid - 1].BSSID));
3209         for (i = 0; i < WPA2_PMKID_LEN; i++) {
3210                 WL_DBG(("%02x\n",
3211                         wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid - 1].
3212                         PMKID[i]));
3213         }
3214
3215         err = wl_update_pmklist(dev, wl->pmk_list, err);
3216
3217         return err;
3218 }
3219
3220 static s32
3221 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
3222         struct cfg80211_pmksa *pmksa)
3223 {
3224         struct wl_priv *wl = wiphy_priv(wiphy);
3225         struct _pmkid_list pmkid;
3226         s32 err = 0;
3227         int i;
3228
3229         CHECK_SYS_UP(wl);
3230         memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
3231         memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
3232
3233         WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
3234                 &pmkid.pmkid[0].BSSID));
3235         for (i = 0; i < WPA2_PMKID_LEN; i++) {
3236                 WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
3237         }
3238
3239         for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
3240                 if (!memcmp
3241                     (pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
3242                      ETHER_ADDR_LEN))
3243                         break;
3244
3245         if ((wl->pmk_list->pmkids.npmkid > 0) &&
3246                 (i < wl->pmk_list->pmkids.npmkid)) {
3247                 memset(&wl->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
3248                 for (; i < (wl->pmk_list->pmkids.npmkid - 1); i++) {
3249                         memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID,
3250                                 &wl->pmk_list->pmkids.pmkid[i + 1].BSSID,
3251                                 ETHER_ADDR_LEN);
3252                         memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID,
3253                                 &wl->pmk_list->pmkids.pmkid[i + 1].PMKID,
3254                                 WPA2_PMKID_LEN);
3255                 }
3256                 wl->pmk_list->pmkids.npmkid--;
3257         } else {
3258                 err = -EINVAL;
3259         }
3260
3261         err = wl_update_pmklist(dev, wl->pmk_list, err);
3262
3263         return err;
3264
3265 }
3266
3267 static s32
3268 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
3269 {
3270         struct wl_priv *wl = wiphy_priv(wiphy);
3271         s32 err = 0;
3272         CHECK_SYS_UP(wl);
3273         memset(wl->pmk_list, 0, sizeof(*wl->pmk_list));
3274         err = wl_update_pmklist(dev, wl->pmk_list, err);
3275         return err;
3276
3277 }
3278
3279 static wl_scan_params_t *
3280 wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size)
3281 {
3282         wl_scan_params_t *params;
3283         int params_size;
3284         int num_chans;
3285
3286         *out_params_size = 0;
3287
3288         /* Our scan params only need space for 1 channel and 0 ssids */
3289         params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16);
3290         params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL);
3291         if (params == NULL) {
3292                 WL_ERR(("%s: mem alloc failed (%d bytes)\n", __func__, params_size));
3293                 return params;
3294         }
3295         memset(params, 0, params_size);
3296         params->nprobes = nprobes;
3297
3298         num_chans = (channel == 0) ? 0 : 1;
3299
3300         memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
3301         params->bss_type = DOT11_BSSTYPE_ANY;
3302         params->scan_type = DOT11_SCANTYPE_ACTIVE;
3303         params->nprobes = htod32(1);
3304         params->active_time = htod32(-1);
3305         params->passive_time = htod32(-1);
3306         params->home_time = htod32(10);
3307         params->channel_list[0] = htodchanspec(channel);
3308
3309         /* Our scan params have 1 channel and 0 ssids */
3310         params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
3311                 (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
3312
3313         *out_params_size = params_size; /* rtn size to the caller */
3314         return params;
3315 }
3316
3317 static s32
3318 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev,
3319         struct ieee80211_channel * channel,
3320         enum nl80211_channel_type channel_type,
3321         unsigned int duration, u64 *cookie)
3322 {
3323         s32 target_channel;
3324         u32 id;
3325         struct ether_addr primary_mac;
3326         struct net_device *ndev = NULL;
3327
3328         s32 err = BCME_OK;
3329         struct wl_priv *wl = wiphy_priv(wiphy);
3330         WL_DBG(("Enter, netdev_ifidx: %d \n", dev->ifindex));
3331
3332         if (wl->p2p_net == dev) {
3333                 ndev = wl_to_prmry_ndev(wl);
3334         } else {
3335                 ndev = dev;
3336         }
3337
3338         if (wl_get_drv_status(wl, SCANNING, ndev)) {
3339                 wl_notify_escan_complete(wl, ndev, true, true);
3340         }
3341         target_channel = ieee80211_frequency_to_channel(channel->center_freq);
3342         memcpy(&wl->remain_on_chan, channel, sizeof(struct ieee80211_channel));
3343         wl->remain_on_chan_type = channel_type;
3344         id = ++wl->last_roc_id;
3345         if (id == 0)
3346                 id = ++wl->last_roc_id;
3347         *cookie = id;
3348         cfg80211_ready_on_channel(dev, *cookie, channel,
3349                 channel_type, duration, GFP_KERNEL);
3350         if (wl->p2p && !wl->p2p->on) {
3351                 get_primary_mac(wl, &primary_mac);
3352                 wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr);
3353
3354                 /* In case of p2p_listen command, supplicant send remain_on_channel
3355                  * without turning on P2P
3356                  */
3357
3358                 p2p_on(wl) = true;
3359                 err = wl_cfgp2p_enable_discovery(wl, ndev, NULL, 0);
3360
3361                 if (unlikely(err)) {
3362                         goto exit;
3363                 }
3364         }
3365         if (p2p_is_on(wl))
3366                 wl_cfgp2p_discover_listen(wl, target_channel, duration);
3367
3368
3369 exit:
3370         return err;
3371 }
3372
3373 static s32
3374 wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct net_device *dev,
3375         u64 cookie)
3376 {
3377         s32 err = 0;
3378         WL_DBG((" enter ) netdev_ifidx: %d \n", dev->ifindex));
3379         return err;
3380 }
3381
3382 static s32
3383 wl_cfg80211_send_pending_tx_act_frm(struct wl_priv *wl)
3384 {
3385         wl_af_params_t *tx_act_frm;
3386         struct net_device *dev = wl->afx_hdl->dev;
3387         if (!p2p_is_on(wl))
3388                 return -1;
3389
3390         if (dev == wl->p2p_net) {
3391                 dev = wl_to_prmry_ndev(wl);
3392         }
3393
3394         tx_act_frm = wl->afx_hdl->pending_tx_act_frm;
3395         WL_DBG(("Sending the action frame\n"));
3396         wl->afx_hdl->pending_tx_act_frm = NULL;
3397         if (tx_act_frm != NULL) {
3398                 /* Suspend P2P discovery's search-listen to prevent it from
3399                  * starting a scan or changing the channel.
3400                  */
3401                 wl_clr_drv_status(wl, SENDING_ACT_FRM, wl->afx_hdl->dev);
3402                 wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
3403                 wl_notify_escan_complete(wl, dev, true, true);
3404                 wl_cfgp2p_discover_enable_search(wl, false);
3405                 tx_act_frm->channel = wl->afx_hdl->peer_chan;
3406                 wl->afx_hdl->ack_recv = (wl_cfgp2p_tx_action_frame(wl, dev,
3407                         tx_act_frm, wl->afx_hdl->bssidx)) ? false : true;
3408         }
3409         return 0;
3410 }
3411 static void
3412 wl_cfg80211_afx_handler(struct work_struct *work)
3413 {
3414
3415         struct afx_hdl *afx_instance;
3416         struct wl_priv *wl = wlcfg_drv_priv;
3417         afx_instance = container_of(work, struct afx_hdl, work);
3418         if (afx_instance != NULL) {
3419                 wl_cfgp2p_act_frm_search(wl, wl->afx_hdl->dev,
3420                         wl->afx_hdl->bssidx, 0);
3421         }
3422 }
3423
3424 static bool
3425 wl_cfg80211_send_at_common_channel(struct wl_priv *wl,
3426         struct net_device *dev,
3427         wl_af_params_t *af_params)
3428 {
3429         WL_DBG((" enter ) \n"));
3430         /* initialize afx_hdl */
3431         wl->afx_hdl->pending_tx_act_frm = af_params;
3432         wl->afx_hdl->bssidx = wl_cfgp2p_find_idx(wl, dev);
3433         wl->afx_hdl->dev = dev;
3434         wl->afx_hdl->retry = 0;
3435         wl->afx_hdl->peer_chan = WL_INVALID;
3436         wl->afx_hdl->ack_recv = false;
3437         memcpy(wl->afx_hdl->pending_tx_dst_addr.octet,
3438                 af_params->action_frame.da.octet,
3439                 sizeof(wl->afx_hdl->pending_tx_dst_addr.octet));
3440         /* Loop to wait until we have sent the pending tx action frame or the
3441          * pending action frame tx is cancelled.
3442          */
3443         while ((wl->afx_hdl->retry < WL_CHANNEL_SYNC_RETRY) &&
3444                 (wl->afx_hdl->peer_chan == WL_INVALID)) {
3445                 wl_set_drv_status(wl, SENDING_ACT_FRM, dev);
3446                 wl_set_drv_status(wl, SCANNING, dev);
3447                 WL_DBG(("Scheduling the action frame for sending.. retry %d\n",
3448                         wl->afx_hdl->retry));
3449                 /* Do find_peer_for_action */
3450                 schedule_work(&wl->afx_hdl->work);
3451                 wait_for_completion(&wl->act_frm_scan);
3452                 wl->afx_hdl->retry++;
3453         }
3454         if (wl->afx_hdl->peer_chan != WL_INVALID)
3455                 wl_cfg80211_send_pending_tx_act_frm(wl);
3456         else {
3457                 WL_ERR(("Couldn't find the peer " MACSTR " after %d retries\n",
3458                         MAC2STR(wl->afx_hdl->pending_tx_dst_addr.octet), wl->afx_hdl->retry));
3459         }
3460         wl->afx_hdl->dev = NULL;
3461         wl->afx_hdl->bssidx = WL_INVALID;
3462         wl_clr_drv_status(wl, SENDING_ACT_FRM, dev);
3463         if (wl->afx_hdl->ack_recv)
3464                 return true; /* ACK */
3465         else
3466                 return false; /* NO ACK */
3467 }
3468
3469 static s32
3470 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
3471         struct ieee80211_channel *channel, bool offchan,
3472         enum nl80211_channel_type channel_type,
3473         bool channel_type_valid, unsigned int wait,
3474         const u8* buf, size_t len,
3475 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
3476         bool no_cck,
3477 #endif
3478         u64 *cookie)
3479 {
3480         wl_action_frame_t *action_frame;
3481         wl_af_params_t *af_params;
3482         wifi_p2p_ie_t *p2p_ie;
3483         wpa_ie_fixed_t *wps_ie;
3484         scb_val_t scb_val;
3485         const struct ieee80211_mgmt *mgmt;
3486         struct wl_priv *wl = wiphy_priv(wiphy);
3487         struct net_device *dev = NULL;
3488         s32 err = BCME_OK;
3489         s32 bssidx = 0;
3490         u32 p2pie_len = 0;
3491         u32 wpsie_len = 0;
3492         u32 id;
3493         u32 retry = 0;
3494         bool ack = false;
3495         wifi_p2p_pub_act_frame_t *act_frm = NULL;
3496         wifi_p2p_action_frame_t *p2p_act_frm = NULL;
3497         wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
3498         s8 eabuf[ETHER_ADDR_STR_LEN];
3499         int retry_cnt = 0;
3500
3501         WL_DBG(("Enter \n"));
3502
3503         if (ndev == wl->p2p_net) {
3504                 dev = wl_to_prmry_ndev(wl);
3505         } else {
3506                 /* If TX req is for any valid ifidx. Use as is */
3507                 dev = ndev;
3508         }
3509
3510         /* find bssidx based on ndev */
3511         bssidx = wl_cfgp2p_find_idx(wl, dev);
3512         if (bssidx == -1) {
3513
3514                 WL_ERR(("Can not find the bssidx for dev( %p )\n", dev));
3515                 return -ENODEV;
3516         }
3517         if (p2p_is_on(wl)) {
3518                 /* Suspend P2P discovery search-listen to prevent it from changing the
3519                  * channel.
3520                  */
3521                 if ((err = wl_cfgp2p_discover_enable_search(wl, false)) < 0) {
3522                         WL_ERR(("Can not disable discovery mode\n"));
3523                         return -EFAULT;
3524                 }
3525         }
3526         *cookie = 0;
3527         id = wl->send_action_id++;
3528         if (id == 0)
3529                 id = wl->send_action_id++;
3530         *cookie = id;
3531         mgmt = (const struct ieee80211_mgmt *)buf;
3532         if (ieee80211_is_mgmt(mgmt->frame_control)) {
3533                 if (ieee80211_is_probe_resp(mgmt->frame_control)) {
3534                         s32 ie_offset =  DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
3535                         s32 ie_len = len - ie_offset;
3536                         if ((p2p_ie = wl_cfgp2p_find_p2pie((u8 *)(buf + ie_offset), ie_len))
3537                                 != NULL) {
3538                                 /* Total length of P2P Information Element */
3539                                 p2pie_len = p2p_ie->len + sizeof(p2p_ie->len) + sizeof(p2p_ie->id);
3540                         }
3541                         if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)(buf + ie_offset), ie_len))
3542                                 != NULL) {
3543                                 /* Order of Vendor IE is 1) WPS IE +
3544                                  * 2) P2P IE created by supplicant
3545                                  *  So, it is ok to find start address of WPS IE
3546                                  *  to save IEs
3547                                  */
3548                                 wpsie_len = wps_ie->length + sizeof(wps_ie->length) +
3549                                         sizeof(wps_ie->tag);
3550                                 wl_cfgp2p_set_management_ie(wl, dev, bssidx,
3551                                         VNDR_IE_PRBRSP_FLAG,
3552                                         (u8 *)wps_ie, wpsie_len + p2pie_len);
3553                         }
3554                         cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL);
3555                         goto exit;
3556                 } else if (ieee80211_is_disassoc(mgmt->frame_control) ||
3557                         ieee80211_is_deauth(mgmt->frame_control)) {
3558                         memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN);
3559                         scb_val.val = mgmt->u.disassoc.reason_code;
3560                         wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
3561                                 sizeof(scb_val_t), true);
3562                         WL_DBG(("Disconnect STA : %s scb_val.val %d\n",
3563                                 bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf),
3564                                 scb_val.val));
3565                         /* Wait for the deauth event to come, supplicant will do the
3566                          * delete iface immediately and we will have problem in sending
3567                          * deauth frame if we delete the bss in firmware
3568                          */
3569                         wl_delay(400);
3570                         cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL);
3571                         goto exit;
3572
3573                 } else if (ieee80211_is_action(mgmt->frame_control)) {
3574                         /* Abort the dwell time of any previous off-channel
3575                         * action frame that may be still in effect.  Sending
3576                         * off-channel action frames relies on the driver's
3577                         * scan engine.  If a previous off-channel action frame
3578                         * tx is still in progress (including the dwell time),
3579                         * then this new action frame will not be sent out.
3580                         */
3581                         wl_notify_escan_complete(wl, dev, true, true);
3582
3583                 }
3584
3585         } else {
3586                 WL_ERR(("Driver only allows MGMT packet type\n"));
3587                 goto exit;
3588         }
3589
3590         af_params = (wl_af_params_t *) kzalloc(WL_WIFI_AF_PARAMS_SIZE, GFP_KERNEL);
3591
3592         if (af_params == NULL)
3593         {
3594                 WL_ERR(("unable to allocate frame\n"));
3595                 return -ENOMEM;
3596         }
3597
3598         action_frame = &af_params->action_frame;
3599
3600         /* Add the packet Id */
3601         action_frame->packetId = *cookie;
3602         WL_DBG(("action frame %d\n", action_frame->packetId));
3603         /* Add BSSID */
3604         memcpy(&action_frame->da, &mgmt->da[0], ETHER_ADDR_LEN);
3605         memcpy(&af_params->BSSID, &mgmt->bssid[0], ETHER_ADDR_LEN);
3606
3607         /* Add the length exepted for 802.11 header  */
3608         action_frame->len = len - DOT11_MGMT_HDR_LEN;
3609         WL_DBG(("action_frame->len: %d\n", action_frame->len));
3610
3611         /* Add the channel */
3612         af_params->channel =
3613                 ieee80211_frequency_to_channel(channel->center_freq);
3614
3615         if (channel->band == IEEE80211_BAND_5GHZ) {
3616                 WL_DBG(("5GHz channel %d", af_params->channel));
3617                 err = wldev_ioctl(dev, WLC_SET_CHANNEL,
3618                         &af_params->channel, sizeof(af_params->channel), true);
3619                 if (err < 0) {
3620                         WL_ERR(("WLC_SET_CHANNEL error %d\n", err));
3621                 }
3622         }
3623
3624         /* Add the dwell time
3625          * Dwell time to stay off-channel to wait for a response action frame
3626          * after transmitting an GO Negotiation action frame
3627          */
3628         af_params->dwell_time = WL_DWELL_TIME;
3629
3630         memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len);
3631         if (wl_cfgp2p_is_pub_action(action_frame->data, action_frame->len)) {
3632                 act_frm = (wifi_p2p_pub_act_frame_t *) (action_frame->data);
3633                 WL_DBG(("P2P PUB action_frame->len: %d chan %d category %d subtype %d\n",
3634                         action_frame->len, af_params->channel,
3635                         act_frm->category, act_frm->subtype));
3636                 if (act_frm && ((act_frm->subtype == P2P_PAF_GON_REQ) ||
3637                   (act_frm->subtype == P2P_PAF_GON_RSP) ||
3638                   (act_frm->subtype == P2P_PAF_GON_CONF) ||
3639                   (act_frm->subtype == P2P_PAF_PROVDIS_REQ))) {
3640                         wldev_iovar_setint(dev, "mpc", 0);
3641                 }
3642
3643                 if (act_frm->subtype == P2P_PAF_GON_REQ) {
3644                         WL_DBG(("P2P: GO_NEG_PHASE status set \n"));
3645                         wl_set_p2p_status(wl, GO_NEG_PHASE);
3646                 } else if (act_frm->subtype == P2P_PAF_GON_CONF) {
3647                         /* If we reached till GO Neg confirmation
3648                          * reset the filter
3649                          */
3650                         WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
3651                         wl_clr_p2p_status(wl, GO_NEG_PHASE);
3652                 }
3653
3654                 if (act_frm->subtype == P2P_PAF_GON_RSP)
3655                         retry_cnt = 1;
3656                 else retry_cnt = WL_ACT_FRAME_RETRY;
3657
3658                 if (act_frm && act_frm->subtype == P2P_PAF_DEVDIS_REQ) {
3659                         af_params->dwell_time = WL_LONG_DWELL_TIME;
3660                 } else if (act_frm &&
3661                         (act_frm->subtype == P2P_PAF_PROVDIS_REQ ||
3662                         act_frm->subtype == P2P_PAF_PROVDIS_RSP ||
3663                         act_frm->subtype == P2P_PAF_GON_RSP)) {
3664                         af_params->dwell_time = WL_MED_DWELL_TIME;
3665                 }
3666         } else if (wl_cfgp2p_is_p2p_action(action_frame->data, action_frame->len)) {
3667                 p2p_act_frm = (wifi_p2p_action_frame_t *) (action_frame->data);
3668                 WL_DBG(("P2P action_frame->len: %d chan %d category %d subtype %d\n",
3669                         action_frame->len, af_params->channel,
3670                         p2p_act_frm->category, p2p_act_frm->subtype));
3671         } else if (wl_cfgp2p_is_gas_action(action_frame->data, action_frame->len)) {
3672                 sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *) (action_frame->data);
3673                 WL_DBG(("Service Discovery action_frame->len: %d chan %d category %d action %d\n",
3674                         action_frame->len, af_params->channel,
3675                         sd_act_frm->category, sd_act_frm->action));
3676                 af_params->dwell_time = WL_MED_DWELL_TIME;
3677                 retry_cnt = WL_ACT_FRAME_RETRY;
3678         }
3679         wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len);
3680         /*
3681          * To make sure to send successfully action frame, we have to turn off mpc
3682          */
3683         if (IS_P2P_SOCIAL(af_params->channel) &&
3684                 (IS_P2P_PUB_ACT_REQ(act_frm, &act_frm->elts[0], action_frame->len) ||
3685                 IS_GAS_REQ(sd_act_frm, action_frame->len)) &&
3686                 wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len) {
3687                 /* channel offload require P2P IE for Probe request
3688                  * otherwise, we will use wl_cfgp2p_tx_action_frame directly.
3689                  * channel offload for action request frame
3690                  */
3691
3692                 /* channel offload for action request frame */
3693                 ack = wl_cfg80211_send_at_common_channel(wl, dev, af_params);
3694                 /* We need to retry Service discovery frames as they don't get retried immediately by supplicant*/
3695                 if ((!ack) && (IS_GAS_REQ(sd_act_frm, action_frame->len))) {
3696                         for (retry = 1; retry < retry_cnt; retry++) {
3697                                 WL_DBG(("Service Discovery action_frame retry %d len: %d chan %d category %d action %d\n",
3698                                         retry, action_frame->len, af_params->channel,
3699                                         sd_act_frm->category, sd_act_frm->action));
3700                                 ack = (wl_cfgp2p_tx_action_frame(wl, dev,
3701                                         af_params, bssidx)) ? false : true;
3702                                 if (ack)
3703                                         break;
3704                         }
3705                 }
3706         } else {
3707                 ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? false : true;
3708                 if (!ack) {
3709                                 for (retry = 1; retry < retry_cnt; retry++) {
3710                                         ack = (wl_cfgp2p_tx_action_frame(wl, dev,
3711                                                 af_params, bssidx)) ? false : true;
3712                                         if (ack)
3713                                                 break;
3714                                 }
3715                 }
3716
3717         }
3718         cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, ack, GFP_KERNEL);
3719         if (act_frm && act_frm->subtype == P2P_PAF_GON_CONF) {
3720                 wldev_iovar_setint(dev, "mpc", 1);
3721         }
3722         kfree(af_params);
3723 exit:
3724         return err;
3725 }
3726
3727
3728 static void
3729 wl_cfg80211_mgmt_frame_register(struct wiphy *wiphy, struct net_device *dev,
3730         u16 frame_type, bool reg)
3731 {
3732
3733         WL_DBG(("%s: frame_type: %x, reg: %d\n", __func__, frame_type, reg));
3734
3735         if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
3736                 return;
3737
3738         return;
3739 }
3740
3741
3742 static s32
3743 wl_cfg80211_change_bss(struct wiphy *wiphy,
3744         struct net_device *dev,
3745         struct bss_parameters *params)
3746 {
3747         if (params->use_cts_prot >= 0) {
3748         }
3749
3750         if (params->use_short_preamble >= 0) {
3751         }
3752
3753         if (params->use_short_slot_time >= 0) {
3754         }
3755
3756         if (params->basic_rates) {
3757         }
3758
3759         if (params->ap_isolate >= 0) {
3760         }
3761
3762         if (params->ht_opmode >= 0) {
3763         }
3764
3765         return 0;
3766 }
3767
3768 static s32
3769 wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
3770         struct ieee80211_channel *chan,
3771         enum nl80211_channel_type channel_type)
3772 {
3773         s32 channel;
3774         s32 err = BCME_OK;
3775         struct wl_priv *wl = wiphy_priv(wiphy);
3776
3777         if (wl->p2p_net == dev) {
3778                 dev = wl_to_prmry_ndev(wl);
3779         }
3780         channel = ieee80211_frequency_to_channel(chan->center_freq);
3781
3782         if (wl_get_drv_status(wl, AP_CREATING, dev)) {
3783                 WL_TRACE(("<0> %s: as!!! in AP creating mode, save chan num:%d\n",
3784                         __FUNCTION__, channel));
3785                 wl->hostapd_chan = channel;
3786                 if (channel == 14)
3787                         return err; /* hostapd requested ch auto-select, will be done later */
3788         }
3789
3790         WL_DBG(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
3791                 dev->ifindex, channel_type, channel));
3792         err = wldev_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel), true);
3793         if (err < 0) {
3794                 WL_ERR(("WLC_SET_CHANNEL error %d chip may not be supporting this channel\n", err));
3795         }
3796         return err;
3797 }
3798
3799 static s32
3800 wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
3801 {
3802         s32 len = 0;
3803         s32 err = BCME_OK;
3804         u16 auth = WL_AUTH_OPEN_SYSTEM; /* d11 open authentication */
3805         u32 wsec;
3806         u32 pval = 0;
3807         u32 gval = 0;
3808         u32 wpa_auth = 0;
3809         u8* tmp;
3810         wpa_suite_mcast_t *mcast;
3811         wpa_suite_ucast_t *ucast;
3812         wpa_suite_auth_key_mgmt_t *mgmt;
3813         if (wpa2ie == NULL)
3814                 goto exit;
3815
3816         WL_DBG(("Enter \n"));
3817         len =  wpa2ie->len;
3818         /* check the mcast cipher */
3819         mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
3820         tmp = mcast->oui;
3821         switch (tmp[DOT11_OUI_LEN]) {
3822                 case WPA_CIPHER_NONE:
3823                         gval = 0;
3824                         break;
3825                 case WPA_CIPHER_WEP_40:
3826                 case WPA_CIPHER_WEP_104:
3827                         gval = WEP_ENABLED;
3828                         break;
3829                 case WPA_CIPHER_TKIP:
3830                         gval = TKIP_ENABLED;
3831                         break;
3832                 case WPA_CIPHER_AES_CCM:
3833                         gval = AES_ENABLED;
3834                         break;
3835                 default:
3836                         WL_ERR(("No Security Info\n"));
3837                         break;
3838         }
3839         len -= WPA_SUITE_LEN;
3840         /* check the unicast cipher */
3841         ucast = (wpa_suite_ucast_t *)&mcast[1];
3842         ltoh16_ua(&ucast->count);
3843         tmp = ucast->list[0].oui;
3844         switch (tmp[DOT11_OUI_LEN]) {
3845                 case WPA_CIPHER_NONE:
3846                         pval = 0;
3847                         break;
3848                 case WPA_CIPHER_WEP_40:
3849                 case WPA_CIPHER_WEP_104:
3850                         pval = WEP_ENABLED;
3851                         break;
3852                 case WPA_CIPHER_TKIP:
3853                         pval = TKIP_ENABLED;
3854                         break;
3855                 case WPA_CIPHER_AES_CCM:
3856                         pval = AES_ENABLED;
3857                         break;
3858                 default:
3859                         WL_ERR(("No Security Info\n"));
3860         }
3861         /* FOR WPS , set SEC_OW_ENABLED */
3862         wsec = (pval | gval | SES_OW_ENABLED);
3863         /* check the AKM */
3864         mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[1];
3865         ltoh16_ua(&mgmt->count);
3866         tmp = (u8 *)&mgmt->list[0];
3867         switch (tmp[DOT11_OUI_LEN]) {
3868                 case RSN_AKM_NONE:
3869                         wpa_auth = WPA_AUTH_NONE;
3870                         break;
3871                 case RSN_AKM_UNSPECIFIED:
3872                         wpa_auth = WPA2_AUTH_UNSPECIFIED;
3873                         break;
3874                 case RSN_AKM_PSK:
3875                         wpa_auth = WPA2_AUTH_PSK;
3876                         break;
3877                 default:
3878                         WL_ERR(("No Key Mgmt Info\n"));
3879         }
3880         /* set auth */
3881         err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
3882         if (err < 0) {
3883                 WL_ERR(("auth error %d\n", err));
3884                 return BCME_ERROR;
3885         }
3886         /* set wsec */
3887         err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
3888         if (err < 0) {
3889                 WL_ERR(("wsec error %d\n", err));
3890                 return BCME_ERROR;
3891         }
3892         /* set upper-layer auth */
3893         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
3894         if (err < 0) {
3895                 WL_ERR(("wpa_auth error %d\n", err));
3896                 return BCME_ERROR;
3897         }
3898 exit:
3899         return 0;
3900 }
3901
3902 static s32
3903 wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx)
3904 {
3905         wpa_suite_mcast_t *mcast;
3906         wpa_suite_ucast_t *ucast;
3907         wpa_suite_auth_key_mgmt_t *mgmt;
3908         u16 auth = WL_AUTH_OPEN_SYSTEM; /* d11 open authentication */
3909         u16 count;
3910         s32 err = BCME_OK;
3911         s32 len = 0;
3912         u32 i;
3913         u32 wsec;
3914         u32 pval = 0;
3915         u32 gval = 0;
3916         u32 wpa_auth = 0;
3917         u32 tmp = 0;
3918
3919         if (wpaie == NULL)
3920                 goto exit;
3921         WL_DBG(("Enter \n"));
3922         len = wpaie->length;    /* value length */
3923         len -= WPA_IE_TAG_FIXED_LEN;
3924         /* check for multicast cipher suite */
3925         if (len < WPA_SUITE_LEN) {
3926                 WL_INFO(("no multicast cipher suite\n"));
3927                 goto exit;
3928         }
3929
3930         /* pick up multicast cipher */
3931         mcast = (wpa_suite_mcast_t *)&wpaie[1];
3932         len -= WPA_SUITE_LEN;
3933         if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
3934                 if (IS_WPA_CIPHER(mcast->type)) {
3935                         tmp = 0;
3936                         switch (mcast->type) {
3937                                 case WPA_CIPHER_NONE:
3938                                         tmp = 0;
3939                                         break;
3940                                 case WPA_CIPHER_WEP_40:
3941                                 case WPA_CIPHER_WEP_104:
3942                                         tmp = WEP_ENABLED;
3943                                         break;
3944                                 case WPA_CIPHER_TKIP:
3945                                         tmp = TKIP_ENABLED;
3946                                         break;
3947                                 case WPA_CIPHER_AES_CCM:
3948                                         tmp = AES_ENABLED;
3949                                         break;
3950                                 default:
3951                                         WL_ERR(("No Security Info\n"));
3952                         }
3953                         gval |= tmp;
3954                 }
3955         }
3956         /* Check for unicast suite(s) */
3957         if (len < WPA_IE_SUITE_COUNT_LEN) {
3958                 WL_INFO(("no unicast suite\n"));
3959                 goto exit;
3960         }
3961         /* walk thru unicast cipher list and pick up what we recognize */
3962         ucast = (wpa_suite_ucast_t *)&mcast[1];
3963         count = ltoh16_ua(&ucast->count);
3964         len -= WPA_IE_SUITE_COUNT_LEN;
3965         for (i = 0; i < count && len >= WPA_SUITE_LEN;
3966                 i++, len -= WPA_SUITE_LEN) {
3967                 if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
3968                         if (IS_WPA_CIPHER(ucast->list[i].type)) {
3969                                 tmp = 0;
3970                                 switch (ucast->list[i].type) {
3971                                         case WPA_CIPHER_NONE:
3972                                                 tmp = 0;
3973                                                 break;
3974                                         case WPA_CIPHER_WEP_40:
3975                                         case WPA_CIPHER_WEP_104:
3976                                                 tmp = WEP_ENABLED;
3977                                                 break;
3978                                         case WPA_CIPHER_TKIP:
3979                                                 tmp = TKIP_ENABLED;
3980                                                 break;
3981                                         case WPA_CIPHER_AES_CCM:
3982                                                 tmp = AES_ENABLED;
3983                                                 break;
3984                                         default:
3985                                                 WL_ERR(("No Security Info\n"));
3986                                 }
3987                                 pval |= tmp;
3988                         }
3989                 }
3990         }
3991         len -= (count - i) * WPA_SUITE_LEN;
3992         /* Check for auth key management suite(s) */
3993         if (len < WPA_IE_SUITE_COUNT_LEN) {
3994                 WL_INFO((" no auth key mgmt suite\n"));
3995                 goto exit;
3996         }
3997         /* walk thru auth management suite list and pick up what we recognize */
3998         mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
3999         count = ltoh16_ua(&mgmt->count);
4000         len -= WPA_IE_SUITE_COUNT_LEN;
4001         for (i = 0; i < count && len >= WPA_SUITE_LEN;
4002                 i++, len -= WPA_SUITE_LEN) {
4003                 if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
4004                         if (IS_WPA_AKM(mgmt->list[i].type)) {
4005                                 tmp = 0;
4006                                 switch (mgmt->list[i].type) {
4007                                         case RSN_AKM_NONE:
4008                                                 tmp = WPA_AUTH_NONE;
4009                                                 break;
4010                                         case RSN_AKM_UNSPECIFIED:
4011                                                 tmp = WPA_AUTH_UNSPECIFIED;
4012                                                 break;
4013                                         case RSN_AKM_PSK:
4014                                                 tmp = WPA_AUTH_PSK;
4015                                                 break;
4016                                         default:
4017                                                 WL_ERR(("No Key Mgmt Info\n"));
4018                                 }
4019                                 wpa_auth |= tmp;
4020                         }
4021                 }
4022
4023         }
4024         /* FOR WPS , set SEC_OW_ENABLED */
4025         wsec = (pval | gval | SES_OW_ENABLED);
4026         /* set auth */
4027         err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
4028         if (err < 0) {
4029                 WL_ERR(("auth error %d\n", err));
4030                 return BCME_ERROR;
4031         }
4032         /* set wsec */
4033         err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
4034         if (err < 0) {
4035                 WL_ERR(("wsec error %d\n", err));
4036                 return BCME_ERROR;
4037         }
4038         /* set upper-layer auth */
4039         err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
4040         if (err < 0) {
4041                 WL_ERR(("wpa_auth error %d\n", err));
4042                 return BCME_ERROR;
4043         }
4044 exit:
4045         return 0;
4046 }
4047
4048 static s32
4049 wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
4050         struct beacon_parameters *info)
4051 {
4052         s32 err = BCME_OK;
4053         bcm_tlv_t *ssid_ie;
4054         wlc_ssid_t ssid;
4055         struct wl_priv *wl = wiphy_priv(wiphy);
4056         struct wl_join_params join_params;
4057         wpa_ie_fixed_t *wps_ie;
4058         wpa_ie_fixed_t *wpa_ie;
4059         bcm_tlv_t *wpa2_ie;
4060         wifi_p2p_ie_t *p2p_ie;
4061         bool is_bssup = false;
4062         bool update_bss = false;
4063         bool pbc = false;
4064         u16 wpsie_len = 0;
4065         u16 p2pie_len = 0;
4066         u8 beacon_ie[IE_MAX_LEN];
4067         s32 ie_offset = 0;
4068         s32 bssidx = 0;
4069         s32 infra = 1;
4070         s32 join_params_size = 0;
4071         s32 ap = 0;
4072         WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
4073                 info->interval, info->dtim_period, info->head_len, info->tail_len));
4074
4075         if (wl->p2p_net == dev) {
4076                 dev = wl_to_prmry_ndev(wl);
4077         }
4078
4079         bssidx = wl_cfgp2p_find_idx(wl, dev);
4080         if (p2p_is_on(wl) &&
4081                 (bssidx == wl_to_p2p_bss_bssidx(wl,
4082                 P2PAPI_BSSCFG_CONNECTION))) {
4083                 memset(beacon_ie, 0, sizeof(beacon_ie));
4084                 /* We don't need to set beacon for P2P_GO,
4085                  * but need to parse ssid from beacon_parameters
4086                  * because there is no way to set ssid
4087                  */
4088                 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
4089                 /* find the SSID */
4090                 if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
4091                         info->head_len - ie_offset,
4092                         DOT11_MNG_SSID_ID)) != NULL) {
4093                         memcpy(wl->p2p->ssid.SSID, ssid_ie->data, ssid_ie->len);
4094                         wl->p2p->ssid.SSID_len = ssid_ie->len;
4095                         WL_DBG(("SSID (%s) in Head \n", ssid_ie->data));
4096
4097                 } else {
4098                         WL_ERR(("No SSID in beacon \n"));
4099                 }
4100
4101                 /* find the WPSIE */
4102                 if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)info->tail, info->tail_len)) != NULL) {
4103                         wpsie_len = wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
4104                         /*
4105                          * Should be compared with saved ie before saving it
4106                          */
4107                         wl_validate_wps_ie((char *) wps_ie, &pbc);
4108                         memcpy(beacon_ie, wps_ie, wpsie_len);
4109                 } else {
4110                         WL_ERR(("No WPSIE in beacon \n"));
4111                 }
4112
4113
4114                 /* find the P2PIE */
4115                 if ((p2p_ie = wl_cfgp2p_find_p2pie((u8 *)info->tail, info->tail_len)) != NULL) {
4116                         /* Total length of P2P Information Element */
4117                         p2pie_len = p2p_ie->len + sizeof(p2p_ie->len) + sizeof(p2p_ie->id);
4118                         memcpy(&beacon_ie[wpsie_len], p2p_ie, p2pie_len);
4119
4120                 } else {
4121                         WL_ERR(("No P2PIE in beacon \n"));
4122                 }
4123                 /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */
4124                 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc);
4125                 wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG,
4126                         beacon_ie, wpsie_len + p2pie_len);
4127
4128                 /* find the RSN_IE */
4129                 if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len,
4130                         DOT11_MNG_RSN_ID)) != NULL) {
4131                         WL_DBG((" WPA2 IE is found\n"));
4132                 }
4133                 is_bssup = wl_cfgp2p_bss_isup(dev, bssidx);
4134
4135                 if (!is_bssup && (wpa2_ie != NULL)) {
4136                         wldev_iovar_setint(dev, "mpc", 0);
4137                         if ((err = wl_validate_wpa2ie(dev, wpa2_ie, bssidx)) < 0) {
4138                                 WL_ERR(("WPA2 IE parsing error"));
4139                                 goto exit;
4140                         }
4141                         err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
4142                         if (err < 0) {
4143                                 WL_ERR(("SET INFRA error %d\n", err));
4144                                 goto exit;
4145                         }
4146                         err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &wl->p2p->ssid,
4147                                 sizeof(wl->p2p->ssid), wl->ioctl_buf, WLC_IOCTL_MAXLEN,
4148                                 bssidx, &wl->ioctl_buf_sync);
4149                         if (err < 0) {
4150                                 WL_ERR(("GO SSID setting error %d\n", err));
4151                                 goto exit;
4152                         }
4153                         if ((err = wl_cfgp2p_bss(wl, dev, bssidx, 1)) < 0) {
4154                                 WL_ERR(("GO Bring up error %d\n", err));
4155                                 goto exit;
4156                         }
4157                 }
4158         } else if (wl_get_drv_status(wl, AP_CREATING, dev)) {
4159                 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
4160                 ap = 1;
4161                 /* find the SSID */
4162                 if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
4163                         info->head_len - ie_offset,
4164                         DOT11_MNG_SSID_ID)) != NULL) {
4165                         memset(&ssid, 0, sizeof(wlc_ssid_t));
4166                         memcpy(ssid.SSID, ssid_ie->data, ssid_ie->len);
4167                         WL_DBG(("SSID is (%s) in Head \n", ssid.SSID));
4168                         ssid.SSID_len = ssid_ie->len;
4169                         wldev_iovar_setint(dev, "mpc", 0);
4170                         wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), true);
4171                         wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
4172                         if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
4173                                 WL_ERR(("setting AP mode failed %d \n", err));
4174                                 return err;
4175                         }
4176
4177                         /* if requested, do softap ch autoselect  */
4178                         if (wl->hostapd_chan == 14) {
4179                                 int auto_chan;
4180                                 if ((err = wldev_get_auto_channel(dev, &auto_chan)) != 0) {
4181                                         WL_ERR(("softap: auto chan select failed,"
4182                                                 " will use ch 6\n"));
4183                                         auto_chan = 6;
4184                                 } else {
4185                                         printf("<0>softap: got auto ch:%d\n", auto_chan);
4186                                 }
4187                                 err = wldev_ioctl(dev, WLC_SET_CHANNEL,
4188                                         &auto_chan, sizeof(auto_chan), true);
4189                                 if (err < 0) {
4190                                         WL_ERR(("softap: WLC_SET_CHANNEL error %d chip"
4191                                                 " may not be supporting this channel\n", err));
4192                                         return err;
4193                                 }
4194                         }
4195
4196                         /* find the RSN_IE */
4197                         if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len,
4198                                 DOT11_MNG_RSN_ID)) != NULL) {
4199                                 WL_DBG((" WPA2 IE is found\n"));
4200                         }
4201                         /* find the WPA_IE */
4202                         if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)info->tail,
4203                         info->tail_len)) != NULL) {
4204                                 WL_DBG((" WPA IE is found\n"));
4205                         }
4206                         if ((wpa_ie != NULL || wpa2_ie != NULL)) {
4207                                 if (wl_validate_wpa2ie(dev, wpa2_ie, bssidx)  < 0 ||
4208                                         wl_validate_wpaie(dev, wpa_ie, bssidx) < 0) {
4209                                         wl->ap_info->security_mode = false;
4210                                         return BCME_ERROR;
4211                                 }
4212                                 wl->ap_info->security_mode = true;
4213                                 if (wl->ap_info->rsn_ie) {
4214                                         kfree(wl->ap_info->rsn_ie);
4215                                         wl->ap_info->rsn_ie = NULL;
4216                                 }
4217                                 if (wl->ap_info->wpa_ie) {
4218                                         kfree(wl->ap_info->wpa_ie);
4219                                         wl->ap_info->wpa_ie = NULL;
4220                                 }
4221                                 if (wl->ap_info->wps_ie) {
4222                                         kfree(wl->ap_info->wps_ie);
4223                                         wl->ap_info->wps_ie = NULL;
4224                                 }
4225                                 if (wpa_ie != NULL) {
4226                                         /* WPAIE */
4227                                         wl->ap_info->rsn_ie = NULL;
4228                                         wl->ap_info->wpa_ie = kmemdup(wpa_ie,
4229                                                 wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
4230                                                 GFP_KERNEL);
4231                                 } else {
4232                                         /* RSNIE */
4233                                         wl->ap_info->wpa_ie = NULL;
4234                                         wl->ap_info->rsn_ie = kmemdup(wpa2_ie,
4235                                                 wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
4236                                                 GFP_KERNEL);
4237                                 }
4238                         } else
4239                                 wl->ap_info->security_mode = false;
4240                         /* find the WPSIE */
4241                         if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)info->tail,
4242                                 info->tail_len)) != NULL) {
4243                                 wpsie_len = wps_ie->length +WPA_RSN_IE_TAG_FIXED_LEN;
4244                                 /*
4245                                 * Should be compared with saved ie before saving it
4246                                 */
4247                                 wl_validate_wps_ie((char *) wps_ie, &pbc);
4248                                 memcpy(beacon_ie, wps_ie, wpsie_len);
4249                                 wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG,
4250                                 beacon_ie, wpsie_len);
4251                                 wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL);
4252                                 /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */
4253                                 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc);
4254                         } else {
4255                                 WL_DBG(("No WPSIE in beacon \n"));
4256                         }
4257                         if (info->interval) {
4258                                 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
4259                                         &info->interval, sizeof(s32), true)) < 0) {
4260                                         WL_ERR(("Beacon Interval Set Error, %d\n", err));
4261                                         return err;
4262                                 }
4263                         }
4264                         if (info->dtim_period) {
4265                                 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
4266                                         &info->dtim_period, sizeof(s32), true)) < 0) {
4267                                         WL_ERR(("DTIM Interval Set Error, %d\n", err));
4268                                         return err;
4269                                 }
4270                         }
4271                         err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
4272                         if (unlikely(err)) {
4273                                 WL_ERR(("WLC_UP error (%d)\n", err));
4274                                 return err;
4275                         }
4276                         memset(&join_params, 0, sizeof(join_params));
4277                         /* join parameters starts with ssid */
4278                         join_params_size = sizeof(join_params.ssid);
4279                         memcpy(join_params.ssid.SSID, ssid.SSID, ssid.SSID_len);
4280                         join_params.ssid.SSID_len = htod32(ssid.SSID_len);
4281                         /* create softap */
4282                         if ((err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
4283                                 join_params_size, true)) == 0) {
4284                                 wl_clr_drv_status(wl, AP_CREATING, dev);
4285                                 wl_set_drv_status(wl, AP_CREATED, dev);
4286                         }
4287                 }
4288         } else if (wl_get_drv_status(wl, AP_CREATED, dev)) {
4289                 ap = 1;
4290                 /* find the WPSIE */
4291                 if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)info->tail, info->tail_len)) != NULL) {
4292                         wpsie_len = wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
4293                         /*
4294                          * Should be compared with saved ie before saving it
4295                          */
4296                         wl_validate_wps_ie((char *) wps_ie, &pbc);
4297                         memcpy(beacon_ie, wps_ie, wpsie_len);
4298                         wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG,
4299                         beacon_ie, wpsie_len);
4300                         if (wl->ap_info->wps_ie &&
4301                                 memcmp(wl->ap_info->wps_ie, wps_ie, wpsie_len)) {
4302                                 WL_DBG((" WPS IE is changed\n"));
4303                                 kfree(wl->ap_info->wps_ie);
4304                                 wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL);
4305                                 /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */
4306                                 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc);
4307                         } else if (wl->ap_info->wps_ie == NULL) {
4308                                 WL_DBG((" WPS IE is added\n"));
4309                                 wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL);
4310                                 /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */
4311                                 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc);
4312                         }
4313                         /* find the RSN_IE */
4314                         if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len,
4315                                 DOT11_MNG_RSN_ID)) != NULL) {
4316                                 WL_DBG((" WPA2 IE is found\n"));
4317                         }
4318                         /* find the WPA_IE */
4319                         if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)info->tail,
4320                                 info->tail_len)) != NULL) {
4321                                 WL_DBG((" WPA IE is found\n"));
4322                         }
4323                         if ((wpa_ie != NULL || wpa2_ie != NULL)) {
4324                                 if (!wl->ap_info->security_mode) {
4325                                         /* change from open mode to security mode */
4326                                         update_bss = true;
4327                                         if (wpa_ie != NULL) {
4328                                                 wl->ap_info->wpa_ie = kmemdup(wpa_ie,
4329                                                 wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
4330                                                 GFP_KERNEL);
4331                                         } else {
4332                                                 wl->ap_info->rsn_ie = kmemdup(wpa2_ie,
4333                                                 wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
4334                                                 GFP_KERNEL);
4335                                         }
4336                                 } else if (wl->ap_info->wpa_ie) {
4337                                         /* change from WPA mode to WPA2 mode */
4338                                         if (wpa2_ie != NULL) {
4339                                                 update_bss = true;
4340                                                 kfree(wl->ap_info->wpa_ie);
4341                                                 wl->ap_info->rsn_ie = kmemdup(wpa2_ie,
4342                                                 wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
4343                                                 GFP_KERNEL);
4344                                                 wl->ap_info->wpa_ie = NULL;
4345                                         }
4346                                         else if (memcmp(wl->ap_info->wpa_ie,
4347                                                 wpa_ie, wpa_ie->length +
4348                                                 WPA_RSN_IE_TAG_FIXED_LEN)) {
4349                                                 kfree(wl->ap_info->wpa_ie);
4350                                                 update_bss = true;
4351                                                 wl->ap_info->wpa_ie = kmemdup(wpa_ie,
4352                                                 wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
4353                                                 GFP_KERNEL);
4354                                                 wl->ap_info->rsn_ie = NULL;
4355                                         }
4356                                 } else {
4357                                         /* change from WPA2 mode to WPA mode */
4358                                         if (wpa_ie != NULL) {
4359                                                 update_bss = true;
4360                                                 kfree(wl->ap_info->rsn_ie);
4361                                                 wl->ap_info->rsn_ie = NULL;
4362                                                 wl->ap_info->wpa_ie = kmemdup(wpa_ie,
4363                                                 wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
4364                                                 GFP_KERNEL);
4365                                         } else if (memcmp(wl->ap_info->rsn_ie,
4366                                                 wpa2_ie, wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN)) {
4367                                                 update_bss = true;
4368                                                 kfree(wl->ap_info->rsn_ie);
4369                                                 wl->ap_info->rsn_ie = kmemdup(wpa2_ie,
4370                                                 wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
4371                                                 GFP_KERNEL);
4372                                                 wl->ap_info->wpa_ie = NULL;
4373                                         }
4374                                 }
4375                                 if (update_bss) {
4376                                         wl->ap_info->security_mode = true;
4377                                         wl_cfgp2p_bss(wl, dev, bssidx, 0);
4378                                         if (wl_validate_wpa2ie(dev, wpa2_ie, bssidx)  < 0 ||
4379                                                 wl_validate_wpaie(dev, wpa_ie, bssidx) < 0) {
4380                                                 return BCME_ERROR;
4381                                         }
4382                                         wl_cfgp2p_bss(wl, dev, bssidx, 1);
4383                                 }
4384                         }
4385                 } else {
4386                         WL_ERR(("No WPSIE in beacon \n"));
4387                 }
4388         }
4389 exit:
4390         if (err)
4391                 wldev_iovar_setint(dev, "mpc", 1);
4392         return err;
4393 }
4394
4395 #ifdef WL_SCHED_SCAN
4396 #define PNO_TIME        30
4397 #define PNO_REPEAT      4
4398 #define PNO_FREQ_EXPO_MAX       2
4399 int wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
4400                              struct net_device *dev,
4401                              struct cfg80211_sched_scan_request *request)
4402 {
4403         ushort pno_time = PNO_TIME;
4404         int pno_repeat = PNO_REPEAT;
4405         int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
4406         wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
4407         struct wl_priv *wl = wiphy_priv(wiphy);
4408         struct cfg80211_ssid *ssid = NULL;
4409         int ssid_count = 0;
4410         int i;
4411         int ret = 0;
4412
4413         WL_DBG(("Enter n_match_sets:%d   n_ssids:%d \n",
4414                 request->n_match_sets, request->n_ssids));
4415         WL_DBG(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
4416                 request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max));
4417
4418 #if defined(WL_ENABLE_P2P_IF)
4419         /* While GO is operational, PNO is not supported */
4420         if (dhd_cfg80211_get_opmode(wl) & P2P_GO_ENABLED) {
4421                 WL_DBG(("PNO not enabled! op_mode: P2P GO"));
4422                 return -1;
4423         }
4424 #endif
4425
4426         if (!request || !request->n_ssids || !request->n_match_sets) {
4427                 WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids));
4428                 return -EINVAL;
4429         }
4430
4431         memset(&ssids_local, 0, sizeof(ssids_local));
4432
4433         if (request->n_match_sets > 0) {
4434                 for (i = 0; i < request->n_match_sets; i++) {
4435                         ssid = &request->match_sets[i].ssid;
4436                         memcpy(ssids_local[i].SSID, ssid->ssid, ssid->ssid_len);
4437                         ssids_local[i].SSID_len = ssid->ssid_len;
4438                         WL_DBG((">>> PNO filter set for ssid (%s) \n", ssid->ssid));
4439                         ssid_count++;
4440                 }
4441         }
4442
4443         if (request->n_ssids > 0) {
4444                 for (i = 0; i < request->n_ssids; i++) {
4445                         /* Active scan req for ssids */
4446                         WL_DBG((">>> Active scan req for ssid (%s) \n", request->ssids[i].ssid));
4447
4448                         /* match_set ssids is a supert set of n_ssid list, so we need
4449                          * not add these set seperately
4450                          */
4451                 }
4452         }
4453
4454         if (ssid_count) {
4455                 if ((ret = dhd_dev_pno_set(dev, ssids_local, request->n_match_sets,
4456                         pno_time, pno_repeat, pno_freq_expo_max)) < 0) {
4457                         WL_ERR(("PNO setup failed!! ret=%d \n", ret));
4458                         return -EINVAL;
4459                 }
4460
4461                 /* Enable the PNO */
4462                 if (dhd_dev_pno_enable(dev, 1) < 0) {
4463                         WL_ERR(("PNO enable failed!! ret=%d \n", ret));
4464                         return -EINVAL;
4465                 }
4466                 wl->sched_scan_req = request;
4467         } else {
4468                 return -EINVAL;
4469         }
4470
4471         return 0;
4472 }
4473
4474 int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
4475 {
4476         struct wl_priv *wl = wiphy_priv(wiphy);
4477
4478         WL_DBG(("Enter \n"));
4479
4480         if (dhd_dev_pno_enable(dev, 0) < 0)
4481                 WL_ERR(("PNO disable failed"));
4482
4483         if (dhd_dev_pno_reset(dev) < 0)
4484                 WL_ERR(("PNO reset failed"));
4485
4486         if (wl->scan_request && wl->sched_scan_running) {
4487                 wl_notify_escan_complete(wl, dev, true, true);
4488         }
4489
4490          wl->sched_scan_req = NULL;
4491          wl->sched_scan_running = FALSE;
4492
4493         return 0;
4494 }
4495 #endif /* WL_SCHED_SCAN */
4496
4497 static struct cfg80211_ops wl_cfg80211_ops = {
4498         .add_virtual_intf = wl_cfg80211_add_virtual_iface,
4499         .del_virtual_intf = wl_cfg80211_del_virtual_iface,
4500         .change_virtual_intf = wl_cfg80211_change_virtual_iface,
4501         .scan = wl_cfg80211_scan,
4502         .set_wiphy_params = wl_cfg80211_set_wiphy_params,
4503         .join_ibss = wl_cfg80211_join_ibss,
4504         .leave_ibss = wl_cfg80211_leave_ibss,
4505         .get_station = wl_cfg80211_get_station,
4506         .set_tx_power = wl_cfg80211_set_tx_power,
4507         .get_tx_power = wl_cfg80211_get_tx_power,
4508         .add_key = wl_cfg80211_add_key,
4509         .del_key = wl_cfg80211_del_key,
4510         .get_key = wl_cfg80211_get_key,
4511         .set_default_key = wl_cfg80211_config_default_key,
4512         .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
4513         .set_power_mgmt = wl_cfg80211_set_power_mgmt,
4514         .connect = wl_cfg80211_connect,
4515         .disconnect = wl_cfg80211_disconnect,
4516         .suspend = wl_cfg80211_suspend,
4517         .resume = wl_cfg80211_resume,
4518         .set_pmksa = wl_cfg80211_set_pmksa,
4519         .del_pmksa = wl_cfg80211_del_pmksa,
4520         .flush_pmksa = wl_cfg80211_flush_pmksa,
4521         .remain_on_channel = wl_cfg80211_remain_on_channel,
4522         .cancel_remain_on_channel = wl_cfg80211_cancel_remain_on_channel,
4523         .mgmt_tx = wl_cfg80211_mgmt_tx,
4524         .mgmt_frame_register = wl_cfg80211_mgmt_frame_register,
4525         .change_bss = wl_cfg80211_change_bss,
4526         .set_channel = wl_cfg80211_set_channel,
4527         .set_beacon = wl_cfg80211_add_set_beacon,
4528         .add_beacon = wl_cfg80211_add_set_beacon,
4529 #ifdef WL_SCHED_SCAN
4530         .sched_scan_start = wl_cfg80211_sched_scan_start,
4531         .sched_scan_stop = wl_cfg80211_sched_scan_stop,
4532 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */
4533 };
4534
4535 s32 wl_mode_to_nl80211_iftype(s32 mode)
4536 {
4537         s32 err = 0;
4538
4539         switch (mode) {
4540         case WL_MODE_BSS:
4541                 return NL80211_IFTYPE_STATION;
4542         case WL_MODE_IBSS:
4543                 return NL80211_IFTYPE_ADHOC;
4544         case WL_MODE_AP:
4545                 return NL80211_IFTYPE_AP;
4546         default:
4547                 return NL80211_IFTYPE_UNSPECIFIED;
4548         }
4549
4550         return err;
4551 }
4552
4553 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev)
4554 {
4555         s32 err = 0;
4556         wdev->wiphy =
4557             wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_priv));
4558         if (unlikely(!wdev->wiphy)) {
4559                 WL_ERR(("Couldn not allocate wiphy device\n"));
4560                 err = -ENOMEM;
4561                 return err;
4562         }
4563         set_wiphy_dev(wdev->wiphy, sdiofunc_dev);
4564         wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX;
4565         /* Report  how many SSIDs Driver can support per Scan request */
4566         wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX;
4567         wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
4568 #ifdef WL_SCHED_SCAN
4569         wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT;
4570         wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT;
4571         wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX;
4572         wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
4573 #endif /* WL_SCHED_SCAN */
4574         wdev->wiphy->interface_modes =
4575                 BIT(NL80211_IFTYPE_STATION)
4576                 | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR);
4577
4578         wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
4579         /* wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; - set in runtime */
4580         wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
4581         wdev->wiphy->cipher_suites = __wl_cipher_suites;
4582         wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
4583         wdev->wiphy->max_remain_on_channel_duration = 5000;
4584         wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes;
4585 #ifndef WL_POWERSAVE_DISABLED
4586         wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
4587 #else
4588         wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
4589 #endif                          /* !WL_POWERSAVE_DISABLED */
4590         wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK |
4591                 WIPHY_FLAG_4ADDR_AP |
4592 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)
4593                 WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS |
4594 #endif
4595                 WIPHY_FLAG_4ADDR_STATION;
4596 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
4597         wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
4598 #endif
4599         WL_DBG(("Registering custom regulatory)\n"));
4600         wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
4601         wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom);
4602         /* Now we can register wiphy with cfg80211 module */
4603         err = wiphy_register(wdev->wiphy);
4604         if (unlikely(err < 0)) {
4605                 WL_ERR(("Couldn not register wiphy device (%d)\n", err));
4606                 wiphy_free(wdev->wiphy);
4607         }
4608         return err;
4609 }
4610
4611 static void wl_free_wdev(struct wl_priv *wl)
4612 {
4613         struct wireless_dev *wdev = wl->wdev;
4614         struct wiphy *wiphy;
4615         if (!wdev) {
4616                 WL_ERR(("wdev is invalid\n"));
4617                 return;
4618         }
4619         wiphy = wdev->wiphy;
4620         wiphy_unregister(wdev->wiphy);
4621         wdev->wiphy->dev.parent = NULL;
4622
4623         wl_delete_all_netinfo(wl);
4624         wiphy_free(wiphy);
4625         /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "wl",
4626          * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
4627          */
4628 }
4629
4630 static s32 wl_inform_bss(struct wl_priv *wl)
4631 {
4632         struct wl_scan_results *bss_list;
4633         struct wl_bss_info *bi = NULL;  /* must be initialized */
4634         s32 err = 0;
4635         s32 i;
4636
4637         bss_list = wl->bss_list;
4638         WL_DBG(("scanned AP count (%d)\n", bss_list->count));
4639         bi = next_bss(bss_list, bi);
4640         for_each_bss(bss_list, bi, i) {
4641                 err = wl_inform_single_bss(wl, bi);
4642                 if (unlikely(err))
4643                         break;
4644         }
4645         return err;
4646 }
4647
4648 static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
4649 {
4650         struct wiphy *wiphy = wiphy_from_scan(wl);
4651         struct ieee80211_mgmt *mgmt;
4652         struct ieee80211_channel *channel;
4653         struct ieee80211_supported_band *band;
4654         struct wl_cfg80211_bss_info *notif_bss_info;
4655         struct wl_scan_req *sr = wl_to_sr(wl);
4656         struct beacon_proberesp *beacon_proberesp;
4657         struct cfg80211_bss *cbss = NULL;
4658         s32 mgmt_type;
4659         s32 signal;
4660         u32 freq;
4661         s32 err = 0;
4662
4663         if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
4664                 WL_DBG(("Beacon is larger than buffer. Discarding\n"));
4665                 return err;
4666         }
4667         notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt)
4668                 - sizeof(u8) + WL_BSS_INFO_MAX, GFP_KERNEL);
4669         if (unlikely(!notif_bss_info)) {
4670                 WL_ERR(("notif_bss_info alloc failed\n"));
4671                 return -ENOMEM;
4672         }
4673         mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
4674         notif_bss_info->channel =
4675                 bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(bi->chanspec);
4676
4677         if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
4678                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
4679         else
4680                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
4681         if (!band) {
4682                 WL_ERR(("No valid band"));
4683                 kfree(notif_bss_info);
4684                 return -EINVAL;
4685         }
4686         notif_bss_info->rssi = dtoh16(bi->RSSI);
4687         memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
4688         mgmt_type = wl->active_scan ?
4689                 IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
4690         if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
4691             mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
4692         }
4693         beacon_proberesp = wl->active_scan ?
4694                 (struct beacon_proberesp *)&mgmt->u.probe_resp :
4695                 (struct beacon_proberesp *)&mgmt->u.beacon;
4696         beacon_proberesp->timestamp = 0;
4697         beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
4698         beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
4699         wl_rst_ie(wl);
4700
4701         wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
4702         wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX -
4703                 offsetof(struct wl_cfg80211_bss_info, frame_buf));
4704         notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
4705                 u.beacon.variable) + wl_get_ielen(wl);
4706 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
4707         freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
4708 #else
4709         freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band);
4710 #endif
4711         channel = ieee80211_get_channel(wiphy, freq);
4712         if (!channel) {
4713                 WL_ERR(("No valid channel"));
4714                 kfree(notif_bss_info);
4715                 return -EINVAL;
4716         }
4717
4718         WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM "
4719                         "mgmt_type %d frame_len %d\n", bi->SSID,
4720                         notif_bss_info->rssi, notif_bss_info->channel,
4721                         mgmt->u.beacon.capab_info, &bi->BSSID, mgmt_type,
4722                         notif_bss_info->frame_len));
4723
4724         signal = notif_bss_info->rssi * 100;
4725
4726 #if defined(WLP2P) && defined(WL_ENABLE_P2P_IF)
4727         if (wl->p2p && wl->p2p_net && wl->scan_request &&
4728                 ((wl->scan_request->dev == wl->p2p_net) ||
4729                 (wl->scan_request->dev == wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION)))){
4730 #else
4731         if (p2p_is_on(wl) && ( p2p_scan(wl) ||
4732                 (wl->scan_request->dev == wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION)))) {
4733 #endif
4734                 /* find the P2PIE, if we do not find it, we will discard this frame */
4735                 wifi_p2p_ie_t * p2p_ie;
4736                 if ((p2p_ie = wl_cfgp2p_find_p2pie((u8 *)beacon_proberesp->variable,
4737                         wl_get_ielen(wl))) == NULL) {
4738                         WL_ERR(("Couldn't find P2PIE in probe response/beacon\n"));
4739                         kfree(notif_bss_info);
4740                         return err;
4741                 }
4742                 else if( wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_DEV_INFO) == NULL)
4743                 {
4744                         WL_DBG(("Couldn't find P2P_SEID_DEV_INFO in probe response/beacon\n"));
4745                         kfree(notif_bss_info);
4746                         return err;
4747                 }
4748         }
4749         if (!mgmt->u.probe_resp.timestamp) {
4750                 struct timeval tv;
4751
4752                 do_gettimeofday(&tv);
4753                 mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec * 1000000)
4754                                                 + tv.tv_usec;
4755         }
4756
4757         cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
4758                 le16_to_cpu(notif_bss_info->frame_len), signal, GFP_KERNEL);
4759         if (unlikely(!cbss)) {
4760                 WL_ERR(("cfg80211_inform_bss_frame error\n"));
4761                 kfree(notif_bss_info);
4762                 return -EINVAL;
4763         }
4764
4765         cfg80211_put_bss(cbss);
4766         kfree(notif_bss_info);
4767
4768         return err;
4769 }
4770
4771 static s32 wl_inform_ibss(struct wl_priv *wl, const u8 *bssid)
4772 {
4773         struct net_device *ndev = wl_to_prmry_ndev(wl);
4774         struct wiphy *wiphy = wl_to_wiphy(wl);
4775         struct wl_bss_info *bi = NULL;
4776         struct ieee80211_channel *notify_channel;
4777         struct ieee80211_supported_band *band;
4778         struct cfg80211_bss *bss;
4779         s32 err = 0;
4780         u16 channel;
4781         u32 freq;
4782         u32 wsec = 0;
4783         u16 notify_capability;
4784         u16 notify_interval;
4785         u8 *notify_ie;
4786         size_t notify_ielen;
4787         s32 notify_signal;
4788
4789         WL_TRACE(("Enter\n"));
4790
4791         if (wl->scan_request) {
4792                 wl_notify_escan_complete(wl, ndev, true, true);
4793         }
4794
4795         mutex_lock(&wl->usr_sync);
4796
4797         *(u32 *)wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
4798         err = wldev_ioctl(ndev, WLC_GET_BSS_INFO, wl->extra_buf,
4799                                         WL_EXTRA_BUF_MAX, false);
4800         if (err) {
4801                 WL_ERR(("Failed to get bss info for IBSS\n"));
4802                 err = -EIO;
4803                 goto CleanUp;
4804         }
4805         bi = (struct wl_bss_info *)(wl->extra_buf + 4);
4806
4807         if (memcmp(bssid, &bi->BSSID, ETHER_ADDR_LEN)) {
4808                 WL_ERR(("BSSID mismatch: Inform %02x:%02x:%02x:%02x:%02x:%02x,"
4809                                         "%02x:%02x:%02x:%02x:%02x:%02x\n",
4810                                         bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5],
4811                                         bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2],
4812                                         bi->BSSID.octet[3], bi->BSSID.octet[4],
4813                                         bi->BSSID.octet[5]));
4814                 err = -EINVAL;
4815                 goto CleanUp;
4816         }
4817
4818         err = wldev_iovar_getint(ndev, "wsec", &wsec);
4819         if (err) {
4820                 WL_ERR(("wsec failed: %d\n", err));
4821                 err = -EIO;
4822                 goto CleanUp;
4823         }
4824
4825         channel = bi->ctl_ch ? bi->ctl_ch :
4826                                 CHSPEC_CHANNEL(dtohchanspec(bi->chanspec));
4827         if (channel <= CH_MAX_2G_CHANNEL)
4828                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
4829         else
4830                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
4831
4832 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
4833         freq = ieee80211_channel_to_frequency(channel);
4834         (void)band->band;
4835 #else
4836         freq = ieee80211_channel_to_frequency(channel, band->band);
4837 #endif
4838         notify_channel = ieee80211_get_channel(wiphy, freq);
4839
4840         notify_capability = dtoh16(bi->capability);
4841         notify_interval = dtoh16(bi->beacon_period);
4842         notify_ie = (u8 *)bi + dtoh16(bi->ie_offset);
4843         notify_ielen = dtoh32(bi->ie_length);
4844         notify_signal = (int16)dtoh16(bi->RSSI) * 100;
4845
4846         if (wl->p2p_supported) {
4847                 notify_capability |= DOT11_CAP_IBSS;
4848                 if (wsec)
4849                         notify_capability |= DOT11_CAP_PRIVACY;
4850         }
4851
4852         WL_DBG(("BSSID %02x:%02x:%02x:%02x:%02x:%02x",
4853                         bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]));
4854         WL_INFO(("channel: %d(%d)\n", channel, freq));
4855         WL_INFO(("capability: %X\n", notify_capability));
4856         WL_INFO(("beacon interval: %d ms\n", notify_interval));
4857         WL_INFO(("signal: %d dBm\n", notify_signal));
4858         WL_INFO(("ie_len: %d\n", notify_ielen));
4859         bss = cfg80211_inform_bss(wiphy, notify_channel, bssid, 0,
4860                                 notify_capability, notify_interval,
4861                                 notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
4862         if (!bss) {
4863                 WL_ERR(("cfg80211_inform_bss() Failed\n"));
4864                 err = -ENOMEM;
4865                 goto CleanUp;
4866         }
4867
4868         cfg80211_put_bss(bss);
4869         err = 0;
4870
4871 CleanUp:
4872
4873         mutex_unlock(&wl->usr_sync);
4874
4875         WL_TRACE(("Exit\n"));
4876         return err;
4877 }
4878
4879 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev)
4880 {
4881         u32 event = ntoh32(e->event_type);
4882         u32 status =  ntoh32(e->status);
4883         u16 flags = ntoh16(e->flags);
4884
4885         WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
4886         if (event == WLC_E_SET_SSID) {
4887                 if (status == WLC_E_STATUS_SUCCESS) {
4888                         return true;
4889                 }
4890         } else if (event == WLC_E_LINK) {
4891                 if (flags & WLC_EVENT_MSG_LINK)
4892                         if (!wl_is_ibssmode(wl, ndev))
4893                                 return true;
4894         }
4895
4896         WL_DBG(("wl_is_linkup false\n"));
4897         return false;
4898 }
4899
4900 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
4901 {
4902         u32 event = ntoh32(e->event_type);
4903         u16 flags = ntoh16(e->flags);
4904
4905         if (event == WLC_E_DEAUTH_IND ||
4906         event == WLC_E_DISASSOC_IND ||
4907         event == WLC_E_DISASSOC ||
4908         event == WLC_E_DEAUTH) {
4909                 return true;
4910         } else if (event == WLC_E_LINK) {
4911                 if (!(flags & WLC_EVENT_MSG_LINK))
4912                         return true;
4913         }
4914
4915         return false;
4916 }
4917
4918 static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e)
4919 {
4920         u32 event = ntoh32(e->event_type);
4921         u32 status = ntoh32(e->status);
4922
4923         if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS)
4924                 return true;
4925         if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS)
4926                 return true;
4927
4928         return false;
4929 }
4930
4931 /* The mainline kernel >= 3.2.0 has support for indicating new/del station
4932  * to AP/P2P GO via events. If this change is backported to kernel for which
4933  * this driver is being built, then define WL_CFG80211_STA_EVENT. You
4934  * should use this new/del sta event mechanism for BRCM supplicant >= 22.
4935  */
4936 static s32
4937 wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev,
4938         const wl_event_msg_t *e, void *data)
4939 {
4940         s32 err = 0;
4941         u32 event = ntoh32(e->event_type);
4942         u32 reason = ntoh32(e->reason);
4943         u32 len = ntoh32(e->datalen);
4944
4945 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
4946         bool isfree = false;
4947         u8 *mgmt_frame;
4948         u8 bsscfgidx = e->bsscfgidx;
4949         s32 freq;
4950         s32 channel;
4951         u8 body[WL_FRAME_LEN];
4952         u16 fc = 0;
4953         struct ieee80211_supported_band *band;
4954         struct ether_addr da;
4955         struct ether_addr bssid;
4956         struct wiphy *wiphy = wl_to_wiphy(wl);
4957         channel_info_t ci;
4958 #else
4959         struct station_info sinfo;
4960 #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !WL_CFG80211_STA_EVENT */
4961
4962
4963 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
4964         memset(body, 0, sizeof(body));
4965         memset(&bssid, 0, ETHER_ADDR_LEN);
4966         WL_DBG(("Enter event %d ndev %p\n", event, ndev));
4967         if (wl_get_mode_by_netdev(wl, ndev) == WL_INVALID)
4968                 return WL_INVALID;
4969
4970         if (len > WL_FRAME_LEN) {
4971                 WL_ERR(("Received frame length %d from dongle is greater than"
4972                         " allocated body buffer len %d", len, WL_FRAME_LEN));
4973                 goto exit;
4974         }
4975         memcpy(body, data, len);
4976         wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
4977                 NULL, 0, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bsscfgidx, &wl->ioctl_buf_sync);
4978         memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN);
4979         err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
4980         switch (event) {
4981                 case WLC_E_ASSOC_IND:
4982                         fc = FC_ASSOC_REQ;
4983                         break;
4984                 case WLC_E_REASSOC_IND:
4985                         fc = FC_REASSOC_REQ;
4986                         break;
4987                 case WLC_E_DISASSOC_IND:
4988                         fc = FC_DISASSOC;
4989                         break;
4990                 case WLC_E_DEAUTH_IND:
4991                         fc = FC_DISASSOC;
4992                         break;
4993                 case WLC_E_DEAUTH:
4994                         fc = FC_DISASSOC;
4995                         break;
4996                 default:
4997                         fc = 0;
4998                         goto exit;
4999         }
5000         if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false)))
5001                 return err;
5002
5003         channel = dtoh32(ci.hw_channel);
5004         if (channel <= CH_MAX_2G_CHANNEL)
5005                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
5006         else
5007                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
5008         if (!band) {
5009                 WL_ERR(("No valid band"));
5010                 return -EINVAL;
5011         }
5012 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
5013         freq = ieee80211_channel_to_frequency(channel);
5014 #else
5015         freq = ieee80211_channel_to_frequency(channel, band->band);
5016 #endif
5017
5018         err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
5019                 &mgmt_frame, &len, body);
5020         if (err < 0)
5021                 goto exit;
5022         isfree = true;
5023
5024         if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) {
5025                 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
5026         } else if (event == WLC_E_DISASSOC_IND) {
5027                 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
5028         } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
5029                 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
5030         }
5031
5032 exit:
5033         if (isfree)
5034                 kfree(mgmt_frame);
5035         return err;
5036 #else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !WL_CFG80211_STA_EVENT */
5037         sinfo.filled = 0;
5038         if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
5039                 reason == DOT11_SC_SUCCESS) {
5040                 sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
5041                 if (!data) {
5042                         WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
5043                         return -EINVAL;
5044                 }
5045                 sinfo.assoc_req_ies = data;
5046                 sinfo.assoc_req_ies_len = len;
5047                 cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
5048         } else if (event == WLC_E_DISASSOC_IND) {
5049                 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
5050         } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
5051                 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
5052         }
5053 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !WL_CFG80211_STA_EVENT */
5054         return err;
5055 }
5056
5057 static s32
5058 wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
5059         const wl_event_msg_t *e, void *data)
5060 {
5061         bool act;
5062         s32 err = 0;
5063         u32 event = ntoh32(e->event_type);
5064         u32 reason;
5065
5066         if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) {
5067                 wl_notify_connect_status_ap(wl, ndev, e, data);
5068         } else {
5069                 WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
5070                         ntoh32(e->event_type), ntoh32(e->status), ndev));
5071                 if((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DISASSOC_IND)) {
5072                         reason = ntoh32(e->reason);
5073                         wl->deauth_reason = reason;
5074                         WL_ERR(("Received %s event with reason code: %d\n",
5075                         (event == WLC_E_DEAUTH_IND)?
5076                         "WLC_E_DEAUTH_IND":"WLC_E_DISASSOC_IND", reason));
5077                 }
5078                 if (wl_is_linkup(wl, e, ndev)) {
5079                         wl_link_up(wl);
5080                         act = true;
5081                         wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT);
5082                         wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
5083                         wl->deauth_reason = 0;
5084                         if (wl_is_ibssmode(wl, ndev)) {
5085                                 wl_ibss_join_done(wl, ndev, e, data, true);
5086                                 WL_DBG(("wl_ibss_join_done succeeded\n"));
5087                         } else {
5088                                 if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) {
5089                                         printk("wl_bss_connect_done succeeded\n");
5090                                         wl_bss_connect_done(wl, ndev, e, data, true);
5091                                         WL_DBG(("joined in BSS network \"%s\"\n",
5092                                         ((struct wlc_ssid *)
5093                                          wl_read_prof(wl, ndev, WL_PROF_SSID))->SSID));
5094                                 }
5095                         }
5096                 } else if (wl_is_linkdown(wl, e)) {
5097                         if (wl->scan_request) {
5098                                 if (wl->escan_on) {
5099                                         wl_notify_escan_complete(wl, ndev, true, true);
5100                                 } else {
5101                                         del_timer_sync(&wl->scan_timeout);
5102                                         wl_iscan_aborted(wl);
5103                                 }
5104                         }
5105                         if (wl_get_drv_status(wl, CONNECTED, ndev)) {
5106                                 scb_val_t scbval;
5107                                 u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
5108                                 wl_clr_drv_status(wl, CONNECTED, ndev);
5109                                 if (! wl_get_drv_status(wl, DISCONNECTING, ndev)) {
5110                                         /* To make sure disconnect, explictly send dissassoc
5111                                         *  for BSSID 00:00:00:00:00:00 issue
5112                                         */
5113                                         scbval.val = WLAN_REASON_DEAUTH_LEAVING;
5114
5115                                         memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
5116                                         scbval.val = htod32(scbval.val);
5117                                         wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
5118                                                 sizeof(scb_val_t), true);
5119                                         WL_ERR(("link down, calling cfg80211_disconnected"
5120                                         " with deauth_reason:%d\n", wl->deauth_reason));
5121                                         if (!wl_is_ibssmode(wl, ndev))
5122                                                 cfg80211_disconnected(ndev, wl->deauth_reason,
5123                                                         NULL, 0, GFP_KERNEL);
5124                                         wl_link_down(wl);
5125                                         wl_init_prof(wl, ndev);
5126                                 }
5127                         }
5128                         else if (wl_get_drv_status(wl, CONNECTING, ndev)) {
5129                                 printk("link down, during connecting\n");
5130                                 if (wl_is_ibssmode(wl, ndev))
5131                                         wl_ibss_join_done(wl, ndev, e, data, false);
5132                                 else
5133                                         wl_bss_connect_done(wl, ndev, e, data, false);
5134                         }
5135                         wl_clr_drv_status(wl, DISCONNECTING, ndev);
5136
5137                 } else if (wl_is_nonetwork(wl, e)) {
5138                         printk("connect failed event=%d e->status 0x%x\n",
5139                                 event, (int)ntoh32(e->status));
5140                         /* Clean up any pending scan request */
5141                         if (wl->scan_request) {
5142                                 if (wl->escan_on) {
5143                                         wl_notify_escan_complete(wl, ndev, true, true);
5144                                 } else {
5145                                         del_timer_sync(&wl->scan_timeout);
5146                                         wl_iscan_aborted(wl);
5147                                 }
5148                         }
5149                         if (wl_get_drv_status(wl, CONNECTING, ndev))
5150                                 wl_bss_connect_done(wl, ndev, e, data, false);
5151                 } else {
5152                         printk("%s nothing\n", __FUNCTION__);
5153                 }
5154         }
5155         return err;
5156 }
5157
5158 static s32
5159 wl_notify_roaming_status(struct wl_priv *wl, struct net_device *ndev,
5160         const wl_event_msg_t *e, void *data)
5161 {
5162         bool act;
5163         s32 err = 0;
5164         u32 event = be32_to_cpu(e->event_type);
5165         u32 status = be32_to_cpu(e->status);
5166         WL_DBG(("Enter \n"));
5167         if (event == WLC_E_ROAM && status == WLC_E_STATUS_SUCCESS) {
5168                 if (wl_get_drv_status(wl, CONNECTED, ndev))
5169                         wl_bss_roaming_done(wl, ndev, e, data);
5170                 else
5171                         wl_bss_connect_done(wl, ndev, e, data, true);
5172                 act = true;
5173                 wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT);
5174                 wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
5175         }
5176         return err;
5177 }
5178
5179 static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev)
5180 {
5181         wl_assoc_info_t assoc_info;
5182         struct wl_connect_info *conn_info = wl_to_conn(wl);
5183         s32 err = 0;
5184
5185         WL_DBG(("Enter \n"));
5186         err = wldev_iovar_getbuf(ndev, "assoc_info", NULL, 0, wl->extra_buf,
5187                 WL_ASSOC_INFO_MAX, NULL);
5188         if (unlikely(err)) {
5189                 WL_ERR(("could not get assoc info (%d)\n", err));
5190                 return err;
5191         }
5192         memcpy(&assoc_info, wl->extra_buf, sizeof(wl_assoc_info_t));
5193         assoc_info.req_len = htod32(assoc_info.req_len);
5194         assoc_info.resp_len = htod32(assoc_info.resp_len);
5195         assoc_info.flags = htod32(assoc_info.flags);
5196         if (conn_info->req_ie_len) {
5197                 conn_info->req_ie_len = 0;
5198                 bzero(conn_info->req_ie, sizeof(conn_info->req_ie));
5199         }
5200         if (conn_info->resp_ie_len) {
5201                 conn_info->resp_ie_len = 0;
5202                 bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie));
5203         }
5204         if (assoc_info.req_len) {
5205                 err = wldev_iovar_getbuf(ndev, "assoc_req_ies", NULL, 0, wl->extra_buf,
5206                         WL_ASSOC_INFO_MAX, NULL);
5207                 if (unlikely(err)) {
5208                         WL_ERR(("could not get assoc req (%d)\n", err));
5209                         return err;
5210                 }
5211                 conn_info->req_ie_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
5212                 if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
5213                         conn_info->req_ie_len -= ETHER_ADDR_LEN;
5214                 }
5215                 if (conn_info->req_ie_len <= MAX_REQ_LINE)
5216                         memcpy(conn_info->req_ie, wl->extra_buf, conn_info->req_ie_len);
5217                 else {
5218                         WL_ERR(("%s IE size %d above max %d size \n",
5219                                 __FUNCTION__, conn_info->req_ie_len, MAX_REQ_LINE));
5220                         return err;
5221                 }
5222         } else {
5223                 conn_info->req_ie_len = 0;
5224         }
5225         if (assoc_info.resp_len) {
5226                 err = wldev_iovar_getbuf(ndev, "assoc_resp_ies", NULL, 0, wl->extra_buf,
5227                         WL_ASSOC_INFO_MAX, NULL);
5228                 if (unlikely(err)) {
5229                         WL_ERR(("could not get assoc resp (%d)\n", err));
5230                         return err;
5231                 }
5232                 conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp);
5233                 if (conn_info->resp_ie_len <= MAX_REQ_LINE)
5234                         memcpy(conn_info->resp_ie, wl->extra_buf, conn_info->resp_ie_len);
5235                 else {
5236                         WL_ERR(("%s IE size %d above max %d size \n",
5237                                 __FUNCTION__, conn_info->resp_ie_len, MAX_REQ_LINE));
5238                         return err;
5239                 }
5240         } else {
5241                 conn_info->resp_ie_len = 0;
5242         }
5243         WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
5244                 conn_info->resp_ie_len));
5245
5246         return err;
5247 }
5248
5249 static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
5250         size_t *join_params_size)
5251 {
5252         chanspec_t chanspec = 0;
5253
5254         if (ch != 0) {
5255                 join_params->params.chanspec_num = 1;
5256                 join_params->params.chanspec_list[0] = ch;
5257
5258                 if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
5259                         chanspec |= WL_CHANSPEC_BAND_2G;
5260                 else
5261                         chanspec |= WL_CHANSPEC_BAND_5G;
5262
5263                 chanspec |= WL_CHANSPEC_BW_20;
5264                 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
5265
5266                 *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
5267                         join_params->params.chanspec_num * sizeof(chanspec_t);
5268
5269                 join_params->params.chanspec_list[0]  &= WL_CHANSPEC_CHAN_MASK;
5270                 join_params->params.chanspec_list[0] |= chanspec;
5271                 join_params->params.chanspec_list[0] =
5272                         htodchanspec(join_params->params.chanspec_list[0]);
5273
5274                 join_params->params.chanspec_num =
5275                         htod32(join_params->params.chanspec_num);
5276
5277                 WL_DBG(("%s  join_params->params.chanspec_list[0]= %X\n",
5278                         __FUNCTION__, join_params->params.chanspec_list[0]));
5279
5280         }
5281 }
5282
5283 static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev)
5284 {
5285         struct cfg80211_bss *bss;
5286         struct wl_bss_info *bi;
5287         struct wlc_ssid *ssid;
5288         struct bcm_tlv *tim;
5289         s32 beacon_interval;
5290         s32 dtim_period;
5291         size_t ie_len;
5292         u8 *ie;
5293         u8 *curbssid;
5294         s32 err = 0;
5295         struct wiphy *wiphy;
5296
5297         wiphy = wl_to_wiphy(wl);
5298
5299         if (wl_is_ibssmode(wl, ndev))
5300                 return err;
5301
5302         ssid = (struct wlc_ssid *)wl_read_prof(wl, ndev, WL_PROF_SSID);
5303         curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
5304         bss = cfg80211_get_bss(wiphy, NULL, curbssid,
5305                 ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS,
5306                 WLAN_CAPABILITY_ESS);
5307
5308         mutex_lock(&wl->usr_sync);
5309         if (!bss) {
5310                 WL_DBG(("Could not find the AP\n"));
5311                 *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
5312                 err = wldev_ioctl(ndev, WLC_GET_BSS_INFO,
5313                         wl->extra_buf, WL_EXTRA_BUF_MAX, false);
5314                 if (unlikely(err)) {
5315                         WL_ERR(("Could not get bss info %d\n", err));
5316                         goto update_bss_info_out;
5317                 }
5318                 bi = (struct wl_bss_info *)(wl->extra_buf + 4);
5319                 if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) {
5320                         err = -EIO;
5321                         goto update_bss_info_out;
5322                 }
5323                 err = wl_inform_single_bss(wl, bi);
5324                 if (unlikely(err))
5325                         goto update_bss_info_out;
5326
5327                 ie = ((u8 *)bi) + bi->ie_offset;
5328                 ie_len = bi->ie_length;
5329                 beacon_interval = cpu_to_le16(bi->beacon_period);
5330         } else {
5331                 WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid));
5332                 ie = bss->information_elements;
5333                 ie_len = bss->len_information_elements;
5334                 beacon_interval = bss->beacon_interval;
5335                 cfg80211_put_bss(bss);
5336         }
5337
5338         tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
5339         if (tim) {
5340                 dtim_period = tim->data[1];
5341         } else {
5342                 /*
5343                 * active scan was done so we could not get dtim
5344                 * information out of probe response.
5345                 * so we speficially query dtim information.
5346                 */
5347                 err = wldev_ioctl(ndev, WLC_GET_DTIMPRD,
5348                         &dtim_period, sizeof(dtim_period), false);
5349                 if (unlikely(err)) {
5350                         WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
5351                         goto update_bss_info_out;
5352                 }
5353         }
5354
5355         wl_update_prof(wl, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT);
5356         wl_update_prof(wl, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
5357
5358 update_bss_info_out:
5359         mutex_unlock(&wl->usr_sync);
5360         return err;
5361 }
5362
5363 static s32
5364 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
5365         const wl_event_msg_t *e, void *data)
5366 {
5367         struct wl_connect_info *conn_info = wl_to_conn(wl);
5368         s32 err = 0;
5369         u8 *curbssid;
5370
5371         wl_get_assoc_ies(wl, ndev);
5372         wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID);
5373         curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
5374         wl_update_bss_info(wl, ndev);
5375         wl_update_pmklist(ndev, wl->pmk_list, err);
5376         cfg80211_roamed(ndev,
5377 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)
5378                 NULL,
5379 #endif
5380                 curbssid,
5381                 conn_info->req_ie, conn_info->req_ie_len,
5382                 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
5383         WL_DBG(("Report roaming result\n"));
5384
5385         wl_set_drv_status(wl, CONNECTED, ndev);
5386
5387         return err;
5388 }
5389
5390 static s32
5391 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
5392         const wl_event_msg_t *e, void *data, bool completed)
5393 {
5394         struct wl_connect_info *conn_info = wl_to_conn(wl);
5395         s32 err = 0;
5396         u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
5397
5398         WL_DBG((" enter\n"));
5399         if (wl->scan_request) {
5400                 wl_notify_escan_complete(wl, ndev, true, true);
5401         }
5402         if (wl_get_drv_status(wl, CONNECTING, ndev)) {
5403                 wl_clr_drv_status(wl, CONNECTING, ndev);
5404                 if (completed) {
5405                         wl_get_assoc_ies(wl, ndev);
5406                         wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID);
5407                         curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
5408                         wl_update_bss_info(wl, ndev);
5409                         wl_update_pmklist(ndev, wl->pmk_list, err);
5410                         wl_set_drv_status(wl, CONNECTED, ndev);
5411                 }
5412                 cfg80211_connect_result(ndev,
5413                         curbssid,
5414                         conn_info->req_ie,
5415                         conn_info->req_ie_len,
5416                         conn_info->resp_ie,
5417                         conn_info->resp_ie_len,
5418                         completed ? WLAN_STATUS_SUCCESS : WLAN_STATUS_AUTH_TIMEOUT,
5419                         GFP_KERNEL);
5420                 if (completed)
5421                         WL_INFO(("Report connect result - connection succeeded\n"));
5422                 else
5423                         WL_ERR(("Report connect result - connection failed\n"));
5424         }
5425         return err;
5426 }
5427
5428 static s32
5429 wl_ibss_join_done(struct wl_priv *wl, struct net_device *ndev,
5430         const wl_event_msg_t *e, void *data, bool completed)
5431 {
5432         s32 err = 0;
5433
5434         WL_TRACE(("Enter\n"));
5435
5436         if (wl->scan_request) {
5437                 wl_notify_escan_complete(wl, ndev, true, true);
5438         }
5439         if (wl_get_drv_status(wl, CONNECTING, ndev)) {
5440                 wl_clr_drv_status(wl, CONNECTING, ndev);
5441                 if (completed) {
5442                         err = wl_inform_ibss(wl, (u8 *)&e->addr);
5443                         if (err) {
5444                                 WL_ERR(("wl_inform_ibss() failed: %d\n", err));
5445                         }
5446                         wl_set_drv_status(wl, CONNECTED, ndev);
5447
5448                         cfg80211_ibss_joined(ndev, (u8 *)&e->addr, GFP_KERNEL);
5449                         WL_DBG(("cfg80211_ibss_joined() called with valid BSSID\n"));
5450                 }
5451         }
5452
5453         WL_TRACE(("Exit\n"));
5454         return err;
5455 }
5456
5457 static s32
5458 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
5459         const wl_event_msg_t *e, void *data)
5460 {
5461         u16 flags = ntoh16(e->flags);
5462         enum nl80211_key_type key_type;
5463
5464         mutex_lock(&wl->usr_sync);
5465         if (flags & WLC_EVENT_MSG_GROUP)
5466                 key_type = NL80211_KEYTYPE_GROUP;
5467         else
5468                 key_type = NL80211_KEYTYPE_PAIRWISE;
5469
5470         cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
5471                 NULL, GFP_KERNEL);
5472         mutex_unlock(&wl->usr_sync);
5473
5474         return 0;
5475 }
5476
5477 #ifdef PNO_SUPPORT
5478 static s32
5479 wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev,
5480         const wl_event_msg_t *e, void *data)
5481 {
5482         WL_ERR((" PNO Event\n"));
5483
5484         mutex_lock(&wl->usr_sync);
5485 #ifndef WL_SCHED_SCAN
5486         /* TODO: Use cfg80211_sched_scan_results(wiphy); */
5487         cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
5488 #else
5489         /* If cfg80211 scheduled scan is supported, report the pno results via sched
5490          * scan results
5491          */
5492         wl_notify_sched_scan_results(wl, ndev, e, data);
5493 #endif /* WL_SCHED_SCAN */
5494         mutex_unlock(&wl->usr_sync);
5495         return 0;
5496 }
5497 #endif /* PNO_SUPPORT */
5498
5499 static s32
5500 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
5501         const wl_event_msg_t *e, void *data)
5502 {
5503         struct channel_info channel_inform;
5504         struct wl_scan_results *bss_list;
5505         u32 len = WL_SCAN_BUF_MAX;
5506         s32 err = 0;
5507         unsigned long flags;
5508
5509         WL_DBG(("Enter \n"));
5510         if (!wl_get_drv_status(wl, SCANNING, ndev)) {
5511                 WL_ERR(("scan is not ready \n"));
5512                 return err;
5513         }
5514         if (wl->iscan_on && wl->iscan_kickstart)
5515                 return wl_wakeup_iscan(wl_to_iscan(wl));
5516
5517         mutex_lock(&wl->usr_sync);
5518         wl_clr_drv_status(wl, SCANNING, ndev);
5519         err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
5520                 sizeof(channel_inform), false);
5521         if (unlikely(err)) {
5522                 WL_ERR(("scan busy (%d)\n", err));
5523                 goto scan_done_out;
5524         }
5525         channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
5526         if (unlikely(channel_inform.scan_channel)) {
5527
5528                 WL_DBG(("channel_inform.scan_channel (%d)\n",
5529                         channel_inform.scan_channel));
5530         }
5531         wl->bss_list = wl->scan_results;
5532         bss_list = wl->bss_list;
5533         memset(bss_list, 0, len);
5534         bss_list->buflen = htod32(len);
5535         err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, false);
5536         if (unlikely(err)) {
5537                 WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
5538                 err = -EINVAL;
5539                 goto scan_done_out;
5540         }
5541         bss_list->buflen = dtoh32(bss_list->buflen);
5542         bss_list->version = dtoh32(bss_list->version);
5543         bss_list->count = dtoh32(bss_list->count);
5544
5545         err = wl_inform_bss(wl);
5546
5547 scan_done_out:
5548         del_timer_sync(&wl->scan_timeout);
5549         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
5550         if (wl->scan_request) {
5551                 WL_DBG(("cfg80211_scan_done\n"));
5552                 cfg80211_scan_done(wl->scan_request, false);
5553                 wl->scan_request = NULL;
5554         }
5555         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
5556         mutex_unlock(&wl->usr_sync);
5557         return err;
5558 }
5559 static s32
5560 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
5561         const struct ether_addr *sa, const struct ether_addr *bssid,
5562         u8 **pheader, u32 *body_len, u8 *pbody)
5563 {
5564         struct dot11_management_header *hdr;
5565         u32 totlen = 0;
5566         s32 err = 0;
5567         u8 *offset;
5568         u32 prebody_len = *body_len;
5569         switch (fc) {
5570                 case FC_ASSOC_REQ:
5571                         /* capability , listen interval */
5572                         totlen = DOT11_ASSOC_REQ_FIXED_LEN;
5573                         *body_len += DOT11_ASSOC_REQ_FIXED_LEN;
5574                         break;
5575
5576                 case FC_REASSOC_REQ:
5577                         /* capability, listen inteval, ap address */
5578                         totlen = DOT11_REASSOC_REQ_FIXED_LEN;
5579                         *body_len += DOT11_REASSOC_REQ_FIXED_LEN;
5580                         break;
5581         }
5582         totlen += DOT11_MGMT_HDR_LEN + prebody_len;
5583         *pheader = kzalloc(totlen, GFP_KERNEL);
5584         if (*pheader == NULL) {
5585                 WL_ERR(("memory alloc failed \n"));
5586                 return -ENOMEM;
5587         }
5588         hdr = (struct dot11_management_header *) (*pheader);
5589         hdr->fc = htol16(fc);
5590         hdr->durid = 0;
5591         hdr->seq = 0;
5592         offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
5593         bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
5594         bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
5595         bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
5596         bcopy((const char*)pbody, offset, prebody_len);
5597         *body_len = totlen;
5598         return err;
5599 }
5600 static s32
5601 wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
5602         const wl_event_msg_t *e, void *data)
5603 {
5604         struct ieee80211_supported_band *band;
5605         struct wiphy *wiphy = wl_to_wiphy(wl);
5606         struct ether_addr da;
5607         struct ether_addr bssid;
5608         bool isfree = false;
5609         s32 err = 0;
5610         s32 freq;
5611         struct net_device *dev = NULL;
5612         wifi_p2p_pub_act_frame_t *act_frm = NULL;
5613         wifi_p2p_action_frame_t *p2p_act_frm = NULL;
5614         wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
5615         wl_event_rx_frame_data_t *rxframe =
5616                 (wl_event_rx_frame_data_t*)data;
5617         u32 event = ntoh32(e->event_type);
5618         u8 *mgmt_frame;
5619         u8 bsscfgidx = e->bsscfgidx;
5620         u32 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t);
5621         u16 channel = ((ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK));
5622
5623         memset(&bssid, 0, ETHER_ADDR_LEN);
5624
5625         if (wl->p2p_net == ndev) {
5626                 dev = wl_to_prmry_ndev(wl);
5627         } else {
5628                 dev = ndev;
5629         }
5630
5631         if (channel <= CH_MAX_2G_CHANNEL)
5632                 band = wiphy->bands[IEEE80211_BAND_2GHZ];
5633         else
5634                 band = wiphy->bands[IEEE80211_BAND_5GHZ];
5635         if (!band) {
5636                 WL_ERR(("No valid band"));
5637                 return -EINVAL;
5638         }
5639
5640         if ((event == WLC_E_P2P_PROBREQ_MSG) &&
5641                 wl->p2p && wl_get_p2p_status(wl, GO_NEG_PHASE)) {
5642                 WL_DBG(("Filtering P2P probe_req while being in GO-Neg state\n"));
5643                 goto exit;
5644         }
5645
5646 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
5647         freq = ieee80211_channel_to_frequency(channel);
5648 #else
5649         freq = ieee80211_channel_to_frequency(channel, band->band);
5650 #endif
5651         if (event == WLC_E_ACTION_FRAME_RX) {
5652                 wldev_iovar_getbuf_bsscfg(dev, "cur_etheraddr",
5653                         NULL, 0, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bsscfgidx, &wl->ioctl_buf_sync);
5654
5655                 wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
5656                 memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN);
5657                 err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid,
5658                         &mgmt_frame, &mgmt_frame_len,
5659                         (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1));
5660                 if (err < 0) {
5661                         WL_ERR(("%s: Error in receiving action frame len %d channel %d freq %d\n",
5662                                 __func__, mgmt_frame_len, channel, freq));
5663                         goto exit;
5664                 }
5665                 isfree = true;
5666                 if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
5667                         mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
5668                         act_frm = (wifi_p2p_pub_act_frame_t *)
5669                                         (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
5670                 } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
5671                         mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
5672                         p2p_act_frm = (wifi_p2p_action_frame_t *)
5673                                         (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
5674                         (void) p2p_act_frm;
5675                 } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
5676                         mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
5677                         sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)
5678                                         (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
5679                         (void) sd_act_frm;
5680                 }
5681                 wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN],
5682                         mgmt_frame_len - DOT11_MGMT_HDR_LEN);
5683                 /*
5684                  * After complete GO Negotiation, roll back to mpc mode
5685                  */
5686                 if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) ||
5687                         (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
5688                         wldev_iovar_setint(dev, "mpc", 1);
5689                 }
5690
5691                 if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) {
5692                         WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
5693                         wl_clr_p2p_status(wl, GO_NEG_PHASE);
5694                 }
5695         } else {
5696                 mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
5697         }
5698
5699         cfg80211_rx_mgmt(ndev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
5700
5701         WL_DBG(("%s: mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n", __func__,
5702                 mgmt_frame_len, ntoh32(e->datalen), channel, freq));
5703
5704         if (isfree)
5705                 kfree(mgmt_frame);
5706 exit:
5707         return 0;
5708 }
5709
5710 #ifdef WL_SCHED_SCAN
5711 /* If target scan is not reliable, set the below define to "1" to do a
5712  * full escan
5713  */
5714 #define FULL_ESCAN_ON_PFN_NET_FOUND             0
5715 static s32
5716 wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev,
5717         const wl_event_msg_t *e, void *data)
5718 {
5719         wl_pfn_net_info_t *netinfo, *pnetinfo;
5720         struct cfg80211_scan_request request;
5721         struct wiphy *wiphy     = wl_to_wiphy(wl);
5722         int err = 0;
5723         struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
5724         struct ieee80211_channel *channel = NULL;
5725         int channel_req = 0;
5726         int band = 0;
5727         struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data;
5728
5729         WL_DBG(("Enter\n"));
5730
5731         if (e->event_type == WLC_E_PFN_NET_LOST) {
5732                 WL_DBG(("PFN NET LOST event. Do Nothing \n"));
5733                 return 0;
5734         }
5735         WL_DBG(("PFN NET FOUND event. count:%d \n", pfn_result->count));
5736         if (pfn_result->count > 0) {
5737                 int i;
5738
5739                 memset(&request, 0x00, sizeof(struct cfg80211_scan_request));
5740                 memset(&ssid, 0x00, sizeof(ssid));
5741                 request.wiphy = wiphy;
5742
5743                 pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t)
5744                                 - sizeof(wl_pfn_net_info_t));
5745                 channel = (struct ieee80211_channel *)kzalloc(
5746                         (sizeof(struct ieee80211_channel) * MAX_PFN_LIST_COUNT),
5747                         GFP_KERNEL);
5748                 if (!channel) {
5749                         WL_ERR(("No memory"));
5750                         err = -ENOMEM;
5751                         goto out_err;
5752                 }
5753
5754                 for (i = 0; i < pfn_result->count; i++) {
5755                         netinfo = &pnetinfo[i];
5756                         if (!netinfo) {
5757                                 WL_ERR(("Invalid netinfo ptr. index:%d", i));
5758                                 err = -EINVAL;
5759                                 goto out_err;
5760                         }
5761                         WL_DBG(("SSID:%s Channel:%d \n",
5762                                 netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel));
5763                         /* PFN result doesn't have all the info which are required by the supplicant
5764                          * (For e.g IEs) Do a target Escan so that sched scan results are reported
5765                          * via wl_inform_single_bss in the required format. Escan does require the
5766                          * scan request in the form of cfg80211_scan_request. For timebeing, create
5767                          * cfg80211_scan_request one out of the received PNO event.
5768                          */
5769                         memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID,
5770                                 netinfo->pfnsubnet.SSID_len);
5771                         ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len;
5772                         request.n_ssids++;
5773
5774                         channel_req = netinfo->pfnsubnet.channel;
5775                         band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
5776                                 : NL80211_BAND_5GHZ;
5777                         channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band);
5778                         channel[i].band = band;
5779                         channel[i].flags |= IEEE80211_CHAN_NO_HT40;
5780                         request.channels[i] = &channel[i];
5781                         request.n_channels++;
5782                 }
5783
5784                 /* assign parsed ssid array */
5785                 if (request.n_ssids)
5786                         request.ssids = &ssid[0];
5787
5788                 if (wl_get_drv_status_all(wl, SCANNING)) {
5789                         /* Abort any on-going scan */
5790                         wl_notify_escan_complete(wl, ndev, true, true);
5791                 }
5792
5793                 if (wl_get_p2p_status(wl, DISCOVERY_ON)) {
5794                         err = wl_cfgp2p_discover_enable_search(wl, false);
5795                         if (unlikely(err)) {
5796                                 wl_clr_drv_status(wl, SCANNING, ndev);
5797                                 goto out_err;
5798                         }
5799                 }
5800
5801                 wl_set_drv_status(wl, SCANNING, ndev);
5802 #if FULL_ESCAN_ON_PFN_NET_FOUND
5803                 err = wl_do_escan(wl, wiphy, ndev, NULL);
5804 #else
5805                 err = wl_do_escan(wl, wiphy, ndev, &request);
5806 #endif
5807                 if (err) {
5808                         wl_clr_drv_status(wl, SCANNING, ndev);
5809                         goto out_err;
5810                 }
5811                 wl->sched_scan_running = TRUE;
5812         }
5813         else {
5814                 WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
5815         }
5816 out_err:
5817         if (channel)
5818                 kfree(channel);
5819         return err;
5820 }
5821 #endif /* WL_SCHED_SCAN */
5822
5823 static void wl_init_conf(struct wl_conf *conf)
5824 {
5825         WL_DBG(("Enter \n"));
5826         conf->frag_threshold = (u32)-1;
5827         conf->rts_threshold = (u32)-1;
5828         conf->retry_short = (u32)-1;
5829         conf->retry_long = (u32)-1;
5830         conf->tx_power = -1;
5831 }
5832
5833 static void wl_init_prof(struct wl_priv *wl, struct net_device *ndev)
5834 {
5835         unsigned long flags;
5836         struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
5837
5838         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
5839         memset(profile, 0, sizeof(struct wl_profile));
5840         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
5841 }
5842
5843 static void wl_init_event_handler(struct wl_priv *wl)
5844 {
5845         memset(wl->evt_handler, 0, sizeof(wl->evt_handler));
5846
5847         wl->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
5848         wl->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
5849         wl->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
5850         wl->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
5851         wl->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
5852         wl->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
5853         wl->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
5854         wl->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;
5855         wl->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
5856         wl->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;
5857         wl->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;
5858         wl->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
5859         wl->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
5860         wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
5861         wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
5862         wl->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
5863 #ifdef PNO_SUPPORT
5864         wl->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status;
5865 #endif /* PNO_SUPPORT */
5866 }
5867
5868 static s32 wl_init_priv_mem(struct wl_priv *wl)
5869 {
5870         WL_DBG(("Enter \n"));
5871         wl->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
5872         if (unlikely(!wl->scan_results)) {
5873                 WL_ERR(("Scan results alloc failed\n"));
5874                 goto init_priv_mem_out;
5875         }
5876         wl->conf = (void *)kzalloc(sizeof(*wl->conf), GFP_KERNEL);
5877         if (unlikely(!wl->conf)) {
5878                 WL_ERR(("wl_conf alloc failed\n"));
5879                 goto init_priv_mem_out;
5880         }
5881         wl->scan_req_int =
5882             (void *)kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL);
5883         if (unlikely(!wl->scan_req_int)) {
5884                 WL_ERR(("Scan req alloc failed\n"));
5885                 goto init_priv_mem_out;
5886         }
5887         wl->ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
5888         if (unlikely(!wl->ioctl_buf)) {
5889                 WL_ERR(("Ioctl buf alloc failed\n"));
5890                 goto init_priv_mem_out;
5891         }
5892         wl->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
5893         if (unlikely(!wl->escan_ioctl_buf)) {
5894                 WL_ERR(("Ioctl buf alloc failed\n"));
5895                 goto init_priv_mem_out;
5896         }
5897         wl->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
5898         if (unlikely(!wl->extra_buf)) {
5899                 WL_ERR(("Extra buf alloc failed\n"));
5900                 goto init_priv_mem_out;
5901         }
5902         wl->iscan = (void *)kzalloc(sizeof(*wl->iscan), GFP_KERNEL);
5903         if (unlikely(!wl->iscan)) {
5904                 WL_ERR(("Iscan buf alloc failed\n"));
5905                 goto init_priv_mem_out;
5906         }
5907         wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL);
5908         if (unlikely(!wl->pmk_list)) {
5909                 WL_ERR(("pmk list alloc failed\n"));
5910                 goto init_priv_mem_out;
5911         }
5912         wl->sta_info = (void *)kzalloc(sizeof(*wl->sta_info), GFP_KERNEL);
5913         if (unlikely(!wl->sta_info)) {
5914                 WL_ERR(("sta info  alloc failed\n"));
5915                 goto init_priv_mem_out;
5916         }
5917         wl->afx_hdl = (void *)kzalloc(sizeof(*wl->afx_hdl), GFP_KERNEL);
5918         if (unlikely(!wl->afx_hdl)) {
5919                 WL_ERR(("afx hdl  alloc failed\n"));
5920                 goto init_priv_mem_out;
5921         } else {
5922                 init_completion(&wl->act_frm_scan);
5923                 INIT_WORK(&wl->afx_hdl->work, wl_cfg80211_afx_handler);
5924         }
5925         return 0;
5926
5927 init_priv_mem_out:
5928         wl_deinit_priv_mem(wl);
5929
5930         return -ENOMEM;
5931 }
5932
5933 static void wl_deinit_priv_mem(struct wl_priv *wl)
5934 {
5935         kfree(wl->scan_results);
5936         wl->scan_results = NULL;
5937         kfree(wl->conf);
5938         wl->conf = NULL;
5939         kfree(wl->scan_req_int);
5940         wl->scan_req_int = NULL;
5941         kfree(wl->ioctl_buf);
5942         wl->ioctl_buf = NULL;
5943         kfree(wl->escan_ioctl_buf);
5944         wl->escan_ioctl_buf = NULL;
5945         kfree(wl->extra_buf);
5946         wl->extra_buf = NULL;
5947         kfree(wl->iscan);
5948         wl->iscan = NULL;
5949         kfree(wl->pmk_list);
5950         wl->pmk_list = NULL;
5951         kfree(wl->sta_info);
5952         wl->sta_info = NULL;
5953         if (wl->afx_hdl) {
5954                 cancel_work_sync(&wl->afx_hdl->work);
5955                 kfree(wl->afx_hdl);
5956                 wl->afx_hdl = NULL;
5957         }
5958
5959         if (wl->ap_info) {
5960                 kfree(wl->ap_info->wpa_ie);
5961                 kfree(wl->ap_info->rsn_ie);
5962                 kfree(wl->ap_info->wps_ie);
5963                 kfree(wl->ap_info);
5964                 wl->ap_info = NULL;
5965         }
5966 }
5967
5968 static s32 wl_create_event_handler(struct wl_priv *wl)
5969 {
5970         int ret = 0;
5971         WL_DBG(("Enter \n"));
5972
5973         /* Do not use DHD in cfg driver */
5974         wl->event_tsk.thr_pid = -1;
5975         PROC_START(wl_event_handler, wl, &wl->event_tsk, 0);
5976         if (wl->event_tsk.thr_pid < 0)
5977                 ret = -ENOMEM;
5978         return ret;
5979 }
5980
5981 static void wl_destroy_event_handler(struct wl_priv *wl)
5982 {
5983         if (wl->event_tsk.thr_pid >= 0)
5984                 PROC_STOP(&wl->event_tsk);
5985 }
5986
5987 static void wl_term_iscan(struct wl_priv *wl)
5988 {
5989         struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
5990         WL_TRACE(("In\n"));
5991         if (wl->iscan_on && iscan->tsk) {
5992                 iscan->state = WL_ISCAN_STATE_IDLE;
5993                 WL_INFO(("SIGTERM\n"));
5994                 send_sig(SIGTERM, iscan->tsk, 1);
5995                 WL_DBG(("kthread_stop\n"));
5996                 kthread_stop(iscan->tsk);
5997                 iscan->tsk = NULL;
5998         }
5999 }
6000
6001 static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted)
6002 {
6003         struct wl_priv *wl = iscan_to_wl(iscan);
6004         struct net_device *ndev = wl_to_prmry_ndev(wl);
6005         unsigned long flags;
6006
6007         WL_DBG(("Enter \n"));
6008         if (!wl_get_drv_status(wl, SCANNING, ndev)) {
6009                 wl_clr_drv_status(wl, SCANNING, ndev);
6010                 WL_ERR(("Scan complete while device not scanning\n"));
6011                 return;
6012         }
6013         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
6014         wl_clr_drv_status(wl, SCANNING, ndev);
6015         if (likely(wl->scan_request)) {
6016                 cfg80211_scan_done(wl->scan_request, aborted);
6017                 wl->scan_request = NULL;
6018         }
6019         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
6020         wl->iscan_kickstart = false;
6021 }
6022
6023 static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan)
6024 {
6025         if (likely(iscan->state != WL_ISCAN_STATE_IDLE)) {
6026                 WL_DBG(("wake up iscan\n"));
6027                 up(&iscan->sync);
6028                 return 0;
6029         }
6030
6031         return -EIO;
6032 }
6033
6034 static s32
6035 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
6036         struct wl_scan_results **bss_list)
6037 {
6038         struct wl_iscan_results list;
6039         struct wl_scan_results *results;
6040         struct wl_iscan_results *list_buf;
6041         s32 err = 0;
6042
6043         WL_DBG(("Enter \n"));
6044         memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
6045         list_buf = (struct wl_iscan_results *)iscan->scan_buf;
6046         results = &list_buf->results;
6047         results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
6048         results->version = 0;
6049         results->count = 0;
6050
6051         memset(&list, 0, sizeof(list));
6052         list.results.buflen = htod32(WL_ISCAN_BUF_MAX);
6053         err = wldev_iovar_getbuf(iscan->dev, "iscanresults", &list,
6054                 WL_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf,
6055                 WL_ISCAN_BUF_MAX, NULL);
6056         if (unlikely(err)) {
6057                 WL_ERR(("error (%d)\n", err));
6058                 return err;
6059         }
6060         results->buflen = dtoh32(results->buflen);
6061         results->version = dtoh32(results->version);
6062         results->count = dtoh32(results->count);
6063         WL_DBG(("results->count = %d\n", results->count));
6064         WL_DBG(("results->buflen = %d\n", results->buflen));
6065         *status = dtoh32(list_buf->status);
6066         *bss_list = results;
6067
6068         return err;
6069 }
6070
6071 static s32 wl_iscan_done(struct wl_priv *wl)
6072 {
6073         struct wl_iscan_ctrl *iscan = wl->iscan;
6074         s32 err = 0;
6075
6076         iscan->state = WL_ISCAN_STATE_IDLE;
6077         mutex_lock(&wl->usr_sync);
6078         wl_inform_bss(wl);
6079         wl_notify_iscan_complete(iscan, false);
6080         mutex_unlock(&wl->usr_sync);
6081
6082         return err;
6083 }
6084
6085 static s32 wl_iscan_pending(struct wl_priv *wl)
6086 {
6087         struct wl_iscan_ctrl *iscan = wl->iscan;
6088         s32 err = 0;
6089
6090         /* Reschedule the timer */
6091         mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
6092         iscan->timer_on = 1;
6093
6094         return err;
6095 }
6096
6097 static s32 wl_iscan_inprogress(struct wl_priv *wl)
6098 {
6099         struct wl_iscan_ctrl *iscan = wl->iscan;
6100         s32 err = 0;
6101
6102         mutex_lock(&wl->usr_sync);
6103         wl_inform_bss(wl);
6104         wl_run_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
6105         mutex_unlock(&wl->usr_sync);
6106         /* Reschedule the timer */
6107         mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
6108         iscan->timer_on = 1;
6109
6110         return err;
6111 }
6112
6113 static s32 wl_iscan_aborted(struct wl_priv *wl)
6114 {
6115         struct wl_iscan_ctrl *iscan = wl->iscan;
6116         s32 err = 0;
6117
6118         iscan->state = WL_ISCAN_STATE_IDLE;
6119         mutex_lock(&wl->usr_sync);
6120         wl_notify_iscan_complete(iscan, true);
6121         mutex_unlock(&wl->usr_sync);
6122
6123         return err;
6124 }
6125
6126 static s32 wl_iscan_thread(void *data)
6127 {
6128         struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
6129         struct wl_priv *wl = iscan_to_wl(iscan);
6130         u32 status;
6131         int err = 0;
6132
6133         allow_signal(SIGTERM);
6134         status = WL_SCAN_RESULTS_PARTIAL;
6135         while (likely(!down_interruptible(&iscan->sync))) {
6136                 if (kthread_should_stop())
6137                         break;
6138                 if (iscan->timer_on) {
6139                         del_timer_sync(&iscan->timer);
6140                         iscan->timer_on = 0;
6141                 }
6142                 mutex_lock(&wl->usr_sync);
6143                 err = wl_get_iscan_results(iscan, &status, &wl->bss_list);
6144                 if (unlikely(err)) {
6145                         status = WL_SCAN_RESULTS_ABORTED;
6146                         WL_ERR(("Abort iscan\n"));
6147                 }
6148                 mutex_unlock(&wl->usr_sync);
6149                 iscan->iscan_handler[status] (wl);
6150         }
6151         if (iscan->timer_on) {
6152                 del_timer_sync(&iscan->timer);
6153                 iscan->timer_on = 0;
6154         }
6155         WL_DBG(("%s was terminated\n", __func__));
6156
6157         return 0;
6158 }
6159
6160 static void wl_scan_timeout(unsigned long data)
6161 {
6162         struct wl_priv *wl = (struct wl_priv *)data;
6163
6164         if (wl->scan_request) {
6165                 WL_ERR(("timer expired\n"));
6166                 if (wl->escan_on)
6167                         wl_notify_escan_complete(wl, wl->escan_info.ndev, true, false);
6168                 else
6169                         wl_notify_iscan_complete(wl_to_iscan(wl), true);
6170         }
6171 }
6172
6173 static void wl_iscan_timer(unsigned long data)
6174 {
6175         struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
6176
6177         if (iscan) {
6178                 iscan->timer_on = 0;
6179                 WL_DBG(("timer expired\n"));
6180                 wl_wakeup_iscan(iscan);
6181         }
6182 }
6183
6184 static s32 wl_invoke_iscan(struct wl_priv *wl)
6185 {
6186         struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
6187         int err = 0;
6188
6189         if (wl->iscan_on && !iscan->tsk) {
6190                 iscan->state = WL_ISCAN_STATE_IDLE;
6191                 sema_init(&iscan->sync, 0);
6192                 iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan");
6193                 if (IS_ERR(iscan->tsk)) {
6194                         WL_ERR(("Could not create iscan thread\n"));
6195                         iscan->tsk = NULL;
6196                         return -ENOMEM;
6197                 }
6198         }
6199
6200         return err;
6201 }
6202
6203 static void wl_init_iscan_handler(struct wl_iscan_ctrl *iscan)
6204 {
6205         memset(iscan->iscan_handler, 0, sizeof(iscan->iscan_handler));
6206         iscan->iscan_handler[WL_SCAN_RESULTS_SUCCESS] = wl_iscan_done;
6207         iscan->iscan_handler[WL_SCAN_RESULTS_PARTIAL] = wl_iscan_inprogress;
6208         iscan->iscan_handler[WL_SCAN_RESULTS_PENDING] = wl_iscan_pending;
6209         iscan->iscan_handler[WL_SCAN_RESULTS_ABORTED] = wl_iscan_aborted;
6210         iscan->iscan_handler[WL_SCAN_RESULTS_NO_MEM] = wl_iscan_aborted;
6211 }
6212
6213 static s32
6214 wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
6215         unsigned long state,
6216         void *ndev)
6217 {
6218         struct net_device *dev = ndev;
6219         struct wireless_dev *wdev = dev->ieee80211_ptr;
6220         struct wl_priv *wl = wlcfg_drv_priv;
6221
6222         WL_DBG(("Enter \n"));
6223         if (!wdev || !wl || dev == wl_to_prmry_ndev(wl))
6224                 return NOTIFY_DONE;
6225         switch (state) {
6226                 case NETDEV_UNREGISTER:
6227                         /* after calling list_del_rcu(&wdev->list) */
6228                         wl_dealloc_netinfo(wl, ndev);
6229                         break;
6230                 case NETDEV_GOING_DOWN:
6231                         /* At NETDEV_DOWN state, wdev_cleanup_work work will be called.
6232                         *  In front of door, the function checks
6233                         *  whether current scan is working or not.
6234                         *  If the scanning is still working, wdev_cleanup_work call WARN_ON and
6235                         *  make the scan done forcibly.
6236                         */
6237                         if (wl_get_drv_status(wl, SCANNING, dev)) {
6238                                 if (wl->escan_on) {
6239                                         wl_notify_escan_complete(wl, dev, true, true);
6240                                 }
6241                         }
6242                         break;
6243         }
6244         return NOTIFY_DONE;
6245 }
6246 static struct notifier_block wl_cfg80211_netdev_notifier = {
6247         .notifier_call = wl_cfg80211_netdev_notifier_call,
6248 };
6249
6250 static s32 wl_notify_escan_complete(struct wl_priv *wl,
6251         struct net_device *ndev,
6252         bool aborted, bool fw_abort)
6253 {
6254         wl_scan_params_t *params = NULL;
6255         s32 params_size = 0;
6256         s32 err = BCME_OK;
6257         unsigned long flags;
6258         struct net_device *dev;
6259
6260         WL_DBG(("Enter \n"));
6261
6262         if (wl->scan_request) {
6263                 if (wl->scan_request->dev == wl->p2p_net)
6264                         dev = wl_to_prmry_ndev(wl);
6265                 else
6266                         dev = wl->scan_request->dev;
6267         }
6268         else {
6269                 WL_ERR(("wl->scan_request is NULL may be internal scan."
6270                         "doing scan_abort for ndev %p primary %p p2p_net %p",
6271                                 ndev, wl_to_prmry_ndev(wl), wl->p2p_net));
6272                 dev = ndev;
6273         }
6274         if (fw_abort && !in_atomic()) {
6275                 /* Our scan params only need space for 1 channel and 0 ssids */
6276                 params = wl_cfg80211_scan_alloc_params(-1, 0, &params_size);
6277                 if (params == NULL) {
6278                         WL_ERR(("scan params allocation failed \n"));
6279                         err = -ENOMEM;
6280                 } else {
6281                         /* Do a scan abort to stop the driver's scan engine */
6282                         err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true);
6283                         if (err < 0) {
6284                                 WL_ERR(("scan abort  failed \n"));
6285                         }
6286                 }
6287         }
6288         if (timer_pending(&wl->scan_timeout))
6289                 del_timer_sync(&wl->scan_timeout);
6290         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
6291
6292 #ifdef WL_SCHED_SCAN
6293         if (wl->sched_scan_req && !wl->scan_request) {
6294                 WL_DBG((" REPORTING SCHED SCAN RESULTS \n"));
6295                 if (aborted)
6296                         cfg80211_sched_scan_stopped(wl->sched_scan_req->wiphy);
6297                 else
6298                         cfg80211_sched_scan_results(wl->sched_scan_req->wiphy);
6299                 wl->sched_scan_running = FALSE;
6300                 wl->sched_scan_req = NULL;
6301         }
6302 #endif /* WL_SCHED_SCAN */
6303
6304         if (likely(wl->scan_request)) {
6305                 cfg80211_scan_done(wl->scan_request, aborted);
6306                 wl->scan_request = NULL;
6307         }
6308         if (p2p_is_on(wl))
6309                 wl_clr_p2p_status(wl, SCANNING);
6310         wl_clr_drv_status(wl, SCANNING, dev);
6311         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
6312         if (params)
6313                 kfree(params);
6314
6315         return err;
6316 }
6317
6318 static s32 wl_escan_handler(struct wl_priv *wl,
6319         struct net_device *ndev,
6320         const wl_event_msg_t *e, void *data)
6321 {
6322         s32 err = BCME_OK;
6323         s32 status = ntoh32(e->status);
6324         wl_bss_info_t *bi;
6325         wl_escan_result_t *escan_result;
6326         wl_bss_info_t *bss = NULL;
6327         wl_scan_results_t *list;
6328         u32 bi_length;
6329         u32 i;
6330         u8 *p2p_dev_addr = NULL;
6331         WL_DBG((" enter event type : %d, status : %d \n",
6332                 ntoh32(e->event_type), ntoh32(e->status)));
6333         /* P2P SCAN is coming from primary interface */
6334         if (wl_get_p2p_status(wl, SCANNING)) {
6335                 if (wl_get_drv_status_all(wl, SENDING_ACT_FRM))
6336                         ndev = wl->afx_hdl->dev;
6337                 else
6338                         ndev = wl->escan_info.ndev;
6339
6340         }
6341         if (!ndev || !wl->escan_on ||
6342                 !wl_get_drv_status(wl, SCANNING, ndev)) {
6343                 WL_ERR(("escan is not ready ndev %p wl->escan_on %d drv_status 0x%x\n",
6344                         ndev, wl->escan_on, wl_get_drv_status(wl, SCANNING, ndev)));
6345                 return err;
6346         }
6347
6348         if (status == WLC_E_STATUS_PARTIAL) {
6349                 WL_INFO(("WLC_E_STATUS_PARTIAL \n"));
6350                 escan_result = (wl_escan_result_t *) data;
6351                 if (!escan_result) {
6352                         WL_ERR(("Invalid escan result (NULL pointer)\n"));
6353                         goto exit;
6354                 }
6355                 if (dtoh16(escan_result->bss_count) != 1) {
6356                         WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
6357                         goto exit;
6358                 }
6359                 bi = escan_result->bss_info;
6360                 if (!bi) {
6361                         WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
6362                         goto exit;
6363                 }
6364                 bi_length = dtoh32(bi->length);
6365                 if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
6366                         WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length));
6367                         goto exit;
6368                 }
6369
6370                 if (!(wl_to_wiphy(wl)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
6371                         if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
6372                                 WL_DBG(("Ignoring IBSS result\n"));
6373                                 goto exit;
6374                         }
6375                 }
6376
6377                 if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) {
6378                         p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
6379                         if (p2p_dev_addr && !memcmp(p2p_dev_addr,
6380                                 wl->afx_hdl->pending_tx_dst_addr.octet, ETHER_ADDR_LEN)) {
6381                                 s32 channel = CHSPEC_CHANNEL(dtohchanspec(bi->chanspec));
6382                                 WL_DBG(("ACTION FRAME SCAN : Peer " MACSTR " found, channel : %d\n",
6383                                         MAC2STR(wl->afx_hdl->pending_tx_dst_addr.octet), channel));
6384                                 wl_clr_p2p_status(wl, SCANNING);
6385                                 wl->afx_hdl->peer_chan = channel;
6386                                 complete(&wl->act_frm_scan);
6387                                 goto exit;
6388                         }
6389
6390                 } else {
6391                         list = (wl_scan_results_t *)wl->escan_info.escan_buf;
6392                         if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
6393                                 WL_ERR(("Buffer is too small: ignoring\n"));
6394                                 goto exit;
6395                         }
6396 #define WLC_BSS_RSSI_ON_CHANNEL 0x0002
6397                         for (i = 0; i < list->count; i++) {
6398                                 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
6399                                         : list->bss_info;
6400
6401                                 if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
6402                                         CHSPEC_BAND(bi->chanspec) == CHSPEC_BAND(bss->chanspec) &&
6403                                         bi->SSID_len == bss->SSID_len &&
6404                                         !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
6405                                         if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) ==
6406                                                 (bi->flags & WLC_BSS_RSSI_ON_CHANNEL)) {
6407                                                 /* preserve max RSSI if the measurements are
6408                                                 * both on-channel or both off-channel
6409                                                 */
6410                                                 bss->RSSI = MAX(bss->RSSI, bi->RSSI);
6411                                         } else if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) &&
6412                                                 (bi->flags & WLC_BSS_RSSI_ON_CHANNEL) == 0) {
6413                                                 /* preserve the on-channel rssi measurement
6414                                                 * if the new measurement is off channel
6415                                                 */
6416                                                 bss->RSSI = bi->RSSI;
6417                                                 bss->flags |= WLC_BSS_RSSI_ON_CHANNEL;
6418                                         }
6419
6420                                         goto exit;
6421                                 }
6422                         }
6423                         memcpy(&(wl->escan_info.escan_buf[list->buflen]), bi, bi_length);
6424                         list->version = dtoh32(bi->version);
6425                         list->buflen += bi_length;
6426                         list->count++;
6427
6428                 }
6429
6430         }
6431         else if (status == WLC_E_STATUS_SUCCESS) {
6432                 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
6433                 if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) {
6434                         WL_INFO(("ACTION FRAME SCAN DONE\n"));
6435                         wl_clr_p2p_status(wl, SCANNING);
6436                         wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
6437                         if (wl->afx_hdl->peer_chan == WL_INVALID)
6438                                 complete(&wl->act_frm_scan);
6439                 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
6440                         mutex_lock(&wl->usr_sync);
6441                         WL_INFO(("ESCAN COMPLETED\n"));
6442                         wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf;
6443                         wl_inform_bss(wl);
6444                         wl_notify_escan_complete(wl, ndev, false, false);
6445                         mutex_unlock(&wl->usr_sync);
6446                 }
6447         }
6448         else if (status == WLC_E_STATUS_ABORT) {
6449                 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
6450                 if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) {
6451                         WL_INFO(("ACTION FRAME SCAN DONE\n"));
6452                         wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
6453                         wl_clr_p2p_status(wl, SCANNING);
6454                         if (wl->afx_hdl->peer_chan == WL_INVALID)
6455                                 complete(&wl->act_frm_scan);
6456                 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
6457                         mutex_lock(&wl->usr_sync);
6458                         WL_INFO(("ESCAN ABORTED\n"));
6459                         wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf;
6460                         wl_inform_bss(wl);
6461                         wl_notify_escan_complete(wl, ndev, true, false);
6462                         mutex_unlock(&wl->usr_sync);
6463                 }
6464         }
6465         else {
6466                 WL_ERR(("unexpected Escan Event %d : abort\n", status));
6467                 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
6468                 if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) {
6469                         WL_INFO(("ACTION FRAME SCAN DONE\n"));
6470                         wl_clr_p2p_status(wl, SCANNING);
6471                         wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
6472                         if (wl->afx_hdl->peer_chan == WL_INVALID)
6473                                 complete(&wl->act_frm_scan);
6474                 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
6475                         mutex_lock(&wl->usr_sync);
6476                         wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf;
6477                         wl_inform_bss(wl);
6478                         wl_notify_escan_complete(wl, ndev, true, false);
6479                         mutex_unlock(&wl->usr_sync);
6480                 }
6481         }
6482 exit:
6483         return err;
6484 }
6485
6486 static s32 wl_init_scan(struct wl_priv *wl)
6487 {
6488         struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
6489         int err = 0;
6490
6491         if (wl->iscan_on) {
6492                 iscan->dev = wl_to_prmry_ndev(wl);
6493                 iscan->state = WL_ISCAN_STATE_IDLE;
6494                 wl_init_iscan_handler(iscan);
6495                 iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
6496                 init_timer(&iscan->timer);
6497                 iscan->timer.data = (unsigned long) iscan;
6498                 iscan->timer.function = wl_iscan_timer;
6499                 sema_init(&iscan->sync, 0);
6500                 iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan");
6501                 if (IS_ERR(iscan->tsk)) {
6502                         WL_ERR(("Could not create iscan thread\n"));
6503                         iscan->tsk = NULL;
6504                         return -ENOMEM;
6505                 }
6506                 iscan->data = wl;
6507         } else if (wl->escan_on) {
6508                 wl->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
6509                 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
6510         }
6511         /* Init scan_timeout timer */
6512         init_timer(&wl->scan_timeout);
6513         wl->scan_timeout.data = (unsigned long) wl;
6514         wl->scan_timeout.function = wl_scan_timeout;
6515
6516         return err;
6517 }
6518
6519 static s32 wl_init_priv(struct wl_priv *wl)
6520 {
6521         struct wiphy *wiphy = wl_to_wiphy(wl);
6522         struct net_device *ndev = wl_to_prmry_ndev(wl);
6523         s32 err = 0;
6524
6525         wl->scan_request = NULL;
6526         wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
6527         wl->iscan_on = false;
6528         wl->escan_on = true;
6529         wl->roam_on = false;
6530         wl->iscan_kickstart = false;
6531         wl->active_scan = true;
6532         wl->rf_blocked = false;
6533         wl->deauth_reason = 0;
6534         spin_lock_init(&wl->cfgdrv_lock);
6535         mutex_init(&wl->ioctl_buf_sync);
6536         init_waitqueue_head(&wl->netif_change_event);
6537         wl_init_eq(wl);
6538         err = wl_init_priv_mem(wl);
6539         if (err)
6540                 return err;
6541         if (wl_create_event_handler(wl))
6542                 return -ENOMEM;
6543         wl_init_event_handler(wl);
6544         mutex_init(&wl->usr_sync);
6545         err = wl_init_scan(wl);
6546         if (err)
6547                 return err;
6548         wl_init_conf(wl->conf);
6549         wl_init_prof(wl, ndev);
6550         wl_link_down(wl);
6551         DNGL_FUNC(dhd_cfg80211_init, (wl));
6552
6553         return err;
6554 }
6555
6556 static void wl_deinit_priv(struct wl_priv *wl)
6557 {
6558         DNGL_FUNC(dhd_cfg80211_deinit, (wl));
6559         wl_destroy_event_handler(wl);
6560         wl_flush_eq(wl);
6561         wl_link_down(wl);
6562         del_timer_sync(&wl->scan_timeout);
6563         wl_term_iscan(wl);
6564         wl_deinit_priv_mem(wl);
6565         unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
6566 }
6567
6568 #if defined(WLP2P) && defined(WL_ENABLE_P2P_IF)
6569 static s32 wl_cfg80211_attach_p2p(void)
6570 {
6571         struct wl_priv *wl = wlcfg_drv_priv;
6572
6573         WL_TRACE(("Enter \n"));
6574
6575         if (wl_cfgp2p_register_ndev(wl) < 0) {
6576                 WL_ERR(("%s: P2P attach failed. \n", __func__));
6577                 return -ENODEV;
6578         }
6579
6580         return 0;
6581 }
6582
6583 static s32  wl_cfg80211_detach_p2p(void)
6584 {
6585         struct wl_priv *wl = wlcfg_drv_priv;
6586         struct wireless_dev *wdev = wl->p2p_wdev;
6587
6588         WL_DBG(("Enter \n"));
6589         if (!wdev || !wl) {
6590                 WL_ERR(("Invalid Ptr\n"));
6591                 return -EINVAL;
6592         }
6593
6594         wl_cfgp2p_unregister_ndev(wl);
6595
6596         wl->p2p_wdev = NULL;
6597         wl->p2p_net = NULL;
6598         WL_DBG(("Freeing 0x%08x \n", (unsigned int)wdev));
6599         kfree(wdev);
6600
6601         return 0;
6602 }
6603 #endif /* defined(WLP2P) && defined(WL_ENABLE_P2P_IF) */
6604
6605 s32 wl_cfg80211_attach_post(struct net_device *ndev)
6606 {
6607         struct wl_priv * wl = NULL;
6608         s32 err = 0;
6609         WL_TRACE(("In\n"));
6610         if (unlikely(!ndev)) {
6611                 WL_ERR(("ndev is invaild\n"));
6612                 return -ENODEV;
6613         }
6614         wl = wlcfg_drv_priv;
6615         if (wl && !wl_get_drv_status(wl, READY, ndev)) {
6616                         if (wl->wdev &&
6617                                 wl_cfgp2p_supported(wl, ndev)) {
6618 #if !defined(WL_ENABLE_P2P_IF)
6619                                 wl->wdev->wiphy->interface_modes |=
6620                                         (BIT(NL80211_IFTYPE_P2P_CLIENT)|
6621                                         BIT(NL80211_IFTYPE_P2P_GO));
6622 #endif
6623                                 if ((err = wl_cfgp2p_init_priv(wl)) != 0)
6624                                         goto fail;
6625
6626 #if defined(WLP2P) && defined(WL_ENABLE_P2P_IF)
6627                                 if (wl->p2p_net) {
6628                                         /* Update MAC addr for p2p0 interface here. */
6629                                         memcpy(wl->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN);
6630                                         wl->p2p_net->dev_addr[0] |= 0x02;
6631                                         printk("%s: p2p_dev_addr="MACSTR "\n",
6632                                                 wl->p2p_net->name, MAC2STR(wl->p2p_net->dev_addr));
6633                                 } else {
6634                                         WL_ERR(("p2p_net not yet populated."
6635                                         " Couldn't update the MAC Address for p2p0 \n"));
6636                                         return -ENODEV;
6637                                 }
6638 #endif /* defined(WLP2P) && (WL_ENABLE_P2P_IF) */
6639
6640                                 wl->p2p_supported = true;
6641                         }
6642         } else
6643                 return -ENODEV;
6644         wl_set_drv_status(wl, READY, ndev);
6645 fail:
6646         return err;
6647 }
6648
6649 s32 wl_cfg80211_attach(struct net_device *ndev, void *data)
6650 {
6651         struct wireless_dev *wdev;
6652         struct wl_priv *wl;
6653         s32 err = 0;
6654         struct device *dev;
6655
6656         WL_TRACE(("In\n"));
6657         if (!ndev) {
6658                 WL_ERR(("ndev is invaild\n"));
6659                 return -ENODEV;
6660         }
6661         WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev()));
6662         dev = wl_cfg80211_get_parent_dev();
6663
6664         wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
6665         if (unlikely(!wdev)) {
6666                 WL_ERR(("Could not allocate wireless device\n"));
6667                 return -ENOMEM;
6668         }
6669         err = wl_setup_wiphy(wdev, dev);
6670         if (unlikely(err)) {
6671                 kfree(wdev);
6672                 return -ENOMEM;
6673         }
6674         wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
6675         wl = (struct wl_priv *)wiphy_priv(wdev->wiphy);
6676         wl->wdev = wdev;
6677         wl->pub = data;
6678         INIT_LIST_HEAD(&wl->net_list);
6679         ndev->ieee80211_ptr = wdev;
6680         SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
6681         wdev->netdev = ndev;
6682         err = wl_alloc_netinfo(wl, ndev, wdev, WL_MODE_BSS);
6683         if (err) {
6684                 WL_ERR(("Failed to alloc net_info (%d)\n", err));
6685                 goto cfg80211_attach_out;
6686         }
6687         err = wl_init_priv(wl);
6688         if (err) {
6689                 WL_ERR(("Failed to init iwm_priv (%d)\n", err));
6690                 goto cfg80211_attach_out;
6691         }
6692
6693         err = wl_setup_rfkill(wl, TRUE);
6694         if (err) {
6695                 WL_ERR(("Failed to setup rfkill %d\n", err));
6696                 goto cfg80211_attach_out;
6697         }
6698         err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier);
6699         if (err) {
6700                 WL_ERR(("Failed to register notifierl %d\n", err));
6701                 goto cfg80211_attach_out;
6702         }
6703 #if defined(COEX_DHCP)
6704         if (wl_cfg80211_btcoex_init(wl))
6705                 goto cfg80211_attach_out;
6706 #endif 
6707
6708         wlcfg_drv_priv = wl;
6709
6710 #if defined(WLP2P) && defined(WL_ENABLE_P2P_IF)
6711         err = wl_cfg80211_attach_p2p();
6712         if (err)
6713                 goto cfg80211_attach_out;
6714 #endif
6715
6716         return err;
6717
6718 cfg80211_attach_out:
6719         err = wl_setup_rfkill(wl, FALSE);
6720         wl_free_wdev(wl);
6721         return err;
6722 }
6723
6724 void wl_cfg80211_detach(void *para)
6725 {
6726         struct wl_priv *wl;
6727
6728         wl = wlcfg_drv_priv;
6729
6730         WL_TRACE(("In\n"));
6731
6732 #if defined(COEX_DHCP)
6733         wl_cfg80211_btcoex_deinit(wl);
6734 #endif 
6735
6736 #if defined(WLP2P) && defined(WL_ENABLE_P2P_IF)
6737         wl_cfg80211_detach_p2p();
6738 #endif
6739         wl_setup_rfkill(wl, FALSE);
6740         if (wl->p2p_supported)
6741                 wl_cfgp2p_deinit_priv(wl);
6742         wl_deinit_priv(wl);
6743         wlcfg_drv_priv = NULL;
6744         wl_cfg80211_clear_parent_dev();
6745         wl_free_wdev(wl);
6746          /* PLEASE do NOT call any function after wl_free_wdev, the driver's private structure "wl",
6747           * which is the private part of wiphy, has been freed in wl_free_wdev !!!!!!!!!!!
6748           */
6749 }
6750
6751 static void wl_wakeup_event(struct wl_priv *wl)
6752 {
6753         if (wl->event_tsk.thr_pid >= 0) {
6754                 DHD_OS_WAKE_LOCK(wl->pub);
6755                 up(&wl->event_tsk.sema);
6756         }
6757 }
6758
6759 static int wl_is_p2p_event(struct wl_event_q *e)
6760 {
6761         switch (e->etype) {
6762         /* We have to seperate out the P2P events received
6763          * on primary interface so that it can be send up
6764          * via p2p0 interface.
6765         */
6766         case WLC_E_P2P_PROBREQ_MSG:
6767         case WLC_E_P2P_DISC_LISTEN_COMPLETE:
6768         case WLC_E_ACTION_FRAME_RX:
6769         case WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE:
6770         case WLC_E_ACTION_FRAME_COMPLETE:
6771
6772                 if (e->emsg.ifidx != 0) {
6773                         WL_TRACE(("P2P Event on Virtual I/F (ifidx:%d) \n",
6774                         e->emsg.ifidx));
6775                         /* We are only bothered about the P2P events received
6776                          * on primary interface. For rest of them return false
6777                          * so that it is sent over the interface corresponding
6778                          * to the ifidx.
6779                          */
6780                         return FALSE;
6781                 } else {
6782                         WL_TRACE(("P2P Event on Primary I/F (ifidx:%d)."
6783                                 " Sent it to p2p0 \n", e->emsg.ifidx));
6784                         return TRUE;
6785                 }
6786                 break;
6787
6788         default:
6789                 WL_TRACE(("NON-P2P Event %d on ifidx (ifidx:%d) \n",
6790                         e->etype, e->emsg.ifidx));
6791                 return FALSE;
6792         }
6793 }
6794
6795 static s32 wl_event_handler(void *data)
6796 {
6797         struct net_device *netdev;
6798         struct wl_priv *wl = NULL;
6799         struct wl_event_q *e;
6800         tsk_ctl_t *tsk = (tsk_ctl_t *)data;
6801
6802         wl = (struct wl_priv *)tsk->parent;
6803         DAEMONIZE("dhd_cfg80211_event");
6804         complete(&tsk->completed);
6805
6806         while (down_interruptible (&tsk->sema) == 0) {
6807                 SMP_RD_BARRIER_DEPENDS();
6808                 if (tsk->terminated)
6809                         break;
6810                 while ((e = wl_deq_event(wl))) {
6811                         WL_DBG(("event type (%d), if idx: %d\n", e->etype, e->emsg.ifidx));
6812                         /* All P2P device address related events comes on primary interface since
6813                          * there is no corresponding bsscfg for P2P interface. Map it to p2p0
6814                          * interface.
6815                          */
6816                         if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_net)) {
6817                                 netdev = wl->p2p_net;
6818                         } else {
6819                                 netdev = dhd_idx2net((struct dhd_pub *)(wl->pub), e->emsg.ifidx);
6820                         }
6821                         if (!netdev)
6822                                 netdev = wl_to_prmry_ndev(wl);
6823                         if (e->etype < WLC_E_LAST && wl->evt_handler[e->etype]) {
6824                                 wl->evt_handler[e->etype] (wl, netdev, &e->emsg, e->edata);
6825                         } else {
6826                                 WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
6827                         }
6828                         wl_put_event(e);
6829                 }
6830                 DHD_OS_WAKE_UNLOCK(wl->pub);
6831         }
6832         WL_ERR(("%s was terminated\n", __func__));
6833         complete_and_exit(&tsk->completed, 0);
6834         return 0;
6835 }
6836
6837 void
6838 wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
6839 {
6840         u32 event_type = ntoh32(e->event_type);
6841         struct wl_priv *wl = wlcfg_drv_priv;
6842
6843 #if (WL_DBG_LEVEL > 0)
6844         s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
6845             wl_dbg_estr[event_type] : (s8 *) "Unknown";
6846         WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
6847 #endif /* (WL_DBG_LEVEL > 0) */
6848
6849         if (likely(!wl_enq_event(wl, ndev, event_type, e, data)))
6850                 wl_wakeup_event(wl);
6851 }
6852
6853 static void wl_init_eq(struct wl_priv *wl)
6854 {
6855         wl_init_eq_lock(wl);
6856         INIT_LIST_HEAD(&wl->eq_list);
6857 }
6858
6859 static void wl_flush_eq(struct wl_priv *wl)
6860 {
6861         struct wl_event_q *e;
6862         unsigned long flags;
6863
6864         flags = wl_lock_eq(wl);
6865         while (!list_empty(&wl->eq_list)) {
6866                 e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
6867                 list_del(&e->eq_list);
6868                 kfree(e);
6869         }
6870         wl_unlock_eq(wl, flags);
6871 }
6872
6873 /*
6874 * retrieve first queued event from head
6875 */
6876
6877 static struct wl_event_q *wl_deq_event(struct wl_priv *wl)
6878 {
6879         struct wl_event_q *e = NULL;
6880         unsigned long flags;
6881
6882         flags = wl_lock_eq(wl);
6883         if (likely(!list_empty(&wl->eq_list))) {
6884                 e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
6885                 list_del(&e->eq_list);
6886         }
6887         wl_unlock_eq(wl, flags);
6888
6889         return e;
6890 }
6891
6892 /*
6893  * push event to tail of the queue
6894  */
6895
6896 static s32
6897 wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 event, const wl_event_msg_t *msg,
6898         void *data)
6899 {
6900         struct wl_event_q *e;
6901         s32 err = 0;
6902         uint32 evtq_size;
6903         uint32 data_len;
6904         unsigned long flags;
6905         gfp_t aflags;
6906
6907         data_len = 0;
6908         if (data)
6909                 data_len = ntoh32(msg->datalen);
6910         evtq_size = sizeof(struct wl_event_q) + data_len;
6911         aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
6912         e = kzalloc(evtq_size, aflags);
6913         if (unlikely(!e)) {
6914                 WL_ERR(("event alloc failed\n"));
6915                 return -ENOMEM;
6916         }
6917         e->etype = event;
6918         memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
6919         if (data)
6920                 memcpy(e->edata, data, data_len);
6921         flags = wl_lock_eq(wl);
6922         list_add_tail(&e->eq_list, &wl->eq_list);
6923         wl_unlock_eq(wl, flags);
6924
6925         return err;
6926 }
6927
6928 static void wl_put_event(struct wl_event_q *e)
6929 {
6930         kfree(e);
6931 }
6932
6933 static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype)
6934 {
6935         s32 infra = 0;
6936         s32 err = 0;
6937         s32 mode = 0;
6938         switch (iftype) {
6939         case NL80211_IFTYPE_MONITOR:
6940         case NL80211_IFTYPE_WDS:
6941                 WL_ERR(("type (%d) : currently we do not support this mode\n",
6942                         iftype));
6943                 err = -EINVAL;
6944                 return err;
6945         case NL80211_IFTYPE_ADHOC:
6946                 mode = WL_MODE_IBSS;
6947                 break;
6948         case NL80211_IFTYPE_STATION:
6949         case NL80211_IFTYPE_P2P_CLIENT:
6950                 mode = WL_MODE_BSS;
6951                 infra = 1;
6952                 break;
6953         case NL80211_IFTYPE_AP:
6954         case NL80211_IFTYPE_P2P_GO:
6955                 mode = WL_MODE_AP;
6956                 infra = 1;
6957                 break;
6958         default:
6959                 err = -EINVAL;
6960                 WL_ERR(("invalid type (%d)\n", iftype));
6961                 return err;
6962         }
6963         infra = htod32(infra);
6964         err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true);
6965         if (unlikely(err)) {
6966                 WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
6967                 return err;
6968         }
6969
6970         wl_set_mode_by_netdev(wl, ndev, mode);
6971
6972         return 0;
6973 }
6974
6975 static s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add)
6976 {
6977         s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
6978
6979         s8 eventmask[WL_EVENTING_MASK_LEN];
6980         s32 err = 0;
6981
6982         /* Setup event_msgs */
6983         bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
6984                 sizeof(iovbuf));
6985         err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
6986         if (unlikely(err)) {
6987                 WL_ERR(("Get event_msgs error (%d)\n", err));
6988                 goto eventmsg_out;
6989         }
6990         memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
6991         if (add) {
6992                 setbit(eventmask, event);
6993         } else {
6994                 clrbit(eventmask, event);
6995         }
6996         bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
6997                 sizeof(iovbuf));
6998         err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
6999         if (unlikely(err)) {
7000                 WL_ERR(("Set event_msgs error (%d)\n", err));
7001                 goto eventmsg_out;
7002         }
7003
7004 eventmsg_out:
7005         return err;
7006
7007 }
7008
7009 static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap)
7010 {
7011         struct net_device *dev = wl_to_prmry_ndev(wl);
7012         struct ieee80211_channel *band_chan_arr = NULL;
7013         wl_uint32_list_t *list;
7014         u32 i, j, index, n_2g, n_5g, band, channel, array_size;
7015         u32 *n_cnt = NULL;
7016         chanspec_t c = 0;
7017         s32 err = BCME_OK;
7018         bool update;
7019         bool ht40_allowed;
7020         u8 *pbuf = NULL;
7021
7022 #define LOCAL_BUF_LEN 1024
7023         pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL);
7024         if (pbuf == NULL) {
7025                 WL_ERR(("failed to allocate local buf\n"));
7026                 return -ENOMEM;
7027         }
7028
7029         list = (wl_uint32_list_t *)(void *)pbuf;
7030         list->count = htod32(WL_NUMCHANSPECS);
7031
7032         err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
7033                 0, pbuf, LOCAL_BUF_LEN, 0, &wl->ioctl_buf_sync);
7034         if (err != 0) {
7035                 WL_ERR(("get chanspecs failed with %d\n", err));
7036                 kfree(pbuf);
7037                 return err;
7038         }
7039 #undef LOCAL_BUF_LEN
7040
7041         band = array_size = n_2g = n_5g = 0;
7042         for (i = 0; i < dtoh32(list->count); i++) {
7043                 index = 0;
7044                 update = FALSE;
7045                 ht40_allowed = FALSE;
7046                 c = (chanspec_t)dtoh32(list->element[i]);
7047                 channel = CHSPEC_CHANNEL(c);
7048                 if (CHSPEC_IS40(c)) {
7049                         if (CHSPEC_SB_UPPER(c))
7050                                 channel += CH_10MHZ_APART;
7051                         else
7052                                 channel -= CH_10MHZ_APART;
7053                 }
7054
7055                 if (CHSPEC_IS2G(c) && channel <= CH_MAX_2G_CHANNEL) {
7056                         band_chan_arr = __wl_2ghz_channels;
7057                         array_size = ARRAYSIZE(__wl_2ghz_channels);
7058                         n_cnt = &n_2g;
7059                         band = IEEE80211_BAND_2GHZ;
7060                         ht40_allowed = (bw_cap == WLC_N_BW_40ALL) ? TRUE : FALSE;
7061                 } else if (CHSPEC_IS5G(c) && channel > CH_MAX_2G_CHANNEL) {
7062                         band_chan_arr = __wl_5ghz_a_channels;
7063                         array_size = ARRAYSIZE(__wl_5ghz_a_channels);
7064                         n_cnt = &n_5g;
7065                         band = IEEE80211_BAND_5GHZ;
7066                         ht40_allowed = (bw_cap == WLC_N_BW_20ALL) ? FALSE : TRUE;
7067                 }
7068
7069                 for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
7070                         if (band_chan_arr[j].hw_value == channel) {
7071                                 update = TRUE;
7072                                 break;
7073                         }
7074                 }
7075
7076                 if (update)
7077                         index = j;
7078                 else
7079                         index = *n_cnt;
7080
7081                 if (index <  array_size) {
7082 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
7083                         band_chan_arr[index].center_freq =
7084                                 ieee80211_channel_to_frequency(channel);
7085 #else
7086                         band_chan_arr[index].center_freq =
7087                                 ieee80211_channel_to_frequency(channel, band);
7088 #endif
7089                         band_chan_arr[index].hw_value = channel;
7090
7091                         if (CHSPEC_IS40(c) && ht40_allowed) {
7092                                 u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
7093                                 if (CHSPEC_SB_UPPER(c)) {
7094                                         if (ht40_flag == IEEE80211_CHAN_NO_HT40)
7095                                                 band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
7096                                         band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
7097                                 } else {
7098                                         band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
7099                                         if (ht40_flag == IEEE80211_CHAN_NO_HT40)
7100                                                 band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40MINUS;
7101                                 }
7102                         } else {
7103                                 band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
7104                                 if (band == IEEE80211_BAND_2GHZ)
7105                                         channel |= WL_CHANSPEC_BAND_2G;
7106                                 else
7107                                         channel |= WL_CHANSPEC_BAND_5G;
7108                                 err = wldev_iovar_getint(dev, "per_chan_info", &channel);
7109                                 if (!err) {
7110                                         if (channel & WL_CHAN_RADAR) {
7111                                                 band_chan_arr[index].flags |= IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS;
7112                                         }
7113                                         if (channel & WL_CHAN_PASSIVE) {
7114                                                 band_chan_arr[index].flags |= IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS;
7115                                         }
7116                                 }
7117                         }
7118
7119                         if (!update)
7120                                 (*n_cnt)++;
7121                 }
7122         }
7123
7124         __wl_band_2ghz.n_channels = n_2g;
7125         __wl_band_5ghz_a.n_channels = n_5g;
7126
7127         kfree(pbuf);
7128         return err;
7129 }
7130
7131 s32 wl_update_wiphybands(struct wl_priv *wl)
7132 {
7133         struct wiphy *wiphy;
7134         struct net_device *dev;
7135         u32 bandlist[3];
7136         u32 nband = 0;
7137         u32 i = 0;
7138         s32 err = 0;
7139         int nmode = 0;
7140         int bw_cap = 0;
7141         int index = 0;
7142
7143         WL_DBG(("Entry"));
7144
7145         if (wl == NULL)
7146                 wl = wlcfg_drv_priv;
7147         dev = wl_to_prmry_ndev(wl);
7148
7149         memset(bandlist, 0, sizeof(bandlist));
7150         err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist,
7151                 sizeof(bandlist), false);
7152         if (unlikely(err)) {
7153                 WL_ERR(("error read bandlist (%d)\n", err));
7154                 return err;
7155         }
7156         wiphy = wl_to_wiphy(wl);
7157         nband = bandlist[0];
7158         wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
7159         wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
7160
7161         err = wldev_iovar_getint(dev, "nmode", &nmode);
7162         if (unlikely(err)) {
7163                 WL_ERR(("error reading nmode (%d)\n", err));
7164         } else {
7165                 /* For nmodeonly  check bw cap */
7166                 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
7167                 if (unlikely(err)) {
7168                         WL_ERR(("error get mimo_bw_cap (%d)\n", err));
7169                 }
7170         }
7171
7172         err = wl_construct_reginfo(wl, bw_cap);
7173         if (err) {
7174                 WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
7175                 return err;
7176         }
7177         for (i = 1; i <= nband && i < sizeof(bandlist)/sizeof(u32); i++) {
7178                 index = -1;
7179                 if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
7180                         wiphy->bands[IEEE80211_BAND_5GHZ] =
7181                                 &__wl_band_5ghz_a;
7182                         index = IEEE80211_BAND_5GHZ;
7183                         if (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G)
7184                                 wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
7185                 } else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
7186                         wiphy->bands[IEEE80211_BAND_2GHZ] =
7187                                 &__wl_band_2ghz;
7188                         index = IEEE80211_BAND_2GHZ;
7189                         if (bandlist[i] == WLC_BAND_2G && bw_cap == WLC_N_BW_40ALL)
7190                                 wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
7191                 }
7192                 if ((index >= 0) && nmode) {
7193                         wiphy->bands[index]->ht_cap.cap |=
7194                                 IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40;
7195                         wiphy->bands[index]->ht_cap.ht_supported = TRUE;
7196                         wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
7197                         wiphy->bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
7198                 }
7199         }
7200
7201         wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
7202         return err;
7203 }
7204
7205 static s32 __wl_cfg80211_up(struct wl_priv *wl)
7206 {
7207         s32 err = 0;
7208         struct net_device *ndev = wl_to_prmry_ndev(wl);
7209         struct wireless_dev *wdev = ndev->ieee80211_ptr;
7210
7211         WL_DBG(("In\n"));
7212
7213         err = dhd_config_dongle(wl, false);
7214         if (unlikely(err))
7215                 return err;
7216
7217         err = wl_config_ifmode(wl, ndev, wdev->iftype);
7218         if (unlikely(err && err != -EINPROGRESS)) {
7219                 WL_ERR(("wl_config_ifmode failed\n"));
7220         }
7221         err = wl_update_wiphybands(wl);
7222         if (unlikely(err)) {
7223                 WL_ERR(("wl_update_wiphybands failed\n"));
7224         }
7225
7226         err = dhd_monitor_init(wl->pub);
7227         err = wl_invoke_iscan(wl);
7228         wl_set_drv_status(wl, READY, ndev);
7229         return err;
7230 }
7231
7232 static s32 __wl_cfg80211_down(struct wl_priv *wl)
7233 {
7234         s32 err = 0;
7235         unsigned long flags;
7236         struct net_info *iter, *next;
7237         struct net_device *ndev = wl_to_prmry_ndev(wl);
7238 #ifdef WL_ENABLE_P2P_IF
7239         struct wiphy *wiphy = wl_to_prmry_ndev(wl)->ieee80211_ptr->wiphy;
7240         struct net_device *p2p_net = wl->p2p_net;
7241 #endif
7242
7243         WL_DBG(("In\n"));
7244         /* Check if cfg80211 interface is already down */
7245         if (!wl_get_drv_status(wl, READY, ndev))
7246                 return err;     /* it is even not ready */
7247         for_each_ndev(wl, iter, next)
7248                 wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev);
7249
7250         wl_term_iscan(wl);
7251         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
7252         if (wl->scan_request) {
7253                 cfg80211_scan_done(wl->scan_request, true);
7254                 wl->scan_request = NULL;
7255         }
7256         for_each_ndev(wl, iter, next) {
7257                 wl_clr_drv_status(wl, READY, iter->ndev);
7258                 wl_clr_drv_status(wl, SCANNING, iter->ndev);
7259                 wl_clr_drv_status(wl, SCAN_ABORTING, iter->ndev);
7260                 wl_clr_drv_status(wl, CONNECTING, iter->ndev);
7261                 wl_clr_drv_status(wl, CONNECTED, iter->ndev);
7262                 wl_clr_drv_status(wl, DISCONNECTING, iter->ndev);
7263                 wl_clr_drv_status(wl, AP_CREATED, iter->ndev);
7264                 wl_clr_drv_status(wl, AP_CREATING, iter->ndev);
7265         }
7266         wl_to_prmry_ndev(wl)->ieee80211_ptr->iftype =
7267                 NL80211_IFTYPE_STATION;
7268 #ifdef WL_ENABLE_P2P_IF
7269         wiphy->interface_modes = (wiphy->interface_modes)
7270                                         & (~(BIT(NL80211_IFTYPE_P2P_CLIENT)|
7271                                         BIT(NL80211_IFTYPE_P2P_GO)));
7272         if ((p2p_net) && (p2p_net->flags & IFF_UP)) {
7273                 /* p2p0 interface is still UP. Bring it down */
7274                 p2p_net->flags &= ~IFF_UP;
7275         }
7276 #endif /* WL_ENABLE_P2P_IF */
7277         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
7278
7279         DNGL_FUNC(dhd_cfg80211_down, (wl));
7280         wl_flush_eq(wl);
7281         wl_link_down(wl);
7282         if (wl->p2p_supported)
7283                 wl_cfgp2p_down(wl);
7284         dhd_monitor_uninit();
7285
7286         return err;
7287 }
7288
7289 s32 wl_cfg80211_up(void *para)
7290 {
7291         struct wl_priv *wl;
7292         s32 err = 0;
7293
7294         WL_DBG(("In\n"));
7295         wl = wlcfg_drv_priv;
7296         mutex_lock(&wl->usr_sync);
7297         wl_cfg80211_attach_post(wl_to_prmry_ndev(wl));
7298         err = __wl_cfg80211_up(wl);
7299         if (err)
7300                 WL_ERR(("__wl_cfg80211_up failed\n"));
7301         mutex_unlock(&wl->usr_sync);
7302         return err;
7303 }
7304
7305 /* Private Event to Supplicant with indication that chip hangs */
7306 int wl_cfg80211_hang(struct net_device *dev, u16 reason)
7307 {
7308         struct wl_priv *wl;
7309         wl = wlcfg_drv_priv;
7310
7311         WL_ERR(("In : chip crash eventing\n"));
7312         cfg80211_disconnected(dev, reason, NULL, 0, GFP_KERNEL);
7313         if (wl != NULL) {
7314                 wl_link_down(wl);
7315         }
7316         return 0;
7317 }
7318
7319 s32 wl_cfg80211_down(void *para)
7320 {
7321         struct wl_priv *wl;
7322         s32 err = 0;
7323
7324         WL_DBG(("In\n"));
7325         wl = wlcfg_drv_priv;
7326         mutex_lock(&wl->usr_sync);
7327         err = __wl_cfg80211_down(wl);
7328         mutex_unlock(&wl->usr_sync);
7329
7330         return err;
7331 }
7332
7333 static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item)
7334 {
7335         unsigned long flags;
7336         void *rptr = NULL;
7337         struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
7338
7339         if (!profile)
7340                 return NULL;
7341         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
7342         switch (item) {
7343         case WL_PROF_SEC:
7344                 rptr = &profile->sec;
7345                 break;
7346         case WL_PROF_ACT:
7347                 rptr = &profile->active;
7348                 break;
7349         case WL_PROF_BSSID:
7350                 rptr = profile->bssid;
7351                 break;
7352         case WL_PROF_SSID:
7353                 rptr = &profile->ssid;
7354                 break;
7355         }
7356         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
7357         if (!rptr)
7358                 WL_ERR(("invalid item (%d)\n", item));
7359         return rptr;
7360 }
7361
7362 static s32
7363 wl_update_prof(struct wl_priv *wl, struct net_device *ndev,
7364         const wl_event_msg_t *e, void *data, s32 item)
7365 {
7366         s32 err = 0;
7367         struct wlc_ssid *ssid;
7368         unsigned long flags;
7369         struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
7370
7371         if (!profile)
7372                 return WL_INVALID;
7373         spin_lock_irqsave(&wl->cfgdrv_lock, flags);
7374         switch (item) {
7375         case WL_PROF_SSID:
7376                 ssid = (wlc_ssid_t *) data;
7377                 memset(profile->ssid.SSID, 0,
7378                         sizeof(profile->ssid.SSID));
7379                 memcpy(profile->ssid.SSID, ssid->SSID, ssid->SSID_len);
7380                 profile->ssid.SSID_len = ssid->SSID_len;
7381                 break;
7382         case WL_PROF_BSSID:
7383                 if (data)
7384                         memcpy(profile->bssid, data, ETHER_ADDR_LEN);
7385                 else
7386                         memset(profile->bssid, 0, ETHER_ADDR_LEN);
7387                 break;
7388         case WL_PROF_SEC:
7389                 memcpy(&profile->sec, data, sizeof(profile->sec));
7390                 break;
7391         case WL_PROF_ACT:
7392                 profile->active = *(bool *)data;
7393                 break;
7394         case WL_PROF_BEACONINT:
7395                 profile->beacon_interval = *(u16 *)data;
7396                 break;
7397         case WL_PROF_DTIMPERIOD:
7398                 profile->dtim_period = *(u8 *)data;
7399                 break;
7400         default:
7401                 WL_ERR(("unsupported item (%d)\n", item));
7402                 err = -EOPNOTSUPP;
7403                 break;
7404         }
7405         spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
7406         return err;
7407 }
7408
7409 void wl_cfg80211_dbg_level(u32 level)
7410 {
7411         /*
7412         * prohibit to change debug level
7413         * by insmod parameter.
7414         * eventually debug level will be configured
7415         * in compile time by using CONFIG_XXX
7416         */
7417         /* wl_dbg_level = level; */
7418 }
7419
7420 static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev)
7421 {
7422         return wl_get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS;
7423 }
7424
7425 static __used bool wl_is_ibssstarter(struct wl_priv *wl)
7426 {
7427         return wl->ibss_starter;
7428 }
7429
7430 static void wl_rst_ie(struct wl_priv *wl)
7431 {
7432         struct wl_ie *ie = wl_to_ie(wl);
7433
7434         ie->offset = 0;
7435 }
7436
7437 static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v)
7438 {
7439         struct wl_ie *ie = wl_to_ie(wl);
7440         s32 err = 0;
7441
7442         if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
7443                 WL_ERR(("ei crosses buffer boundary\n"));
7444                 return -ENOSPC;
7445         }
7446         ie->buf[ie->offset] = t;
7447         ie->buf[ie->offset + 1] = l;
7448         memcpy(&ie->buf[ie->offset + 2], v, l);
7449         ie->offset += l + 2;
7450
7451         return err;
7452 }
7453
7454 static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size)
7455 {
7456         struct wl_ie *ie = wl_to_ie(wl);
7457         s32 err = 0;
7458
7459         if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
7460                 WL_ERR(("ei_stream crosses buffer boundary\n"));
7461                 return -ENOSPC;
7462         }
7463         memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
7464         ie->offset += ie_size;
7465
7466         return err;
7467 }
7468
7469 static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size)
7470 {
7471         struct wl_ie *ie = wl_to_ie(wl);
7472         s32 err = 0;
7473
7474         if (unlikely(ie->offset > dst_size)) {
7475                 WL_ERR(("dst_size is not enough\n"));
7476                 return -ENOSPC;
7477         }
7478         memcpy(dst, &ie->buf[0], ie->offset);
7479
7480         return err;
7481 }
7482
7483 static u32 wl_get_ielen(struct wl_priv *wl)
7484 {
7485         struct wl_ie *ie = wl_to_ie(wl);
7486
7487         return ie->offset;
7488 }
7489
7490 static void wl_link_up(struct wl_priv *wl)
7491 {
7492         wl->link_up = true;
7493 }
7494
7495 static void wl_link_down(struct wl_priv *wl)
7496 {
7497         struct wl_connect_info *conn_info = wl_to_conn(wl);
7498
7499         WL_DBG(("In\n"));
7500         wl->link_up = false;
7501         conn_info->req_ie_len = 0;
7502         conn_info->resp_ie_len = 0;
7503 }
7504
7505 static unsigned long wl_lock_eq(struct wl_priv *wl)
7506 {
7507         unsigned long flags;
7508
7509         spin_lock_irqsave(&wl->eq_lock, flags);
7510         return flags;
7511 }
7512
7513 static void wl_unlock_eq(struct wl_priv *wl, unsigned long flags)
7514 {
7515         spin_unlock_irqrestore(&wl->eq_lock, flags);
7516 }
7517
7518 static void wl_init_eq_lock(struct wl_priv *wl)
7519 {
7520         spin_lock_init(&wl->eq_lock);
7521 }
7522
7523 static void wl_delay(u32 ms)
7524 {
7525         if (in_atomic() || ms < 1000 / HZ) {
7526                 mdelay(ms);
7527         } else {
7528                 msleep(ms);
7529         }
7530 }
7531
7532 s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
7533 {
7534         struct wl_priv *wl = wlcfg_drv_priv;
7535         struct ether_addr p2pif_addr;
7536         struct ether_addr primary_mac;
7537
7538         if (!wl->p2p)
7539                 return -1;
7540         if (!p2p_is_on(wl)) {
7541                 get_primary_mac(wl, &primary_mac);
7542                 wl_cfgp2p_generate_bss_mac(&primary_mac, p2pdev_addr, &p2pif_addr);
7543         } else {
7544                 memcpy(p2pdev_addr->octet,
7545                         wl->p2p->dev_addr.octet, ETHER_ADDR_LEN);
7546         }
7547
7548         return 0;
7549 }
7550 s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
7551 {
7552         struct wl_priv *wl;
7553
7554         wl = wlcfg_drv_priv;
7555
7556         return wl_cfgp2p_set_p2p_noa(wl, net, buf, len);
7557 }
7558
7559 s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
7560 {
7561         struct wl_priv *wl;
7562         wl = wlcfg_drv_priv;
7563
7564         return wl_cfgp2p_get_p2p_noa(wl, net, buf, len);
7565 }
7566
7567 s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
7568 {
7569         struct wl_priv *wl;
7570         wl = wlcfg_drv_priv;
7571
7572         return wl_cfgp2p_set_p2p_ps(wl, net, buf, len);
7573 }
7574
7575 s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
7576         enum wl_management_type type)
7577 {
7578         struct wl_priv *wl;
7579         struct net_device *ndev = NULL;
7580         struct ether_addr primary_mac;
7581         s32 ret = 0;
7582         s32 bssidx = 0;
7583         s32 pktflag = 0;
7584         wl = wlcfg_drv_priv;
7585
7586         if (wl_get_drv_status(wl, AP_CREATING, net) ||
7587                 wl_get_drv_status(wl, AP_CREATED, net)) {
7588                 ndev = net;
7589                 bssidx = 0;
7590         } else if (wl->p2p) {
7591            if (net == wl->p2p_net) {
7592                         net = wl_to_prmry_ndev(wl);
7593                 }
7594
7595                 if (!wl->p2p->on) {
7596                         get_primary_mac(wl, &primary_mac);
7597                         wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr,
7598                                 &wl->p2p->int_addr);
7599                         /* In case of p2p_listen command, supplicant send remain_on_channel
7600                         * without turning on P2P
7601                         */
7602                         p2p_on(wl) = true;
7603                         ret = wl_cfgp2p_enable_discovery(wl, ndev, NULL, 0);
7604
7605                         if (unlikely(ret)) {
7606                                 goto exit;
7607                         }
7608                 }
7609                 if (net  != wl_to_prmry_ndev(wl)) {
7610                         if (wl_get_mode_by_netdev(wl, net) == WL_MODE_AP) {
7611                                 ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
7612                                 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION);
7613                         }
7614                 } else {
7615                                 ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY);
7616                                 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
7617                 }
7618         }
7619         if (ndev != NULL) {
7620                 switch (type) {
7621                         case WL_BEACON:
7622                                 pktflag = VNDR_IE_BEACON_FLAG;
7623                                 break;
7624                         case WL_PROBE_RESP:
7625                                 pktflag = VNDR_IE_PRBRSP_FLAG;
7626                                 break;
7627                         case WL_ASSOC_RESP:
7628                                 pktflag = VNDR_IE_ASSOCRSP_FLAG;
7629                                 break;
7630                 }
7631                 if (pktflag)
7632                         ret = wl_cfgp2p_set_management_ie(wl, ndev, bssidx, pktflag, buf, len);
7633         }
7634 exit:
7635         return ret;
7636 }
7637
7638 static const struct rfkill_ops wl_rfkill_ops = {
7639         .set_block = wl_rfkill_set
7640 };
7641
7642 static int wl_rfkill_set(void *data, bool blocked)
7643 {
7644         struct wl_priv *wl = (struct wl_priv *)data;
7645
7646         WL_DBG(("Enter \n"));
7647         WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked"));
7648
7649         if (!wl)
7650                 return -EINVAL;
7651
7652         wl->rf_blocked = blocked;
7653
7654         return 0;
7655 }
7656
7657 static int wl_setup_rfkill(struct wl_priv *wl, bool setup)
7658 {
7659         s32 err = 0;
7660
7661         WL_DBG(("Enter \n"));
7662         if (!wl)
7663                 return -EINVAL;
7664         if (setup) {
7665                 wl->rfkill = rfkill_alloc("brcmfmac-wifi",
7666                         wl_cfg80211_get_parent_dev(),
7667                         RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)wl);
7668
7669                 if (!wl->rfkill) {
7670                         err = -ENOMEM;
7671                         goto err_out;
7672                 }
7673
7674                 err = rfkill_register(wl->rfkill);
7675
7676                 if (err)
7677                         rfkill_destroy(wl->rfkill);
7678         } else {
7679                 if (!wl->rfkill) {
7680                         err = -ENOMEM;
7681                         goto err_out;
7682                 }
7683
7684                 rfkill_unregister(wl->rfkill);
7685                 rfkill_destroy(wl->rfkill);
7686         }
7687
7688 err_out:
7689         return err;
7690 }
7691
7692 struct device *wl_cfg80211_get_parent_dev(void)
7693 {
7694         return cfg80211_parent_dev;
7695 }
7696
7697 void wl_cfg80211_set_parent_dev(void *dev)
7698 {
7699         cfg80211_parent_dev = dev;
7700 }
7701
7702 static void wl_cfg80211_clear_parent_dev(void)
7703 {
7704         cfg80211_parent_dev = NULL;
7705 }
7706
7707 static void get_primary_mac(struct wl_priv *wl, struct ether_addr *mac)
7708 {
7709         wldev_iovar_getbuf_bsscfg(wl_to_prmry_ndev(wl), "cur_etheraddr", NULL,
7710                 0, wl->ioctl_buf, WLC_IOCTL_MAXLEN, 0, &wl->ioctl_buf_sync);
7711         memcpy(mac->octet, wl->ioctl_buf, ETHER_ADDR_LEN);
7712 }
7713
7714 int wl_cfg80211_do_driver_init(struct net_device *net)
7715 {
7716         struct wl_priv *wl = *(struct wl_priv **)netdev_priv(net);
7717
7718         if (!wl || !wl->wdev)
7719                 return -EINVAL;
7720
7721         if (dhd_do_driver_init(wl->wdev->netdev) < 0)
7722                 return -1;
7723
7724         return 0;
7725 }
7726
7727 void wl_cfg80211_enable_trace(int level)
7728 {
7729         wl_dbg_level |= WL_DBG_DBG;
7730 }